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
14namespace DB
15{
16
17
18bool 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
76bool 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
110bool 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
148bool 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