From ffabb47ed2a5bdb5f7d2cfee35250f770518efd2 Mon Sep 17 00:00:00 2001 From: Nikolai Kochetov Date: Thu, 13 Nov 2025 12:39:08 +0000 Subject: [PATCH 1/2] 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 | 4 ++ src/Storages/MergeTree/KeyCondition.cpp | 26 ++++++--- ...ion_different_types_many_columns.reference | 56 +++++++++++++++++++ ..._function_different_types_many_columns.sql | 18 ++++++ 4 files changed, 96 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 c5a0decf393f..026797f1c8fe 100644 --- a/src/Interpreters/sortBlock.cpp +++ b/src/Interpreters/sortBlock.cpp @@ -336,6 +336,10 @@ void checkSortedWithPermutation(const Block & block, const SortDescription & des void sortBlock(Block & block, const SortDescription & description, UInt64 limit, IColumn::PermutationSortStability stability) { IColumn::Permutation permutation; + +#ifndef NDEBUG + block.checkNumberOfRows(); +#endif getBlockSortPermutationImpl(block, description, stability, limit, permutation); #ifndef NDEBUG diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index d3d9f2b8dbcb..031ad1aae55b 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -1420,6 +1420,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]; @@ -1491,32 +1494,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 235d29d64ac4d972240558c3ec17be22b0bc77a5 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov Date: Tue, 16 Dec 2025 23:38:58 +0100 Subject: [PATCH 2/2] fix stateless test --- ...ion_different_types_many_columns.reference | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 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..86aad6d9dbb2 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 @@ -5,13 +5,12 @@ CreatingSets Indexes: PrimaryKey Keys: - id 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 + Ranges: 1 CreatingSets Expression Filter @@ -19,13 +18,12 @@ CreatingSets Indexes: PrimaryKey Keys: - id 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 + Ranges: 0 CreatingSets Expression Filter @@ -33,13 +31,12 @@ CreatingSets Indexes: PrimaryKey Keys: - id 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 + Ranges: 1 CreatingSets Expression Filter @@ -47,10 +44,9 @@ CreatingSets Indexes: PrimaryKey Keys: - id 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 + Ranges: 0