peter-toth opened a new pull request, #59308:
URL: https://github.com/apache/spark/pull/59308

   ### Differences from #59294
   
   This is the branch-4.2 backport of #59294. The description below is the 
original one.
   
   - On branch-4.2 `PlanMerger` and `MergeSubplansSuite` are in `sql/catalyst` 
(`org.apache.spark.sql.catalyst.optimizer`), and the end-to-end suite is 
`org.apache.spark.sql.PlanMergeSuite`. The tests went in unchanged.
   - The `PlanMerger` change was ported by hand, because git couldn't map it to 
the catalyst file. 4.2's `PlanMerger` has no DSv2 scan merge, so the code 
around the tagged `(Filter, Filter)` branch looks different. The same lines 
change: the lookup restriction, the dropped `isNew` flag and the append check 
in `mergeNamedExpressions`.
   - On branch-4.2 the 4 new tests fail without the fix. With it, 
`MergeSubplansSuite` (58 tests) and `PlanMergeSuite` (14 tests) pass, and 
scalastyle is clean.
   
   ### What changes were proposed in this pull request?
   
   `PlanMerger.mergeNamedExpressions` appended the new plan's propagated filter 
attribute only when it was a fresh alias. A reused one (`isNew = false`) was 
assumed to be in the merged expression list already.
   
   This PR appends the new plan's filter attribute whenever the list doesn't 
output it yet. It also drops the `isNew` flag from 
`TryMergeResult.newPlanFilter`, because nothing reads it any more.
   
   The reuse lookup in the tagged `(Filter, Filter)` branch now only matches 
the filter aliases that the merged `Filter` references. Before, a computed 
column with the same expression as the new plan's filter could be reused, and 
the merged `Filter` would drop that plan's rows.
   
   ### Why are the changes needed?
   
   The assumption doesn't hold. A merge round can fold a filter attribute into 
another filter alias, and then only the new alias is carried up to the 
aggregate. A later round that reuses the original attribute ends up with an 
aggregate `FILTER` on an attribute its child doesn't output:
   
   ```sql
   SET 
spark.sql.optimizer.mergeSubplans.filterPropagation.symmetricFilterPropagation.enabled=true;
   SET 
spark.sql.optimizer.mergeSubplans.filterPropagation.throughJoin.enabled=true;
   
   CREATE TABLE t USING parquet AS SELECT * FROM VALUES
     (1, 1, 10), (1, 2, 3), (2, 1, 7), (2, 2, 9), (3, 1, 9), (3, 2, 6) AS v(a, 
b, c);
   
   SELECT
     (SELECT sum(l.a) FROM t l LEFT JOIN t r ON l.a = r.a WHERE l.b = 1),
     (SELECT max(l.a) FROM t l LEFT JOIN t r ON l.a = r.a WHERE l.b = 2 AND 
coalesce(r.c, 10) > 5),
     (SELECT count(*) FROM t l LEFT JOIN t r ON l.a = r.a WHERE l.b = 2);
   ```
   
   ```
   [INTERNAL_ERROR_ATTRIBUTE_NOT_FOUND] Could not find propagatedFilter_3#179 
in 
[sum#141L,max#182,count#145L,a#6,propagatedFilter_5#181,propagatedFilter_4#180].
 SQLSTATE: XX000
   ```
   
   What happens there:
   1. Merging the 2nd subquery into the 1st aliases `l.b = 2` on the left side 
of the join.
   2. The 2nd subquery's post-join `coalesce(r.c, 10) > 5` folds that alias 
into a new `AND` alias.
   3. The 3rd subquery reuses the `l.b = 2` alias, but the `Project` under the 
aggregate only outputs the new one.
   
   This was found while reviewing #59161, which runs into the same problem 
through its new join `AND`.
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. The query above now returns `12, 3, 6` instead of failing. It needs 
both configs above, which are off by default. The bug is in 4.2.0.
   
   ### How was this patch tested?
   
   New tests in `MergeSubplansSuite` (merged plans, including the computed 
column case) and `PlanMergingSuite` (end to end). They all fail without the 
fix. `MergeSubplansSuite` and `PlanMergingSuite` pass.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Code (Claude Opus 5.5)
   
   
   


-- 
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