@@ -29,7 +29,7 @@ use crate::{
2929use arrow:: datatypes:: { DataType , Field , SchemaBuilder , SchemaRef } ;
3030use arrow_schema:: Schema ;
3131use async_trait:: async_trait;
32- use datafusion_catalog:: { Session , TableProvider } ;
32+ use datafusion_catalog:: { ScanArgs , ScanResult , Session , TableProvider } ;
3333use datafusion_common:: {
3434 config_datafusion_err, config_err, internal_err, plan_err, project_schema,
3535 stats:: Precision , Constraints , DataFusionError , Result , SchemaExt ,
@@ -1166,6 +1166,22 @@ impl TableProvider for ListingTable {
11661166 filters : & [ Expr ] ,
11671167 limit : Option < usize > ,
11681168 ) -> Result < Arc < dyn ExecutionPlan > > {
1169+ let options = ScanArgs :: default ( )
1170+ . with_projection ( projection. cloned ( ) )
1171+ . with_filters ( Some ( filters. to_vec ( ) ) )
1172+ . with_limit ( limit) ;
1173+ Ok ( self . scan_with_options ( state, options) . await ?. plan ( ) )
1174+ }
1175+
1176+ async fn scan_with_options (
1177+ & self ,
1178+ state : & dyn Session ,
1179+ options : ScanArgs ,
1180+ ) -> Result < ScanResult > {
1181+ let projection = options. projection ( ) ;
1182+ let filters = options. filters ( ) . map ( |f| f. to_vec ( ) ) . unwrap_or_default ( ) ;
1183+ let limit = options. limit ( ) ;
1184+
11691185 // extract types of partition columns
11701186 let table_partition_cols = self
11711187 . options
@@ -1195,21 +1211,36 @@ impl TableProvider for ListingTable {
11951211
11961212 // if no files need to be read, return an `EmptyExec`
11971213 if partitioned_file_lists. is_empty ( ) {
1198- let projected_schema = project_schema ( & self . schema ( ) , projection) ?;
1199- return Ok ( Arc :: new ( EmptyExec :: new ( projected_schema) ) ) ;
1214+ let projected_schema = project_schema ( & self . schema ( ) , projection. as_ref ( ) ) ?;
1215+ return Ok ( ScanResult :: new (
1216+ Arc :: new ( EmptyExec :: new ( projected_schema) ) ,
1217+ filters. clone ( ) ,
1218+ ) ) ;
12001219 }
12011220
1202- let output_ordering = self . try_create_output_ordering ( ) ?;
1221+ let known_file_ordering = self . try_create_output_ordering ( ) ?;
1222+ let desired_file_ordering = match options. preferred_ordering ( ) {
1223+ Some ( ordering) if !ordering. is_empty ( ) => {
1224+ // Prefer the ordering requested by the query to any inherint file ordering
1225+ create_ordering ( & self . table_schema , & [ ordering. to_vec ( ) ] ) ?
1226+ . first ( )
1227+ . cloned ( )
1228+ }
1229+ Some ( _) | None => {
1230+ // If the query did not request a specific ordering, fall back to any inherent file ordering
1231+ known_file_ordering. first ( ) . cloned ( )
1232+ }
1233+ } ;
12031234 match state
12041235 . config_options ( )
12051236 . execution
12061237 . split_file_groups_by_statistics
12071238 . then ( || {
1208- output_ordering . first ( ) . map ( |output_ordering | {
1239+ desired_file_ordering . map ( |ordering | {
12091240 FileScanConfig :: split_groups_by_statistics_with_target_partitions (
12101241 & self . table_schema ,
12111242 & partitioned_file_lists,
1212- output_ordering ,
1243+ & ordering ,
12131244 self . options . target_partitions ,
12141245 )
12151246 } )
@@ -1230,13 +1261,17 @@ impl TableProvider for ListingTable {
12301261 let Some ( object_store_url) =
12311262 self . table_paths . first ( ) . map ( ListingTableUrl :: object_store)
12321263 else {
1233- return Ok ( Arc :: new ( EmptyExec :: new ( Arc :: new ( Schema :: empty ( ) ) ) ) ) ;
1264+ return Ok ( ScanResult :: new (
1265+ Arc :: new ( EmptyExec :: new ( Arc :: new ( Schema :: empty ( ) ) ) ) ,
1266+ filters. clone ( ) ,
1267+ ) ) ;
12341268 } ;
12351269
12361270 let file_source = self . create_file_source_with_schema_adapter ( ) ?;
12371271
12381272 // create the execution plan
1239- self . options
1273+ let plan = self
1274+ . options
12401275 . format
12411276 . create_physical_plan (
12421277 state,
@@ -1248,14 +1283,16 @@ impl TableProvider for ListingTable {
12481283 . with_file_groups ( partitioned_file_lists)
12491284 . with_constraints ( self . constraints . clone ( ) )
12501285 . with_statistics ( statistics)
1251- . with_projection ( projection. cloned ( ) )
1286+ . with_projection ( projection)
12521287 . with_limit ( limit)
1253- . with_output_ordering ( output_ordering )
1288+ . with_output_ordering ( known_file_ordering )
12541289 . with_table_partition_cols ( table_partition_cols)
12551290 . with_expr_adapter ( self . expr_adapter_factory . clone ( ) )
12561291 . build ( ) ,
12571292 )
1258- . await
1293+ . await ?;
1294+
1295+ Ok ( ScanResult :: new ( plan, filters. clone ( ) ) )
12591296 }
12601297
12611298 fn supports_filters_pushdown (
0 commit comments