1#include <Parsers/CommonParsers.h>
2#include <Parsers/ExpressionElementParsers.h>
3#include <Parsers/ExpressionListParsers.h>
4#include <Parsers/ASTFunction.h>
5#include <Parsers/ASTTablesInSelectQuery.h>
6#include <Parsers/ParserSelectQuery.h>
7#include <Parsers/ParserSampleRatio.h>
8#include <Parsers/ParserTablesInSelectQuery.h>
9
10
11namespace DB
12{
13
14namespace ErrorCodes
15{
16 extern const int SYNTAX_ERROR;
17}
18
19
20bool ParserTableExpression::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
21{
22 auto res = std::make_shared<ASTTableExpression>();
23
24 if (!ParserWithOptionalAlias(std::make_unique<ParserSubquery>(), true).parse(pos, res->subquery, expected)
25 && !ParserWithOptionalAlias(std::make_unique<ParserFunction>(), true).parse(pos, res->table_function, expected)
26 && !ParserWithOptionalAlias(std::make_unique<ParserCompoundIdentifier>(), true).parse(pos, res->database_and_table_name, expected))
27 return false;
28
29 /// FINAL
30 if (ParserKeyword("FINAL").ignore(pos, expected))
31 res->final = true;
32
33 /// SAMPLE number
34 if (ParserKeyword("SAMPLE").ignore(pos, expected))
35 {
36 ParserSampleRatio ratio;
37
38 if (!ratio.parse(pos, res->sample_size, expected))
39 return false;
40
41 /// OFFSET number
42 if (ParserKeyword("OFFSET").ignore(pos, expected))
43 {
44 if (!ratio.parse(pos, res->sample_offset, expected))
45 return false;
46 }
47 }
48
49 if (res->database_and_table_name)
50 res->children.emplace_back(res->database_and_table_name);
51 if (res->table_function)
52 res->children.emplace_back(res->table_function);
53 if (res->subquery)
54 res->children.emplace_back(res->subquery);
55 if (res->sample_size)
56 res->children.emplace_back(res->sample_size);
57 if (res->sample_offset)
58 res->children.emplace_back(res->sample_offset);
59
60 node = res;
61 return true;
62}
63
64
65bool ParserArrayJoin::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
66{
67 auto res = std::make_shared<ASTArrayJoin>();
68
69 /// [LEFT] ARRAY JOIN expr list
70 Pos saved_pos = pos;
71 bool has_array_join = false;
72
73 if (ParserKeyword("LEFT ARRAY JOIN").ignore(pos, expected))
74 {
75 res->kind = ASTArrayJoin::Kind::Left;
76 has_array_join = true;
77 }
78 else
79 {
80 pos = saved_pos;
81
82 /// INNER may be specified explicitly, otherwise it is assumed as default.
83 ParserKeyword("INNER").ignore(pos, expected);
84
85 if (ParserKeyword("ARRAY JOIN").ignore(pos, expected))
86 {
87 res->kind = ASTArrayJoin::Kind::Inner;
88 has_array_join = true;
89 }
90 }
91
92 if (!has_array_join)
93 return false;
94
95 if (!ParserExpressionList(false).parse(pos, res->expression_list, expected))
96 return false;
97
98 if (res->expression_list)
99 res->children.emplace_back(res->expression_list);
100
101 node = res;
102 return true;
103}
104
105
106bool ParserTablesInSelectQueryElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
107{
108 auto res = std::make_shared<ASTTablesInSelectQueryElement>();
109
110 if (is_first)
111 {
112 if (!ParserTableExpression().parse(pos, res->table_expression, expected))
113 return false;
114 }
115 else if (ParserArrayJoin().parse(pos, res->array_join, expected))
116 {
117 }
118 else
119 {
120 auto table_join = std::make_shared<ASTTableJoin>();
121
122 if (pos->type == TokenType::Comma)
123 {
124 ++pos;
125 table_join->kind = ASTTableJoin::Kind::Comma;
126 }
127 else
128 {
129 if (ParserKeyword("GLOBAL").ignore(pos))
130 table_join->locality = ASTTableJoin::Locality::Global;
131 else if (ParserKeyword("LOCAL").ignore(pos))
132 table_join->locality = ASTTableJoin::Locality::Local;
133
134 if (ParserKeyword("ANY").ignore(pos))
135 table_join->strictness = ASTTableJoin::Strictness::Any;
136 else if (ParserKeyword("ALL").ignore(pos))
137 table_join->strictness = ASTTableJoin::Strictness::All;
138 else if (ParserKeyword("ASOF").ignore(pos))
139 table_join->strictness = ASTTableJoin::Strictness::Asof;
140 else if (ParserKeyword("SEMI").ignore(pos))
141 table_join->strictness = ASTTableJoin::Strictness::Semi;
142 else if (ParserKeyword("ANTI").ignore(pos) || ParserKeyword("ONLY").ignore(pos))
143 table_join->strictness = ASTTableJoin::Strictness::Anti;
144 else
145 table_join->strictness = ASTTableJoin::Strictness::Unspecified;
146
147 if (ParserKeyword("INNER").ignore(pos))
148 table_join->kind = ASTTableJoin::Kind::Inner;
149 else if (ParserKeyword("LEFT").ignore(pos))
150 table_join->kind = ASTTableJoin::Kind::Left;
151 else if (ParserKeyword("RIGHT").ignore(pos))
152 table_join->kind = ASTTableJoin::Kind::Right;
153 else if (ParserKeyword("FULL").ignore(pos))
154 table_join->kind = ASTTableJoin::Kind::Full;
155 else if (ParserKeyword("CROSS").ignore(pos))
156 table_join->kind = ASTTableJoin::Kind::Cross;
157 else
158 {
159 /// Use INNER by default as in another DBMS.
160 if (table_join->strictness == ASTTableJoin::Strictness::Semi ||
161 table_join->strictness == ASTTableJoin::Strictness::Anti)
162 table_join->kind = ASTTableJoin::Kind::Left;
163 else
164 table_join->kind = ASTTableJoin::Kind::Inner;
165 }
166
167 if (table_join->strictness != ASTTableJoin::Strictness::Unspecified
168 && table_join->kind == ASTTableJoin::Kind::Cross)
169 throw Exception("You must not specify ANY or ALL for CROSS JOIN.", ErrorCodes::SYNTAX_ERROR);
170
171 if ((table_join->strictness == ASTTableJoin::Strictness::Semi || table_join->strictness == ASTTableJoin::Strictness::Anti) &&
172 (table_join->kind != ASTTableJoin::Kind::Left && table_join->kind != ASTTableJoin::Kind::Right))
173 throw Exception("SEMI|ANTI JOIN should be LEFT or RIGHT.", ErrorCodes::SYNTAX_ERROR);
174
175 /// Optional OUTER keyword for outer joins.
176 if (table_join->kind == ASTTableJoin::Kind::Left
177 || table_join->kind == ASTTableJoin::Kind::Right
178 || table_join->kind == ASTTableJoin::Kind::Full)
179 {
180 ParserKeyword("OUTER").ignore(pos);
181 }
182
183 if (!ParserKeyword("JOIN").ignore(pos, expected))
184 return false;
185 }
186
187 if (!ParserTableExpression().parse(pos, res->table_expression, expected))
188 return false;
189
190 if (table_join->kind != ASTTableJoin::Kind::Comma
191 && table_join->kind != ASTTableJoin::Kind::Cross)
192 {
193 if (ParserKeyword("USING").ignore(pos, expected))
194 {
195 /// Expression for USING could be in parentheses or not.
196 bool in_parens = pos->type == TokenType::OpeningRoundBracket;
197 if (in_parens)
198 ++pos;
199
200 if (!ParserExpressionList(false).parse(pos, table_join->using_expression_list, expected))
201 return false;
202
203 if (in_parens)
204 {
205 if (pos->type != TokenType::ClosingRoundBracket)
206 return false;
207 ++pos;
208 }
209 }
210 else if (ParserKeyword("ON").ignore(pos, expected))
211 {
212 /// OR is operator with lowest priority, so start parsing from it.
213 if (!ParserLogicalOrExpression().parse(pos, table_join->on_expression, expected))
214 return false;
215 }
216 else
217 {
218 return false;
219 }
220 }
221
222 if (table_join->using_expression_list)
223 table_join->children.emplace_back(table_join->using_expression_list);
224 if (table_join->on_expression)
225 table_join->children.emplace_back(table_join->on_expression);
226
227 res->table_join = table_join;
228 }
229
230 if (res->table_expression)
231 res->children.emplace_back(res->table_expression);
232 if (res->table_join)
233 res->children.emplace_back(res->table_join);
234 if (res->array_join)
235 res->children.emplace_back(res->array_join);
236
237 node = res;
238 return true;
239}
240
241
242bool ParserTablesInSelectQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expected)
243{
244 auto res = std::make_shared<ASTTablesInSelectQuery>();
245
246 ASTPtr child;
247
248 if (ParserTablesInSelectQueryElement(true).parse(pos, child, expected))
249 res->children.emplace_back(child);
250 else
251 return false;
252
253 while (ParserTablesInSelectQueryElement(false).parse(pos, child, expected))
254 res->children.emplace_back(child);
255
256 node = res;
257 return true;
258}
259
260}
261