mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Handle not implemented cases properly
This commit is contained in:
parent
f6097cf818
commit
3f5e5eb15a
@ -30,6 +30,7 @@ namespace ErrorCodes
|
|||||||
extern const int SYNTAX_ERROR;
|
extern const int SYNTAX_ERROR;
|
||||||
extern const int UNKNOWN_TABLE;
|
extern const int UNKNOWN_TABLE;
|
||||||
extern const int UNKNOWN_DICTIONARY;
|
extern const int UNKNOWN_DICTIONARY;
|
||||||
|
extern const int NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +56,8 @@ BlockIO InterpreterDropQuery::execute()
|
|||||||
{
|
{
|
||||||
if (!drop.is_dictionary)
|
if (!drop.is_dictionary)
|
||||||
return executeToTable(drop);
|
return executeToTable(drop);
|
||||||
|
else if (drop.permanently && drop.kind == ASTDropQuery::Kind::Detach)
|
||||||
|
throw Exception("DETACH PERMANENTLY is not implemented for dictionaries", ErrorCodes::NOT_IMPLEMENTED);
|
||||||
else
|
else
|
||||||
return executeToDictionary(drop.database, drop.table, drop.kind, drop.if_exists, drop.temporary, drop.no_ddl_lock);
|
return executeToDictionary(drop.database, drop.table, drop.kind, drop.if_exists, drop.temporary, drop.no_ddl_lock);
|
||||||
}
|
}
|
||||||
@ -296,11 +299,15 @@ BlockIO InterpreterDropQuery::executeToDatabaseImpl(const ASTDropQuery & query,
|
|||||||
bool drop = query.kind == ASTDropQuery::Kind::Drop;
|
bool drop = query.kind == ASTDropQuery::Kind::Drop;
|
||||||
context.checkAccess(AccessType::DROP_DATABASE, database_name);
|
context.checkAccess(AccessType::DROP_DATABASE, database_name);
|
||||||
|
|
||||||
|
if (query.kind == ASTDropQuery::Kind::Detach && query.permanently)
|
||||||
|
throw Exception("DETACH PERMANENTLY is not implemented for databases", ErrorCodes::NOT_IMPLEMENTED);
|
||||||
|
|
||||||
#if USE_MYSQL
|
#if USE_MYSQL
|
||||||
if (database->getEngineName() == "MaterializeMySQL")
|
if (database->getEngineName() == "MaterializeMySQL")
|
||||||
stopDatabaseSynchronization(database);
|
stopDatabaseSynchronization(database);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (database->shouldBeEmptyOnDetach())
|
if (database->shouldBeEmptyOnDetach())
|
||||||
{
|
{
|
||||||
/// DETACH or DROP all tables and dictionaries inside database.
|
/// DETACH or DROP all tables and dictionaries inside database.
|
||||||
|
@ -11,7 +11,7 @@ namespace DB
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool optional_table_keyword = false)
|
bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, const ASTDropQuery::Kind kind)
|
||||||
{
|
{
|
||||||
ParserKeyword s_temporary("TEMPORARY");
|
ParserKeyword s_temporary("TEMPORARY");
|
||||||
ParserKeyword s_table("TABLE");
|
ParserKeyword s_table("TABLE");
|
||||||
@ -42,15 +42,6 @@ bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool
|
|||||||
|
|
||||||
if (!name_p.parse(pos, database, expected))
|
if (!name_p.parse(pos, database, expected))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
|
||||||
{
|
|
||||||
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_no_delay.ignore(pos, expected) || s_sync.ignore(pos, expected))
|
|
||||||
no_delay = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -61,7 +52,8 @@ bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool
|
|||||||
else if (s_temporary.ignore(pos, expected))
|
else if (s_temporary.ignore(pos, expected))
|
||||||
temporary = true;
|
temporary = true;
|
||||||
|
|
||||||
if (!is_view && !is_dictionary && (!s_table.ignore(pos, expected) && !optional_table_keyword))
|
/// for TRUNCATE queries TABLE keyword is assumed as default and can be skipped
|
||||||
|
if (!is_view && !is_dictionary && (!s_table.ignore(pos, expected) && kind == ASTDropQuery::Kind::Truncate))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -78,24 +70,26 @@ bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool
|
|||||||
if (!name_p.parse(pos, table, expected))
|
if (!name_p.parse(pos, table, expected))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
|
||||||
{
|
|
||||||
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_permanently.ignore(pos, expected))
|
|
||||||
permanently = true;
|
|
||||||
|
|
||||||
if (s_no_delay.ignore(pos, expected) || s_sync.ignore(pos, expected))
|
|
||||||
no_delay = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// common for tables / dictionaries / databases
|
||||||
|
if (ParserKeyword{"ON"}.ignore(pos, expected))
|
||||||
|
{
|
||||||
|
if (!ASTQueryWithOnCluster::parse(pos, cluster_str, expected))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kind == ASTDropQuery::Kind::Detach && s_permanently.ignore(pos, expected))
|
||||||
|
permanently = true;
|
||||||
|
|
||||||
|
/// actually for TRUNCATE NO DELAY / SYNC means nothing
|
||||||
|
if (s_no_delay.ignore(pos, expected) || s_sync.ignore(pos, expected))
|
||||||
|
no_delay = true;
|
||||||
|
|
||||||
auto query = std::make_shared<ASTDropQuery>();
|
auto query = std::make_shared<ASTDropQuery>();
|
||||||
node = query;
|
node = query;
|
||||||
|
|
||||||
query->kind = ASTDropQuery::Kind::Drop;
|
query->kind = kind;
|
||||||
query->if_exists = if_exists;
|
query->if_exists = if_exists;
|
||||||
query->temporary = temporary;
|
query->temporary = temporary;
|
||||||
query->is_dictionary = is_dictionary;
|
query->is_dictionary = is_dictionary;
|
||||||
@ -111,28 +105,6 @@ bool parseDropQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected, bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseDetachQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
|
||||||
{
|
|
||||||
if (parseDropQuery(pos, node, expected))
|
|
||||||
{
|
|
||||||
auto * drop_query = node->as<ASTDropQuery>();
|
|
||||||
drop_query->kind = ASTDropQuery::Kind::Detach;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parseTruncateQuery(IParser::Pos & pos, ASTPtr & node, Expected & expected)
|
|
||||||
{
|
|
||||||
if (parseDropQuery(pos, node, expected, true))
|
|
||||||
{
|
|
||||||
auto * drop_query = node->as<ASTDropQuery>();
|
|
||||||
drop_query->kind = ASTDropQuery::Kind::Truncate;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParserDropQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
bool ParserDropQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
||||||
@ -142,11 +114,11 @@ bool ParserDropQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
|
|||||||
ParserKeyword s_truncate("TRUNCATE");
|
ParserKeyword s_truncate("TRUNCATE");
|
||||||
|
|
||||||
if (s_drop.ignore(pos, expected))
|
if (s_drop.ignore(pos, expected))
|
||||||
return parseDropQuery(pos, node, expected);
|
return parseDropQuery(pos, node, expected, ASTDropQuery::Kind::Drop);
|
||||||
else if (s_detach.ignore(pos, expected))
|
else if (s_detach.ignore(pos, expected))
|
||||||
return parseDetachQuery(pos, node, expected);
|
return parseDropQuery(pos, node, expected, ASTDropQuery::Kind::Detach);
|
||||||
else if (s_truncate.ignore(pos, expected))
|
else if (s_truncate.ignore(pos, expected))
|
||||||
return parseTruncateQuery(pos, node, expected);
|
return parseDropQuery(pos, node, expected, ASTDropQuery::Kind::Truncate);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#####
|
##################
|
||||||
|
setup env
|
||||||
|
##################
|
||||||
db_ordinary.log_table 1
|
db_ordinary.log_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_ordinary.log_table 2
|
db_ordinary.log_table 2
|
||||||
@ -12,7 +14,7 @@ db_ordinary.log_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_ordinary.log_table 6
|
db_ordinary.log_table 6
|
||||||
10
|
10
|
||||||
#####
|
##################
|
||||||
db_ordinary.mt_table 1
|
db_ordinary.mt_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_ordinary.mt_table 2
|
db_ordinary.mt_table 2
|
||||||
@ -26,7 +28,7 @@ db_ordinary.mt_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_ordinary.mt_table 6
|
db_ordinary.mt_table 6
|
||||||
10
|
10
|
||||||
#####
|
##################
|
||||||
db_ordinary.null_table 1
|
db_ordinary.null_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_ordinary.null_table 2
|
db_ordinary.null_table 2
|
||||||
@ -40,7 +42,7 @@ db_ordinary.null_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_ordinary.null_table 6
|
db_ordinary.null_table 6
|
||||||
0
|
0
|
||||||
#####
|
##################
|
||||||
db_atomic.log_table 1
|
db_atomic.log_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_atomic.log_table 2
|
db_atomic.log_table 2
|
||||||
@ -54,7 +56,7 @@ db_atomic.log_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_atomic.log_table 6
|
db_atomic.log_table 6
|
||||||
10
|
10
|
||||||
#####
|
##################
|
||||||
db_atomic.mt_table 1
|
db_atomic.mt_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_atomic.mt_table 2
|
db_atomic.mt_table 2
|
||||||
@ -68,7 +70,7 @@ db_atomic.mt_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_atomic.mt_table 6
|
db_atomic.mt_table 6
|
||||||
10
|
10
|
||||||
#####
|
##################
|
||||||
db_atomic.null_table 1
|
db_atomic.null_table 1
|
||||||
>table detached!
|
>table detached!
|
||||||
db_atomic.null_table 2
|
db_atomic.null_table 2
|
||||||
@ -82,3 +84,19 @@ db_atomic.null_table 5
|
|||||||
>Table is back after attach
|
>Table is back after attach
|
||||||
db_atomic.null_table 6
|
db_atomic.null_table 6
|
||||||
0
|
0
|
||||||
|
##################
|
||||||
|
test for MV
|
||||||
|
MV is working
|
||||||
|
Usual detach works immediately till restart
|
||||||
|
Usual detach activates after restart
|
||||||
|
Permanent detach works immediately
|
||||||
|
Permanent detach still works after restart
|
||||||
|
View can be reattached
|
||||||
|
##################
|
||||||
|
test for MV with inner table
|
||||||
|
MV is working
|
||||||
|
1
|
||||||
|
View can be reattached
|
||||||
|
##################
|
||||||
|
DETACH DATABASE is not implemented (proper error)
|
||||||
|
1
|
||||||
|
@ -6,10 +6,6 @@ CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|||||||
## tests with real clickhouse restart would be a bit to heavy,
|
## tests with real clickhouse restart would be a bit to heavy,
|
||||||
## to ensure the table will not reappear back clickhose-local is enough.
|
## to ensure the table will not reappear back clickhose-local is enough.
|
||||||
|
|
||||||
# TODO: clean it...
|
|
||||||
# CLICKHOUSE_LOCAL="/home/mfilimonov/workspace/ClickHouse-detach-permanently/build/programs/clickhouse-local"
|
|
||||||
# CLICKHOUSE_TMP=$(pwd)
|
|
||||||
|
|
||||||
WORKING_FOLDER_01600="${CLICKHOUSE_TMP}/01600_detach_permanently"
|
WORKING_FOLDER_01600="${CLICKHOUSE_TMP}/01600_detach_permanently"
|
||||||
rm -rf "${WORKING_FOLDER_01600}"
|
rm -rf "${WORKING_FOLDER_01600}"
|
||||||
mkdir -p "${WORKING_FOLDER_01600}"
|
mkdir -p "${WORKING_FOLDER_01600}"
|
||||||
@ -23,7 +19,7 @@ clickhouse_local() {
|
|||||||
test_detach_attach_sequence() {
|
test_detach_attach_sequence() {
|
||||||
local db="$1"
|
local db="$1"
|
||||||
local table="$2"
|
local table="$2"
|
||||||
echo "#####"
|
echo "##################"
|
||||||
|
|
||||||
echo "${db}.${table} 1"
|
echo "${db}.${table} 1"
|
||||||
# normal DETACH - while process is running (clickhouse-local here, same for server) table is detached.
|
# normal DETACH - while process is running (clickhouse-local here, same for server) table is detached.
|
||||||
@ -49,6 +45,9 @@ test_detach_attach_sequence() {
|
|||||||
clickhouse_local "SELECT count() FROM ${db}.${table};"
|
clickhouse_local "SELECT count() FROM ${db}.${table};"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echo "##################"
|
||||||
|
echo "setup env"
|
||||||
|
|
||||||
clickhouse_local "DROP DATABASE IF EXISTS db_ordinary SYNC;"
|
clickhouse_local "DROP DATABASE IF EXISTS db_ordinary SYNC;"
|
||||||
clickhouse_local "DROP DATABASE IF EXISTS db_atomic SYNC;"
|
clickhouse_local "DROP DATABASE IF EXISTS db_atomic SYNC;"
|
||||||
|
|
||||||
@ -69,4 +68,58 @@ test_detach_attach_sequence "db_ordinary" "null_table"
|
|||||||
|
|
||||||
test_detach_attach_sequence "db_atomic" "log_table"
|
test_detach_attach_sequence "db_atomic" "log_table"
|
||||||
test_detach_attach_sequence "db_atomic" "mt_table"
|
test_detach_attach_sequence "db_atomic" "mt_table"
|
||||||
test_detach_attach_sequence "db_atomic" "null_table"
|
test_detach_attach_sequence "db_atomic" "null_table"
|
||||||
|
|
||||||
|
echo "##################"
|
||||||
|
echo "test for MV"
|
||||||
|
clickhouse_local "CREATE TABLE db_ordinary.src Engine=Null AS system.numbers"
|
||||||
|
clickhouse_local "CREATE TABLE db_ordinary.dst Engine=Log AS system.numbers"
|
||||||
|
clickhouse_local "CREATE MATERIALIZED VIEW db_ordinary.src2dst_mv_to TO db_ordinary.dst AS SELECT * FROM db_ordinary.src"
|
||||||
|
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 10, 'MV is working', 'MV failed') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
clickhouse_local "DETACH VIEW db_ordinary.src2dst_mv_to; INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 10, 'Usual detach works immediately till restart', 'Usual detach failed') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 20, 'Usual detach activates after restart', 'Usual detach reactivation failed') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
clickhouse_local "DETACH VIEW db_ordinary.src2dst_mv_to PERMANENTLY; INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 20, 'Permanent detach works immediately', 'Permanent detach failed') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 20, 'Permanent detach still works after restart', 'Permanent detach reactivated!') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
## Quite silly: ATTACH MATERIALIZED VIEW don't work with short syntax (w/o select), but i can attach it using ATTACH TABLE ...
|
||||||
|
clickhouse_local "ATTACH TABLE db_ordinary.src2dst_mv_to"
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 30, 'View can be reattached', 'can not reattach permanently detached view') from db_ordinary.dst;"
|
||||||
|
|
||||||
|
clickhouse_local "DROP VIEW db_ordinary.src2dst_mv_to SYNC"
|
||||||
|
|
||||||
|
echo "##################"
|
||||||
|
echo "test for MV with inner table"
|
||||||
|
clickhouse_local "CREATE MATERIALIZED VIEW db_ordinary.src_mv_with_inner Engine=Log AS SELECT * FROM db_ordinary.src"
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
|
||||||
|
clickhouse_local "SELECT if(count() = 10, 'MV is working', 'MV failed') FROM db_ordinary.src_mv_with_inner"
|
||||||
|
|
||||||
|
clickhouse_local "DETACH VIEW db_ordinary.src_mv_with_inner PERMANENTLY; INSERT INTO db_ordinary.src SELECT * FROM numbers(10)" --stacktrace
|
||||||
|
clickhouse_local "SELECT if(count() = 10, 'MV can be detached permanently', 'MV detach failed') FROM db_ordinary.src_mv_with_inner" 2>&1 | grep -c "db_ordinary.src_mv_with_inner doesn't exist"
|
||||||
|
## Quite silly: ATTACH MATERIALIZED VIEW don't work with short syntax (w/o select), but i can attach it using ATTACH TABLE ...
|
||||||
|
clickhouse_local "ATTACH TABLE db_ordinary.src_mv_with_inner"
|
||||||
|
clickhouse_local "INSERT INTO db_ordinary.src SELECT * FROM numbers(10)"
|
||||||
|
clickhouse_local "SELECT if(count() = 20, 'View can be reattached', 'can not reattach permanently detached view') from db_ordinary.src_mv_with_inner;"
|
||||||
|
|
||||||
|
## clickhouse_local can't work with dicts...
|
||||||
|
# mkdir -p "${WORKING_FOLDER_01600}/user_files"
|
||||||
|
# echo "1" > "${WORKING_FOLDER_01600}/user_files/dummy_dict.tsv"
|
||||||
|
# clickhouse_local "DROP DICTIONARY db_ordinary.dummy; CREATE DICTIONARY db_ordinary.dummy (id UInt64) PRIMARY KEY id LAYOUT(FLAT()) SOURCE(FILE(path 'dummy_dict.tsv' format 'TabSeparated')) LIFETIME(MIN 1 MAX 10); DETACH DICTIONARY db_ordinary.dummy PERMANENTLY; SELECT dictGet('db_ordinary.dummy','val',toUInt64(1));"
|
||||||
|
|
||||||
|
echo "##################"
|
||||||
|
echo "DETACH DATABASE is not implemented (proper error)"
|
||||||
|
clickhouse_local "DETACH DATABASE db_ordinary PERMANENTLY;" 2>&1 | grep -c 'DETACH PERMANENTLY is not implemented'
|
||||||
|
|
||||||
|
# clean up
|
||||||
|
rm -rf "${WORKING_FOLDER_01600}"
|
||||||
|
Loading…
Reference in New Issue
Block a user