1 | #include <Parsers/ParserDictionary.h> |
2 | |
3 | #include <Parsers/ExpressionListParsers.h> |
4 | #include <Parsers/ExpressionElementParsers.h> |
5 | #include <Parsers/ASTFunctionWithKeyValueArguments.h> |
6 | #include <Parsers/ASTExpressionList.h> |
7 | #include <Parsers/ASTDictionary.h> |
8 | #include <Parsers/ASTIdentifier.h> |
9 | #include <Parsers/ASTCreateQuery.h> |
10 | #include <Parsers/ParserDictionaryAttributeDeclaration.h> |
11 | |
12 | #include <Poco/String.h> |
13 | |
14 | namespace DB |
15 | { |
16 | |
17 | |
18 | bool ParserDictionaryLifetime::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
19 | { |
20 | ParserLiteral literal_p; |
21 | ParserKeyValuePairsList key_value_pairs_p; |
22 | ASTPtr ast_lifetime; |
23 | auto res = std::make_shared<ASTDictionaryLifetime>(); |
24 | |
25 | /// simple lifetime with only maximum value e.g. LIFETIME(300) |
26 | if (literal_p.parse(pos, ast_lifetime, expected)) |
27 | { |
28 | auto literal = ast_lifetime->as<const ASTLiteral &>(); |
29 | |
30 | if (literal.value.getType() != Field::Types::UInt64) |
31 | return false; |
32 | |
33 | res->max_sec = literal.value.get<UInt64>(); |
34 | node = res; |
35 | return true; |
36 | } |
37 | |
38 | if (!key_value_pairs_p.parse(pos, ast_lifetime, expected)) |
39 | return false; |
40 | |
41 | const ASTExpressionList & expr_list = ast_lifetime->as<const ASTExpressionList &>(); |
42 | if (expr_list.children.size() != 2) |
43 | return false; |
44 | |
45 | bool initialized_max = false; |
46 | /// should contain both min and max |
47 | for (const auto & elem : expr_list.children) |
48 | { |
49 | const ASTPair & pair = elem->as<const ASTPair &>(); |
50 | const ASTLiteral * literal = dynamic_cast<const ASTLiteral *>(pair.second.get()); |
51 | if (literal == nullptr) |
52 | return false; |
53 | |
54 | if (literal->value.getType() != Field::Types::UInt64) |
55 | return false; |
56 | |
57 | if (pair.first == "min" ) |
58 | res->min_sec = literal->value.get<UInt64>(); |
59 | else if (pair.first == "max" ) |
60 | { |
61 | res->max_sec = literal->value.get<UInt64>(); |
62 | initialized_max = true; |
63 | } |
64 | else |
65 | return false; |
66 | } |
67 | |
68 | if (!initialized_max) |
69 | return false; |
70 | |
71 | node = res; |
72 | return true; |
73 | } |
74 | |
75 | |
76 | bool ParserDictionaryRange::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
77 | { |
78 | ParserKeyValuePairsList key_value_pairs_p; |
79 | ASTPtr ast_range; |
80 | if (!key_value_pairs_p.parse(pos, ast_range, expected)) |
81 | return false; |
82 | |
83 | const ASTExpressionList & expr_list = ast_range->as<const ASTExpressionList &>(); |
84 | if (expr_list.children.size() != 2) |
85 | return false; |
86 | |
87 | auto res = std::make_shared<ASTDictionaryRange>(); |
88 | for (const auto & elem : expr_list.children) |
89 | { |
90 | const ASTPair & pair = elem->as<const ASTPair &>(); |
91 | const ASTIdentifier * identifier = dynamic_cast<const ASTIdentifier *>(pair.second.get()); |
92 | if (identifier == nullptr) |
93 | return false; |
94 | |
95 | if (pair.first == "min" ) |
96 | res->min_attr_name = identifier->name; |
97 | else if (pair.first == "max" ) |
98 | res->max_attr_name = identifier->name; |
99 | else |
100 | return false; |
101 | } |
102 | |
103 | if (res->min_attr_name.empty() || res->max_attr_name.empty()) |
104 | return false; |
105 | |
106 | node = res; |
107 | return true; |
108 | } |
109 | |
110 | bool ParserDictionaryLayout::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
111 | { |
112 | ParserFunctionWithKeyValueArguments key_value_func_p; |
113 | ASTPtr ast_func; |
114 | if (!key_value_func_p.parse(pos, ast_func, expected)) |
115 | return false; |
116 | |
117 | const ASTFunctionWithKeyValueArguments & func = ast_func->as<const ASTFunctionWithKeyValueArguments &>(); |
118 | auto res = std::make_shared<ASTDictionaryLayout>(); |
119 | /// here must be exactly one argument - layout_type |
120 | if (func.children.size() > 1) |
121 | return false; |
122 | |
123 | res->layout_type = func.name; |
124 | const ASTExpressionList & type_expr_list = func.elements->as<const ASTExpressionList &>(); |
125 | |
126 | /// there are no layout with more than 1 parameter |
127 | if (type_expr_list.children.size() > 1) |
128 | return false; |
129 | |
130 | if (type_expr_list.children.size() == 1) |
131 | { |
132 | const ASTPair * pair = dynamic_cast<const ASTPair *>(type_expr_list.children.at(0).get()); |
133 | if (pair == nullptr) |
134 | return false; |
135 | |
136 | const ASTLiteral * literal = dynamic_cast<const ASTLiteral *>(pair->second.get()); |
137 | if (literal == nullptr || literal->value.getType() != Field::Types::UInt64) |
138 | return false; |
139 | res->parameter.emplace(pair->first, nullptr); |
140 | res->set(res->parameter->second, literal->clone()); |
141 | } |
142 | |
143 | node = res; |
144 | return true; |
145 | } |
146 | |
147 | |
148 | bool ParserDictionary::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) |
149 | { |
150 | ParserKeyword primary_key_keyword("PRIMARY KEY" ); |
151 | ParserKeyword source_keyword("SOURCE" ); |
152 | ParserKeyword lifetime_keyword("LIFETIME" ); |
153 | ParserKeyword range_keyword("RANGE" ); |
154 | ParserKeyword layout_keyword("LAYOUT" ); |
155 | ParserToken open(TokenType::OpeningRoundBracket); |
156 | ParserToken close(TokenType::ClosingRoundBracket); |
157 | ParserFunctionWithKeyValueArguments key_value_pairs_p; |
158 | ParserList expression_list_p(std::make_unique<ParserIdentifier>(), std::make_unique<ParserToken>(TokenType::Comma), false); |
159 | ParserDictionaryLifetime lifetime_p; |
160 | ParserDictionaryRange range_p; |
161 | ParserDictionaryLayout layout_p; |
162 | |
163 | ASTPtr primary_key; |
164 | ASTPtr ast_source; |
165 | ASTPtr ast_lifetime; |
166 | ASTPtr ast_layout; |
167 | ASTPtr ast_range; |
168 | |
169 | /// Primary is required to be the first in dictionary definition |
170 | if (primary_key_keyword.ignore(pos) && !expression_list_p.parse(pos, primary_key, expected)) |
171 | return false; |
172 | |
173 | /// Loop is used to avoid strict order of dictionary properties |
174 | while (true) |
175 | { |
176 | if (!ast_source && source_keyword.ignore(pos, expected)) |
177 | { |
178 | |
179 | if (!open.ignore(pos)) |
180 | return false; |
181 | |
182 | if (!key_value_pairs_p.parse(pos, ast_source, expected)) |
183 | return false; |
184 | |
185 | if (!close.ignore(pos)) |
186 | return false; |
187 | |
188 | continue; |
189 | } |
190 | |
191 | if (!ast_lifetime && lifetime_keyword.ignore(pos, expected)) |
192 | { |
193 | if (!open.ignore(pos)) |
194 | return false; |
195 | |
196 | if (!lifetime_p.parse(pos, ast_lifetime, expected)) |
197 | return false; |
198 | |
199 | if (!close.ignore(pos)) |
200 | return false; |
201 | |
202 | continue; |
203 | } |
204 | |
205 | if (!ast_layout && layout_keyword.ignore(pos, expected)) |
206 | { |
207 | if (!open.ignore(pos)) |
208 | return false; |
209 | |
210 | if (!layout_p.parse(pos, ast_layout, expected)) |
211 | return false; |
212 | |
213 | if (!close.ignore(pos)) |
214 | return false; |
215 | |
216 | continue; |
217 | } |
218 | |
219 | if (!ast_range && range_keyword.ignore(pos, expected)) |
220 | { |
221 | if (!open.ignore(pos)) |
222 | return false; |
223 | |
224 | if (!range_p.parse(pos, ast_range, expected)) |
225 | return false; |
226 | |
227 | if (!close.ignore(pos)) |
228 | return false; |
229 | |
230 | continue; |
231 | } |
232 | |
233 | break; |
234 | } |
235 | |
236 | auto query = std::make_shared<ASTDictionary>(); |
237 | node = query; |
238 | if (primary_key) |
239 | query->set(query->primary_key, primary_key); |
240 | |
241 | if (ast_source) |
242 | query->set(query->source, ast_source); |
243 | |
244 | if (ast_lifetime) |
245 | query->set(query->lifetime, ast_lifetime); |
246 | |
247 | if (ast_layout) |
248 | query->set(query->layout, ast_layout); |
249 | |
250 | if (ast_range) |
251 | query->set(query->range, ast_range); |
252 | |
253 | return true; |
254 | } |
255 | |
256 | } |
257 | |