2018-05-15 12:56:14 +00:00
|
|
|
#include <Storages/MutationCommands.h>
|
2021-01-11 14:43:05 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2021-01-11 14:51:23 +00:00
|
|
|
#include <IO/ReadHelpers.h>
|
2018-04-19 10:33:16 +00:00
|
|
|
#include <Parsers/formatAST.h>
|
2018-07-11 12:43:55 +00:00
|
|
|
#include <Parsers/ParserAlterQuery.h>
|
2018-04-19 10:33:16 +00:00
|
|
|
#include <Parsers/parseQuery.h>
|
2018-08-07 13:58:11 +00:00
|
|
|
#include <Parsers/ASTAssignment.h>
|
2020-11-10 10:23:46 +00:00
|
|
|
#include <Parsers/ASTColumnDeclaration.h>
|
|
|
|
#include <Parsers/ASTFunction.h>
|
2019-05-05 17:01:54 +00:00
|
|
|
#include <Parsers/ASTIdentifier.h>
|
2018-07-11 12:43:55 +00:00
|
|
|
#include <Common/typeid_cast.h>
|
2019-10-08 18:42:22 +00:00
|
|
|
#include <Common/quoteString.h>
|
2023-08-09 20:57:49 +00:00
|
|
|
#include "Parsers/ASTAlterQuery.h"
|
2020-04-15 20:28:05 +00:00
|
|
|
#include <Core/Defines.h>
|
2020-01-15 13:00:08 +00:00
|
|
|
#include <DataTypes/DataTypeFactory.h>
|
2018-05-15 12:56:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2018-07-11 12:43:55 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int UNKNOWN_MUTATION_COMMAND;
|
2018-08-07 13:58:11 +00:00
|
|
|
extern const int MULTIPLE_ASSIGNMENTS_TO_COLUMN;
|
2018-07-11 12:43:55 +00:00
|
|
|
}
|
|
|
|
|
2023-02-27 11:27:57 +00:00
|
|
|
|
|
|
|
bool MutationCommand::isBarrierCommand() const
|
|
|
|
{
|
|
|
|
return type == RENAME_COLUMN;
|
|
|
|
}
|
|
|
|
|
2020-03-17 13:49:50 +00:00
|
|
|
std::optional<MutationCommand> MutationCommand::parse(ASTAlterCommand * command, bool parse_alter_commands)
|
2018-04-19 10:33:16 +00:00
|
|
|
{
|
2018-06-13 13:49:27 +00:00
|
|
|
if (command->type == ASTAlterCommand::DELETE)
|
2018-04-19 10:33:16 +00:00
|
|
|
{
|
2018-06-13 13:49:27 +00:00
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = DELETE;
|
|
|
|
res.predicate = command->predicate;
|
2020-11-10 10:23:46 +00:00
|
|
|
res.partition = command->partition;
|
2018-06-13 13:49:27 +00:00
|
|
|
return res;
|
2018-04-19 10:33:16 +00:00
|
|
|
}
|
2018-08-07 13:58:11 +00:00
|
|
|
else if (command->type == ASTAlterCommand::UPDATE)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = UPDATE;
|
|
|
|
res.predicate = command->predicate;
|
2020-11-10 10:23:46 +00:00
|
|
|
res.partition = command->partition;
|
2018-08-07 13:58:11 +00:00
|
|
|
for (const ASTPtr & assignment_ast : command->update_assignments->children)
|
|
|
|
{
|
2019-03-15 16:14:13 +00:00
|
|
|
const auto & assignment = assignment_ast->as<ASTAssignment &>();
|
2020-11-29 13:43:24 +00:00
|
|
|
auto insertion = res.column_to_update_expression.emplace(assignment.column_name, assignment.expression());
|
2018-08-07 13:58:11 +00:00
|
|
|
if (!insertion.second)
|
2023-01-23 21:13:58 +00:00
|
|
|
throw Exception(ErrorCodes::MULTIPLE_ASSIGNMENTS_TO_COLUMN,
|
|
|
|
"Multiple assignments in the single statement to column {}",
|
|
|
|
backQuote(assignment.column_name));
|
2018-08-07 13:58:11 +00:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2019-04-10 17:44:39 +00:00
|
|
|
else if (command->type == ASTAlterCommand::MATERIALIZE_INDEX)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MATERIALIZE_INDEX;
|
|
|
|
res.partition = command->partition;
|
|
|
|
res.predicate = nullptr;
|
2020-10-24 18:46:10 +00:00
|
|
|
res.index_name = command->index->as<ASTIdentifier &>().name();
|
2019-04-10 17:44:39 +00:00
|
|
|
return res;
|
|
|
|
}
|
2023-08-09 20:57:49 +00:00
|
|
|
else if (command->type == ASTAlterCommand::MATERIALIZE_STATISTIC)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MATERIALIZE_STATISTIC;
|
|
|
|
res.partition = command->partition;
|
|
|
|
res.predicate = nullptr;
|
|
|
|
res.statistic_name = command->statistic->as<ASTIdentifier &>().name();
|
|
|
|
return res;
|
|
|
|
}
|
2021-02-10 14:12:49 +00:00
|
|
|
else if (command->type == ASTAlterCommand::MATERIALIZE_PROJECTION)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MATERIALIZE_PROJECTION;
|
|
|
|
res.partition = command->partition;
|
|
|
|
res.predicate = nullptr;
|
|
|
|
res.projection_name = command->projection->as<ASTIdentifier &>().name();
|
|
|
|
return res;
|
|
|
|
}
|
2021-07-31 18:17:06 +00:00
|
|
|
else if (command->type == ASTAlterCommand::MATERIALIZE_COLUMN)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MATERIALIZE_COLUMN;
|
|
|
|
res.partition = command->partition;
|
|
|
|
res.column_name = getIdentifierName(command->column);
|
|
|
|
return res;
|
|
|
|
}
|
2020-03-17 13:49:50 +00:00
|
|
|
else if (parse_alter_commands && command->type == ASTAlterCommand::MODIFY_COLUMN)
|
2020-01-15 13:00:08 +00:00
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
2020-01-17 13:54:22 +00:00
|
|
|
res.type = MutationCommand::Type::READ_COLUMN;
|
2020-01-15 13:00:08 +00:00
|
|
|
const auto & ast_col_decl = command->col_decl->as<ASTColumnDeclaration &>();
|
|
|
|
res.column_name = ast_col_decl.name;
|
|
|
|
res.data_type = DataTypeFactory::instance().get(ast_col_decl.type);
|
|
|
|
return res;
|
|
|
|
}
|
2020-03-17 13:49:50 +00:00
|
|
|
else if (parse_alter_commands && command->type == ASTAlterCommand::DROP_COLUMN)
|
2020-01-15 13:00:08 +00:00
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
2020-01-17 13:54:22 +00:00
|
|
|
res.type = MutationCommand::Type::DROP_COLUMN;
|
2020-01-15 13:00:08 +00:00
|
|
|
res.column_name = getIdentifierName(command->column);
|
2020-03-17 13:49:50 +00:00
|
|
|
if (command->partition)
|
|
|
|
res.partition = command->partition;
|
|
|
|
if (command->clear_column)
|
|
|
|
res.clear = true;
|
|
|
|
|
2020-01-15 13:00:08 +00:00
|
|
|
return res;
|
|
|
|
}
|
2020-03-17 13:49:50 +00:00
|
|
|
else if (parse_alter_commands && command->type == ASTAlterCommand::DROP_INDEX)
|
2020-01-17 13:54:22 +00:00
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MutationCommand::Type::DROP_INDEX;
|
2020-10-24 18:46:10 +00:00
|
|
|
res.column_name = command->index->as<ASTIdentifier &>().name();
|
2020-03-17 13:49:50 +00:00
|
|
|
if (command->partition)
|
|
|
|
res.partition = command->partition;
|
|
|
|
if (command->clear_index)
|
|
|
|
res.clear = true;
|
|
|
|
return res;
|
2020-02-25 08:53:14 +00:00
|
|
|
}
|
2021-02-10 14:12:49 +00:00
|
|
|
else if (parse_alter_commands && command->type == ASTAlterCommand::DROP_PROJECTION)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MutationCommand::Type::DROP_PROJECTION;
|
|
|
|
res.column_name = command->projection->as<ASTIdentifier &>().name();
|
|
|
|
if (command->partition)
|
|
|
|
res.partition = command->partition;
|
|
|
|
if (command->clear_projection)
|
|
|
|
res.clear = true;
|
|
|
|
return res;
|
|
|
|
}
|
2020-03-25 18:44:08 +00:00
|
|
|
else if (parse_alter_commands && command->type == ASTAlterCommand::RENAME_COLUMN)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MutationCommand::Type::RENAME_COLUMN;
|
2020-10-24 18:46:10 +00:00
|
|
|
res.column_name = command->column->as<ASTIdentifier &>().name();
|
|
|
|
res.rename_to = command->rename_to->as<ASTIdentifier &>().name();
|
2020-03-25 18:44:08 +00:00
|
|
|
return res;
|
|
|
|
}
|
2020-01-22 13:24:20 +00:00
|
|
|
else if (command->type == ASTAlterCommand::MATERIALIZE_TTL)
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = MATERIALIZE_TTL;
|
2020-03-10 11:17:26 +00:00
|
|
|
res.partition = command->partition;
|
2020-01-17 13:54:22 +00:00
|
|
|
return res;
|
|
|
|
}
|
2022-12-22 13:31:42 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
MutationCommand res;
|
|
|
|
res.ast = command->ptr();
|
|
|
|
res.type = ALTER_WITHOUT_MUTATION;
|
|
|
|
return res;
|
|
|
|
}
|
2018-04-19 10:33:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-12-22 13:31:42 +00:00
|
|
|
std::shared_ptr<ASTExpressionList> MutationCommands::ast(bool with_pure_metadata_commands) const
|
2018-04-19 10:33:16 +00:00
|
|
|
{
|
2020-12-04 02:15:44 +00:00
|
|
|
auto res = std::make_shared<ASTExpressionList>();
|
2018-06-13 13:49:27 +00:00
|
|
|
for (const MutationCommand & command : *this)
|
2022-12-22 13:31:42 +00:00
|
|
|
{
|
|
|
|
if (command.type != MutationCommand::ALTER_WITHOUT_MUTATION || with_pure_metadata_commands)
|
|
|
|
res->children.push_back(command.ast->clone());
|
|
|
|
}
|
2018-06-13 13:49:27 +00:00
|
|
|
return res;
|
2018-04-19 10:33:16 +00:00
|
|
|
}
|
|
|
|
|
2020-11-10 10:23:46 +00:00
|
|
|
|
2022-12-22 13:31:42 +00:00
|
|
|
void MutationCommands::writeText(WriteBuffer & out, bool with_pure_metadata_commands) const
|
2018-07-11 12:43:55 +00:00
|
|
|
{
|
2020-11-09 16:05:40 +00:00
|
|
|
WriteBufferFromOwnString commands_buf;
|
2022-12-22 13:31:42 +00:00
|
|
|
formatAST(*ast(with_pure_metadata_commands), commands_buf, /* hilite = */ false, /* one_line = */ true);
|
2021-01-11 14:43:05 +00:00
|
|
|
writeEscapedString(commands_buf.str(), out);
|
2018-07-11 12:43:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MutationCommands::readText(ReadBuffer & in)
|
|
|
|
{
|
|
|
|
String commands_str;
|
2021-01-11 14:43:05 +00:00
|
|
|
readEscapedString(commands_str, in);
|
2018-07-11 12:43:55 +00:00
|
|
|
|
|
|
|
ParserAlterCommandList p_alter_commands;
|
|
|
|
auto commands_ast = parseQuery(
|
2020-04-15 20:28:05 +00:00
|
|
|
p_alter_commands, commands_str.data(), commands_str.data() + commands_str.length(), "mutation commands list", 0, DBMS_DEFAULT_MAX_PARSER_DEPTH);
|
2022-12-22 13:31:42 +00:00
|
|
|
|
2020-12-04 02:15:44 +00:00
|
|
|
for (const auto & child : commands_ast->children)
|
2018-07-11 12:43:55 +00:00
|
|
|
{
|
2020-12-04 02:15:44 +00:00
|
|
|
auto * command_ast = child->as<ASTAlterCommand>();
|
2020-01-15 13:00:08 +00:00
|
|
|
auto command = MutationCommand::parse(command_ast, true);
|
2018-07-11 12:43:55 +00:00
|
|
|
if (!command)
|
2023-01-23 21:13:58 +00:00
|
|
|
throw Exception(ErrorCodes::UNKNOWN_MUTATION_COMMAND, "Unknown mutation command type: {}", DB::toString<int>(command_ast->type));
|
2018-07-11 12:43:55 +00:00
|
|
|
push_back(std::move(*command));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-22 13:31:42 +00:00
|
|
|
std::string MutationCommands::toString() const
|
|
|
|
{
|
|
|
|
WriteBufferFromOwnString commands_buf;
|
|
|
|
formatAST(*ast(), commands_buf, /* hilite = */ false, /* one_line = */ true);
|
|
|
|
return commands_buf.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool MutationCommands::hasNonEmptyMutationCommands() const
|
|
|
|
{
|
|
|
|
for (const auto & command : *this)
|
|
|
|
{
|
|
|
|
if (command.type != MutationCommand::Type::EMPTY && command.type != MutationCommand::Type::ALTER_WITHOUT_MUTATION)
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-02-27 11:27:57 +00:00
|
|
|
bool MutationCommands::containBarrierCommand() const
|
|
|
|
{
|
|
|
|
for (const auto & command : *this)
|
|
|
|
{
|
|
|
|
if (command.isBarrierCommand())
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-15 12:56:14 +00:00
|
|
|
}
|