1use crate::ast::*;
2use crate::lexer::lex;
3use crate::token::Token;
4
5const MAX_NESTING_DEPTH: usize = 64;
9
10#[derive(Debug)]
12pub enum ParseError {
13 Lex { message: String, position: usize },
15 UnexpectedToken { expected: String, got: String },
17 NestingDepthExceeded { max: usize },
19 Unsupported { feature: String },
21 Syntax { message: String },
23}
24
25impl ParseError {
26 pub fn message(&self) -> String {
28 self.to_string()
29 }
30}
31
32impl std::fmt::Display for ParseError {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Self::Lex { message, position } => write!(f, "at position {position}: {message}"),
36 Self::UnexpectedToken { expected, got } => {
37 write!(f, "expected {expected}, got {got}")
38 }
39 Self::NestingDepthExceeded { max } => {
40 write!(f, "query nesting depth exceeds maximum of {max}")
41 }
42 Self::Unsupported { feature } => write!(f, "{feature}"),
43 Self::Syntax { message } => write!(f, "{message}"),
44 }
45 }
46}
47
48impl std::error::Error for ParseError {}
49
50fn token_to_scalar_fn(tok: &Token) -> ScalarFn {
51 match tok {
52 Token::Upper => ScalarFn::Upper,
53 Token::Lower => ScalarFn::Lower,
54 Token::Length => ScalarFn::Length,
55 Token::Trim => ScalarFn::Trim,
56 Token::Substring => ScalarFn::Substring,
57 Token::Concat => ScalarFn::Concat,
58 Token::Abs => ScalarFn::Abs,
59 Token::Round => ScalarFn::Round,
60 Token::Ceil => ScalarFn::Ceil,
61 Token::Floor => ScalarFn::Floor,
62 Token::Sqrt => ScalarFn::Sqrt,
63 Token::Pow => ScalarFn::Pow,
64 Token::Now => ScalarFn::Now,
65 Token::Extract => ScalarFn::Extract,
66 Token::DateAdd => ScalarFn::DateAdd,
67 Token::DateDiff => ScalarFn::DateDiff,
68 _ => unreachable!(),
69 }
70}
71
72struct Parser {
73 tokens: Vec<Token>,
74 pos: usize,
75 depth: usize,
76}
77
78pub fn parse(input: &str) -> Result<Statement, ParseError> {
100 let tokens = lex(input).map_err(|e| ParseError::Lex {
101 message: e.message,
102 position: e.position,
103 })?;
104 let mut parser = Parser {
105 tokens,
106 pos: 0,
107 depth: 0,
108 };
109 let stmt = parser.parse_statement()?;
110 if !matches!(parser.peek(), Token::Eof) {
116 return Err(ParseError::Syntax {
117 message: format!(
118 "unexpected trailing token: {}",
119 parser.peek().display_name()
120 ),
121 });
122 }
123 Ok(stmt)
124}
125
126fn substitute_projection_aliases(expr: Expr, fields: &[ProjectionField]) -> Expr {
131 match expr {
132 Expr::Field(ref name) => {
133 for f in fields {
134 if f.alias.as_deref() == Some(name.as_str()) {
135 return f.expr.clone();
136 }
137 }
138 expr
139 }
140 Expr::BinaryOp(l, op, r) => Expr::BinaryOp(
141 Box::new(substitute_projection_aliases(*l, fields)),
142 op,
143 Box::new(substitute_projection_aliases(*r, fields)),
144 ),
145 Expr::UnaryOp(op, inner) => {
146 Expr::UnaryOp(op, Box::new(substitute_projection_aliases(*inner, fields)))
147 }
148 Expr::Coalesce(l, r) => Expr::Coalesce(
149 Box::new(substitute_projection_aliases(*l, fields)),
150 Box::new(substitute_projection_aliases(*r, fields)),
151 ),
152 Expr::InList {
153 expr: e,
154 list,
155 negated,
156 } => Expr::InList {
157 expr: Box::new(substitute_projection_aliases(*e, fields)),
158 list: list
159 .into_iter()
160 .map(|i| substitute_projection_aliases(i, fields))
161 .collect(),
162 negated,
163 },
164 Expr::ScalarFunc(f, args) => Expr::ScalarFunc(
165 f,
166 args.into_iter()
167 .map(|a| substitute_projection_aliases(a, fields))
168 .collect(),
169 ),
170 other => other,
171 }
172}
173
174impl Parser {
175 fn peek(&self) -> &Token {
176 &self.tokens[self.pos]
177 }
178
179 fn advance(&mut self) -> Token {
180 let t = self.tokens[self.pos].clone();
181 self.pos += 1;
182 t
183 }
184
185 fn expect(&mut self, expected: &Token) -> Result<(), ParseError> {
186 let t = self.advance();
187 if &t == expected {
188 Ok(())
189 } else {
190 Err(ParseError::UnexpectedToken {
191 expected: expected.display_name(),
192 got: t.display_name(),
193 })
194 }
195 }
196
197 fn unexpected(&self, expected: &str, got: &Token) -> ParseError {
199 ParseError::UnexpectedToken {
200 expected: expected.into(),
201 got: got.display_name(),
202 }
203 }
204
205 fn parse_statement(&mut self) -> Result<Statement, ParseError> {
206 self.depth += 1;
207 if self.depth > MAX_NESTING_DEPTH {
208 self.depth -= 1;
209 return Err(ParseError::NestingDepthExceeded {
210 max: MAX_NESTING_DEPTH,
211 });
212 }
213 if matches!(self.peek(), Token::Explain) {
214 self.advance();
215 let inner = self.parse_statement()?;
216 self.depth -= 1;
217 return Ok(Statement::Explain(Box::new(inner)));
218 }
219 let stmt = match self.peek() {
220 Token::Insert => self.parse_insert(),
221 Token::Upsert => self.parse_upsert(),
222 Token::Type => self.parse_create_type(),
223 Token::Alter => self.parse_alter_table(),
224 Token::Drop => self.parse_drop_or_drop_view(),
225 Token::Materialized => self.parse_create_view(),
226 Token::Refresh => self.parse_refresh_view(),
227 Token::Count | Token::Avg | Token::Sum | Token::Min | Token::Max => {
228 self.parse_aggregate_query()
229 }
230 Token::Ident(_) => self.parse_query_or_mutation(),
231 _ => Err(self.unexpected("statement", self.peek())),
232 }?;
233 let result = self.maybe_parse_union(stmt);
235 self.depth -= 1;
236 result
237 }
238
239 fn parse_query_or_mutation(&mut self) -> Result<Statement, ParseError> {
240 let source = match self.advance() {
241 Token::Ident(name) => name,
242 t => {
243 return Err(ParseError::UnexpectedToken {
244 expected: "type name".into(),
245 got: t.display_name(),
246 })
247 }
248 };
249 let alias = self.try_parse_alias();
250 let joins = self.parse_joins()?;
251
252 let mut filter = None;
256 let mut order = None;
257 let mut limit = None;
258 let mut offset = None;
259 let mut projection = None;
260 let mut distinct = false;
261 let mut group_by = None;
262
263 loop {
264 match self.peek() {
265 Token::Distinct => {
266 self.advance();
267 distinct = true;
268 }
269 Token::Group => {
270 self.advance();
271 group_by = Some(self.parse_group_by()?);
272 }
273 Token::Filter => {
274 self.advance();
275 filter = Some(self.parse_expr()?);
276 }
277 Token::Order => {
278 self.advance();
279 order = Some(self.parse_order()?);
280 }
281 Token::Limit => {
282 self.advance();
283 limit = Some(self.parse_expr()?);
284 }
285 Token::Offset => {
286 self.advance();
287 offset = Some(self.parse_expr()?);
288 }
289 Token::LBrace => {
290 projection = Some(self.parse_projection()?);
291 }
292 Token::Having => {
293 self.advance();
295 let having_expr = self.parse_expr()?;
296 let group = group_by.as_mut().ok_or_else(|| ParseError::Syntax {
297 message: "having without group by".into(),
298 })?;
299 let rewritten = match projection.as_ref() {
300 Some(fields) => substitute_projection_aliases(having_expr, fields),
301 None => having_expr,
302 };
303 group.having = Some(match group.having.take() {
304 Some(existing) => {
305 Expr::BinaryOp(Box::new(existing), BinOp::And, Box::new(rewritten))
306 }
307 None => rewritten,
308 });
309 }
310 Token::Update => {
311 if !joins.is_empty() {
312 return Err(ParseError::Unsupported {
313 feature: "update on a joined query is not supported".into(),
314 });
315 }
316 self.advance();
317 let assignments = self.parse_assignments()?;
318 return Ok(Statement::UpdateQuery(UpdateExpr {
319 source,
320 filter,
321 assignments,
322 }));
323 }
324 Token::Delete => {
325 if !joins.is_empty() {
326 return Err(ParseError::Unsupported {
327 feature: "delete on a joined query is not supported".into(),
328 });
329 }
330 self.advance();
331 return Ok(Statement::DeleteQuery(DeleteExpr { source, filter }));
332 }
333 _ => break,
334 }
335 }
336
337 Ok(Statement::Query(QueryExpr {
338 source,
339 alias,
340 joins,
341 filter,
342 order,
343 limit,
344 offset,
345 projection,
346 aggregation: None,
347 distinct,
348 group_by,
349 }))
350 }
351
352 fn parse_query_tail(&mut self, source: String) -> Result<QueryExpr, ParseError> {
358 let alias = self.try_parse_alias();
359 let joins = self.parse_joins()?;
360 let mut filter = None;
361 let mut order = None;
362 let mut limit = None;
363 let mut offset = None;
364 let mut projection = None;
365 let mut distinct = false;
366 let mut group_by = None;
367
368 loop {
369 match self.peek() {
370 Token::Distinct => {
371 self.advance();
372 distinct = true;
373 }
374 Token::Group => {
375 self.advance();
376 group_by = Some(self.parse_group_by()?);
377 }
378 Token::Filter => {
379 self.advance();
380 filter = Some(self.parse_expr()?);
381 }
382 Token::Order => {
383 self.advance();
384 order = Some(self.parse_order()?);
385 }
386 Token::Limit => {
387 self.advance();
388 limit = Some(self.parse_expr()?);
389 }
390 Token::Offset => {
391 self.advance();
392 offset = Some(self.parse_expr()?);
393 }
394 Token::LBrace => {
395 projection = Some(self.parse_projection()?);
396 }
397 Token::Having => {
398 self.advance();
404 let having_expr = self.parse_expr()?;
405 let group = group_by.as_mut().ok_or_else(|| ParseError::Syntax {
406 message: "having without group by".into(),
407 })?;
408 let rewritten = match projection.as_ref() {
409 Some(fields) => substitute_projection_aliases(having_expr, fields),
410 None => having_expr,
411 };
412 group.having = Some(match group.having.take() {
413 Some(existing) => {
414 Expr::BinaryOp(Box::new(existing), BinOp::And, Box::new(rewritten))
415 }
416 None => rewritten,
417 });
418 }
419 _ => break,
420 }
421 }
422
423 Ok(QueryExpr {
424 source,
425 alias,
426 joins,
427 filter,
428 order,
429 limit,
430 offset,
431 projection,
432 aggregation: None,
433 distinct,
434 group_by,
435 })
436 }
437
438 fn try_parse_alias(&mut self) -> Option<String> {
442 if *self.peek() == Token::As {
443 self.advance();
444 if let Token::Ident(name) = self.peek().clone() {
445 self.advance();
446 return Some(name);
447 }
448 }
449 None
450 }
451
452 fn parse_joins(&mut self) -> Result<Vec<JoinClause>, ParseError> {
459 let mut joins = Vec::new();
460 loop {
461 let kind = match self.peek() {
462 Token::Join => {
463 self.advance();
464 JoinKind::Inner
465 }
466 Token::Inner => {
467 self.advance();
468 self.expect(&Token::Join)?;
469 JoinKind::Inner
470 }
471 Token::LeftKw => {
472 self.advance();
473 if *self.peek() == Token::Outer {
474 self.advance();
475 }
476 self.expect(&Token::Join)?;
477 JoinKind::LeftOuter
478 }
479 Token::RightKw => {
480 self.advance();
481 if *self.peek() == Token::Outer {
482 self.advance();
483 }
484 self.expect(&Token::Join)?;
485 JoinKind::RightOuter
486 }
487 Token::Cross => {
488 self.advance();
489 self.expect(&Token::Join)?;
490 JoinKind::Cross
491 }
492 _ => break,
493 };
494
495 let source = match self.advance() {
496 Token::Ident(name) => name,
497 t => {
498 return Err(ParseError::UnexpectedToken {
499 expected: "type name after join".into(),
500 got: t.display_name(),
501 });
502 }
503 };
504 let alias = self.try_parse_alias();
505 let on = if kind == JoinKind::Cross {
506 None
507 } else if *self.peek() == Token::On {
508 self.advance();
509 Some(self.parse_expr()?)
510 } else {
511 return Err(ParseError::Syntax {
512 message: format!("expected `on <expr>` after join {source}"),
513 });
514 };
515
516 joins.push(JoinClause {
517 kind,
518 source,
519 alias,
520 on,
521 });
522 }
523 Ok(joins)
524 }
525
526 fn parse_insert(&mut self) -> Result<Statement, ParseError> {
527 self.expect(&Token::Insert)?;
528 let target = match self.advance() {
529 Token::Ident(name) => name,
530 t => {
531 return Err(ParseError::UnexpectedToken {
532 expected: "type name".into(),
533 got: t.display_name(),
534 })
535 }
536 };
537 let assignments = self.parse_assignments()?;
538 Ok(Statement::Insert(InsertExpr {
539 target,
540 assignments,
541 }))
542 }
543
544 fn parse_upsert(&mut self) -> Result<Statement, ParseError> {
546 self.expect(&Token::Upsert)?;
547 let target = match self.advance() {
548 Token::Ident(name) => name,
549 t => {
550 return Err(ParseError::UnexpectedToken {
551 expected: "type name".into(),
552 got: t.display_name(),
553 })
554 }
555 };
556 self.expect(&Token::On)?;
557 let key_column = match self.advance() {
558 Token::DotIdent(name) => name,
559 t => {
560 return Err(ParseError::UnexpectedToken {
561 expected: ".key_column".into(),
562 got: t.display_name(),
563 })
564 }
565 };
566 let assignments = self.parse_assignments()?;
567 let on_conflict = if *self.peek() == Token::On {
568 self.advance(); self.expect(&Token::Conflict)?;
570 self.parse_assignments()?
571 } else {
572 Vec::new()
573 };
574 Ok(Statement::Upsert(UpsertExpr {
575 target,
576 key_column,
577 assignments,
578 on_conflict,
579 }))
580 }
581
582 fn parse_assignments(&mut self) -> Result<Vec<Assignment>, ParseError> {
583 self.expect(&Token::LBrace)?;
584 let mut assignments = Vec::new();
585 while !matches!(self.peek(), Token::RBrace | Token::Eof) {
586 let field = match self.advance() {
587 Token::Ident(name) => name,
588 t => {
589 return Err(ParseError::UnexpectedToken {
590 expected: "field name".into(),
591 got: t.display_name(),
592 })
593 }
594 };
595 self.expect(&Token::Assign)?;
596 let value = self.parse_expr()?;
597 assignments.push(Assignment { field, value });
598 if *self.peek() == Token::Comma {
599 self.advance();
600 }
601 }
602 self.expect(&Token::RBrace)?;
603 Ok(assignments)
604 }
605
606 fn parse_projection(&mut self) -> Result<Vec<ProjectionField>, ParseError> {
607 self.expect(&Token::LBrace)?;
608 let mut fields = Vec::new();
609 while !matches!(self.peek(), Token::RBrace | Token::Eof) {
610 let first = self.advance();
611 if *self.peek() == Token::Colon {
612 self.advance();
614 let alias = match first {
615 Token::Ident(name) => name,
616 _ => {
617 return Err(ParseError::Syntax {
618 message: "expected alias name".into(),
619 })
620 }
621 };
622 let expr = self.parse_expr()?;
623 fields.push(ProjectionField {
624 alias: Some(alias),
625 expr,
626 });
627 } else {
628 let expr = match first {
629 Token::Ident(name) => {
633 if let Token::DotIdent(field) = self.peek().clone() {
634 self.advance();
635 Expr::QualifiedField {
636 qualifier: name,
637 field,
638 }
639 } else {
640 Expr::Field(name)
641 }
642 }
643 Token::DotIdent(name) => Expr::Field(name),
644 Token::RowNumber | Token::Rank | Token::DenseRank => {
645 let wfunc = match first {
646 Token::RowNumber => WindowFunc::RowNumber,
647 Token::Rank => WindowFunc::Rank,
648 Token::DenseRank => WindowFunc::DenseRank,
649 _ => {
650 return Err(ParseError::Syntax {
651 message: "unexpected window function token".into(),
652 })
653 }
654 };
655 self.expect(&Token::LParen)?;
656 self.expect(&Token::RParen)?;
657 let (partition_by, order_by) = self.parse_over_clause()?;
658 Expr::Window {
659 function: wfunc,
660 args: vec![],
661 partition_by,
662 order_by,
663 }
664 }
665 Token::Count | Token::Avg | Token::Sum | Token::Min | Token::Max => {
666 let mut func = match first {
667 Token::Count => AggFunc::Count,
668 Token::Avg => AggFunc::Avg,
669 Token::Sum => AggFunc::Sum,
670 Token::Min => AggFunc::Min,
671 Token::Max => AggFunc::Max,
672 _ => {
673 return Err(ParseError::Syntax {
674 message: "unexpected aggregate token".into(),
675 })
676 }
677 };
678 self.expect(&Token::LParen)?;
679 if func == AggFunc::Count && *self.peek() == Token::Star {
681 self.advance();
682 self.expect(&Token::RParen)?;
683 if *self.peek() == Token::Over {
685 let (partition_by, order_by) = self.parse_over_clause()?;
686 Expr::Window {
687 function: WindowFunc::Count,
688 args: vec![Expr::Field("*".into())],
689 partition_by,
690 order_by,
691 }
692 } else {
693 Expr::FunctionCall(
694 AggFunc::Count,
695 Box::new(Expr::Field("*".into())),
696 )
697 }
698 } else {
699 if func == AggFunc::Count && *self.peek() == Token::Distinct {
701 self.advance();
702 func = AggFunc::CountDistinct;
703 }
704 let inner = self.parse_expr()?;
705 self.expect(&Token::RParen)?;
706 if *self.peek() == Token::Over {
708 let wfunc =
709 match func {
710 AggFunc::Count => WindowFunc::Count,
711 AggFunc::Avg => WindowFunc::Avg,
712 AggFunc::Sum => WindowFunc::Sum,
713 AggFunc::Min => WindowFunc::Min,
714 AggFunc::Max => WindowFunc::Max,
715 _ => return Err(ParseError::Unsupported {
716 feature:
717 "count(distinct ...) over (...) is not supported"
718 .into(),
719 }),
720 };
721 let (partition_by, order_by) = self.parse_over_clause()?;
722 Expr::Window {
723 function: wfunc,
724 args: vec![inner],
725 partition_by,
726 order_by,
727 }
728 } else {
729 Expr::FunctionCall(func, Box::new(inner))
730 }
731 }
732 }
733 Token::Upper
734 | Token::Lower
735 | Token::Length
736 | Token::Trim
737 | Token::Substring
738 | Token::Concat
739 | Token::Abs
740 | Token::Round
741 | Token::Ceil
742 | Token::Floor
743 | Token::Sqrt
744 | Token::Pow
745 | Token::Now
746 | Token::Extract
747 | Token::DateAdd
748 | Token::DateDiff => {
749 let func = token_to_scalar_fn(&first);
750 self.expect(&Token::LParen)?;
751 let mut args = Vec::new();
752 while !matches!(self.peek(), Token::RParen | Token::Eof) {
753 args.push(self.parse_expr()?);
754 if *self.peek() == Token::Comma {
755 self.advance();
756 }
757 }
758 self.expect(&Token::RParen)?;
759 Expr::ScalarFunc(func, args)
760 }
761 Token::Cast => {
762 self.expect(&Token::LParen)?;
763 let inner = self.parse_expr()?;
764 self.expect(&Token::Comma)?;
765 let cast_type = self.parse_cast_type()?;
766 self.expect(&Token::RParen)?;
767 Expr::Cast(Box::new(inner), cast_type)
768 }
769 Token::Case => {
770 let mut whens = Vec::new();
771 while *self.peek() == Token::When {
772 self.advance();
773 let condition = self.parse_expr()?;
774 self.expect(&Token::Then)?;
775 let result = self.parse_expr()?;
776 whens.push((Box::new(condition), Box::new(result)));
777 }
778 let else_expr = if *self.peek() == Token::Else {
779 self.advance();
780 Some(Box::new(self.parse_expr()?))
781 } else {
782 None
783 };
784 self.expect(&Token::End)?;
785 Expr::Case { whens, else_expr }
786 }
787 _ => {
788 return Err(ParseError::UnexpectedToken {
789 expected: "field".into(),
790 got: first.display_name(),
791 })
792 }
793 };
794 fields.push(ProjectionField { alias: None, expr });
795 }
796 if *self.peek() == Token::Comma {
797 self.advance();
798 }
799 }
800 self.expect(&Token::RBrace)?;
801 Ok(fields)
802 }
803
804 fn parse_over_clause(&mut self) -> Result<(Vec<String>, Vec<OrderKey>), ParseError> {
807 self.expect(&Token::Over)?;
808 self.expect(&Token::LParen)?;
809 let mut partition_by = Vec::new();
810 let mut order_by = Vec::new();
811 if *self.peek() == Token::Partition {
812 self.advance();
813 while let Token::DotIdent(name) = self.peek() {
814 let name = name.clone();
815 self.advance();
816 partition_by.push(name);
817 if *self.peek() == Token::Comma {
818 if matches!(self.tokens.get(self.pos + 1), Some(Token::DotIdent(_))) {
822 self.advance();
823 } else {
824 break;
825 }
826 } else {
827 break;
828 }
829 }
830 }
831 if *self.peek() == Token::Order {
832 self.advance();
833 while let Token::DotIdent(name) = self.peek() {
834 let field = name.clone();
835 self.advance();
836 let descending = match self.peek() {
837 Token::Desc => {
838 self.advance();
839 true
840 }
841 Token::Asc => {
842 self.advance();
843 false
844 }
845 _ => false,
846 };
847 order_by.push(OrderKey { field, descending });
848 if *self.peek() == Token::Comma {
849 self.advance();
850 } else {
851 break;
852 }
853 }
854 }
855 self.expect(&Token::RParen)?;
856 Ok((partition_by, order_by))
857 }
858
859 fn parse_cast_type(&mut self) -> Result<CastType, ParseError> {
861 match self.advance() {
862 Token::StringLit(s) => match s.as_str() {
863 "int" | "Int" | "INT" => Ok(CastType::Int),
864 "float" | "Float" | "FLOAT" => Ok(CastType::Float),
865 "str" | "Str" | "STR" | "string" | "String" => Ok(CastType::Str),
866 "bool" | "Bool" | "BOOL" | "boolean" => Ok(CastType::Bool),
867 "datetime" | "DateTime" | "DATETIME" => Ok(CastType::DateTime),
868 other => Err(ParseError::Syntax {
869 message: format!("invalid cast type: \"{other}\""),
870 }),
871 },
872 t => Err(ParseError::UnexpectedToken {
873 expected: "string literal for cast type".into(),
874 got: t.display_name(),
875 }),
876 }
877 }
878
879 fn parse_order(&mut self) -> Result<OrderClause, ParseError> {
880 let mut keys = Vec::new();
881 loop {
882 let field = match self.advance() {
883 Token::DotIdent(name) => name,
884 t => {
885 return Err(ParseError::UnexpectedToken {
886 expected: ".field after order".into(),
887 got: t.display_name(),
888 })
889 }
890 };
891 let descending = match self.peek() {
892 Token::Desc => {
893 self.advance();
894 true
895 }
896 Token::Asc => {
897 self.advance();
898 false
899 }
900 _ => false,
901 };
902 keys.push(OrderKey { field, descending });
903 if *self.peek() == Token::Comma {
904 self.advance();
905 } else {
906 break;
907 }
908 }
909 Ok(OrderClause { keys })
910 }
911
912 fn parse_aggregate_query(&mut self) -> Result<Statement, ParseError> {
913 let mut func = match self.advance() {
914 Token::Count => AggFunc::Count,
915 Token::Avg => AggFunc::Avg,
916 Token::Sum => AggFunc::Sum,
917 Token::Min => AggFunc::Min,
918 Token::Max => AggFunc::Max,
919 t => {
920 return Err(ParseError::UnexpectedToken {
921 expected: "aggregate function".into(),
922 got: t.display_name(),
923 })
924 }
925 };
926 self.expect(&Token::LParen)?;
927 if func == AggFunc::Count && *self.peek() == Token::Distinct {
929 self.advance();
930 func = AggFunc::CountDistinct;
931 }
932 let source = match self.advance() {
933 Token::Ident(name) => name,
934 t => {
935 return Err(ParseError::UnexpectedToken {
936 expected: "type name".into(),
937 got: t.display_name(),
938 })
939 }
940 };
941 let mut query = self.parse_query_tail(source)?;
945 self.expect(&Token::RParen)?;
946
947 let mut agg_field: Option<String> = None;
954 if func != AggFunc::Count {
955 if let Some(proj) = &query.projection {
956 if proj.len() == 1 && proj[0].alias.is_none() {
957 if let Expr::Field(name) = &proj[0].expr {
958 agg_field = Some(name.clone());
959 }
960 }
961 }
962 if agg_field.is_some() {
963 query.projection = None;
964 }
965 }
966 query.aggregation = Some(AggregateExpr {
967 function: func,
968 field: agg_field,
969 });
970 Ok(Statement::Query(query))
971 }
972
973 fn parse_expr(&mut self) -> Result<Expr, ParseError> {
974 self.depth += 1;
975 if self.depth > MAX_NESTING_DEPTH {
976 self.depth -= 1;
977 return Err(ParseError::NestingDepthExceeded {
978 max: MAX_NESTING_DEPTH,
979 });
980 }
981 let result = self.parse_or_expr();
982 self.depth -= 1;
983 result
984 }
985
986 fn parse_or_expr(&mut self) -> Result<Expr, ParseError> {
987 let mut left = self.parse_and_expr()?;
988 while *self.peek() == Token::Or {
989 self.advance();
990 let right = self.parse_and_expr()?;
991 left = Expr::BinaryOp(Box::new(left), BinOp::Or, Box::new(right));
992 }
993 Ok(left)
994 }
995
996 fn parse_and_expr(&mut self) -> Result<Expr, ParseError> {
997 let mut left = self.parse_comparison()?;
998 while *self.peek() == Token::And {
999 self.advance();
1000 let right = self.parse_comparison()?;
1001 left = Expr::BinaryOp(Box::new(left), BinOp::And, Box::new(right));
1002 }
1003 Ok(left)
1004 }
1005
1006 fn parse_comparison(&mut self) -> Result<Expr, ParseError> {
1007 let left = self.parse_additive()?;
1008
1009 if *self.peek() == Token::Is {
1011 self.advance();
1012 if *self.peek() == Token::Not {
1013 self.advance();
1014 self.expect(&Token::Null)?;
1015 return Ok(Expr::UnaryOp(UnaryOp::IsNotNull, Box::new(left)));
1016 } else {
1017 self.expect(&Token::Null)?;
1018 return Ok(Expr::UnaryOp(UnaryOp::IsNull, Box::new(left)));
1019 }
1020 }
1021
1022 match self.peek() {
1025 Token::In => {
1026 self.advance();
1027 return self.parse_in_list(left, false);
1028 }
1029 Token::Like => {
1030 self.advance();
1031 let pattern = self.parse_additive()?;
1032 return Ok(Expr::BinaryOp(
1033 Box::new(left),
1034 BinOp::Like,
1035 Box::new(pattern),
1036 ));
1037 }
1038 Token::Between => {
1039 self.advance();
1040 return self.parse_between(left, false);
1041 }
1042 Token::Not => {
1043 let next = self.tokens.get(self.pos + 1);
1047 match next {
1048 Some(Token::In) => {
1049 self.advance(); self.advance(); return self.parse_in_list(left, true);
1052 }
1053 Some(Token::Like) => {
1054 self.advance(); self.advance(); let pattern = self.parse_additive()?;
1057 let like = Expr::BinaryOp(Box::new(left), BinOp::Like, Box::new(pattern));
1058 return Ok(Expr::UnaryOp(UnaryOp::Not, Box::new(like)));
1059 }
1060 Some(Token::Between) => {
1061 self.advance(); self.advance(); return self.parse_between(left, true);
1064 }
1065 _ => {}
1066 }
1067 }
1068 _ => {}
1069 }
1070
1071 let op = match self.peek() {
1072 Token::Eq => BinOp::Eq,
1073 Token::Neq => BinOp::Neq,
1074 Token::Lt => BinOp::Lt,
1075 Token::Gt => BinOp::Gt,
1076 Token::Lte => BinOp::Lte,
1077 Token::Gte => BinOp::Gte,
1078 _ => return Ok(left),
1079 };
1080 self.advance();
1081 if *self.peek() == Token::Null {
1085 match op {
1086 BinOp::Eq => {
1087 self.advance();
1088 return Ok(Expr::UnaryOp(UnaryOp::IsNull, Box::new(left)));
1089 }
1090 BinOp::Neq => {
1091 self.advance();
1092 return Ok(Expr::UnaryOp(UnaryOp::IsNotNull, Box::new(left)));
1093 }
1094 _ => {}
1095 }
1096 }
1097 let right = self.parse_additive()?;
1098 Ok(Expr::BinaryOp(Box::new(left), op, Box::new(right)))
1099 }
1100
1101 fn parse_in_list(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParseError> {
1106 self.expect(&Token::LParen)?;
1107 if let Token::Ident(_) = self.peek() {
1109 let after = self.tokens.get(self.pos + 1);
1112 let is_subquery = !matches!(after, Some(Token::Comma) | Some(Token::RParen));
1113 if is_subquery {
1114 let source = match self.advance() {
1115 Token::Ident(name) => name,
1116 _ => unreachable!(),
1117 };
1118 let subquery = self.parse_query_tail(source)?;
1119 self.expect(&Token::RParen)?;
1120 return Ok(Expr::InSubquery {
1121 expr: Box::new(expr),
1122 subquery: Box::new(subquery),
1123 negated,
1124 });
1125 }
1126 }
1127 let mut list = Vec::new();
1128 while !matches!(self.peek(), Token::RParen | Token::Eof) {
1129 list.push(self.parse_expr()?);
1130 if *self.peek() == Token::Comma {
1131 self.advance();
1132 }
1133 }
1134 self.expect(&Token::RParen)?;
1135 Ok(Expr::InList {
1136 expr: Box::new(expr),
1137 list,
1138 negated,
1139 })
1140 }
1141
1142 fn try_parse_exists_subquery(&mut self) -> Result<Option<QueryExpr>, ParseError> {
1150 if *self.peek() != Token::LParen {
1151 return Ok(None);
1152 }
1153 let after_lparen = self.tokens.get(self.pos + 1);
1157 if !matches!(after_lparen, Some(Token::Ident(_))) {
1158 return Ok(None);
1159 }
1160 self.expect(&Token::LParen)?;
1161 let source = match self.advance() {
1162 Token::Ident(name) => name,
1163 _ => unreachable!(),
1164 };
1165 let subquery = self.parse_query_tail(source)?;
1166 self.expect(&Token::RParen)?;
1167 Ok(Some(subquery))
1168 }
1169
1170 fn parse_between(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParseError> {
1174 let low = self.parse_additive()?;
1175 self.expect(&Token::And)?;
1176 let high = self.parse_additive()?;
1177 if negated {
1178 Ok(Expr::BinaryOp(
1180 Box::new(Expr::BinaryOp(
1181 Box::new(expr.clone()),
1182 BinOp::Lt,
1183 Box::new(low),
1184 )),
1185 BinOp::Or,
1186 Box::new(Expr::BinaryOp(Box::new(expr), BinOp::Gt, Box::new(high))),
1187 ))
1188 } else {
1189 Ok(Expr::BinaryOp(
1191 Box::new(Expr::BinaryOp(
1192 Box::new(expr.clone()),
1193 BinOp::Gte,
1194 Box::new(low),
1195 )),
1196 BinOp::And,
1197 Box::new(Expr::BinaryOp(Box::new(expr), BinOp::Lte, Box::new(high))),
1198 ))
1199 }
1200 }
1201
1202 fn parse_group_by(&mut self) -> Result<GroupByClause, ParseError> {
1204 let mut keys = Vec::new();
1205 while let Token::DotIdent(name) = self.peek() {
1206 let name = name.clone();
1207 self.advance();
1208 keys.push(name);
1209 if *self.peek() == Token::Comma {
1210 self.advance();
1211 } else {
1212 break;
1213 }
1214 }
1215 if keys.is_empty() {
1216 return Err(ParseError::Syntax {
1217 message: "expected at least one .field after group".into(),
1218 });
1219 }
1220 let having = if *self.peek() == Token::Having {
1221 self.advance();
1222 Some(self.parse_expr()?)
1223 } else {
1224 None
1225 };
1226 Ok(GroupByClause { keys, having })
1227 }
1228
1229 fn parse_additive(&mut self) -> Result<Expr, ParseError> {
1230 let mut left = self.parse_multiplicative()?;
1231 loop {
1232 let op = match self.peek() {
1233 Token::Plus => BinOp::Add,
1234 Token::Minus => BinOp::Sub,
1235 Token::Coalesce => {
1236 self.advance();
1237 let right = self.parse_multiplicative()?;
1238 left = Expr::Coalesce(Box::new(left), Box::new(right));
1239 continue;
1240 }
1241 _ => break,
1242 };
1243 self.advance();
1244 let right = self.parse_multiplicative()?;
1245 left = Expr::BinaryOp(Box::new(left), op, Box::new(right));
1246 }
1247 Ok(left)
1248 }
1249
1250 fn parse_multiplicative(&mut self) -> Result<Expr, ParseError> {
1251 let mut left = self.parse_primary()?;
1252 loop {
1253 let op = match self.peek() {
1254 Token::Star => BinOp::Mul,
1255 Token::Slash => BinOp::Div,
1256 _ => break,
1257 };
1258 self.advance();
1259 let right = self.parse_primary()?;
1260 left = Expr::BinaryOp(Box::new(left), op, Box::new(right));
1261 }
1262 Ok(left)
1263 }
1264
1265 fn parse_primary(&mut self) -> Result<Expr, ParseError> {
1266 match self.peek().clone() {
1267 Token::DotIdent(name) => {
1268 self.advance();
1269 Ok(Expr::Field(name))
1270 }
1271 Token::IntLit(v) => {
1272 self.advance();
1273 Ok(Expr::Literal(Literal::Int(v)))
1274 }
1275 Token::FloatLit(v) => {
1276 self.advance();
1277 Ok(Expr::Literal(Literal::Float(v)))
1278 }
1279 Token::StringLit(v) => {
1280 self.advance();
1281 Ok(Expr::Literal(Literal::String(v)))
1282 }
1283 Token::BoolLit(v) => {
1284 self.advance();
1285 Ok(Expr::Literal(Literal::Bool(v)))
1286 }
1287 Token::Param(name) => {
1288 self.advance();
1289 Ok(Expr::Param(name))
1290 }
1291 Token::Not => {
1292 self.advance();
1293 if *self.peek() == Token::Exists {
1294 self.advance();
1295 if let Some(sub) = self.try_parse_exists_subquery()? {
1299 return Ok(Expr::ExistsSubquery {
1300 subquery: Box::new(sub),
1301 negated: true,
1302 });
1303 }
1304 let expr = self.parse_primary()?;
1305 Ok(Expr::UnaryOp(UnaryOp::NotExists, Box::new(expr)))
1306 } else {
1307 let expr = self.parse_primary()?;
1308 Ok(Expr::UnaryOp(UnaryOp::Not, Box::new(expr)))
1309 }
1310 }
1311 Token::Exists => {
1312 self.advance();
1313 if let Some(sub) = self.try_parse_exists_subquery()? {
1317 return Ok(Expr::ExistsSubquery {
1318 subquery: Box::new(sub),
1319 negated: false,
1320 });
1321 }
1322 let expr = self.parse_primary()?;
1323 Ok(Expr::UnaryOp(UnaryOp::Exists, Box::new(expr)))
1324 }
1325 Token::LParen => {
1326 self.advance();
1327 let expr = self.parse_expr()?;
1328 self.expect(&Token::RParen)?;
1329 Ok(expr)
1330 }
1331 Token::Ident(name) => {
1332 self.advance();
1333 if let Token::DotIdent(field) = self.peek().clone() {
1337 self.advance();
1338 return Ok(Expr::QualifiedField {
1339 qualifier: name,
1340 field,
1341 });
1342 }
1343 Ok(Expr::Field(name))
1344 }
1345 Token::RowNumber | Token::Rank | Token::DenseRank => {
1347 let wfunc = match self.advance() {
1348 Token::RowNumber => WindowFunc::RowNumber,
1349 Token::Rank => WindowFunc::Rank,
1350 Token::DenseRank => WindowFunc::DenseRank,
1351 _ => {
1352 return Err(ParseError::Syntax {
1353 message: "unexpected window function token".into(),
1354 })
1355 }
1356 };
1357 self.expect(&Token::LParen)?;
1358 self.expect(&Token::RParen)?;
1359 let (partition_by, order_by) = self.parse_over_clause()?;
1360 Ok(Expr::Window {
1361 function: wfunc,
1362 args: vec![],
1363 partition_by,
1364 order_by,
1365 })
1366 }
1367 Token::Count | Token::Avg | Token::Sum | Token::Min | Token::Max => {
1371 let mut func = match self.advance() {
1372 Token::Count => AggFunc::Count,
1373 Token::Avg => AggFunc::Avg,
1374 Token::Sum => AggFunc::Sum,
1375 Token::Min => AggFunc::Min,
1376 Token::Max => AggFunc::Max,
1377 _ => {
1378 return Err(ParseError::Syntax {
1379 message: "unexpected aggregate token".into(),
1380 })
1381 }
1382 };
1383 self.expect(&Token::LParen)?;
1384 if func == AggFunc::Count && *self.peek() == Token::Star {
1386 self.advance();
1387 self.expect(&Token::RParen)?;
1388 if *self.peek() == Token::Over {
1390 let (partition_by, order_by) = self.parse_over_clause()?;
1391 return Ok(Expr::Window {
1392 function: WindowFunc::Count,
1393 args: vec![Expr::Field("*".into())],
1394 partition_by,
1395 order_by,
1396 });
1397 }
1398 return Ok(Expr::FunctionCall(
1399 AggFunc::Count,
1400 Box::new(Expr::Field("*".into())),
1401 ));
1402 }
1403 if func == AggFunc::Count && *self.peek() == Token::Distinct {
1405 self.advance();
1406 func = AggFunc::CountDistinct;
1407 }
1408 let inner = self.parse_expr()?;
1409 self.expect(&Token::RParen)?;
1410 if *self.peek() == Token::Over {
1412 let wfunc = match func {
1413 AggFunc::Count => WindowFunc::Count,
1414 AggFunc::Avg => WindowFunc::Avg,
1415 AggFunc::Sum => WindowFunc::Sum,
1416 AggFunc::Min => WindowFunc::Min,
1417 AggFunc::Max => WindowFunc::Max,
1418 _ => {
1419 return Err(ParseError::Unsupported {
1420 feature: "count(distinct ...) over (...) is not supported".into(),
1421 })
1422 }
1423 };
1424 let (partition_by, order_by) = self.parse_over_clause()?;
1425 return Ok(Expr::Window {
1426 function: wfunc,
1427 args: vec![inner],
1428 partition_by,
1429 order_by,
1430 });
1431 }
1432 Ok(Expr::FunctionCall(func, Box::new(inner)))
1433 }
1434 Token::Upper
1435 | Token::Lower
1436 | Token::Length
1437 | Token::Trim
1438 | Token::Substring
1439 | Token::Concat
1440 | Token::Abs
1441 | Token::Round
1442 | Token::Ceil
1443 | Token::Floor
1444 | Token::Sqrt
1445 | Token::Pow
1446 | Token::Now
1447 | Token::Extract
1448 | Token::DateAdd
1449 | Token::DateDiff => {
1450 let tok = self.advance();
1451 let func = token_to_scalar_fn(&tok);
1452 self.expect(&Token::LParen)?;
1453 let mut args = Vec::new();
1454 while !matches!(self.peek(), Token::RParen | Token::Eof) {
1455 args.push(self.parse_expr()?);
1456 if *self.peek() == Token::Comma {
1457 self.advance();
1458 }
1459 }
1460 self.expect(&Token::RParen)?;
1461 Ok(Expr::ScalarFunc(func, args))
1462 }
1463 Token::Cast => {
1464 self.advance();
1465 self.expect(&Token::LParen)?;
1466 let inner = self.parse_expr()?;
1467 self.expect(&Token::Comma)?;
1468 let cast_type = self.parse_cast_type()?;
1469 self.expect(&Token::RParen)?;
1470 Ok(Expr::Cast(Box::new(inner), cast_type))
1471 }
1472 Token::Case => {
1473 self.advance();
1474 let mut whens = Vec::new();
1475 while *self.peek() == Token::When {
1476 self.advance();
1477 let condition = self.parse_expr()?;
1478 self.expect(&Token::Then)?;
1479 let result = self.parse_expr()?;
1480 whens.push((Box::new(condition), Box::new(result)));
1481 }
1482 let else_expr = if *self.peek() == Token::Else {
1483 self.advance();
1484 Some(Box::new(self.parse_expr()?))
1485 } else {
1486 None
1487 };
1488 self.expect(&Token::End)?;
1489 Ok(Expr::Case { whens, else_expr })
1490 }
1491 t => Err(ParseError::Syntax {
1492 message: format!("unexpected token in expression: {}", t.display_name()),
1493 }),
1494 }
1495 }
1496
1497 fn parse_alter_table(&mut self) -> Result<Statement, ParseError> {
1500 self.expect(&Token::Alter)?;
1501 let table = match self.advance() {
1502 Token::Ident(name) => name,
1503 t => {
1504 return Err(ParseError::UnexpectedToken {
1505 expected: "table name after alter".into(),
1506 got: t.display_name(),
1507 })
1508 }
1509 };
1510 match self.peek() {
1511 Token::Add => {
1512 self.advance();
1513 if *self.peek() == Token::Index {
1515 self.advance();
1516 let column = match self.advance() {
1517 Token::DotIdent(n) => n,
1518 t => {
1519 return Err(ParseError::UnexpectedToken {
1520 expected: ".<column> after add index".into(),
1521 got: t.display_name(),
1522 })
1523 }
1524 };
1525 return Ok(Statement::AlterTable(AlterTableExpr {
1526 table,
1527 action: AlterAction::AddIndex { column },
1528 }));
1529 }
1530 if *self.peek() == Token::Column {
1532 self.advance();
1533 }
1534 let required = if *self.peek() == Token::Required {
1535 self.advance();
1536 true
1537 } else {
1538 false
1539 };
1540 let name = match self.advance() {
1541 Token::Ident(n) => n,
1542 t => {
1543 return Err(ParseError::UnexpectedToken {
1544 expected: "column name".into(),
1545 got: t.display_name(),
1546 })
1547 }
1548 };
1549 self.expect(&Token::Colon)?;
1550 let type_name = match self.advance() {
1551 Token::Ident(n) => n,
1552 t => {
1553 return Err(ParseError::UnexpectedToken {
1554 expected: "type name".into(),
1555 got: t.display_name(),
1556 })
1557 }
1558 };
1559 Ok(Statement::AlterTable(AlterTableExpr {
1560 table,
1561 action: AlterAction::AddColumn {
1562 name,
1563 type_name,
1564 required,
1565 },
1566 }))
1567 }
1568 Token::Drop => {
1569 self.advance();
1570 if *self.peek() == Token::Column {
1572 self.advance();
1573 }
1574 let name = match self.advance() {
1575 Token::Ident(n) => n,
1576 t => {
1577 return Err(ParseError::UnexpectedToken {
1578 expected: "column name".into(),
1579 got: t.display_name(),
1580 })
1581 }
1582 };
1583 Ok(Statement::AlterTable(AlterTableExpr {
1584 table,
1585 action: AlterAction::DropColumn { name },
1586 }))
1587 }
1588 t => Err(ParseError::UnexpectedToken {
1589 expected: "add or drop after alter <table>".into(),
1590 got: t.display_name(),
1591 }),
1592 }
1593 }
1594
1595 fn parse_drop_or_drop_view(&mut self) -> Result<Statement, ParseError> {
1597 self.expect(&Token::Drop)?;
1598 if *self.peek() == Token::View {
1599 self.advance(); let name = match self.advance() {
1601 Token::Ident(name) => name,
1602 t => {
1603 return Err(ParseError::UnexpectedToken {
1604 expected: "view name after drop view".into(),
1605 got: t.display_name(),
1606 })
1607 }
1608 };
1609 return Ok(Statement::DropView(DropViewExpr { name }));
1610 }
1611 let table = match self.advance() {
1612 Token::Ident(name) => name,
1613 t => {
1614 return Err(ParseError::UnexpectedToken {
1615 expected: "table name after drop".into(),
1616 got: t.display_name(),
1617 })
1618 }
1619 };
1620 Ok(Statement::DropTable(DropTableExpr { table }))
1621 }
1622
1623 fn parse_create_view(&mut self) -> Result<Statement, ParseError> {
1628 self.expect(&Token::Materialized)?;
1629 let name = match self.advance() {
1630 Token::Ident(name) => name,
1631 t => {
1632 return Err(ParseError::UnexpectedToken {
1633 expected: "view name after materialize".into(),
1634 got: t.display_name(),
1635 })
1636 }
1637 };
1638 self.expect(&Token::As)?;
1639 let query_start = self.pos;
1641 let source = match self.advance() {
1642 Token::Ident(s) => s,
1643 t => {
1644 return Err(ParseError::UnexpectedToken {
1645 expected: "source table name".into(),
1646 got: t.display_name(),
1647 })
1648 }
1649 };
1650 let query = self.parse_query_tail(source)?;
1651 let query_text = tokens_to_text(&self.tokens[query_start..self.pos]);
1653 Ok(Statement::CreateView(CreateViewExpr {
1654 name,
1655 query,
1656 query_text,
1657 }))
1658 }
1659
1660 fn maybe_parse_union(&mut self, left: Statement) -> Result<Statement, ParseError> {
1663 if *self.peek() != Token::Union {
1664 return Ok(left);
1665 }
1666 if !matches!(left, Statement::Query(_) | Statement::Union(_)) {
1667 return Err(ParseError::Syntax {
1668 message: "UNION requires a query on the left side".into(),
1669 });
1670 }
1671 self.advance(); let all = if let Token::Ident(s) = self.peek() {
1673 if s == "all" {
1674 self.advance();
1675 true
1676 } else {
1677 false
1678 }
1679 } else {
1680 false
1681 };
1682 let right = self.parse_single_query()?;
1684 let union = Statement::Union(UnionExpr {
1685 left: Box::new(left),
1686 right: Box::new(right),
1687 all,
1688 });
1689 self.maybe_parse_union(union)
1691 }
1692
1693 fn parse_single_query(&mut self) -> Result<Statement, ParseError> {
1695 match self.peek() {
1696 Token::Count | Token::Avg | Token::Sum | Token::Min | Token::Max => {
1697 self.parse_aggregate_query()
1698 }
1699 Token::Ident(_) => self.parse_query_or_mutation(),
1700 _ => Err(ParseError::Syntax {
1701 message: format!(
1702 "expected query after UNION, got {}",
1703 self.peek().display_name()
1704 ),
1705 }),
1706 }
1707 }
1708
1709 fn parse_refresh_view(&mut self) -> Result<Statement, ParseError> {
1711 self.expect(&Token::Refresh)?;
1712 let name = match self.advance() {
1713 Token::Ident(name) => name,
1714 t => {
1715 return Err(ParseError::UnexpectedToken {
1716 expected: "view name after refresh".into(),
1717 got: t.display_name(),
1718 })
1719 }
1720 };
1721 Ok(Statement::RefreshView(RefreshViewExpr { name }))
1722 }
1723
1724 fn parse_create_type(&mut self) -> Result<Statement, ParseError> {
1725 self.expect(&Token::Type)?;
1726 let name = match self.advance() {
1727 Token::Ident(n) => n,
1728 t => {
1729 return Err(ParseError::UnexpectedToken {
1730 expected: "type name".into(),
1731 got: t.display_name(),
1732 })
1733 }
1734 };
1735 self.expect(&Token::LBrace)?;
1736 let mut fields = Vec::new();
1737 while !matches!(self.peek(), Token::RBrace | Token::Eof) {
1738 let required = if *self.peek() == Token::Required {
1739 self.advance();
1740 true
1741 } else {
1742 false
1743 };
1744 let field_name = match self.advance() {
1745 Token::Ident(n) => n,
1746 t => {
1747 return Err(ParseError::UnexpectedToken {
1748 expected: "field name".into(),
1749 got: t.display_name(),
1750 })
1751 }
1752 };
1753 self.expect(&Token::Colon)?;
1754 let type_name = match self.advance() {
1755 Token::Ident(n) => n,
1756 t => {
1757 return Err(ParseError::UnexpectedToken {
1758 expected: "type name".into(),
1759 got: t.display_name(),
1760 })
1761 }
1762 };
1763 fields.push(FieldDef {
1764 name: field_name,
1765 type_name,
1766 required,
1767 });
1768 if *self.peek() == Token::Comma {
1769 self.advance();
1770 }
1771 }
1772 self.expect(&Token::RBrace)?;
1773 Ok(Statement::CreateType(CreateTypeExpr { name, fields }))
1774 }
1775}
1776
1777fn tokens_to_text(tokens: &[Token]) -> String {
1781 let mut out = String::with_capacity(64);
1782 for tok in tokens {
1783 if !out.is_empty() && !matches!(tok, Token::Eof) {
1784 out.push(' ');
1785 }
1786 match tok {
1787 Token::Ident(s) => out.push_str(s),
1788 Token::DotIdent(s) => {
1789 out.push('.');
1790 out.push_str(s);
1791 }
1792 Token::IntLit(v) => out.push_str(&v.to_string()),
1793 Token::FloatLit(v) => out.push_str(&v.to_string()),
1794 Token::StringLit(s) => {
1795 out.push('"');
1796 out.push_str(s);
1797 out.push('"');
1798 }
1799 Token::BoolLit(v) => out.push_str(if *v { "true" } else { "false" }),
1800 Token::Param(s) => {
1801 out.push('$');
1802 out.push_str(s);
1803 }
1804 Token::Type => out.push_str("type"),
1805 Token::Filter => out.push_str("filter"),
1806 Token::Order => out.push_str("order"),
1807 Token::Limit => out.push_str("limit"),
1808 Token::Offset => out.push_str("offset"),
1809 Token::Insert => out.push_str("insert"),
1810 Token::Update => out.push_str("update"),
1811 Token::Delete => out.push_str("delete"),
1812 Token::Upsert => out.push_str("upsert"),
1813 Token::Conflict => out.push_str("conflict"),
1814 Token::Select => out.push_str("select"),
1815 Token::Required => out.push_str("required"),
1816 Token::Multi => out.push_str("multi"),
1817 Token::Link => out.push_str("link"),
1818 Token::Index => out.push_str("index"),
1819 Token::On => out.push_str("on"),
1820 Token::Asc => out.push_str("asc"),
1821 Token::Desc => out.push_str("desc"),
1822 Token::And => out.push_str("and"),
1823 Token::Or => out.push_str("or"),
1824 Token::Not => out.push_str("not"),
1825 Token::Exists => out.push_str("exists"),
1826 Token::Let => out.push_str("let"),
1827 Token::As => out.push_str("as"),
1828 Token::Match => out.push_str("match"),
1829 Token::Group => out.push_str("group"),
1830 Token::Join => out.push_str("join"),
1831 Token::Inner => out.push_str("inner"),
1832 Token::LeftKw => out.push_str("left"),
1833 Token::RightKw => out.push_str("right"),
1834 Token::Outer => out.push_str("outer"),
1835 Token::Cross => out.push_str("cross"),
1836 Token::Transaction => out.push_str("transaction"),
1837 Token::View => out.push_str("view"),
1838 Token::Materialized => out.push_str("materialized"),
1839 Token::Refresh => out.push_str("refresh"),
1840 Token::Union => out.push_str("union"),
1841 Token::Having => out.push_str("having"),
1842 Token::Distinct => out.push_str("distinct"),
1843 Token::In => out.push_str("in"),
1844 Token::Between => out.push_str("between"),
1845 Token::Like => out.push_str("like"),
1846 Token::Count => out.push_str("count"),
1847 Token::Avg => out.push_str("avg"),
1848 Token::Sum => out.push_str("sum"),
1849 Token::Min => out.push_str("min"),
1850 Token::Max => out.push_str("max"),
1851 Token::Is => out.push_str("is"),
1852 Token::Null => out.push_str("null"),
1853 Token::Upper => out.push_str("upper"),
1854 Token::Lower => out.push_str("lower"),
1855 Token::Length => out.push_str("length"),
1856 Token::Trim => out.push_str("trim"),
1857 Token::Substring => out.push_str("substring"),
1858 Token::Concat => out.push_str("concat"),
1859 Token::Abs => out.push_str("abs"),
1860 Token::Round => out.push_str("round"),
1861 Token::Ceil => out.push_str("ceil"),
1862 Token::Floor => out.push_str("floor"),
1863 Token::Sqrt => out.push_str("sqrt"),
1864 Token::Pow => out.push_str("pow"),
1865 Token::Now => out.push_str("now"),
1866 Token::Extract => out.push_str("extract"),
1867 Token::DateAdd => out.push_str("date_add"),
1868 Token::DateDiff => out.push_str("date_diff"),
1869 Token::Cast => out.push_str("cast"),
1870 Token::Case => out.push_str("case"),
1871 Token::When => out.push_str("when"),
1872 Token::Then => out.push_str("then"),
1873 Token::Else => out.push_str("else"),
1874 Token::End => out.push_str("end"),
1875 Token::Over => out.push_str("over"),
1876 Token::Partition => out.push_str("partition"),
1877 Token::RowNumber => out.push_str("row_number"),
1878 Token::Rank => out.push_str("rank"),
1879 Token::DenseRank => out.push_str("dense_rank"),
1880 Token::Alter => out.push_str("alter"),
1881 Token::Drop => out.push_str("drop"),
1882 Token::Add => out.push_str("add"),
1883 Token::Column => out.push_str("column"),
1884 Token::Eq => out.push('='),
1885 Token::Neq => out.push_str("!="),
1886 Token::Lt => out.push('<'),
1887 Token::Gt => out.push('>'),
1888 Token::Lte => out.push_str("<="),
1889 Token::Gte => out.push_str(">="),
1890 Token::Assign => out.push_str(":="),
1891 Token::Arrow => out.push_str("->"),
1892 Token::Pipe => out.push('|'),
1893 Token::Coalesce => out.push_str("??"),
1894 Token::Plus => out.push('+'),
1895 Token::Minus => out.push('-'),
1896 Token::Star => out.push('*'),
1897 Token::Slash => out.push('/'),
1898 Token::LBrace => out.push('{'),
1899 Token::RBrace => out.push('}'),
1900 Token::LParen => out.push('('),
1901 Token::RParen => out.push(')'),
1902 Token::Comma => out.push(','),
1903 Token::Colon => out.push(':'),
1904 Token::Dot => out.push('.'),
1905 Token::Explain => out.push_str("explain"),
1906 Token::Eof => {}
1907 }
1908 }
1909 out
1910}
1911
1912#[cfg(test)]
1913mod tests {
1914 use super::*;
1915 #[test]
1916 fn test_parse_simple_query() {
1917 let stmt = parse("User").unwrap();
1918 match stmt {
1919 Statement::Query(q) => {
1920 assert_eq!(q.source, "User");
1921 assert!(q.filter.is_none());
1922 assert!(q.projection.is_none());
1923 }
1924 _ => panic!("expected query"),
1925 }
1926 }
1927
1928 #[test]
1929 fn test_parse_filter() {
1930 let stmt = parse("User filter .age > 30").unwrap();
1931 match stmt {
1932 Statement::Query(q) => {
1933 assert_eq!(q.source, "User");
1934 assert!(q.filter.is_some());
1935 }
1936 _ => panic!("expected query"),
1937 }
1938 }
1939
1940 #[test]
1941 fn test_parse_projection() {
1942 let stmt = parse("User { name, email }").unwrap();
1943 match stmt {
1944 Statement::Query(q) => {
1945 let proj = q.projection.unwrap();
1946 assert_eq!(proj.len(), 2);
1947 }
1948 _ => panic!("expected query"),
1949 }
1950 }
1951
1952 #[test]
1953 fn test_parse_filter_order_limit() {
1954 let stmt = parse("User filter .age > 30 order .name desc limit 10").unwrap();
1955 match stmt {
1956 Statement::Query(q) => {
1957 assert!(q.filter.is_some());
1958 let order = q.order.unwrap();
1959 assert_eq!(order.keys.len(), 1);
1960 assert_eq!(order.keys[0].field, "name");
1961 assert!(order.keys[0].descending);
1962 assert!(q.limit.is_some());
1963 }
1964 _ => panic!("expected query"),
1965 }
1966 }
1967
1968 #[test]
1969 fn test_parse_insert() {
1970 let stmt = parse(r#"insert User { name := "Alice", age := 30 }"#).unwrap();
1971 match stmt {
1972 Statement::Insert(ins) => {
1973 assert_eq!(ins.target, "User");
1974 assert_eq!(ins.assignments.len(), 2);
1975 assert_eq!(ins.assignments[0].field, "name");
1976 assert_eq!(ins.assignments[1].field, "age");
1977 }
1978 _ => panic!("expected insert"),
1979 }
1980 }
1981
1982 #[test]
1983 fn test_parse_update() {
1984 let stmt = parse(r#"User filter .email = "alice@ex.com" update { age := 31 }"#).unwrap();
1985 match stmt {
1986 Statement::UpdateQuery(upd) => {
1987 assert_eq!(upd.source, "User");
1988 assert!(upd.filter.is_some());
1989 assert_eq!(upd.assignments.len(), 1);
1990 }
1991 _ => panic!("expected update"),
1992 }
1993 }
1994
1995 #[test]
1996 fn test_parse_delete() {
1997 let stmt = parse("User filter .age < 18 delete").unwrap();
1998 match stmt {
1999 Statement::DeleteQuery(del) => {
2000 assert_eq!(del.source, "User");
2001 assert!(del.filter.is_some());
2002 }
2003 _ => panic!("expected delete"),
2004 }
2005 }
2006
2007 #[test]
2008 fn test_parse_count() {
2009 let stmt = parse("count(User)").unwrap();
2010 match stmt {
2011 Statement::Query(q) => {
2012 let agg = q.aggregation.unwrap();
2013 assert_eq!(agg.function, AggFunc::Count);
2014 assert!(q.filter.is_none());
2015 }
2016 _ => panic!("expected query with aggregation"),
2017 }
2018 }
2019
2020 #[test]
2021 fn test_parse_count_with_filter() {
2022 let stmt = parse("count(User filter .age > 30)").unwrap();
2025 match stmt {
2026 Statement::Query(q) => {
2027 assert_eq!(q.source, "User");
2028 let agg = q.aggregation.unwrap();
2029 assert_eq!(agg.function, AggFunc::Count);
2030 assert!(q.filter.is_some(), "filter should have been parsed");
2031 }
2032 _ => panic!("expected query with aggregation"),
2033 }
2034 }
2035
2036 #[test]
2037 fn test_parse_count_with_filter_and_limit() {
2038 let stmt = parse("count(User filter .age > 30 limit 100)").unwrap();
2039 match stmt {
2040 Statement::Query(q) => {
2041 assert_eq!(q.source, "User");
2042 assert!(q.filter.is_some());
2043 assert!(q.limit.is_some());
2044 assert_eq!(q.aggregation.unwrap().function, AggFunc::Count);
2045 }
2046 _ => panic!("expected query with aggregation"),
2047 }
2048 }
2049
2050 #[test]
2051 fn test_parse_create_type() {
2052 let stmt = parse("type User { required name: str, age: int }").unwrap();
2053 match stmt {
2054 Statement::CreateType(ct) => {
2055 assert_eq!(ct.name, "User");
2056 assert_eq!(ct.fields.len(), 2);
2057 assert!(ct.fields[0].required);
2058 assert!(!ct.fields[1].required);
2059 }
2060 _ => panic!("expected create type"),
2061 }
2062 }
2063
2064 #[test]
2065 fn test_parse_sum_with_field_projection() {
2066 let stmt = parse("sum(User filter .age > 30 { .age })").unwrap();
2069 match stmt {
2070 Statement::Query(q) => {
2071 let agg = q.aggregation.expect("aggregate");
2072 assert_eq!(agg.function, AggFunc::Sum);
2073 assert_eq!(agg.field.as_deref(), Some("age"));
2074 assert!(
2075 q.projection.is_none(),
2076 "projection should be lifted into agg.field"
2077 );
2078 }
2079 _ => panic!("expected query"),
2080 }
2081 }
2082
2083 #[test]
2084 fn test_parse_avg_min_max_with_field() {
2085 for (src, expected) in [
2086 ("avg(User { .age })", AggFunc::Avg),
2087 ("min(User { .age })", AggFunc::Min),
2088 ("max(User { .age })", AggFunc::Max),
2089 ] {
2090 let stmt = parse(src).unwrap();
2091 match stmt {
2092 Statement::Query(q) => {
2093 let agg = q.aggregation.unwrap();
2094 assert_eq!(agg.function, expected, "func mismatch for {src}");
2095 assert_eq!(
2096 agg.field.as_deref(),
2097 Some("age"),
2098 "field mismatch for {src}"
2099 );
2100 assert!(
2101 q.projection.is_none(),
2102 "projection should be cleared for {src}"
2103 );
2104 }
2105 _ => panic!("expected query for {src}"),
2106 }
2107 }
2108 }
2109
2110 #[test]
2111 fn test_parse_count_leaves_projection_alone() {
2112 let stmt = parse("count(User { .age })").unwrap();
2115 match stmt {
2116 Statement::Query(q) => {
2117 let agg = q.aggregation.unwrap();
2118 assert_eq!(agg.function, AggFunc::Count);
2119 assert!(agg.field.is_none());
2120 assert!(q.projection.is_some(), "count must not eat projection");
2121 }
2122 _ => panic!("expected query"),
2123 }
2124 }
2125
2126 #[test]
2131 fn test_parse_source_alias() {
2132 let stmt = parse("User as u filter u.age > 30").unwrap();
2133 match stmt {
2134 Statement::Query(q) => {
2135 assert_eq!(q.source, "User");
2136 assert_eq!(q.alias.as_deref(), Some("u"));
2137 assert!(q.joins.is_empty());
2138 match q.filter.unwrap() {
2139 Expr::BinaryOp(l, BinOp::Gt, _) => match *l {
2140 Expr::QualifiedField { qualifier, field } => {
2141 assert_eq!(qualifier, "u");
2142 assert_eq!(field, "age");
2143 }
2144 other => panic!("expected qualified field, got {other:?}"),
2145 },
2146 other => panic!("expected >, got {other:?}"),
2147 }
2148 }
2149 _ => panic!("expected query"),
2150 }
2151 }
2152
2153 #[test]
2154 fn test_parse_inner_join_on() {
2155 let stmt = parse("User as u inner join Order as o on u.id = o.user_id").unwrap();
2156 match stmt {
2157 Statement::Query(q) => {
2158 assert_eq!(q.source, "User");
2159 assert_eq!(q.alias.as_deref(), Some("u"));
2160 assert_eq!(q.joins.len(), 1);
2161 let j = &q.joins[0];
2162 assert_eq!(j.kind, JoinKind::Inner);
2163 assert_eq!(j.source, "Order");
2164 assert_eq!(j.alias.as_deref(), Some("o"));
2165 let on = j.on.as_ref().expect("on clause");
2166 match on {
2167 Expr::BinaryOp(l, BinOp::Eq, r) => {
2168 assert!(matches!(**l, Expr::QualifiedField { .. }));
2169 assert!(matches!(**r, Expr::QualifiedField { .. }));
2170 }
2171 other => panic!("expected eq, got {other:?}"),
2172 }
2173 }
2174 _ => panic!("expected query"),
2175 }
2176 }
2177
2178 #[test]
2179 fn test_parse_bare_join_defaults_to_inner() {
2180 let stmt = parse("User join Order on User.id = Order.user_id").unwrap();
2181 match stmt {
2182 Statement::Query(q) => {
2183 assert_eq!(q.joins.len(), 1);
2184 assert_eq!(q.joins[0].kind, JoinKind::Inner);
2185 }
2186 _ => panic!("expected query"),
2187 }
2188 }
2189
2190 #[test]
2191 fn test_parse_left_outer_join() {
2192 let stmt = parse("User as u left outer join Order as o on u.id = o.user_id").unwrap();
2193 match stmt {
2194 Statement::Query(q) => {
2195 assert_eq!(q.joins.len(), 1);
2196 assert_eq!(q.joins[0].kind, JoinKind::LeftOuter);
2197 }
2198 _ => panic!("expected query"),
2199 }
2200 }
2201
2202 #[test]
2203 fn test_parse_left_join_without_outer_keyword() {
2204 let stmt = parse("User as u left join Order as o on u.id = o.user_id").unwrap();
2206 match stmt {
2207 Statement::Query(q) => {
2208 assert_eq!(q.joins[0].kind, JoinKind::LeftOuter);
2209 }
2210 _ => panic!("expected query"),
2211 }
2212 }
2213
2214 #[test]
2215 fn test_parse_right_join() {
2216 let stmt = parse("User as u right join Order as o on u.id = o.user_id").unwrap();
2217 match stmt {
2218 Statement::Query(q) => {
2219 assert_eq!(q.joins[0].kind, JoinKind::RightOuter);
2220 }
2221 _ => panic!("expected query"),
2222 }
2223 }
2224
2225 #[test]
2226 fn test_parse_cross_join_has_no_on() {
2227 let stmt = parse("User cross join Order").unwrap();
2228 match stmt {
2229 Statement::Query(q) => {
2230 assert_eq!(q.joins[0].kind, JoinKind::Cross);
2231 assert!(q.joins[0].on.is_none());
2232 }
2233 _ => panic!("expected query"),
2234 }
2235 }
2236
2237 #[test]
2238 fn test_parse_multi_join_chain() {
2239 let stmt = parse(
2240 "User as u join Order as o on u.id = o.user_id \
2241 join Product as p on o.product_id = p.id",
2242 )
2243 .unwrap();
2244 match stmt {
2245 Statement::Query(q) => {
2246 assert_eq!(q.joins.len(), 2);
2247 assert_eq!(q.joins[0].source, "Order");
2248 assert_eq!(q.joins[1].source, "Product");
2249 }
2250 _ => panic!("expected query"),
2251 }
2252 }
2253
2254 #[test]
2255 fn test_parse_join_with_filter_tail() {
2256 let stmt = parse(
2258 "User as u join Order as o on u.id = o.user_id \
2259 filter o.total > 100 order .name limit 10",
2260 )
2261 .unwrap();
2262 match stmt {
2263 Statement::Query(q) => {
2264 assert_eq!(q.joins.len(), 1);
2265 assert!(q.filter.is_some());
2266 assert!(q.order.is_some());
2267 assert!(q.limit.is_some());
2268 }
2269 _ => panic!("expected query"),
2270 }
2271 }
2272
2273 #[test]
2274 fn test_parse_join_requires_on_for_inner() {
2275 let err = parse("User join Order").unwrap_err();
2277 assert!(
2278 err.message().contains("on"),
2279 "expected on-clause error, got {:?}",
2280 err.message()
2281 );
2282 }
2283
2284 #[test]
2285 fn test_parse_update_on_joined_query_errors() {
2286 let err =
2289 parse("User as u join Order as o on u.id = o.user_id update { age := 1 }").unwrap_err();
2290 assert!(err.message().contains("update"));
2291 }
2292
2293 #[test]
2294 fn test_parse_delete_on_joined_query_errors() {
2295 let err = parse("User as u join Order as o on u.id = o.user_id delete").unwrap_err();
2296 assert!(err.message().contains("delete"));
2297 }
2298
2299 #[test]
2302 fn test_parse_distinct() {
2303 let stmt = parse("User distinct { .name }").unwrap();
2304 match stmt {
2305 Statement::Query(q) => {
2306 assert!(q.distinct);
2307 assert!(q.projection.is_some());
2308 }
2309 _ => panic!("expected query"),
2310 }
2311 }
2312
2313 #[test]
2314 fn test_parse_in_list() {
2315 let stmt = parse(r#"User filter .name in ("Alice", "Bob")"#).unwrap();
2316 match stmt {
2317 Statement::Query(q) => match q.filter.unwrap() {
2318 Expr::InList {
2319 expr,
2320 list,
2321 negated,
2322 } => {
2323 assert!(!negated);
2324 assert!(matches!(*expr, Expr::Field(f) if f == "name"));
2325 assert_eq!(list.len(), 2);
2326 }
2327 other => panic!("expected InList, got {other:?}"),
2328 },
2329 _ => panic!("expected query"),
2330 }
2331 }
2332
2333 #[test]
2334 fn test_parse_not_in_list() {
2335 let stmt = parse("User filter .age not in (1, 2, 3)").unwrap();
2336 match stmt {
2337 Statement::Query(q) => match q.filter.unwrap() {
2338 Expr::InList { negated, list, .. } => {
2339 assert!(negated);
2340 assert_eq!(list.len(), 3);
2341 }
2342 other => panic!("expected InList, got {other:?}"),
2343 },
2344 _ => panic!("expected query"),
2345 }
2346 }
2347
2348 #[test]
2349 fn test_parse_between() {
2350 let stmt = parse("User filter .age between 10 and 20").unwrap();
2352 match stmt {
2353 Statement::Query(q) => {
2354 match q.filter.unwrap() {
2355 Expr::BinaryOp(_, BinOp::And, _) => {} other => panic!("expected And (desugared between), got {other:?}"),
2357 }
2358 }
2359 _ => panic!("expected query"),
2360 }
2361 }
2362
2363 #[test]
2364 fn test_parse_not_between() {
2365 let stmt = parse("User filter .age not between 10 and 20").unwrap();
2367 match stmt {
2368 Statement::Query(q) => {
2369 match q.filter.unwrap() {
2370 Expr::BinaryOp(_, BinOp::Or, _) => {} other => panic!("expected Or (desugared not between), got {other:?}"),
2372 }
2373 }
2374 _ => panic!("expected query"),
2375 }
2376 }
2377
2378 #[test]
2379 fn test_parse_like() {
2380 let stmt = parse(r#"User filter .name like "A%""#).unwrap();
2381 match stmt {
2382 Statement::Query(q) => match q.filter.unwrap() {
2383 Expr::BinaryOp(l, BinOp::Like, r) => {
2384 assert!(matches!(*l, Expr::Field(f) if f == "name"));
2385 assert!(matches!(*r, Expr::Literal(Literal::String(s)) if s == "A%"));
2386 }
2387 other => panic!("expected Like, got {other:?}"),
2388 },
2389 _ => panic!("expected query"),
2390 }
2391 }
2392
2393 #[test]
2394 fn test_parse_not_like() {
2395 let stmt = parse(r#"User filter .name not like "A%""#).unwrap();
2396 match stmt {
2397 Statement::Query(q) => match q.filter.unwrap() {
2398 Expr::UnaryOp(UnaryOp::Not, inner) => {
2399 assert!(matches!(*inner, Expr::BinaryOp(_, BinOp::Like, _)));
2400 }
2401 other => panic!("expected Not(Like), got {other:?}"),
2402 },
2403 _ => panic!("expected query"),
2404 }
2405 }
2406
2407 #[test]
2410 fn test_parse_group_by_single_key() {
2411 let stmt = parse("User group .status { .status, n: count(.name) }").unwrap();
2412 match stmt {
2413 Statement::Query(q) => {
2414 let gb = q.group_by.unwrap();
2415 assert_eq!(gb.keys, vec!["status"]);
2416 assert!(gb.having.is_none());
2417 let proj = q.projection.unwrap();
2418 assert_eq!(proj.len(), 2);
2419 assert!(matches!(
2420 &proj[1].expr,
2421 Expr::FunctionCall(AggFunc::Count, _)
2422 ));
2423 assert_eq!(proj[1].alias.as_deref(), Some("n"));
2424 }
2425 _ => panic!("expected query"),
2426 }
2427 }
2428
2429 #[test]
2430 fn test_parse_group_by_multi_key() {
2431 let stmt = parse("User group .status, .age { .status, .age }").unwrap();
2432 match stmt {
2433 Statement::Query(q) => {
2434 let gb = q.group_by.unwrap();
2435 assert_eq!(gb.keys, vec!["status", "age"]);
2436 }
2437 _ => panic!("expected query"),
2438 }
2439 }
2440
2441 #[test]
2442 fn test_parse_group_by_having() {
2443 let stmt = parse("User group .status having count(.name) > 1 { .status }").unwrap();
2444 match stmt {
2445 Statement::Query(q) => {
2446 let gb = q.group_by.unwrap();
2447 assert_eq!(gb.keys, vec!["status"]);
2448 assert!(gb.having.is_some());
2449 match gb.having.unwrap() {
2451 Expr::BinaryOp(l, BinOp::Gt, _) => {
2452 assert!(matches!(*l, Expr::FunctionCall(AggFunc::Count, _)));
2453 }
2454 other => panic!("expected BinaryOp, got {other:?}"),
2455 }
2456 }
2457 _ => panic!("expected query"),
2458 }
2459 }
2460
2461 #[test]
2462 fn test_parse_aggregate_in_projection() {
2463 let stmt = parse("User group .status { .status, count(.name), sum(.age) }").unwrap();
2465 match stmt {
2466 Statement::Query(q) => {
2467 let proj = q.projection.unwrap();
2468 assert_eq!(proj.len(), 3);
2469 assert!(matches!(
2470 &proj[1].expr,
2471 Expr::FunctionCall(AggFunc::Count, _)
2472 ));
2473 assert!(matches!(&proj[2].expr, Expr::FunctionCall(AggFunc::Sum, _)));
2474 }
2475 _ => panic!("expected query"),
2476 }
2477 }
2478
2479 #[test]
2480 fn test_parse_aggregate_in_aliased_projection() {
2481 let stmt = parse("User group .status { .status, total: count(.name), average: avg(.age) }")
2482 .unwrap();
2483 match stmt {
2484 Statement::Query(q) => {
2485 let proj = q.projection.unwrap();
2486 assert_eq!(proj[1].alias.as_deref(), Some("total"));
2487 assert!(matches!(
2488 &proj[1].expr,
2489 Expr::FunctionCall(AggFunc::Count, _)
2490 ));
2491 assert_eq!(proj[2].alias.as_deref(), Some("average"));
2492 assert!(matches!(&proj[2].expr, Expr::FunctionCall(AggFunc::Avg, _)));
2493 }
2494 _ => panic!("expected query"),
2495 }
2496 }
2497
2498 #[test]
2501 fn test_parse_is_null() {
2502 let stmt = parse("User filter .age is null").unwrap();
2503 match stmt {
2504 Statement::Query(q) => {
2505 let filter = q.filter.unwrap();
2506 assert_eq!(
2507 filter,
2508 Expr::UnaryOp(UnaryOp::IsNull, Box::new(Expr::Field("age".into())))
2509 );
2510 }
2511 _ => panic!("expected query"),
2512 }
2513 }
2514
2515 #[test]
2516 fn test_parse_is_not_null() {
2517 let stmt = parse("User filter .age is not null").unwrap();
2518 match stmt {
2519 Statement::Query(q) => {
2520 let filter = q.filter.unwrap();
2521 assert_eq!(
2522 filter,
2523 Expr::UnaryOp(UnaryOp::IsNotNull, Box::new(Expr::Field("age".into())))
2524 );
2525 }
2526 _ => panic!("expected query"),
2527 }
2528 }
2529
2530 #[test]
2531 fn test_parse_eq_null_desugars_to_is_null() {
2532 let stmt = parse("User filter .age = null").unwrap();
2533 match stmt {
2534 Statement::Query(q) => {
2535 let filter = q.filter.unwrap();
2536 assert_eq!(
2537 filter,
2538 Expr::UnaryOp(UnaryOp::IsNull, Box::new(Expr::Field("age".into())))
2539 );
2540 }
2541 _ => panic!("expected query"),
2542 }
2543 }
2544
2545 #[test]
2546 fn test_parse_neq_null_desugars_to_is_not_null() {
2547 let stmt = parse("User filter .age != null").unwrap();
2548 match stmt {
2549 Statement::Query(q) => {
2550 let filter = q.filter.unwrap();
2551 assert_eq!(
2552 filter,
2553 Expr::UnaryOp(UnaryOp::IsNotNull, Box::new(Expr::Field("age".into())))
2554 );
2555 }
2556 _ => panic!("expected query"),
2557 }
2558 }
2559
2560 #[test]
2561 fn test_parse_ordering_null_still_errors() {
2562 assert!(parse("User filter .age < null").is_err());
2564 assert!(parse("User filter .age >= null").is_err());
2565 }
2566
2567 #[test]
2568 fn test_parse_count_star_expr() {
2569 let stmt = parse("User filter count(*) > 0").unwrap();
2570 match stmt {
2571 Statement::Query(q) => {
2572 let filter = q.filter.unwrap();
2573 match filter {
2574 Expr::BinaryOp(left, BinOp::Gt, _) => {
2575 assert_eq!(
2576 *left,
2577 Expr::FunctionCall(AggFunc::Count, Box::new(Expr::Field("*".into())))
2578 );
2579 }
2580 _ => panic!("expected comparison"),
2581 }
2582 }
2583 _ => panic!("expected query"),
2584 }
2585 }
2586
2587 #[test]
2590 fn test_parse_upper_in_filter() {
2591 let stmt = parse(r#"User filter upper(.name) = "ALICE""#).unwrap();
2592 match stmt {
2593 Statement::Query(q) => {
2594 let f = q.filter.unwrap();
2595 match f {
2596 Expr::BinaryOp(left, BinOp::Eq, _right) => {
2597 assert!(matches!(*left, Expr::ScalarFunc(ScalarFn::Upper, _)));
2598 }
2599 _ => panic!("expected binary op with upper"),
2600 }
2601 }
2602 _ => panic!("expected query"),
2603 }
2604 }
2605
2606 #[test]
2607 fn test_parse_substring() {
2608 let stmt = parse("User { sub: substring(.name, 1, 3) }").unwrap();
2609 match stmt {
2610 Statement::Query(q) => {
2611 let proj = q.projection.unwrap();
2612 match &proj[0].expr {
2613 Expr::ScalarFunc(ScalarFn::Substring, args) => {
2614 assert_eq!(args.len(), 3);
2615 }
2616 other => panic!("expected ScalarFunc Substring, got {other:?}"),
2617 }
2618 }
2619 _ => panic!("expected query"),
2620 }
2621 }
2622
2623 #[test]
2624 fn test_parse_concat() {
2625 let stmt = parse(r#"User { full: concat(.name, " - ", .email) }"#).unwrap();
2626 match stmt {
2627 Statement::Query(q) => {
2628 let proj = q.projection.unwrap();
2629 match &proj[0].expr {
2630 Expr::ScalarFunc(ScalarFn::Concat, args) => {
2631 assert_eq!(args.len(), 3);
2632 }
2633 other => panic!("expected ScalarFunc Concat, got {other:?}"),
2634 }
2635 }
2636 _ => panic!("expected query"),
2637 }
2638 }
2639
2640 #[test]
2643 fn test_parse_case_single_when() {
2644 let stmt = parse(r#"User filter case when .age > 30 then true else false end"#).unwrap();
2645 match stmt {
2646 Statement::Query(q) => {
2647 let filter = q.filter.unwrap();
2648 match filter {
2649 Expr::Case { whens, else_expr } => {
2650 assert_eq!(whens.len(), 1);
2651 assert!(else_expr.is_some());
2652 }
2653 other => panic!("expected Case expr, got {other:?}"),
2654 }
2655 }
2656 _ => panic!("expected query"),
2657 }
2658 }
2659
2660 #[test]
2661 fn test_parse_case_multiple_whens() {
2662 let stmt = parse(
2663 r#"User { label: case when .age > 30 then "senior" when .age > 20 then "adult" else "young" end }"#
2664 ).unwrap();
2665 match stmt {
2666 Statement::Query(q) => {
2667 let proj = q.projection.unwrap();
2668 match &proj[0].expr {
2669 Expr::Case { whens, else_expr } => {
2670 assert_eq!(whens.len(), 2);
2671 assert!(else_expr.is_some());
2672 }
2673 other => panic!("expected Case expr, got {other:?}"),
2674 }
2675 }
2676 _ => panic!("expected query"),
2677 }
2678 }
2679
2680 #[test]
2681 fn test_parse_case_without_else() {
2682 let stmt = parse(r#"User filter case when .age > 30 then true end"#).unwrap();
2683 match stmt {
2684 Statement::Query(q) => {
2685 let filter = q.filter.unwrap();
2686 match filter {
2687 Expr::Case { whens, else_expr } => {
2688 assert_eq!(whens.len(), 1);
2689 assert!(else_expr.is_none());
2690 }
2691 other => panic!("expected Case expr, got {other:?}"),
2692 }
2693 }
2694 _ => panic!("expected query"),
2695 }
2696 }
2697
2698 #[test]
2701 fn test_parse_mul_expr() {
2702 let stmt = parse("User filter .price * .quantity > 100").unwrap();
2703 match stmt {
2704 Statement::Query(q) => {
2705 let filter = q.filter.unwrap();
2706 match filter {
2707 Expr::BinaryOp(left, BinOp::Gt, _) => match *left {
2708 Expr::BinaryOp(_, BinOp::Mul, _) => {}
2709 other => panic!("expected Mul, got {other:?}"),
2710 },
2711 other => panic!("expected BinaryOp Gt, got {other:?}"),
2712 }
2713 }
2714 _ => panic!("expected query"),
2715 }
2716 }
2717
2718 #[test]
2719 fn test_parse_div_expr() {
2720 let stmt = parse("User { ratio: .total / .count }").unwrap();
2721 match stmt {
2722 Statement::Query(q) => {
2723 let proj = q.projection.unwrap();
2724 assert_eq!(proj[0].alias.as_deref(), Some("ratio"));
2725 match &proj[0].expr {
2726 Expr::BinaryOp(_, BinOp::Div, _) => {}
2727 other => panic!("expected Div, got {other:?}"),
2728 }
2729 }
2730 _ => panic!("expected query"),
2731 }
2732 }
2733
2734 #[test]
2735 fn test_parse_mul_div_precedence() {
2736 let stmt = parse("User filter .a + .b * .c > 0").unwrap();
2738 match stmt {
2739 Statement::Query(q) => {
2740 let filter = q.filter.unwrap();
2741 match filter {
2742 Expr::BinaryOp(left, BinOp::Gt, _) => match *left {
2743 Expr::BinaryOp(_, BinOp::Add, right) => {
2744 assert!(matches!(*right, Expr::BinaryOp(_, BinOp::Mul, _)));
2745 }
2746 other => panic!("expected Add, got {other:?}"),
2747 },
2748 other => panic!("expected Gt, got {other:?}"),
2749 }
2750 }
2751 _ => panic!("expected query"),
2752 }
2753 }
2754
2755 #[test]
2758 fn test_parse_multi_order() {
2759 let stmt = parse("User order .name asc, .age desc").unwrap();
2760 match stmt {
2761 Statement::Query(q) => {
2762 let order = q.order.unwrap();
2763 assert_eq!(order.keys.len(), 2);
2764 assert_eq!(order.keys[0].field, "name");
2765 assert!(!order.keys[0].descending);
2766 assert_eq!(order.keys[1].field, "age");
2767 assert!(order.keys[1].descending);
2768 }
2769 _ => panic!("expected query"),
2770 }
2771 }
2772
2773 #[test]
2774 fn test_parse_order_default_asc() {
2775 let stmt = parse("User order .name").unwrap();
2776 match stmt {
2777 Statement::Query(q) => {
2778 let order = q.order.unwrap();
2779 assert_eq!(order.keys.len(), 1);
2780 assert!(!order.keys[0].descending);
2781 }
2782 _ => panic!("expected query"),
2783 }
2784 }
2785
2786 #[test]
2789 fn test_parse_alter_add_column() {
2790 let stmt = parse("alter User add column status: str").unwrap();
2791 match stmt {
2792 Statement::AlterTable(at) => {
2793 assert_eq!(at.table, "User");
2794 match at.action {
2795 AlterAction::AddColumn {
2796 name,
2797 type_name,
2798 required,
2799 } => {
2800 assert_eq!(name, "status");
2801 assert_eq!(type_name, "str");
2802 assert!(!required);
2803 }
2804 other => panic!("expected AddColumn, got {other:?}"),
2805 }
2806 }
2807 other => panic!("expected AlterTable, got {other:?}"),
2808 }
2809 }
2810
2811 #[test]
2812 fn test_parse_alter_add_required_column() {
2813 let stmt = parse("alter User add required status: str").unwrap();
2814 match stmt {
2815 Statement::AlterTable(at) => match at.action {
2816 AlterAction::AddColumn { required, .. } => assert!(required),
2817 other => panic!("expected AddColumn, got {other:?}"),
2818 },
2819 other => panic!("expected AlterTable, got {other:?}"),
2820 }
2821 }
2822
2823 #[test]
2824 fn test_parse_alter_drop_column() {
2825 let stmt = parse("alter User drop column status").unwrap();
2826 match stmt {
2827 Statement::AlterTable(at) => {
2828 assert_eq!(at.table, "User");
2829 match at.action {
2830 AlterAction::DropColumn { name } => assert_eq!(name, "status"),
2831 other => panic!("expected DropColumn, got {other:?}"),
2832 }
2833 }
2834 other => panic!("expected AlterTable, got {other:?}"),
2835 }
2836 }
2837
2838 #[test]
2839 fn test_parse_alter_drop_without_column_keyword() {
2840 let stmt = parse("alter User drop status").unwrap();
2841 match stmt {
2842 Statement::AlterTable(at) => match at.action {
2843 AlterAction::DropColumn { name } => assert_eq!(name, "status"),
2844 other => panic!("expected DropColumn, got {other:?}"),
2845 },
2846 other => panic!("expected AlterTable, got {other:?}"),
2847 }
2848 }
2849
2850 #[test]
2851 fn test_parse_drop_table() {
2852 let stmt = parse("drop User").unwrap();
2853 match stmt {
2854 Statement::DropTable(dt) => assert_eq!(dt.table, "User"),
2855 other => panic!("expected DropTable, got {other:?}"),
2856 }
2857 }
2858
2859 #[test]
2862 fn test_parse_in_subquery() {
2863 let stmt = parse("User filter .name in (VIP { .name })").unwrap();
2864 match stmt {
2865 Statement::Query(q) => {
2866 let filter = q.filter.unwrap();
2867 match filter {
2868 Expr::InSubquery {
2869 expr,
2870 subquery,
2871 negated,
2872 } => {
2873 assert!(!negated);
2874 assert!(matches!(*expr, Expr::Field(ref f) if f == "name"));
2875 assert_eq!(subquery.source, "VIP");
2876 }
2877 other => panic!("expected InSubquery, got {other:?}"),
2878 }
2879 }
2880 _ => panic!("expected query"),
2881 }
2882 }
2883
2884 #[test]
2885 fn test_parse_not_in_subquery() {
2886 let stmt = parse("User filter .id not in (Order { .user_id })").unwrap();
2887 match stmt {
2888 Statement::Query(q) => match q.filter.unwrap() {
2889 Expr::InSubquery { negated, .. } => assert!(negated),
2890 other => panic!("expected InSubquery, got {other:?}"),
2891 },
2892 _ => panic!("expected query"),
2893 }
2894 }
2895
2896 #[test]
2897 fn test_parse_in_literal_list_still_works() {
2898 let stmt = parse("User filter .age in (25, 30, 35)").unwrap();
2900 match stmt {
2901 Statement::Query(q) => match q.filter.unwrap() {
2902 Expr::InList { list, negated, .. } => {
2903 assert!(!negated);
2904 assert_eq!(list.len(), 3);
2905 }
2906 other => panic!("expected InList, got {other:?}"),
2907 },
2908 _ => panic!("expected query"),
2909 }
2910 }
2911
2912 #[test]
2915 fn test_parse_create_view() {
2916 let stmt = parse("materialize OldUsers as User filter .age > 28").unwrap();
2917 match stmt {
2918 Statement::CreateView(cv) => {
2919 assert_eq!(cv.name, "OldUsers");
2920 assert_eq!(cv.query.source, "User");
2921 assert!(cv.query.filter.is_some());
2922 assert!(!cv.query_text.is_empty());
2923 }
2924 _ => panic!("expected CreateView"),
2925 }
2926 }
2927
2928 #[test]
2929 fn test_parse_create_view_with_projection() {
2930 let stmt = parse("materialize UserNames as User { .name }").unwrap();
2931 match stmt {
2932 Statement::CreateView(cv) => {
2933 assert_eq!(cv.name, "UserNames");
2934 assert!(cv.query.projection.is_some());
2935 }
2936 _ => panic!("expected CreateView"),
2937 }
2938 }
2939
2940 #[test]
2941 fn test_parse_refresh_view() {
2942 let stmt = parse("refresh OldUsers").unwrap();
2943 match stmt {
2944 Statement::RefreshView(rv) => {
2945 assert_eq!(rv.name, "OldUsers");
2946 }
2947 _ => panic!("expected RefreshView"),
2948 }
2949 }
2950
2951 #[test]
2952 fn test_parse_drop_view() {
2953 let stmt = parse("drop view OldUsers").unwrap();
2954 match stmt {
2955 Statement::DropView(dv) => {
2956 assert_eq!(dv.name, "OldUsers");
2957 }
2958 _ => panic!("expected DropView"),
2959 }
2960 }
2961
2962 #[test]
2963 fn test_parse_drop_table_still_works() {
2964 let stmt = parse("drop Users").unwrap();
2965 match stmt {
2966 Statement::DropTable(dt) => {
2967 assert_eq!(dt.table, "Users");
2968 }
2969 _ => panic!("expected DropTable"),
2970 }
2971 }
2972
2973 #[test]
2974 fn test_parse_union() {
2975 let stmt = parse("User union Order").unwrap();
2976 match stmt {
2977 Statement::Union(u) => {
2978 assert!(!u.all);
2979 match *u.left {
2980 Statement::Query(_) => {}
2981 _ => panic!("expected Query on left"),
2982 }
2983 match *u.right {
2984 Statement::Query(_) => {}
2985 _ => panic!("expected Query on right"),
2986 }
2987 }
2988 _ => panic!("expected Union"),
2989 }
2990 }
2991
2992 #[test]
2993 fn test_parse_union_all() {
2994 let stmt = parse("User union all Order").unwrap();
2995 match stmt {
2996 Statement::Union(u) => {
2997 assert!(u.all, "expected UNION ALL");
2998 match *u.left {
2999 Statement::Query(_) => {}
3000 _ => panic!("expected Query on left"),
3001 }
3002 match *u.right {
3003 Statement::Query(_) => {}
3004 _ => panic!("expected Query on right"),
3005 }
3006 }
3007 _ => panic!("expected Union"),
3008 }
3009 }
3010
3011 #[test]
3012 fn test_parse_union_chain() {
3013 let stmt = parse("User union Order union Product").unwrap();
3015 match stmt {
3016 Statement::Union(outer) => {
3017 assert!(!outer.all);
3018 match *outer.right {
3020 Statement::Query(q) => assert_eq!(q.source, "Product"),
3021 _ => panic!("expected Query(Product) on right"),
3022 }
3023 match *outer.left {
3025 Statement::Union(inner) => {
3026 assert!(!inner.all);
3027 match *inner.left {
3028 Statement::Query(q) => assert_eq!(q.source, "User"),
3029 _ => panic!("expected Query(User)"),
3030 }
3031 match *inner.right {
3032 Statement::Query(q) => assert_eq!(q.source, "Order"),
3033 _ => panic!("expected Query(Order)"),
3034 }
3035 }
3036 _ => panic!("expected inner Union"),
3037 }
3038 }
3039 _ => panic!("expected Union"),
3040 }
3041 }
3042
3043 #[test]
3044 fn test_parse_union_with_filter() {
3045 let stmt = parse("User filter .age > 10 union Order filter .total > 50").unwrap();
3046 match stmt {
3047 Statement::Union(u) => {
3048 assert!(!u.all);
3049 match *u.left {
3051 Statement::Query(q) => {
3052 assert_eq!(q.source, "User");
3053 assert!(q.filter.is_some());
3054 }
3055 _ => panic!("expected Query on left"),
3056 }
3057 match *u.right {
3058 Statement::Query(q) => {
3059 assert_eq!(q.source, "Order");
3060 assert!(q.filter.is_some());
3061 }
3062 _ => panic!("expected Query on right"),
3063 }
3064 }
3065 _ => panic!("expected Union"),
3066 }
3067 }
3068
3069 #[test]
3070 fn test_parse_count_distinct_standalone() {
3071 let stmt = parse("count(distinct User { .name })").unwrap();
3072 match stmt {
3073 Statement::Query(q) => {
3074 let agg = q.aggregation.unwrap();
3075 assert_eq!(agg.function, AggFunc::CountDistinct);
3076 assert_eq!(agg.field.as_deref(), Some("name"));
3077 }
3078 _ => panic!("expected Query"),
3079 }
3080 }
3081
3082 #[test]
3083 fn test_parse_count_distinct_in_projection() {
3084 let stmt = parse("User group .dept { .dept, count(distinct .name) }").unwrap();
3085 match stmt {
3086 Statement::Query(q) => {
3087 let proj = q.projection.unwrap();
3088 assert_eq!(proj.len(), 2);
3089 match &proj[1].expr {
3090 Expr::FunctionCall(func, _) => {
3091 assert_eq!(*func, AggFunc::CountDistinct);
3092 }
3093 _ => panic!("expected FunctionCall"),
3094 }
3095 }
3096 _ => panic!("expected Query"),
3097 }
3098 }
3099
3100 #[test]
3103 fn test_parse_window_row_number_order() {
3104 let stmt = parse("User { .name, rn: row_number() over (order .age) }").unwrap();
3105 match stmt {
3106 Statement::Query(q) => {
3107 let proj = q.projection.unwrap();
3108 assert_eq!(proj.len(), 2);
3109 assert_eq!(proj[1].alias.as_deref(), Some("rn"));
3110 match &proj[1].expr {
3111 Expr::Window {
3112 function,
3113 args,
3114 partition_by,
3115 order_by,
3116 } => {
3117 assert_eq!(*function, WindowFunc::RowNumber);
3118 assert!(args.is_empty());
3119 assert!(partition_by.is_empty());
3120 assert_eq!(order_by.len(), 1);
3121 assert_eq!(order_by[0].field, "age");
3122 assert!(!order_by[0].descending);
3123 }
3124 other => panic!("expected Window, got {other:?}"),
3125 }
3126 }
3127 _ => panic!("expected query"),
3128 }
3129 }
3130
3131 #[test]
3132 fn test_parse_window_sum_partition_order() {
3133 let stmt =
3134 parse("User { .name, s: sum(.salary) over (partition .dept order .salary) }").unwrap();
3135 match stmt {
3136 Statement::Query(q) => {
3137 let proj = q.projection.unwrap();
3138 assert_eq!(proj.len(), 2);
3139 assert_eq!(proj[1].alias.as_deref(), Some("s"));
3140 match &proj[1].expr {
3141 Expr::Window {
3142 function,
3143 args,
3144 partition_by,
3145 order_by,
3146 } => {
3147 assert_eq!(*function, WindowFunc::Sum);
3148 assert_eq!(args.len(), 1);
3149 assert!(matches!(&args[0], Expr::Field(f) if f == "salary"));
3150 assert_eq!(partition_by, &["dept"]);
3151 assert_eq!(order_by.len(), 1);
3152 assert_eq!(order_by[0].field, "salary");
3153 assert!(!order_by[0].descending);
3154 }
3155 other => panic!("expected Window, got {other:?}"),
3156 }
3157 }
3158 _ => panic!("expected query"),
3159 }
3160 }
3161
3162 #[test]
3163 fn test_parse_window_rank_desc() {
3164 let stmt =
3165 parse("User { .dept, .salary, r: rank() over (partition .dept order .salary desc) }")
3166 .unwrap();
3167 match stmt {
3168 Statement::Query(q) => {
3169 let proj = q.projection.unwrap();
3170 assert_eq!(proj.len(), 3);
3171 match &proj[2].expr {
3172 Expr::Window {
3173 function,
3174 partition_by,
3175 order_by,
3176 ..
3177 } => {
3178 assert_eq!(*function, WindowFunc::Rank);
3179 assert_eq!(partition_by, &["dept"]);
3180 assert_eq!(order_by.len(), 1);
3181 assert!(order_by[0].descending);
3182 }
3183 other => panic!("expected Window, got {other:?}"),
3184 }
3185 }
3186 _ => panic!("expected query"),
3187 }
3188 }
3189
3190 #[test]
3191 fn test_parse_window_dense_rank() {
3192 let stmt = parse("User { .name, dr: dense_rank() over (order .score desc) }").unwrap();
3193 match stmt {
3194 Statement::Query(q) => {
3195 let proj = q.projection.unwrap();
3196 assert_eq!(proj.len(), 2);
3197 match &proj[1].expr {
3198 Expr::Window { function, .. } => {
3199 assert_eq!(*function, WindowFunc::DenseRank);
3200 }
3201 other => panic!("expected Window, got {other:?}"),
3202 }
3203 }
3204 _ => panic!("expected query"),
3205 }
3206 }
3207
3208 #[test]
3209 fn test_parse_sum_without_over_is_aggregate() {
3210 let stmt = parse("User group .dept { .dept, total: sum(.salary) }").unwrap();
3212 match stmt {
3213 Statement::Query(q) => {
3214 let proj = q.projection.unwrap();
3215 assert_eq!(proj.len(), 2);
3216 match &proj[1].expr {
3217 Expr::FunctionCall(AggFunc::Sum, _) => {} other => panic!("expected FunctionCall(Sum), got {other:?}"),
3219 }
3220 }
3221 _ => panic!("expected query"),
3222 }
3223 }
3224
3225 #[test]
3226 fn test_nesting_depth_limit() {
3227 let mut query = String::from("User filter ");
3229 for _ in 0..70 {
3230 query.push('(');
3231 }
3232 query.push_str(".age > 1");
3233 for _ in 0..70 {
3234 query.push(')');
3235 }
3236 let result = parse(&query);
3237 assert!(result.is_err());
3238 let err = result.unwrap_err();
3239 assert!(
3240 err.message().contains("nesting depth"),
3241 "expected nesting depth error, got: {}",
3242 err.message()
3243 );
3244 }
3245
3246 #[test]
3247 fn test_moderate_nesting_succeeds() {
3248 let mut query = String::from("User filter ");
3250 for _ in 0..10 {
3251 query.push('(');
3252 }
3253 query.push_str(".age > 1");
3254 for _ in 0..10 {
3255 query.push(')');
3256 }
3257 assert!(parse(&query).is_ok());
3258 }
3259
3260 #[test]
3264 fn test_parse_fuzz_repro_projection_eof() {
3265 let err = parse("nn{").expect_err("unterminated projection must error, not panic");
3266 let _ = err.message();
3267 }
3268
3269 #[test]
3272 fn test_parse_fuzz_repro_short_projection_eof() {
3273 let err = parse("z{").expect_err("unterminated projection must error, not panic");
3274 let _ = err.message();
3275 }
3276}