Skip to content

26.1 Antalya port - Alternative syntax for cluster functions#1390

Open
ianton-ru wants to merge 41 commits intoantalya-26.1from
frontport/antalya-26.1/alternative_syntax
Open

26.1 Antalya port - Alternative syntax for cluster functions#1390
ianton-ru wants to merge 41 commits intoantalya-26.1from
frontport/antalya-26.1/alternative_syntax

Conversation

@ianton-ru
Copy link

@ianton-ru ianton-ru commented Feb 11, 2026

Changelog category (leave one):

  • New Feature

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

Frontports for Antalya 26.1

CI/CD Options

Exclude tests:

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

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • Tiered Storage (2h)

@github-actions
Copy link

github-actions bot commented Feb 11, 2026

Workflow [PR], commit [1be630c]

@ianton-ru
Copy link
Author

@codex review

Copy link

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

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: f5b1756a56

ℹ️ 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".

auto arguments = make_intrusive<ASTExpressionList>();

arguments->children.push_back(make_intrusive<ASTLiteral>(connection_params.endpoint.storage_account_url));
arguments->children.push_back(make_intrusive<ASTIdentifier>(connection_params.endpoint.container_name));

Choose a reason for hiding this comment

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

P1 Badge Emit Azure container argument as a string literal

When StorageObjectStorageCluster rewrites Azure table-engine reads into table-function calls (for object_storage_cluster/cluster-mode execution), this argument builder emits the container as ASTIdentifier instead of ASTLiteral. Azure table-function parsing expects a literal container name, so distributed reads can fail with argument/identifier errors on remote nodes. This should serialize container_name as a literal string to keep rewritten queries valid.

Useful? React with 👍 / 👎.


updateBeforeRead(context);
auto cluster = getCluster(context);
auto cluster = getClusterImpl(context, cluster_name_from_settings, context->getSettingsRef()[Setting::object_storage_max_nodes]);

Choose a reason for hiding this comment

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

P2 Badge Limit host capping to object-storage cluster engines only

This unconditionally applies object_storage_max_nodes in base IStorageCluster::read, so non-object-storage engines that also inherit IStorageCluster (notably StorageURLCluster and StorageFileCluster) will also have shards silently dropped when the setting is non-zero. That can return partial query results for urlCluster/fileCluster even though the setting is documented for object-storage cluster functions.

Useful? React with 👍 / 👎.

