sunchao commented on code in PR #25579:
URL: https://github.com/apache/datafusion/pull/25579#discussion_r4074509468


##########
datafusion/sqllogictest/test_files/push_down_filter_regression.slt:
##########
@@ -443,6 +443,65 @@ drop table agg_dyn_mixed;
 statement ok
 reset datafusion.execution.batch_size;
 
+# --- one aggregate has a bound before another sees its first non-NULL value 
---
+# Both files establish MIN(a)=1 and MAX(a)=8 in their first row group. Until b
+# has a non-NULL bound, filtering only on a would prune every remaining row and
+# incorrectly leave MIN(b) and MAX(b) NULL, regardless of partition order.
+
+statement ok
+set datafusion.execution.batch_size = 2;
+
+statement ok
+COPY (
+  SELECT * FROM (VALUES (1, NULL), (8, NULL), (2, 5), (3, 7)) AS v(a, b)
+) TO 
'test_files/scratch/push_down_filter_regression/agg_dyn_late_bound/file_0.parquet'
+STORED AS PARQUET
+OPTIONS ('format.max_row_group_size' '2');
+
+statement ok
+COPY (
+  SELECT * FROM (VALUES (1, NULL), (8, NULL), (2, 5), (3, 7)) AS v(a, b)
+) TO 
'test_files/scratch/push_down_filter_regression/agg_dyn_late_bound/file_1.parquet'
+STORED AS PARQUET
+OPTIONS ('format.max_row_group_size' '2');
+
+statement ok
+CREATE EXTERNAL TABLE agg_dyn_late_bound (a INT, b INT)
+STORED AS PARQUET
+LOCATION 'test_files/scratch/push_down_filter_regression/agg_dyn_late_bound/';
+
+statement ok
+set datafusion.optimizer.enable_aggregate_dynamic_filter_pushdown = false;
+
+query IIII
+SELECT MIN(a), MAX(a), MIN(b), MAX(b) FROM agg_dyn_late_bound;
+----
+1 8 5 7
+
+statement ok
+set datafusion.optimizer.enable_aggregate_dynamic_filter_pushdown = true;
+
+query IIII
+SELECT MIN(a), MAX(a), MIN(b), MAX(b) FROM agg_dyn_late_bound;
+----
+1 8 5 7
+
+# Filtering resumes once every aggregate has seen a non-NULL value.
+query TT
+EXPLAIN ANALYZE SELECT MIN(a), MAX(a), MIN(b), MAX(b) FROM agg_dyn_late_bound;
+----
+Plan with Metrics
+01)AggregateExec: mode=Final, gby=[], aggr=[min(agg_dyn_late_bound.a), 
max(agg_dyn_late_bound.a), min(agg_dyn_late_bound.b), 
max(agg_dyn_late_bound.b)], metrics=[]
+02)--CoalescePartitionsExec, metrics=[]
+03)----AggregateExec: mode=Partial, gby=[], aggr=[min(agg_dyn_late_bound.a), 
max(agg_dyn_late_bound.a), min(agg_dyn_late_bound.b), 
max(agg_dyn_late_bound.b)], metrics=[]
+04)------DataSourceExec: file_groups={2 groups: 
[[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/push_down_filter_regression/agg_dyn_late_bound/file_0.parquet],
 
[WORKSPACE_ROOT/datafusion/sqllogictest/test_files/scratch/push_down_filter_regression/agg_dyn_late_bound/file_1.parquet]]},
 projection=[a, b], file_type=parquet, predicate=DynamicFilter [ a@0 < 1 OR a@0 
> 8 OR b@1 < 5 OR b@1 > 7 ], dynamic_rg_pruning=eligible, 
pruning_predicate=a_null_count@1 != row_count@2 AND a_min@0 < 1 OR 
a_null_count@1 != row_count@2 AND a_max@3 > 8 OR b_null_count@5 != row_count@2 
AND b_min@4 < 5 OR b_null_count@5 != row_count@2 AND b_max@6 > 7, 
required_guarantees=[], metrics=[]

Review Comment:
   [P2] Make the final dynamic-filter assertion deterministic
   
   This exact snapshot can fail even when the query correctly returns `1 8 5 
7`. Giving both files the same extrema does not guarantee the final filter when 
the first batch publishes `true`:
   
   1. Partition A processes its first batch and constructs `true`, then is 
preempted before `filter.update`.
   2. Partition B processes both batches and publishes the complete four-bound 
predicate.
   3. A resumes and publishes its saved `true`. Its second batch does not 
improve any shared bound, so `bounds_changed` stays false and the complete 
predicate is never republished.
   
   The partitions run in independent tasks on a multithreaded runtime, and 
predicate construction/publication are not covered by one lock. I verified this 
interleaving with a deterministic native test using the production helpers: 
both partitions produced `[1, 8, 5, 7]`, while the final predicate was `true`. 
This is a controlled scheduling witness, not a naturally observed SLT failure. 
The publication race predates this PR; the new exact plan assertion introduces 
the flaky expectation.
   
   Please retain the enabled/disabled SQL result assertions and verify 
typed-null recovery/resumed filtering in a controlled execution test, or 
otherwise make this snapshot assertion insensitive to the valid publication 
order.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to