Fix logical error "Column identifier ... is already registered" in mutations#106414
Conversation
…tations A mutation (lightweight `DELETE`, `ALTER UPDATE`, `ALTER DELETE`) whose predicate contains an `IN` / `EXISTS` subquery that reads from a default table expression nested in another subquery threw a logical error such as `Column identifier dummy is already registered`. `DELETE FROM test_filter WHERE exists((SELECT DISTINCT * LIMIT 452))` is rewritten to `1 IN (SELECT 1 FROM (SELECT DISTINCT * LIMIT 452) ...)`, where the inner `SELECT *` reads `system.one` (column `dummy`). On the analyzer mutation path, `buildSubqueryPlansForSetsAndAdd` plans each set subquery standalone with its own `GlobalPlannerContext`, but the detached subquery tree had no unique table aliases. Two distinct table expressions exposing a column with the same name both produced a bare column identifier, and `GlobalPlannerContext::createColumnIdentifier` threw because the identifier was already registered. The regular planner path (`addBuildSubqueriesForSetsStepIfNeeded`) collects sets from an already-aliased query tree, so this never happens there. Re-apply `createUniqueAliasesIfNecessary` to the detached set subquery before planning it on the mutation path. Found by the AST fuzzer: https://s3.amazonaws.com/clickhouse-test-reports/json.html?REF=master&sha=33b37ca22cfe6d153b35f57f36d8e649750e2061&name_0=MasterCI&name_1=AST%20fuzzer%20%28amd_debug%29 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…query-column-identifier
|
Merged Empirically verified the fix end-to-end:
Built clean after the merge. The two red CI checks are pre-existing, unrelated master failures:
|
…query-column-identifier
|
Merged The only red is the ARM |
…query-column-identifier
|
Merged The two CI failure categories were both unrelated to this analyzer/mutation-planner change:
|
LLVM Coverage ReportChanged lines: Changed C/C++ lines covered by tests: 4/4 (100.00%) | Lost baseline coverage: none · Uncovered code |
…ions Per @novikd's review (ClickHouse#106025 "remove the code added in ClickHouse#106414 (keep the test)") and the unresolved thread asking to reuse `traverseQueryTree` instead of a new visitor. Both halves of this PR's earlier code are now redundant with `master`: * The non-correlated `EXISTS` crash-fix (`createUniqueAliasesIfNecessary` on the detached subquery) landed independently on `master` via ClickHouse#106414 (`MutationsInterpreter.cpp`). * Correlated subqueries in mutations are already rejected with `NOT_IMPLEMENTED` on `master` by `correlated_subtrees.assertEmpty("in mutation filter"/"in mutation update")` in `MutationsInterpreter::prepareMutationStages`. This PR's `ValidateNoCorrelatedSubqueryVisitor` therefore added no behavior over `master`; `Bugfix validation` confirms the regression test `04303_stid_4697_4326_mutation_exists_column_identifier` already passes on the unfixed base, so every case it covers is handled by the existing `master` code. Restore `MutationsInterpreter.cpp` to `master` and keep only the regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

A mutation (lightweight
DELETE,ALTER UPDATE,ALTER DELETE) whose predicate contains anIN/EXISTSsubquery that reads from a default table expression nested in another subquery threw a logical error such asColumn identifier dummy is already registered.For example:
exists((subquery))is rewritten to1 IN (SELECT 1 FROM (subquery) ...), and the innerSELECT *over aFROM-less query readssystem.one(columndummy). On the analyzer mutation path,buildSubqueryPlansForSetsAndAddplans each set subquery standalone with its ownGlobalPlannerContext, but the detached subquery tree carried no unique table aliases. Two distinct table expressions exposing a column with the same name both produced a bare column identifier, andGlobalPlannerContext::createColumnIdentifierthrew because the identifier was already registered.The regular planner path (
addBuildSubqueriesForSetsStepIfNeeded) collects sets from an already-aliased query tree, so the collision never occurs there. The fix re-appliescreateUniqueAliasesIfNecessaryto the detached set subquery before planning it on the mutation path.Found by the AST fuzzer: https://s3.amazonaws.com/clickhouse-test-reports/json.html?REF=master&sha=33b37ca22cfe6d153b35f57f36d8e649750e2061&name_0=MasterCI&name_1=AST%20fuzzer%20%28amd_debug%29
Closes #99931 (same STID
4697-4326), related to #100678.Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fix a logical error
Column identifier ... is already registeredwhen a mutation (DELETE/UPDATE) predicate contains anIN/EXISTSsubquery that reads from a default table expression nested in another subquery.Documentation entry for user-facing changes
🤖 Generated with Claude Code
Version info
26.6.1.742