Skip to content

branch-4.1: [fix](nereids) Allocate fresh ExprId for constants when pushing project into Union #62296#63018

Merged
yiguolei merged 1 commit into
branch-4.1from
auto-pick-62296-branch-4.1
May 7, 2026
Merged

branch-4.1: [fix](nereids) Allocate fresh ExprId for constants when pushing project into Union #62296#63018
yiguolei merged 1 commit into
branch-4.1from
auto-pick-62296-branch-4.1

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 6, 2026

Cherry-picked from #62296

…ct into Union (#62296)

### What problem does this PR solve?

Issue Number: close #62294

Problem Summary:

When `PushProjectIntoUnion` folds a parent `Project`'s expression into a
`LogicalUnion`'s `constantExprsList`, the outer `Alias` of a
non-`SlotReference` project expression is preserved by
`ExpressionUtils.replaceNameExpression`. Its `ExprId` then collides with
the new UNION output `ExprId` (which comes from the parent project's
output `Alias`) and is reused across every constant row of the same
column. Downstream rules such as `PushDownFilterThroughSetOperation`
rely on the invariant that each `constantExprsList` row carries
`NamedExpression`s whose `ExprId`s are distinct from the UNION output
and from each other across rows; the collision causes them to
mis-rewrite the plan and return wrong results, e.g.

```sql
WITH tbl0(n) AS (SELECT 1 UNION ALL SELECT 3 UNION ALL SELECT NULL),
     tbl1(n) AS (SELECT 2 UNION ALL SELECT NULL UNION ALL SELECT 1)
SELECT (n*2) AS n FROM tbl0
INTERSECT
SELECT (n*2) AS n FROM tbl1;
```

`PushProjectThroughUnion` has the same class of bug in its mixed-union
constant-row branch: when `MergeOneRowRelationIntoUnion` folds a
`LogicalOneRowRelation` into the union's `constantExprsList`, an outer
`Alias(Cast(slot))` project survives `outerProject.rewriteUp` with its
parent `ExprId` intact, and then the same `ExprId` is reused as the new
UNION output via `project.toSlot()`. The plan-level invariant is broken
even though no current downstream rule appears to mis-handle the
specific shape today.

Fix:
- `PushProjectIntoUnion`: after folding the substituted expression,
re-wrap the result in a fresh `Alias` so each constant cell receives a
new unique `ExprId`. Qualifier and name from the folded `Alias` are
preserved. The `SlotReference` branch is left unchanged because it
already returns the original `NamedExpression` from `constExprs` whose
`ExprId`s are row-distinct and not equal to the UNION output `ExprId`.
- `PushProjectThroughUnion`: same treatment for the constant-row
non-Slot branch — re-wrap the rewritten `Alias` to allocate a fresh
`ExprId`.

Introduced by #39450 (closest commit touching the relevant lines; the
file `PushProjectIntoUnion` was originally added by #27947).

### Release note

Fix wrong results for INTERSECT/EXCEPT/UNION over constant rows when the
projection contains expressions such as `((col*2) AS col)`, and harden
the parallel `PushProjectThroughUnion` rule against the same class of
ExprId collision.


Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot requested a review from yiguolei as a code owner May 6, 2026 08:44
@hello-stephen
Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

@hello-stephen
Copy link
Copy Markdown
Contributor

run buildall

@yiguolei yiguolei merged commit f888e1f into branch-4.1 May 7, 2026
29 of 32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants