Fix crash when GLOBAL IN set lacks explicit elements during DIA#101178
Conversation
…ed index analysis When distributed index analysis (DIA) encounters a GLOBAL IN predicate whose set has been built without explicit elements (e.g. because use_index_for_in_with_subqueries_max_values was exceeded during buildOrderedSetInplace), setExternalTable() would crash with: "Trying to attach external table to a ready set without explicit elements" This happened in stress tests where the AST fuzzer could produce queries with GLOBAL IN on tables with DIA enabled, and the set had too many elements to retain explicit values (only hashes remained). The fix adds a check in tryBuildAdditionalFilterAST(): if the set is already built without explicit elements, the GLOBAL IN predicate is skipped from the distributed filter. DIA still functions correctly — it just won't use this predicate for remote index analysis, which is a slight optimization loss but maintains correctness. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-PR Validation Gate (Session cron:clickhouse-ci-task-worker:20260330-081500)a) Deterministic repro? ✅ Yes — the following crashes the server every time without the fix: CREATE TABLE t (key Int32, value Int32) ENGINE = MergeTree() ORDER BY key
SETTINGS distributed_index_analysis_min_parts_to_activate = 0, distributed_index_analysis_min_indexes_bytes_to_activate = 0;
INSERT INTO t SELECT number, number * 10 FROM numbers(10000) SETTINGS max_block_size = 1000, min_insert_block_size_rows = 1000, max_insert_threads = 1;
SELECT sum(key) FROM t WHERE key GLOBAL IN (SELECT key FROM t WHERE key > 5000)
SETTINGS distributed_index_analysis_for_non_shared_merge_tree = 1, enable_parallel_replicas = 0,
distributed_index_analysis = 1, distributed_index_analysis_only_on_coordinator = 1,
cluster_for_parallel_replicas = 'test_cluster_one_shard_two_replicas',
use_index_for_in_with_subqueries_max_values = 1;b) Root cause explained? ✅ c) Fix matches root cause? ✅ Yes — the fix adds a check in d) Test intent preserved? / New tests added? ✅ New regression test e) Both directions demonstrated? ✅ Without fix: server crashes with |
|
cc @nickitat @KochetovNicolai — could you review this? It fixes a LOGICAL_ERROR crash in |
|
Workflow [PR], commit [a1798fe] Summary: ❌
AI ReviewSummaryThis PR prevents a ClickHouse Rules
Final Verdict
|
|
@groeneai investigate all failed tests |
|
@nickitat I investigated all 5 failing tests. None are caused by this PR — all are pre-existing trunk issues appearing across many unrelated PRs:
Details:
All data from CIDB ( |
|
The Stress test (arm_msan) failure is fixed by #101239, which should be merged first. After it is merged, please update the branch to include the fix. |
|
Done — merged latest master (includes the SimSIMD SVE MSan fix from #101239) into the branch. CI should re-run with the fix included. |
|
The MSan stress test failure (MemorySanitizer: use-of-uninitialized-value, STID 4179-5154 or 4148-3044) is a known pre-existing issue unrelated to this PR. Fix: #102158 |
|
The |
LLVM Coverage Report
Changed lines: 100.00% (9/9) · Uncovered code |
48e9a55
|
Hi @groeneai @nickitat — the changelog category needs updating. Current: Why: This fixes a LOGICAL_ERROR exception (PreparedSets.cpp:261). Per ClickHouse guidelines, LOGICAL_ERROR must use the critical category since it causes crashes in debug builds and is considered a code invariant violation. Could you update the category? Thanks! |
|
Hi — this PR may need backporting to Affected code: Why: The GLOBAL IN support in If this should be backported, consider adding |
… elements during DIA
… elements during DIA
… elements during DIA
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Fix server crash with "Trying to attach external table to a ready set without explicit elements" when distributed index analysis encounters a GLOBAL IN predicate whose set was built without explicit elements.
Documentation entry for user-facing changes
Summary
When distributed index analysis (DIA) encounters a
GLOBAL INpredicate whose set has been built without explicit elements (e.g. becauseuse_index_for_in_with_subqueries_max_valueswas exceeded duringbuildOrderedSetInplace()),setExternalTable()crashes with aLOGICAL_ERROR:This crash appeared in stress tests (STID: 4224-4913) — 5 hits across 5 distinct unrelated PRs in 30 days — where the AST fuzzer can produce queries combining
GLOBAL INon tables with DIA enabled whileuse_index_for_in_with_subqueries_max_valuescauses the set's explicit elements to be dropped (retaining only hashes).Root Cause
The crash path:
buildOrderedSetInplace()builds the IN subquery set, callingfillSetElements()firstuse_index_for_in_with_subqueries_max_valuesis exceeded →fill_set_elementsis reset tofalse, elements cleared — the set is created with only hashestryBuildAdditionalFilterAST()which finds theglobalInfunctionsetExternalTable()setExternalTable()assertshasExplicitSetElements()→ false → LOGICAL_ERROR crashFix
In
tryBuildAdditionalFilterAST(), before callingsetExternalTable(), check if the set is already built without explicit elements. If so, skip theGLOBAL INpredicate — the distributed filter will simply omit it. DIA still functions correctly (it just won't use this predicate for remote index analysis), maintaining correctness at a slight optimization cost.Test Plan
04071_global_in_dia_no_explicit_set_elements— reproduces the crash deterministically withGLOBAL IN+ DIA +use_index_for_in_with_subqueries_max_values = 1enable_parallel_replicas🤖 Generated with Claude Code