Fix some rename cases

This commit is contained in:
alesapin 2020-05-13 20:43:30 +03:00
parent 41ca7ae83a
commit ab760846c2
7 changed files with 53 additions and 27 deletions

View File

@ -15,6 +15,7 @@ using NameSet = std::unordered_set<std::string>;
using NameOrderedSet = std::set<std::string>;
using NameToNameMap = std::unordered_map<std::string, std::string>;
using NameToNameSetMap = std::unordered_map<std::string, NameSet>;
using NameToNameVector = std::vector<std::pair<std::string, std::string>>;
using NameWithAlias = std::pair<std::string, std::string>;
using NamesWithAliases = std::vector<NameWithAlias>;

View File

@ -733,7 +733,6 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con
auto all_columns = metadata.columns;
/// Default expression for all added/modified columns
ASTPtr default_expr_list = std::make_shared<ASTExpressionList>();
NameToNameMap renames_map;
for (size_t i = 0; i < size(); ++i)
{
const auto & command = (*this)[i];
@ -809,31 +808,40 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con
}
else if (command.type == AlterCommand::RENAME_COLUMN)
{
for (size_t j = i + 1; j < size(); ++j)
{
auto next_command = (*this)[j];
if (next_command.type == AlterCommand::RENAME_COLUMN)
{
if (next_command.column_name == command.rename_to)
throw Exception{"Transitive renames in a single ALTER query are not allowed (don't make sence)",
ErrorCodes::NOT_IMPLEMENTED};
else if (next_command.column_name == command.column_name)
throw Exception{"Cannot rename column '" + backQuote(command.column_name)
+ "' to two different names in a single ALTER query",
ErrorCodes::BAD_ARGUMENTS};
}
}
/// TODO Implement nested rename
if (metadata.columns.hasNested(command.column_name))
if (all_columns.hasNested(command.column_name))
{
throw Exception{"Cannot rename whole Nested struct", ErrorCodes::NOT_IMPLEMENTED};
}
if (!metadata.columns.has(command.column_name))
if (!all_columns.has(command.column_name))
{
if (!command.if_exists)
throw Exception{"Wrong column name. Cannot find column " + backQuote(command.column_name) + " to rename",
ErrorCodes::NOT_FOUND_COLUMN_IN_BLOCK};
else
continue;
}
if (metadata.columns.has(command.rename_to))
if (all_columns.has(command.rename_to))
throw Exception{"Cannot rename to " + backQuote(command.rename_to) + ": column with this name already exists",
ErrorCodes::DUPLICATE_COLUMN};
if (renames_map.count(command.column_name))
throw Exception{"Cannot rename column '" + backQuote(command.column_name) + "' to two different names in a single ALTER query", ErrorCodes::BAD_ARGUMENTS};
if (renames_map.count(command.rename_to))
throw Exception{"Rename loop detected in ALTER query",
ErrorCodes::BAD_ARGUMENTS};
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;
@ -846,7 +854,7 @@ void AlterCommands::validate(const StorageInMemoryMetadata & metadata, const Con
}
else if (!from_nested && !to_nested)
{
renames_map[command.column_name] = command.rename_to;
all_columns.rename(command.column_name, command.rename_to);
}
else
{

View File

@ -1085,7 +1085,7 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataMergerMutator::mutatePartToTempor
auto indices_to_recalc = getIndicesToRecalculate(in, storage_from_source_part, updated_header.getNamesAndTypesList(), context);
NameSet files_to_skip = collectFilesToSkip(updated_header, indices_to_recalc, mrk_extension);
NameToNameMap files_to_rename = collectFilesForRenames(source_part, for_file_renames, mrk_extension);
NameToNameVector files_to_rename = collectFilesForRenames(source_part, for_file_renames, mrk_extension);
if (need_remove_expired_values)
files_to_skip.insert("ttl.txt");
@ -1097,7 +1097,8 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataMergerMutator::mutatePartToTempor
continue;
String destination = new_part_tmp_path + "/";
auto rename_it = files_to_rename.find(it->name());
String file_name = it->name();
auto rename_it = std::find_if(files_to_rename.begin(), files_to_rename.end(), [&file_name](const auto & rename_pair) { return rename_pair.first == file_name; });
if (rename_it != files_to_rename.end())
{
if (rename_it->second.empty())
@ -1328,7 +1329,7 @@ void MergeTreeDataMergerMutator::splitMutationCommands(
}
NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames(
NameToNameVector MergeTreeDataMergerMutator::collectFilesForRenames(
MergeTreeData::DataPartPtr source_part, const MutationCommands & commands_for_removes, const String & mrk_extension)
{
/// Collect counts for shared streams of different columns. As an example, Nested columns have shared stream with array sizes.
@ -1343,14 +1344,14 @@ NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames(
{});
}
NameToNameMap rename_map;
NameToNameVector rename_vector;
/// Remove old indices
for (const auto & command : commands_for_removes)
{
if (command.type == MutationCommand::Type::DROP_INDEX)
{
rename_map.emplace("skp_idx_" + command.column_name + ".idx", "");
rename_map.emplace("skp_idx_" + command.column_name + mrk_extension, "");
rename_vector.emplace_back("skp_idx_" + command.column_name + ".idx", "");
rename_vector.emplace_back("skp_idx_" + command.column_name + mrk_extension, "");
}
else if (command.type == MutationCommand::Type::DROP_COLUMN)
{
@ -1360,8 +1361,8 @@ NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames(
/// Delete files if they are no longer shared with another column.
if (--stream_counts[stream_name] == 0)
{
rename_map.emplace(stream_name + ".bin", "");
rename_map.emplace(stream_name + mrk_extension, "");
rename_vector.emplace_back(stream_name + ".bin", "");
rename_vector.emplace_back(stream_name + mrk_extension, "");
}
};
@ -1383,8 +1384,8 @@ NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames(
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);
rename_vector.emplace_back(stream_from + ".bin", stream_to + ".bin");
rename_vector.emplace_back(stream_from + mrk_extension, stream_to + mrk_extension);
}
};
IDataType::SubstreamPath stream_path;
@ -1394,7 +1395,7 @@ NameToNameMap MergeTreeDataMergerMutator::collectFilesForRenames(
}
}
return rename_map;
return rename_vector;
}
NameSet MergeTreeDataMergerMutator::collectFilesToSkip(

View File

@ -143,10 +143,9 @@ private:
MutationCommands & for_interpreter,
MutationCommands & for_file_renames);
/// Apply commands to source_part i.e. remove some columns in source_part
/// and return set of files, that have to be removed from filesystem and checksums
static NameToNameMap collectFilesForRenames(MergeTreeData::DataPartPtr source_part, const MutationCommands & commands_for_removes, const String & mrk_extension);
static NameToNameVector collectFilesForRenames(MergeTreeData::DataPartPtr source_part, const MutationCommands & commands_for_removes, const String & mrk_extension);
/// Files, that we don't need to remove and don't need to hardlink, for example columns.txt and checksums.txt.
/// Because we will generate new versions of them after we perform mutation.

View File

@ -24,7 +24,7 @@ SELECT * FROM table_for_rename WHERE key = 1 FORMAT TSVWithNames;
ALTER TABLE table_for_rename RENAME COLUMN value3 to value2; --{serverError 15}
ALTER TABLE table_for_rename RENAME COLUMN value3 TO r1, RENAME COLUMN value3 TO r2; --{serverError 36}
ALTER TABLE table_for_rename RENAME COLUMN value3 TO r1, RENAME COLUMN r1 TO value1; --{serverError 10}
ALTER TABLE table_for_rename RENAME COLUMN value3 TO r1, RENAME COLUMN r1 TO value1; --{serverError 48}
ALTER TABLE table_for_rename RENAME COLUMN value2 TO renamed_value2, RENAME COLUMN value3 TO renamed_value3;

View File

@ -0,0 +1,3 @@
CREATE TABLE default.rename_table\n(\n `key` Int32, \n `old_value1` Int32, \n `value1` Int32\n)\nENGINE = MergeTree\nORDER BY tuple()\nSETTINGS index_granularity = 8192
key old_value1 value1
1 2 3

View File

@ -0,0 +1,14 @@
DROP TABLE IF EXISTS rename_table;
CREATE TABLE rename_table (key Int32, value1 Int32, value2 Int32) ENGINE = MergeTree ORDER BY tuple();
INSERT INTO rename_table VALUES (1, 2, 3);
-- replace one with other
ALTER TABLE rename_table RENAME COLUMN value1 TO old_value1, RENAME COLUMN value2 TO value1;
SHOW CREATE TABLE rename_table;
SELECT * FROM rename_table FORMAT TSVWithNames;
DROP TABLE IF EXISTS rename_table;