@@ -29,7 +29,8 @@ use arrow::datatypes::{DataType, Schema, SchemaRef};
2929use datafusion_common:: config:: ConfigOptions ;
3030use datafusion_common:: tree_node:: TreeNodeRecursion ;
3131use datafusion_common:: {
32- Constraints , Result , ScalarValue , Statistics , internal_datafusion_err, internal_err,
32+ Constraints , Result , ScalarValue , Statistics , assert_eq_or_internal_err,
33+ internal_datafusion_err, internal_err,
3334} ;
3435use datafusion_execution:: {
3536 SendableRecordBatchStream , TaskContext , object_store:: ObjectStoreUrl ,
@@ -38,15 +39,15 @@ use datafusion_expr::Operator;
3839
3940use datafusion_physical_expr:: equivalence:: project_orderings;
4041use datafusion_physical_expr:: expressions:: { BinaryExpr , Column } ;
41- use datafusion_physical_expr:: projection:: ProjectionExprs ;
42+ use datafusion_physical_expr:: projection:: { ProjectionExpr , ProjectionExprs } ;
4243use datafusion_physical_expr:: utils:: reassign_expr_columns;
4344use datafusion_physical_expr:: { EquivalenceProperties , Partitioning , split_conjunction} ;
4445use datafusion_physical_expr_adapter:: PhysicalExprAdapterFactory ;
4546use datafusion_physical_expr_common:: physical_expr:: PhysicalExpr ;
4647use datafusion_physical_expr_common:: sort_expr:: { LexOrdering , PhysicalSortExpr } ;
4748use datafusion_physical_plan:: SortOrderPushdownResult ;
4849use datafusion_physical_plan:: coop:: cooperative;
49- use datafusion_physical_plan:: execution_plan:: SchedulingType ;
50+ use datafusion_physical_plan:: execution_plan:: { ReplacePhysicalExpr , SchedulingType } ;
5051use datafusion_physical_plan:: {
5152 DisplayAs , DisplayFormatType ,
5253 display:: { ProjectSchemaDisplay , display_orderings} ,
@@ -941,6 +942,75 @@ impl DataSource for FileScanConfig {
941942 // Delegate to the file source
942943 self . file_source . apply_expressions ( f)
943944 }
945+
946+ fn physical_expressions < ' a > (
947+ & ' a self ,
948+ ) -> Option < Box < dyn Iterator < Item = Arc < dyn PhysicalExpr > > + ' a > > {
949+ let filter = self . file_source . filter ( ) . into_iter ( ) ;
950+ let projection = self
951+ . file_source
952+ . projection ( )
953+ . into_iter ( )
954+ . flat_map ( |p| p. expr_iter ( ) ) ;
955+
956+ Some ( Box :: new ( filter. chain ( projection) ) )
957+ }
958+
959+ fn with_physical_expressions (
960+ & self ,
961+ params : ReplacePhysicalExpr ,
962+ ) -> Result < Option < Arc < dyn DataSource > > > {
963+ let filter_count = self . file_source . filter ( ) . iter ( ) . len ( ) ;
964+ let projection_count = self
965+ . file_source
966+ . projection ( )
967+ . map ( |p| p. expr_iter ( ) . count ( ) )
968+ . unwrap_or ( 0 ) ;
969+
970+ let expected_count = filter_count + projection_count;
971+ let exprs_count = params. exprs . len ( ) ;
972+
973+ assert_eq_or_internal_err ! (
974+ expected_count,
975+ exprs_count,
976+ "Inconsistent number of physical expressions for FileScanConfig" ,
977+ ) ;
978+
979+ let mut filter = None ;
980+ let mut projection = vec ! [ ] ;
981+ let mut expr_iter = params. exprs . into_iter ( ) ;
982+
983+ if filter_count > 0 {
984+ filter = expr_iter. next ( ) ;
985+ }
986+
987+ if projection_count > 0 {
988+ projection = self
989+ . file_source
990+ . projection ( )
991+ . expect ( "should have expressions" )
992+ . iter ( )
993+ . zip ( expr_iter)
994+ . map ( |( p, expr) | ProjectionExpr :: new ( expr, p. alias . clone ( ) ) )
995+ . collect ( ) ;
996+ }
997+
998+ let file_source = self
999+ . file_source
1000+ . with_filter_and_projection ( filter, projection. into ( ) ) ?;
1001+
1002+ match file_source {
1003+ Some ( file_source) => {
1004+ let conf_builder: FileScanConfigBuilder = self . clone ( ) . into ( ) ;
1005+ Ok ( Some ( Arc :: new (
1006+ conf_builder. with_source ( file_source) . build ( ) ,
1007+ ) ) )
1008+ }
1009+ None => {
1010+ internal_err ! ( "file source is not rebuilt" )
1011+ }
1012+ }
1013+ }
9441014}
9451015
9461016impl FileScanConfig {
0 commit comments