Preparation for rename

This commit is contained in:
alesapin 2020-03-24 20:05:38 +03:00
parent df19d6aac1
commit 4159fa0382
15 changed files with 115 additions and 1 deletions

View File

@ -28,6 +28,7 @@ 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
@ -195,6 +196,7 @@ 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);

View File

@ -280,6 +280,11 @@ AccessRightsElements InterpreterAlterQuery::getRequiredAccessForCommand(const AS
required_access.emplace_back(AccessType::REFRESH_VIEW, database, table);
break;
}
case ASTAlterCommand::RENAME_COLUMN:
{
required_access.emplace_back(AccessType::RENAME_COLUMN, database, table);
break;
}
case ASTAlterCommand::NO_TYPE: break;
}

View File

@ -56,6 +56,11 @@ ASTPtr ASTAlterCommand::clone() const
res->values = values->clone();
res->children.push_back(res->values);
}
if (rename_to)
{
res->rename_to = rename_to->clone();
res->children.push_back(res->rename_to);
}
return res;
}
@ -285,6 +290,15 @@ void ASTAlterCommand::formatImpl(
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "REFRESH " << (settings.hilite ? hilite_none : "");
}
else if (type == ASTAlterCommand::RENAME_COLUMN)
{
settings.ostr << (settings.hilite ? hilite_keyword : "") << indent_str << "RENAME COLUMN " << (if_exists ? "IF EXISTS " : "")
<< (settings.hilite ? hilite_none : "");
column->formatImpl(settings, state, frame);
settings.ostr << (settings.hilite ? hilite_keyword : "") << " TO ";
rename_to->formatImpl(settings, state, frame);
}
else
throw Exception("Unexpected type of ALTER", ErrorCodes::UNEXPECTED_AST_STRUCTURE);
}

View File

@ -29,6 +29,7 @@ public:
DROP_COLUMN,
MODIFY_COLUMN,
COMMENT_COLUMN,
RENAME_COLUMN,
MODIFY_ORDER_BY,
MODIFY_TTL,
MATERIALIZE_TTL,
@ -69,6 +70,7 @@ public:
/** The ADD COLUMN query here optionally stores the name of the column following AFTER
* The DROP query stores the column name for deletion here
* Also used for RENAME COLUMN.
*/
ASTPtr column;
@ -155,6 +157,9 @@ public:
String to_database;
String to_table;
/// Target column name
ASTPtr rename_to;
String getID(char delim) const override { return "AlterCommand" + (delim + std::to_string(static_cast<int>(type))); }
ASTPtr clone() const override;

View File

@ -231,10 +231,20 @@ std::optional<AlterCommand> AlterCommand::parse(const ASTAlterCommand * command_
else if (command_ast->type == ASTAlterCommand::MODIFY_QUERY)
{
AlterCommand command;
command.ast = command_ast->clone();
command.type = AlterCommand::MODIFY_QUERY;
command.select = command_ast->select;
return command;
}
else if (command_ast->type == ASTAlterCommand::RENAME_COLUMN)
{
AlterCommand command;
command.ast = command_ast->clone();
command.type = AlterCommand::RENAME_COLUMN;
command.column_name = command_ast->column->as<ASTIdentifier &>().name;
command.rename_to = command_ast->rename_to->as<ASTIdentifier &>().name;
return command;
}
else
return {};
}
@ -437,6 +447,10 @@ void AlterCommand::apply(StorageInMemoryMetadata & metadata) const
settings_from_storage.push_back(change);
}
}
else if (type == RENAME_COLUMN)
{
metadata.columns.rename(column_name, rename_to);
}
else
throw Exception("Wrong parameter type in ALTER query", ErrorCodes::LOGICAL_ERROR);
}
@ -519,7 +533,7 @@ bool AlterCommand::isRequireMutationStage(const StorageInMemoryMetadata & metada
if (ignore)
return false;
if (type == DROP_COLUMN || type == DROP_INDEX)
if (type == DROP_COLUMN || type == DROP_INDEX || type == RENAME_COLUMN)
return true;
if (type != MODIFY_COLUMN || data_type == nullptr)
@ -619,6 +633,8 @@ String alterTypeToString(const AlterCommand::Type type)
return "MODIFY SETTING";
case AlterCommand::Type::MODIFY_QUERY:
return "MODIFY QUERY";
case AlterCommand::Type::RENAME_COLUMN:
return "RENAME COLUMN";
}
__builtin_unreachable();
}

View File

@ -35,6 +35,7 @@ struct AlterCommand
MODIFY_TTL,
MODIFY_SETTING,
MODIFY_QUERY,
RENAME_COLUMN,
};
Type type;
@ -96,6 +97,9 @@ struct AlterCommand
/// For MODIFY_QUERY
ASTPtr select = nullptr;
/// Target column name
String rename_to;
static std::optional<AlterCommand> parse(const ASTAlterCommand * command);
void apply(StorageInMemoryMetadata & metadata) const;

View File