Comment on lines +445 to +449
auto p = function_to_cluster_function.find(table_function->name);
if (p == function_to_cluster_function.end())
{
throw Exception(
ErrorCodes::LOGICAL_ERROR,

Choose a reason for hiding this comment

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

P2 Badge Handle deltaLakeLocal in cluster-function rewrite

In cluster mode for table engines, DeltaLakeLocal is rewritten to table function deltaLakeLocal, but this conversion path only maps functions that have *Cluster equivalents and then throws LOGICAL_ERROR when none is found. As a result, reads of ENGINE=DeltaLakeLocal with non-empty object_storage_cluster fail with an internal error instead of a supported path or a proper user-facing validation error.

Useful? React with 👍 / 👎.

@ianton-ru ianton-ru added antalya antalya-26.1 port-antalya PRs to be ported to all new Antalya releases labels Feb 13, 2026
@ianton-ru
Copy link
Author

@codex review

Copy link

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

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: 6048e5d947

ℹ️ 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".


#if USE_AVRO
using TableFunctionIcebergCluster = TableFunctionObjectStorageCluster<IcebergClusterDefinition, StorageIcebergConfiguration, true>;
using TableFunctionIcebergLocalCluster = TableFunctionObjectStorageCluster<IcebergLocalClusterDefinition, StorageLocalIcebergConfiguration, true>;

Choose a reason for hiding this comment

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

P1 Badge Remove duplicate IcebergLocal cluster type alias

This header now declares TableFunctionIcebergLocalCluster twice under the same #if USE_AVRO guard, which creates a redefinition in AVRO-enabled builds and breaks compilation of the table-function targets. Keeping a single alias declaration avoids a hard build failure for Iceberg-capable configurations.

Useful? React with 👍 / 👎.

Comment on lines +331 to +333
auto p = engine_to_function.find(storage_engine_name);
if (p == engine_to_function.end())
{

Choose a reason for hiding this comment

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

P2 Badge Add S3-alias mappings before throwing on engine rewrite

This lookup throws when storage_engine_name is not in engine_to_function, but the rewrite path is also used for GCS, COSN, and OSS engines (their storage engine names are defined separately in StorageObjectStorageDefinitions.h). With object_storage_cluster enabled, queries against those engines now fail with LOGICAL_ERROR instead of executing, so these aliases need explicit mapping or a fallback in this conversion step.

Useful? React with 👍 / 👎.

{
chassert(result.count == 0); /// We shouldn't use replacement with masking other arguments
result.start = url_arg_idx;
result.start = function->arguments->getRealIndex(url_arg_idx);

Choose a reason for hiding this comment

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

P2 Badge Align SAS masking index with skipped-argument offsets

After introducing skipped arguments (used for iceberg(..., storage_type=...)), Azure secret masking must always map back to original argument positions; this branch was updated for AccountKey, but the SharedAccessSignature branch below still writes a relative index. In queries like iceberg(storage_type='azure', '...SharedAccessSignature=...'), that mismatch masks the wrong argument and can leave the SAS token unredacted.

Useful? React with 👍 / 👎.

@ianton-ru
Copy link
Author

@codex review

Copy link

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

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: f3c7d36056

ℹ️ 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 +420 to +423
auto args_copy = args;
// Remove cluster name from args to avoid confusing cluster name and named collection name
args_copy.erase(args_copy.begin());
configuration->extractDynamicStorageType(args_copy, context, &object_storage_type_arg);

Choose a reason for hiding this comment

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

P1 Badge Extract dynamic storage_type from live args

For old *Cluster syntax (for example icebergCluster(..., storage_type='azure')), this code extracts storage_type from args_copy instead of args, so the original argument remains in args and then gets appended again via object_storage_type_arg later in updateQueryToSendIfNeeded. The forwarded query can end up with two storage_type key-value arguments, and worker-side parsing rejects it with the duplicate-parameter error, which breaks distributed reads that use explicit storage_type.

Useful? React with 👍 / 👎.

assert int(hosts_engine_distributed) == 3


def test_distributed_s3_table_engine(started_cluster):

Choose a reason for hiding this comment

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

P3 Badge Remove duplicate test_distributed_s3_table_engine

This module defines test_distributed_s3_table_engine twice; in Python the later definition overwrites the earlier one at import time, so one full test body is never executed. That silently drops intended coverage and can hide regressions in this path while CI still reports green.

Useful? React with 👍 / 👎.

@ianton-ru
Copy link
Author

@codex review

Copy link

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

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: 8ffa292f43

ℹ️ 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".

#endif

#if USE_AVRO
using TableFunctionIcebergCluster = TableFunctionObjectStorageCluster<IcebergClusterDefinition, StorageIcebergConfiguration, true>;

Choose a reason for hiding this comment

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

P1 Badge Route icebergCluster masking through storage_type-aware logic

TableFunctionIcebergCluster now uses StorageIcebergConfiguration, so icebergCluster(..., storage_type='azure', ...) can carry Azure secrets, but FunctionSecretArgumentsFinder::findOrdinaryFunctionSecretArguments still classifies icebergCluster under the S3 branch (findS3FunctionSecretArguments(true)) rather than the new Iceberg storage-type-aware masking path. In cluster queries this can leave account_key/connection-string secrets visible in query text and system.query_log (while masking the wrong positional argument), so the cluster Iceberg variant needs the same storage-type dispatch that was added for iceberg.

Useful? React with 👍 / 👎.

@ianton-ru
Copy link
Author

ianton-ru commented Feb 23, 2026

Stateless tests and integration tests are killed by timeout.

@zvonand
Copy link
Collaborator

zvonand commented Mar 4, 2026

test_export_merge_tree_part_to_object_storage is failing. @arthurpassos this looks like it is coming from your code, but I do not recall seeing those in you PRs actually. @ianton-ru maybe you resolved conflicts in a wrong way?

@zvonand
Copy link
Collaborator

zvonand commented Mar 5, 2026

  • test_export_merge_tree_part_to_object_storage, test_export_replicated_mt_partition_to_object_storage still fails (suspicious)
  • test_storage_iceberg_with_spark -- I do no recall it failing before (link)

@ianton-ru
Copy link
Author

@arthurpassos Arthur, could you check test_storage_iceberg_with_spark/test_system_iceberg_metadata.py::test_system_tables_partition_sorting_keys[s3] test?
I guess it related to #1473. And with "warmup" table info with reading result is different, "","id, torelativehournum(ts)" instead of "bucket(16, id), day(ts)","id desc, hour(ts) asc"

@ianton-ru
Copy link
Author

test_export_replicated_mt_partition_to_object_storage/test.py::test_drop_source_table_during_export failed on request timeout to S3 storage. Minio is down?

@arthurpassos
Copy link
Collaborator

test_export_replicated_mt_partition_to_object_storage/test.py::test_drop_source_table_during_export failed on request timeout to S3 storage. Minio is down?

I am looking at this one first. I also see MinIO is not responding. This test blocks the traffict to MinIO for some time in order to perform some operations on tables while exports are active, so it might be related to the IP table rules that were set. Weirdly enough, it is the same test code that was not failing in25.8. Plus, @CarlosFelipeOR mentioned it is only ASAN, which makes it super weird.

I connected to the ClickHouse instance while the test was stuck, and the instance seems to be fine, but it can't reach S3. Investigating.

@ianton-ru
Copy link
Author

test_export_merge_tree_part_to_object_storage tests also failed because of MinIO timeouts.
Query executes 20+ minutes with timeout in 10 minutes, lot of

AWSClient: Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql: Poco::Exception. Code: 1000, e.code() = 0, Timeout: connect timed out: 172.16.2.5:9001

@arthurpassos
Copy link
Collaborator

test_export_merge_tree_part_to_object_storage tests also failed because of MinIO timeouts. Query executes 20+ minutes with timeout in 10 minutes, lot of

AWSClient: Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql: Poco::Exception. Code: 1000, e.code() = 0, Timeout: connect timed out: 172.16.2.5:9001

Aha, I think I found it. It seems to be trying to make a request to MinIO on an operation to a merge tree table, which does not make sense. MergeTree tables are local.

Look at the table name, it has mt, short for merge tree. This was triggered during a drop column operation.

Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql

The test suite has db disk in the name, and perhaps that means it is using a remote disk for merge tree tables, which break once MinIO requests are blocked via IP tables.

@arthurpassos
Copy link
Collaborator

@arthurpassos Arthur, could you check test_storage_iceberg_with_spark/test_system_iceberg_metadata.py::test_system_tables_partition_sorting_keys[s3] test? I guess it related to #1473. And with "warmup" table info with reading result is different, "","id, torelativehournum(ts)" instead of "bucket(16, id), day(ts)","id desc, hour(ts) asc"

But wasn't @zvonand who looked into this issue? I have no context or whatsoever in Iceberg metadata partition keys

@arthurpassos
Copy link
Collaborator

test_export_merge_tree_part_to_object_storage tests also failed because of MinIO timeouts. Query executes 20+ minutes with timeout in 10 minutes, lot of

AWSClient: Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql: Poco::Exception. Code: 1000, e.code() = 0, Timeout: connect timed out: 172.16.2.5:9001

Aha, I think I found it. It seems to be trying to make a request to MinIO on an operation to a merge tree table, which does not make sense. MergeTree tables are local.

Look at the table name, it has mt, short for merge tree. This was triggered during a drop column operation.

Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql

The test suite has db disk in the name, and perhaps that means it is using a remote disk for merge tree tables, which break once MinIO requests are blocked via IP tables.

I will create a PR that skips the tests that block MinIO access for the suite that has remote metadata for MergeTree tables

@arthurpassos
Copy link
Collaborator

test_export_merge_tree_part_to_object_storage tests also failed because of MinIO timeouts. Query executes 20+ minutes with timeout in 10 minutes, lot of

AWSClient: Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql: Poco::Exception. Code: 1000, e.code() = 0, Timeout: connect timed out: 172.16.2.5:9001

Aha, I think I found it. It seems to be trying to make a request to MinIO on an operation to a merge tree table, which does not make sense. MergeTree tables are local.
Look at the table name, it has mt, short for merge tree. This was triggered during a drop column operation.
Failed to make request to: http://minio1:9001/root-db-disk/test-default%7Cnode1/yxnenopepqpulrfwhippqhadacucuddt/mutations_snapshot_mt_table.sql
The test suite has db disk in the name, and perhaps that means it is using a remote disk for merge tree tables, which break once MinIO requests are blocked via IP tables.

I will create a PR that skips the tests that block MinIO access for the suite that has remote metadata for MergeTree tables

#1478

@ianton-ru
Copy link
Author

@arthurpassos Arthur, could you check test_storage_iceberg_with_spark/test_system_iceberg_metadata.py::test_system_tables_partition_sorting_keys[s3] test? I guess it related to #1473. And with "warmup" table info with reading result is different, "","id, torelativehournum(ts)" instead of "bucket(16, id), day(ts)","id desc, hour(ts) asc"

But wasn't @zvonand who looked into this issue? I have no context or whatsoever in Iceberg metadata partition keys

Ah, sorry, I thought it related to partition export.
I'll look

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

Labels

antalya antalya-26.1 port-antalya PRs to be ported to all new Antalya releases

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(not present in released builds) Segfault in ClusterDiscovery::getNodeNames (null ZooKeeper dereference) in PR #1414/#1390

4 participants