From 134786afd525d7bac39a3dd097b2b0992d38f2e2 Mon Sep 17 00:00:00 2001 From: Amos Bird Date: Wed, 11 Nov 2020 22:34:58 +0800 Subject: [PATCH] Disable ATTACH/DETACH TABLE --- src/Interpreters/InterpreterCreateQuery.cpp | 4 +++ src/Interpreters/InterpreterDropQuery.cpp | 1 + src/Storages/IStorage.h | 2 ++ src/Storages/StorageDictionary.cpp | 5 ++++ src/Storages/StorageDictionary.h | 1 + ...sable_detach_table_of_dictionary.reference | 0 ...575_disable_detach_table_of_dictionary.sql | 26 +++++++++++++++++++ 7 files changed, 39 insertions(+) create mode 100644 tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.reference create mode 100644 tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.sql diff --git a/src/Interpreters/InterpreterCreateQuery.cpp b/src/Interpreters/InterpreterCreateQuery.cpp index 286d5269a64..8e6e6170f06 100644 --- a/src/Interpreters/InterpreterCreateQuery.cpp +++ b/src/Interpreters/InterpreterCreateQuery.cpp @@ -684,6 +684,10 @@ BlockIO InterpreterCreateQuery::createTable(ASTCreateQuery & create) // Table SQL definition is available even if the table is detached auto query = database->getCreateTableQuery(create.table, context); create = query->as(); // Copy the saved create query, but use ATTACH instead of CREATE + if (create.is_dictionary) + throw Exception( + "Cannot ATTACH TABLE " + backQuoteIfNeed(database_name) + "." + backQuoteIfNeed(create.table) + ", it is a Dictionary", + ErrorCodes::INCORRECT_QUERY); create.attach = true; create.attach_short_syntax = true; create.if_not_exists = if_not_exists; diff --git a/src/Interpreters/InterpreterDropQuery.cpp b/src/Interpreters/InterpreterDropQuery.cpp index 144e045ecee..5f7f70fdda4 100644 --- a/src/Interpreters/InterpreterDropQuery.cpp +++ b/src/Interpreters/InterpreterDropQuery.cpp @@ -119,6 +119,7 @@ BlockIO InterpreterDropQuery::executeToTableImpl(const ASTDropQuery & query, Dat if (query.kind == ASTDropQuery::Kind::Detach) { context.checkAccess(table->isView() ? AccessType::DROP_VIEW : AccessType::DROP_TABLE, table_id); + table->checkTableCanBeDetached(); table->shutdown(); TableExclusiveLockHolder table_lock; if (database->getEngineName() != "Atomic") diff --git a/src/Storages/IStorage.h b/src/Storages/IStorage.h index 5fa2a915978..7c27282e4f3 100644 --- a/src/Storages/IStorage.h +++ b/src/Storages/IStorage.h @@ -443,6 +443,8 @@ public: /// Otherwise - throws an exception with detailed information. /// We do not use mutex because it is not very important that the size could change during the operation. virtual void checkTableCanBeDropped() const {} + /// Similar to above but checks for DETACH. It's only used for DICTIONARIES. + virtual void checkTableCanBeDetached() const {} /// Checks that Partition could be dropped right now /// Otherwise - throws an exception with detailed information. diff --git a/src/Storages/StorageDictionary.cpp b/src/Storages/StorageDictionary.cpp index ee08dd5a824..70c3ce8094e 100644 --- a/src/Storages/StorageDictionary.cpp +++ b/src/Storages/StorageDictionary.cpp @@ -130,6 +130,11 @@ void StorageDictionary::checkTableCanBeDropped() const throw Exception("Cannot detach table " + getStorageID().getFullTableName() + " from a database with DICTIONARY engine", ErrorCodes::CANNOT_DETACH_DICTIONARY_AS_TABLE); } +void StorageDictionary::checkTableCanBeDetached() const +{ + checkTableCanBeDropped(); +} + Pipe StorageDictionary::read( const Names & column_names, const StorageMetadataPtr & /*metadata_snapshot*/, diff --git a/src/Storages/StorageDictionary.h b/src/Storages/StorageDictionary.h index 576cc2de064..589ff7d4654 100644 --- a/src/Storages/StorageDictionary.h +++ b/src/Storages/StorageDictionary.h @@ -15,6 +15,7 @@ public: std::string getName() const override { return "Dictionary"; } void checkTableCanBeDropped() const override; + void checkTableCanBeDetached() const override; Pipe read( const Names & column_names, diff --git a/tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.reference b/tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.sql b/tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.sql new file mode 100644 index 00000000000..44c0c149e3c --- /dev/null +++ b/tests/queries/0_stateless/01575_disable_detach_table_of_dictionary.sql @@ -0,0 +1,26 @@ +DROP DATABASE IF EXISTS database_for_dict; + +CREATE DATABASE database_for_dict; + +CREATE TABLE database_for_dict.table_for_dict (k UInt64, v UInt8) ENGINE = MergeTree ORDER BY k; + +DROP DICTIONARY IF EXISTS database_for_dict.dict1; + +CREATE DICTIONARY database_for_dict.dict1 (k UInt64 DEFAULT 0, v UInt8 DEFAULT 1) PRIMARY KEY k +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' TABLE 'table_for_dict' PASSWORD '' DB 'database_for_dict')) +LIFETIME(MIN 1 MAX 10) +LAYOUT(FLAT()); + +DETACH TABLE database_for_dict.dict1; -- { serverError 520 } + +DETACH DICTIONARY database_for_dict.dict1; + +ATTACH TABLE database_for_dict.dict1; -- { serverError 80 } + +ATTACH DICTIONARY database_for_dict.dict1; + +DROP DICTIONARY database_for_dict.dict1; + +DROP TABLE database_for_dict.table_for_dict; + +DROP DATABASE IF EXISTS database_for_dict;