@@ -2871,39 +2871,25 @@ fn assert_dynamic_filter_update_is_visible(
28712871 Ok ( ( ) )
28722872}
28732873
2874- /// Format the observable state of a `DynamicFilterPhysicalExpr` for
2875- /// equality comparison in roundtrip tests.
2876- fn fmt_dynamic_filter ( filter : & DynamicFilterPhysicalExpr ) -> String {
2877- let inner = filter. inner ( ) ;
2878- format ! (
2879- "DynamicFilter {{ children: {:?}, remapped_children: {:?}, expression_id: {}, generation: {}, inner_expr: {:?}, is_complete: {} }}" ,
2880- filter. original_children( ) ,
2881- filter. remapped_children( ) ,
2882- filter
2883- . expression_id( )
2884- . expect( "DynamicFilterPhysicalExpr always has an expression_id" ) ,
2885- inner. generation,
2886- inner. expr,
2887- inner. is_complete,
2888- )
2889- }
2890-
2891- /// Assert that the actual dynamic filter snapshot matches the expected one
2892- /// after roundtrip.
2893- fn assert_dynamic_filter_snapshot_matches (
2874+ /// Assert that two dynamic filters are equal both structurally (Debug output)
2875+ /// and by identity (`expression_id`).
2876+ ///
2877+ fn assert_dynamic_filters_equal (
28942878 expected : & Arc < dyn PhysicalExpr > ,
28952879 actual : & Arc < dyn PhysicalExpr > ,
28962880) {
2897- let expected_filter = expected
2898- . downcast_ref :: < DynamicFilterPhysicalExpr > ( )
2899- . expect ( "Expected dynamic filter" ) ;
2900- let actual_filter = actual
2901- . downcast_ref :: < DynamicFilterPhysicalExpr > ( )
2902- . expect ( "Expected dynamic filter" ) ;
2903-
2904- let actual_snapshot = fmt_dynamic_filter ( actual_filter) ;
2905- let expected_snapshot = fmt_dynamic_filter ( expected_filter) ;
2906- if expected_snapshot == actual_snapshot {
2881+ // TODO: Debug currently omits `expression_id` so the id has to be checked
2882+ // separately here. Once plan nodes like `SortExec` / `AggregateExec` /
2883+ // `HashJoinExec` serialize their own dynamic filter, Debug can include
2884+ // `expression_id`.
2885+ //
2886+ // See https://github.com/apache/datafusion/issues/20418
2887+ assert_eq ! ( expected. expression_id( ) , actual. expression_id( ) ) ;
2888+
2889+ // Structural.
2890+ let expected_dbg = format ! ( "{expected:?}" ) ;
2891+ let actual_dbg = format ! ( "{actual:?}" ) ;
2892+ if expected_dbg == actual_dbg {
29072893 return ;
29082894 }
29092895
@@ -2913,12 +2899,7 @@ fn assert_dynamic_filter_snapshot_matches(
29132899 let rewritten = Arc :: clone ( expected)
29142900 . with_new_children ( expected. children ( ) . iter ( ) . map ( |c| Arc :: clone ( c) ) . collect ( ) )
29152901 . expect ( "with_new_children on a dynamic filter should not fail" ) ;
2916- let rewritten_snapshot = fmt_dynamic_filter (
2917- rewritten
2918- . downcast_ref :: < DynamicFilterPhysicalExpr > ( )
2919- . expect ( "with_new_children returns a DynamicFilterPhysicalExpr" ) ,
2920- ) ;
2921- assert_eq ! ( rewritten_snapshot, actual_snapshot) ;
2902+ assert_eq ! ( format!( "{rewritten:?}" ) , actual_dbg) ;
29222903}
29232904
29242905// Two clones of a dynamic filter expression should be deduped to the exact same expression.
@@ -2936,15 +2917,9 @@ fn test_dynamic_filter_roundtrip_dedupe() -> Result<()> {
29362917 ) ?;
29372918
29382919 // Assert the filters are not modified during roundtrip.
2939- assert_dynamic_filter_snapshot_matches (
2940- & filter_expr_1,
2941- & filter_expr_1_after_roundtrip,
2942- ) ;
2943- assert_dynamic_filter_snapshot_matches (
2944- & filter_expr_2,
2945- & filter_expr_2_after_roundtrip,
2946- ) ;
2947- assert_dynamic_filter_snapshot_matches (
2920+ assert_dynamic_filters_equal ( & filter_expr_1, & filter_expr_1_after_roundtrip) ;
2921+ assert_dynamic_filters_equal ( & filter_expr_2, & filter_expr_2_after_roundtrip) ;
2922+ assert_dynamic_filters_equal (
29482923 & filter_expr_1_after_roundtrip,
29492924 & filter_expr_2_after_roundtrip,
29502925 ) ;
@@ -2970,14 +2945,8 @@ fn test_dynamic_filter_plan_roundtrip_dedupe() -> Result<()> {
29702945 ) = roundtrip_dynamic_filter_plan_pair ( ) ?;
29712946
29722947 // Assert the filters are not modified during roundtrip.
2973- assert_dynamic_filter_snapshot_matches (
2974- & filter_expr_1,
2975- & filter_expr_1_after_roundtrip,
2976- ) ;
2977- assert_dynamic_filter_snapshot_matches (
2978- & filter_expr_2,
2979- & filter_expr_2_after_roundtrip,
2980- ) ;
2948+ assert_dynamic_filters_equal ( & filter_expr_1, & filter_expr_1_after_roundtrip) ;
2949+ assert_dynamic_filters_equal ( & filter_expr_2, & filter_expr_2_after_roundtrip) ;
29812950
29822951 // Assert referential integrity.
29832952 assert_dynamic_filter_update_is_visible (
0 commit comments