Fix Column identifier is already registered with additional_result_filter in UNION/EXCEPT by alexey-milovidov · Pull Request #101051 · ClickHouse/ClickHouse · GitHub
Skip to content

Fix Column identifier is already registered with additional_result_filter in UNION/EXCEPT#101051

Merged
alexey-milovidov merged 12 commits into
masterfrom
fix-column-identifier-additional-result-filter
Apr 25, 2026
Merged

Fix Column identifier is already registered with additional_result_filter in UNION/EXCEPT#101051
alexey-milovidov merged 12 commits into
masterfrom
fix-column-identifier-additional-result-filter

Conversation

@alexey-milovidov

@alexey-milovidov alexey-milovidov commented Mar 29, 2026

Copy link
Copy Markdown
Member

When multiple UNION/EXCEPT branches share the same GlobalPlannerContext and each applies additional_result_filter, the addAdditionalFilterStepIfNeeded function creates a fake TableNode without an alias for each branch. Both branches try to register the same bare column identifier (e.g. a) in the shared context, causing the second to throw a LOGICAL_ERROR exception.

Fix by giving each fake table expression a unique alias so that column identifiers become unique across branches.

Fixes #99931

CI report: https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=100947&sha=d0c5ef2315e4d001a6d34cf2e54a9ee2b176a538&name_0=PR&name_1=Stress%20test%20%28amd_debug%29
#100947

Changelog category (leave one):

  • Bug Fix (user-visible misbehavior in an official stable release)

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

Fix LOGICAL_ERROR exception "Column identifier is already registered" when additional_result_filter setting is used with UNION or EXCEPT queries.

Documentation entry for user-facing changes

  • Documentation is written (mandatory for new features)

Version info

  • Merged into: 26.5.1.81

…_filter` in UNION/EXCEPT

When multiple UNION branches share the same `GlobalPlannerContext` and each
applies `additional_result_filter`, the `addAdditionalFilterStepIfNeeded`
function creates a fake `TableNode` without an alias for each branch. Both
branches try to register the same bare column identifier (e.g. "a") in the
shared context, causing the second to throw a LOGICAL_ERROR.

Fix by giving each fake table expression a unique alias so that column
identifiers become unique across branches (e.g. "_additional_result_filter_0.a"
and "_additional_result_filter_1.a").

Fixes #99931
https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=100947&sha=d0c5ef2315e4d001a6d34cf2e54a9ee2b176a538&name_0=PR&name_1=Stress%20test%20%28amd_debug%29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@clickhouse-gh

clickhouse-gh Bot commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

@clickhouse-gh clickhouse-gh Bot added the pr-bugfix Pull request with bugfix, not backported by default label Mar 29, 2026
Comment thread src/Planner/Planner.cpp Outdated
/// When multiple UNION branches share the same GlobalPlannerContext and each applies additional_result_filter,
/// the bare column names (e.g. "a") would collide. Give the fake table expression a unique alias
/// so that identifiers become unique (e.g. "_additional_result_filter_0.a").
auto unique_alias = "_additional_result_filter_" + std::to_string(planner_context->getGlobalPlannerContext()->nextUniqueId());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ This alias is deterministic and can still collide with real query aliases. For example, if a user has a source alias _additional_result_filter_0 and a projected column a, GlobalPlannerContext::createColumnIdentifier can still throw Column identifier ... is already registered for _additional_result_filter_0.a.

Please make the synthetic alias collision-resistant against existing identifiers in the shared context, e.g. loop over generated aliases until alias + "." + projection_column does not exist in GlobalPlannerContext (or use a truly unique suffix that cannot appear in user aliases).

@alexey-milovidov

Copy link
Copy Markdown
Member Author

The Stress test (arm_msan) failure is fixed by #101239, which should be merged first. After it is merged, please update the branch to include the fix.

alexey-milovidov and others added 6 commits April 6, 2026 17:49
The synthetic alias `_additional_result_filter_N` used in
`addAdditionalFilterStepIfNeeded` was deterministic and could collide
with a real user alias. Now loop over candidate aliases, checking each
against existing column identifiers in `GlobalPlannerContext`, until
a collision-free one is found.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CREATE TABLE t_04064 (x UInt64) ENGINE = MergeTree ORDER BY x;
INSERT INTO t_04064 VALUES (1), (2), (3);

SELECT * FROM (SELECT x AS a FROM t_04064)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ This regression test covers UNION/EXCEPT with regular aliases, but it does not exercise the collision scenario fixed in the second commit (user alias like _additional_result_filter_0).

Please add a case where a branch explicitly uses _additional_result_filter_0 (or similar) as a table/query alias and verifies additional_result_filter works without Column identifier ... is already registered exception.

@clickhouse-gh

clickhouse-gh Bot commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

LLVM Coverage Report

Metric Baseline Current Δ
Lines 83.80% 83.80% +0.00%
Functions 91.10% 91.10% +0.00%
Branches 76.20% 76.30% +0.10%

Changed lines: 83.33% (15/18) · Uncovered code

Full report · Diff report

@alexey-milovidov alexey-milovidov added this pull request to the merge queue Apr 25, 2026
Merged via the queue into master with commit 1e20a7f Apr 25, 2026
165 checks passed
@alexey-milovidov alexey-milovidov deleted the fix-column-identifier-additional-result-filter branch April 25, 2026 12:54
@robot-clickhouse robot-clickhouse added the pr-synced-to-cloud The PR is synced to the cloud repo label Apr 25, 2026
@clickgapai

Copy link
Copy Markdown
Contributor

alexey-milovidov added a commit that referenced this pull request Apr 27, 2026
The original "Column identifier is already registered" exception is fixed
by other PRs that landed on master:

- #101048 ("Fix exception 'Column identifier is already registered' in planner")
- #101051 ("Fix Column identifier is already registered with additional_result_filter in UNION/EXCEPT")

Per the author's review comment on this PR, drop the disambiguation
workaround in `GlobalPlannerContext::createColumnIdentifier` and keep
only the regression test from this PR as a guard.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
alexey-milovidov added a commit that referenced this pull request Apr 27, 2026
Reword the comment per review feedback and note that the underlying bug
was fixed by other PRs (#101048, #101051), so this test remains as a
regression guard rather than as a reproducer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-bugfix Pull request with bugfix, not backported by default pr-synced-to-cloud The PR is synced to the cloud repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logical error: Column identifier A is already registered (STID: 4697-4326)

4 participants