1) Support CLONE AS with ReplicatedMergeTree

2) Support CLONE AS with specifying ENGINE
This commit is contained in:
Tuan Pham Anh 2024-09-10 07:55:21 +00:00
parent 841dc275bd
commit 0b7f28f75b
3 changed files with 80 additions and 26 deletions

View File

@ -9,6 +9,7 @@
#include <Interpreters/InterpreterAlterQuery.h>
#include <Parsers/ASTPartition.h>
#include <Parsers/ASTSetQuery.h>
#include <Parsers/queryToString.h>
#include <Common/Exception.h>
#include <Common/Macros.h>
#include <Common/PoolId.h>
@ -811,10 +812,7 @@ InterpreterCreateQuery::TableProperties InterpreterCreateQuery::getTableProperti
/// as_storage->getColumns() and setEngine(...) must be called under structure lock of other_table for CREATE ... AS other_table.
as_storage_lock = as_storage->lockForShare(getContext()->getCurrentQueryId(), getContext()->getSettingsRef().lock_acquire_timeout);
if (create.is_clone_as && !endsWith(as_storage->getName(), "MergeTree"))
{
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "Only support CLONE AS with tables of the MergeTree family");
}
auto as_storage_metadata = as_storage->getInMemoryMetadataPtr();
properties.columns = as_storage_metadata->getColumns();
@ -836,6 +834,43 @@ InterpreterCreateQuery::TableProperties InterpreterCreateQuery::getTableProperti
}
properties.constraints = as_storage_metadata->getConstraints();
if (create.is_clone_as)
{
if (!endsWith(as_storage->getName(), "MergeTree"))
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "Only support CLONE AS from tables of the MergeTree family");
if (create.storage)
{
if (!endsWith(create.storage->engine->name, "MergeTree"))
throw Exception(ErrorCodes::SUPPORT_IS_DISABLED, "Only support CLONE AS with tables of the MergeTree family");
/// Ensure that as_storage and the new storage has the same primary key, sorting key and partition key
auto query_to_string = [](const IAST * ast) { return ast ? queryToString(*ast) : ""; };
const String as_storage_sorting_key_str = query_to_string(as_storage_metadata->getSortingKeyAST().get());
const String as_storage_primary_key_str = query_to_string(as_storage_metadata->getPrimaryKeyAST().get());
const String as_storage_partition_key_str = query_to_string(as_storage_metadata->getPartitionKeyAST().get());
const String storage_sorting_key_str = query_to_string(create.storage->order_by);
const String storage_primary_key_str = query_to_string(create.storage->primary_key);
const String storage_partition_key_str = query_to_string(create.storage->partition_by);
if (as_storage_sorting_key_str != storage_sorting_key_str)
{
/// It is possible that the storage only has primary key and an empty sorting key, and as_storage has both primary key and sorting key with the same value.
if (as_storage_sorting_key_str != as_storage_primary_key_str || as_storage_sorting_key_str != storage_primary_key_str)
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different ordering");
}
}
if (as_storage_partition_key_str != storage_partition_key_str)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different partition key");
if (as_storage_primary_key_str != storage_primary_key_str)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Tables have different primary key");
}
}
}
else if (create.select)
{
@ -1139,10 +1174,6 @@ void InterpreterCreateQuery::setEngine(ASTCreateQuery & create) const
if (create.storage)
{
/// When creating a table with CLONE AS, the structure of the new table must be copied from the source table's structure. So that the data could be cloned later.
if (create.is_clone_as)
throw Exception(ErrorCodes::INCORRECT_QUERY, "Cannot specify ENGINE when creating a table with CLONE AS");
/// This table already has a storage definition.
if (!create.storage->engine)
{
@ -1515,11 +1546,6 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create)
throw Exception(
ErrorCodes::SUPPORT_IS_DISABLED,
"CREATE CLONE AS is not supported with Replicated databases. Consider using separate CREATE and INSERT queries.");
if (is_storage_replicated)
throw Exception(
ErrorCodes::SUPPORT_IS_DISABLED,
"CREATE CLONE AS is not supported with Replicated storages. Consider using separate CREATE and INSERT queries.");
}
if (database && database->shouldReplicateQuery(getContext(), query_ptr))

View File

@ -10,6 +10,9 @@ from foo_merge_tree
from clone_as_foo_merge_tree
1 a
2 b
from clone_as_foo_merge_tree_p_x
1 a
2 b
CREATE TABLE default.foo_replacing_merge_tree\n(\n `x` Int8,\n `y` String\n)\nENGINE = ReplacingMergeTree\nPRIMARY KEY x\nORDER BY x\nSETTINGS index_granularity = 8192
1 a
2 b
@ -20,7 +23,15 @@ from foo_replacing_merge_tree
from clone_as_foo_replacing_merge_tree
1 a
2 b
from clone_as_foo_replacing_merge_tree_p_x
1 a
2 b
CREATE TABLE default.foo_replicated_merge_tree\n(\n `x` Int8,\n `y` String\n)\nENGINE = ReplicatedMergeTree(\'/clickhouse/tables/default/test_foo_replicated_merge_tree\', \'r1\')\nPRIMARY KEY x\nORDER BY x\nSETTINGS index_granularity = 8192
from foo_replicated_merge_tree
1 a
2 b
CREATE TABLE default.clone_as_foo_replicated_merge_tree_p_x\n(\n `x` Int8,\n `y` String\n)\nENGINE = ReplicatedMergeTree(\'/clickhouse/tables/default/clone_as_foo_replicated_merge_tree_p_x\', \'r1\')\nPRIMARY KEY x\nORDER BY x\nSETTINGS index_granularity = 8192
from clone_as_foo_replicated_merge_tree_p_x
1 a
2 b
s1 r1 OK 0 0

View File

@ -7,14 +7,16 @@ DROP TABLE IF EXISTS foo_file;
DROP TABLE IF EXISTS clone_as_foo_file;
DROP TABLE IF EXISTS foo_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_x;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_y;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_p_y;
DROP TABLE IF EXISTS foo_replacing_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_x;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_y;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_p_y;
DROP TABLE IF EXISTS foo_replicated_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree_p_y;
-- CLONE AS with a table of Memory engine
CREATE TABLE foo_memory (x Int8, y String) ENGINE=Memory;
@ -44,8 +46,10 @@ SELECT 'from clone_as_foo_merge_tree';
SELECT * FROM clone_as_foo_merge_tree;
-- Specify ENGINE
CREATE TABLE clone_as_foo_merge_tree_p_x CLONE AS foo_merge_tree ENGINE=MergeTree PRIMARY KEY x; -- { serverError INCORRECT_QUERY }
CREATE TABLE clone_as_foo_merge_tree_p_y CLONE AS foo_merge_tree ENGINE=MergeTree PRIMARY KEY y; -- { serverError INCORRECT_QUERY }
CREATE TABLE clone_as_foo_merge_tree_p_x CLONE AS foo_merge_tree ENGINE=MergeTree PRIMARY KEY x;
SELECT 'from clone_as_foo_merge_tree_p_x';
SELECT * FROM clone_as_foo_merge_tree_p_x;
CREATE TABLE clone_as_foo_merge_tree_p_y CLONE AS foo_merge_tree ENGINE=MergeTree PRIMARY KEY y; -- { serverError BAD_ARGUMENTS }
-- CLONE AS with a table of ReplacingMergeTree engine
CREATE TABLE foo_replacing_merge_tree (x Int8, y String) ENGINE=ReplacingMergeTree PRIMARY KEY x;
@ -61,15 +65,26 @@ SELECT 'from clone_as_foo_replacing_merge_tree';
SELECT * FROM clone_as_foo_replacing_merge_tree;
-- Specify ENGINE
CREATE TABLE clone_as_foo_replacing_merge_tree_x CLONE AS foo_replacing_merge_tree ENGINE=ReplacingMergeTree PRIMARY KEY x; -- { serverError INCORRECT_QUERY }
CREATE TABLE clone_as_foo_replacing_merge_tree_y CLONE AS foo_replacing_merge_tree ENGINE=ReplacingMergeTree PRIMARY KEY y; -- { serverError INCORRECT_QUERY }
CREATE TABLE clone_as_foo_replacing_merge_tree_p_x CLONE AS foo_replacing_merge_tree ENGINE=ReplacingMergeTree PRIMARY KEY x;
SELECT 'from clone_as_foo_replacing_merge_tree_p_x';
SELECT * FROM clone_as_foo_replacing_merge_tree_p_x;
CREATE TABLE clone_as_foo_replacing_merge_tree_p_y CLONE AS foo_replacing_merge_tree ENGINE=ReplacingMergeTree PRIMARY KEY y; -- { serverError BAD_ARGUMENTS }
-- CLONE AS with a table of ReplicatedMergeTree engine
CREATE TABLE foo_replicated_merge_tree (x Int8, y String) ENGINE=ReplicatedMergeTree('/clickhouse/tables/{database}/test_foo_replicated_merge_tree', 'r1') PRIMARY KEY x;
SHOW CREATE TABLE foo_replicated_merge_tree;
INSERT INTO foo_replicated_merge_tree VALUES (1, 'a'), (2, 'b');
SELECT 'from foo_replicated_merge_tree';
SELECT * FROM foo_replicated_merge_tree;
CREATE TABLE clone_as_foo_replicated_merge_tree CLONE AS foo_replicated_merge_tree; -- { serverError SUPPORT_IS_DISABLED }
CREATE TABLE clone_as_foo_replicated_merge_tree CLONE AS foo_replicated_merge_tree; -- { serverError REPLICA_ALREADY_EXISTS }
-- Specify ENGINE
CREATE TABLE clone_as_foo_replicated_merge_tree_p_x CLONE AS foo_replicated_merge_tree ENGINE=ReplicatedMergeTree('/clickhouse/tables/{database}/clone_as_foo_replicated_merge_tree_p_x', 'r1') PRIMARY KEY x;
SHOW CREATE TABLE clone_as_foo_replicated_merge_tree_p_x;
SELECT 'from clone_as_foo_replicated_merge_tree_p_x';
SELECT * FROM foo_replicated_merge_tree;
CREATE TABLE clone_as_foo_replicated_merge_tree_p_y CLONE AS foo_replicated_merge_tree ENGINE=ReplicatedMergeTree('/clickhouse/tables/{database}/clone_as_foo_replicated_merge_tree_p_y', 'r1') PRIMARY KEY y; -- { serverError BAD_ARGUMENTS }
DROP TABLE IF EXISTS foo_memory;
DROP TABLE IF EXISTS clone_as_foo_memory;
@ -77,14 +92,16 @@ DROP TABLE IF EXISTS foo_file;
DROP TABLE IF EXISTS clone_as_foo_file;
DROP TABLE IF EXISTS foo_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_x;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_y;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_merge_tree_p_y;
DROP TABLE IF EXISTS foo_replacing_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_x;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_y;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_replacing_merge_tree_p_y;
DROP TABLE IF EXISTS foo_replicated_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree_p_x;
DROP TABLE IF EXISTS clone_as_foo_replicated_merge_tree_p_y;
-- CLONE AS with a Replicated database
DROP DATABASE IF EXISTS {CLICKHOUSE_DATABASE_1:Identifier};