@@ -118,6 +118,7 @@ impl StandardTableProvider {
118
118
#[ allow( clippy:: too_many_arguments) ]
119
119
async fn create_parquet_physical_plan (
120
120
& self ,
121
+ execution_plans : & mut Vec < Arc < dyn ExecutionPlan > > ,
121
122
object_store_url : ObjectStoreUrl ,
122
123
partitions : Vec < Vec < PartitionedFile > > ,
123
124
statistics : Statistics ,
@@ -126,7 +127,7 @@ impl StandardTableProvider {
126
127
limit : Option < usize > ,
127
128
state : & dyn Session ,
128
129
time_partition : Option < String > ,
129
- ) -> Result < Arc < dyn ExecutionPlan > , DataFusionError > {
130
+ ) -> Result < ( ) , DataFusionError > {
130
131
let filters = if let Some ( expr) = conjunction ( filters. to_vec ( ) ) {
131
132
let table_df_schema = self . schema . as_ref ( ) . clone ( ) . to_dfschema ( ) ?;
132
133
let filters = create_physical_expr ( & expr, & table_df_schema, state. execution_props ( ) ) ?;
@@ -165,20 +166,23 @@ impl StandardTableProvider {
165
166
filters. as_ref ( ) ,
166
167
)
167
168
. await ?;
168
- Ok ( plan)
169
+ execution_plans. push ( plan) ;
170
+
171
+ Ok ( ( ) )
169
172
}
170
173
171
174
#[ allow( clippy:: too_many_arguments) ]
172
175
async fn get_cache_exectuion_plan (
173
176
& self ,
177
+ execution_plans : & mut Vec < Arc < dyn ExecutionPlan > > ,
174
178
cache_manager : & LocalCacheManager ,
175
179
manifest_files : & mut Vec < File > ,
176
180
projection : Option < & Vec < usize > > ,
177
181
filters : & [ Expr ] ,
178
182
limit : Option < usize > ,
179
183
state : & dyn Session ,
180
184
time_partition : Option < String > ,
181
- ) -> Result < Option < Arc < dyn ExecutionPlan > > , DataFusionError > {
185
+ ) -> Result < ( ) , DataFusionError > {
182
186
let ( cached, remainder) = cache_manager
183
187
. partition_on_cached ( & self . stream , manifest_files. clone ( ) , |file : & File | {
184
188
& file. file_path
@@ -200,33 +204,34 @@ impl StandardTableProvider {
200
204
. collect ( ) ;
201
205
202
206
let ( partitioned_files, statistics) = self . partitioned_files ( cached) ;
203
- let plan = self
204
- . create_parquet_physical_plan (
205
- ObjectStoreUrl :: parse ( "file:///" ) . unwrap ( ) ,
206
- partitioned_files,
207
- statistics,
208
- projection,
209
- filters,
210
- limit,
211
- state,
212
- time_partition. clone ( ) ,
213
- )
214
- . await ?;
207
+ self . create_parquet_physical_plan (
208
+ execution_plans ,
209
+ ObjectStoreUrl :: parse ( "file:///" ) . unwrap ( ) ,
210
+ partitioned_files,
211
+ statistics,
212
+ projection,
213
+ filters,
214
+ limit,
215
+ state,
216
+ time_partition. clone ( ) ,
217
+ )
218
+ . await ?;
215
219
216
- Ok ( Some ( plan ) )
220
+ Ok ( ( ) )
217
221
}
218
222
219
223
#[ allow( clippy:: too_many_arguments) ]
220
224
async fn get_hottier_exectuion_plan (
221
225
& self ,
226
+ execution_plans : & mut Vec < Arc < dyn ExecutionPlan > > ,
222
227
hot_tier_manager : & HotTierManager ,
223
228
manifest_files : & mut Vec < File > ,
224
229
projection : Option < & Vec < usize > > ,
225
230
filters : & [ Expr ] ,
226
231
limit : Option < usize > ,
227
232
state : & dyn Session ,
228
233
time_partition : Option < String > ,
229
- ) -> Result < Option < Arc < dyn ExecutionPlan > > , DataFusionError > {
234
+ ) -> Result < ( ) , DataFusionError > {
230
235
let hot_tier_files = hot_tier_manager
231
236
. get_hot_tier_manifest_files ( & self . stream , manifest_files)
232
237
. await
@@ -247,25 +252,26 @@ impl StandardTableProvider {
247
252
. collect ( ) ;
248
253
249
254
let ( partitioned_files, statistics) = self . partitioned_files ( hot_tier_files) ;
250
- let plan = self
251
- . create_parquet_physical_plan (
252
- ObjectStoreUrl :: parse ( "file:///" ) . unwrap ( ) ,
253
- partitioned_files,
254
- statistics,
255
- projection,
256
- filters,
257
- limit,
258
- state,
259
- time_partition. clone ( ) ,
260
- )
261
- . await ?;
255
+ self . create_parquet_physical_plan (
256
+ execution_plans ,
257
+ ObjectStoreUrl :: parse ( "file:///" ) . unwrap ( ) ,
258
+ partitioned_files,
259
+ statistics,
260
+ projection,
261
+ filters,
262
+ limit,
263
+ state,
264
+ time_partition. clone ( ) ,
265
+ )
266
+ . await ?;
262
267
263
- Ok ( Some ( plan ) )
268
+ Ok ( ( ) )
264
269
}
265
270
266
271
#[ allow( clippy:: too_many_arguments) ]
267
272
async fn legacy_listing_table (
268
273
& self ,
274
+ execution_plans : & mut Vec < Arc < dyn ExecutionPlan > > ,
269
275
glob_storage : Arc < dyn ObjectStorage > ,
270
276
object_store : Arc < dyn ObjectStore > ,
271
277
time_filters : & [ PartialTimeFilter ] ,
@@ -274,33 +280,32 @@ impl StandardTableProvider {
274
280
filters : & [ Expr ] ,
275
281
limit : Option < usize > ,
276
282
time_partition : Option < String > ,
277
- ) -> Result < Option < Arc < dyn ExecutionPlan > > , DataFusionError > {
278
- let remote_table = ListingTableBuilder :: new ( self . stream . to_owned ( ) )
283
+ ) -> Result < ( ) , DataFusionError > {
284
+ ListingTableBuilder :: new ( self . stream . to_owned ( ) )
279
285
. populate_via_listing ( glob_storage. clone ( ) , object_store, time_filters)
280
286
. and_then ( |builder| async {
281
287
let table = builder. build (
282
288
self . schema . clone ( ) ,
283
289
|x| glob_storage. query_prefixes ( x) ,
284
290
time_partition,
285
291
) ?;
286
- let res = match table {
287
- Some ( table) => Some ( table. scan ( state, projection, filters, limit) . await ?) ,
288
- _ => None ,
289
- } ;
290
- Ok ( res)
292
+ if let Some ( table) = table {
293
+ let plan = table. scan ( state, projection, filters, limit) . await ?;
294
+ execution_plans. push ( plan) ;
295
+ }
296
+
297
+ Ok ( ( ) )
291
298
} )
292
299
. await ?;
293
300
294
- Ok ( remote_table )
301
+ Ok ( ( ) )
295
302
}
296
303
297
304
fn final_plan (
298
305
& self ,
299
- execution_plans : Vec < Option < Arc < dyn ExecutionPlan > > > ,
306
+ mut execution_plans : Vec < Arc < dyn ExecutionPlan > > ,
300
307
projection : Option < & Vec < usize > > ,
301
308
) -> Result < Arc < dyn ExecutionPlan > , DataFusionError > {
302
- let mut execution_plans = execution_plans. into_iter ( ) . flatten ( ) . collect_vec ( ) ;
303
-
304
309
let exec: Arc < dyn ExecutionPlan > = if execution_plans. is_empty ( ) {
305
310
let schema = match projection {
306
311
Some ( projection) => Arc :: new ( self . schema . project ( projection) ?) ,
@@ -462,10 +467,7 @@ impl TableProvider for StandardTableProvider {
462
467
filters : & [ Expr ] ,
463
468
limit : Option < usize > ,
464
469
) -> Result < Arc < dyn ExecutionPlan > , DataFusionError > {
465
- let mut memory_exec = None ;
466
- let mut cache_exec = None ;
467
- let mut hot_tier_exec = None ;
468
- let mut listing_exec = None ;
470
+ let mut execution_plans = vec ! [ ] ;
469
471
let object_store = state
470
472
. runtime_env ( )
471
473
. object_store_registry
@@ -488,11 +490,11 @@ impl TableProvider for StandardTableProvider {
488
490
event:: STREAM_WRITERS . recordbatches_cloned ( & self . stream , & self . schema )
489
491
{
490
492
let reversed_mem_table = reversed_mem_table ( records, self . schema . clone ( ) ) ?;
491
- memory_exec = Some (
492
- reversed_mem_table
493
- . scan ( state, projection, filters, limit)
494
- . await ?,
495
- ) ;
493
+
494
+ let memory_exec = reversed_mem_table
495
+ . scan ( state, projection, filters, limit)
496
+ . await ?;
497
+ execution_plans . push ( memory_exec ) ;
496
498
}
497
499
} ;
498
500
let mut merged_snapshot: snapshot:: Snapshot = Snapshot :: default ( ) ;
@@ -526,8 +528,9 @@ impl TableProvider for StandardTableProvider {
526
528
let listing_time_fiters =
527
529
return_listing_time_filters ( & merged_snapshot. manifest_list , & mut time_filters) ;
528
530
529
- listing_exec = if let Some ( listing_time_filter) = listing_time_fiters {
531
+ if let Some ( listing_time_filter) = listing_time_fiters {
530
532
self . legacy_listing_table (
533
+ & mut execution_plans,
531
534
glob_storage. clone ( ) ,
532
535
object_store. clone ( ) ,
533
536
& listing_time_filter,
@@ -537,10 +540,8 @@ impl TableProvider for StandardTableProvider {
537
540
limit,
538
541
time_partition. clone ( ) ,
539
542
)
540
- . await ?
541
- } else {
542
- None
543
- } ;
543
+ . await ?;
544
+ }
544
545
}
545
546
546
547
let mut manifest_files = collect_from_snapshot (
@@ -553,14 +554,30 @@ impl TableProvider for StandardTableProvider {
553
554
. await ?;
554
555
555
556
if manifest_files. is_empty ( ) {
556
- return self . final_plan ( vec ! [ listing_exec , memory_exec ] , projection) ;
557
+ return self . final_plan ( execution_plans , projection) ;
557
558
}
558
559
559
560
// Based on entries in the manifest files, find them in the cache and create a physical plan.
560
561
if let Some ( cache_manager) = LocalCacheManager :: global ( ) {
561
- cache_exec = self
562
- . get_cache_exectuion_plan (
563
- cache_manager,
562
+ self . get_cache_exectuion_plan (
563
+ & mut execution_plans,
564
+ cache_manager,
565
+ & mut manifest_files,
566
+ projection,
567
+ filters,
568
+ limit,
569
+ state,
570
+ time_partition. clone ( ) ,
571
+ )
572
+ . await ?;
573
+ }
574
+
575
+ // Hot tier data fetch
576
+ if let Some ( hot_tier_manager) = HotTierManager :: global ( ) {
577
+ if hot_tier_manager. check_stream_hot_tier_exists ( & self . stream ) {
578
+ self . get_hottier_exectuion_plan (
579
+ & mut execution_plans,
580
+ hot_tier_manager,
564
581
& mut manifest_files,
565
582
projection,
566
583
filters,
@@ -569,56 +586,28 @@ impl TableProvider for StandardTableProvider {
569
586
time_partition. clone ( ) ,
570
587
)
571
588
. await ?;
572
- }
573
-
574
- // Hot tier data fetch
575
- if let Some ( hot_tier_manager) = HotTierManager :: global ( ) {
576
- if hot_tier_manager. check_stream_hot_tier_exists ( & self . stream ) {
577
- hot_tier_exec = self
578
- . get_hottier_exectuion_plan (
579
- hot_tier_manager,
580
- & mut manifest_files,
581
- projection,
582
- filters,
583
- limit,
584
- state,
585
- time_partition. clone ( ) ,
586
- )
587
- . await ?;
588
589
}
589
590
}
590
591
if manifest_files. is_empty ( ) {
591
592
QUERY_CACHE_HIT . with_label_values ( & [ & self . stream ] ) . inc ( ) ;
592
- return self . final_plan (
593
- vec ! [ listing_exec, memory_exec, cache_exec, hot_tier_exec] ,
594
- projection,
595
- ) ;
593
+ return self . final_plan ( execution_plans, projection) ;
596
594
}
597
595
598
596
let ( partitioned_files, statistics) = self . partitioned_files ( manifest_files) ;
599
- let remote_exec = self
600
- . create_parquet_physical_plan (
601
- ObjectStoreUrl :: parse ( glob_storage. store_url ( ) ) . unwrap ( ) ,
602
- partitioned_files,
603
- statistics,
604
- projection,
605
- filters,
606
- limit,
607
- state,
608
- time_partition. clone ( ) ,
609
- )
610
- . await ?;
611
-
612
- Ok ( self . final_plan (
613
- vec ! [
614
- listing_exec,
615
- memory_exec,
616
- cache_exec,
617
- hot_tier_exec,
618
- Some ( remote_exec) ,
619
- ] ,
597
+ self . create_parquet_physical_plan (
598
+ & mut execution_plans,
599
+ ObjectStoreUrl :: parse ( glob_storage. store_url ( ) ) . unwrap ( ) ,
600
+ partitioned_files,
601
+ statistics,
620
602
projection,
621
- ) ?)
603
+ filters,
604
+ limit,
605
+ state,
606
+ time_partition. clone ( ) ,
607
+ )
608
+ . await ?;
609
+
610
+ Ok ( self . final_plan ( execution_plans, projection) ?)
622
611
}
623
612
624
613
/*
0 commit comments