fix: preserve computed projections in unions_to_filter - #25074
fix: preserve computed projections in unions_to_filter#25074pushnanashi2 wants to merge 1 commit into
Conversation
kumarUjjawal
left a comment
There was a problem hiding this comment.
Thank you @pushnanashi2 for the fix. I have left few comment for you. Please take a look. Some slt test would also be nice to have.
| LogicalPlan::Projection(Projection { input, .. }) => { | ||
| Arc::unwrap_or_clone(input) | ||
| } | ||
| LogicalPlan::Projection(_) => return None, |
There was a problem hiding this comment.
Removing SubqueryAlias has the same defect you just fixed for projections? SELECT x.a FROM t AS x WHERE x.a = 1 UNION SELECT x.a FROM t AS x WHERE x.a = 2 plans as a filter over the alias over TableScan: t, so the merged predicate still names x.a while the source only exposes t.a.
We should trip nothing and take the filter input as the source. GroupKey equality then keeps different projections apart and still merges identical ones, so views and derived tables keep the rewrite instead of losing it. That source needs the volatility test that the wrappers already get.
There was a problem hiding this comment.
Thanks, keeping the filter input intact makes sense. I’ll update the implementation and add tests over the next day or two.
I’ll also check whether different underlying sources with otherwise identical scan metadata can end up in the same GroupKey, since TableScan::eq does not compare source. I haven’t reproduced this yet; I’ll investigate and report back.
| wrappers, | ||
| })), | ||
| other => { | ||
| let Some(source) = strip_passthrough_nodes(other) else { |
There was a problem hiding this comment.
peel_wrappers already consumed every Projection and SubqueryAlias before this match, so the plan that reaches this arm can never be either one.
strip_passthrough_nodes returns Some on the first iteration here, and the new debug message cannot fire. I would use other directly as the source.
There was a problem hiding this comment.
Thanks for pointing this out. You're right: after peel_wrappers, other cannot be a Projection or SubqueryAlias, so strip_passthrough_nodes always returns Some(other) here. I’ll use other directly as the source and remove the redundant check and unreachable debug message
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #25074 +/- ##
==========================================
- Coverage 81.74% 81.74% -0.01%
==========================================
Files 1128 1128
Lines 416644 416682 +38
Branches 416644 416682 +38
==========================================
+ Hits 340592 340606 +14
- Misses 55995 56003 +8
- Partials 20057 20073 +16 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Which issue does this PR close?
Rationale for this change
With
enable_unions_to_filterenabled,UNION DISTINCTbranches containing different computed projections below their filters can be incorrectly treated as equivalent. This produces wrong result values and row counts without an error.What changes are included in this PR?
unions_to_filternow skips the rewrite when a projection appears below a branch filter. Alias nodes remain safe to strip. A regression test covers branches computinga + 100anda + 200below their filters.What is the testing strategy for this PR?
cargo +1.97.0-x86_64-pc-windows-gnullvm test --locked -p datafusion-optimizer unions_to_filter --lib(9 passed)[1100, 1200]with the optimizer setting both disabled and enabled after the fix.git diff --checkAre there any user-facing changes?
This prevents incorrect query results when the opt-in
unions_to_filteroptimizer rule is enabled.