Allow to CLEAR column even if there are depending DEFAULT expressions #12333

This commit is contained in:
Alexey Milovidov 2020-07-10 08:54:35 +03:00
parent c16d8e094b
commit a4b35a8a6f
3 changed files with 69 additions and 11 deletions

View File

@ -844,20 +844,24 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con
{ {
if (all_columns.has(command.column_name) || all_columns.hasNested(command.column_name)) if (all_columns.has(command.column_name) || all_columns.hasNested(command.column_name))
{ {
for (const ColumnDescription & column : all_columns) if (!command.clear) /// CLEAR column is Ok even if there are dependencies.
{ {
const auto & default_expression = column.default_desc.expression; /// Check if we are going to DROP a column that some other columns depend on.
if (default_expression) for (const ColumnDescription & column : all_columns)
{ {
ASTPtr query = default_expression->clone(); const auto & default_expression = column.default_desc.expression;
auto syntax_result = SyntaxAnalyzer(context).analyze(query, all_columns.getAll()); if (default_expression)
const auto actions = ExpressionAnalyzer(query, syntax_result, context).getActions(true); {
const auto required_columns = actions->getRequiredColumns(); ASTPtr query = default_expression->clone();
auto syntax_result = SyntaxAnalyzer(context).analyze(query, all_columns.getAll());
const auto actions = ExpressionAnalyzer(query, syntax_result, context).getActions(true);
const auto required_columns = actions->getRequiredColumns();
if (required_columns.end() != std::find(required_columns.begin(), required_columns.end(), command.column_name)) if (required_columns.end() != std::find(required_columns.begin(), required_columns.end(), command.column_name))
throw Exception( throw Exception("Cannot drop column " + backQuote(command.column_name)
"Cannot drop column " + backQuote(command.column_name) + ", because column " + backQuote(column.name) + " depends on it", + ", because column " + backQuote(column.name) + " depends on it",
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
}
} }
} }
all_columns.remove(command.column_name); all_columns.remove(command.column_name);

View File

@ -0,0 +1,18 @@
1 2
2 3
3 4
0 2
0 3
0 4
1 2
2 3
3 4
0 2
0 3
0 4
1 2
2 3
3 4
0 1
0 1
0 1

View File

@ -0,0 +1,36 @@
-- It's Ok to CLEAR column when there are columns with default expression depending on it.
-- But it's not Ok to DROP such column.
DROP TABLE IF EXISTS test;
CREATE TABLE test (x UInt8, y UInt8 DEFAULT x + 1) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO test (x) VALUES (1), (2), (3);
SELECT * FROM test ORDER BY x, y;
ALTER TABLE test CLEAR COLUMN x;
SELECT * FROM test ORDER BY x, y;
ALTER TABLE test DROP COLUMN x; -- { serverError 44 }
DROP TABLE test;
DROP TABLE IF EXISTS test;
CREATE TABLE test (x UInt8, y UInt8 MATERIALIZED x + 1) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO test (x) VALUES (1), (2), (3);
SELECT x, y FROM test ORDER BY x, y;
ALTER TABLE test CLEAR COLUMN x;
SELECT x, y FROM test ORDER BY x, y;
ALTER TABLE test DROP COLUMN x; -- { serverError 44 }
DROP TABLE test;
DROP TABLE IF EXISTS test;
CREATE TABLE test (x UInt8, y UInt8 ALIAS x + 1, z String DEFAULT 'Hello') ENGINE = MergeTree ORDER BY tuple();
INSERT INTO test (x) VALUES (1), (2), (3);
SELECT x, y FROM test ORDER BY x, y;
ALTER TABLE test CLEAR COLUMN x;
SELECT x, y FROM test ORDER BY x, y;
ALTER TABLE test DROP COLUMN x; -- { serverError 44 }
DROP TABLE test;
-- The original report from Mikhail Petrov
DROP TABLE IF EXISTS Test;
create table Test (impression_id String,impression_id_compressed FixedString(16) DEFAULT UUIDStringToNum(substring(impression_id, 1, 36)), impression_id_hashed UInt16 DEFAULT reinterpretAsUInt16(impression_id_compressed), event_date Date ) ENGINE = MergeTree(event_date, impression_id_hashed, (event_date, impression_id_hashed), 8192);
alter table Test clear column impression_id in partition '202001';
DROP TABLE Test;