1#include <Storages/MutationCommands.h>
2#include <IO/Operators.h>
3#include <Parsers/formatAST.h>
4#include <Parsers/ExpressionListParsers.h>
5#include <Parsers/ParserAlterQuery.h>
6#include <Parsers/parseQuery.h>
7#include <Parsers/ASTAssignment.h>
8#include <Parsers/ASTIdentifier.h>
9#include <Common/typeid_cast.h>
10#include <Common/quoteString.h>
11
12
13namespace DB
14{
15
16namespace ErrorCodes
17{
18 extern const int UNKNOWN_MUTATION_COMMAND;
19 extern const int MULTIPLE_ASSIGNMENTS_TO_COLUMN;
20}
21
22std::optional<MutationCommand> MutationCommand::parse(ASTAlterCommand * command)
23{
24 if (command->type == ASTAlterCommand::DELETE)
25 {
26 MutationCommand res;
27 res.ast = command->ptr();
28 res.type = DELETE;
29 res.predicate = command->predicate;
30 return res;
31 }
32 else if (command->type == ASTAlterCommand::UPDATE)
33 {
34 MutationCommand res;
35 res.ast = command->ptr();
36 res.type = UPDATE;
37 res.predicate = command->predicate;
38 for (const ASTPtr & assignment_ast : command->update_assignments->children)
39 {
40 const auto & assignment = assignment_ast->as<ASTAssignment &>();
41 auto insertion = res.column_to_update_expression.emplace(assignment.column_name, assignment.expression);
42 if (!insertion.second)
43 throw Exception("Multiple assignments in the single statement to column " + backQuote(assignment.column_name),
44 ErrorCodes::MULTIPLE_ASSIGNMENTS_TO_COLUMN);
45 }
46 return res;
47 }
48 else if (command->type == ASTAlterCommand::MATERIALIZE_INDEX)
49 {
50 MutationCommand res;
51 res.ast = command->ptr();
52 res.type = MATERIALIZE_INDEX;
53 res.partition = command->partition;
54 res.predicate = nullptr;
55 res.index_name = command->index->as<ASTIdentifier &>().name;
56 return res;
57 }
58 else
59 return {};
60}
61
62
63std::shared_ptr<ASTAlterCommandList> MutationCommands::ast() const
64{
65 auto res = std::make_shared<ASTAlterCommandList>();
66 for (const MutationCommand & command : *this)
67 res->add(command.ast->clone());
68 return res;
69}
70
71void MutationCommands::writeText(WriteBuffer & out) const
72{
73 std::stringstream commands_ss;
74 formatAST(*ast(), commands_ss, /* hilite = */ false, /* one_line = */ true);
75 out << escape << commands_ss.str();
76}
77
78void MutationCommands::readText(ReadBuffer & in)
79{
80 String commands_str;
81 in >> escape >> commands_str;
82
83 ParserAlterCommandList p_alter_commands;
84 auto commands_ast = parseQuery(
85 p_alter_commands, commands_str.data(), commands_str.data() + commands_str.length(), "mutation commands list", 0);
86 for (ASTAlterCommand * command_ast : commands_ast->as<ASTAlterCommandList &>().commands)
87 {
88 auto command = MutationCommand::parse(command_ast);
89 if (!command)
90 throw Exception("Unknown mutation command type: " + DB::toString<int>(command_ast->type), ErrorCodes::UNKNOWN_MUTATION_COMMAND);
91 push_back(std::move(*command));
92 }
93}
94
95}
96