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