1 | #include <Common/typeid_cast.h> |
2 | #include <Parsers/ASTSetQuery.h> |
3 | #include <Parsers/ASTFunction.h> |
4 | #include <Parsers/ASTIdentifier.h> |
5 | #include <Parsers/ASTSelectQuery.h> |
6 | #include <Parsers/ASTOrderByElement.h> |
7 | #include <Parsers/ASTTablesInSelectQuery.h> |
8 | |
9 | |
10 | namespace DB |
11 | { |
12 | |
13 | namespace ErrorCodes |
14 | { |
15 | extern const int LOGICAL_ERROR; |
16 | } |
17 | |
18 | |
19 | ASTPtr ASTSelectQuery::clone() const |
20 | { |
21 | auto res = std::make_shared<ASTSelectQuery>(*this); |
22 | res->children.clear(); |
23 | res->positions.clear(); |
24 | |
25 | #define CLONE(expr) res->setExpression(expr, getExpression(expr, true)) |
26 | |
27 | /** NOTE Members must clone exactly in the same order, |
28 | * in which they were inserted into `children` in ParserSelectQuery. |
29 | * This is important because of the children's names the identifier (getTreeHash) is compiled, |
30 | * which can be used for column identifiers in the case of subqueries in the IN statement. |
31 | * For distributed query processing, in case one of the servers is localhost and the other one is not, |
32 | * localhost query is executed within the process and is cloned, |
33 | * and the request is sent to the remote server in text form via TCP. |
34 | * And if the cloning order does not match the parsing order, |
35 | * then different servers will get different identifiers. |
36 | */ |
37 | CLONE(Expression::WITH); |
38 | CLONE(Expression::SELECT); |
39 | CLONE(Expression::TABLES); |
40 | CLONE(Expression::PREWHERE); |
41 | CLONE(Expression::WHERE); |
42 | CLONE(Expression::GROUP_BY); |
43 | CLONE(Expression::HAVING); |
44 | CLONE(Expression::ORDER_BY); |
45 | CLONE(Expression::LIMIT_BY_OFFSET); |
46 | CLONE(Expression::LIMIT_BY_LENGTH); |
47 | CLONE(Expression::LIMIT_BY); |
48 | CLONE(Expression::LIMIT_OFFSET); |
49 | CLONE(Expression::LIMIT_LENGTH); |
50 | CLONE(Expression::SETTINGS); |
51 | |
52 | #undef CLONE |
53 | |
54 | return res; |
55 | } |
56 | |
57 | |
58 | void ASTSelectQuery::formatImpl(const FormatSettings & s, FormatState & state, FormatStateStacked frame) const |
59 | { |
60 | frame.current_select = this; |
61 | frame.need_parens = false; |
62 | std::string indent_str = s.one_line ? "" : std::string(4 * frame.indent, ' '); |
63 | |
64 | if (with()) |
65 | { |
66 | s.ostr << (s.hilite ? hilite_keyword : "" ) << indent_str << "WITH " << (s.hilite ? hilite_none : "" ); |
67 | s.one_line |
68 | ? with()->formatImpl(s, state, frame) |
69 | : with()->as<ASTExpressionList &>().formatImplMultiline(s, state, frame); |
70 | s.ostr << s.nl_or_ws; |
71 | } |
72 | |
73 | s.ostr << (s.hilite ? hilite_keyword : "" ) << indent_str << "SELECT " << (distinct ? "DISTINCT " : "" ) << (s.hilite ? hilite_none : "" ); |
74 | |
75 | s.one_line |
76 | ? select()->formatImpl(s, state, frame) |
77 | : select()->as<ASTExpressionList &>().formatImplMultiline(s, state, frame); |
78 | |
79 | if (tables()) |
80 | { |
81 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "FROM " << (s.hilite ? hilite_none : "" ); |
82 | tables()->formatImpl(s, state, frame); |
83 | } |
84 | |
85 | if (prewhere()) |
86 | { |
87 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "PREWHERE " << (s.hilite ? hilite_none : "" ); |
88 | prewhere()->formatImpl(s, state, frame); |
89 | } |
90 | |
91 | if (where()) |
92 | { |
93 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "WHERE " << (s.hilite ? hilite_none : "" ); |
94 | where()->formatImpl(s, state, frame); |
95 | } |
96 | |
97 | if (groupBy()) |
98 | { |
99 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "GROUP BY " << (s.hilite ? hilite_none : "" ); |
100 | s.one_line |
101 | ? groupBy()->formatImpl(s, state, frame) |
102 | : groupBy()->as<ASTExpressionList &>().formatImplMultiline(s, state, frame); |
103 | } |
104 | |
105 | if (group_by_with_rollup) |
106 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << (s.one_line ? "" : " " ) << "WITH ROLLUP" << (s.hilite ? hilite_none : "" ); |
107 | |
108 | if (group_by_with_cube) |
109 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << (s.one_line ? "" : " " ) << "WITH CUBE" << (s.hilite ? hilite_none : "" ); |
110 | |
111 | if (group_by_with_totals) |
112 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << (s.one_line ? "" : " " ) << "WITH TOTALS" << (s.hilite ? hilite_none : "" ); |
113 | |
114 | if (having()) |
115 | { |
116 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "HAVING " << (s.hilite ? hilite_none : "" ); |
117 | having()->formatImpl(s, state, frame); |
118 | } |
119 | |
120 | if (orderBy()) |
121 | { |
122 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "ORDER BY " << (s.hilite ? hilite_none : "" ); |
123 | s.one_line |
124 | ? orderBy()->formatImpl(s, state, frame) |
125 | : orderBy()->as<ASTExpressionList &>().formatImplMultiline(s, state, frame); |
126 | } |
127 | |
128 | if (limitByLength()) |
129 | { |
130 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "LIMIT " << (s.hilite ? hilite_none : "" ); |
131 | if (limitByOffset()) |
132 | { |
133 | limitByOffset()->formatImpl(s, state, frame); |
134 | s.ostr << ", " ; |
135 | } |
136 | limitByLength()->formatImpl(s, state, frame); |
137 | s.ostr << (s.hilite ? hilite_keyword : "" ) << " BY " << (s.hilite ? hilite_none : "" ); |
138 | s.one_line |
139 | ? limitBy()->formatImpl(s, state, frame) |
140 | : limitBy()->as<ASTExpressionList &>().formatImplMultiline(s, state, frame); |
141 | } |
142 | |
143 | if (limitLength()) |
144 | { |
145 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "LIMIT " << (s.hilite ? hilite_none : "" ); |
146 | if (limitOffset()) |
147 | { |
148 | limitOffset()->formatImpl(s, state, frame); |
149 | s.ostr << ", " ; |
150 | } |
151 | limitLength()->formatImpl(s, state, frame); |
152 | if (limit_with_ties) |
153 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << " WITH TIES" << (s.hilite ? hilite_none : "" ); |
154 | } |
155 | |
156 | if (settings()) |
157 | { |
158 | s.ostr << (s.hilite ? hilite_keyword : "" ) << s.nl_or_ws << indent_str << "SETTINGS " << (s.hilite ? hilite_none : "" ); |
159 | settings()->formatImpl(s, state, frame); |
160 | } |
161 | } |
162 | |
163 | |
164 | /// Compatibility functions. TODO Remove. |
165 | |
166 | |
167 | static const ASTTableExpression * getFirstTableExpression(const ASTSelectQuery & select) |
168 | { |
169 | if (!select.tables()) |
170 | return {}; |
171 | |
172 | const auto & tables_in_select_query = select.tables()->as<ASTTablesInSelectQuery &>(); |
173 | if (tables_in_select_query.children.empty()) |
174 | return {}; |
175 | |
176 | const auto & tables_element = tables_in_select_query.children[0]->as<ASTTablesInSelectQueryElement &>(); |
177 | if (!tables_element.table_expression) |
178 | return {}; |
179 | |
180 | return tables_element.table_expression->as<ASTTableExpression>(); |
181 | } |
182 | |
183 | static ASTTableExpression * getFirstTableExpression(ASTSelectQuery & select) |
184 | { |
185 | if (!select.tables()) |
186 | return {}; |
187 | |
188 | auto & tables_in_select_query = select.tables()->as<ASTTablesInSelectQuery &>(); |
189 | if (tables_in_select_query.children.empty()) |
190 | return {}; |
191 | |
192 | auto & tables_element = tables_in_select_query.children[0]->as<ASTTablesInSelectQueryElement &>(); |
193 | if (!tables_element.table_expression) |
194 | return {}; |
195 | |
196 | return tables_element.table_expression->as<ASTTableExpression>(); |
197 | } |
198 | |
199 | static const ASTArrayJoin * getFirstArrayJoin(const ASTSelectQuery & select) |
200 | { |
201 | if (!select.tables()) |
202 | return {}; |
203 | |
204 | const auto & tables_in_select_query = select.tables()->as<ASTTablesInSelectQuery &>(); |
205 | if (tables_in_select_query.children.empty()) |
206 | return {}; |
207 | |
208 | const ASTArrayJoin * array_join = nullptr; |
209 | for (const auto & child : tables_in_select_query.children) |
210 | { |
211 | const auto & tables_element = child->as<ASTTablesInSelectQueryElement &>(); |
212 | if (tables_element.array_join) |
213 | { |
214 | if (!array_join) |
215 | array_join = tables_element.array_join->as<ASTArrayJoin>(); |
216 | else |
217 | throw Exception("Support for more than one ARRAY JOIN in query is not implemented" , ErrorCodes::NOT_IMPLEMENTED); |
218 | } |
219 | } |
220 | |
221 | return array_join; |
222 | } |
223 | |
224 | static const ASTTablesInSelectQueryElement * getFirstTableJoin(const ASTSelectQuery & select) |
225 | { |
226 | if (!select.tables()) |
227 | return nullptr; |
228 | |
229 | const auto & tables_in_select_query = select.tables()->as<ASTTablesInSelectQuery &>(); |
230 | if (tables_in_select_query.children.empty()) |
231 | return nullptr; |
232 | |
233 | const ASTTablesInSelectQueryElement * joined_table = nullptr; |
234 | for (const auto & child : tables_in_select_query.children) |
235 | { |
236 | const auto & tables_element = child->as<ASTTablesInSelectQueryElement &>(); |
237 | if (tables_element.table_join) |
238 | { |
239 | if (!joined_table) |
240 | joined_table = &tables_element; |
241 | else |
242 | throw Exception("Multiple JOIN does not support the query." , ErrorCodes::NOT_IMPLEMENTED); |
243 | } |
244 | } |
245 | |
246 | return joined_table; |
247 | } |
248 | |
249 | |
250 | ASTPtr ASTSelectQuery::sample_size() const |
251 | { |
252 | const ASTTableExpression * table_expression = getFirstTableExpression(*this); |
253 | if (!table_expression) |
254 | return {}; |
255 | |
256 | return table_expression->sample_size; |
257 | } |
258 | |
259 | |
260 | ASTPtr ASTSelectQuery::sample_offset() const |
261 | { |
262 | const ASTTableExpression * table_expression = getFirstTableExpression(*this); |
263 | if (!table_expression) |
264 | return {}; |
265 | |
266 | return table_expression->sample_offset; |
267 | } |
268 | |
269 | |
270 | bool ASTSelectQuery::final() const |
271 | { |
272 | const ASTTableExpression * table_expression = getFirstTableExpression(*this); |
273 | if (!table_expression) |
274 | return {}; |
275 | |
276 | return table_expression->final; |
277 | } |
278 | |
279 | bool ASTSelectQuery::withFill() const |
280 | { |
281 | if (!orderBy()) |
282 | return false; |
283 | |
284 | for (const auto & order_expression_element : orderBy()->children) |
285 | if (order_expression_element->as<ASTOrderByElement &>().with_fill) |
286 | return true; |
287 | |
288 | return false; |
289 | } |
290 | |
291 | |
292 | ASTPtr ASTSelectQuery::array_join_expression_list(bool & is_left) const |
293 | { |
294 | const ASTArrayJoin * array_join = getFirstArrayJoin(*this); |
295 | if (!array_join) |
296 | return {}; |
297 | |
298 | is_left = (array_join->kind == ASTArrayJoin::Kind::Left); |
299 | return array_join->expression_list; |
300 | } |
301 | |
302 | |
303 | ASTPtr ASTSelectQuery::array_join_expression_list() const |
304 | { |
305 | bool is_left; |
306 | return array_join_expression_list(is_left); |
307 | } |
308 | |
309 | |
310 | const ASTTablesInSelectQueryElement * ASTSelectQuery::join() const |
311 | { |
312 | return getFirstTableJoin(*this); |
313 | } |
314 | |
315 | static String getTableExpressionAlias(const ASTTableExpression * table_expression) |
316 | { |
317 | if (table_expression->subquery) |
318 | return table_expression->subquery->tryGetAlias(); |
319 | else if (table_expression->table_function) |
320 | return table_expression->table_function->tryGetAlias(); |
321 | else if (table_expression->database_and_table_name) |
322 | return table_expression->database_and_table_name->tryGetAlias(); |
323 | |
324 | return String(); |
325 | } |
326 | |
327 | void ASTSelectQuery::replaceDatabaseAndTable(const String & database_name, const String & table_name) |
328 | { |
329 | ASTTableExpression * table_expression = getFirstTableExpression(*this); |
330 | |
331 | if (!table_expression) |
332 | { |
333 | setExpression(Expression::TABLES, std::make_shared<ASTTablesInSelectQuery>()); |
334 | auto element = std::make_shared<ASTTablesInSelectQueryElement>(); |
335 | auto table_expr = std::make_shared<ASTTableExpression>(); |
336 | element->table_expression = table_expr; |
337 | element->children.emplace_back(table_expr); |
338 | tables()->children.emplace_back(element); |
339 | table_expression = table_expr.get(); |
340 | } |
341 | |
342 | String table_alias = getTableExpressionAlias(table_expression); |
343 | table_expression->database_and_table_name = createTableIdentifier(database_name, table_name); |
344 | |
345 | if (!table_alias.empty()) |
346 | table_expression->database_and_table_name->setAlias(table_alias); |
347 | } |
348 | |
349 | |
350 | void ASTSelectQuery::addTableFunction(ASTPtr & table_function_ptr) |
351 | { |
352 | ASTTableExpression * table_expression = getFirstTableExpression(*this); |
353 | |
354 | if (!table_expression) |
355 | { |
356 | setExpression(Expression::TABLES, std::make_shared<ASTTablesInSelectQuery>()); |
357 | auto element = std::make_shared<ASTTablesInSelectQueryElement>(); |
358 | auto table_expr = std::make_shared<ASTTableExpression>(); |
359 | element->table_expression = table_expr; |
360 | element->children.emplace_back(table_expr); |
361 | tables()->children.emplace_back(element); |
362 | table_expression = table_expr.get(); |
363 | } |
364 | |
365 | String table_alias = getTableExpressionAlias(table_expression); |
366 | /// Maybe need to modify the alias, so we should clone new table_function node |
367 | table_expression->table_function = table_function_ptr->clone(); |
368 | table_expression->database_and_table_name = nullptr; |
369 | |
370 | if (table_alias.empty()) |
371 | table_expression->table_function->setAlias(table_alias); |
372 | } |
373 | |
374 | void ASTSelectQuery::setExpression(Expression expr, ASTPtr && ast) |
375 | { |
376 | if (ast) |
377 | { |
378 | auto it = positions.find(expr); |
379 | if (it == positions.end()) |
380 | { |
381 | positions[expr] = children.size(); |
382 | children.emplace_back(ast); |
383 | } |
384 | else |
385 | children[it->second] = ast; |
386 | } |
387 | else if (positions.count(expr)) |
388 | { |
389 | size_t pos = positions[expr]; |
390 | children.erase(children.begin() + pos); |
391 | positions.erase(expr); |
392 | for (auto & pr : positions) |
393 | if (pr.second > pos) |
394 | --pr.second; |
395 | } |
396 | } |
397 | |
398 | ASTPtr & ASTSelectQuery::getExpression(Expression expr) |
399 | { |
400 | if (!positions.count(expr)) |
401 | throw Exception("Get expression before set" , ErrorCodes::LOGICAL_ERROR); |
402 | return children[positions[expr]]; |
403 | } |
404 | |
405 | } |
406 | |