@ -1,4 +1,6 @@
#include <Storages/ColumnsDescription.h>
#include <boost/algorithm/string/replace.hpp>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ExpressionElementParsers.h>
#include <Parsers/ExpressionListParsers.h>
@ -195,6 +197,27 @@ void ColumnsDescription::remove(const String & column_name)
list_it = columns.get<0>().erase(list_it);
}
void ColumnsDescription::rename(const String & column_from, const String & column_to)
{
auto range = getNameRange(columns, column_from);
if (range.first == range.second)
throw Exception("There is no column " + column_from + " in table.", ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
std::vector<ColumnDescription> iterators;
for (auto list_it = range.first; list_it != range.second;)
{
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);
}
}
void ColumnsDescription::flattenNested()
{

View File

@ -57,6 +57,9 @@ public:
/// `column_name` can be a Nested column name;
void remove(const String & column_name);
/// TODO(alesap)
void rename(const String & column_from, const String & column_to);
void flattenNested(); /// TODO: remove, insert already flattened Nested columns.
bool operator==(const ColumnsDescription & other) const { return columns == other.columns; }

View File

@ -3589,4 +3589,8 @@ bool MergeTreeData::canUsePolymorphicParts(const MergeTreeSettings & settings, S
return true;
}
MergeTreeData::AlterConversions MergeTreeData::getAlterConversionsForPart(const MergeTreeDataPartPtr /*part*/) const
{
return AlterConversions{};
}
}

View File

@ -33,6 +33,7 @@ namespace DB
class MergeListEntry;
class AlterCommands;
class MergeTreePartsMover;
class MutationCommands;
class ExpressionActions;
using ExpressionActionsPtr = std::shared_ptr<ExpressionActions>;
@ -124,6 +125,11 @@ public:
STRONG_TYPEDEF(String, PartitionID)
struct AlterConversions
{
std::unordered_map<String, String> rename_map;
};
struct LessDataPart
{
using is_transparent = void;
@ -647,6 +653,8 @@ public:
/// Reserves 0 bytes
ReservationPtr makeEmptyReservationOnLargestDisk() { return getStoragePolicy()->makeEmptyReservationOnLargestDisk(); }
AlterConversions getAlterConversionsForPart(const MergeTreeDataPartPtr part) const;
MergeTreeDataFormatVersion format_version;
Context & global_context;
@ -908,6 +916,7 @@ protected:
/// mechanisms for parts locking
virtual bool partIsAssignedToBackgroundOperation(const DataPartPtr & part) const = 0;
virtual MutationCommands getFirtsAlterMutationCommandsForPart(const DataPartPtr & part) const = 0;
/// Moves part to specified space, used in ALTER ... MOVE ... queries
bool movePartsToSpace(const DataPartsVector & parts, SpacePtr space);

View File

@ -1309,6 +1309,21 @@ ReplicatedMergeTreeMergePredicate ReplicatedMergeTreeQueue::getMergePredicate(zk
}
MutationCommands ReplicatedMergeTreeQueue::getFirstAlterMutationCommandsForPart(const MergeTreeData::DataPartPtr & part) const
{
std::lock_guard lock(state_mutex);
auto in_partition = mutations_by_partition.find(part->info.partition_id);
if (in_partition == mutations_by_partition.end())
return MutationCommands{};
Int64 part_version = part->info.getDataVersion();
for (auto [mutation_version, mutation_status] : in_partition->second)
if (mutation_version > part_version && mutation_status->entry->alter_version != -1)
return mutation_status->entry->commands;
return MutationCommands{};
}
MutationCommands ReplicatedMergeTreeQueue::getMutationCommands(
const MergeTreeData::DataPartPtr & part, Int64 desired_mutation_version) const
{

View File

@ -331,6 +331,9 @@ public:
MutationCommands getMutationCommands(const MergeTreeData::DataPartPtr & part, Int64 desired_mutation_version) const;
/// TODO(alesap)
MutationCommands getFirstAlterMutationCommandsForPart(const MergeTreeData::DataPartPtr & part) const;
/// Mark finished mutations as done. If the function needs to be called again at some later time
/// (because some mutations are probably done but we are not sure yet), returns true.
bool tryFinalizeMutations(zkutil::ZooKeeperPtr zookeeper);

View File

@ -164,6 +164,8 @@ protected:
const MergingParams & merging_params_,
std::unique_ptr<MergeTreeSettings> settings_,
bool has_force_restore_data_flag);
MutationCommands getFirtsAlterMutationCommandsForPart(const DataPartPtr & /* part */) const override { return {}; }
};
}

View File

@ -5297,4 +5297,9 @@ StorageReplicatedMergeTree::getMetadataFromSharedZookeeper(const String & metada
}
MutationCommands StorageReplicatedMergeTree::getFirtsAlterMutationCommandsForPart(const DataPartPtr & part) const
{
return queue.getFirstAlterMutationCommandsForPart(part);
}
}

View File

@ -527,6 +527,9 @@ private:
StorageInMemoryMetadata getMetadataFromSharedZookeeper(const String & metadata_str, const String & columns_str) const;
MutationCommands getFirtsAlterMutationCommandsForPart(const DataPartPtr & part) const override;
protected:
/** If not 'attach', either creates a new table in ZK, or adds a replica to an existing table.
*/
@ -542,6 +545,7 @@ protected:
const MergingParams & merging_params_,
std::unique_ptr<MergeTreeSettings> settings_,
bool has_force_restore_data_flag);
};