@@ -27,9 +27,9 @@ use tokio::fs::File;
27
27
use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
28
28
use tokio_stream:: Stream ;
29
29
30
- use databend_client:: APIClient ;
31
30
use databend_client:: PresignedResponse ;
32
31
use databend_client:: QueryResponse ;
32
+ use databend_client:: { APIClient , SchemaField } ;
33
33
use databend_driver_core:: error:: { Error , Result } ;
34
34
use databend_driver_core:: rows:: { Row , RowIterator , RowStatsIterator , RowWithStats , ServerStats } ;
35
35
use databend_driver_core:: schema:: { Schema , SchemaRef } ;
@@ -82,7 +82,7 @@ impl Connection for RestAPIConnection {
82
82
async fn query_iter_ext ( & self , sql : & str ) -> Result < RowStatsIterator > {
83
83
info ! ( "query iter ext: {}" , sql) ;
84
84
let resp = self . client . start_query ( sql) . await ?;
85
- let resp = self . wait_for_schema ( resp) . await ?;
85
+ let resp = self . wait_for_schema ( resp, true ) . await ?;
86
86
let ( schema, rows) = RestAPIRows :: from_response ( self . client . clone ( ) , resp) ?;
87
87
Ok ( RowStatsIterator :: new ( Arc :: new ( schema) , Box :: pin ( rows) ) )
88
88
}
@@ -209,8 +209,14 @@ impl<'o> RestAPIConnection {
209
209
} )
210
210
}
211
211
212
- async fn wait_for_schema ( & self , resp : QueryResponse ) -> Result < QueryResponse > {
213
- if !resp. data . is_empty ( ) || !resp. schema . is_empty ( ) || resp. stats . progresses . has_progress ( )
212
+ async fn wait_for_schema (
213
+ & self ,
214
+ resp : QueryResponse ,
215
+ return_on_progress : bool ,
216
+ ) -> Result < QueryResponse > {
217
+ if !resp. data . is_empty ( )
218
+ || !resp. schema . is_empty ( )
219
+ || ( return_on_progress && resp. stats . progresses . has_progress ( ) )
214
220
{
215
221
return Ok ( resp) ;
216
222
}
@@ -228,7 +234,7 @@ impl<'o> RestAPIConnection {
228
234
229
235
if !result. data . is_empty ( )
230
236
|| !result. schema . is_empty ( )
231
- || result. stats . progresses . has_progress ( )
237
+ || ( return_on_progress && result. stats . progresses . has_progress ( ) )
232
238
{
233
239
break ;
234
240
}
@@ -250,6 +256,12 @@ impl<'o> RestAPIConnection {
250
256
fn default_copy_options ( ) -> BTreeMap < & ' o str , & ' o str > {
251
257
vec ! [ ( "purge" , "true" ) ] . into_iter ( ) . collect ( )
252
258
}
259
+
260
+ pub async fn query_row_batch ( & self , sql : & str ) -> Result < RowBatch > {
261
+ let resp = self . client . start_query ( sql) . await ?;
262
+ let resp = self . wait_for_schema ( resp, false ) . await ?;
263
+ Ok ( RowBatch :: from_response ( self . client . clone ( ) , resp) ?)
264
+ }
253
265
}
254
266
255
267
type PageFut = Pin < Box < dyn Future < Output = Result < QueryResponse > > + Send > > ;
@@ -341,3 +353,48 @@ impl Stream for RestAPIRows {
341
353
}
342
354
}
343
355
}
356
+
357
+ pub struct RowBatch {
358
+ schema : Vec < SchemaField > ,
359
+ client : Arc < APIClient > ,
360
+ query_id : String ,
361
+ node_id : Option < String > ,
362
+
363
+ next_uri : Option < String > ,
364
+ data : Vec < Vec < Option < String > > > ,
365
+ }
366
+
367
+ impl RowBatch {
368
+ pub fn schema ( & self ) -> Vec < SchemaField > {
369
+ self . schema . clone ( )
370
+ }
371
+
372
+ fn from_response ( client : Arc < APIClient > , mut resp : QueryResponse ) -> Result < Self > {
373
+ Ok ( Self {
374
+ schema : std:: mem:: take ( & mut resp. schema ) ,
375
+ client,
376
+ query_id : resp. id ,
377
+ node_id : resp. node_id ,
378
+ next_uri : resp. next_uri ,
379
+ data : resp. data ,
380
+ } )
381
+ }
382
+
383
+ pub async fn fetch_next_page ( & mut self ) -> Result < Vec < Vec < Option < String > > > > {
384
+ if !self . data . is_empty ( ) {
385
+ return Ok ( std:: mem:: take ( & mut self . data ) ) ;
386
+ }
387
+ while let Some ( next_uri) = & self . next_uri {
388
+ let resp = self
389
+ . client
390
+ . query_page ( & self . query_id , & next_uri, & self . node_id )
391
+ . await ?;
392
+
393
+ self . next_uri = resp. next_uri ;
394
+ if !resp. data . is_empty ( ) {
395
+ return Ok ( resp. data ) ;
396
+ }
397
+ }
398
+ Ok ( vec ! [ ] )
399
+ }
400
+ }
0 commit comments