1 | #include <Interpreters/InterpreterAlterQuery.h> |
2 | #include <Interpreters/DDLWorker.h> |
3 | #include <Interpreters/MutationsInterpreter.h> |
4 | #include <Interpreters/AddDefaultDatabaseVisitor.h> |
5 | #include <Interpreters/Context.h> |
6 | #include <Parsers/ASTAlterQuery.h> |
7 | #include <Storages/IStorage.h> |
8 | #include <Storages/AlterCommands.h> |
9 | #include <Storages/MutationCommands.h> |
10 | #include <Storages/PartitionCommands.h> |
11 | #include <Storages/LiveView/LiveViewCommands.h> |
12 | #include <Storages/LiveView/StorageLiveView.h> |
13 | #include <Common/typeid_cast.h> |
14 | |
15 | #include <algorithm> |
16 | |
17 | |
18 | namespace DB |
19 | { |
20 | |
21 | namespace ErrorCodes |
22 | { |
23 | extern const int LOGICAL_ERROR; |
24 | extern const int ILLEGAL_COLUMN; |
25 | extern const int SUPPORT_IS_DISABLED; |
26 | } |
27 | |
28 | |
29 | InterpreterAlterQuery::InterpreterAlterQuery(const ASTPtr & query_ptr_, const Context & context_) |
30 | : query_ptr(query_ptr_), context(context_) |
31 | { |
32 | } |
33 | |
34 | BlockIO InterpreterAlterQuery::execute() |
35 | { |
36 | const auto & alter = query_ptr->as<ASTAlterQuery &>(); |
37 | |
38 | if (!alter.cluster.empty()) |
39 | return executeDDLQueryOnCluster(query_ptr, context, {alter.database}); |
40 | |
41 | const String & table_name = alter.table; |
42 | String database_name = alter.database.empty() ? context.getCurrentDatabase() : alter.database; |
43 | StoragePtr table = context.getTable(database_name, table_name); |
44 | |
45 | /// Add default database to table identifiers that we can encounter in e.g. default expressions, |
46 | /// mutation expression, etc. |
47 | AddDefaultDatabaseVisitor visitor(database_name); |
48 | ASTPtr command_list_ptr = alter.command_list->ptr(); |
49 | visitor.visit(command_list_ptr); |
50 | |
51 | AlterCommands alter_commands; |
52 | PartitionCommands partition_commands; |
53 | MutationCommands mutation_commands; |
54 | LiveViewCommands live_view_commands; |
55 | for (ASTAlterCommand * command_ast : alter.command_list->commands) |
56 | { |
57 | if (auto alter_command = AlterCommand::parse(command_ast)) |
58 | alter_commands.emplace_back(std::move(*alter_command)); |
59 | else if (auto partition_command = PartitionCommand::parse(command_ast)) |
60 | { |
61 | if (partition_command->type == PartitionCommand::DROP_DETACHED_PARTITION |
62 | && !context.getSettingsRef().allow_drop_detached) |
63 | throw DB::Exception("Cannot execute query: DROP DETACHED PART is disabled " |
64 | "(see allow_drop_detached setting)" , ErrorCodes::SUPPORT_IS_DISABLED); |
65 | partition_commands.emplace_back(std::move(*partition_command)); |
66 | } |
67 | else if (auto mut_command = MutationCommand::parse(command_ast)) |
68 | mutation_commands.emplace_back(std::move(*mut_command)); |
69 | else if (auto live_view_command = LiveViewCommand::parse(command_ast)) |
70 | live_view_commands.emplace_back(std::move(*live_view_command)); |
71 | else |
72 | throw Exception("Wrong parameter type in ALTER query" , ErrorCodes::LOGICAL_ERROR); |
73 | } |
74 | |
75 | if (!mutation_commands.empty()) |
76 | { |
77 | auto table_lock_holder = table->lockStructureForShare(false /* because mutation is executed asyncronously */, context.getCurrentQueryId()); |
78 | MutationsInterpreter(table, mutation_commands, context, false).validate(table_lock_holder); |
79 | table->mutate(mutation_commands, context); |
80 | } |
81 | |
82 | if (!partition_commands.empty()) |
83 | { |
84 | partition_commands.validate(*table); |
85 | table->alterPartition(query_ptr, partition_commands, context); |
86 | } |
87 | |
88 | if (!live_view_commands.empty()) |
89 | { |
90 | live_view_commands.validate(*table); |
91 | for (const LiveViewCommand & command : live_view_commands) |
92 | { |
93 | auto live_view = std::dynamic_pointer_cast<StorageLiveView>(table); |
94 | switch (command.type) |
95 | { |
96 | case LiveViewCommand::REFRESH: |
97 | live_view->refresh(context); |
98 | break; |
99 | } |
100 | } |
101 | } |
102 | |
103 | if (!alter_commands.empty()) |
104 | { |
105 | auto table_lock_holder = table->lockAlterIntention(context.getCurrentQueryId()); |
106 | StorageInMemoryMetadata metadata = table->getInMemoryMetadata(); |
107 | alter_commands.validate(metadata, context); |
108 | alter_commands.prepare(metadata, context); |
109 | table->checkAlterIsPossible(alter_commands, context.getSettingsRef()); |
110 | table->alter(alter_commands, context, table_lock_holder); |
111 | } |
112 | |
113 | return {}; |
114 | } |
115 | |
116 | } |
117 | |