From c911c8daf4bd626315d6b67f35ed7ea0f6c476ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1nos=20Benjamin=20Antal?= Date: Wed, 27 Sep 2023 21:02:53 +0200 Subject: [PATCH] Prevent attaching parts from tables with different projections or indices (#55062) * Prevent attaching parts from tables with different projections or indices * Update docs * Add tests --- .../statements/alter/partition.md | 3 + src/Storages/MergeTree/MergeTreeData.cpp | 22 +++++ ..._partition_from_different_tables.reference | 11 +++ ...attach_partition_from_different_tables.sql | 90 +++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 tests/queries/0_stateless/02888_attach_partition_from_different_tables.reference create mode 100644 tests/queries/0_stateless/02888_attach_partition_from_different_tables.sql diff --git a/docs/en/sql-reference/statements/alter/partition.md b/docs/en/sql-reference/statements/alter/partition.md index a0aa74e6d25..114b8d5ffe3 100644 --- a/docs/en/sql-reference/statements/alter/partition.md +++ b/docs/en/sql-reference/statements/alter/partition.md @@ -113,6 +113,7 @@ For the query to run successfully, the following conditions must be met: - Both tables must have the same structure. - Both tables must have the same partition key, the same order by key and the same primary key. +- Both tables must have the same indices and projections. - Both tables must have the same storage policy. ## REPLACE PARTITION @@ -132,6 +133,7 @@ For the query to run successfully, the following conditions must be met: - Both tables must have the same structure. - Both tables must have the same partition key, the same order by key and the same primary key. +- Both tables must have the same indices and projections. - Both tables must have the same storage policy. ## MOVE PARTITION TO TABLE @@ -146,6 +148,7 @@ For the query to run successfully, the following conditions must be met: - Both tables must have the same structure. - Both tables must have the same partition key, the same order by key and the same primary key. +- Both tables must have the same indices and projections. - Both tables must have the same storage policy. - Both tables must be the same engine family (replicated or non-replicated). diff --git a/src/Storages/MergeTree/MergeTreeData.cpp b/src/Storages/MergeTree/MergeTreeData.cpp index 165d3dc331f..4a6a1e40ba8 100644 --- a/src/Storages/MergeTree/MergeTreeData.cpp +++ b/src/Storages/MergeTree/MergeTreeData.cpp @@ -7543,6 +7543,28 @@ MergeTreeData & MergeTreeData::checkStructureAndGetMergeTreeData(IStorage & sour if (query_to_string(my_snapshot->getPrimaryKeyAST()) != query_to_string(src_snapshot->getPrimaryKeyAST())) throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different primary key"); + const auto check_definitions = [](const auto & my_descriptions, const auto & src_descriptions) + { + if (my_descriptions.size() != src_descriptions.size()) + return false; + + std::unordered_set my_query_strings; + for (const auto & description : my_descriptions) + my_query_strings.insert(queryToString(description.definition_ast)); + + for (const auto & src_description : src_descriptions) + if (!my_query_strings.contains(queryToString(src_description.definition_ast))) + return false; + + return true; + }; + + if (!check_definitions(my_snapshot->getSecondaryIndices(), src_snapshot->getSecondaryIndices())) + throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different secondary indices"); + + if (!check_definitions(my_snapshot->getProjections(), src_snapshot->getProjections())) + throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different projections"); + return *src_data; } diff --git a/tests/queries/0_stateless/02888_attach_partition_from_different_tables.reference b/tests/queries/0_stateless/02888_attach_partition_from_different_tables.reference new file mode 100644 index 00000000000..3cc269ec01c --- /dev/null +++ b/tests/queries/0_stateless/02888_attach_partition_from_different_tables.reference @@ -0,0 +1,11 @@ +1 1 +0 0 +1 1 +2 2 +3 3 +4 4 +5 5 +6 6 +7 7 +8 8 +9 9 diff --git a/tests/queries/0_stateless/02888_attach_partition_from_different_tables.sql b/tests/queries/0_stateless/02888_attach_partition_from_different_tables.sql new file mode 100644 index 00000000000..98f841394e1 --- /dev/null +++ b/tests/queries/0_stateless/02888_attach_partition_from_different_tables.sql @@ -0,0 +1,90 @@ +-- test different index type +CREATE TABLE attach_partition_t1 ( + a UInt32, + b String, + INDEX bf b TYPE tokenbf_v1(8192, 3, 0) GRANULARITY 1 +) +ENGINE = MergeTree +ORDER BY a; + +INSERT INTO attach_partition_t1 SELECT number, toString(number) FROM numbers(10); + +CREATE TABLE attach_partition_t2 ( + a UInt32, + b String, + INDEX bf b TYPE bloom_filter GRANULARITY 1 +) +ENGINE = MergeTree +ORDER BY a; + +ALTER TABLE attach_partition_t2 ATTACH PARTITION tuple() FROM attach_partition_t1; -- { serverError 36 } + +-- test different projection name +CREATE TABLE attach_partition_t3 ( + a UInt32, + b String, + PROJECTION proj + ( + SELECT + b, + sum(a) + GROUP BY b + ) +) +ENGINE = MergeTree +ORDER BY a; + +INSERT INTO attach_partition_t3 SELECT number, toString(number) FROM numbers(10); + +CREATE TABLE attach_partition_t4 ( + a UInt32, + b String, + PROJECTION differently_named_proj + ( + SELECT + b, + sum(a) + GROUP BY b + ) +) +ENGINE = MergeTree +ORDER BY a; + +ALTER TABLE attach_partition_t4 ATTACH PARTITION tuple() FROM attach_partition_t3; -- { serverError 36 } + +-- check attach with same index and projection +CREATE TABLE attach_partition_t5 ( + a UInt32, + b String, + PROJECTION proj + ( + SELECT + b, + sum(a) + GROUP BY b + ) +) +ENGINE = MergeTree +ORDER BY a; + +INSERT INTO attach_partition_t5 SELECT number, toString(number) FROM numbers(10); + + +CREATE TABLE attach_partition_t6 ( + a UInt32, + b String, + PROJECTION proj + ( + SELECT + b, + sum(a) + GROUP BY b + ) +) +ENGINE = MergeTree +ORDER BY a; + +ALTER TABLE attach_partition_t6 ATTACH PARTITION tuple() FROM attach_partition_t5; + +SELECT * FROM attach_partition_t6 WHERE b = '1'; +SELECT b, sum(a) FROM attach_partition_t6 GROUP BY b ORDER BY b;