1 | #pragma once |
2 | |
3 | #include <Parsers/IParserBase.h> |
4 | #include <Parsers/ExpressionElementParsers.h> |
5 | #include <Parsers/ExpressionListParsers.h> |
6 | #include <Parsers/ASTNameTypePair.h> |
7 | #include <Parsers/ASTColumnDeclaration.h> |
8 | #include <Parsers/ASTIdentifier.h> |
9 | #include <Parsers/ASTLiteral.h> |
10 | #include <Parsers/CommonParsers.h> |
11 | #include <Poco/String.h> |
12 | |
13 | |
14 | namespace DB |
15 | { |
16 | |
17 | /** A nested table. For example, Nested(UInt32 CounterID, FixedString(2) UserAgentMajor) |
18 | */ |
19 | class ParserNestedTable : public IParserBase |
20 | { |
21 | protected: |
22 | const char * getName() const { return "nested table" ; } |
23 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
24 | }; |
25 | |
26 | |
27 | /** Parametric type or Storage. For example: |
28 | * FixedString(10) or |
29 | * Partitioned(Log, ChunkID) or |
30 | * Nested(UInt32 CounterID, FixedString(2) UserAgentMajor) |
31 | * Result of parsing - ASTFunction with or without parameters. |
32 | */ |
33 | class ParserIdentifierWithParameters : public IParserBase |
34 | { |
35 | protected: |
36 | const char * getName() const { return "identifier with parameters" ; } |
37 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
38 | }; |
39 | |
40 | template <typename NameParser> |
41 | class IParserNameTypePair : public IParserBase |
42 | { |
43 | protected: |
44 | const char * getName() const { return "name and type pair" ; } |
45 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
46 | }; |
47 | |
48 | /** The name and type are separated by a space. For example, URL String. */ |
49 | using ParserNameTypePair = IParserNameTypePair<ParserIdentifier>; |
50 | /** Name and type separated by a space. The name can contain a dot. For example, Hits.URL String. */ |
51 | using ParserCompoundNameTypePair = IParserNameTypePair<ParserCompoundIdentifier>; |
52 | |
53 | template <typename NameParser> |
54 | bool IParserNameTypePair<NameParser>::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
55 | { |
56 | NameParser name_parser; |
57 | ParserIdentifierWithOptionalParameters type_parser; |
58 | |
59 | ASTPtr name, type; |
60 | if (name_parser.parse(pos, name, expected) |
61 | && type_parser.parse(pos, type, expected)) |
62 | { |
63 | auto name_type_pair = std::make_shared<ASTNameTypePair>(); |
64 | tryGetIdentifierNameInto(name, name_type_pair->name); |
65 | name_type_pair->type = type; |
66 | name_type_pair->children.push_back(type); |
67 | node = name_type_pair; |
68 | return true; |
69 | } |
70 | |
71 | return false; |
72 | } |
73 | |
74 | /** List of columns. */ |
75 | class ParserNameTypePairList : public IParserBase |
76 | { |
77 | protected: |
78 | const char * getName() const { return "name and type pair list" ; } |
79 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
80 | }; |
81 | |
82 | /** List of table names. */ |
83 | class ParserNameList : public IParserBase |
84 | { |
85 | protected: |
86 | const char * getName() const { return "name list" ; } |
87 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
88 | }; |
89 | |
90 | |
91 | template <typename NameParser> |
92 | class IParserColumnDeclaration : public IParserBase |
93 | { |
94 | public: |
95 | explicit IParserColumnDeclaration(bool require_type_ = true) : require_type(require_type_) |
96 | { |
97 | } |
98 | |
99 | protected: |
100 | using ASTDeclarePtr = std::shared_ptr<ASTColumnDeclaration>; |
101 | |
102 | const char * getName() const { return "column declaration" ; } |
103 | |
104 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
105 | |
106 | bool require_type = true; |
107 | }; |
108 | |
109 | using ParserColumnDeclaration = IParserColumnDeclaration<ParserIdentifier>; |
110 | using ParserCompoundColumnDeclaration = IParserColumnDeclaration<ParserCompoundIdentifier>; |
111 | |
112 | template <typename NameParser> |
113 | bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
114 | { |
115 | NameParser name_parser; |
116 | ParserIdentifierWithOptionalParameters type_parser; |
117 | ParserKeyword s_default{"DEFAULT" }; |
118 | ParserKeyword s_materialized{"MATERIALIZED" }; |
119 | ParserKeyword s_alias{"ALIAS" }; |
120 | ParserKeyword {"COMMENT" }; |
121 | ParserKeyword s_codec{"CODEC" }; |
122 | ParserKeyword s_ttl{"TTL" }; |
123 | ParserTernaryOperatorExpression expr_parser; |
124 | ParserStringLiteral string_literal_parser; |
125 | ParserCodec codec_parser; |
126 | ParserExpression expression_parser; |
127 | |
128 | /// mandatory column name |
129 | ASTPtr name; |
130 | if (!name_parser.parse(pos, name, expected)) |
131 | return false; |
132 | |
133 | /** column name should be followed by type name if it |
134 | * is not immediately followed by {DEFAULT, MATERIALIZED, ALIAS, COMMENT} |
135 | */ |
136 | ASTPtr type; |
137 | String default_specifier; |
138 | ASTPtr default_expression; |
139 | ASTPtr ; |
140 | ASTPtr codec_expression; |
141 | ASTPtr ttl_expression; |
142 | |
143 | if (!s_default.checkWithoutMoving(pos, expected) && |
144 | !s_materialized.checkWithoutMoving(pos, expected) && |
145 | !s_alias.checkWithoutMoving(pos, expected) && |
146 | !s_comment.checkWithoutMoving(pos, expected) && |
147 | !s_codec.checkWithoutMoving(pos, expected)) |
148 | { |
149 | if (!type_parser.parse(pos, type, expected)) |
150 | return false; |
151 | } |
152 | |
153 | Pos pos_before_specifier = pos; |
154 | if (s_default.ignore(pos, expected) || s_materialized.ignore(pos, expected) || s_alias.ignore(pos, expected)) |
155 | { |
156 | default_specifier = Poco::toUpper(std::string{pos_before_specifier->begin, pos_before_specifier->end}); |
157 | |
158 | /// should be followed by an expression |
159 | if (!expr_parser.parse(pos, default_expression, expected)) |
160 | return false; |
161 | } |
162 | |
163 | if (require_type && !type && !default_expression) |
164 | return false; /// reject column name without type |
165 | |
166 | |
167 | if (s_comment.ignore(pos, expected)) |
168 | { |
169 | /// should be followed by a string literal |
170 | if (!string_literal_parser.parse(pos, comment_expression, expected)) |
171 | return false; |
172 | } |
173 | |
174 | if (s_codec.ignore(pos, expected)) |
175 | { |
176 | if (!codec_parser.parse(pos, codec_expression, expected)) |
177 | return false; |
178 | } |
179 | |
180 | if (s_ttl.ignore(pos, expected)) |
181 | { |
182 | if (!expression_parser.parse(pos, ttl_expression, expected)) |
183 | return false; |
184 | } |
185 | |
186 | const auto column_declaration = std::make_shared<ASTColumnDeclaration>(); |
187 | node = column_declaration; |
188 | tryGetIdentifierNameInto(name, column_declaration->name); |
189 | |
190 | if (type) |
191 | { |
192 | column_declaration->type = type; |
193 | column_declaration->children.push_back(std::move(type)); |
194 | } |
195 | |
196 | if (default_expression) |
197 | { |
198 | column_declaration->default_specifier = default_specifier; |
199 | column_declaration->default_expression = default_expression; |
200 | column_declaration->children.push_back(std::move(default_expression)); |
201 | } |
202 | |
203 | if (comment_expression) |
204 | { |
205 | column_declaration->comment = comment_expression; |
206 | column_declaration->children.push_back(std::move(comment_expression)); |
207 | } |
208 | |
209 | if (codec_expression) |
210 | { |
211 | column_declaration->codec = codec_expression; |
212 | column_declaration->children.push_back(std::move(codec_expression)); |
213 | } |
214 | |
215 | if (ttl_expression) |
216 | { |
217 | column_declaration->ttl = ttl_expression; |
218 | column_declaration->children.push_back(std::move(ttl_expression)); |
219 | } |
220 | |
221 | return true; |
222 | } |
223 | |
224 | class ParserColumnDeclarationList : public IParserBase |
225 | { |
226 | protected: |
227 | const char * getName() const { return "column declaration list" ; } |
228 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
229 | }; |
230 | |
231 | |
232 | /** name BY expr TYPE typename(arg1, arg2, ...) GRANULARITY value */ |
233 | class ParserIndexDeclaration : public IParserBase |
234 | { |
235 | public: |
236 | ParserIndexDeclaration() {} |
237 | |
238 | protected: |
239 | const char * getName() const override { return "index declaration" ; } |
240 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
241 | }; |
242 | |
243 | class ParserConstraintDeclaration : public IParserBase |
244 | { |
245 | protected: |
246 | const char * getName() const override { return "constraint declaration" ; } |
247 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
248 | }; |
249 | |
250 | class ParserTablePropertyDeclaration : public IParserBase |
251 | { |
252 | protected: |
253 | const char * getName() const override { return "table property (column, index, constraint) declaration" ; } |
254 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
255 | }; |
256 | |
257 | |
258 | class ParserIndexDeclarationList : public IParserBase |
259 | { |
260 | protected: |
261 | const char * getName() const override { return "index declaration list" ; } |
262 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
263 | }; |
264 | |
265 | class ParserConstraintDeclarationList : public IParserBase |
266 | { |
267 | protected: |
268 | const char * getName() const override { return "constraint declaration list" ; } |
269 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
270 | }; |
271 | |
272 | |
273 | class ParserTablePropertiesDeclarationList : public IParserBase |
274 | { |
275 | protected: |
276 | const char * getName() const override { return "columns or indices declaration list" ; } |
277 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
278 | }; |
279 | |
280 | |
281 | /** |
282 | * ENGINE = name [PARTITION BY expr] [ORDER BY expr] [PRIMARY KEY expr] [SAMPLE BY expr] [SETTINGS name = value, ...] |
283 | */ |
284 | class ParserStorage : public IParserBase |
285 | { |
286 | protected: |
287 | const char * getName() const { return "storage definition" ; } |
288 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
289 | }; |
290 | |
291 | /** Query like this: |
292 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name |
293 | * ( |
294 | * name1 type1, |
295 | * name2 type2, |
296 | * ... |
297 | * INDEX name1 expr TYPE type1(args) GRANULARITY value, |
298 | * ... |
299 | * ) ENGINE = engine |
300 | * |
301 | * Or: |
302 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name AS [db2.]name2 [ENGINE = engine] |
303 | * |
304 | * Or: |
305 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name AS ENGINE = engine SELECT ... |
306 | * |
307 | */ |
308 | class ParserCreateTableQuery : public IParserBase |
309 | { |
310 | protected: |
311 | const char * getName() const { return "CREATE TABLE or ATTACH TABLE query" ; } |
312 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
313 | }; |
314 | |
315 | /// CREATE|ATTACH LIVE VIEW [IF NOT EXISTS] [db.]name [TO [db.]name] AS SELECT ... |
316 | class ParserCreateLiveViewQuery : public IParserBase |
317 | { |
318 | protected: |
319 | const char * getName() const { return "CREATE LIVE VIEW query" ; } |
320 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
321 | }; |
322 | |
323 | /// CREATE|ATTACH DATABASE db [ENGINE = engine] |
324 | class ParserCreateDatabaseQuery : public IParserBase |
325 | { |
326 | protected: |
327 | const char * getName() const { return "CREATE DATABASE query" ; } |
328 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
329 | }; |
330 | |
331 | /// CREATE[OR REPLACE]|ATTACH [[MATERIALIZED] VIEW] | [VIEW]] [IF NOT EXISTS] [db.]name [TO [db.]name] [ENGINE = engine] [POPULATE] AS SELECT ... |
332 | class ParserCreateViewQuery : public IParserBase |
333 | { |
334 | protected: |
335 | const char * getName() const { return "CREATE VIEW query" ; } |
336 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
337 | }; |
338 | |
339 | /// Parses complete dictionary create query. Uses ParserDictionary and |
340 | /// ParserDictionaryAttributeDeclaration. Produces ASTCreateQuery. |
341 | /// CREATE DICTIONAY [IF NOT EXISTS] [db.]name (attrs) PRIMARY KEY key SOURCE(s(params)) LAYOUT(l(params)) LIFETIME([min v1 max] v2) [RANGE(min v1 max v2)] |
342 | class ParserCreateDictionaryQuery : public IParserBase |
343 | { |
344 | protected: |
345 | const char * getName() const override { return "CREATE DICTIONARY" ; } |
346 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected) override; |
347 | }; |
348 | |
349 | |
350 | /** Query like this: |
351 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name |
352 | * ( |
353 | * name1 type1, |
354 | * name2 type2, |
355 | * ... |
356 | * INDEX name1 expr TYPE type1(args) GRANULARITY value, |
357 | * ... |
358 | * ) ENGINE = engine |
359 | * |
360 | * Or: |
361 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name AS [db2.]name2 [ENGINE = engine] |
362 | * |
363 | * Or: |
364 | * CREATE|ATTACH TABLE [IF NOT EXISTS] [db.]name AS ENGINE = engine SELECT ... |
365 | * |
366 | * Or: |
367 | * CREATE|ATTACH DATABASE db [ENGINE = engine] |
368 | * |
369 | * Or: |
370 | * CREATE[OR REPLACE]|ATTACH [[MATERIALIZED] VIEW] | [VIEW]] [IF NOT EXISTS] [db.]name [TO [db.]name] [ENGINE = engine] [POPULATE] AS SELECT ... |
371 | */ |
372 | class ParserCreateQuery : public IParserBase |
373 | { |
374 | protected: |
375 | const char * getName() const { return "CREATE TABLE or ATTACH TABLE query" ; } |
376 | bool parseImpl(Pos & pos, ASTPtr & node, Expected & expected); |
377 | }; |
378 | |
379 | } |
380 | |