diff --git a/src/Planner/Planner.cpp b/src/Planner/Planner.cpp index f5be70fa40e1..d316651608f9 100644 --- a/src/Planner/Planner.cpp +++ b/src/Planner/Planner.cpp @@ -101,6 +101,7 @@ namespace DB { namespace Setting { + extern const SettingsMap additional_table_filters; extern const SettingsUInt64 aggregation_in_order_max_block_bytes; extern const SettingsUInt64 aggregation_memory_efficient_merge_threads; extern const SettingsUInt64 allow_experimental_parallel_reading_from_replicas; @@ -1571,6 +1572,26 @@ void Planner::buildPlanForQueryNode() } } + /// `additional_table_filters` keys are resolved against the initiator's session current database, + /// but on followers the rewritten `SELECT` uses fully qualified names and the follower's current + /// database is the initiator's user-default DB, so the filter match is unreliable. Rather than + /// patch the match (which differs case by case), disable the combination on the analyzer path. + /// Upstream `serialize_query_plan=1` is exempt because the initiator lowers the filter into an + /// explicit `FilterStep` and ships the serialized plan, but in 25.8 parallel-replicas followers + /// always receive the rewritten AST (see ReadFromParallelRemoteReplicasStep), so the setting + /// does not help here and the check applies unconditionally. + if (query_context->canUseParallelReplicasOnInitiator() + && !settings[Setting::additional_table_filters].value.empty()) + { + if (settings[Setting::allow_experimental_parallel_reading_from_replicas] >= 2) + throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, + "additional_table_filters is not supported with parallel replicas"); + + auto & mutable_context = planner_context->getMutableQueryContext(); + mutable_context->setSetting("allow_experimental_parallel_reading_from_replicas", Field(0)); + LOG_DEBUG(log, "Disabling parallel replicas to execute a query with additional_table_filters"); + } + collectTableExpressionData(query_tree, planner_context); checkStoragesSupportTransactions(planner_context); diff --git a/tests/queries/0_stateless/04207_pr_additional_filters.reference b/tests/queries/0_stateless/04207_pr_additional_filters.reference new file mode 100644 index 000000000000..a5c8806279fa --- /dev/null +++ b/tests/queries/0_stateless/04207_pr_additional_filters.reference @@ -0,0 +1,2 @@ +3 +3 diff --git a/tests/queries/0_stateless/04207_pr_additional_filters.sql b/tests/queries/0_stateless/04207_pr_additional_filters.sql new file mode 100644 index 000000000000..031665dbaf0f --- /dev/null +++ b/tests/queries/0_stateless/04207_pr_additional_filters.sql @@ -0,0 +1,63 @@ +-- Tags: no-parallel +-- ^ failpoint + +DROP TABLE IF EXISTS atf_p; +CREATE TABLE atf_p (x UInt64) ENGINE = MergeTree ORDER BY tuple(); +INSERT INTO atf_p SELECT number FROM numbers(10); + +-- The failpoint disables cancellation of unused replicas after all ranges +-- are assigned, so every replica's contribution lands on the initiator and any +-- missing-filter regression is deterministic regardless of timing. + +-- `additional_table_filters` keys are resolved against the initiator's session current +-- database, so they cannot be reliably matched on parallel-replica followers (the +-- rewritten query qualifies the table and the follower's current database differs). +-- On the legacy AST-forwarding path the analyzer rejects the combination instead of +-- silently dropping the filter. +SYSTEM ENABLE FAILPOINT parallel_replicas_wait_for_unused_replicas; +SELECT count() FROM atf_p SETTINGS additional_table_filters = {'atf_p': 'x <= 2'}, + enable_analyzer = 1, + enable_parallel_replicas = 2, + max_parallel_replicas = 3, + cluster_for_parallel_replicas = 'test_cluster_one_shard_three_replicas_localhost', + parallel_replicas_for_non_replicated_merge_tree = 1, + parallel_replicas_local_plan = 1, + serialize_query_plan = 0; -- { serverError SUPPORT_IS_DISABLED } + +SELECT count() FROM atf_p SETTINGS additional_table_filters = {'atf_p': 'x <= 2'}, + enable_analyzer = 0, + enable_parallel_replicas = 2, + max_parallel_replicas = 3, + cluster_for_parallel_replicas = 'test_cluster_one_shard_three_replicas_localhost', + parallel_replicas_for_non_replicated_merge_tree = 1, + parallel_replicas_local_plan = 1, + serialize_query_plan = 0; + +-- With `enable_parallel_replicas = 1` (best-effort) parallel replicas is silently +-- disabled and the query runs locally with the filter applied. +SYSTEM ENABLE FAILPOINT parallel_replicas_wait_for_unused_replicas; +SELECT count() FROM atf_p SETTINGS additional_table_filters = {'atf_p': 'x <= 2'}, + enable_analyzer = 1, + enable_parallel_replicas = 1, + max_parallel_replicas = 3, + cluster_for_parallel_replicas = 'test_cluster_one_shard_three_replicas_localhost', + parallel_replicas_for_non_replicated_merge_tree = 1, + parallel_replicas_local_plan = 1, + serialize_query_plan = 0; + +-- Upstream `serialize_query_plan = 1` makes the combination work (the initiator lowers the +-- additional filter into an explicit `FilterStep` and ships the serialized plan), but in 25.8 +-- parallel-replicas followers always receive the rewritten AST, so the setting does not help +-- and the combination is rejected as well. +SYSTEM ENABLE FAILPOINT parallel_replicas_wait_for_unused_replicas; +SELECT count() FROM atf_p SETTINGS additional_table_filters = {'atf_p': 'x <= 2'}, + enable_analyzer = 1, + enable_parallel_replicas = 2, + max_parallel_replicas = 3, + cluster_for_parallel_replicas = 'test_cluster_one_shard_three_replicas_localhost', + parallel_replicas_for_non_replicated_merge_tree = 1, + parallel_replicas_local_plan = 1, + serialize_query_plan = 1; -- { serverError SUPPORT_IS_DISABLED } + +SYSTEM DISABLE FAILPOINT parallel_replicas_wait_for_unused_replicas; +DROP TABLE atf_p;