Skip to content

Fix GROUP BY server constants over s3Cluster and object_storage_cluster - #2490

Open
ianton-ru wants to merge 4 commits into
antalya-26.6from
bugfix/antalya-26.6/2139-hostname-object-storage-cluster
Open

ianton-ru wants to merge 4 commits into
antalya-26.6from
bugfix/antalya-26.6/2139-hostname-object-storage-cluster

Conversation

@ianton-ru

@ianton-ru ianton-ru commented Oct 6, 2026 •

Copy link
Copy Markdown

Solved #2139

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 to CHANGELOG.md):

Fix GROUP BY server constants over s3Cluster and object_storage_cluster

Documentation entry for user-facing changes

...

CI/CD Options

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Unit tests
  • Performance tests
  • Aarch64 tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • CAS (content-addressed storage; Antalya only)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • OAuth (5m)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

ianton-ru and others added 2 commits October 6, 2026 13:31
The old analyzer drops constant GROUP BY keys when distributed_depth is 0. Cluster table function reads never increased that depth, so workers folded hostName() and returned only the aggregate.

https: //github.com//issues/2139
Co-authored-by: Cursor <cursoragent@cursor.com>
Raising distributed_depth on cluster reads also changes parallel replicas, max_distributed_depth, and block marshalling. The old analyzer now keeps a key such as hostName() and still drops ordinary constants.

https: //github.com//issues/2139
Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Workflow [PR], commit [26d3a68]

@ianton-ru

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T16:06:38.582813Z 26d3a68 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea70a1fdff

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Interpreters/ExpressionAnalyzer.cpp Outdated
Comment on lines +174 to +175
if (current->function_base && current->function_base->isServerConstant())
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude scalar-subquery accessors from server constants

When a scalar subquery is represented by __getScalar (notably for Array, Tuple, or aggregate-state results), its function base also reports isServerConstant, even though ExecuteScalarSubqueriesVisitor evaluates it on the initiator and ships the same scalar to every shard. This check therefore retains such constant GROUP BY keys instead of removing them as before; for example, with the old analyzer, grouping an aggregate query by a scalar subquery returning Tuple(Dynamic) now reaches group-key validation and throws ILLEGAL_COLUMN, whereas the constant key previously disappeared. Special-case shipped scalar accessors, or otherwise distinguish genuinely per-server functions from every function carrying this flag.

Useful? React with 👍 / 👎.

__getScalar is marked as a server constant, but the initiator evaluates it and sends the same value to every shard. Keeping it made GROUP BY of a scalar subquery with Dynamic throw ILLEGAL_COLUMN.

https: //github.com//pull/2490
Co-authored-by: Cursor <cursoragent@cursor.com>
@ianton-ru

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12460edf61

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +179 to +180
for (const auto * child : current->children)
stack.push(child);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Deduplicate DAG nodes during traversal

Because an ActionsDAG can share child nodes, this traversal can revisit the same subtree exponentially many times. For example, a linear sequence of aliases such as plus(x0, x0) AS x1, plus(x1, x1) AS x2, and so on produces a constant DAG where each level references the same child twice; checking the final alias explores roughly 2^N paths when no server constant exists, allowing a compact old-analyzer query to consume an analysis thread indefinitely. Track visited node pointers before pushing children.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The alias chain in this comment does not keep an analysis thread busy. containsServerConstant does not record visited nodes, and an ActionsDAG can store the same child twice, but this example never reaches that walk as a compact graph.

The old analyzer expands aliases in QueryNormalizer before aggregation analysis. The expanded tree is limited by max_expanded_ast_elements (default 500000). A chain 1 AS x0, x0 + x0 AS x1, … throws TOO_BIG_AST at depth 16. Depth 15 finishes in about 0.25s (enable_analyzer = 0). The same SELECT list with GROUP BY 1 takes about 0.15s, so the extra time is the expanded tree, not an unbounded walk of a shared DAG.

Measured on a local server:

Depth Result
8 0.009s
12 0.028s
14 0.120s
15 0.244s
16 TOO_BIG_AST

Comment thread src/Interpreters/ExpressionAnalyzer.cpp Outdated
/// Constant expressions have non-null column pointer at this stage.
if (node->column)
/// Server constants stay: they are different on each shard.
if (node->column && !containsServerConstant(node))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve server constants only when the query can fan out

For a local enable_analyzer=0 query, distributed_depth is also zero, so this predicate now retains server constants even though only one server can observe their value. For example, SELECT count() FROM numbers(3) GROUP BY [CAST(hostName(), 'Dynamic')] SETTINGS enable_analyzer = 0 previously removed the folded constant key, but now retains its Array(Dynamic) type and subsequently raises ILLEGAL_COLUMN under the default allow_suspicious_types_in_group_by = 0; the new analyzer still removes such keys when the context is not distributed. Limit this exception to queries that can actually dispatch work, including the affected cluster-backed table functions.

Useful? React with 👍 / 👎.

Comment thread src/Interpreters/ExpressionAnalyzer.cpp Outdated
return true;
}

/// A folded server constant (`hostName()`, `tcpPort()`, ...) must stay a GROUP BY key.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove call syntax from function-name examples

This comment refers to the functions themselves rather than describing particular applications, so the repository convention requires the names to be written as hostName and tcpPort, without parentheses.

AGENTS.md reference: AGENTS.md:L11-L11

Useful? React with 👍 / 👎.

@ianton-ru ianton-ru added antalya port-antalya PRs to be ported to all new Antalya releases antalya-26.6 labels Oct 8, 2026
A local query has one server, so a folded server constant is an ordinary constant. Keeping it made GROUP BY of `hostName` cast to `Dynamic` throw `ILLEGAL_COLUMN`. Secondary queries still keep the key, because cluster table function workers also have `distributed_depth` 0.

https: //github.com//pull/2490
Co-authored-by: Cursor <cursoragent@cursor.com>
@ianton-ru

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 26d3a68f3e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ianton-ru
ianton-ru marked this pull request as ready for review October 9, 2026 17:34

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

antalya antalya-26.6 bugfix port-antalya PRs to be ported to all new Antalya releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants