@@ -29,9 +29,9 @@ use tokio::fs::File;
29
29
use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
30
30
use tokio_stream:: Stream ;
31
31
32
- use databend_client:: APIClient ;
33
32
use databend_client:: PresignedResponse ;
34
33
use databend_client:: QueryResponse ;
34
+ use databend_client:: { APIClient , SchemaField } ;
35
35
use databend_driver_core:: error:: { Error , Result } ;
36
36
use databend_driver_core:: rows:: { Row , RowIterator , RowStatsIterator , RowWithStats , ServerStats } ;
37
37
use databend_driver_core:: schema:: { Schema , SchemaRef } ;
@@ -84,7 +84,7 @@ impl Connection for RestAPIConnection {
84
84
async fn query_iter_ext ( & self , sql : & str ) -> Result < RowStatsIterator > {
85
85
info ! ( "query iter ext: {}" , sql) ;
86
86
let resp = self . client . start_query ( sql) . await ?;
87
- let resp = self . wait_for_schema ( resp) . await ?;
87
+ let resp = self . wait_for_schema ( resp, true ) . await ?;
88
88
let ( schema, rows) = RestAPIRows :: < RowWithStats > :: from_response ( self . client . clone ( ) , resp) ?;
89
89
Ok ( RowStatsIterator :: new ( Arc :: new ( schema) , Box :: pin ( rows) ) )
90
90
}
@@ -93,7 +93,7 @@ impl Connection for RestAPIConnection {
93
93
async fn query_raw_iter ( & self , sql : & str ) -> Result < RawRowIterator > {
94
94
info ! ( "query raw iter: {}" , sql) ;
95
95
let resp = self . client . start_query ( sql) . await ?;
96
- let resp = self . wait_for_schema ( resp) . await ?;
96
+ let resp = self . wait_for_schema ( resp, true ) . await ?;
97
97
let ( schema, rows) =
98
98
RestAPIRows :: < RawRowWithStats > :: from_response ( self . client . clone ( ) , resp) ?;
99
99
Ok ( RawRowIterator :: new ( Arc :: new ( schema) , Box :: pin ( rows) ) )
@@ -221,8 +221,14 @@ impl<'o> RestAPIConnection {
221
221
} )
222
222
}
223
223
224
- async fn wait_for_schema ( & self , resp : QueryResponse ) -> Result < QueryResponse > {
225
- if !resp. data . is_empty ( ) || !resp. schema . is_empty ( ) || resp. stats . progresses . has_progress ( )
224
+ async fn wait_for_schema (
225
+ & self ,
226
+ resp : QueryResponse ,
227
+ return_on_progress : bool ,
228
+ ) -> Result < QueryResponse > {
229
+ if !resp. data . is_empty ( )
230
+ || !resp. schema . is_empty ( )
231
+ || ( return_on_progress && resp. stats . progresses . has_progress ( ) )
226
232
{
227
233
return Ok ( resp) ;
228
234
}
@@ -240,7 +246,7 @@ impl<'o> RestAPIConnection {
240
246
241
247
if !result. data . is_empty ( )
242
248
|| !result. schema . is_empty ( )
243
- || result. stats . progresses . has_progress ( )
249
+ || ( return_on_progress && result. stats . progresses . has_progress ( ) )
244
250
{
245
251
break ;
246
252
}
@@ -262,6 +268,12 @@ impl<'o> RestAPIConnection {
262
268
fn default_copy_options ( ) -> BTreeMap < & ' o str , & ' o str > {
263
269
vec ! [ ( "purge" , "true" ) ] . into_iter ( ) . collect ( )
264
270
}
271
+
272
+ pub async fn query_row_batch ( & self , sql : & str ) -> Result < RowBatch > {
273
+ let resp = self . client . start_query ( sql) . await ?;
274
+ let resp = self . wait_for_schema ( resp, false ) . await ?;
275
+ RowBatch :: from_response ( self . client . clone ( ) , resp)
276
+ }
265
277
}
266
278
267
279
type PageFut = Pin < Box < dyn Future < Output = Result < QueryResponse > > + Send > > ;
@@ -380,3 +392,48 @@ impl FromRowStats for RawRowWithStats {
380
392
Ok ( RawRowWithStats :: Row ( RawRow :: new ( rows, row) ) )
381
393
}
382
394
}
395
+
396
+ pub struct RowBatch {
397
+ schema : Vec < SchemaField > ,
398
+ client : Arc < APIClient > ,
399
+ query_id : String ,
400
+ node_id : Option < String > ,
401
+
402
+ next_uri : Option < String > ,
403
+ data : Vec < Vec < Option < String > > > ,
404
+ }
405
+
406
+ impl RowBatch {
407
+ pub fn schema ( & self ) -> Vec < SchemaField > {
408
+ self . schema . clone ( )
409
+ }
410
+
411
+ fn from_response ( client : Arc < APIClient > , mut resp : QueryResponse ) -> Result < Self > {
412
+ Ok ( Self {
413
+ schema : std:: mem:: take ( & mut resp. schema ) ,
414
+ client,
415
+ query_id : resp. id ,
416
+ node_id : resp. node_id ,
417
+ next_uri : resp. next_uri ,
418
+ data : resp. data ,
419
+ } )
420
+ }
421
+
422
+ pub async fn fetch_next_page ( & mut self ) -> Result < Vec < Vec < Option < String > > > > {
423
+ if !self . data . is_empty ( ) {
424
+ return Ok ( std:: mem:: take ( & mut self . data ) ) ;
425
+ }
426
+ while let Some ( next_uri) = & self . next_uri {
427
+ let resp = self
428
+ . client
429
+ . query_page ( & self . query_id , next_uri, & self . node_id )
430
+ . await ?;
431
+
432
+ self . next_uri = resp. next_uri ;
433
+ if !resp. data . is_empty ( ) {
434
+ return Ok ( resp. data ) ;
435
+ }
436
+ }
437
+ Ok ( vec ! [ ] )
438
+ }
439
+ }
0 commit comments