From 0b3e81aef0e554da74a1d33f436552cf787886e8 Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 31 Mar 2020 19:18:18 +0300 Subject: [PATCH] Add limited support for nested structs --- dbms/src/Storages/AlterCommands.cpp | 26 ++++++++++++- dbms/src/Storages/ColumnsDescription.cpp | 1 + .../MergeTree/MergeTreeDataMergerMutator.cpp | 17 +++++++-- .../01213_alter_rename_nested.reference | 6 +++ .../0_stateless/01213_alter_rename_nested.sql | 34 +++++++++++++++++ .../01213_alter_table_rename_nested.sql | 38 +++++++++++++++++++ 6 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 dbms/tests/queries/0_stateless/01213_alter_rename_nested.reference create mode 100644 dbms/tests/queries/0_stateless/01213_alter_rename_nested.sql create mode 100644 dbms/tests/queries/0_stateless/01213_alter_table_rename_nested.sql diff --git a/dbms/src/Storages/AlterCommands.cpp b/dbms/src/Storages/AlterCommands.cpp index 14ff07daa12..1b135563095 100644 --- a/dbms/src/Storages/AlterCommands.cpp +++ b/dbms/src/Storages/AlterCommands.cpp @@ -39,6 +39,7 @@ namespace ErrorCodes extern const int NOT_FOUND_COLUMN_IN_BLOCK; extern const int LOGICAL_ERROR; extern const int DUPLICATE_COLUMN; + extern const int NOT_IMPLEMENTED; } @@ -778,6 +779,12 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con } else if (command.type == AlterCommand::RENAME_COLUMN) { + /// TODO Implement nested rename + if (metadata.columns.hasNested(command.column_name)) + { + throw Exception{"Cannot rename whole Nested struct", ErrorCodes::NOT_IMPLEMENTED}; + } + if (!metadata.columns.has(command.column_name)) { if (!command.if_exists) @@ -797,7 +804,24 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con throw Exception{"Rename loop detected in ALTER query", ErrorCodes::BAD_ARGUMENTS}; - renames_map[command.column_name] = command.rename_to; + String from_nested_table_name = Nested::extractTableName(command.column_name); + String to_nested_table_name = Nested::extractTableName(command.rename_to); + bool from_nested = from_nested_table_name != command.column_name; + bool to_nested = to_nested_table_name != command.rename_to; + + if (from_nested && to_nested) + { + if (from_nested_table_name != to_nested_table_name) + throw Exception{"Cannot rename column from one nested name to another", ErrorCodes::BAD_ARGUMENTS}; + } + else if (!from_nested && !to_nested) + { + renames_map[command.column_name] = command.rename_to; + } + else + { + throw Exception{"Cannot rename column from nested struct to normal column and vice versa", ErrorCodes::BAD_ARGUMENTS}; + } } /// Collect default expressions for MODIFY and ADD comands diff --git a/dbms/src/Storages/ColumnsDescription.cpp b/dbms/src/Storages/ColumnsDescription.cpp index 787fa2b739a..f7d00ea2d54 100644 --- a/dbms/src/Storages/ColumnsDescription.cpp +++ b/dbms/src/Storages/ColumnsDescription.cpp @@ -38,6 +38,7 @@ namespace ErrorCodes extern const int ILLEGAL_COLUMN; extern const int CANNOT_PARSE_TEXT; extern const int THERE_IS_NO_DEFAULT_VALUE; + extern const int LOGICAL_ERROR; } ColumnDescription::ColumnDescription(String name_, DataTypePtr type_, bool is_virtual_) diff --git a/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp b/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp index 64650165c28..d1dd2861202 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeDataMergerMutator.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1061,7 +1062,6 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataMergerMutator::mutatePartToTempor NameSet files_to_skip = collectFilesToSkip(updated_header, indices_to_recalc, mrk_extension); NameToNameMap files_to_rename = collectFilesForRenames(source_part, for_file_renames, mrk_extension); - if (need_remove_expired_values) files_to_skip.insert("ttl.txt"); @@ -1108,7 +1108,9 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataMergerMutator::mutatePartToTempor for (const auto & [rename_from, rename_to] : files_to_rename) { if (rename_to.empty() && new_data_part->checksums.files.count(rename_from)) + { new_data_part->checksums.files.erase(rename_from); + } else if (new_data_part->checksums.files.count(rename_from)) { new_data_part->checksums.files[rename_to] = new_data_part->checksums.files[rename_from]; @@ -1329,13 +1331,20 @@ NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames( } else if (command.type == MutationCommand::Type::RENAME_COLUMN) { + String escaped_name_from = escapeForFileName(command.column_name); + String escaped_name_to = escapeForFileName(command.rename_to); + IDataType::StreamCallback callback = [&](const IDataType::SubstreamPath & substream_path) { String stream_from = IDataType::getFileNameForStream(command.column_name, substream_path); - String stream_to = boost::replace_first_copy(stream_from, command.column_name, command.rename_to); - rename_map.emplace(stream_from + ".bin", stream_to + ".bin"); - rename_map.emplace(stream_from + mrk_extension, stream_to + mrk_extension); + String stream_to = boost::replace_first_copy(stream_from, escaped_name_from, escaped_name_to); + + if (stream_from != stream_to) + { + rename_map.emplace(stream_from + ".bin", stream_to + ".bin"); + rename_map.emplace(stream_from + mrk_extension, stream_to + mrk_extension); + } }; IDataType::SubstreamPath stream_path; auto column = source_part->getColumns().tryGetByName(command.column_name); diff --git a/dbms/tests/queries/0_stateless/01213_alter_rename_nested.reference b/dbms/tests/queries/0_stateless/01213_alter_rename_nested.reference new file mode 100644 index 00000000000..51647dc2e7b --- /dev/null +++ b/dbms/tests/queries/0_stateless/01213_alter_rename_nested.reference @@ -0,0 +1,6 @@ +[8,9,10] +['a','b','c'] +CREATE TABLE default.table_for_rename_nested (`date` Date, `key` UInt64, `n.x` Array(UInt32), `n.y` Array(String), `value1` String) ENGINE = MergeTree() PARTITION BY date ORDER BY key SETTINGS index_granularity = 8192 +CREATE TABLE default.table_for_rename_nested (`date` Date, `key` UInt64, `n.renamed_x` Array(UInt32), `n.renamed_y` Array(String), `value1` String) ENGINE = MergeTree() PARTITION BY date ORDER BY key SETTINGS index_granularity = 8192 +7 [8,9,10] +7 ['a','b','c'] diff --git a/dbms/tests/queries/0_stateless/01213_alter_rename_nested.sql b/dbms/tests/queries/0_stateless/01213_alter_rename_nested.sql new file mode 100644 index 00000000000..8dc221ef388 --- /dev/null +++ b/dbms/tests/queries/0_stateless/01213_alter_rename_nested.sql @@ -0,0 +1,34 @@ +DROP TABLE IF EXISTS table_for_rename_nested; +CREATE TABLE table_for_rename_nested +( + date Date, + key UInt64, + n Nested(x UInt32, y String), + value1 String +) +ENGINE = MergeTree() +PARTITION BY date +ORDER BY key; + +INSERT INTO table_for_rename_nested (date, key, n.x, n.y, value1) SELECT toDate('2019-10-01'), number, [number + 1, number + 2, number + 3], ['a', 'b', 'c'], toString(number) FROM numbers(10); + +SELECT n.x FROM table_for_rename_nested WHERE key = 7; +SELECT n.y FROM table_for_rename_nested WHERE key = 7; + +SHOW CREATE TABLE table_for_rename_nested; + +ALTER TABLE table_for_rename_nested RENAME COLUMN n.x TO n.renamed_x; +ALTER TABLE table_for_rename_nested RENAME COLUMN n.y TO n.renamed_y; + +SHOW CREATE TABLE table_for_rename_nested; + +SELECT key, n.renamed_x FROM table_for_rename_nested WHERE key = 7; +SELECT key, n.renamed_y FROM table_for_rename_nested WHERE key = 7; + +ALTER TABLE table_for_rename_nested RENAME COLUMN n.renamed_x TO not_nested_x; --{serverError 36} + +-- Currently not implemented +ALTER TABLE table_for_rename_nested RENAME COLUMN n TO renamed_n; --{serverError 48} + +DROP TABLE IF EXISTS table_for_rename_nested; + diff --git a/dbms/tests/queries/0_stateless/01213_alter_table_rename_nested.sql b/dbms/tests/queries/0_stateless/01213_alter_table_rename_nested.sql new file mode 100644 index 00000000000..e08e3c0c3b1 --- /dev/null +++ b/dbms/tests/queries/0_stateless/01213_alter_table_rename_nested.sql @@ -0,0 +1,38 @@ +DROP TABLE IF EXISTS table_for_rename_nested; +CREATE TABLE table_for_rename_nested +( + date Date, + key UInt64, + n Nested(x UInt32, y String), + value1 String +) +ENGINE = MergeTree() +PARTITION BY date +ORDER BY key; + +INSERT INTO table_for_rename_nested (date, key, n.x, n.y, value1) SELECT toDate('2019-10-01'), number, [number + 1, number + 2, number + 3], ['a', 'b', 'c'], toString(number) FROM numbers(10); + +SELECT n.x FROM table_for_rename_nested WHERE key = 7; +SELECT n.y FROM table_for_rename_nested WHERE key = 7; + +SHOW CREATE TABLE table_for_rename_nested; + +ALTER TABLE table_for_rename_nested RENAME COLUMN n.x TO n.renamed_x; +ALTER TABLE table_for_rename_nested RENAME COLUMN n.y TO n.renamed_y; + +SHOW CREATE TABLE table_for_rename_nested; + +SELECT key, n.renamed_x FROM table_for_rename_nested WHERE key = 7; +SELECT key, n.renamed_y FROM table_for_rename_nested WHERE key = 7; + +ALTER TABLE table_for_rename_nested RENAME COLUMN n.renamed_x TO not_nested_x; --{serverError 36} + +ALTER TABLE table_for_rename_nested RENAME COLUMN n.renamed_x TO q.renamed_x; --{serverError 36} + +ALTER TABLE table_for_rename_nested RENAME COLUMN value1 TO q.renamed_x; --{serverError 36} + +-- Currently not implemented +ALTER TABLE table_for_rename_nested RENAME COLUMN n TO renamed_n; --{serverError 48} + +DROP TABLE IF EXISTS table_for_rename_nested; +