From c7c745bed2238152ad5c46a33e645d9b914026c3 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov <32552679+zvonand@users.noreply.github.com> Date: Thu, 8 Oct 2026 11:13:22 +0200 Subject: [PATCH 1/2] Cherry-pick of https://github.com/Altinity/ClickHouse/pull/2471 with unresolved conflict markers (resolution in next commit) --- Original cherry-pick message follows: Merge pull request #2471 from Altinity/bugfix/antalya-26.6/fix-union-hostname-server-constant Do not reuse a server constant built in another scope. # Conflicts: # src/Analyzer/Resolve/resolveFunction.cpp --- src/Analyzer/Resolve/resolveFunction.cpp | 11 +++++++++++ ...union_hostname_with_cluster_function.reference | 2 ++ ...05294_union_hostname_with_cluster_function.sql | 15 +++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/queries/0_stateless/05294_union_hostname_with_cluster_function.reference create mode 100644 tests/queries/0_stateless/05294_union_hostname_with_cluster_function.sql diff --git a/src/Analyzer/Resolve/resolveFunction.cpp b/src/Analyzer/Resolve/resolveFunction.cpp index bb3e74a48993..0aa4ee485b01 100644 --- a/src/Analyzer/Resolve/resolveFunction.cpp +++ b/src/Analyzer/Resolve/resolveFunction.cpp @@ -2763,6 +2763,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi /// `getTreeHash` walks the whole argument subtree, dominating analysis of deeply nested expressions. /// So the hash and the cache are computed only for non-deterministic functions. /// +<<<<<<< HEAD /// The cache is global across the whole query, so only a function that is stable inside a query /// may be shared. A function that is not deterministic in the scope of a query (`getSetting`, /// `getSettingOrDefault`, `blockNumber`, `rowNumberInAllBlocks`, ...) must NOT be shared: its @@ -2777,6 +2778,16 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi /// is the documented way to ask for two different constants in one query. if (function && !function->isDeterministic() && !function->isStateful() && function->isDeterministicInScopeOfQuery()) +======= + /// `getSetting` and `rowNumberInAllBlocks` are non-deterministic but must NOT be shared: the cache + /// is global across scopes, and e.g. `SETTINGS` can change `getSetting`'s result for every scope. + /// + /// Server constants (`hostName`, `serverUUID`, ...) capture `Context::isDistributed` when built. + /// A local `UNION` branch and a later cluster branch must not share that instance. + if (function && !function->isDeterministic() + && !function->isServerConstant() + && function_name != "getSetting" && function_name != "rowNumberInAllBlocks") +>>>>>>> f61f42a5fc6 (Merge pull request #2471 from Altinity/bugfix/antalya-26.6/fix-union-hostname-server-constant) { auto hash = function_node_ptr->getTreeHash({ .compare_aliases = false }); function_base_cache = &functions_cache[hash]; diff --git a/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.reference b/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.reference new file mode 100644 index 000000000000..8c8256f6afc5 --- /dev/null +++ b/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.reference @@ -0,0 +1,2 @@ +1 1 1 +2 2 1 diff --git a/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.sql b/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.sql new file mode 100644 index 000000000000..b578f6ad5915 --- /dev/null +++ b/tests/queries/0_stateless/05294_union_hostname_with_cluster_function.sql @@ -0,0 +1,15 @@ +-- A local GROUP BY hostName() must not be reused for a later cluster branch. +-- hostName() is folded on the local branch and must stay a per-shard column on the cluster branch. + +SELECT tag, c, h = hostName() +FROM +( + SELECT hostName() AS h, count() AS c, 1 AS tag + FROM numbers(1) + GROUP BY h + UNION ALL + SELECT hostName() AS h, count() AS c, 2 AS tag + FROM cluster('test_cluster_two_shards', system.one) + GROUP BY h +) +ORDER BY tag; From 9951eed3f97e03de418286fa105e1cc84a822284 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov <32552679+zvonand@users.noreply.github.com> Date: Thu, 8 Oct 2026 16:44:57 +0200 Subject: [PATCH 2/2] Resolve conflicts in cherry-pick of #2471 Kept the antalya-26.8 cache condition (`isStateful` / `isDeterministicInScopeOfQuery`), which replaced the hardcoded `getSetting` / `rowNumberInAllBlocks` name checks, and added the PR's `isServerConstant` exclusion and comment on top of it. --- src/Analyzer/Resolve/resolveFunction.cpp | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Analyzer/Resolve/resolveFunction.cpp b/src/Analyzer/Resolve/resolveFunction.cpp index 0aa4ee485b01..9961d7419d20 100644 --- a/src/Analyzer/Resolve/resolveFunction.cpp +++ b/src/Analyzer/Resolve/resolveFunction.cpp @@ -2763,7 +2763,6 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi /// `getTreeHash` walks the whole argument subtree, dominating analysis of deeply nested expressions. /// So the hash and the cache are computed only for non-deterministic functions. /// -<<<<<<< HEAD /// The cache is global across the whole query, so only a function that is stable inside a query /// may be shared. A function that is not deterministic in the scope of a query (`getSetting`, /// `getSettingOrDefault`, `blockNumber`, `rowNumberInAllBlocks`, ...) must NOT be shared: its @@ -2776,18 +2775,12 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi /// `randConstant(), randConstant()` shares. What separates two calls is their arguments, which /// the hash still covers: `randConstant(1)` and `randConstant(2)` keep their own values, and that /// is the documented way to ask for two different constants in one query. - if (function && !function->isDeterministic() && !function->isStateful() - && function->isDeterministicInScopeOfQuery()) -======= - /// `getSetting` and `rowNumberInAllBlocks` are non-deterministic but must NOT be shared: the cache - /// is global across scopes, and e.g. `SETTINGS` can change `getSetting`'s result for every scope. /// /// Server constants (`hostName`, `serverUUID`, ...) capture `Context::isDistributed` when built. /// A local `UNION` branch and a later cluster branch must not share that instance. - if (function && !function->isDeterministic() - && !function->isServerConstant() - && function_name != "getSetting" && function_name != "rowNumberInAllBlocks") ->>>>>>> f61f42a5fc6 (Merge pull request #2471 from Altinity/bugfix/antalya-26.6/fix-union-hostname-server-constant) + if (function && !function->isDeterministic() && !function->isStateful() + && function->isDeterministicInScopeOfQuery() + && !function->isServerConstant()) { auto hash = function_node_ptr->getTreeHash({ .compare_aliases = false }); function_base_cache = &functions_cache[hash];