diff --git a/dbms/src/Access/AccessType.h b/dbms/src/Access/AccessType.h index 29a289ac235..27892076d59 100644 --- a/dbms/src/Access/AccessType.h +++ b/dbms/src/Access/AccessType.h @@ -28,7 +28,6 @@ enum class AccessType ADD_COLUMN, DROP_COLUMN, MODIFY_COLUMN, - RENAME_COLUMN, COMMENT_COLUMN, CLEAR_COLUMN, ALTER_COLUMN, /// allow to execute ALTER {ADD|DROP|MODIFY...} COLUMN @@ -196,7 +195,6 @@ namespace impl ACCESS_TYPE_TO_KEYWORD_CASE(ADD_COLUMN); ACCESS_TYPE_TO_KEYWORD_CASE(DROP_COLUMN); ACCESS_TYPE_TO_KEYWORD_CASE(MODIFY_COLUMN); - ACCESS_TYPE_TO_KEYWORD_CASE(RENAME_COLUMN); ACCESS_TYPE_TO_KEYWORD_CASE(COMMENT_COLUMN); ACCESS_TYPE_TO_KEYWORD_CASE(CLEAR_COLUMN); ACCESS_TYPE_TO_KEYWORD_CASE(ALTER_COLUMN); diff --git a/dbms/src/Interpreters/InterpreterAlterQuery.cpp b/dbms/src/Interpreters/InterpreterAlterQuery.cpp index 298f3fc4097..ff2afeab8ef 100644 --- a/dbms/src/Interpreters/InterpreterAlterQuery.cpp +++ b/dbms/src/Interpreters/InterpreterAlterQuery.cpp @@ -282,7 +282,6 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS } case ASTAlterCommand::RENAME_COLUMN: { - required_access.emplace_back(AccessType::RENAME_COLUMN, database, table); break; } case ASTAlterCommand::NO_TYPE: break; diff --git a/dbms/src/Parsers/ParserAlterQuery.cpp b/dbms/src/Parsers/ParserAlterQuery.cpp index 1b647cf067c..3df946ba485 100644 --- a/dbms/src/Parsers/ParserAlterQuery.cpp +++ b/dbms/src/Parsers/ParserAlterQuery.cpp @@ -27,6 +27,7 @@ bool ParserAlterCommand::parseImpl(Pos & pos, ASTPtr & node, Expected & expected ParserKeyword s_drop_column("DROP COLUMN"); ParserKeyword s_clear_column("CLEAR COLUMN"); ParserKeyword s_modify_column("MODIFY COLUMN"); + ParserKeyword s_rename_column("RENAME COLUMN"); ParserKeyword s_comment_column("COMMENT COLUMN"); ParserKeyword s_modify_order_by("MODIFY ORDER BY"); ParserKeyword s_modify_ttl("MODIFY TTL"); @@ -77,6 +78,7 @@ bool ParserAlterCommand::parseImpl(Pos & pos, ASTPtr & node, Expected & expected ParserKeyword s_delete_where("DELETE WHERE"); ParserKeyword s_update("UPDATE"); ParserKeyword s_where("WHERE"); + ParserKeyword s_to("TO"); ParserCompoundIdentifier parser_name; ParserStringLiteral parser_string_literal; @@ -121,6 +123,22 @@ bool ParserAlterCommand::parseImpl(Pos & pos, ASTPtr & node, Expected & expected command->type = ASTAlterCommand::ADD_COLUMN; } + else if (s_rename_column.ignore(pos, expected)) + { + if (s_if_not_exists.ignore(pos, expected)) + command->if_not_exists = true; + + if (!parser_name.parse(pos, command->column, expected)) + return false; + + if (!s_to.ignore(pos, expected)) + return false; + + if (!parser_name.parse(pos, command->rename_to, expected)) + return false; + + command->type = ASTAlterCommand::RENAME_COLUMN; + } else if (s_drop_partition.ignore(pos, expected)) { if (!parser_partition.parse(pos, command->partition, expected)) diff --git a/dbms/src/Parsers/ParserAlterQuery.h b/dbms/src/Parsers/ParserAlterQuery.h index 61a25b9b387..a0981c77ca6 100644 --- a/dbms/src/Parsers/ParserAlterQuery.h +++ b/dbms/src/Parsers/ParserAlterQuery.h @@ -12,6 +12,7 @@ namespace DB * [DROP COLUMN [IF EXISTS] col_to_drop, ...] * [CLEAR COLUMN [IF EXISTS] col_to_clear [IN PARTITION partition],] * [MODIFY COLUMN [IF EXISTS] col_to_modify type, ...] + * [RENAME COLUMN [IF EXISTS] col_name TO col_name] * [MODIFY PRIMARY KEY (a, b, c...)] * [MODIFY SETTING setting_name=setting_value, ...] * [COMMENT COLUMN [IF EXISTS] col_name string] diff --git a/dbms/src/Storages/AlterCommands.cpp b/dbms/src/Storages/AlterCommands.cpp index 4af0e3e49c9..f20a3f58382 100644 --- a/dbms/src/Storages/AlterCommands.cpp +++ b/dbms/src/Storages/AlterCommands.cpp @@ -533,7 +533,7 @@ bool AlterCommand::isRequireMutationStage(const StorageInMemoryMetadata & metada if (ignore) return false; - if (type == DROP_COLUMN || type == DROP_INDEX || type == RENAME_COLUMN) + if (type == DROP_COLUMN || type == DROP_INDEX) return true; if (type != MODIFY_COLUMN || data_type == nullptr) diff --git a/dbms/src/Storages/ColumnsDescription.cpp b/dbms/src/Storages/ColumnsDescription.cpp index ea8217c5f18..787fa2b739a 100644 --- a/dbms/src/Storages/ColumnsDescription.cpp +++ b/dbms/src/Storages/ColumnsDescription.cpp @@ -199,23 +199,14 @@ void ColumnsDescription::remove(const String & column_name) void ColumnsDescription::rename(const String & column_from, const String & column_to) { - auto range = getNameRange(columns, column_from); + auto it = columns.get<1>().find(column_from); + if (it == columns.get<1>().end()) + throw Exception("Cannot find column " + column_from + " in ColumnsDescription", ErrorCodes::LOGICAL_ERROR); - if (range.first == range.second) - throw Exception("There is no column " + column_from + " in table.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE); - - std::vector iterators; - for (auto list_it = range.first; list_it != range.second;) + columns.get<1>().modify_key(it, [&column_to] (String & old_name) { - iterators.push_back(*list_it); - list_it = columns.get<0>().erase(list_it); - } - - for (auto & col_desc : iterators) - { - boost::replace_all(col_desc.name, column_from, column_to); - add(col_desc); - } + old_name = column_to; + }); } diff --git a/dbms/src/Storages/MergeTree/IMergeTreeReader.cpp b/dbms/src/Storages/MergeTree/IMergeTreeReader.cpp index 91d52cfa1fc..7ccbe71938c 100644 --- a/dbms/src/Storages/MergeTree/IMergeTreeReader.cpp +++ b/dbms/src/Storages/MergeTree/IMergeTreeReader.cpp @@ -30,6 +30,7 @@ IMergeTreeReader::IMergeTreeReader(const MergeTreeData::DataPartPtr & data_part_ , columns(columns_), uncompressed_cache(uncompressed_cache_), mark_cache(mark_cache_) , settings(settings_), storage(data_part_->storage) , all_mark_ranges(all_mark_ranges_) + , alter_conversions(storage.getAlterConversionsForPart(data_part)) { } @@ -62,6 +63,11 @@ static bool arrayHasNoElementsRead(const IColumn & column) } +//void IMergeTreeReader::renameColumnsWithAlters(Columns & res_columns) +//{ +// +//} + void IMergeTreeReader::fillMissingColumns(Columns & res_columns, bool & should_evaluate_missing_defaults, size_t num_rows) { try diff --git a/dbms/src/Storages/MergeTree/IMergeTreeReader.h b/dbms/src/Storages/MergeTree/IMergeTreeReader.h index 75fefe235f8..f74530f2d5f 100644 --- a/dbms/src/Storages/MergeTree/IMergeTreeReader.h +++ b/dbms/src/Storages/MergeTree/IMergeTreeReader.h @@ -48,6 +48,9 @@ public: /// try to perform conversions of columns. void performRequiredConversions(Columns & res_columns); + /// TODO(alesap) + void renameColumnsWithAlters(Columns & res_columns); + const NamesAndTypesList & getColumns() const { return columns; } size_t numColumnsInResult() const { return columns.size(); } @@ -78,6 +81,7 @@ protected: MarkRanges all_mark_ranges; friend class MergeTreeRangeReader::DelayedStream; + MergeTreeData::AlterConversions alter_conversions; }; } diff --git a/dbms/src/Storages/MergeTree/MergeTreeData.cpp b/dbms/src/Storages/MergeTree/MergeTreeData.cpp index 83442f4dff1..7d07540741e 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeData.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeData.cpp @@ -3589,8 +3589,15 @@ bool MergeTreeData::canUsePolymorphicParts(const MergeTreeSettings & settings, S return true; } -MergeTreeData::AlterConversions MergeTreeData::getAlterConversionsForPart(const MergeTreeDataPartPtr /*part*/) const +MergeTreeData::AlterConversions MergeTreeData::getAlterConversionsForPart(const MergeTreeDataPartPtr part) const { - return AlterConversions{}; + MutationCommands commands = getFirtsAlterMutationCommandsForPart(part); + + AlterConversions result{}; + for (const auto & command : commands) + if (command.type == MutationCommand::Type::RENAME_COLUMN) + result.rename_map[command.column_name] = command.rename_to; + + return result; } } diff --git a/dbms/src/Storages/MutationCommands.cpp b/dbms/src/Storages/MutationCommands.cpp index 8c66646abed..d48f8525162 100644 --- a/dbms/src/Storages/MutationCommands.cpp +++ b/dbms/src/Storages/MutationCommands.cpp @@ -94,6 +94,15 @@ std::optional MutationCommand::parse(ASTAlterCommand * command, res.clear = true; return res; } + else if (parse_alter_commands && command->type == ASTAlterCommand::RENAME_COLUMN) + { + MutationCommand res; + res.ast = command->ptr(); + res.type = MutationCommand::Type::RENAME_COLUMN; + res.column_name = command->column->as().name; + res.rename_to = command->rename_to->as().name; + return res; + } else if (command->type == ASTAlterCommand::MATERIALIZE_TTL) { MutationCommand res; diff --git a/dbms/src/Storages/MutationCommands.h b/dbms/src/Storages/MutationCommands.h index f006575a9b8..6fa4f7fb641 100644 --- a/dbms/src/Storages/MutationCommands.h +++ b/dbms/src/Storages/MutationCommands.h @@ -31,7 +31,8 @@ struct MutationCommand READ_COLUMN, DROP_COLUMN, DROP_INDEX, - MATERIALIZE_TTL + MATERIALIZE_TTL, + RENAME_COLUMN, }; Type type = EMPTY; @@ -53,6 +54,9 @@ struct MutationCommand /// We need just clear column, not drop from metadata. bool clear = false; + /// Column rename_to + String rename_to; + /// If parse_alter_commands, than consider more Alter commands as mutation commands static std::optional parse(ASTAlterCommand * command, bool parse_alter_commands = false); }; diff --git a/dbms/tests/queries/0_stateless/01213_alter_rename_column.reference b/dbms/tests/queries/0_stateless/01213_alter_rename_column.reference new file mode 100644 index 00000000000..6ed281c757a --- /dev/null +++ b/dbms/tests/queries/0_stateless/01213_alter_rename_column.reference @@ -0,0 +1,2 @@ +1 +1 diff --git a/dbms/tests/queries/0_stateless/01213_alter_rename_column.sql b/dbms/tests/queries/0_stateless/01213_alter_rename_column.sql new file mode 100644 index 00000000000..efd485ef89b --- /dev/null +++ b/dbms/tests/queries/0_stateless/01213_alter_rename_column.sql @@ -0,0 +1,23 @@ +DROP TABLE IF EXISTS table_for_rename; + +CREATE TABLE table_for_rename +( + date Date, + key UInt64, + value1 String, + value2 String, + value3 String +) +ENGINE = MergeTree() +PARTITION BY date +ORDER BY key; + +INSERT INTO table_for_rename SELECT toDate('2019-10-01') + number % 3, number, toString(number), toString(number), toString(number) from numbers(9); + +SELECT value1 FROM table_for_rename WHERE key = 1; + +ALTER TABLE table_for_rename RENAME COLUMN value1 to renamed_value1; + +SELECT renamed_value1 FROM table_for_rename WHERE key = 1; + +DROP TABLE IF EXISTS table_for_rename;