@@ -1468,6 +1468,7 @@ pub fn wrap_partition_value_in_dict(val: ScalarValue) -> ScalarValue {
14681468#[ cfg( test) ]
14691469mod tests {
14701470 use super :: * ;
1471+ use crate :: test_util:: col;
14711472 use crate :: {
14721473 generate_test_files, test_util:: MockSource , tests:: aggr_test_schema,
14731474 verify_sort_integrity,
@@ -1476,8 +1477,9 @@ mod tests {
14761477 use arrow:: array:: { Int32Array , RecordBatch } ;
14771478 use datafusion_common:: stats:: Precision ;
14781479 use datafusion_common:: { assert_batches_eq, internal_err} ;
1479- use datafusion_expr:: SortExpr ;
1480+ use datafusion_expr:: { Operator , SortExpr } ;
14801481 use datafusion_physical_expr:: create_physical_sort_expr;
1482+ use datafusion_physical_expr:: expressions:: { BinaryExpr , Literal } ;
14811483
14821484 /// Returns the column names on the schema
14831485 pub fn columns ( schema : & Schema ) -> Vec < String > {
@@ -2233,6 +2235,54 @@ mod tests {
22332235 assert_eq ! ( config. output_ordering. len( ) , 1 ) ;
22342236 }
22352237
2238+ #[ test]
2239+ fn equivalence_properties_after_schema_change ( ) {
2240+ let file_schema = aggr_test_schema ( ) ;
2241+ let object_store_url = ObjectStoreUrl :: parse ( "test:///" ) . unwrap ( ) ;
2242+ // Create a file source with a filter
2243+ let file_source: Arc < dyn FileSource > =
2244+ Arc :: new ( MockSource :: default ( ) . with_filter ( Arc :: new ( BinaryExpr :: new (
2245+ col ( "c2" , & file_schema) . unwrap ( ) ,
2246+ Operator :: Eq ,
2247+ Arc :: new ( Literal :: new ( ScalarValue :: Int32 ( Some ( 10 ) ) ) ) ,
2248+ ) ) ) ) ;
2249+
2250+ let config = FileScanConfigBuilder :: new (
2251+ object_store_url. clone ( ) ,
2252+ Arc :: clone ( & file_schema) ,
2253+ Arc :: clone ( & file_source) ,
2254+ )
2255+ . with_projection ( Some ( vec ! [ 0 , 1 , 2 ] ) )
2256+ . build ( ) ;
2257+
2258+ // Simulate projection being updated. Since the filter has already been pushed down,
2259+ // the new projection won't include the filtered column.
2260+ let data_source = config
2261+ . try_swapping_with_projection ( & [ ProjectionExpr :: new (
2262+ col ( "c3" , & file_schema) . unwrap ( ) ,
2263+ "c3" . to_string ( ) ,
2264+ ) ] )
2265+ . unwrap ( )
2266+ . unwrap ( ) ;
2267+
2268+ // Gather the equivalence properties from the new data source. There should
2269+ // be no equivalence class for column c2 since it was removed by the projection.
2270+ let eq_properties = data_source. eq_properties ( ) ;
2271+ let eq_group = eq_properties. eq_group ( ) ;
2272+
2273+ for class in eq_group. iter ( ) {
2274+ for expr in class. iter ( ) {
2275+ if let Some ( col) = expr. as_any ( ) . downcast_ref :: < Column > ( ) {
2276+ assert_ne ! (
2277+ col. name( ) ,
2278+ "c2" ,
2279+ "c2 should not be present in any equivalence class"
2280+ ) ;
2281+ }
2282+ }
2283+ }
2284+ }
2285+
22362286 #[ test]
22372287 fn test_file_scan_config_builder_defaults ( ) {
22382288 let file_schema = aggr_test_schema ( ) ;
0 commit comments