aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/clickhouse/src/Storages/AlterCommands.h
blob: 3e526dcc0bb349d71bbfb07bbc62cb7a0ef11c77 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
#pragma once

#include <optional>
#include <Core/NamesAndTypes.h>
#include <Storages/IStorage_fwd.h>
#include <Storages/StorageInMemoryMetadata.h>
#include <Storages/MutationCommands.h>
#include <Storages/ColumnsDescription.h>
#include <Common/SettingsChanges.h>


namespace DB
{

class ASTAlterCommand;
class IDatabase;
using DatabasePtr = std::shared_ptr<IDatabase>;

/// Operation from the ALTER query (except for manipulation with PART/PARTITION).
/// Adding Nested columns is not expanded to add individual columns.
struct AlterCommand
{
    /// The AST of the whole command
    ASTPtr ast;

    enum Type
    {
        UNKNOWN,
        ADD_COLUMN,
        DROP_COLUMN,
        MODIFY_COLUMN,
        COMMENT_COLUMN,
        MODIFY_ORDER_BY,
        MODIFY_SAMPLE_BY,
        ADD_INDEX,
        DROP_INDEX,
        ADD_CONSTRAINT,
        DROP_CONSTRAINT,
        ADD_PROJECTION,
        DROP_PROJECTION,
        MODIFY_TTL,
        MODIFY_SETTING,
        RESET_SETTING,
        MODIFY_QUERY,
        RENAME_COLUMN,
        REMOVE_TTL,
        MODIFY_DATABASE_SETTING,
        COMMENT_TABLE,
        REMOVE_SAMPLE_BY,
    };

    /// Which property user wants to remove from column
    enum class RemoveProperty
    {
        NO_PROPERTY,
        /// Default specifiers
        DEFAULT,
        MATERIALIZED,
        ALIAS,

        /// Other properties
        COMMENT,
        CODEC,
        TTL
    };

    Type type = UNKNOWN;

    String column_name;

    /// For DROP/CLEAR COLUMN/INDEX ... IN PARTITION
    ASTPtr partition;

    /// For ADD and MODIFY, a new column type.
    DataTypePtr data_type = nullptr;

    ColumnDefaultKind default_kind{};
    ASTPtr default_expression{};

    /// For COMMENT column or table
    std::optional<String> comment;

    /// For ADD or MODIFY - after which column to add a new one. If an empty string, add to the end.
    String after_column;

    /// For ADD_COLUMN, MODIFY_COLUMN, ADD_INDEX - Add to the begin if it is true.
    bool first = false;

    /// For DROP_COLUMN, MODIFY_COLUMN, COMMENT_COLUMN, RESET_SETTING
    bool if_exists = false;

    /// For ADD_COLUMN
    bool if_not_exists = false;

    /// For MODIFY_ORDER_BY
    ASTPtr order_by = nullptr;

    /// For MODIFY_SAMPLE_BY
    ASTPtr sample_by = nullptr;

    /// For ADD INDEX
    ASTPtr index_decl = nullptr;
    String after_index_name;

    /// For ADD/DROP INDEX
    String index_name;

    // For ADD CONSTRAINT
    ASTPtr constraint_decl = nullptr;

    // For ADD/DROP CONSTRAINT
    String constraint_name;

    /// For ADD PROJECTION
    ASTPtr projection_decl = nullptr;
    String after_projection_name;

    /// For ADD/DROP PROJECTION
    String projection_name;

    /// For MODIFY TTL
    ASTPtr ttl = nullptr;

    /// indicates that this command should not be applied, for example in case of if_exists=true and column doesn't exist.
    bool ignore = false;

    /// Clear columns or index (don't drop from metadata)
    bool clear = false;

    /// For ADD and MODIFY
    ASTPtr codec = nullptr;

    /// For MODIFY SETTING
    SettingsChanges settings_changes;

    /// For RESET SETTING
    std::set<String> settings_resets;

    /// For MODIFY_QUERY
    ASTPtr select = nullptr;

    /// Target column name
    String rename_to;

    /// What to remove from column (or TTL)
    RemoveProperty to_remove = RemoveProperty::NO_PROPERTY;

    static std::optional<AlterCommand> parse(const ASTAlterCommand * command);

    void apply(StorageInMemoryMetadata & metadata, ContextPtr context) const;

    /// Check that alter command require data modification (mutation) to be
    /// executed. For example, cast from Date to UInt16 type can be executed
    /// without any data modifications. But column drop or modify from UInt16 to
    /// UInt32 require data modification.
    bool isRequireMutationStage(const StorageInMemoryMetadata & metadata) const;

    /// Checks that only settings changed by alter
    bool isSettingsAlter() const;

    /// Checks that only comment changed by alter
    bool isCommentAlter() const;

    /// Checks that any TTL changed by alter
    bool isTTLAlter(const StorageInMemoryMetadata & metadata) const;

    /// Command removing some property from column or table
    bool isRemovingProperty() const;

    /// If possible, convert alter command to mutation command. In other case
    /// return empty optional. Some storages may execute mutations after
    /// metadata changes.
    std::optional<MutationCommand> tryConvertToMutationCommand(StorageInMemoryMetadata & metadata, ContextPtr context) const;
};

class Context;

/// Vector of AlterCommand with several additional functions
class AlterCommands : public std::vector<AlterCommand>
{
private:
    bool prepared = false;

public:
    /// Validate that commands can be applied to metadata.
    /// Checks that all columns exist and dependencies between them.
    /// This check is lightweight and base only on metadata.
    /// More accurate check have to be performed with storage->checkAlterIsPossible.
    void validate(const StoragePtr & table, ContextPtr context) const;

    /// Prepare alter commands. Set ignore flag to some of them and set some
    /// parts to commands from storage's metadata (for example, absent default)
    void prepare(const StorageInMemoryMetadata & metadata);

    /// Apply all alter command in sequential order to storage metadata.
    /// Commands have to be prepared before apply.
    void apply(StorageInMemoryMetadata & metadata, ContextPtr context) const;

    /// At least one command modify settings.
    bool hasSettingsAlterCommand() const;

    /// All commands modify settings only.
    bool isSettingsAlter() const;

    /// All commands modify comments only.
    bool isCommentAlter() const;

    /// Return mutation commands which some storages may execute as part of
    /// alter. If alter can be performed as pure metadata update, than result is
    /// empty. If some TTL changes happened than, depending on materialize_ttl
    /// additional mutation command (MATERIALIZE_TTL) will be returned.
    MutationCommands getMutationCommands(StorageInMemoryMetadata metadata, bool materialize_ttl, ContextPtr context, bool with_alters=false) const;

    /// Check if commands have any inverted index
    static bool hasInvertedIndex(const StorageInMemoryMetadata & metadata);
};

}