1use super::super::ast::{
4 FieldRef, GraphQuery, JoinCondition, JoinQuery, JoinType, QueryExpr, SelectItem, TableQuery,
5};
6use super::super::lexer::Token;
7use super::error::ParseError;
8use super::Parser;
9use crate::storage::query::sql_lowering::{filter_to_expr, projection_to_select_item};
10impl<'a> Parser<'a> {
11 pub fn parse_from_query(&mut self) -> Result<QueryExpr, ParseError> {
13 self.expect(Token::From)?;
14
15 let mut table_query = if self.check(&Token::LParen) {
24 self.advance()?; if !self.check(&Token::Select) {
28 return Err(ParseError::new(
29 "subquery in FROM must start with SELECT".to_string(),
30 self.position(),
31 ));
32 }
33 let inner = self.parse_select_query()?;
34 self.expect(Token::RParen)?;
35 let alias = if self.consume(&Token::As)?
36 || (self.check(&Token::Ident("".into())) && !self.is_join_keyword())
37 {
38 Some(self.expect_ident()?)
39 } else {
40 None
41 };
42 TableQuery::from_subquery(inner, alias)
43 } else {
44 let table = self.parse_table_source()?;
46 let alias = if self.consume(&Token::As)?
47 || (self.check(&Token::Ident("".into())) && !self.is_join_keyword())
48 {
49 Some(self.expect_ident()?)
50 } else {
51 None
52 };
53 TableQuery {
54 table,
55 source: None,
56 alias,
57 select_items: Vec::new(),
58 columns: Vec::new(),
59 where_expr: None,
60 filter: None,
61 group_by_exprs: Vec::new(),
62 group_by: Vec::new(),
63 having_expr: None,
64 having: None,
65 order_by: Vec::new(),
66 limit: None,
67 limit_param: None,
68 offset: None,
69 offset_param: None,
70 expand: None,
71 as_of: None,
72 }
73 };
74
75 if self.is_join_keyword() {
77 return self.parse_join_query(table_query);
78 }
79
80 if self.consume(&Token::Where)? {
82 let filter = self.parse_filter()?;
83 table_query.where_expr = Some(filter_to_expr(&filter));
84 table_query.filter = Some(filter);
85 }
86
87 if self.consume(&Token::Order)? {
89 self.expect(Token::By)?;
90 table_query.order_by = self.parse_order_by_list()?;
91 }
92
93 if self.consume(&Token::Limit)? {
95 table_query.limit = Some(self.parse_integer()? as u64);
96 }
97 if self.consume(&Token::Offset)? {
98 table_query.offset = Some(self.parse_integer()? as u64);
99 }
100
101 if self.consume(&Token::Return)? {
103 let (select_items, columns) = self.parse_select_items_and_projections()?;
104 table_query.select_items = select_items;
105 table_query.columns = columns;
106 }
107
108 Ok(QueryExpr::Table(table_query))
109 }
110
111 pub fn is_join_keyword(&self) -> bool {
113 matches!(
114 self.peek(),
115 Token::Join | Token::Inner | Token::Left | Token::Right | Token::Full | Token::Cross
116 )
117 }
118
119 fn parse_join_query(&mut self, left_table: TableQuery) -> Result<QueryExpr, ParseError> {
121 let join_type = if self.consume(&Token::Inner)? {
123 self.expect(Token::Join)?;
124 JoinType::Inner
125 } else if self.consume(&Token::Left)? {
126 self.consume(&Token::Outer)?;
127 self.expect(Token::Join)?;
128 JoinType::LeftOuter
129 } else if self.consume(&Token::Right)? {
130 self.consume(&Token::Outer)?;
131 self.expect(Token::Join)?;
132 JoinType::RightOuter
133 } else if self.consume(&Token::Full)? {
134 self.consume(&Token::Outer)?;
136 self.expect(Token::Join)?;
137 JoinType::FullOuter
138 } else if self.consume(&Token::Cross)? {
139 self.expect(Token::Join)?;
140 JoinType::Cross
141 } else {
142 self.expect(Token::Join)?;
143 JoinType::Inner
144 };
145
146 if self.consume(&Token::Graph)? {
147 return self.parse_graph_join_query(left_table, join_type);
148 }
149 if self.check(&Token::Path) {
150 return self.parse_path_join_query(left_table, join_type);
151 }
152 if self.check(&Token::Vector) {
153 return self.parse_vector_join_query(left_table, join_type);
154 }
155 if self.check(&Token::Hybrid) {
156 return self.parse_hybrid_join_query(left_table, join_type);
157 }
158
159 self.parse_table_join_query(left_table, join_type)
160 }
161
162 fn parse_graph_join_query(
163 &mut self,
164 left_table: TableQuery,
165 join_type: JoinType,
166 ) -> Result<QueryExpr, ParseError> {
167 let pattern = self.parse_graph_pattern()?;
169 let alias = self.parse_join_rhs_alias()?;
170
171 self.expect(Token::On)?;
173 let on = self.parse_graph_join_condition()?;
174 let (filter, order_by, limit, offset, return_items, return_) =
175 self.parse_join_post_clauses()?;
176 let graph_query = GraphQuery {
177 alias,
178 pattern,
179 filter: None,
180 return_: Vec::new(),
181 };
182
183 Ok(QueryExpr::Join(JoinQuery {
184 left: Box::new(QueryExpr::Table(left_table)),
185 right: Box::new(QueryExpr::Graph(graph_query)),
186 join_type,
187 on,
188 filter,
189 order_by,
190 limit,
191 offset,
192 return_items,
193 return_,
194 }))
195 }
196
197 fn parse_table_join_query(
198 &mut self,
199 left_table: TableQuery,
200 join_type: JoinType,
201 ) -> Result<QueryExpr, ParseError> {
202 let table = self.parse_table_source()?;
203 let alias = if self.consume(&Token::As)?
204 || (self.check(&Token::Ident("".into())) && !self.is_clause_keyword())
205 {
206 Some(self.expect_ident()?)
207 } else {
208 None
209 };
210
211 let on = if matches!(join_type, JoinType::Cross) {
214 cross_join_sentinel()
215 } else {
216 self.expect(Token::On)?;
217 self.parse_table_join_condition()?
218 };
219 let (filter, order_by, limit, offset, return_items, return_) =
220 self.parse_join_post_clauses()?;
221 let table_query = TableQuery {
222 table,
223 source: None,
224 alias,
225 select_items: Vec::new(),
226 columns: Vec::new(),
227 where_expr: None,
228 filter: None,
229 group_by_exprs: Vec::new(),
230 group_by: Vec::new(),
231 having_expr: None,
232 having: None,
233 order_by: Vec::new(),
234 limit: None,
235 limit_param: None,
236 offset: None,
237 offset_param: None,
238 expand: None,
239 as_of: None,
240 };
241
242 Ok(QueryExpr::Join(JoinQuery {
243 left: Box::new(QueryExpr::Table(left_table)),
244 right: Box::new(QueryExpr::Table(table_query)),
245 join_type,
246 on,
247 filter,
248 order_by,
249 limit,
250 offset,
251 return_items,
252 return_,
253 }))
254 }
255
256 fn parse_vector_join_query(
257 &mut self,
258 left_table: TableQuery,
259 join_type: JoinType,
260 ) -> Result<QueryExpr, ParseError> {
261 let mut right = match self.parse_vector_query()? {
262 QueryExpr::Vector(query) => query,
263 _ => unreachable!("vector parser must return QueryExpr::Vector"),
264 };
265 right.alias = self.parse_join_rhs_alias()?;
266 self.expect(Token::On)?;
267 let on = self.parse_table_join_condition()?;
268 let (filter, order_by, limit, offset, return_items, return_) =
269 self.parse_join_post_clauses()?;
270
271 Ok(QueryExpr::Join(JoinQuery {
272 left: Box::new(QueryExpr::Table(left_table)),
273 right: Box::new(QueryExpr::Vector(right)),
274 join_type,
275 on,
276 filter,
277 order_by,
278 limit,
279 offset,
280 return_items,
281 return_,
282 }))
283 }
284
285 fn parse_path_join_query(
286 &mut self,
287 left_table: TableQuery,
288 join_type: JoinType,
289 ) -> Result<QueryExpr, ParseError> {
290 let mut right = match self.parse_path_query()? {
291 QueryExpr::Path(query) => query,
292 _ => unreachable!("path parser must return QueryExpr::Path"),
293 };
294 right.alias = self.parse_join_rhs_alias()?;
295 self.expect(Token::On)?;
296 let on = self.parse_table_join_condition()?;
297 let (filter, order_by, limit, offset, return_items, return_) =
298 self.parse_join_post_clauses()?;
299
300 Ok(QueryExpr::Join(JoinQuery {
301 left: Box::new(QueryExpr::Table(left_table)),
302 right: Box::new(QueryExpr::Path(right)),
303 join_type,
304 on,
305 filter,
306 order_by,
307 limit,
308 offset,
309 return_items,
310 return_,
311 }))
312 }
313
314 fn parse_hybrid_join_query(
315 &mut self,
316 left_table: TableQuery,
317 join_type: JoinType,
318 ) -> Result<QueryExpr, ParseError> {
319 let mut right = match self.parse_hybrid_query()? {
320 QueryExpr::Hybrid(query) => query,
321 _ => unreachable!("hybrid parser must return QueryExpr::Hybrid"),
322 };
323 right.alias = self.parse_join_rhs_alias()?;
324 self.expect(Token::On)?;
325 let on = self.parse_table_join_condition()?;
326 let (filter, order_by, limit, offset, return_items, return_) =
327 self.parse_join_post_clauses()?;
328
329 Ok(QueryExpr::Join(JoinQuery {
330 left: Box::new(QueryExpr::Table(left_table)),
331 right: Box::new(QueryExpr::Hybrid(right)),
332 join_type,
333 on,
334 filter,
335 order_by,
336 limit,
337 offset,
338 return_items,
339 return_,
340 }))
341 }
342
343 fn parse_join_post_clauses(
344 &mut self,
345 ) -> Result<
346 (
347 Option<super::super::ast::Filter>,
348 Vec<super::super::ast::OrderByClause>,
349 Option<u64>,
350 Option<u64>,
351 Vec<SelectItem>,
352 Vec<super::super::ast::Projection>,
353 ),
354 ParseError,
355 > {
356 let filter = if self.consume(&Token::Where)? {
357 Some(self.parse_filter()?)
358 } else {
359 None
360 };
361
362 let order_by = if self.consume(&Token::Order)? {
363 self.expect(Token::By)?;
364 self.parse_order_by_list()?
365 } else {
366 Vec::new()
367 };
368
369 let limit = if self.consume(&Token::Limit)? {
370 Some(self.parse_integer()? as u64)
371 } else {
372 None
373 };
374
375 let offset = if self.consume(&Token::Offset)? {
376 Some(self.parse_integer()? as u64)
377 } else {
378 None
379 };
380
381 let (return_items, return_) = if self.consume(&Token::Return)? {
382 let projections = self.parse_return_list()?;
383 let items = projections
384 .iter()
385 .filter_map(projection_to_select_item)
386 .collect();
387 (items, projections)
388 } else {
389 (Vec::new(), Vec::new())
390 };
391
392 Ok((filter, order_by, limit, offset, return_items, return_))
393 }
394
395 fn parse_join_rhs_alias(&mut self) -> Result<Option<String>, ParseError> {
396 if self.consume(&Token::As)?
397 || (self.check(&Token::Ident("".into())) && !self.is_join_rhs_clause_keyword())
398 {
399 Ok(Some(self.expect_ident()?))
400 } else {
401 Ok(None)
402 }
403 }
404
405 fn is_join_rhs_clause_keyword(&self) -> bool {
406 matches!(
407 self.peek(),
408 Token::On
409 | Token::Where
410 | Token::Order
411 | Token::Limit
412 | Token::Offset
413 | Token::Return
414 | Token::Join
415 | Token::Inner
416 | Token::Left
417 | Token::Right
418 )
419 }
420
421 fn parse_table_source(&mut self) -> Result<String, ParseError> {
422 if self.consume(&Token::Star)? {
423 Ok("*".to_string())
424 } else if self.consume(&Token::All)? {
425 Ok("all".to_string())
426 } else {
427 self.expect_ident()
428 }
429 }
430
431 fn parse_graph_join_condition(&mut self) -> Result<JoinCondition, ParseError> {
433 let left_field = self.parse_field_ref()?;
434 self.expect(Token::Eq)?;
435 let right_first = self.expect_ident()?;
436 self.expect(Token::Dot)?;
437 let right_second = self.expect_ident()?;
438
439 let right_field = if right_second == "id" {
441 FieldRef::NodeId { alias: right_first }
442 } else {
443 FieldRef::NodeProperty {
444 alias: right_first,
445 property: right_second,
446 }
447 };
448
449 Ok(JoinCondition {
450 left_field,
451 right_field,
452 })
453 }
454
455 fn parse_table_join_condition(&mut self) -> Result<JoinCondition, ParseError> {
456 let left_field = self.parse_field_ref()?;
457 self.expect(Token::Eq)?;
458 let right_field = self.parse_field_ref()?;
459
460 Ok(JoinCondition {
461 left_field,
462 right_field,
463 })
464 }
465}
466
467fn cross_join_sentinel() -> JoinCondition {
472 JoinCondition {
473 left_field: FieldRef::TableColumn {
474 table: String::new(),
475 column: String::new(),
476 },
477 right_field: FieldRef::TableColumn {
478 table: String::new(),
479 column: String::new(),
480 },
481 }
482}