From 345136ddf71a254fbd3742845334540540cae986 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Thu, 13 Nov 2025 12:39:08 +0000 Subject: [PATCH 1/3] Merge pull request #89367 from ilejn/in_function_crash Crash in IN function where columns have different types and many columns are involved --- src/Interpreters/sortBlock.cpp | 3 + src/Storages/MergeTree/KeyCondition.cpp | 26 ++++++--- ...ion_different_types_many_columns.reference | 56 +++++++++++++++++++ ..._function_different_types_many_columns.sql | 18 ++++++ 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference create mode 100644 tests/queries/0_stateless/03635_in_function_different_types_many_columns.sql diff --git a/src/Interpreters/sortBlock.cpp b/src/Interpreters/sortBlock.cpp index 190df67076d2..e687ea0b7390 100644 --- a/src/Interpreters/sortBlock.cpp +++ b/src/Interpreters/sortBlock.cpp @@ -336,6 +336,9 @@ void checkSortedWithPermutation(const Block & block, const SortDescription & des void sortBlock(Block & block, const SortDescription & description, UInt64 limit) { IColumn::Permutation permutation; +#ifndef NDEBUG + block.checkNumberOfRows(); +#endif getBlockSortPermutationImpl(block, description, IColumn::PermutationSortStability::Unstable, limit, permutation); #ifndef NDEBUG diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index c7233a5e51c0..22a016b4cfd8 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -1384,6 +1384,9 @@ bool KeyCondition::tryPrepareSetIndex( Columns transformed_set_columns = set_columns; + IColumn::Filter filter(transformed_set_columns.front()->size(), 1); + bool filter_used = false; + for (size_t indexes_mapping_index = 0; indexes_mapping_index < indexes_mapping_size; ++indexes_mapping_index) { const auto & key_column_type = data_types[indexes_mapping_index]; @@ -1455,32 +1458,39 @@ bool KeyCondition::tryPrepareSetIndex( const NullMap & nullable_set_column_null_map = nullable_set_column_typed->getNullMapData(); size_t nullable_set_column_null_map_size = nullable_set_column_null_map.size(); - IColumn::Filter filter(nullable_set_column_null_map_size); - if (set_column_null_map) { for (size_t i = 0; i < nullable_set_column_null_map_size; ++i) { if (nullable_set_column_null_map_size < set_column_null_map->size()) - filter[i] = (*set_column_null_map)[i] || !nullable_set_column_null_map[i]; + filter[i] &= (*set_column_null_map)[i] || !nullable_set_column_null_map[i]; else - filter[i] = !nullable_set_column_null_map[i]; + filter[i] &= !nullable_set_column_null_map[i]; } - set_column = nullable_set_column_typed->filter(filter, 0); + set_column = nullable_set_column; } else { for (size_t i = 0; i < nullable_set_column_null_map_size; ++i) - filter[i] = !nullable_set_column_null_map[i]; + filter[i] &= !nullable_set_column_null_map[i]; - set_column = nullable_set_column_typed->getNestedColumn().filter(filter, 0); + set_column = nullable_set_column_typed->getNestedColumnPtr(); } + filter_used = true; transformed_set_columns[set_element_index] = std::move(set_column); } - set_columns = std::move(transformed_set_columns); + if (filter_used) + { + for (size_t set_element_index = 0; set_element_index < transformed_set_columns.size(); ++set_element_index) + set_columns[set_element_index] = transformed_set_columns[set_element_index]->filter(filter, 0); + } + else + { + set_columns = std::move(transformed_set_columns); + } out.set_index = std::make_shared(set_columns, std::move(indexes_mapping)); diff --git a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference new file mode 100644 index 000000000000..3b13a5c09a2d --- /dev/null +++ b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference @@ -0,0 +1,56 @@ +CreatingSets + Expression + Filter + ReadFromMergeTree + Indexes: + PrimaryKey + Keys: + id + value + Condition: ((id, value) in 5-element set) + Parts: 1/1 + Granules: 1/1 + Search Algorithm: generic exclusion search + Ranges: 1 +CreatingSets + Expression + Filter + ReadFromMergeTree + Indexes: + PrimaryKey + Keys: + id + value + Condition: ((id, value) in 0-element set) + Parts: 0/1 + Granules: 0/1 + Search Algorithm: generic exclusion search + Ranges: 0 +CreatingSets + Expression + Filter + ReadFromMergeTree + Indexes: + PrimaryKey + Keys: + id + value + Condition: ((id, value) in 5-element set) + Parts: 1/1 + Granules: 1/1 + Search Algorithm: generic exclusion search + Ranges: 1 +CreatingSets + Expression + Filter + ReadFromMergeTree + Indexes: + PrimaryKey + Keys: + id + value + Condition: ((id, value) in 0-element set) + Parts: 0/1 + Granules: 0/1 + Search Algorithm: generic exclusion search + Ranges: 0 diff --git a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.sql b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.sql new file mode 100644 index 000000000000..1be37f4054f0 --- /dev/null +++ b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.sql @@ -0,0 +1,18 @@ +-- Tags: no-parallel-replicas, no-random-merge-tree-settings +-- followup to 02882_primary_key_index_in_function_different_types + +DROP TABLE IF EXISTS test_table; +CREATE TABLE test_table +( + id UInt64, + value UInt64 +) ENGINE=MergeTree ORDER BY (id, value) SETTINGS index_granularity = 8192, index_granularity_bytes = '1Mi'; + +INSERT INTO test_table SELECT number, number FROM numbers(10); + +EXPLAIN indexes = 1, description=0 SELECT id FROM test_table WHERE (id, value) IN (SELECT '5', number FROM numbers(5)); +EXPLAIN indexes = 1, description=0 SELECT id FROM test_table WHERE (id, value) IN (SELECT 'not a number', number FROM numbers(5)); +EXPLAIN indexes = 1, description=0 SELECT id FROM test_table WHERE (id, value) IN (SELECT 42, 'not a number' UNION ALL SELECT 5, toString(number) FROM numbers(5)); +EXPLAIN indexes = 1, description=0 SELECT id FROM test_table WHERE (id, value) IN (SELECT '42', 'not a number' UNION ALL SELECT 'not a number', '42' FROM numbers(5)); + +DROP TABLE test_table; From 2340f8575d1f8c3cf8d802ee5a117ec95b32c0f7 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov <32552679+zvonand@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:02:36 +0200 Subject: [PATCH 2/3] fix stateless test for 25.3.14 Co-Authored-By: Claude Sonnet 4.6 --- ...ion_different_types_many_columns.reference | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference index 3b13a5c09a2d..5ea6be17baca 100644 --- a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference +++ b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference @@ -4,53 +4,41 @@ CreatingSets ReadFromMergeTree Indexes: PrimaryKey - Keys: - id + Keys: value - Condition: ((id, value) in 5-element set) + Condition: (value in 5-element set) Parts: 1/1 Granules: 1/1 - Search Algorithm: generic exclusion search - Ranges: 1 CreatingSets Expression Filter ReadFromMergeTree Indexes: PrimaryKey - Keys: - id + Keys: value - Condition: ((id, value) in 0-element set) + Condition: (value in 0-element set) Parts: 0/1 Granules: 0/1 - Search Algorithm: generic exclusion search - Ranges: 0 CreatingSets Expression Filter ReadFromMergeTree Indexes: PrimaryKey - Keys: - id + Keys: value - Condition: ((id, value) in 5-element set) + Condition: (value in 6-element set) Parts: 1/1 Granules: 1/1 - Search Algorithm: generic exclusion search - Ranges: 1 CreatingSets Expression Filter ReadFromMergeTree Indexes: PrimaryKey - Keys: - id + Keys: value - Condition: ((id, value) in 0-element set) + Condition: (value in 1-element set) Parts: 0/1 Granules: 0/1 - Search Algorithm: generic exclusion search - Ranges: 0 From 161a4db70ea065b81aba903f2a946093c15bceb4 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov <32552679+zvonand@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:24:57 +0200 Subject: [PATCH 3/3] Fix reference for 03635_in_function_different_types_many_columns Queries 3 and 4 had the set sizes recorded from a build without the KeyCondition fix (6 and 1). With the fix, rows that cannot be cast to the key column type are filtered out of every set column, so the sets hold 5 and 0 elements. --- .../03635_in_function_different_types_many_columns.reference | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference index 5ea6be17baca..1f8cec584b32 100644 --- a/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference +++ b/tests/queries/0_stateless/03635_in_function_different_types_many_columns.reference @@ -28,7 +28,7 @@ CreatingSets PrimaryKey Keys: value - Condition: (value in 6-element set) + Condition: (value in 5-element set) Parts: 1/1 Granules: 1/1 CreatingSets @@ -39,6 +39,6 @@ CreatingSets PrimaryKey Keys: value - Condition: (value in 1-element set) + Condition: (value in 0-element set) Parts: 0/1 Granules: 0/1