1use fsqlite_ast::{
22 BinaryOp, ColumnRef, CompoundOp, Cte, CteMaterialized, Distinctness, Expr, FrameBound,
23 FrameExclude, FrameSpec, FrameType, FromClause, FunctionArgs, InSet, JoinClause,
24 JoinConstraint, JoinKind, JoinType, JsonArrow, LikeOp, LimitClause, Literal, NullsOrder,
25 OrderingTerm, PlaceholderType, QualifiedName, RaiseAction, ResultColumn, SelectBody,
26 SelectCore, SelectStatement, SortDirection, Span, TableOrSubquery, TypeName, UnaryOp,
27 ValuesClause, WindowDef, WindowReference, WindowSpec, WithClause,
28};
29#[cfg(test)]
30use std::cell::Cell;
31use std::sync::Arc;
32
33use crate::parser::{
34 HeightTracked, MAX_PARSE_DEPTH, ParseError, Parser, is_nonreserved_kw, kw_to_str,
35 starts_bare_window_name, starts_post_dot_identifier, starts_table_star_qualifier,
36 starts_window_base_name,
37};
38use crate::token::{Token, TokenKind};
39
40pub(crate) struct ParsedExpr {
41 pub(crate) expr: Expr,
42 pub(crate) height: u32,
43 is_constant: bool,
44 has_function: bool,
45 root: CachedRoot,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49enum CachedRoot {
50 Other,
51 UnaryPlus,
52 Vector,
53 ScalarSubquery,
54}
55
56fn vector_in_list_arity_error(lhs: &Expr, items: &[ParsedExpr]) -> Option<String> {
57 let expected = match lhs {
58 Expr::RowValue(lhs_terms, _) => lhs_terms.len(),
59 _ => return None,
64 };
65 for item in items {
66 let actual = match &item.expr {
67 Expr::RowValue(element_terms, _) => element_terms.len(),
68 Expr::Subquery(..) => continue,
75 _ => 1,
76 };
77 if actual == expected {
78 continue;
79 }
80 let term_suffix = if actual == 1 { "" } else { "s" };
81 return Some(format!(
82 "IN(...) element has {actual} term{term_suffix} - expected {expected}"
83 ));
84 }
85 None
86}
87
88#[cfg(test)]
89enum DeepExprFrame {
90 Unary {
91 op: UnaryOp,
92 span: Span,
93 right_bp: u8,
94 },
95 Parenthesis {
96 span: Span,
97 },
98}
99
100struct InlineStack<T, const N: usize> {
101 inline: [Option<T>; N],
102 inline_len: usize,
103 spill: Vec<T>,
104}
105
106impl<T, const N: usize> InlineStack<T, N> {
107 fn new() -> Self {
108 Self {
109 inline: [const { None }; N],
110 inline_len: 0,
111 spill: Vec::new(),
112 }
113 }
114
115 fn push(&mut self, value: T) {
116 if self.inline_len < N && self.spill.is_empty() {
117 self.inline[self.inline_len] = Some(value);
118 self.inline_len += 1;
119 } else {
120 #[cfg(test)]
121 if self.spill.is_empty() {
122 PARSE_MACHINE_STACK_SPILLS.set(PARSE_MACHINE_STACK_SPILLS.get().saturating_add(1));
123 }
124 self.spill.push(value);
125 }
126 }
127
128 fn pop(&mut self) -> Option<T> {
129 if let Some(value) = self.spill.pop() {
130 return Some(value);
131 }
132 if self.inline_len == 0 {
133 return None;
134 }
135 self.inline_len -= 1;
136 self.inline[self.inline_len].take()
137 }
138}
139
140struct FunctionBuild {
141 name: String,
142 start: Span,
143 args: FunctionArgs,
144 distinct: bool,
145 height: u32,
146 order_by: Vec<OrderingTerm>,
147 filter: Option<Box<Expr>>,
148 over: Option<WindowSpec>,
149 end: Span,
150}
151
152struct CaseBuild {
153 start: Span,
154 operand: Option<ParsedExpr>,
155 whens: Vec<(ParsedExpr, ParsedExpr)>,
156}
157
158struct SelectBuild {
159 with: Option<WithClause>,
160 first: SelectCore,
161 compounds: Vec<(CompoundOp, SelectCore)>,
162 height: u32,
163 order_by: Vec<OrderingTerm>,
164}
165
166struct CoreBuild {
167 distinct: Distinctness,
168 columns: Vec<ResultColumn>,
169 height: u32,
170 from: Option<FromClause>,
171 where_clause: Option<Box<Expr>>,
172 group_by: Vec<Expr>,
173 having: Option<Box<Expr>>,
174 windows: Vec<WindowDef>,
175}
176
177struct FromBuild {
178 source: TableOrSubquery,
179 joins: Vec<JoinClause>,
180}
181
182struct WindowBuild {
183 base_window: Option<String>,
184 partition_by: Vec<Expr>,
185 order_by: Vec<OrderingTerm>,
186}
187
188pub(crate) struct ParsedFrameBound {
189 pub(crate) value: FrameBound,
190 pub(crate) origin: Token,
191}
192
193fn frame_bound_rank(bound: &FrameBound) -> u8 {
194 match bound {
195 FrameBound::UnboundedPreceding => 0,
196 FrameBound::Preceding(_) => 1,
197 FrameBound::CurrentRow => 2,
198 FrameBound::Following(_) => 3,
199 FrameBound::UnboundedFollowing => 4,
200 }
201}
202
203pub(crate) fn validate_frame_start(
204 start: &ParsedFrameBound,
205 has_explicit_end: bool,
206) -> Result<(), ParseError> {
207 if matches!(start.value, FrameBound::UnboundedFollowing) {
208 return Err(ParseError::unexpected_at(
212 "window frame starting bound must not be UNBOUNDED FOLLOWING",
213 Some(&start.origin),
214 ));
215 }
216 if !has_explicit_end && frame_bound_rank(&start.value) > 2 {
217 return Err(ParseError::semantic_at(
221 "unsupported frame specification",
222 Some(&start.origin),
223 ));
224 }
225 Ok(())
226}
227
228pub(crate) fn validate_frame_end(
229 start: &ParsedFrameBound,
230 end: &ParsedFrameBound,
231) -> Result<(), ParseError> {
232 if matches!(end.value, FrameBound::UnboundedPreceding) {
233 return Err(ParseError::unexpected_at(
237 "window frame ending bound must not be UNBOUNDED PRECEDING",
238 Some(&end.origin),
239 ));
240 }
241 if frame_bound_rank(&end.value) < frame_bound_rank(&start.value) {
242 return Err(ParseError::semantic_at(
245 "unsupported frame specification",
246 Some(&end.origin),
247 ));
248 }
249 Ok(())
250}
251
252#[allow(clippy::large_enum_variant)]
255enum MachineValue {
256 Expr(ParsedExpr),
257 Select(HeightTracked<SelectStatement>),
258 Core(HeightTracked<SelectCore>),
259 From(FromClause),
260 Table(TableOrSubquery),
261 Ordering(HeightTracked<OrderingTerm>),
262 Window(WindowSpec),
263 FrameBound(ParsedFrameBound),
264 With(WithClause),
265}
266
267#[allow(clippy::large_enum_variant)]
270enum ParseControl {
271 ExprStart {
272 min_bp: u8,
273 },
274 ExprTail {
275 min_bp: u8,
276 },
277 UnaryDone {
278 outer_min_bp: u8,
279 op: UnaryOp,
280 span: Span,
281 },
282 CastDone {
283 outer_min_bp: u8,
284 start: Span,
285 },
286 GroupFirstDone {
287 outer_min_bp: u8,
288 start: Span,
289 },
290 RowItemDone {
291 outer_min_bp: u8,
292 start: Span,
293 values: Vec<Expr>,
294 is_constant: bool,
295 has_function: bool,
296 },
297 CaseOperandDone {
298 outer_min_bp: u8,
299 start: Span,
300 },
301 CaseWhenStart {
302 outer_min_bp: u8,
303 build: CaseBuild,
304 },
305 CaseConditionDone {
306 outer_min_bp: u8,
307 build: CaseBuild,
308 },
309 CaseResultDone {
310 outer_min_bp: u8,
311 build: CaseBuild,
312 condition: ParsedExpr,
313 },
314 CaseElseDone {
315 outer_min_bp: u8,
316 build: CaseBuild,
317 },
318 FunctionArgDone {
319 outer_min_bp: u8,
320 build: FunctionBuild,
321 },
322 FunctionOrderStart {
323 outer_min_bp: u8,
324 build: FunctionBuild,
325 },
326 FunctionOrderDone {
327 outer_min_bp: u8,
328 build: FunctionBuild,
329 },
330 FunctionClose {
331 outer_min_bp: u8,
332 build: FunctionBuild,
333 },
334 FunctionFilterDone {
335 outer_min_bp: u8,
336 build: FunctionBuild,
337 has_filter: bool,
338 },
339 FunctionOverDone {
340 outer_min_bp: u8,
341 build: FunctionBuild,
342 },
343 BinaryDone {
344 outer_min_bp: u8,
345 lhs: ParsedExpr,
346 op: BinaryOp,
347 },
348 JsonDone {
349 outer_min_bp: u8,
350 lhs: ParsedExpr,
351 arrow: JsonArrow,
352 },
353 IsDone {
354 outer_min_bp: u8,
355 lhs: ParsedExpr,
356 not: bool,
357 },
358 LikePatternDone {
359 outer_min_bp: u8,
360 lhs: ParsedExpr,
361 op: LikeOp,
362 not: bool,
363 },
364 LikeEscapeDone {
365 outer_min_bp: u8,
366 lhs: ParsedExpr,
367 pattern: ParsedExpr,
368 op: LikeOp,
369 not: bool,
370 },
371 BetweenLowDone {
372 outer_min_bp: u8,
373 lhs: ParsedExpr,
374 not: bool,
375 },
376 BetweenHighDone {
377 outer_min_bp: u8,
378 lhs: ParsedExpr,
379 low: ParsedExpr,
380 not: bool,
381 },
382 InItemDone {
383 outer_min_bp: u8,
384 lhs: ParsedExpr,
385 not: bool,
386 items: Vec<ParsedExpr>,
387 start: Span,
388 },
389 InSelectDone {
390 outer_min_bp: u8,
391 lhs: ParsedExpr,
392 not: bool,
393 start: Span,
394 },
395 ExistsDone {
396 outer_min_bp: u8,
397 not: bool,
398 start: Span,
399 },
400 ScalarSelectDone {
401 outer_min_bp: u8,
402 start: Span,
403 },
404 OrderingStart,
405 OrderingDone,
406 WindowStart,
407 WindowPartitionDone {
408 build: WindowBuild,
409 },
410 WindowOrderStart {
411 build: WindowBuild,
412 },
413 WindowOrderDone {
414 build: WindowBuild,
415 },
416 WindowFrameStart {
417 build: WindowBuild,
418 },
419 WindowFirstBoundDone {
420 build: WindowBuild,
421 frame_type: FrameType,
422 between: bool,
423 },
424 WindowSecondBoundDone {
425 build: WindowBuild,
426 frame_type: FrameType,
427 start: ParsedFrameBound,
428 },
429 FrameBoundStart,
430 FrameBoundExprDone {
431 origin: Token,
432 },
433 SubqueryStart,
434 SubqueryWithDone,
435 SelectStart {
436 with: Option<WithClause>,
437 },
438 SelectFirstCoreDone {
439 with: Option<WithClause>,
440 },
441 SelectCompoundDone {
442 build: SelectBuild,
443 op: CompoundOp,
444 },
445 SelectOrderStart {
446 build: SelectBuild,
447 },
448 SelectOrderDone {
449 build: SelectBuild,
450 },
451 SelectLimitFirstDone {
452 build: SelectBuild,
453 },
454 SelectLimitSecondDone {
455 build: SelectBuild,
456 first: ParsedExpr,
457 comma_form: bool,
458 },
459 CoreStart,
460 CoreColumnStart {
461 build: CoreBuild,
462 },
463 CoreColumnDone {
464 build: CoreBuild,
465 },
466 CoreAfterColumns {
467 build: CoreBuild,
468 },
469 CoreFromDone {
470 build: CoreBuild,
471 },
472 CoreWhereDone {
473 build: CoreBuild,
474 },
475 CoreGroupDone {
476 build: CoreBuild,
477 },
478 CoreHavingDone {
479 build: CoreBuild,
480 },
481 CoreWindowStart {
482 build: CoreBuild,
483 },
484 CoreWindowDone {
485 build: CoreBuild,
486 name: String,
487 },
488 ValuesRowStart {
489 rows: Vec<Vec<Expr>>,
490 height: u32,
491 force_union_all_from: Option<usize>,
492 },
493 ValuesItemDone {
494 rows: Vec<Vec<Expr>>,
495 row: Vec<Expr>,
496 height: u32,
497 force_union_all_from: Option<usize>,
498 },
499 FromStart,
500 FromSourceDone,
501 FromTableDone {
502 build: FromBuild,
503 join_type: JoinType,
504 },
505 FromJoinConstraintDone {
506 build: FromBuild,
507 join_type: JoinType,
508 table: TableOrSubquery,
509 },
510 TableStart,
511 TableSubqueryDone,
512 TableParenJoinDone,
513 TableFunctionArgDone {
514 name: String,
515 args: Vec<Expr>,
516 },
517 WithStart,
518 CteQueryDone {
519 recursive: bool,
520 ctes: Vec<Cte>,
521 name: String,
522 columns: Vec<String>,
523 materialized: Option<CteMaterialized>,
524 },
525}
526
527impl ParsedExpr {
528 fn leaf(expr: Expr) -> Self {
529 let (is_constant, has_function) = match &expr {
530 Expr::Literal(
531 Literal::CurrentTime | Literal::CurrentDate | Literal::CurrentTimestamp,
532 _,
533 ) => (false, true),
534 Expr::Literal(..) | Expr::BoundOuterValue { .. } => (true, false),
535 _ => (false, false),
536 };
537 Self {
538 expr,
539 height: 1,
540 is_constant,
541 has_function,
542 root: CachedRoot::Other,
543 }
544 }
545}
546
547#[cfg(test)]
548enum CachedHeightTask<'a> {
549 Expr(&'a Expr),
550 Select(&'a SelectStatement),
551 SelectCore(&'a SelectCore),
552 Limit(&'a fsqlite_ast::LimitClause),
553 Finish(CachedFinish),
554}
555
556#[cfg(test)]
557#[derive(Clone, Copy)]
558enum CachedFinish {
559 Generic(usize),
560 Unary(UnaryOp),
561 Vector(usize),
562 Like { children: usize, not: bool },
563 Between { not: bool },
564 InList { items: usize, not: bool },
565 InSubquery { not: bool },
566 InTable { not: bool },
567 Exists { not: bool },
568 Subquery,
569 Function { args: usize },
570 Select { expressions: usize },
571 Limit { expressions: usize },
572}
573
574#[cfg(test)]
575#[derive(Clone, Copy)]
576struct CachedFacts {
577 height: u32,
578 is_constant: bool,
579 has_function: bool,
580 root: CachedRoot,
581}
582
583#[cfg(test)]
584impl CachedFacts {
585 const fn leaf(is_constant: bool, has_function: bool) -> Self {
586 Self {
587 height: 1,
588 is_constant,
589 has_function,
590 root: CachedRoot::Other,
591 }
592 }
593}
594
595#[cfg(test)]
596thread_local! {
597 static HEIGHT_WALK_VISITS: Cell<usize> = const { Cell::new(0) };
598 static PARSE_MACHINE_STEPS: Cell<usize> = const { Cell::new(0) };
599 static PARSE_MACHINE_STACK_SPILLS: Cell<usize> = const { Cell::new(0) };
600}
601
602#[cfg(test)]
603fn aggregate_cached_facts(values: &mut Vec<CachedFacts>, count: usize) -> CachedFacts {
604 let start = values.len().saturating_sub(count);
605 let mut facts = CachedFacts {
606 height: 0,
607 is_constant: true,
608 has_function: false,
609 root: CachedRoot::Other,
610 };
611 for child in &values[start..] {
612 facts.height = facts.height.max(child.height);
613 facts.is_constant &= child.is_constant;
614 facts.has_function |= child.has_function;
615 }
616 if count == 1 {
617 facts.root = values[start].root;
618 }
619 values.truncate(start);
620 facts
621}
622
623#[cfg(test)]
624fn cached_facts_from_tasks(mut pending: Vec<CachedHeightTask<'_>>) -> CachedFacts {
625 let mut values = Vec::new();
626 while let Some(task) = pending.pop() {
627 #[cfg(test)]
628 HEIGHT_WALK_VISITS.set(HEIGHT_WALK_VISITS.get() + 1);
629 match task {
630 CachedHeightTask::Expr(current) => match current {
631 Expr::BinaryOp { left, right, .. } => {
632 pending.push(CachedHeightTask::Finish(CachedFinish::Generic(2)));
633 pending.push(CachedHeightTask::Expr(left));
634 pending.push(CachedHeightTask::Expr(right));
635 }
636 Expr::UnaryOp { op, expr, .. } => {
637 pending.push(CachedHeightTask::Finish(CachedFinish::Unary(*op)));
638 pending.push(CachedHeightTask::Expr(expr));
639 }
640 Expr::Cast { expr, .. }
641 | Expr::Collate { expr, .. }
642 | Expr::IsNull { expr, .. } => {
643 pending.push(CachedHeightTask::Finish(CachedFinish::Generic(1)));
644 pending.push(CachedHeightTask::Expr(expr));
645 }
646 Expr::Between {
647 expr,
648 low,
649 high,
650 not,
651 ..
652 } => {
653 pending.push(CachedHeightTask::Finish(CachedFinish::Between {
654 not: *not,
655 }));
656 pending.push(CachedHeightTask::Expr(expr));
657 pending.push(CachedHeightTask::Expr(low));
658 pending.push(CachedHeightTask::Expr(high));
659 }
660 Expr::In { expr, set, not, .. } => match set {
661 InSet::List(values) => {
662 pending.push(CachedHeightTask::Finish(CachedFinish::InList {
663 items: values.len(),
664 not: *not,
665 }));
666 pending.push(CachedHeightTask::Expr(expr));
667 pending.extend(values.iter().map(CachedHeightTask::Expr));
668 }
669 InSet::Subquery(select) => {
670 pending.push(CachedHeightTask::Finish(CachedFinish::InSubquery {
671 not: *not,
672 }));
673 pending.push(CachedHeightTask::Expr(expr));
674 pending.push(CachedHeightTask::Select(select));
675 }
676 InSet::Table(_) => {
677 pending.push(CachedHeightTask::Finish(CachedFinish::InTable {
678 not: *not,
679 }));
680 pending.push(CachedHeightTask::Expr(expr));
681 }
682 },
683 Expr::Like {
684 expr,
685 pattern,
686 escape,
687 not,
688 ..
689 } => {
690 pending.push(CachedHeightTask::Finish(CachedFinish::Like {
691 children: 2 + usize::from(escape.is_some()),
692 not: *not,
693 }));
694 pending.push(CachedHeightTask::Expr(expr));
695 pending.push(CachedHeightTask::Expr(pattern));
696 if let Some(escape) = escape {
697 pending.push(CachedHeightTask::Expr(escape));
698 }
699 }
700 Expr::Case {
701 operand,
702 whens,
703 else_expr,
704 ..
705 } => {
706 let children = usize::from(operand.is_some())
707 + whens.len().saturating_mul(2)
708 + usize::from(else_expr.is_some());
709 pending.push(CachedHeightTask::Finish(CachedFinish::Generic(children)));
710 if let Some(operand) = operand {
711 pending.push(CachedHeightTask::Expr(operand));
712 }
713 for (condition, result) in whens {
714 pending.push(CachedHeightTask::Expr(condition));
715 pending.push(CachedHeightTask::Expr(result));
716 }
717 if let Some(else_expr) = else_expr {
718 pending.push(CachedHeightTask::Expr(else_expr));
719 }
720 }
721 Expr::Exists { subquery, not, .. } => {
722 pending.push(CachedHeightTask::Finish(CachedFinish::Exists { not: *not }));
723 pending.push(CachedHeightTask::Select(subquery));
724 }
725 Expr::Subquery(subquery, _) => {
726 pending.push(CachedHeightTask::Finish(CachedFinish::Subquery));
727 pending.push(CachedHeightTask::Select(subquery));
728 }
729 Expr::FunctionCall { args, .. } => {
730 let FunctionArgs::List(args) = args else {
731 values.push(CachedFacts {
732 height: 1,
733 is_constant: false,
734 has_function: true,
735 root: CachedRoot::Other,
736 });
737 continue;
738 };
739 pending.push(CachedHeightTask::Finish(CachedFinish::Function {
740 args: args.len(),
741 }));
742 pending.extend(args.iter().map(CachedHeightTask::Expr));
743 }
744 Expr::JsonAccess { expr, path, .. } => {
745 pending.push(CachedHeightTask::Finish(CachedFinish::Like {
746 children: 2,
747 not: false,
748 }));
749 pending.push(CachedHeightTask::Expr(expr));
750 pending.push(CachedHeightTask::Expr(path));
751 }
752 Expr::RowValue(items, _) => {
753 pending.push(CachedHeightTask::Finish(CachedFinish::Vector(items.len())));
754 pending.extend(items.iter().map(CachedHeightTask::Expr));
755 }
756 Expr::Literal(
757 Literal::CurrentTime | Literal::CurrentDate | Literal::CurrentTimestamp,
758 _,
759 ) => values.push(CachedFacts::leaf(false, true)),
760 Expr::Literal(..) | Expr::BoundOuterValue { .. } => {
761 values.push(CachedFacts::leaf(true, false));
762 }
763 Expr::Column(column, _) if column.table.is_some() => {
764 values.push(CachedFacts {
765 height: 2,
766 is_constant: false,
767 has_function: false,
768 root: CachedRoot::Other,
769 });
770 }
771 Expr::Column(..) | Expr::Raise { .. } | Expr::Placeholder(..) => {
772 values.push(CachedFacts::leaf(false, false));
773 }
774 },
775 CachedHeightTask::Select(select) => {
776 let expressions = 1
777 + select.body.compounds.len()
778 + select.order_by.len()
779 + usize::from(select.limit.is_some());
780 pending.push(CachedHeightTask::Finish(CachedFinish::Select {
781 expressions,
782 }));
783 pending.push(CachedHeightTask::SelectCore(&select.body.select));
784 pending.extend(
785 select
786 .body
787 .compounds
788 .iter()
789 .map(|(_, core)| CachedHeightTask::SelectCore(core)),
790 );
791 pending.extend(
792 select
793 .order_by
794 .iter()
795 .map(|term| CachedHeightTask::Expr(&term.expr)),
796 );
797 if let Some(limit) = &select.limit {
798 pending.push(CachedHeightTask::Limit(limit));
799 }
800 }
801 CachedHeightTask::SelectCore(core) => match core {
802 SelectCore::Select {
803 columns,
804 where_clause,
805 group_by,
806 having,
807 ..
808 } => {
809 let expressions = columns
810 .iter()
811 .filter(|column| matches!(column, ResultColumn::Expr { .. }))
812 .count()
813 + usize::from(where_clause.is_some())
814 + group_by.len()
815 + usize::from(having.is_some());
816 pending.push(CachedHeightTask::Finish(CachedFinish::Select {
817 expressions,
818 }));
819 pending.extend(columns.iter().filter_map(|column| match column {
820 ResultColumn::Expr { expr, .. } => Some(CachedHeightTask::Expr(expr)),
821 ResultColumn::Star | ResultColumn::TableStar(_) => None,
822 }));
823 if let Some(where_clause) = where_clause {
824 pending.push(CachedHeightTask::Expr(where_clause));
825 }
826 pending.extend(group_by.iter().map(CachedHeightTask::Expr));
827 if let Some(having) = having {
828 pending.push(CachedHeightTask::Expr(having));
829 }
830 }
831 SelectCore::Values(rows) => {
832 let expressions = rows.iter().map(Vec::len).sum();
833 pending.push(CachedHeightTask::Finish(CachedFinish::Select {
834 expressions,
835 }));
836 pending.extend(rows.iter().flatten().map(CachedHeightTask::Expr));
837 }
838 },
839 CachedHeightTask::Limit(limit) => {
840 let expressions = 1 + usize::from(limit.offset.is_some());
841 pending.push(CachedHeightTask::Finish(CachedFinish::Limit {
842 expressions,
843 }));
844 pending.push(CachedHeightTask::Expr(&limit.limit));
845 if let Some(offset) = &limit.offset {
846 pending.push(CachedHeightTask::Expr(offset));
847 }
848 }
849 CachedHeightTask::Finish(finish) => match finish {
850 CachedFinish::Generic(children) => {
851 let mut facts = aggregate_cached_facts(&mut values, children);
852 facts.height = facts.height.saturating_add(1);
853 facts.root = CachedRoot::Other;
854 values.push(facts);
855 }
856 CachedFinish::Unary(op) => {
857 let mut child = values.pop().expect("unary cached-height child");
858 if !(matches!(op, UnaryOp::Plus | UnaryOp::Negate)
859 && child.root == CachedRoot::UnaryPlus)
860 {
861 child.height = child.height.saturating_add(1);
862 }
863 child.root = if op == UnaryOp::Plus {
864 CachedRoot::UnaryPlus
865 } else {
866 CachedRoot::Other
867 };
868 values.push(child);
869 }
870 CachedFinish::Vector(children) => {
871 let mut facts = aggregate_cached_facts(&mut values, children);
872 facts.height = 1;
873 facts.root = CachedRoot::Vector;
874 values.push(facts);
875 }
876 CachedFinish::Like { children, not } => {
877 let mut facts = aggregate_cached_facts(&mut values, children);
878 facts.height = facts
879 .height
880 .saturating_add(1)
881 .saturating_add(u32::from(not));
882 facts.is_constant = false;
883 facts.has_function = true;
884 facts.root = CachedRoot::Other;
885 values.push(facts);
886 }
887 CachedFinish::Between { not } => {
888 let mut facts = aggregate_cached_facts(&mut values, 3);
889 facts.height = facts
890 .height
891 .saturating_add(1)
892 .saturating_add(u32::from(not));
893 facts.root = CachedRoot::Other;
894 values.push(facts);
895 }
896 CachedFinish::InList { items, not } => {
897 let lhs = values.pop().expect("IN cached-height lhs");
898 let item_facts = aggregate_cached_facts(&mut values, items);
899 if items == 0 {
900 values.push(if lhs.has_function {
901 CachedFacts {
902 height: lhs.height.saturating_add(1),
903 is_constant: false,
904 has_function: true,
905 root: CachedRoot::Other,
906 }
907 } else {
908 CachedFacts::leaf(true, false)
909 });
910 continue;
911 }
912 let cached_child_height =
913 if items == 1 && item_facts.is_constant && lhs.root != CachedRoot::Vector {
914 lhs.height.max(item_facts.height.saturating_add(1))
915 } else if items == 1 && item_facts.root == CachedRoot::ScalarSubquery {
916 lhs.height.max(item_facts.height.saturating_sub(1))
917 } else {
918 lhs.height.max(item_facts.height)
919 };
920 values.push(CachedFacts {
921 height: cached_child_height
922 .saturating_add(1)
923 .saturating_add(u32::from(not)),
924 is_constant: lhs.is_constant && item_facts.is_constant,
925 has_function: lhs.has_function || item_facts.has_function,
926 root: CachedRoot::Other,
927 });
928 }
929 CachedFinish::InSubquery { not } => {
930 let lhs = values.pop().expect("IN-subquery cached-height lhs");
931 let select = values.pop().expect("IN-subquery cached-height SELECT");
932 values.push(CachedFacts {
933 height: lhs
934 .height
935 .max(select.height)
936 .saturating_add(1)
937 .saturating_add(u32::from(not)),
938 is_constant: false,
939 has_function: lhs.has_function,
940 root: CachedRoot::Other,
941 });
942 }
943 CachedFinish::InTable { not } => {
944 let lhs = values.pop().expect("IN-table cached-height lhs");
945 values.push(CachedFacts {
946 height: lhs.height.saturating_add(1).saturating_add(u32::from(not)),
947 is_constant: false,
948 has_function: lhs.has_function,
949 root: CachedRoot::Other,
950 });
951 }
952 CachedFinish::Exists { not } => {
953 let select = values.pop().expect("EXISTS cached-height SELECT");
954 values.push(CachedFacts {
955 height: select
956 .height
957 .saturating_add(1)
958 .saturating_add(u32::from(not)),
959 is_constant: false,
960 has_function: false,
961 root: CachedRoot::Other,
962 });
963 }
964 CachedFinish::Subquery => {
965 let select = values.pop().expect("scalar-subquery cached-height SELECT");
966 values.push(CachedFacts {
967 height: select.height.saturating_add(1),
968 is_constant: false,
969 has_function: false,
970 root: CachedRoot::ScalarSubquery,
971 });
972 }
973 CachedFinish::Function { args } => {
974 let facts = aggregate_cached_facts(&mut values, args);
975 values.push(CachedFacts {
976 height: facts.height.saturating_add(1),
977 is_constant: false,
978 has_function: true,
979 root: CachedRoot::Other,
980 });
981 }
982 CachedFinish::Select { expressions } => {
983 let facts = aggregate_cached_facts(&mut values, expressions);
984 values.push(CachedFacts {
985 height: facts.height,
986 is_constant: false,
987 has_function: false,
988 root: CachedRoot::Other,
989 });
990 }
991 CachedFinish::Limit { expressions } => {
992 let mut facts = aggregate_cached_facts(&mut values, expressions);
993 facts.height = facts.height.saturating_add(1);
994 facts.root = CachedRoot::Other;
995 values.push(facts);
996 }
997 },
998 }
999 }
1000 values.pop().unwrap_or(CachedFacts {
1001 height: 0,
1002 is_constant: false,
1003 has_function: false,
1004 root: CachedRoot::Other,
1005 })
1006}
1007
1008#[cfg(test)]
1013#[must_use]
1014fn normalized_ast_expr_height(expr: &Expr) -> u32 {
1015 cached_facts_from_tasks(vec![CachedHeightTask::Expr(expr)]).height
1016}
1017
1018#[cfg(test)]
1023#[must_use]
1024fn normalized_ast_select_height(select: &SelectStatement) -> u32 {
1025 cached_facts_from_tasks(vec![CachedHeightTask::Select(select)]).height
1026}
1027
1028mod bp {
1031 pub const OR: (u8, u8) = (1, 2);
1033 pub const AND: (u8, u8) = (3, 4);
1034 pub const NOT_PREFIX: u8 = 5;
1036 pub const EQUALITY: (u8, u8) = (7, 8);
1038 pub const COMPARISON: (u8, u8) = (9, 10);
1040 pub const BITWISE: (u8, u8) = (13, 14);
1042 pub const ADD: (u8, u8) = (15, 16);
1044 pub const MUL: (u8, u8) = (17, 18);
1046 pub const CONCAT: (u8, u8) = (19, 20);
1048 pub const COLLATE: u8 = 21;
1050 pub const UNARY: u8 = 23;
1052 pub const JSON: (u8, u8) = (19, 20);
1054}
1055
1056struct ParseMachine<'a> {
1057 parser: &'a mut Parser,
1058 controls: InlineStack<ParseControl, 8>,
1059 values: InlineStack<MachineValue, 8>,
1060}
1061
1062impl<'a> ParseMachine<'a> {
1063 fn for_expr(parser: &'a mut Parser) -> Self {
1064 let mut controls = InlineStack::new();
1065 controls.push(ParseControl::ExprStart { min_bp: 0 });
1066 Self {
1067 parser,
1068 controls,
1069 values: InlineStack::new(),
1070 }
1071 }
1072
1073 fn for_select(parser: &'a mut Parser, with: Option<WithClause>) -> Self {
1074 let mut controls = InlineStack::new();
1075 controls.push(ParseControl::SelectStart { with });
1076 Self {
1077 parser,
1078 controls,
1079 values: InlineStack::new(),
1080 }
1081 }
1082
1083 fn for_with(parser: &'a mut Parser) -> Self {
1084 let mut controls = InlineStack::new();
1085 controls.push(ParseControl::WithStart);
1086 Self {
1087 parser,
1088 controls,
1089 values: InlineStack::new(),
1090 }
1091 }
1092
1093 fn for_from(parser: &'a mut Parser) -> Self {
1094 let mut controls = InlineStack::new();
1095 controls.push(ParseControl::FromStart);
1096 Self {
1097 parser,
1098 controls,
1099 values: InlineStack::new(),
1100 }
1101 }
1102
1103 fn run_expr(mut self) -> Result<ParsedExpr, ParseError> {
1104 self.run()?;
1105 self.pop_expr()
1106 }
1107
1108 fn run_select(mut self) -> Result<HeightTracked<SelectStatement>, ParseError> {
1109 self.run()?;
1110 self.pop_select()
1111 }
1112
1113 fn run_with(mut self) -> Result<WithClause, ParseError> {
1114 self.run()?;
1115 self.pop_with()
1116 }
1117
1118 fn run_from(mut self) -> Result<FromClause, ParseError> {
1119 self.run()?;
1120 self.pop_from()
1121 }
1122
1123 fn run(&mut self) -> Result<(), ParseError> {
1124 while let Some(control) = self.controls.pop() {
1125 #[cfg(test)]
1126 PARSE_MACHINE_STEPS.set(PARSE_MACHINE_STEPS.get().saturating_add(1));
1127 self.step(control)?;
1128 }
1129 Ok(())
1130 }
1131
1132 fn pop_expr(&mut self) -> Result<ParsedExpr, ParseError> {
1133 match self.values.pop() {
1134 Some(MachineValue::Expr(expr)) => Ok(expr),
1135 _ => Err(self
1136 .parser
1137 .err_here("internal expression parser state mismatch")),
1138 }
1139 }
1140
1141 fn pop_select(&mut self) -> Result<HeightTracked<SelectStatement>, ParseError> {
1142 match self.values.pop() {
1143 Some(MachineValue::Select(select)) => Ok(select),
1144 _ => Err(self
1145 .parser
1146 .err_here("internal SELECT parser state mismatch")),
1147 }
1148 }
1149
1150 fn pop_core(&mut self) -> Result<HeightTracked<SelectCore>, ParseError> {
1151 match self.values.pop() {
1152 Some(MachineValue::Core(core)) => Ok(core),
1153 _ => Err(self
1154 .parser
1155 .err_here("internal SELECT-core parser state mismatch")),
1156 }
1157 }
1158
1159 fn pop_from(&mut self) -> Result<FromClause, ParseError> {
1160 match self.values.pop() {
1161 Some(MachineValue::From(from)) => Ok(from),
1162 _ => Err(self.parser.err_here("internal FROM parser state mismatch")),
1163 }
1164 }
1165
1166 fn pop_table(&mut self) -> Result<TableOrSubquery, ParseError> {
1167 match self.values.pop() {
1168 Some(MachineValue::Table(table)) => Ok(table),
1169 _ => Err(self.parser.err_here("internal table parser state mismatch")),
1170 }
1171 }
1172
1173 fn pop_ordering(&mut self) -> Result<HeightTracked<OrderingTerm>, ParseError> {
1174 match self.values.pop() {
1175 Some(MachineValue::Ordering(term)) => Ok(term),
1176 _ => Err(self
1177 .parser
1178 .err_here("internal ORDER BY parser state mismatch")),
1179 }
1180 }
1181
1182 fn pop_window(&mut self) -> Result<WindowSpec, ParseError> {
1183 match self.values.pop() {
1184 Some(MachineValue::Window(window)) => Ok(window),
1185 _ => Err(self
1186 .parser
1187 .err_here("internal WINDOW parser state mismatch")),
1188 }
1189 }
1190
1191 fn pop_frame_bound(&mut self) -> Result<ParsedFrameBound, ParseError> {
1192 match self.values.pop() {
1193 Some(MachineValue::FrameBound(bound)) => Ok(bound),
1194 _ => Err(self
1195 .parser
1196 .err_here("internal frame-bound parser state mismatch")),
1197 }
1198 }
1199
1200 fn pop_with(&mut self) -> Result<WithClause, ParseError> {
1201 match self.values.pop() {
1202 Some(MachineValue::With(with)) => Ok(with),
1203 _ => Err(self.parser.err_here("internal WITH parser state mismatch")),
1204 }
1205 }
1206
1207 fn push_expr_tail(&mut self, expr: ParsedExpr, min_bp: u8) {
1208 self.values.push(MachineValue::Expr(expr));
1209 self.controls.push(ParseControl::ExprTail { min_bp });
1210 }
1211
1212 fn finish_function(
1213 &mut self,
1214 outer_min_bp: u8,
1215 build: FunctionBuild,
1216 ) -> Result<(), ParseError> {
1217 let span = build.start.merge(build.end);
1218 let parsed = self.parser.checked_expr(
1219 Expr::FunctionCall {
1220 name: build.name,
1221 args: build.args,
1222 distinct: build.distinct,
1223 order_by: build.order_by,
1224 filter: build.filter,
1225 over: build.over,
1226 span,
1227 },
1228 build.height,
1229 false,
1230 true,
1231 )?;
1232 self.push_expr_tail(parsed, outer_min_bp);
1233 Ok(())
1234 }
1235
1236 #[allow(clippy::too_many_lines)]
1237 fn step(&mut self, control: ParseControl) -> Result<(), ParseError> {
1238 match control {
1239 ParseControl::ExprStart { min_bp } => self.expr_start(min_bp),
1240 ParseControl::ExprTail { min_bp } => self.expr_tail(min_bp),
1241 ParseControl::UnaryDone {
1242 outer_min_bp,
1243 op,
1244 span,
1245 } => {
1246 let inner = self.pop_expr()?;
1247 let span = span.merge(inner.expr.span());
1248 let parsed = self.parser.finish_unary(op, inner, span)?;
1249 self.push_expr_tail(parsed, outer_min_bp);
1250 Ok(())
1251 }
1252 ParseControl::CastDone {
1253 outer_min_bp,
1254 start,
1255 } => {
1256 let inner = self.pop_expr()?;
1257 self.parser.expect_kind(&TokenKind::KwAs)?;
1258 let type_name = self.parser.parse_cast_type_name()?;
1259 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1260 let height = inner.height;
1261 let is_constant = inner.is_constant;
1262 let has_function = inner.has_function;
1263 let parsed = self.parser.checked_expr(
1264 Expr::Cast {
1265 expr: Box::new(inner.expr),
1266 type_name,
1267 span: start.merge(end),
1268 },
1269 height,
1270 is_constant,
1271 has_function,
1272 )?;
1273 self.push_expr_tail(parsed, outer_min_bp);
1274 Ok(())
1275 }
1276 ParseControl::GroupFirstDone {
1277 outer_min_bp,
1278 start,
1279 } => {
1280 let first = self.pop_expr()?;
1281 if self.parser.eat_kind(&TokenKind::Comma) {
1282 let is_constant = first.is_constant;
1283 let has_function = first.has_function;
1284 self.controls.push(ParseControl::RowItemDone {
1285 outer_min_bp,
1286 start,
1287 values: vec![first.expr],
1288 is_constant,
1289 has_function,
1290 });
1291 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1292 } else {
1293 self.parser.expect_kind(&TokenKind::RightParen)?;
1294 self.push_expr_tail(first, outer_min_bp);
1295 }
1296 Ok(())
1297 }
1298 ParseControl::RowItemDone {
1299 outer_min_bp,
1300 start,
1301 mut values,
1302 mut is_constant,
1303 mut has_function,
1304 } => {
1305 let parsed = self.pop_expr()?;
1306 is_constant &= parsed.is_constant;
1307 has_function |= parsed.has_function;
1308 values.push(parsed.expr);
1309 if self.parser.eat_kind(&TokenKind::Comma) {
1310 self.controls.push(ParseControl::RowItemDone {
1311 outer_min_bp,
1312 start,
1313 values,
1314 is_constant,
1315 has_function,
1316 });
1317 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1318 } else {
1319 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1320 let parsed = self.parser.finish_expr(
1321 Expr::RowValue(values, start.merge(end)),
1322 1,
1323 is_constant,
1324 has_function,
1325 )?;
1326 self.push_expr_tail(parsed, outer_min_bp);
1327 }
1328 Ok(())
1329 }
1330 ParseControl::CaseOperandDone {
1331 outer_min_bp,
1332 start,
1333 } => {
1334 let operand = self.pop_expr()?;
1335 self.controls.push(ParseControl::CaseWhenStart {
1336 outer_min_bp,
1337 build: CaseBuild {
1338 start,
1339 operand: Some(operand),
1340 whens: Vec::new(),
1341 },
1342 });
1343 Ok(())
1344 }
1345 ParseControl::CaseWhenStart {
1346 outer_min_bp,
1347 build,
1348 } => {
1349 if self.parser.eat_kind(&TokenKind::KwWhen) {
1350 self.controls.push(ParseControl::CaseConditionDone {
1351 outer_min_bp,
1352 build,
1353 });
1354 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1355 return Ok(());
1356 }
1357 if build.whens.is_empty() {
1358 return Err(self
1359 .parser
1360 .err_here("CASE requires at least one WHEN clause"));
1361 }
1362 if self.parser.eat_kind(&TokenKind::KwElse) {
1363 self.controls.push(ParseControl::CaseElseDone {
1364 outer_min_bp,
1365 build,
1366 });
1367 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1368 return Ok(());
1369 }
1370 self.finish_case(outer_min_bp, build, None)
1371 }
1372 ParseControl::CaseConditionDone {
1373 outer_min_bp,
1374 build,
1375 } => {
1376 let condition = self.pop_expr()?;
1377 if !self.parser.eat_kind(&TokenKind::KwThen) {
1378 return Err(self.parser.err_here("expected THEN in CASE expression"));
1379 }
1380 self.controls.push(ParseControl::CaseResultDone {
1381 outer_min_bp,
1382 build,
1383 condition,
1384 });
1385 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1386 Ok(())
1387 }
1388 ParseControl::CaseResultDone {
1389 outer_min_bp,
1390 mut build,
1391 condition,
1392 } => {
1393 let result = self.pop_expr()?;
1394 build.whens.push((condition, result));
1395 self.controls.push(ParseControl::CaseWhenStart {
1396 outer_min_bp,
1397 build,
1398 });
1399 Ok(())
1400 }
1401 ParseControl::CaseElseDone {
1402 outer_min_bp,
1403 build,
1404 } => {
1405 let else_expr = self.pop_expr()?;
1406 self.finish_case(outer_min_bp, build, Some(else_expr))
1407 }
1408 ParseControl::FunctionArgDone {
1409 outer_min_bp,
1410 mut build,
1411 } => {
1412 let arg = self.pop_expr()?;
1413 build.height = build.height.max(arg.height);
1414 let FunctionArgs::List(args) = &mut build.args else {
1415 return Err(self
1416 .parser
1417 .err_here("internal function argument state mismatch"));
1418 };
1419 args.push(arg.expr);
1420 if self.parser.eat_kind(&TokenKind::Comma) {
1421 self.controls.push(ParseControl::FunctionArgDone {
1422 outer_min_bp,
1423 build,
1424 });
1425 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1426 } else {
1427 self.controls.push(ParseControl::FunctionOrderStart {
1428 outer_min_bp,
1429 build,
1430 });
1431 }
1432 Ok(())
1433 }
1434 ParseControl::FunctionOrderStart {
1435 outer_min_bp,
1436 build,
1437 } => {
1438 if self.parser.eat_kind(&TokenKind::KwOrder) {
1439 self.parser.expect_kind(&TokenKind::KwBy)?;
1440 self.controls.push(ParseControl::FunctionOrderDone {
1441 outer_min_bp,
1442 build,
1443 });
1444 self.controls.push(ParseControl::OrderingStart);
1445 } else {
1446 self.controls.push(ParseControl::FunctionClose {
1447 outer_min_bp,
1448 build,
1449 });
1450 }
1451 Ok(())
1452 }
1453 ParseControl::FunctionOrderDone {
1454 outer_min_bp,
1455 mut build,
1456 } => {
1457 let term = self.pop_ordering()?;
1458 build.order_by.push(term.value);
1459 if self.parser.eat_kind(&TokenKind::Comma) {
1460 self.controls.push(ParseControl::FunctionOrderDone {
1461 outer_min_bp,
1462 build,
1463 });
1464 self.controls.push(ParseControl::OrderingStart);
1465 } else {
1466 self.controls.push(ParseControl::FunctionClose {
1467 outer_min_bp,
1468 build,
1469 });
1470 }
1471 Ok(())
1472 }
1473 ParseControl::FunctionClose {
1474 outer_min_bp,
1475 mut build,
1476 } => {
1477 build.end = self.parser.expect_kind(&TokenKind::RightParen)?;
1478 if matches!(self.parser.peek_kind(), TokenKind::KwFilter)
1479 && self
1480 .parser
1481 .tokens
1482 .get(self.parser.pos + 1)
1483 .is_some_and(|token| token.kind == TokenKind::LeftParen)
1484 {
1485 self.parser.advance_token();
1486 self.parser.expect_kind(&TokenKind::LeftParen)?;
1487 self.parser.expect_kind(&TokenKind::KwWhere)?;
1488 self.controls.push(ParseControl::FunctionFilterDone {
1489 outer_min_bp,
1490 build,
1491 has_filter: true,
1492 });
1493 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1494 } else {
1495 self.controls.push(ParseControl::FunctionFilterDone {
1496 outer_min_bp,
1497 build,
1498 has_filter: false,
1499 });
1500 }
1501 Ok(())
1502 }
1503 ParseControl::FunctionFilterDone {
1504 outer_min_bp,
1505 mut build,
1506 has_filter,
1507 } => {
1508 if has_filter {
1509 let filter = self.pop_expr()?;
1510 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1511 build.end = build.end.merge(end);
1512 build.filter = Some(Box::new(filter.expr));
1513 }
1514 if matches!(self.parser.peek_kind(), TokenKind::KwOver)
1515 && self
1516 .parser
1517 .tokens
1518 .get(self.parser.pos + 1)
1519 .is_some_and(|token| {
1520 matches!(token.kind, TokenKind::LeftParen)
1521 || starts_bare_window_name(&token.kind)
1522 })
1523 {
1524 self.parser.advance_token();
1525 if self.parser.eat_kind(&TokenKind::LeftParen) {
1526 self.controls.push(ParseControl::FunctionOverDone {
1527 outer_min_bp,
1528 build,
1529 });
1530 self.controls.push(ParseControl::WindowStart);
1531 } else {
1532 let base_window = self.parser.parse_window_name()?;
1533 let base_span = self.parser.tokens[self.parser.pos.saturating_sub(1)].span;
1534 build.end = build.end.merge(base_span);
1535 build.over = Some(WindowSpec {
1536 window_ref: Some(WindowReference::Direct(base_window)),
1537 partition_by: Vec::new(),
1538 order_by: Vec::new(),
1539 frame: None,
1540 });
1541 self.finish_function(outer_min_bp, build)?;
1542 }
1543 } else {
1544 self.finish_function(outer_min_bp, build)?;
1545 }
1546 Ok(())
1547 }
1548 ParseControl::FunctionOverDone {
1549 outer_min_bp,
1550 mut build,
1551 } => {
1552 build.over = Some(self.pop_window()?);
1553 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1554 build.end = build.end.merge(end);
1555 self.finish_function(outer_min_bp, build)
1556 }
1557 ParseControl::BinaryDone {
1558 outer_min_bp,
1559 lhs,
1560 op,
1561 } => {
1562 let rhs = self.pop_expr()?;
1563 let span = lhs.expr.span().merge(rhs.expr.span());
1564 let height = lhs.height.max(rhs.height);
1565 let is_constant = lhs.is_constant && rhs.is_constant;
1566 let has_function = lhs.has_function || rhs.has_function;
1567 let parsed = self.parser.checked_expr(
1568 Expr::BinaryOp {
1569 left: Box::new(lhs.expr),
1570 op,
1571 right: Box::new(rhs.expr),
1572 span,
1573 },
1574 height,
1575 is_constant,
1576 has_function,
1577 )?;
1578 self.push_expr_tail(parsed, outer_min_bp);
1579 Ok(())
1580 }
1581 ParseControl::JsonDone {
1582 outer_min_bp,
1583 lhs,
1584 arrow,
1585 } => {
1586 let rhs = self.pop_expr()?;
1587 let span = lhs.expr.span().merge(rhs.expr.span());
1588 let height = lhs.height.max(rhs.height);
1589 let parsed = self.parser.checked_expr(
1590 Expr::JsonAccess {
1591 expr: Box::new(lhs.expr),
1592 path: Box::new(rhs.expr),
1593 arrow,
1594 span,
1595 },
1596 height,
1597 false,
1598 true,
1599 )?;
1600 self.push_expr_tail(parsed, outer_min_bp);
1601 Ok(())
1602 }
1603 ParseControl::IsDone {
1604 outer_min_bp,
1605 lhs,
1606 not,
1607 } => {
1608 let rhs = self.pop_expr()?;
1609 let span = lhs.expr.span().merge(rhs.expr.span());
1610 let parsed = if matches!(&rhs.expr, Expr::Literal(Literal::Null, _)) {
1611 self.parser.checked_expr(
1612 Expr::IsNull {
1613 expr: Box::new(lhs.expr),
1614 not,
1615 span,
1616 },
1617 lhs.height,
1618 lhs.is_constant,
1619 lhs.has_function,
1620 )?
1621 } else {
1622 let height = lhs.height.max(rhs.height);
1623 let is_constant = lhs.is_constant && rhs.is_constant;
1624 let has_function = lhs.has_function || rhs.has_function;
1625 self.parser.checked_expr(
1626 Expr::BinaryOp {
1627 left: Box::new(lhs.expr),
1628 op: if not { BinaryOp::IsNot } else { BinaryOp::Is },
1629 right: Box::new(rhs.expr),
1630 span,
1631 },
1632 height,
1633 is_constant,
1634 has_function,
1635 )?
1636 };
1637 self.push_expr_tail(parsed, outer_min_bp);
1638 Ok(())
1639 }
1640 ParseControl::LikePatternDone {
1641 outer_min_bp,
1642 lhs,
1643 op,
1644 not,
1645 } => {
1646 let pattern = self.pop_expr()?;
1647 if self.parser.eat_kind(&TokenKind::KwEscape) {
1648 self.controls.push(ParseControl::LikeEscapeDone {
1649 outer_min_bp,
1650 lhs,
1651 pattern,
1652 op,
1653 not,
1654 });
1655 self.controls.push(ParseControl::ExprStart {
1656 min_bp: bp::EQUALITY.1,
1657 });
1658 return Ok(());
1659 }
1660 self.finish_like(outer_min_bp, lhs, pattern, None, op, not)
1661 }
1662 ParseControl::LikeEscapeDone {
1663 outer_min_bp,
1664 lhs,
1665 pattern,
1666 op,
1667 not,
1668 } => {
1669 let escape = self.pop_expr()?;
1670 self.finish_like(outer_min_bp, lhs, pattern, Some(escape), op, not)
1671 }
1672 ParseControl::BetweenLowDone {
1673 outer_min_bp,
1674 lhs,
1675 not,
1676 } => {
1677 let low = self.pop_expr()?;
1678 if !self.parser.eat_kind(&TokenKind::KwAnd) {
1679 return Err(self.parser.err_here("expected AND in BETWEEN expression"));
1680 }
1681 self.controls.push(ParseControl::BetweenHighDone {
1682 outer_min_bp,
1683 lhs,
1684 low,
1685 not,
1686 });
1687 self.controls.push(ParseControl::ExprStart {
1688 min_bp: bp::EQUALITY.1,
1689 });
1690 Ok(())
1691 }
1692 ParseControl::BetweenHighDone {
1693 outer_min_bp,
1694 lhs,
1695 low,
1696 not,
1697 } => {
1698 let high = self.pop_expr()?;
1699 let span = lhs.expr.span().merge(high.expr.span());
1700 let height = lhs.height.max(low.height).max(high.height);
1701 let is_constant = lhs.is_constant && low.is_constant && high.is_constant;
1702 let has_function = lhs.has_function || low.has_function || high.has_function;
1703 let parsed = self.parser.checked_expr(
1704 Expr::Between {
1705 expr: Box::new(lhs.expr),
1706 low: Box::new(low.expr),
1707 high: Box::new(high.expr),
1708 not,
1709 span,
1710 },
1711 height,
1712 is_constant,
1713 has_function,
1714 )?;
1715 let parsed = if not {
1716 self.parser.add_cached_parent(parsed)?
1717 } else {
1718 parsed
1719 };
1720 self.push_expr_tail(parsed, outer_min_bp);
1721 Ok(())
1722 }
1723 ParseControl::InItemDone {
1724 outer_min_bp,
1725 lhs,
1726 not,
1727 mut items,
1728 start,
1729 } => {
1730 let item = self.pop_expr()?;
1731 items.push(item);
1732 if self.parser.eat_kind(&TokenKind::Comma) {
1733 self.controls.push(ParseControl::InItemDone {
1734 outer_min_bp,
1735 lhs,
1736 not,
1737 items,
1738 start,
1739 });
1740 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1741 } else {
1742 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1743 self.finish_in_list(outer_min_bp, lhs, not, items, start.merge(end))?;
1744 }
1745 Ok(())
1746 }
1747 ParseControl::InSelectDone {
1748 outer_min_bp,
1749 lhs,
1750 not,
1751 start,
1752 } => {
1753 let select = self.pop_select()?;
1754 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1755 let height = lhs.height.max(select.height);
1756 let has_function = lhs.has_function;
1757 let parsed = self.parser.checked_expr(
1758 Expr::In {
1759 expr: Box::new(lhs.expr),
1760 set: InSet::Subquery(Box::new(select.value)),
1761 not,
1762 span: start.merge(end),
1763 },
1764 height,
1765 false,
1766 has_function,
1767 )?;
1768 let parsed = if not {
1769 self.parser.add_cached_parent(parsed)?
1770 } else {
1771 parsed
1772 };
1773 self.push_expr_tail(parsed, outer_min_bp);
1774 Ok(())
1775 }
1776 ParseControl::ExistsDone {
1777 outer_min_bp,
1778 not,
1779 start,
1780 } => {
1781 let select = self.pop_select()?;
1782 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1783 let parsed = self.parser.checked_expr(
1784 Expr::Exists {
1785 subquery: Box::new(select.value),
1786 not,
1787 span: start.merge(end),
1788 },
1789 select.height,
1790 false,
1791 false,
1792 )?;
1793 let parsed = if not {
1794 self.parser.add_cached_parent(parsed)?
1795 } else {
1796 parsed
1797 };
1798 self.push_expr_tail(parsed, outer_min_bp);
1799 Ok(())
1800 }
1801 ParseControl::ScalarSelectDone {
1802 outer_min_bp,
1803 start,
1804 } => {
1805 let select = self.pop_select()?;
1806 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
1807 let parsed = self.parser.checked_expr(
1808 Expr::Subquery(Box::new(select.value), start.merge(end)),
1809 select.height,
1810 false,
1811 false,
1812 )?;
1813 self.push_expr_tail(parsed, outer_min_bp);
1814 Ok(())
1815 }
1816 ParseControl::OrderingStart => {
1817 self.controls.push(ParseControl::OrderingDone);
1818 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1819 Ok(())
1820 }
1821 ParseControl::OrderingDone => {
1822 let expr = self.pop_expr()?;
1823 let direction = if self.parser.eat_kind(&TokenKind::KwAsc) {
1824 Some(SortDirection::Asc)
1825 } else if self.parser.eat_kind(&TokenKind::KwDesc) {
1826 Some(SortDirection::Desc)
1827 } else {
1828 None
1829 };
1830 let nulls = if self.parser.eat_kind(&TokenKind::KwNulls) {
1831 if self.parser.eat_kind(&TokenKind::KwFirst) {
1832 Some(NullsOrder::First)
1833 } else {
1834 self.parser.expect_kw(&TokenKind::KwLast)?;
1835 Some(NullsOrder::Last)
1836 }
1837 } else {
1838 None
1839 };
1840 self.values.push(MachineValue::Ordering(HeightTracked {
1841 height: expr.height,
1842 value: OrderingTerm {
1843 expr: expr.expr,
1844 direction,
1845 nulls,
1846 },
1847 }));
1848 Ok(())
1849 }
1850 ParseControl::WindowStart => self.window_start(),
1851 ParseControl::WindowPartitionDone { mut build } => {
1852 build.partition_by.push(self.pop_expr()?.expr);
1853 if self.parser.eat_kind(&TokenKind::Comma) {
1854 self.controls
1855 .push(ParseControl::WindowPartitionDone { build });
1856 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
1857 } else {
1858 self.controls.push(ParseControl::WindowOrderStart { build });
1859 }
1860 Ok(())
1861 }
1862 ParseControl::WindowOrderStart { build } => {
1863 if self.parser.eat_kind(&TokenKind::KwOrder) {
1864 self.parser.expect_kw(&TokenKind::KwBy)?;
1865 self.controls.push(ParseControl::WindowOrderDone { build });
1866 self.controls.push(ParseControl::OrderingStart);
1867 } else {
1868 self.controls.push(ParseControl::WindowFrameStart { build });
1869 }
1870 Ok(())
1871 }
1872 ParseControl::WindowOrderDone { mut build } => {
1873 build.order_by.push(self.pop_ordering()?.value);
1874 if self.parser.eat_kind(&TokenKind::Comma) {
1875 self.controls.push(ParseControl::WindowOrderDone { build });
1876 self.controls.push(ParseControl::OrderingStart);
1877 } else {
1878 self.controls.push(ParseControl::WindowFrameStart { build });
1879 }
1880 Ok(())
1881 }
1882 ParseControl::WindowFrameStart { build } => {
1883 self.window_frame_start(build);
1884 Ok(())
1885 }
1886 ParseControl::WindowFirstBoundDone {
1887 build,
1888 frame_type,
1889 between,
1890 } => {
1891 let start = self.pop_frame_bound()?;
1892 validate_frame_start(&start, between)?;
1893 if between {
1894 self.parser.expect_kw(&TokenKind::KwAnd)?;
1895 self.controls.push(ParseControl::WindowSecondBoundDone {
1896 build,
1897 frame_type,
1898 start,
1899 });
1900 self.controls.push(ParseControl::FrameBoundStart);
1901 } else {
1902 let frame = self.finish_frame(frame_type, start.value, None)?;
1903 self.values.push(MachineValue::Window(WindowSpec {
1904 window_ref: build.base_window.map(WindowReference::Base),
1905 partition_by: build.partition_by,
1906 order_by: build.order_by,
1907 frame: Some(frame),
1908 }));
1909 }
1910 Ok(())
1911 }
1912 ParseControl::WindowSecondBoundDone {
1913 build,
1914 frame_type,
1915 start,
1916 } => {
1917 let end = self.pop_frame_bound()?;
1918 validate_frame_end(&start, &end)?;
1919 let frame = self.finish_frame(frame_type, start.value, Some(end.value))?;
1920 self.values.push(MachineValue::Window(WindowSpec {
1921 window_ref: build.base_window.map(WindowReference::Base),
1922 partition_by: build.partition_by,
1923 order_by: build.order_by,
1924 frame: Some(frame),
1925 }));
1926 Ok(())
1927 }
1928 ParseControl::FrameBoundStart => self.frame_bound_start(),
1929 ParseControl::FrameBoundExprDone { origin } => {
1930 let expr = self.pop_expr()?.expr;
1931 let bound = if self.parser.eat_kind(&TokenKind::KwPreceding) {
1932 FrameBound::Preceding(Box::new(expr))
1933 } else {
1934 self.parser.expect_kw(&TokenKind::KwFollowing)?;
1935 FrameBound::Following(Box::new(expr))
1936 };
1937 self.values.push(MachineValue::FrameBound(ParsedFrameBound {
1938 value: bound,
1939 origin,
1940 }));
1941 Ok(())
1942 }
1943 ParseControl::SubqueryStart => {
1944 if self.parser.at_kind(&TokenKind::KwWith) {
1945 self.controls.push(ParseControl::SubqueryWithDone);
1946 self.controls.push(ParseControl::WithStart);
1947 } else {
1948 self.controls.push(ParseControl::SelectStart { with: None });
1949 }
1950 Ok(())
1951 }
1952 ParseControl::SubqueryWithDone => {
1953 let with = self.pop_with()?;
1954 self.controls
1955 .push(ParseControl::SelectStart { with: Some(with) });
1956 Ok(())
1957 }
1958 other => self.step_select(other),
1959 }
1960 }
1961
1962 #[allow(clippy::too_many_lines)]
1963 fn expr_start(&mut self, min_bp: u8) -> Result<(), ParseError> {
1964 let Token {
1965 kind,
1966 span: token_span,
1967 line,
1968 col,
1969 } = self.parser.advance_token();
1970 if self.parser.at_kind(&TokenKind::Dot) && starts_table_star_qualifier(&kind) {
1971 let name = match &kind {
1972 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => Arc::clone(name),
1973 TokenKind::String(name) => Arc::<str>::from(name.as_str()),
1974 keyword => Arc::<str>::from(kw_to_str(keyword)),
1975 };
1976 return self.identifier_or_function(name, token_span, min_bp);
1977 }
1978 let parsed = match kind {
1979 TokenKind::Integer(value) => {
1980 ParsedExpr::leaf(Expr::Literal(Literal::Integer(value), token_span))
1981 }
1982 TokenKind::OversizedInt(value) => match value.parse::<f64>() {
1983 Ok(value) => ParsedExpr::leaf(Expr::Literal(Literal::Float(value), token_span)),
1984 Err(_) => {
1985 return Err(ParseError {
1986 kind: crate::parser::ParseErrorKind::Syntax,
1987 message: "integer out of range".to_owned(),
1988 span: token_span,
1989 line,
1990 col,
1991 });
1992 }
1993 },
1994 TokenKind::Float(value) => {
1995 ParsedExpr::leaf(Expr::Literal(Literal::Float(value), token_span))
1996 }
1997 TokenKind::String(value) if self.parser.at_kind(&TokenKind::Dot) => {
1998 return self.identifier_or_function(Arc::<str>::from(value), token_span, min_bp);
1999 }
2000 TokenKind::String(value) => {
2001 ParsedExpr::leaf(Expr::Literal(Literal::String(value), token_span))
2002 }
2003 TokenKind::Blob(value) => {
2004 ParsedExpr::leaf(Expr::Literal(Literal::Blob(value), token_span))
2005 }
2006 TokenKind::KwNull => ParsedExpr::leaf(Expr::Literal(Literal::Null, token_span)),
2007 TokenKind::KwTrue => ParsedExpr::leaf(Expr::Literal(Literal::True, token_span)),
2008 TokenKind::KwFalse => ParsedExpr::leaf(Expr::Literal(Literal::False, token_span)),
2009 TokenKind::KwCurrentTime => {
2010 ParsedExpr::leaf(Expr::Literal(Literal::CurrentTime, token_span))
2011 }
2012 TokenKind::KwCurrentDate => {
2013 ParsedExpr::leaf(Expr::Literal(Literal::CurrentDate, token_span))
2014 }
2015 TokenKind::KwCurrentTimestamp => {
2016 ParsedExpr::leaf(Expr::Literal(Literal::CurrentTimestamp, token_span))
2017 }
2018 TokenKind::Question => {
2019 ParsedExpr::leaf(Expr::Placeholder(PlaceholderType::Anonymous, token_span))
2020 }
2021 TokenKind::QuestionNum(value) => ParsedExpr::leaf(Expr::Placeholder(
2022 PlaceholderType::Numbered(value),
2023 token_span,
2024 )),
2025 TokenKind::ColonParam(value) => ParsedExpr::leaf(Expr::Placeholder(
2026 PlaceholderType::ColonNamed(value),
2027 token_span,
2028 )),
2029 TokenKind::AtParam(value) => ParsedExpr::leaf(Expr::Placeholder(
2030 PlaceholderType::AtNamed(value),
2031 token_span,
2032 )),
2033 TokenKind::DollarParam(value) => ParsedExpr::leaf(Expr::Placeholder(
2034 PlaceholderType::DollarNamed(value),
2035 token_span,
2036 )),
2037 TokenKind::Minus => {
2038 if let TokenKind::OversizedInt(value) = self.parser.peek_kind()
2039 && value == "9223372036854775808"
2040 {
2041 let number_span = self.parser.advance_token().span;
2042 let parsed = self.parser.finish_expr(
2043 Expr::Literal(Literal::Integer(i64::MIN), token_span.merge(number_span)),
2044 1,
2045 true,
2046 false,
2047 )?;
2048 self.push_expr_tail(parsed, min_bp);
2049 return Ok(());
2050 }
2051 self.controls.push(ParseControl::UnaryDone {
2052 outer_min_bp: min_bp,
2053 op: UnaryOp::Negate,
2054 span: token_span,
2055 });
2056 self.controls
2057 .push(ParseControl::ExprStart { min_bp: bp::UNARY });
2058 return Ok(());
2059 }
2060 TokenKind::Plus => {
2061 self.controls.push(ParseControl::UnaryDone {
2062 outer_min_bp: min_bp,
2063 op: UnaryOp::Plus,
2064 span: token_span,
2065 });
2066 self.controls
2067 .push(ParseControl::ExprStart { min_bp: bp::UNARY });
2068 return Ok(());
2069 }
2070 TokenKind::Tilde => {
2071 self.controls.push(ParseControl::UnaryDone {
2072 outer_min_bp: min_bp,
2073 op: UnaryOp::BitNot,
2074 span: token_span,
2075 });
2076 self.controls
2077 .push(ParseControl::ExprStart { min_bp: bp::UNARY });
2078 return Ok(());
2079 }
2080 TokenKind::KwNot => {
2081 if self.parser.eat_kind(&TokenKind::KwExists) {
2082 self.parser.expect_kind(&TokenKind::LeftParen)?;
2083 self.controls.push(ParseControl::ExistsDone {
2084 outer_min_bp: min_bp,
2085 not: true,
2086 start: token_span,
2087 });
2088 self.controls.push(ParseControl::SubqueryStart);
2089 } else {
2090 self.controls.push(ParseControl::UnaryDone {
2091 outer_min_bp: min_bp,
2092 op: UnaryOp::Not,
2093 span: token_span,
2094 });
2095 self.controls.push(ParseControl::ExprStart {
2096 min_bp: bp::NOT_PREFIX,
2097 });
2098 }
2099 return Ok(());
2100 }
2101 TokenKind::KwExists => {
2102 self.parser.expect_kind(&TokenKind::LeftParen)?;
2103 self.controls.push(ParseControl::ExistsDone {
2104 outer_min_bp: min_bp,
2105 not: false,
2106 start: token_span,
2107 });
2108 self.controls.push(ParseControl::SubqueryStart);
2109 return Ok(());
2110 }
2111 TokenKind::KwCast => {
2112 self.parser.expect_kind(&TokenKind::LeftParen)?;
2113 self.controls.push(ParseControl::CastDone {
2114 outer_min_bp: min_bp,
2115 start: token_span,
2116 });
2117 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2118 return Ok(());
2119 }
2120 TokenKind::KwCase => {
2121 if self.parser.at_kind(&TokenKind::KwWhen) {
2122 self.controls.push(ParseControl::CaseWhenStart {
2123 outer_min_bp: min_bp,
2124 build: CaseBuild {
2125 start: token_span,
2126 operand: None,
2127 whens: Vec::new(),
2128 },
2129 });
2130 } else {
2131 self.controls.push(ParseControl::CaseOperandDone {
2132 outer_min_bp: min_bp,
2133 start: token_span,
2134 });
2135 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2136 }
2137 return Ok(());
2138 }
2139 TokenKind::KwRaise => {
2140 self.parser.expect_kind(&TokenKind::LeftParen)?;
2141 let (action, message) = self.parser.parse_raise_args()?;
2142 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
2143 ParsedExpr::leaf(Expr::Raise {
2144 action,
2145 message,
2146 span: token_span.merge(end),
2147 })
2148 }
2149 TokenKind::LeftParen => {
2150 if matches!(
2151 self.parser.peek_kind(),
2152 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
2153 ) {
2154 self.controls.push(ParseControl::ScalarSelectDone {
2155 outer_min_bp: min_bp,
2156 start: token_span,
2157 });
2158 self.controls.push(ParseControl::SubqueryStart);
2159 } else {
2160 self.controls.push(ParseControl::GroupFirstDone {
2161 outer_min_bp: min_bp,
2162 start: token_span,
2163 });
2164 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2165 }
2166 return Ok(());
2167 }
2168 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => {
2169 return self.identifier_or_function(name, token_span, min_bp);
2170 }
2171 TokenKind::KwReplace if self.parser.at_kind(&TokenKind::LeftParen) => {
2172 return self.start_function("replace".to_owned(), token_span, min_bp);
2173 }
2174 TokenKind::KwLike if self.parser.at_kind(&TokenKind::LeftParen) => {
2175 return self.start_function("like".to_owned(), token_span, min_bp);
2176 }
2177 TokenKind::KwGlob if self.parser.at_kind(&TokenKind::LeftParen) => {
2178 return self.start_function("glob".to_owned(), token_span, min_bp);
2179 }
2180 TokenKind::KwRegexp if self.parser.at_kind(&TokenKind::LeftParen) => {
2181 return self.start_function("regexp".to_owned(), token_span, min_bp);
2182 }
2183 TokenKind::KwMatch if self.parser.at_kind(&TokenKind::LeftParen) => {
2184 return self.start_function("match".to_owned(), token_span, min_bp);
2185 }
2186 kind if is_nonreserved_kw(&kind) => {
2187 let name = Arc::<str>::from(kw_to_str(&kind));
2188 return self.identifier_or_function(name, token_span, min_bp);
2189 }
2190 TokenKind::Error(msg) => {
2191 return Err(ParseError {
2196 kind: crate::parser::ParseErrorKind::Tokenizer,
2197 message: msg,
2198 span: token_span,
2199 line,
2200 col,
2201 });
2202 }
2203 kind => {
2204 return Err(ParseError {
2205 kind: crate::parser::ParseErrorKind::UnexpectedToken,
2206 message: format!("unexpected token in expression: {kind:?}"),
2207 span: token_span,
2208 line,
2209 col,
2210 });
2211 }
2212 };
2213 self.push_expr_tail(parsed, min_bp);
2214 Ok(())
2215 }
2216
2217 fn identifier_or_function(
2218 &mut self,
2219 name: Arc<str>,
2220 start: Span,
2221 min_bp: u8,
2222 ) -> Result<(), ParseError> {
2223 if self.parser.at_kind(&TokenKind::LeftParen) {
2224 return self.start_function(name.to_string(), start, min_bp);
2225 }
2226 let parsed = if self.parser.at_kind(&TokenKind::Dot) {
2227 let Some(mid_token) = self.parser.tokens.get(self.parser.pos + 1).cloned() else {
2228 return Err(self.parser.err_here("expected column name after '.'"));
2229 };
2230 let mid = match &mid_token.kind {
2231 TokenKind::Id(mid) | TokenKind::QuotedId(mid, _) => Arc::clone(mid),
2232 TokenKind::String(mid) => Arc::<str>::from(mid.as_str()),
2233 kind if starts_post_dot_identifier(kind) => Arc::<str>::from(kw_to_str(kind)),
2234 _ => {
2235 return Err(ParseError::unexpected_at(
2236 format!("expected column name after '.', got {:?}", mid_token.kind),
2237 Some(&mid_token),
2238 ));
2239 }
2240 };
2241 if matches!(
2245 self.parser.tokens.get(self.parser.pos + 2).map(|t| &t.kind),
2246 Some(TokenKind::Dot)
2247 ) {
2248 let Some(column_token) = self.parser.tokens.get(self.parser.pos + 3).cloned()
2249 else {
2250 return Err(ParseError::unexpected_at(
2251 "expected column name after '.'".to_owned(),
2252 self.parser.tokens.get(self.parser.pos + 2),
2253 ));
2254 };
2255 let column = match &column_token.kind {
2256 TokenKind::Id(column) | TokenKind::QuotedId(column, _) => Arc::clone(column),
2257 TokenKind::String(column) => Arc::<str>::from(column.as_str()),
2258 kind if starts_post_dot_identifier(kind) => Arc::<str>::from(kw_to_str(kind)),
2259 _ => {
2260 return Err(ParseError::unexpected_at(
2261 format!(
2262 "expected column name after '.', got {:?}",
2263 column_token.kind
2264 ),
2265 Some(&column_token),
2266 ));
2267 }
2268 };
2269 self.parser.pos = self.parser.pos.saturating_add(4);
2270 self.parser.finish_expr(
2271 Expr::Column(
2272 ColumnRef::schema_qualified(name, mid, column),
2273 start.merge(column_token.span),
2274 ),
2275 2,
2276 false,
2277 false,
2278 )?
2279 } else {
2280 self.parser.pos = self.parser.pos.saturating_add(2);
2281 self.parser.finish_expr(
2282 Expr::Column(ColumnRef::qualified(name, mid), start.merge(mid_token.span)),
2283 2,
2284 false,
2285 false,
2286 )?
2287 }
2288 } else {
2289 ParsedExpr::leaf(Expr::Column(ColumnRef::bare(name), start))
2290 };
2291 self.push_expr_tail(parsed, min_bp);
2292 Ok(())
2293 }
2294
2295 fn start_function(
2296 &mut self,
2297 name: String,
2298 start: Span,
2299 outer_min_bp: u8,
2300 ) -> Result<(), ParseError> {
2301 self.parser.expect_kind(&TokenKind::LeftParen)?;
2302 let mut build = FunctionBuild {
2303 name,
2304 start,
2305 args: FunctionArgs::List(Vec::new()),
2306 distinct: false,
2307 height: 0,
2308 order_by: Vec::new(),
2309 filter: None,
2310 over: None,
2311 end: start,
2312 };
2313 if self.parser.eat_kind(&TokenKind::Star) {
2314 build.args = if build.name.eq_ignore_ascii_case("count") {
2320 FunctionArgs::Star
2321 } else {
2322 FunctionArgs::List(Vec::new())
2323 };
2324 self.controls.push(ParseControl::FunctionClose {
2325 outer_min_bp,
2326 build,
2327 });
2328 } else {
2329 build.distinct = self.parser.eat_kind(&TokenKind::KwDistinct);
2330 if self.parser.at_kind(&TokenKind::RightParen) {
2331 if build.distinct {
2332 return Err(self
2333 .parser
2334 .err_here("DISTINCT requires at least one argument"));
2335 }
2336 self.controls.push(ParseControl::FunctionOrderStart {
2337 outer_min_bp,
2338 build,
2339 });
2340 } else {
2341 self.controls.push(ParseControl::FunctionArgDone {
2342 outer_min_bp,
2343 build,
2344 });
2345 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2346 }
2347 }
2348 Ok(())
2349 }
2350
2351 #[allow(clippy::too_many_lines)]
2352 fn expr_tail(&mut self, min_bp: u8) -> Result<(), ParseError> {
2353 let lhs = self.pop_expr()?;
2354 if let Some(left_bp) = self.parser.postfix_bp()
2355 && left_bp >= min_bp
2356 {
2357 let parsed = self.parser.parse_postfix(lhs)?;
2358 self.push_expr_tail(parsed, min_bp);
2359 return Ok(());
2360 }
2361 let Some((left_bp, right_bp)) = self.parser.infix_bp() else {
2362 self.values.push(MachineValue::Expr(lhs));
2363 return Ok(());
2364 };
2365 if left_bp < min_bp {
2366 self.values.push(MachineValue::Expr(lhs));
2367 return Ok(());
2368 }
2369
2370 let token = self.parser.advance_token();
2371 let simple = match &token.kind {
2372 TokenKind::Plus => Some(BinaryOp::Add),
2373 TokenKind::Minus => Some(BinaryOp::Subtract),
2374 TokenKind::Star => Some(BinaryOp::Multiply),
2375 TokenKind::Slash => Some(BinaryOp::Divide),
2376 TokenKind::Percent => Some(BinaryOp::Modulo),
2377 TokenKind::Concat => Some(BinaryOp::Concat),
2378 TokenKind::Eq | TokenKind::EqEq => Some(BinaryOp::Eq),
2379 TokenKind::Ne | TokenKind::LtGt => Some(BinaryOp::Ne),
2380 TokenKind::Lt => Some(BinaryOp::Lt),
2381 TokenKind::Le => Some(BinaryOp::Le),
2382 TokenKind::Gt => Some(BinaryOp::Gt),
2383 TokenKind::Ge => Some(BinaryOp::Ge),
2384 TokenKind::Ampersand => Some(BinaryOp::BitAnd),
2385 TokenKind::Pipe => Some(BinaryOp::BitOr),
2386 TokenKind::ShiftLeft => Some(BinaryOp::ShiftLeft),
2387 TokenKind::ShiftRight => Some(BinaryOp::ShiftRight),
2388 TokenKind::KwOr => Some(BinaryOp::Or),
2389 TokenKind::KwAnd => Some(BinaryOp::And),
2390 _ => None,
2391 };
2392 if let Some(op) = simple {
2393 self.controls.push(ParseControl::BinaryDone {
2394 outer_min_bp: min_bp,
2395 lhs,
2396 op,
2397 });
2398 self.controls
2399 .push(ParseControl::ExprStart { min_bp: right_bp });
2400 return Ok(());
2401 }
2402 match &token.kind {
2403 TokenKind::KwIs => {
2404 let not = self.parser.eat_kind(&TokenKind::KwNot);
2405 if self.parser.eat_kind(&TokenKind::KwDistinct) {
2406 self.parser.expect_kind(&TokenKind::KwFrom)?;
2407 self.controls.push(ParseControl::BinaryDone {
2408 outer_min_bp: min_bp,
2409 lhs,
2410 op: if not { BinaryOp::Is } else { BinaryOp::IsNot },
2411 });
2412 } else {
2413 self.controls.push(ParseControl::IsDone {
2414 outer_min_bp: min_bp,
2415 lhs,
2416 not,
2417 });
2418 }
2419 self.controls
2420 .push(ParseControl::ExprStart { min_bp: right_bp });
2421 }
2422 TokenKind::KwLike | TokenKind::KwGlob | TokenKind::KwMatch | TokenKind::KwRegexp => {
2423 let op = match &token.kind {
2424 TokenKind::KwLike => LikeOp::Like,
2425 TokenKind::KwGlob => LikeOp::Glob,
2426 TokenKind::KwMatch => LikeOp::Match,
2427 TokenKind::KwRegexp => LikeOp::Regexp,
2428 _ => unreachable!(),
2429 };
2430 self.controls.push(ParseControl::LikePatternDone {
2431 outer_min_bp: min_bp,
2432 lhs,
2433 op,
2434 not: false,
2435 });
2436 self.controls.push(ParseControl::ExprStart {
2437 min_bp: bp::EQUALITY.1,
2438 });
2439 }
2440 TokenKind::KwBetween => {
2441 self.controls.push(ParseControl::BetweenLowDone {
2442 outer_min_bp: min_bp,
2443 lhs,
2444 not: false,
2445 });
2446 self.controls.push(ParseControl::ExprStart {
2447 min_bp: bp::NOT_PREFIX,
2448 });
2449 }
2450 TokenKind::KwIn => self.start_in(lhs, false, min_bp)?,
2451 TokenKind::Arrow => {
2452 self.controls.push(ParseControl::JsonDone {
2453 outer_min_bp: min_bp,
2454 lhs,
2455 arrow: JsonArrow::Arrow,
2456 });
2457 self.controls
2458 .push(ParseControl::ExprStart { min_bp: right_bp });
2459 }
2460 TokenKind::DoubleArrow => {
2461 self.controls.push(ParseControl::JsonDone {
2462 outer_min_bp: min_bp,
2463 lhs,
2464 arrow: JsonArrow::DoubleArrow,
2465 });
2466 self.controls
2467 .push(ParseControl::ExprStart { min_bp: right_bp });
2468 }
2469 TokenKind::KwNot => {
2470 let next = self.parser.advance_token();
2471 match &next.kind {
2472 TokenKind::KwLike
2473 | TokenKind::KwGlob
2474 | TokenKind::KwMatch
2475 | TokenKind::KwRegexp => {
2476 let op = match &next.kind {
2477 TokenKind::KwLike => LikeOp::Like,
2478 TokenKind::KwGlob => LikeOp::Glob,
2479 TokenKind::KwMatch => LikeOp::Match,
2480 TokenKind::KwRegexp => LikeOp::Regexp,
2481 _ => unreachable!(),
2482 };
2483 self.controls.push(ParseControl::LikePatternDone {
2484 outer_min_bp: min_bp,
2485 lhs,
2486 op,
2487 not: true,
2488 });
2489 self.controls.push(ParseControl::ExprStart {
2490 min_bp: bp::EQUALITY.1,
2491 });
2492 }
2493 TokenKind::KwBetween => {
2494 self.controls.push(ParseControl::BetweenLowDone {
2495 outer_min_bp: min_bp,
2496 lhs,
2497 not: true,
2498 });
2499 self.controls.push(ParseControl::ExprStart {
2500 min_bp: bp::NOT_PREFIX,
2501 });
2502 }
2503 TokenKind::KwIn => self.start_in(lhs, true, min_bp)?,
2504 _ => {
2505 return Err(ParseError::unexpected_at(
2506 format!(
2507 "expected LIKE/GLOB/MATCH/REGEXP/BETWEEN/IN after NOT, got {:?}",
2508 next.kind
2509 ),
2510 Some(&next),
2511 ));
2512 }
2513 }
2514 }
2515 other => {
2516 return Err(ParseError::unexpected_at(
2517 format!("unexpected infix token: {other:?}"),
2518 Some(&token),
2519 ));
2520 }
2521 }
2522 Ok(())
2523 }
2524
2525 fn start_in(&mut self, lhs: ParsedExpr, not: bool, outer_min_bp: u8) -> Result<(), ParseError> {
2526 let start = lhs.expr.span();
2527 if !self.parser.eat_kind(&TokenKind::LeftParen) {
2528 let table = self.parser.parse_qualified_name()?;
2529 let end = self.parser.tokens[self.parser.pos.saturating_sub(1)].span;
2530 let height = lhs.height;
2531 let has_function = lhs.has_function;
2532 let parsed = self.parser.checked_expr(
2533 Expr::In {
2534 expr: Box::new(lhs.expr),
2535 set: InSet::Table(table),
2536 not,
2537 span: start.merge(end),
2538 },
2539 height,
2540 false,
2541 has_function,
2542 )?;
2543 let parsed = if not {
2544 self.parser.add_cached_parent(parsed)?
2545 } else {
2546 parsed
2547 };
2548 self.push_expr_tail(parsed, outer_min_bp);
2549 } else if matches!(
2550 self.parser.peek_kind(),
2551 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
2552 ) {
2553 self.controls.push(ParseControl::InSelectDone {
2554 outer_min_bp,
2555 lhs,
2556 not,
2557 start,
2558 });
2559 self.controls.push(ParseControl::SubqueryStart);
2560 } else if self.parser.at_kind(&TokenKind::RightParen) {
2561 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
2562 self.finish_in_list(outer_min_bp, lhs, not, Vec::new(), start.merge(end))?;
2563 } else {
2564 self.controls.push(ParseControl::InItemDone {
2565 outer_min_bp,
2566 lhs,
2567 not,
2568 items: Vec::new(),
2569 start,
2570 });
2571 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2572 }
2573 Ok(())
2574 }
2575
2576 fn finish_case(
2577 &mut self,
2578 outer_min_bp: u8,
2579 build: CaseBuild,
2580 else_expr: Option<ParsedExpr>,
2581 ) -> Result<(), ParseError> {
2582 if !self.parser.eat_kind(&TokenKind::KwEnd) {
2583 return Err(self.parser.err_here("expected END for CASE expression"));
2584 }
2585 let end = self.parser.tokens[self.parser.pos.saturating_sub(1)].span;
2586 let mut height = build.operand.as_ref().map_or(0, |expr| expr.height);
2587 let mut is_constant = build.operand.as_ref().is_none_or(|expr| expr.is_constant);
2588 let mut has_function = build.operand.as_ref().is_some_and(|expr| expr.has_function);
2589 for (condition, result) in &build.whens {
2590 height = height.max(condition.height).max(result.height);
2591 is_constant &= condition.is_constant && result.is_constant;
2592 has_function |= condition.has_function || result.has_function;
2593 }
2594 if let Some(expr) = &else_expr {
2595 height = height.max(expr.height);
2596 is_constant &= expr.is_constant;
2597 has_function |= expr.has_function;
2598 }
2599 let parsed = self.parser.checked_expr(
2600 Expr::Case {
2601 operand: build.operand.map(|expr| Box::new(expr.expr)),
2602 whens: build
2603 .whens
2604 .into_iter()
2605 .map(|(condition, result)| (condition.expr, result.expr))
2606 .collect(),
2607 else_expr: else_expr.map(|expr| Box::new(expr.expr)),
2608 span: build.start.merge(end),
2609 },
2610 height,
2611 is_constant,
2612 has_function,
2613 )?;
2614 self.push_expr_tail(parsed, outer_min_bp);
2615 Ok(())
2616 }
2617
2618 fn finish_like(
2619 &mut self,
2620 outer_min_bp: u8,
2621 lhs: ParsedExpr,
2622 pattern: ParsedExpr,
2623 escape: Option<ParsedExpr>,
2624 op: LikeOp,
2625 not: bool,
2626 ) -> Result<(), ParseError> {
2627 let end = escape
2628 .as_ref()
2629 .map_or_else(|| pattern.expr.span(), |expr| expr.expr.span());
2630 let height = escape.as_ref().map_or_else(
2631 || lhs.height.max(pattern.height),
2632 |expr| lhs.height.max(pattern.height).max(expr.height),
2633 );
2634 let span = lhs.expr.span().merge(end);
2635 let parsed = self.parser.checked_expr(
2636 Expr::Like {
2637 expr: Box::new(lhs.expr),
2638 pattern: Box::new(pattern.expr),
2639 escape: escape.map(|expr| Box::new(expr.expr)),
2640 op,
2641 not,
2642 span,
2643 },
2644 height,
2645 false,
2646 true,
2647 )?;
2648 let parsed = if not {
2649 self.parser.add_cached_parent(parsed)?
2650 } else {
2651 parsed
2652 };
2653 self.push_expr_tail(parsed, outer_min_bp);
2654 Ok(())
2655 }
2656
2657 fn finish_in_list(
2658 &mut self,
2659 outer_min_bp: u8,
2660 lhs: ParsedExpr,
2661 not: bool,
2662 items: Vec<ParsedExpr>,
2663 span: Span,
2664 ) -> Result<(), ParseError> {
2665 if let Some(message) = vector_in_list_arity_error(&lhs.expr, &items) {
2666 return Err(self.parser.err_semantic(message));
2669 }
2670 let item_height = items.iter().map(|item| item.height).max().unwrap_or(0);
2671 let items_are_constant = items.iter().all(|item| item.is_constant);
2672 let item_has_function = items.iter().any(|item| item.has_function);
2673 let singleton_constant = matches!(items.as_slice(), [item] if item.is_constant)
2674 && lhs.root != CachedRoot::Vector;
2675 let singleton_subquery =
2676 matches!(items.as_slice(), [item] if item.root == CachedRoot::ScalarSubquery);
2677 let lhs_height = lhs.height;
2678 let lhs_is_constant = lhs.is_constant;
2679 let lhs_has_function = lhs.has_function;
2680 let expr = Expr::In {
2681 expr: Box::new(lhs.expr),
2682 set: InSet::List(items.into_iter().map(|item| item.expr).collect()),
2683 not,
2684 span,
2685 };
2686 let parsed = if item_height == 0 {
2687 if lhs_has_function {
2688 self.parser
2689 .finish_expr(expr, lhs_height.saturating_add(1), false, true)?
2690 } else {
2691 self.parser.finish_expr(expr, 1, true, false)?
2692 }
2693 } else {
2694 let cached_child_height = if singleton_constant {
2695 lhs_height.max(item_height.saturating_add(1))
2696 } else if singleton_subquery {
2697 lhs_height.max(item_height.saturating_sub(1))
2698 } else {
2699 lhs_height.max(item_height)
2700 };
2701 let parsed = self.parser.checked_expr(
2702 expr,
2703 cached_child_height,
2704 lhs_is_constant && items_are_constant,
2705 lhs_has_function || item_has_function,
2706 )?;
2707 if not {
2708 self.parser.add_cached_parent(parsed)?
2709 } else {
2710 parsed
2711 }
2712 };
2713 self.push_expr_tail(parsed, outer_min_bp);
2714 Ok(())
2715 }
2716
2717 fn window_start(&mut self) -> Result<(), ParseError> {
2718 let has_base_window = starts_window_base_name(self.parser.peek_kind());
2719 let build = WindowBuild {
2720 base_window: if has_base_window {
2721 Some(self.parser.parse_window_name()?)
2722 } else {
2723 None
2724 },
2725 partition_by: Vec::new(),
2726 order_by: Vec::new(),
2727 };
2728 if self.parser.eat_kind(&TokenKind::KwPartition) {
2729 self.parser.expect_kw(&TokenKind::KwBy)?;
2730 self.controls
2731 .push(ParseControl::WindowPartitionDone { build });
2732 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2733 } else {
2734 self.controls.push(ParseControl::WindowOrderStart { build });
2735 }
2736 Ok(())
2737 }
2738
2739 fn window_frame_start(&mut self, build: WindowBuild) {
2740 let frame_type = if self.parser.eat_kind(&TokenKind::KwRows) {
2741 Some(FrameType::Rows)
2742 } else if self.parser.eat_kind(&TokenKind::KwRange) {
2743 Some(FrameType::Range)
2744 } else if self.parser.eat_kind(&TokenKind::KwGroups) {
2745 Some(FrameType::Groups)
2746 } else {
2747 None
2748 };
2749 let Some(frame_type) = frame_type else {
2750 self.values.push(MachineValue::Window(WindowSpec {
2751 window_ref: build.base_window.map(WindowReference::Base),
2752 partition_by: build.partition_by,
2753 order_by: build.order_by,
2754 frame: None,
2755 }));
2756 return;
2757 };
2758 let between = self.parser.eat_kind(&TokenKind::KwBetween);
2759 self.controls.push(ParseControl::WindowFirstBoundDone {
2760 build,
2761 frame_type,
2762 between,
2763 });
2764 self.controls.push(ParseControl::FrameBoundStart);
2765 }
2766
2767 fn frame_bound_start(&mut self) -> Result<(), ParseError> {
2768 let origin = self
2769 .parser
2770 .peek_token()
2771 .cloned()
2772 .ok_or_else(|| self.parser.err_here("expected window frame bound"))?;
2773 if self.parser.eat_kind(&TokenKind::KwUnbounded) {
2774 let keyword_origin = self.parser.peek_token().cloned();
2778 let bound = if self.parser.eat_kind(&TokenKind::KwPreceding) {
2779 FrameBound::UnboundedPreceding
2780 } else {
2781 self.parser.expect_kw(&TokenKind::KwFollowing)?;
2782 FrameBound::UnboundedFollowing
2783 };
2784 self.values.push(MachineValue::FrameBound(ParsedFrameBound {
2785 value: bound,
2786 origin: keyword_origin.unwrap_or(origin),
2787 }));
2788 } else if matches!(
2789 self.parser.peek_kind(),
2790 TokenKind::Id(value) if value.eq_ignore_ascii_case("CURRENT")
2791 ) {
2792 self.parser.advance_token();
2793 self.parser.expect_kw(&TokenKind::KwRow)?;
2794 self.values.push(MachineValue::FrameBound(ParsedFrameBound {
2795 value: FrameBound::CurrentRow,
2796 origin,
2797 }));
2798 } else {
2799 self.controls
2800 .push(ParseControl::FrameBoundExprDone { origin });
2801 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2802 }
2803 Ok(())
2804 }
2805
2806 fn finish_frame(
2807 &mut self,
2808 frame_type: FrameType,
2809 start: FrameBound,
2810 end: Option<FrameBound>,
2811 ) -> Result<FrameSpec, ParseError> {
2812 let exclude = if self.parser.eat_kind(&TokenKind::KwExclude) {
2813 if self.parser.eat_kind(&TokenKind::KwNo) {
2814 let others = self.parser.parse_identifier()?;
2815 if !others.eq_ignore_ascii_case("OTHERS") {
2816 return Err(self.parser.err_here("expected OTHERS"));
2817 }
2818 Some(FrameExclude::NoOthers)
2819 } else if self.parser.eat_kind(&TokenKind::KwTies) {
2820 Some(FrameExclude::Ties)
2821 } else if self.parser.eat_kind(&TokenKind::KwGroup) {
2822 Some(FrameExclude::Group)
2823 } else if matches!(
2824 self.parser.peek_kind(),
2825 TokenKind::Id(value) if value.eq_ignore_ascii_case("CURRENT")
2826 ) {
2827 self.parser.advance_token();
2828 self.parser.expect_kw(&TokenKind::KwRow)?;
2829 Some(FrameExclude::CurrentRow)
2830 } else {
2831 return Err(self
2832 .parser
2833 .err_here("expected NO OTHERS, TIES, GROUP, or CURRENT ROW after EXCLUDE"));
2834 }
2835 } else {
2836 None
2837 };
2838 Ok(FrameSpec {
2839 frame_type,
2840 start,
2841 end,
2842 exclude,
2843 })
2844 }
2845
2846 fn step_select(&mut self, control: ParseControl) -> Result<(), ParseError> {
2847 match control {
2848 ParseControl::SelectStart { with } => {
2849 self.controls
2850 .push(ParseControl::SelectFirstCoreDone { with });
2851 self.controls.push(ParseControl::CoreStart);
2852 Ok(())
2853 }
2854 ParseControl::SelectFirstCoreDone { with } => {
2855 let core = self.pop_core()?;
2856 self.continue_select_body(SelectBuild {
2857 with,
2858 height: core.height,
2859 first: core.value,
2860 compounds: Vec::new(),
2861 order_by: Vec::new(),
2862 });
2863 Ok(())
2864 }
2865 ParseControl::SelectCompoundDone { mut build, op } => {
2866 let core = self.pop_core()?;
2867 build.height = build.height.max(core.height);
2868 build.compounds.push((op, core.value));
2869 self.continue_select_body(build);
2870 Ok(())
2871 }
2872 ParseControl::SelectOrderStart { build } => {
2873 let final_core = build
2874 .compounds
2875 .last()
2876 .map_or(&build.first, |(_, core)| core);
2877 if matches!(final_core, SelectCore::Values(_))
2878 && matches!(
2879 self.parser.peek_kind(),
2880 TokenKind::KwOrder | TokenKind::KwLimit
2881 )
2882 {
2883 return Err(self
2884 .parser
2885 .err_here("ORDER BY / LIMIT clause is not allowed after a VALUES term"));
2886 }
2887 if self.parser.eat_kind(&TokenKind::KwOrder) {
2888 self.parser.expect_kw(&TokenKind::KwBy)?;
2889 self.controls.push(ParseControl::SelectOrderDone { build });
2890 self.controls.push(ParseControl::OrderingStart);
2891 } else {
2892 self.start_select_limit(build)?;
2893 }
2894 Ok(())
2895 }
2896 ParseControl::SelectOrderDone { mut build } => {
2897 let term = self.pop_ordering()?;
2898 build.height = build.height.max(term.height);
2899 build.order_by.push(term.value);
2900 if self.parser.eat_kind(&TokenKind::Comma) {
2901 self.controls.push(ParseControl::SelectOrderDone { build });
2902 self.controls.push(ParseControl::OrderingStart);
2903 } else {
2904 self.start_select_limit(build)?;
2905 }
2906 Ok(())
2907 }
2908 ParseControl::SelectLimitFirstDone { build } => {
2909 let first = self.pop_expr()?;
2910 if self.parser.eat_kind(&TokenKind::KwOffset) {
2911 self.controls.push(ParseControl::SelectLimitSecondDone {
2912 build,
2913 first,
2914 comma_form: false,
2915 });
2916 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2917 } else if self.parser.eat_kind(&TokenKind::Comma) {
2918 self.controls.push(ParseControl::SelectLimitSecondDone {
2919 build,
2920 first,
2921 comma_form: true,
2922 });
2923 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2924 } else {
2925 let height = self.parser.checked_cached_parent_height(first.height)?;
2926 self.finish_select(
2927 build,
2928 HeightTracked {
2929 value: Some(LimitClause {
2930 limit: first.expr,
2931 offset: None,
2932 }),
2933 height,
2934 },
2935 )?;
2936 }
2937 Ok(())
2938 }
2939 ParseControl::SelectLimitSecondDone {
2940 build,
2941 first,
2942 comma_form,
2943 } => {
2944 let second = self.pop_expr()?;
2945 let height = self
2946 .parser
2947 .checked_cached_parent_height(first.height.max(second.height))?;
2948 let limit = if comma_form {
2949 LimitClause {
2950 limit: second.expr,
2951 offset: Some(first.expr),
2952 }
2953 } else {
2954 LimitClause {
2955 limit: first.expr,
2956 offset: Some(second.expr),
2957 }
2958 };
2959 self.finish_select(
2960 build,
2961 HeightTracked {
2962 value: Some(limit),
2963 height,
2964 },
2965 )
2966 }
2967 ParseControl::CoreStart => self.core_start(),
2968 ParseControl::CoreColumnStart { build } => self.core_column_start(build),
2969 ParseControl::CoreColumnDone { mut build } => {
2970 let expr = self.pop_expr()?;
2971 build.height = build.height.max(expr.height);
2972 build.columns.push(ResultColumn::Expr {
2973 expr: expr.expr,
2974 alias: self.parser.try_result_alias()?,
2975 });
2976 if self.parser.eat_kind(&TokenKind::Comma) {
2977 self.controls.push(ParseControl::CoreColumnStart { build });
2978 } else {
2979 self.controls.push(ParseControl::CoreAfterColumns { build });
2980 }
2981 Ok(())
2982 }
2983 ParseControl::CoreAfterColumns { build } => {
2984 if self.parser.eat_kind(&TokenKind::KwFrom) {
2985 self.controls.push(ParseControl::CoreFromDone { build });
2986 self.controls.push(ParseControl::FromStart);
2987 } else {
2988 self.continue_core_where(build)?;
2989 }
2990 Ok(())
2991 }
2992 ParseControl::CoreFromDone { mut build } => {
2993 build.from = Some(self.pop_from()?);
2994 self.continue_core_where(build)
2995 }
2996 ParseControl::CoreWhereDone { mut build } => {
2997 let expr = self.pop_expr()?;
2998 build.height = build.height.max(expr.height);
2999 build.where_clause = Some(Box::new(expr.expr));
3000 self.continue_core_group(build)
3001 }
3002 ParseControl::CoreGroupDone { mut build } => {
3003 let expr = self.pop_expr()?;
3004 build.height = build.height.max(expr.height);
3005 build.group_by.push(expr.expr);
3006 if self.parser.eat_kind(&TokenKind::Comma) {
3007 self.controls.push(ParseControl::CoreGroupDone { build });
3008 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3009 } else {
3010 self.continue_core_having(build);
3011 }
3012 Ok(())
3013 }
3014 ParseControl::CoreHavingDone { mut build } => {
3015 let expr = self.pop_expr()?;
3016 build.height = build.height.max(expr.height);
3017 build.having = Some(Box::new(expr.expr));
3018 self.continue_core_windows(build);
3019 Ok(())
3020 }
3021 ParseControl::CoreWindowStart { build } => {
3022 let name = self.parser.parse_window_name()?;
3023 self.parser.expect_kw(&TokenKind::KwAs)?;
3024 self.parser.expect_token(&TokenKind::LeftParen)?;
3025 self.controls
3026 .push(ParseControl::CoreWindowDone { build, name });
3027 self.controls.push(ParseControl::WindowStart);
3028 Ok(())
3029 }
3030 ParseControl::CoreWindowDone { mut build, name } => {
3031 let spec = self.pop_window()?;
3032 self.parser.expect_token(&TokenKind::RightParen)?;
3033 build.windows.push(WindowDef { name, spec });
3034 if self.parser.eat_kind(&TokenKind::Comma) {
3035 self.controls.push(ParseControl::CoreWindowStart { build });
3036 } else {
3037 self.finish_core(build);
3038 }
3039 Ok(())
3040 }
3041 ParseControl::ValuesRowStart {
3042 rows,
3043 height,
3044 force_union_all_from,
3045 } => {
3046 self.parser.expect_token(&TokenKind::LeftParen)?;
3047 self.controls.push(ParseControl::ValuesItemDone {
3048 rows,
3049 row: Vec::new(),
3050 height,
3051 force_union_all_from,
3052 });
3053 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3054 Ok(())
3055 }
3056 ParseControl::ValuesItemDone {
3057 mut rows,
3058 mut row,
3059 mut height,
3060 mut force_union_all_from,
3061 } => {
3062 let expr = self.pop_expr()?;
3063 height = height.max(expr.height);
3064 row.push(expr.expr);
3065 if self.parser.eat_kind(&TokenKind::Comma) {
3066 self.controls.push(ParseControl::ValuesItemDone {
3067 rows,
3068 row,
3069 height,
3070 force_union_all_from,
3071 });
3072 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3073 } else {
3074 self.parser.expect_token(&TokenKind::RightParen)?;
3075 if force_union_all_from.is_none() && self.parser.has_with {
3076 force_union_all_from = Some(rows.len());
3077 }
3078 rows.push(row);
3079 if self.parser.eat_kind(&TokenKind::Comma) {
3080 self.controls.push(ParseControl::ValuesRowStart {
3081 rows,
3082 height,
3083 force_union_all_from,
3084 });
3085 } else {
3086 self.values.push(MachineValue::Core(HeightTracked {
3087 value: SelectCore::Values(ValuesClause::parsed(
3088 rows,
3089 force_union_all_from,
3090 )),
3091 height,
3092 }));
3093 }
3094 }
3095 Ok(())
3096 }
3097 ParseControl::FromStart => {
3098 self.controls.push(ParseControl::FromSourceDone);
3099 self.controls.push(ParseControl::TableStart);
3100 Ok(())
3101 }
3102 ParseControl::FromSourceDone => {
3103 let source = self.pop_table()?;
3104 self.continue_from(FromBuild {
3105 source,
3106 joins: Vec::new(),
3107 })
3108 }
3109 ParseControl::FromTableDone { build, join_type } => {
3110 let table = self.pop_table()?;
3111 if self.parser.eat_kind(&TokenKind::KwOn) {
3112 self.controls.push(ParseControl::FromJoinConstraintDone {
3113 build,
3114 join_type,
3115 table,
3116 });
3117 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3118 return Ok(());
3119 }
3120 let constraint = if self.parser.eat_kind(&TokenKind::KwUsing) {
3121 self.parser.expect_token(&TokenKind::LeftParen)?;
3122 let mut columns = vec![self.parser.parse_identifier()?];
3123 while self.parser.eat_kind(&TokenKind::Comma) {
3124 columns.push(self.parser.parse_identifier()?);
3125 }
3126 self.parser.expect_token(&TokenKind::RightParen)?;
3127 Some(JoinConstraint::Using(columns))
3128 } else {
3129 None
3130 };
3131 self.append_join(build, join_type, table, constraint)
3132 }
3133 ParseControl::FromJoinConstraintDone {
3134 build,
3135 join_type,
3136 table,
3137 } => {
3138 let expr = self.pop_expr()?;
3139 self.append_join(build, join_type, table, Some(JoinConstraint::On(expr.expr)))
3140 }
3141 ParseControl::TableStart => self.table_start(),
3142 ParseControl::TableSubqueryDone => {
3143 let select = self.pop_select()?;
3144 self.parser.expect_token(&TokenKind::RightParen)?;
3145 self.values
3146 .push(MachineValue::Table(TableOrSubquery::Subquery {
3147 query: Box::new(select.value),
3148 alias: self.parser.try_table_alias()?,
3149 }));
3150 Ok(())
3151 }
3152 ParseControl::TableParenJoinDone => {
3153 let from = self.pop_from()?;
3154 self.parser.expect_token(&TokenKind::RightParen)?;
3155 self.values
3156 .push(MachineValue::Table(TableOrSubquery::ParenJoin(Box::new(
3157 from,
3158 ))));
3159 Ok(())
3160 }
3161 ParseControl::TableFunctionArgDone { name, mut args } => {
3162 args.push(self.pop_expr()?.expr);
3163 if self.parser.eat_kind(&TokenKind::Comma) {
3164 self.controls
3165 .push(ParseControl::TableFunctionArgDone { name, args });
3166 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3167 } else {
3168 self.parser.expect_token(&TokenKind::RightParen)?;
3169 self.values
3170 .push(MachineValue::Table(TableOrSubquery::TableFunction {
3171 name,
3172 args,
3173 alias: self.parser.try_table_alias()?,
3174 }));
3175 }
3176 Ok(())
3177 }
3178 ParseControl::WithStart => self.with_start(),
3179 ParseControl::CteQueryDone {
3180 recursive,
3181 mut ctes,
3182 name,
3183 columns,
3184 materialized,
3185 } => {
3186 let query = self.pop_select()?;
3187 self.parser.expect_token(&TokenKind::RightParen)?;
3188 ctes.push(Cte {
3189 name,
3190 columns,
3191 materialized,
3192 query: query.value,
3193 });
3194 if self.parser.eat_kind(&TokenKind::Comma) {
3195 self.start_cte(recursive, ctes)?;
3196 } else {
3197 let mut with = WithClause { recursive, ctes };
3200 with.normalize_recursive();
3201 self.values.push(MachineValue::With(with));
3202 }
3203 Ok(())
3204 }
3205 _ => Err(self
3206 .parser
3207 .err_here("internal expression parser control reached SELECT dispatcher")),
3208 }
3209 }
3210
3211 fn continue_select_body(&mut self, build: SelectBuild) {
3212 let op = if self.parser.eat_kind(&TokenKind::KwUnion) {
3213 Some(if self.parser.eat_kind(&TokenKind::KwAll) {
3214 CompoundOp::UnionAll
3215 } else {
3216 CompoundOp::Union
3217 })
3218 } else if self.parser.eat_kind(&TokenKind::KwIntersect) {
3219 Some(CompoundOp::Intersect)
3220 } else if self.parser.eat_kind(&TokenKind::KwExcept) {
3221 Some(CompoundOp::Except)
3222 } else {
3223 None
3224 };
3225 if let Some(op) = op {
3226 self.controls
3227 .push(ParseControl::SelectCompoundDone { build, op });
3228 self.controls.push(ParseControl::CoreStart);
3229 } else {
3230 self.controls.push(ParseControl::SelectOrderStart { build });
3231 }
3232 }
3233
3234 fn start_select_limit(&mut self, build: SelectBuild) -> Result<(), ParseError> {
3235 if self.parser.eat_kind(&TokenKind::KwLimit) {
3236 self.controls
3237 .push(ParseControl::SelectLimitFirstDone { build });
3238 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3239 } else {
3240 self.finish_select(
3241 build,
3242 HeightTracked {
3243 value: None,
3244 height: 0,
3245 },
3246 )?;
3247 }
3248 Ok(())
3249 }
3250
3251 fn finish_select(
3252 &mut self,
3253 mut build: SelectBuild,
3254 limit: HeightTracked<Option<LimitClause>>,
3255 ) -> Result<(), ParseError> {
3256 build.height = build.height.max(limit.height);
3257 let final_core = build
3258 .compounds
3259 .last()
3260 .map_or(&build.first, |(_, core)| core);
3261 if matches!(final_core, SelectCore::Values(_))
3262 && (!build.order_by.is_empty() || limit.value.is_some())
3263 {
3264 return Err(self
3265 .parser
3266 .err_here("ORDER BY / LIMIT clause is not allowed after a VALUES term"));
3267 }
3268 self.values.push(MachineValue::Select(HeightTracked {
3269 value: SelectStatement {
3270 with: build.with,
3271 body: SelectBody {
3272 select: build.first,
3273 compounds: build.compounds,
3274 },
3275 order_by: build.order_by,
3276 limit: limit.value,
3277 },
3278 height: build.height,
3279 }));
3280 Ok(())
3281 }
3282
3283 fn core_start(&mut self) -> Result<(), ParseError> {
3284 if self.parser.eat_kind(&TokenKind::KwValues) {
3285 self.controls.push(ParseControl::ValuesRowStart {
3286 rows: Vec::new(),
3287 height: 0,
3288 force_union_all_from: None,
3289 });
3290 return Ok(());
3291 }
3292 self.parser.expect_kw(&TokenKind::KwSelect)?;
3293 let distinct = if self.parser.eat_kind(&TokenKind::KwDistinct) {
3294 Distinctness::Distinct
3295 } else {
3296 let _ = self.parser.eat_kind(&TokenKind::KwAll);
3297 Distinctness::All
3298 };
3299 self.controls.push(ParseControl::CoreColumnStart {
3300 build: CoreBuild {
3301 distinct,
3302 columns: Vec::new(),
3303 height: 0,
3304 from: None,
3305 where_clause: None,
3306 group_by: Vec::new(),
3307 having: None,
3308 windows: Vec::new(),
3309 },
3310 });
3311 Ok(())
3312 }
3313
3314 fn core_column_start(&mut self, mut build: CoreBuild) -> Result<(), ParseError> {
3315 if self.parser.eat_kind(&TokenKind::Star) {
3316 build.columns.push(ResultColumn::Star);
3317 if self.parser.eat_kind(&TokenKind::Comma) {
3318 self.controls.push(ParseControl::CoreColumnStart { build });
3319 } else {
3320 self.controls.push(ParseControl::CoreAfterColumns { build });
3321 }
3322 return Ok(());
3323 }
3324 if starts_table_star_qualifier(self.parser.peek_kind())
3325 && self
3326 .parser
3327 .tokens
3328 .get(self.parser.pos + 1)
3329 .is_some_and(|token| token.kind == TokenKind::Dot)
3330 {
3331 let table_star = self
3332 .parser
3333 .tokens
3334 .get(self.parser.pos + 2)
3335 .is_some_and(|token| token.kind == TokenKind::Star);
3336 let schema_table_star = self
3337 .parser
3338 .tokens
3339 .get(self.parser.pos + 2)
3340 .is_some_and(|token| starts_table_star_qualifier(&token.kind))
3341 && self
3342 .parser
3343 .tokens
3344 .get(self.parser.pos + 3)
3345 .is_some_and(|token| token.kind == TokenKind::Dot)
3346 && self
3347 .parser
3348 .tokens
3349 .get(self.parser.pos + 4)
3350 .is_some_and(|token| token.kind == TokenKind::Star);
3351 if table_star || schema_table_star {
3352 let first = self.parser.parse_table_star_qualifier()?;
3353 self.parser.expect_token(&TokenKind::Dot)?;
3354 let name = if schema_table_star {
3355 let second = self.parser.parse_table_star_qualifier()?;
3356 self.parser.expect_token(&TokenKind::Dot)?;
3357 QualifiedName::qualified(first, second)
3358 } else {
3359 QualifiedName::bare(first)
3360 };
3361 self.parser.expect_token(&TokenKind::Star)?;
3362 build.columns.push(ResultColumn::TableStar(name));
3363 if self.parser.eat_kind(&TokenKind::Comma) {
3364 self.controls.push(ParseControl::CoreColumnStart { build });
3365 } else {
3366 self.controls.push(ParseControl::CoreAfterColumns { build });
3367 }
3368 return Ok(());
3369 }
3370 }
3371 self.controls.push(ParseControl::CoreColumnDone { build });
3372 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3373 Ok(())
3374 }
3375
3376 fn continue_core_where(&mut self, build: CoreBuild) -> Result<(), ParseError> {
3377 if self.parser.eat_kind(&TokenKind::KwWhere) {
3378 self.controls.push(ParseControl::CoreWhereDone { build });
3379 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3380 } else {
3381 self.continue_core_group(build)?;
3382 }
3383 Ok(())
3384 }
3385
3386 fn continue_core_group(&mut self, build: CoreBuild) -> Result<(), ParseError> {
3387 if self.parser.eat_kind(&TokenKind::KwGroup) {
3388 self.parser.expect_kw(&TokenKind::KwBy)?;
3389 self.controls.push(ParseControl::CoreGroupDone { build });
3390 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3391 } else {
3392 self.continue_core_having(build);
3393 }
3394 Ok(())
3395 }
3396
3397 fn continue_core_having(&mut self, build: CoreBuild) {
3398 if self.parser.eat_kind(&TokenKind::KwHaving) {
3399 self.controls.push(ParseControl::CoreHavingDone { build });
3400 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3401 } else {
3402 self.continue_core_windows(build);
3403 }
3404 }
3405
3406 fn continue_core_windows(&mut self, build: CoreBuild) {
3407 if self.parser.eat_kind(&TokenKind::KwWindow) {
3408 self.controls.push(ParseControl::CoreWindowStart { build });
3409 } else {
3410 self.finish_core(build);
3411 }
3412 }
3413
3414 fn finish_core(&mut self, build: CoreBuild) {
3415 self.values.push(MachineValue::Core(HeightTracked {
3416 value: SelectCore::Select {
3417 distinct: build.distinct,
3418 columns: build.columns,
3419 from: build.from,
3420 where_clause: build.where_clause,
3421 group_by: build.group_by,
3422 having: build.having,
3423 windows: build.windows,
3424 },
3425 height: build.height,
3426 }));
3427 }
3428
3429 fn continue_from(&mut self, build: FromBuild) -> Result<(), ParseError> {
3430 let join_type = if let Some(join_type) = self.parser.try_join_type()? {
3431 Some(join_type)
3432 } else if self.parser.eat_kind(&TokenKind::Comma) {
3433 Some(JoinType {
3434 natural: false,
3435 kind: JoinKind::Cross,
3436 })
3437 } else {
3438 None
3439 };
3440 if let Some(join_type) = join_type {
3441 self.controls
3442 .push(ParseControl::FromTableDone { build, join_type });
3443 self.controls.push(ParseControl::TableStart);
3444 } else {
3445 self.values.push(MachineValue::From(FromClause {
3446 source: build.source,
3447 joins: build.joins,
3448 }));
3449 }
3450 Ok(())
3451 }
3452
3453 fn append_join(
3454 &mut self,
3455 mut build: FromBuild,
3456 join_type: JoinType,
3457 table: TableOrSubquery,
3458 constraint: Option<JoinConstraint>,
3459 ) -> Result<(), ParseError> {
3460 if join_type.natural && constraint.is_some() {
3461 return Err(self
3464 .parser
3465 .err_semantic("a NATURAL join may not have an ON or USING clause"));
3466 }
3467 build.joins.push(JoinClause {
3468 join_type,
3469 table,
3470 constraint,
3471 });
3472 self.continue_from(build)
3473 }
3474
3475 fn table_start(&mut self) -> Result<(), ParseError> {
3476 if self.parser.eat_kind(&TokenKind::LeftParen) {
3477 if matches!(
3478 self.parser.peek_kind(),
3479 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
3480 ) {
3481 self.controls.push(ParseControl::TableSubqueryDone);
3482 self.controls.push(ParseControl::SubqueryStart);
3483 } else {
3484 self.controls.push(ParseControl::TableParenJoinDone);
3485 self.controls.push(ParseControl::FromStart);
3486 }
3487 return Ok(());
3488 }
3489 let name = self.parser.parse_qualified_name()?;
3490 if name.schema.is_none() && self.parser.eat_kind(&TokenKind::LeftParen) {
3491 if self.parser.eat_kind(&TokenKind::RightParen) {
3492 self.values
3493 .push(MachineValue::Table(TableOrSubquery::TableFunction {
3494 name: name.name,
3495 args: Vec::new(),
3496 alias: self.parser.try_table_alias()?,
3497 }));
3498 } else {
3499 self.controls.push(ParseControl::TableFunctionArgDone {
3500 name: name.name,
3501 args: Vec::new(),
3502 });
3503 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3504 }
3505 return Ok(());
3506 }
3507 self.values
3508 .push(MachineValue::Table(TableOrSubquery::Table {
3509 name,
3510 alias: self.parser.try_table_alias()?,
3511 index_hint: self.parser.parse_index_hint()?,
3512 time_travel: self.parser.parse_time_travel_clause()?,
3513 }));
3514 Ok(())
3515 }
3516
3517 fn with_start(&mut self) -> Result<(), ParseError> {
3518 self.parser.expect_kw(&TokenKind::KwWith)?;
3519 self.parser.has_with = true;
3520 let recursive = self.parser.eat_kind(&TokenKind::KwRecursive);
3521 self.start_cte(recursive, Vec::new())
3522 }
3523
3524 fn start_cte(&mut self, recursive: bool, ctes: Vec<Cte>) -> Result<(), ParseError> {
3525 let name = self.parser.parse_identifier()?;
3526 let columns = if self.parser.eat_kind(&TokenKind::LeftParen) {
3527 let mut columns = vec![self.parser.parse_identifier()?];
3528 while self.parser.eat_kind(&TokenKind::Comma) {
3529 columns.push(self.parser.parse_identifier()?);
3530 }
3531 self.parser.expect_token(&TokenKind::RightParen)?;
3532 columns
3533 } else {
3534 Vec::new()
3535 };
3536 self.parser.expect_kw(&TokenKind::KwAs)?;
3537 let materialized = if self.parser.eat_kind(&TokenKind::KwNot) {
3538 self.parser.expect_kw(&TokenKind::KwMaterialized)?;
3539 Some(CteMaterialized::NotMaterialized)
3540 } else if self.parser.eat_kind(&TokenKind::KwMaterialized) {
3541 Some(CteMaterialized::Materialized)
3542 } else {
3543 None
3544 };
3545 self.parser.expect_token(&TokenKind::LeftParen)?;
3546 self.controls.push(ParseControl::CteQueryDone {
3547 recursive,
3548 ctes,
3549 name,
3550 columns,
3551 materialized,
3552 });
3553 self.controls.push(ParseControl::SubqueryStart);
3554 Ok(())
3555 }
3556}
3557
3558impl Parser {
3559 pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
3561 self.parse_expr_tracked().map(|parsed| parsed.expr)
3562 }
3563
3564 pub(crate) fn parse_expr_tracked(&mut self) -> Result<ParsedExpr, ParseError> {
3565 ParseMachine::for_expr(self).run_expr()
3566 }
3567
3568 pub(crate) fn parse_select_tracked_machine(
3569 &mut self,
3570 with: Option<WithClause>,
3571 ) -> Result<HeightTracked<SelectStatement>, ParseError> {
3572 ParseMachine::for_select(self, with).run_select()
3573 }
3574
3575 pub(crate) fn parse_with_clause_machine(&mut self) -> Result<WithClause, ParseError> {
3576 ParseMachine::for_with(self).run_with()
3577 }
3578
3579 pub(crate) fn parse_from_clause_machine(&mut self) -> Result<FromClause, ParseError> {
3580 ParseMachine::for_from(self).run_from()
3581 }
3582
3583 fn finish_expr(
3584 &self,
3585 expr: Expr,
3586 height: u32,
3587 is_constant: bool,
3588 has_function: bool,
3589 ) -> Result<ParsedExpr, ParseError> {
3590 if height > MAX_PARSE_DEPTH {
3591 return Err(ParseError::expression_too_deep(
3592 MAX_PARSE_DEPTH,
3593 self.peek_token(),
3594 ));
3595 }
3596 let root = match &expr {
3597 Expr::UnaryOp {
3598 op: UnaryOp::Plus, ..
3599 } => CachedRoot::UnaryPlus,
3600 Expr::RowValue(..) => CachedRoot::Vector,
3601 Expr::Subquery(..) => CachedRoot::ScalarSubquery,
3602 _ => CachedRoot::Other,
3603 };
3604 Ok(ParsedExpr {
3605 expr,
3606 height,
3607 is_constant,
3608 has_function,
3609 root,
3610 })
3611 }
3612
3613 fn checked_expr(
3614 &self,
3615 expr: Expr,
3616 max_child_height: u32,
3617 is_constant: bool,
3618 has_function: bool,
3619 ) -> Result<ParsedExpr, ParseError> {
3620 let height = max_child_height.saturating_add(1);
3621 self.finish_expr(expr, height, is_constant, has_function)
3622 }
3623
3624 fn add_cached_parent(&self, mut parsed: ParsedExpr) -> Result<ParsedExpr, ParseError> {
3625 parsed.height = parsed.height.saturating_add(1);
3626 if parsed.height > MAX_PARSE_DEPTH {
3627 return Err(ParseError::expression_too_deep(
3628 MAX_PARSE_DEPTH,
3629 self.peek_token(),
3630 ));
3631 }
3632 parsed.root = CachedRoot::Other;
3633 Ok(parsed)
3634 }
3635
3636 fn finish_unary(
3637 &self,
3638 op: UnaryOp,
3639 mut inner: ParsedExpr,
3640 span: Span,
3641 ) -> Result<ParsedExpr, ParseError> {
3642 if matches!(op, UnaryOp::Plus | UnaryOp::Negate)
3643 && inner.root == CachedRoot::UnaryPlus
3644 && let Expr::UnaryOp {
3645 op: inner_op,
3646 span: inner_span,
3647 ..
3648 } = &mut inner.expr
3649 {
3650 *inner_op = op;
3651 *inner_span = span;
3652 inner.root = if op == UnaryOp::Plus {
3653 CachedRoot::UnaryPlus
3654 } else {
3655 CachedRoot::Other
3656 };
3657 return Ok(inner);
3658 }
3659
3660 let height = inner.height;
3661 let is_constant = inner.is_constant;
3662 let has_function = inner.has_function;
3663 self.checked_expr(
3664 Expr::UnaryOp {
3665 op,
3666 expr: Box::new(inner.expr),
3667 span,
3668 },
3669 height,
3670 is_constant,
3671 has_function,
3672 )
3673 }
3674
3675 #[cfg(test)]
3678 fn parse_expr_bp(&mut self, min_bp: u8) -> Result<ParsedExpr, ParseError> {
3679 self.with_recursion_guard(|p| p.parse_expr_bp_inner(min_bp))
3680 }
3681
3682 #[cfg(test)]
3683 fn parse_expr_bp_inner(&mut self, min_bp: u8) -> Result<ParsedExpr, ParseError> {
3684 let prefixes = self.collect_prefix_frames();
3685 let mut lhs = self.parse_prefix()?;
3686
3687 for prefix in prefixes.into_iter().rev() {
3688 match prefix {
3689 DeepExprFrame::Unary { op, span, right_bp } => {
3690 lhs = self.parse_expr_tail(lhs, right_bp)?;
3691 let span = span.merge(lhs.expr.span());
3692 lhs = self.finish_unary(op, lhs, span)?;
3693 }
3694 DeepExprFrame::Parenthesis { span } => {
3695 lhs = self.finish_parenthesized_frame(lhs, span)?;
3696 }
3697 }
3698 }
3699
3700 self.parse_expr_tail(lhs, min_bp)
3701 }
3702
3703 #[cfg(test)]
3704 fn parse_expr_tail(
3705 &mut self,
3706 mut lhs: ParsedExpr,
3707 min_bp: u8,
3708 ) -> Result<ParsedExpr, ParseError> {
3709 loop {
3710 if let Some(l_bp) = self.postfix_bp() {
3712 if l_bp < min_bp {
3713 break;
3714 }
3715 lhs = self.parse_postfix(lhs)?;
3716 continue;
3717 }
3718
3719 if let Some((l_bp, r_bp)) = self.infix_bp() {
3721 if l_bp < min_bp {
3722 break;
3723 }
3724 lhs = self.parse_infix(lhs, r_bp)?;
3725 continue;
3726 }
3727
3728 break;
3729 }
3730
3731 Ok(lhs)
3732 }
3733
3734 #[cfg(test)]
3735 fn collect_prefix_frames(&mut self) -> Vec<DeepExprFrame> {
3736 let mut prefixes = Vec::new();
3737 loop {
3738 let unary = match self.peek_kind() {
3739 TokenKind::Minus => {
3740 let folds_i64_min = matches!(
3741 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3742 Some(TokenKind::OversizedInt(value)) if value == "9223372036854775808"
3743 );
3744 if folds_i64_min {
3745 break;
3746 }
3747 Some((UnaryOp::Negate, bp::UNARY))
3748 }
3749 TokenKind::Plus => Some((UnaryOp::Plus, bp::UNARY)),
3750 TokenKind::Tilde => Some((UnaryOp::BitNot, bp::UNARY)),
3751 TokenKind::KwNot => {
3752 if matches!(
3753 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3754 Some(TokenKind::KwExists)
3755 ) {
3756 break;
3757 }
3758 Some((UnaryOp::Not, bp::NOT_PREFIX))
3759 }
3760 TokenKind::LeftParen => {
3761 let starts_subquery = matches!(
3762 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3763 Some(TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues)
3764 );
3765 if starts_subquery {
3766 break;
3767 }
3768 let token = self.advance_token();
3769 prefixes.push(DeepExprFrame::Parenthesis { span: token.span });
3770 continue;
3771 }
3772 _ => break,
3773 };
3774 let Some((op, right_bp)) = unary else {
3775 break;
3776 };
3777 let token = self.advance_token();
3778 prefixes.push(DeepExprFrame::Unary {
3779 op,
3780 span: token.span,
3781 right_bp,
3782 });
3783 }
3784 prefixes
3785 }
3786
3787 #[cfg(test)]
3788 fn finish_parenthesized_frame(
3789 &mut self,
3790 mut first: ParsedExpr,
3791 start: Span,
3792 ) -> Result<ParsedExpr, ParseError> {
3793 first = self.parse_expr_tail(first, 0)?;
3794 if self.eat_kind(&TokenKind::Comma) {
3795 let mut is_constant = first.is_constant;
3796 let mut has_function = first.has_function;
3797 let mut exprs = vec![first.expr];
3798 loop {
3799 let parsed = self.parse_expr_bp(0)?;
3800 is_constant &= parsed.is_constant;
3801 has_function |= parsed.has_function;
3802 exprs.push(parsed.expr);
3803 if !self.eat_kind(&TokenKind::Comma) {
3804 break;
3805 }
3806 }
3807 let end = self.expect_kind(&TokenKind::RightParen)?;
3808 return self.finish_expr(
3809 Expr::RowValue(exprs, start.merge(end)),
3810 1,
3811 is_constant,
3812 has_function,
3813 );
3814 }
3815 self.expect_kind(&TokenKind::RightParen)?;
3816 Ok(first)
3817 }
3818
3819 fn peek_kind(&self) -> &TokenKind {
3822 self.tokens
3823 .get(self.pos)
3824 .map_or(&TokenKind::Eof, |t| &t.kind)
3825 }
3826
3827 fn peek_token(&self) -> Option<&Token> {
3828 self.tokens.get(self.pos)
3829 }
3830
3831 #[cfg(test)]
3832 fn peek_nth_token(&self, offset: usize) -> Option<&Token> {
3833 self.tokens.get(self.pos + offset)
3834 }
3835
3836 fn advance_token(&mut self) -> Token {
3837 let tok = self.tokens[self.pos].clone();
3838 if tok.kind != TokenKind::Eof {
3839 self.pos += 1;
3840 }
3841 tok
3842 }
3843
3844 fn at_kind(&self, kind: &TokenKind) -> bool {
3845 std::mem::discriminant(self.peek_kind()) == std::mem::discriminant(kind)
3846 }
3847
3848 fn eat_kind(&mut self, kind: &TokenKind) -> bool {
3849 if self.at_kind(kind) {
3850 self.advance_token();
3851 true
3852 } else {
3853 false
3854 }
3855 }
3856
3857 fn expect_kind(&mut self, expected: &TokenKind) -> Result<Span, ParseError> {
3858 if self.at_kind(expected) {
3859 Ok(self.advance_token().span)
3860 } else {
3861 Err(self.err_here(format!("expected {expected:?}, got {:?}", self.peek_kind())))
3862 }
3863 }
3864
3865 fn err_here(&self, message: impl Into<String>) -> ParseError {
3866 let mut error = ParseError::at(message, self.peek_token());
3872 error.kind = crate::parser::ParseErrorKind::UnexpectedToken;
3873 error
3874 }
3875
3876 #[cfg(test)]
3879 #[allow(clippy::too_many_lines)]
3880 fn parse_prefix(&mut self) -> Result<ParsedExpr, ParseError> {
3881 let Token {
3882 kind,
3883 span: token_span,
3884 line,
3885 col,
3886 } = self.advance_token();
3887 if self.at_kind(&TokenKind::Dot) && starts_table_star_qualifier(&kind) {
3888 let name = match &kind {
3889 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => Arc::clone(name),
3890 TokenKind::String(name) => Arc::<str>::from(name.as_str()),
3891 keyword => Arc::<str>::from(kw_to_str(keyword)),
3892 };
3893 return self.parse_ident_expr(name, token_span);
3894 }
3895 match kind {
3896 TokenKind::Integer(i) => Ok(ParsedExpr::leaf(Expr::Literal(
3898 Literal::Integer(i),
3899 token_span,
3900 ))),
3901 TokenKind::OversizedInt(s) => match s.parse::<f64>() {
3905 Ok(v) => Ok(ParsedExpr::leaf(Expr::Literal(
3906 Literal::Float(v),
3907 token_span,
3908 ))),
3909 Err(_) => Err(ParseError {
3910 kind: crate::parser::ParseErrorKind::Syntax,
3911 message: "integer out of range".to_owned(),
3912 span: token_span,
3913 line,
3914 col,
3915 }),
3916 },
3917 TokenKind::Float(f) => Ok(ParsedExpr::leaf(Expr::Literal(
3918 Literal::Float(f),
3919 token_span,
3920 ))),
3921 TokenKind::String(s) if matches!(self.peek_kind(), TokenKind::Dot) => {
3922 self.parse_ident_expr(s, token_span)
3923 }
3924 TokenKind::String(s) => Ok(ParsedExpr::leaf(Expr::Literal(
3925 Literal::String(s),
3926 token_span,
3927 ))),
3928 TokenKind::Blob(b) => Ok(ParsedExpr::leaf(Expr::Literal(
3929 Literal::Blob(b),
3930 token_span,
3931 ))),
3932 TokenKind::KwNull => Ok(ParsedExpr::leaf(Expr::Literal(Literal::Null, token_span))),
3933 TokenKind::KwTrue => Ok(ParsedExpr::leaf(Expr::Literal(Literal::True, token_span))),
3934 TokenKind::KwFalse => Ok(ParsedExpr::leaf(Expr::Literal(Literal::False, token_span))),
3935 TokenKind::KwCurrentTime => Ok(ParsedExpr::leaf(Expr::Literal(
3936 Literal::CurrentTime,
3937 token_span,
3938 ))),
3939 TokenKind::KwCurrentDate => Ok(ParsedExpr::leaf(Expr::Literal(
3940 Literal::CurrentDate,
3941 token_span,
3942 ))),
3943 TokenKind::KwCurrentTimestamp => Ok(ParsedExpr::leaf(Expr::Literal(
3944 Literal::CurrentTimestamp,
3945 token_span,
3946 ))),
3947
3948 TokenKind::Question => Ok(ParsedExpr::leaf(Expr::Placeholder(
3950 PlaceholderType::Anonymous,
3951 token_span,
3952 ))),
3953 TokenKind::QuestionNum(n) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3954 PlaceholderType::Numbered(n),
3955 token_span,
3956 ))),
3957 TokenKind::ColonParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3958 PlaceholderType::ColonNamed(s),
3959 token_span,
3960 ))),
3961 TokenKind::AtParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3962 PlaceholderType::AtNamed(s),
3963 token_span,
3964 ))),
3965 TokenKind::DollarParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3966 PlaceholderType::DollarNamed(s),
3967 token_span,
3968 ))),
3969
3970 TokenKind::Minus => {
3972 if let TokenKind::OversizedInt(s) = self.peek_kind()
3976 && s == "9223372036854775808"
3977 {
3978 let num_span = self.advance_token().span;
3979 let span = token_span.merge(num_span);
3980 return self.finish_expr(
3981 Expr::Literal(Literal::Integer(i64::MIN), span),
3982 1,
3983 true,
3984 false,
3985 );
3986 }
3987 let inner = self.parse_expr_bp(bp::UNARY)?;
3988 let span = token_span.merge(inner.expr.span());
3989 self.finish_unary(UnaryOp::Negate, inner, span)
3990 }
3991 TokenKind::Plus => {
3992 let inner = self.parse_expr_bp(bp::UNARY)?;
3993 let span = token_span.merge(inner.expr.span());
3994 self.finish_unary(UnaryOp::Plus, inner, span)
3995 }
3996 TokenKind::Tilde => {
3997 let inner = self.parse_expr_bp(bp::UNARY)?;
3998 let span = token_span.merge(inner.expr.span());
3999 self.finish_unary(UnaryOp::BitNot, inner, span)
4000 }
4001
4002 TokenKind::KwNot => {
4004 if matches!(self.peek_kind(), TokenKind::KwExists) {
4006 self.advance_token();
4007 self.expect_kind(&TokenKind::LeftParen)?;
4008 let subquery = self.parse_subquery_minimal()?;
4009 let end = self.expect_kind(&TokenKind::RightParen)?;
4010 let span = token_span.merge(end);
4011 let height = subquery.height;
4012 let exists = self.checked_expr(
4013 Expr::Exists {
4014 subquery: Box::new(subquery.value),
4015 not: true,
4016 span,
4017 },
4018 height,
4019 false,
4020 false,
4021 )?;
4022 return self.add_cached_parent(exists);
4023 }
4024 let inner = self.parse_expr_bp(bp::NOT_PREFIX)?;
4025 let span = token_span.merge(inner.expr.span());
4026 self.finish_unary(UnaryOp::Not, inner, span)
4027 }
4028
4029 TokenKind::KwExists => {
4031 self.expect_kind(&TokenKind::LeftParen)?;
4032 let subquery = self.parse_subquery_minimal()?;
4033 let end = self.expect_kind(&TokenKind::RightParen)?;
4034 let span = token_span.merge(end);
4035 let height = subquery.height;
4036 self.checked_expr(
4037 Expr::Exists {
4038 subquery: Box::new(subquery.value),
4039 not: false,
4040 span,
4041 },
4042 height,
4043 false,
4044 false,
4045 )
4046 }
4047
4048 TokenKind::KwCast => {
4050 self.expect_kind(&TokenKind::LeftParen)?;
4051 let inner = self.parse_expr_bp(0)?;
4052 self.expect_kind(&TokenKind::KwAs)?;
4053 let type_name = self.parse_cast_type_name()?;
4054 let end = self.expect_kind(&TokenKind::RightParen)?;
4055 let span = token_span.merge(end);
4056 let height = inner.height;
4057 let is_constant = inner.is_constant;
4058 let has_function = inner.has_function;
4059 self.checked_expr(
4060 Expr::Cast {
4061 expr: Box::new(inner.expr),
4062 type_name,
4063 span,
4064 },
4065 height,
4066 is_constant,
4067 has_function,
4068 )
4069 }
4070
4071 TokenKind::KwCase => self.parse_case_expr(token_span),
4073
4074 TokenKind::KwRaise => {
4076 self.expect_kind(&TokenKind::LeftParen)?;
4077 let (action, message) = self.parse_raise_args()?;
4078 let end = self.expect_kind(&TokenKind::RightParen)?;
4079 let span = token_span.merge(end);
4080 Ok(ParsedExpr::leaf(Expr::Raise {
4081 action,
4082 message,
4083 span,
4084 }))
4085 }
4086
4087 TokenKind::LeftParen => {
4089 if matches!(
4090 self.peek_kind(),
4091 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
4092 ) {
4093 let subquery = self.parse_subquery_minimal()?;
4094 let end = self.expect_kind(&TokenKind::RightParen)?;
4095 let span = token_span.merge(end);
4096 return self.checked_expr(
4097 Expr::Subquery(Box::new(subquery.value), span),
4098 subquery.height,
4099 false,
4100 false,
4101 );
4102 }
4103 let first = self.parse_expr_bp(0)?;
4104 if self.eat_kind(&TokenKind::Comma) {
4105 let mut is_constant = first.is_constant;
4106 let mut has_function = first.has_function;
4107 let mut exprs = vec![first.expr];
4108 loop {
4109 let parsed = self.parse_expr_bp(0)?;
4110 is_constant &= parsed.is_constant;
4111 has_function |= parsed.has_function;
4112 exprs.push(parsed.expr);
4113 if !self.eat_kind(&TokenKind::Comma) {
4114 break;
4115 }
4116 }
4117 let end = self.expect_kind(&TokenKind::RightParen)?;
4118 let span = token_span.merge(end);
4119 self.finish_expr(Expr::RowValue(exprs, span), 1, is_constant, has_function)
4120 } else {
4121 self.expect_kind(&TokenKind::RightParen)?;
4122 Ok(first)
4123 }
4124 }
4125
4126 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => {
4128 self.parse_ident_expr(name, token_span)
4129 }
4130
4131 TokenKind::KwReplace if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4133 self.parse_function_call("replace".to_owned(), token_span)
4134 }
4135 TokenKind::KwLike if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4141 self.parse_function_call("like".to_owned(), token_span)
4142 }
4143 TokenKind::KwGlob if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4144 self.parse_function_call("glob".to_owned(), token_span)
4145 }
4146 TokenKind::KwRegexp if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4147 self.parse_function_call("regexp".to_owned(), token_span)
4148 }
4149 TokenKind::KwMatch if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4150 self.parse_function_call("match".to_owned(), token_span)
4151 }
4152
4153 k if is_nonreserved_kw(&k) => {
4157 let name = kw_to_str(&k);
4158 self.parse_ident_expr(name, token_span)
4159 }
4160
4161 TokenKind::Error(msg) => Err(ParseError {
4162 kind: crate::parser::ParseErrorKind::Tokenizer,
4165 message: msg,
4166 span: token_span,
4167 line,
4168 col,
4169 }),
4170 kind => Err(ParseError {
4171 kind: crate::parser::ParseErrorKind::UnexpectedToken,
4172 message: format!("unexpected token in expression: {kind:?}"),
4173 span: token_span,
4174 line,
4175 col,
4176 }),
4177 }
4178 }
4179
4180 #[cfg(test)]
4182 fn parse_ident_expr<S>(&mut self, name: S, start: Span) -> Result<ParsedExpr, ParseError>
4183 where
4184 S: AsRef<str> + Into<Arc<str>>,
4185 {
4186 if matches!(self.peek_kind(), TokenKind::LeftParen) {
4188 return self.parse_function_call(name.as_ref().to_owned(), start);
4189 }
4190 let name = name.into();
4191 if matches!(self.peek_kind(), TokenKind::Dot) {
4194 let Some(mid_tok) = self.peek_nth_token(1).cloned() else {
4195 return Err(self.err_here("expected column name after '.'"));
4196 };
4197 let mid_name = match &mid_tok.kind {
4198 TokenKind::Id(c) | TokenKind::QuotedId(c, _) => Arc::clone(c),
4199 TokenKind::String(c) => Arc::<str>::from(c.as_str()),
4200 k if starts_post_dot_identifier(k) => Arc::<str>::from(kw_to_str(k)),
4201 _ => {
4202 return Err(ParseError::unexpected_at(
4203 format!("expected column name after '.', got {:?}", mid_tok.kind),
4204 Some(&mid_tok),
4205 ));
4206 }
4207 };
4208 if matches!(
4210 self.peek_nth_token(2).map(|t| &t.kind),
4211 Some(TokenKind::Dot)
4212 ) {
4213 let Some(col_tok) = self.peek_nth_token(3).cloned() else {
4214 return Err(self.err_here("expected column name after '.'"));
4215 };
4216 let col_name = match &col_tok.kind {
4217 TokenKind::Id(c) | TokenKind::QuotedId(c, _) => Arc::clone(c),
4218 TokenKind::String(c) => Arc::<str>::from(c.as_str()),
4219 k if starts_post_dot_identifier(k) => Arc::<str>::from(kw_to_str(k)),
4220 _ => {
4221 return Err(ParseError::unexpected_at(
4222 format!("expected column name after '.', got {:?}", col_tok.kind),
4223 Some(&col_tok),
4224 ));
4225 }
4226 };
4227 let span = start.merge(col_tok.span);
4228 self.pos = self.pos.saturating_add(4);
4229 return self.finish_expr(
4230 Expr::Column(ColumnRef::schema_qualified(name, mid_name, col_name), span),
4231 2,
4232 false,
4233 false,
4234 );
4235 }
4236 let span = start.merge(mid_tok.span);
4237 self.pos = self.pos.saturating_add(2);
4238 return self.finish_expr(
4239 Expr::Column(ColumnRef::qualified(name, mid_name), span),
4240 2,
4241 false,
4242 false,
4243 );
4244 }
4245 Ok(ParsedExpr::leaf(Expr::Column(ColumnRef::bare(name), start)))
4246 }
4247
4248 fn postfix_bp(&self) -> Option<u8> {
4251 match self.peek_kind() {
4252 TokenKind::KwCollate => Some(bp::COLLATE),
4253 TokenKind::KwIsnull | TokenKind::KwNotnull => Some(bp::EQUALITY.0),
4254 TokenKind::KwNot => {
4255 if let Some(next) = self.tokens.get(self.pos + 1)
4256 && matches!(next.kind, TokenKind::KwNull)
4257 {
4258 return Some(bp::EQUALITY.0);
4259 }
4260 None
4261 }
4262 _ => None,
4263 }
4264 }
4265
4266 fn parse_postfix(&mut self, lhs: ParsedExpr) -> Result<ParsedExpr, ParseError> {
4267 let tok = self.advance_token();
4268 match &tok.kind {
4269 TokenKind::KwCollate => {
4270 let collation = match self.parse_identifier() {
4271 Ok(s) => s,
4272 Err(_) => {
4273 return Err(self.err_here("expected collation name after COLLATE"));
4274 }
4275 };
4276 let name_span = self.tokens[self.pos.saturating_sub(1)].span;
4277 let span = lhs.expr.span().merge(name_span);
4278 let height = lhs.height;
4279 let is_constant = lhs.is_constant;
4280 let has_function = lhs.has_function;
4281 self.checked_expr(
4282 Expr::Collate {
4283 expr: Box::new(lhs.expr),
4284 collation,
4285 span,
4286 },
4287 height,
4288 is_constant,
4289 has_function,
4290 )
4291 }
4292 TokenKind::KwIsnull => {
4293 let span = lhs.expr.span().merge(tok.span);
4294 let height = lhs.height;
4295 let is_constant = lhs.is_constant;
4296 let has_function = lhs.has_function;
4297 self.checked_expr(
4298 Expr::IsNull {
4299 expr: Box::new(lhs.expr),
4300 not: false,
4301 span,
4302 },
4303 height,
4304 is_constant,
4305 has_function,
4306 )
4307 }
4308 TokenKind::KwNotnull => {
4309 let span = lhs.expr.span().merge(tok.span);
4310 let height = lhs.height;
4311 let is_constant = lhs.is_constant;
4312 let has_function = lhs.has_function;
4313 self.checked_expr(
4314 Expr::IsNull {
4315 expr: Box::new(lhs.expr),
4316 not: true,
4317 span,
4318 },
4319 height,
4320 is_constant,
4321 has_function,
4322 )
4323 }
4324 TokenKind::KwNot => {
4325 let null_tok = self.advance_token(); let span = lhs.expr.span().merge(null_tok.span);
4327 let height = lhs.height;
4328 let is_constant = lhs.is_constant;
4329 let has_function = lhs.has_function;
4330 self.checked_expr(
4331 Expr::IsNull {
4332 expr: Box::new(lhs.expr),
4333 not: true,
4334 span,
4335 },
4336 height,
4337 is_constant,
4338 has_function,
4339 )
4340 }
4341 other => Err(ParseError::unexpected_at(
4342 format!("unexpected postfix token: {other:?}"),
4343 Some(&tok),
4344 )),
4345 }
4346 }
4347
4348 fn infix_bp(&self) -> Option<(u8, u8)> {
4351 match self.peek_kind() {
4352 TokenKind::KwOr => Some(bp::OR),
4353 TokenKind::KwAnd => Some(bp::AND),
4354
4355 TokenKind::Eq
4356 | TokenKind::EqEq
4357 | TokenKind::Ne
4358 | TokenKind::LtGt
4359 | TokenKind::KwIs
4360 | TokenKind::KwLike
4361 | TokenKind::KwGlob
4362 | TokenKind::KwMatch
4363 | TokenKind::KwRegexp
4364 | TokenKind::KwBetween
4365 | TokenKind::KwIn => Some(bp::EQUALITY),
4366
4367 TokenKind::KwNot => {
4369 let next = self.tokens.get(self.pos + 1).map(|t| &t.kind);
4370 match next {
4371 Some(
4372 TokenKind::KwLike
4373 | TokenKind::KwGlob
4374 | TokenKind::KwMatch
4375 | TokenKind::KwRegexp
4376 | TokenKind::KwBetween
4377 | TokenKind::KwIn,
4378 ) => Some(bp::EQUALITY),
4379 _ => None,
4380 }
4381 }
4382
4383 TokenKind::Lt | TokenKind::Le | TokenKind::Gt | TokenKind::Ge => Some(bp::COMPARISON),
4384
4385 TokenKind::Ampersand
4386 | TokenKind::Pipe
4387 | TokenKind::ShiftLeft
4388 | TokenKind::ShiftRight => Some(bp::BITWISE),
4389
4390 TokenKind::Plus | TokenKind::Minus => Some(bp::ADD),
4391 TokenKind::Star | TokenKind::Slash | TokenKind::Percent => Some(bp::MUL),
4392 TokenKind::Concat => Some(bp::CONCAT),
4393 TokenKind::Arrow | TokenKind::DoubleArrow => Some(bp::JSON),
4394
4395 _ => None,
4396 }
4397 }
4398
4399 #[cfg(test)]
4400 #[allow(clippy::too_many_lines)]
4401 fn parse_infix(&mut self, lhs: ParsedExpr, r_bp: u8) -> Result<ParsedExpr, ParseError> {
4402 let tok = self.advance_token();
4403 match &tok.kind {
4404 TokenKind::Plus => self.make_binop(lhs, BinaryOp::Add, r_bp),
4406 TokenKind::Minus => self.make_binop(lhs, BinaryOp::Subtract, r_bp),
4407 TokenKind::Star => self.make_binop(lhs, BinaryOp::Multiply, r_bp),
4408 TokenKind::Slash => self.make_binop(lhs, BinaryOp::Divide, r_bp),
4409 TokenKind::Percent => self.make_binop(lhs, BinaryOp::Modulo, r_bp),
4410 TokenKind::Concat => self.make_binop(lhs, BinaryOp::Concat, r_bp),
4411 TokenKind::Eq | TokenKind::EqEq => self.make_binop(lhs, BinaryOp::Eq, r_bp),
4412 TokenKind::Ne | TokenKind::LtGt => self.make_binop(lhs, BinaryOp::Ne, r_bp),
4413 TokenKind::Lt => self.make_binop(lhs, BinaryOp::Lt, r_bp),
4414 TokenKind::Le => self.make_binop(lhs, BinaryOp::Le, r_bp),
4415 TokenKind::Gt => self.make_binop(lhs, BinaryOp::Gt, r_bp),
4416 TokenKind::Ge => self.make_binop(lhs, BinaryOp::Ge, r_bp),
4417 TokenKind::Ampersand => self.make_binop(lhs, BinaryOp::BitAnd, r_bp),
4418 TokenKind::Pipe => self.make_binop(lhs, BinaryOp::BitOr, r_bp),
4419 TokenKind::ShiftLeft => self.make_binop(lhs, BinaryOp::ShiftLeft, r_bp),
4420 TokenKind::ShiftRight => self.make_binop(lhs, BinaryOp::ShiftRight, r_bp),
4421 TokenKind::KwOr => self.make_binop(lhs, BinaryOp::Or, r_bp),
4422 TokenKind::KwAnd => self.make_binop(lhs, BinaryOp::And, r_bp),
4423
4424 TokenKind::KwIs => {
4426 let not = self.eat_kind(&TokenKind::KwNot);
4427 if self.eat_kind(&TokenKind::KwDistinct) {
4428 self.expect_kind(&TokenKind::KwFrom)?;
4429 let rhs = self.parse_expr_bp(r_bp)?;
4430 let span = lhs.expr.span().merge(rhs.expr.span());
4431 let height = lhs.height.max(rhs.height);
4432 let is_constant = lhs.is_constant && rhs.is_constant;
4433 let has_function = lhs.has_function || rhs.has_function;
4434 let op = if not { BinaryOp::Is } else { BinaryOp::IsNot };
4437 return self.checked_expr(
4438 Expr::BinaryOp {
4439 left: Box::new(lhs.expr),
4440 op,
4441 right: Box::new(rhs.expr),
4442 span,
4443 },
4444 height,
4445 is_constant,
4446 has_function,
4447 );
4448 }
4449 let rhs = self.parse_expr_bp(r_bp)?;
4450 let span = lhs.expr.span().merge(rhs.expr.span());
4451 if matches!(&rhs.expr, Expr::Literal(Literal::Null, _)) {
4459 let height = lhs.height;
4460 let is_constant = lhs.is_constant;
4461 let has_function = lhs.has_function;
4462 return self.checked_expr(
4463 Expr::IsNull {
4464 expr: Box::new(lhs.expr),
4465 not,
4466 span,
4467 },
4468 height,
4469 is_constant,
4470 has_function,
4471 );
4472 }
4473 let op = if not { BinaryOp::IsNot } else { BinaryOp::Is };
4474 let height = lhs.height.max(rhs.height);
4475 let is_constant = lhs.is_constant && rhs.is_constant;
4476 let has_function = lhs.has_function || rhs.has_function;
4477 self.checked_expr(
4478 Expr::BinaryOp {
4479 left: Box::new(lhs.expr),
4480 op,
4481 right: Box::new(rhs.expr),
4482 span,
4483 },
4484 height,
4485 is_constant,
4486 has_function,
4487 )
4488 }
4489
4490 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, false),
4492 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, false),
4493 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, false),
4494 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, false),
4495
4496 TokenKind::KwBetween => self.parse_between(lhs, false),
4498
4499 TokenKind::KwIn => self.parse_in(lhs, false),
4501
4502 TokenKind::Arrow => {
4504 let rhs = self.parse_expr_bp(r_bp)?;
4505 let span = lhs.expr.span().merge(rhs.expr.span());
4506 let height = lhs.height.max(rhs.height);
4507 let is_constant = false;
4508 let has_function = true;
4509 self.checked_expr(
4510 Expr::JsonAccess {
4511 expr: Box::new(lhs.expr),
4512 path: Box::new(rhs.expr),
4513 arrow: JsonArrow::Arrow,
4514 span,
4515 },
4516 height,
4517 is_constant,
4518 has_function,
4519 )
4520 }
4521 TokenKind::DoubleArrow => {
4522 let rhs = self.parse_expr_bp(r_bp)?;
4523 let span = lhs.expr.span().merge(rhs.expr.span());
4524 let height = lhs.height.max(rhs.height);
4525 let is_constant = false;
4526 let has_function = true;
4527 self.checked_expr(
4528 Expr::JsonAccess {
4529 expr: Box::new(lhs.expr),
4530 path: Box::new(rhs.expr),
4531 arrow: JsonArrow::DoubleArrow,
4532 span,
4533 },
4534 height,
4535 is_constant,
4536 has_function,
4537 )
4538 }
4539
4540 TokenKind::KwNot => {
4542 let next = self.advance_token();
4543 match &next.kind {
4544 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, true),
4545 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, true),
4546 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, true),
4547 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, true),
4548 TokenKind::KwBetween => self.parse_between(lhs, true),
4549 TokenKind::KwIn => self.parse_in(lhs, true),
4550 _ => Err(ParseError::unexpected_at(
4551 format!(
4552 "expected LIKE/GLOB/MATCH/REGEXP/BETWEEN/IN \
4553 after NOT, got {:?}",
4554 next.kind
4555 ),
4556 Some(&next),
4557 )),
4558 }
4559 }
4560
4561 other => Err(ParseError::unexpected_at(
4562 format!("unexpected infix token: {other:?}"),
4563 Some(&tok),
4564 )),
4565 }
4566 }
4567
4568 #[cfg(test)]
4569 fn make_binop(
4570 &mut self,
4571 lhs: ParsedExpr,
4572 op: BinaryOp,
4573 r_bp: u8,
4574 ) -> Result<ParsedExpr, ParseError> {
4575 let rhs = self.parse_expr_bp(r_bp)?;
4576 let span = lhs.expr.span().merge(rhs.expr.span());
4577 let height = lhs.height.max(rhs.height);
4578 let is_constant = lhs.is_constant && rhs.is_constant;
4579 let has_function = lhs.has_function || rhs.has_function;
4580 self.checked_expr(
4581 Expr::BinaryOp {
4582 left: Box::new(lhs.expr),
4583 op,
4584 right: Box::new(rhs.expr),
4585 span,
4586 },
4587 height,
4588 is_constant,
4589 has_function,
4590 )
4591 }
4592
4593 #[cfg(test)]
4596 fn parse_like(
4597 &mut self,
4598 lhs: ParsedExpr,
4599 op: LikeOp,
4600 not: bool,
4601 ) -> Result<ParsedExpr, ParseError> {
4602 let pattern = self.parse_expr_bp(bp::EQUALITY.1)?;
4603 let escape = if self.eat_kind(&TokenKind::KwEscape) {
4604 Some(self.parse_expr_bp(bp::EQUALITY.1)?)
4607 } else {
4608 None
4609 };
4610 let end = escape
4611 .as_ref()
4612 .map_or_else(|| pattern.expr.span(), |e| e.expr.span());
4613 let span = lhs.expr.span().merge(end);
4614 let height = escape.as_ref().map_or_else(
4615 || lhs.height.max(pattern.height),
4616 |parsed| lhs.height.max(pattern.height).max(parsed.height),
4617 );
4618 let parsed = self.checked_expr(
4619 Expr::Like {
4620 expr: Box::new(lhs.expr),
4621 pattern: Box::new(pattern.expr),
4622 escape: escape.map(|parsed| Box::new(parsed.expr)),
4623 op,
4624 not,
4625 span,
4626 },
4627 height,
4628 false,
4629 true,
4630 )?;
4631 if not {
4632 self.add_cached_parent(parsed)
4633 } else {
4634 Ok(parsed)
4635 }
4636 }
4637
4638 #[cfg(test)]
4639 fn parse_between(&mut self, lhs: ParsedExpr, not: bool) -> Result<ParsedExpr, ParseError> {
4640 let low = self.parse_expr_bp(bp::NOT_PREFIX)?;
4642 if !self.eat_kind(&TokenKind::KwAnd) {
4643 return Err(self.err_here("expected AND in BETWEEN expression"));
4644 }
4645 let high = self.parse_expr_bp(bp::EQUALITY.1)?;
4646 let span = lhs.expr.span().merge(high.expr.span());
4647 let height = lhs.height.max(low.height).max(high.height);
4648 let is_constant = lhs.is_constant && low.is_constant && high.is_constant;
4649 let has_function = lhs.has_function || low.has_function || high.has_function;
4650 let parsed = self.checked_expr(
4651 Expr::Between {
4652 expr: Box::new(lhs.expr),
4653 low: Box::new(low.expr),
4654 high: Box::new(high.expr),
4655 not,
4656 span,
4657 },
4658 height,
4659 is_constant,
4660 has_function,
4661 )?;
4662 if not {
4663 self.add_cached_parent(parsed)
4664 } else {
4665 Ok(parsed)
4666 }
4667 }
4668
4669 #[cfg(test)]
4670 fn parse_in(&mut self, lhs: ParsedExpr, not: bool) -> Result<ParsedExpr, ParseError> {
4671 let start = lhs.expr.span();
4672
4673 if !self.at_kind(&TokenKind::LeftParen) {
4675 let table = self.parse_qualified_name()?;
4676 let end = self.tokens[self.pos.saturating_sub(1)].span;
4677 let span = start.merge(end);
4678 let height = lhs.height;
4679 let has_function = lhs.has_function;
4680 let parsed = self.checked_expr(
4681 Expr::In {
4682 expr: Box::new(lhs.expr),
4683 set: InSet::Table(table),
4684 not,
4685 span,
4686 },
4687 height,
4688 false,
4689 has_function,
4690 )?;
4691 return if not {
4692 self.add_cached_parent(parsed)
4693 } else {
4694 Ok(parsed)
4695 };
4696 }
4697
4698 self.expect_kind(&TokenKind::LeftParen)?;
4699
4700 if matches!(
4701 self.peek_kind(),
4702 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
4703 ) {
4704 let subquery = self.parse_subquery_minimal()?;
4705 let end = self.expect_kind(&TokenKind::RightParen)?;
4706 let span = start.merge(end);
4707 let height = lhs.height.max(subquery.height);
4708 let has_function = lhs.has_function;
4709 let parsed = self.checked_expr(
4710 Expr::In {
4711 expr: Box::new(lhs.expr),
4712 set: InSet::Subquery(Box::new(subquery.value)),
4713 not,
4714 span,
4715 },
4716 height,
4717 false,
4718 has_function,
4719 )?;
4720 return if not {
4721 self.add_cached_parent(parsed)
4722 } else {
4723 Ok(parsed)
4724 };
4725 }
4726
4727 let mut parsed_items = Vec::new();
4728 if !self.at_kind(&TokenKind::RightParen) {
4729 let item = self.parse_expr_bp(0)?;
4730 parsed_items.push(item);
4731 while self.eat_kind(&TokenKind::Comma) {
4732 let item = self.parse_expr_bp(0)?;
4733 parsed_items.push(item);
4734 }
4735 }
4736 let end = self.expect_kind(&TokenKind::RightParen)?;
4737 if let Some(message) = vector_in_list_arity_error(&lhs.expr, &parsed_items) {
4738 return Err(self.err_semantic(message));
4741 }
4742 let span = start.merge(end);
4743 let item_height = parsed_items
4744 .iter()
4745 .map(|item| item.height)
4746 .max()
4747 .unwrap_or(0);
4748 let items_are_constant = parsed_items.iter().all(|item| item.is_constant);
4749 let item_has_function = parsed_items.iter().any(|item| item.has_function);
4750 let singleton_constant = matches!(parsed_items.as_slice(), [item] if item.is_constant)
4751 && lhs.root != CachedRoot::Vector;
4752 let singleton_subquery =
4753 matches!(parsed_items.as_slice(), [item] if item.root == CachedRoot::ScalarSubquery);
4754 let exprs = parsed_items.into_iter().map(|parsed| parsed.expr).collect();
4755 let lhs_height = lhs.height;
4756 let lhs_is_constant = lhs.is_constant;
4757 let lhs_has_function = lhs.has_function;
4758 let expr = Expr::In {
4759 expr: Box::new(lhs.expr),
4760 set: InSet::List(exprs),
4761 not,
4762 span,
4763 };
4764
4765 if item_height == 0 {
4766 if lhs_has_function {
4767 return self.finish_expr(expr, lhs_height.saturating_add(1), false, true);
4768 }
4769 return self.finish_expr(expr, 1, true, false);
4770 }
4771
4772 let cached_child_height = if singleton_constant {
4773 lhs_height.max(item_height.saturating_add(1))
4774 } else if singleton_subquery {
4775 lhs_height.max(item_height.saturating_sub(1))
4776 } else {
4777 lhs_height.max(item_height)
4778 };
4779 let parsed = self.checked_expr(
4780 expr,
4781 cached_child_height,
4782 lhs_is_constant && items_are_constant,
4783 lhs_has_function || item_has_function,
4784 )?;
4785 if not {
4786 self.add_cached_parent(parsed)
4787 } else {
4788 Ok(parsed)
4789 }
4790 }
4791
4792 #[cfg(test)]
4793 fn parse_case_expr(&mut self, start: Span) -> Result<ParsedExpr, ParseError> {
4794 let operand = if matches!(self.peek_kind(), TokenKind::KwWhen) {
4795 None
4796 } else {
4797 Some(self.parse_expr_bp(0)?)
4798 };
4799
4800 let mut whens = Vec::new();
4801 while self.eat_kind(&TokenKind::KwWhen) {
4802 let condition = self.parse_expr_bp(0)?;
4803 if !self.eat_kind(&TokenKind::KwThen) {
4804 return Err(self.err_here("expected THEN in CASE expression"));
4805 }
4806 let result = self.parse_expr_bp(0)?;
4807 whens.push((condition, result));
4808 }
4809 if whens.is_empty() {
4810 return Err(self.err_here("CASE requires at least one WHEN clause"));
4811 }
4812
4813 let else_expr = if self.eat_kind(&TokenKind::KwElse) {
4814 Some(self.parse_expr_bp(0)?)
4815 } else {
4816 None
4817 };
4818
4819 if !self.eat_kind(&TokenKind::KwEnd) {
4820 return Err(self.err_here("expected END for CASE expression"));
4821 }
4822 let end = self.tokens[self.pos.saturating_sub(1)].span;
4823 let span = start.merge(end);
4824 let mut height = operand.as_ref().map_or(0, |parsed| parsed.height);
4825 let mut is_constant = operand.as_ref().is_none_or(|parsed| parsed.is_constant);
4826 let mut has_function = operand.as_ref().is_some_and(|parsed| parsed.has_function);
4827 for (condition, result) in &whens {
4828 height = height.max(condition.height).max(result.height);
4829 is_constant &= condition.is_constant && result.is_constant;
4830 has_function |= condition.has_function || result.has_function;
4831 }
4832 if let Some(parsed) = &else_expr {
4833 height = height.max(parsed.height);
4834 is_constant &= parsed.is_constant;
4835 has_function |= parsed.has_function;
4836 }
4837 self.checked_expr(
4838 Expr::Case {
4839 operand: operand.map(|parsed| Box::new(parsed.expr)),
4840 whens: whens
4841 .into_iter()
4842 .map(|(condition, result)| (condition.expr, result.expr))
4843 .collect(),
4844 else_expr: else_expr.map(|parsed| Box::new(parsed.expr)),
4845 span,
4846 },
4847 height,
4848 is_constant,
4849 has_function,
4850 )
4851 }
4852
4853 #[cfg(test)]
4854 fn parse_function_call(&mut self, name: String, start: Span) -> Result<ParsedExpr, ParseError> {
4855 self.expect_kind(&TokenKind::LeftParen)?;
4856
4857 let (args, distinct, height) = if matches!(self.peek_kind(), TokenKind::Star) {
4858 self.advance_token();
4859 if name.eq_ignore_ascii_case("count") {
4862 (FunctionArgs::Star, false, 0)
4863 } else {
4864 (FunctionArgs::List(Vec::new()), false, 0)
4865 }
4866 } else {
4867 let distinct = self.eat_kind(&TokenKind::KwDistinct);
4868 let (args, height) = if matches!(self.peek_kind(), TokenKind::RightParen) {
4869 if distinct {
4870 return Err(self.err_here("DISTINCT requires at least one argument"));
4871 }
4872 (FunctionArgs::List(Vec::new()), 0)
4873 } else {
4874 let first = self.parse_expr_bp(0)?;
4875 let mut height = first.height;
4876 let mut list = vec![first.expr];
4877 while self.eat_kind(&TokenKind::Comma) {
4878 let parsed = self.parse_expr_bp(0)?;
4879 height = height.max(parsed.height);
4880 list.push(parsed.expr);
4881 }
4882 (FunctionArgs::List(list), height)
4883 };
4884 (args, distinct, height)
4885 };
4886
4887 let order_by =
4889 if matches!(&args, FunctionArgs::List(_)) && self.eat_kind(&TokenKind::KwOrder) {
4890 self.expect_kind(&TokenKind::KwBy)?;
4891 self.parse_comma_sep(Self::parse_ordering_term)?
4892 } else {
4893 vec![]
4894 };
4895
4896 let mut end = self.expect_kind(&TokenKind::RightParen)?;
4897 let filter = if matches!(self.peek_kind(), TokenKind::KwFilter)
4900 && self
4901 .tokens
4902 .get(self.pos + 1)
4903 .is_some_and(|t| t.kind == TokenKind::LeftParen)
4904 {
4905 self.advance_token(); self.expect_kind(&TokenKind::LeftParen)?;
4907 self.expect_kind(&TokenKind::KwWhere)?;
4908 let predicate = self.parse_expr()?;
4909 let filter_end = self.expect_kind(&TokenKind::RightParen)?;
4910 end = end.merge(filter_end);
4911 Some(Box::new(predicate))
4912 } else {
4913 None
4914 };
4915 let over = if matches!(self.peek_kind(), TokenKind::KwOver)
4918 && self.tokens.get(self.pos + 1).is_some_and(|t| {
4919 matches!(t.kind, TokenKind::LeftParen) || starts_bare_window_name(&t.kind)
4920 }) {
4921 self.advance_token(); if self.eat_kind(&TokenKind::LeftParen) {
4923 let spec = self.parse_window_spec()?;
4924 let over_end = self.expect_kind(&TokenKind::RightParen)?;
4925 end = end.merge(over_end);
4926 Some(spec)
4927 } else {
4928 let base_window = self.parse_window_name()?;
4929 let base_span = self.tokens[self.pos.saturating_sub(1)].span;
4930 end = end.merge(base_span);
4931 Some(WindowSpec {
4932 window_ref: Some(WindowReference::Direct(base_window)),
4933 partition_by: Vec::new(),
4934 order_by: Vec::new(),
4935 frame: None,
4936 })
4937 }
4938 } else {
4939 None
4940 };
4941
4942 let span = start.merge(end);
4943 self.checked_expr(
4944 Expr::FunctionCall {
4945 name,
4946 args,
4947 distinct,
4948 order_by,
4949 filter,
4950 over,
4951 span,
4952 },
4953 height,
4954 false,
4955 true,
4956 )
4957 }
4958
4959 fn parse_raise_args(&mut self) -> Result<(RaiseAction, Option<String>), ParseError> {
4960 let action_tok = self.advance_token();
4961 let action = match &action_tok.kind {
4962 TokenKind::KwIgnore => RaiseAction::Ignore,
4963 TokenKind::KwRollback => RaiseAction::Rollback,
4964 TokenKind::KwAbort => RaiseAction::Abort,
4965 TokenKind::KwFail => RaiseAction::Fail,
4966 _ => {
4967 return Err(ParseError::unexpected_at(
4968 "expected IGNORE, ROLLBACK, ABORT, or FAIL in RAISE",
4969 Some(&action_tok),
4970 ));
4971 }
4972 };
4973 if matches!(action, RaiseAction::Ignore) {
4974 return Ok((action, None));
4975 }
4976 self.expect_kind(&TokenKind::Comma)?;
4977 let msg_tok = self.advance_token();
4978 let message = match &msg_tok.kind {
4979 TokenKind::String(s) => s.clone(),
4980 _ => {
4981 return Err(ParseError::unexpected_at(
4982 "expected string message in RAISE",
4983 Some(&msg_tok),
4984 ));
4985 }
4986 };
4987 Ok((action, Some(message)))
4988 }
4989
4990 fn parse_cast_type_name(&mut self) -> Result<TypeName, ParseError> {
4999 if matches!(self.peek_kind(), TokenKind::RightParen) {
5000 return Ok(TypeName {
5001 name: String::new(),
5002 arg1: None,
5003 arg2: None,
5004 });
5005 }
5006 self.parse_type_name()
5007 }
5008
5009 fn parse_type_name(&mut self) -> Result<TypeName, ParseError> {
5010 let mut parts = Vec::new();
5011 loop {
5012 match self.peek_kind() {
5013 TokenKind::Id(_) | TokenKind::QuotedId(_, _) => {
5014 let tok = self.advance_token();
5015 if let TokenKind::Id(s) | TokenKind::QuotedId(s, _) = &tok.kind {
5016 parts.push(s.to_string());
5017 } else {
5018 unreachable!();
5019 }
5020 }
5021 k if is_nonreserved_kw(k) => {
5022 let tok = self.advance_token();
5023 parts.push(kw_to_str(&tok.kind));
5024 }
5025 _ => break,
5026 }
5027 }
5028 if parts.is_empty() {
5029 return Err(self.err_here("expected type name"));
5030 }
5031 let name = parts.join(" ");
5032
5033 let (arg1, arg2) = if self.eat_kind(&TokenKind::LeftParen) {
5034 let a1 = self.parse_type_arg()?;
5035 let a2 = if self.eat_kind(&TokenKind::Comma) {
5036 Some(self.parse_type_arg()?)
5037 } else {
5038 None
5039 };
5040 self.expect_kind(&TokenKind::RightParen)?;
5041 (Some(a1), a2)
5042 } else {
5043 (None, None)
5044 };
5045
5046 Ok(TypeName { name, arg1, arg2 })
5047 }
5048
5049 fn parse_type_arg(&mut self) -> Result<String, ParseError> {
5050 let tok = self.advance_token();
5051 match &tok.kind {
5052 TokenKind::Integer(i) => Ok(i.to_string()),
5053 TokenKind::Float(f) => Ok(f.to_string()),
5054 TokenKind::Minus => {
5055 let next = self.advance_token();
5056 match &next.kind {
5057 TokenKind::Integer(i) => Ok(format!("-{i}")),
5058 TokenKind::OversizedInt(s) => Ok(format!("-{s}")),
5059 TokenKind::Float(f) => Ok(format!("-{f}")),
5060 _ => Err(ParseError::unexpected_at(
5061 "expected number in type argument",
5062 Some(&next),
5063 )),
5064 }
5065 }
5066 TokenKind::Plus => {
5067 let next = self.advance_token();
5068 match &next.kind {
5069 TokenKind::Integer(i) => Ok(format!("+{i}")),
5070 TokenKind::OversizedInt(s) => Ok(format!("+{s}")),
5071 TokenKind::Float(f) => Ok(format!("+{f}")),
5072 _ => Err(ParseError::unexpected_at(
5073 "expected number in type argument",
5074 Some(&next),
5075 )),
5076 }
5077 }
5078 TokenKind::OversizedInt(s) => Ok(s.clone()),
5079 TokenKind::Id(s) | TokenKind::QuotedId(s, _) => Ok(s.to_string()),
5080 _ => Err(ParseError::unexpected_at(
5081 "expected type argument",
5082 Some(&tok),
5083 )),
5084 }
5085 }
5086
5087 #[cfg(test)]
5089 fn parse_subquery_minimal(&mut self) -> Result<HeightTracked<SelectStatement>, ParseError> {
5090 let with = if self.at_kind(&TokenKind::KwWith) {
5091 Some(ParseMachine::for_with(self).run_with()?)
5092 } else {
5093 None
5094 };
5095 ParseMachine::for_select(self, with).run_select()
5096 }
5097}
5098
5099pub fn parse_expr(sql: &str) -> Result<Expr, ParseError> {
5101 let mut parser = Parser::from_sql(sql);
5102 let expr = parser.parse_expr()?;
5103 let _ = parser.eat(&TokenKind::Semicolon);
5104 if !parser.at_eof() {
5105 return Err(parser.err_here(format!(
5106 "unexpected token after expression: {:?}",
5107 parser.peek_kind()
5108 )));
5109 }
5110 Ok(expr)
5111}
5112
5113#[cfg(test)]
5114mod tests {
5115 use super::*;
5116 use crate::parser::ParseErrorKind;
5117 use fsqlite_ast::{BoundCollation, SelectCore, TableOrSubquery};
5118 use fsqlite_types::{SqliteValue, TypeAffinity};
5119
5120 fn parse(sql: &str) -> Expr {
5121 match parse_expr(sql) {
5122 Ok(expr) => expr,
5123 Err(err) => unreachable!("parse error for `{sql}`: {err}"),
5124 }
5125 }
5126
5127 fn repeated_infix_expression(term_count: usize, operator: &str) -> String {
5128 std::iter::repeat_n("1", term_count)
5129 .collect::<Vec<_>>()
5130 .join(operator)
5131 }
5132
5133 fn assert_expression_depth_error(sql: &str) {
5134 let error = parse_expr(sql).expect_err("expression height 1001 must fail closed");
5135 assert_eq!(
5136 error.kind,
5137 ParseErrorKind::ExpressionTooDeep {
5138 max: MAX_PARSE_DEPTH
5139 }
5140 );
5141 assert_eq!(
5142 error.message,
5143 format!(
5144 "Expression tree is too large (maximum depth {})",
5145 MAX_PARSE_DEPTH
5146 )
5147 );
5148 assert!(error.is_expression_too_deep());
5149 }
5150
5151 fn right_deep_binary_expression(height: usize) -> String {
5152 format!("{}1{}", "1 + (".repeat(height - 1), ")".repeat(height - 1))
5153 }
5154
5155 fn single_arg_function_expression(height: usize) -> String {
5156 format!("{}1{}", "abs(".repeat(height - 1), ")".repeat(height - 1))
5157 }
5158
5159 fn scalar_subquery_expression(height: usize) -> String {
5160 format!(
5161 "{}1{}",
5162 "(SELECT ".repeat(height - 1),
5163 ")".repeat(height - 1)
5164 )
5165 }
5166
5167 fn on_one_mib_stack<T: Send + 'static>(task: impl FnOnce() -> T + Send + 'static) -> T {
5168 std::thread::Builder::new()
5169 .stack_size(1024 * 1024)
5170 .spawn(task)
5171 .expect("1 MiB parser thread must spawn")
5172 .join()
5173 .expect("parser task must not overflow or panic")
5174 }
5175
5176 fn parsed_select_height(sql: &str) -> u32 {
5177 let mut parser = Parser::from_sql(sql);
5178 let select = parser
5179 .parse_subquery_minimal()
5180 .expect("SELECT fixture must parse");
5181 assert_eq!(
5182 select.height,
5183 normalized_ast_select_height(&select.value),
5184 "tracked SELECT height diverged from the normalized AST test oracle"
5185 );
5186 select.height
5187 }
5188
5189 fn parsed_expr_height(sql: &str) -> u32 {
5190 let mut parser = Parser::from_sql(sql);
5191 let parsed = parser
5192 .parse_expr_tracked()
5193 .expect("expression fixture must parse");
5194 assert!(
5195 matches!(parser.peek_kind(), TokenKind::Eof | TokenKind::Semicolon),
5196 "expression fixture left an unparsed token: {sql}"
5197 );
5198 assert_eq!(
5199 parsed.height,
5200 normalized_ast_expr_height(&parsed.expr),
5201 "tracked expression height diverged from the normalized AST test oracle: {sql}"
5202 );
5203 parsed.height
5204 }
5205
5206 #[test]
5207 fn bound_outer_value_has_constant_leaf_facts() {
5208 let expr = Expr::BoundOuterValue {
5209 value: SqliteValue::Integer(42),
5210 collation: BoundCollation::Named("NOCASE".to_owned()),
5211 affinity: Some(TypeAffinity::Integer),
5212 span: Span::ZERO,
5213 };
5214
5215 let parsed = ParsedExpr::leaf(expr.clone());
5216 assert_eq!(parsed.height, 1);
5217 assert!(parsed.is_constant);
5218 assert!(!parsed.has_function);
5219
5220 let facts = cached_facts_from_tasks(vec![CachedHeightTask::Expr(&expr)]);
5221 assert_eq!(facts.height, 1);
5222 assert!(facts.is_constant);
5223 assert!(!facts.has_function);
5224 }
5225
5226 fn mixed_deep_expression(height: usize) -> String {
5227 let mut prefix = String::new();
5228 let mut closing_count = 0;
5229 for index in 1..height {
5230 if index % 7 == 0 {
5231 prefix.push('(');
5232 closing_count += 1;
5233 }
5234 match index % 4 {
5235 0 => prefix.push('~'),
5236 1 => {
5237 prefix.push_str("abs(");
5238 closing_count += 1;
5239 }
5240 2 => {
5241 prefix.push_str("(SELECT ");
5242 closing_count += 1;
5243 }
5244 _ => {
5245 prefix.push_str("1 + (");
5246 closing_count += 1;
5247 }
5248 }
5249 }
5250 prefix.push('1');
5251 prefix.push_str(&")".repeat(closing_count));
5252 prefix
5253 }
5254
5255 fn assert_machine_matches_recursive_oracle(sql: &str) {
5256 let mut machine = Parser::from_sql(sql);
5257 let machine_result = machine.parse_expr_tracked();
5258 let machine_pos = machine.pos;
5259 let machine_tail = machine.peek_kind().clone();
5260
5261 let mut oracle = Parser::from_sql(sql);
5262 let oracle_result = oracle.parse_expr_bp(0);
5263 let oracle_pos = oracle.pos;
5264 let oracle_tail = oracle.peek_kind().clone();
5265
5266 assert_eq!(
5267 machine_pos, oracle_pos,
5268 "parser tail position differs: {sql}"
5269 );
5270 assert_eq!(
5271 machine_tail, oracle_tail,
5272 "parser tail token differs: {sql}"
5273 );
5274 match (machine_result, oracle_result) {
5275 (Ok(machine), Ok(oracle)) => {
5276 assert_eq!(machine.expr, oracle.expr, "AST or spans differ: {sql}");
5277 assert_eq!(machine.height, oracle.height, "height differs: {sql}");
5278 assert_eq!(
5279 machine.is_constant, oracle.is_constant,
5280 "constant fact differs: {sql}"
5281 );
5282 assert_eq!(
5283 machine.has_function, oracle.has_function,
5284 "function fact differs: {sql}"
5285 );
5286 assert_eq!(machine.root, oracle.root, "root fact differs: {sql}");
5287 }
5288 (Err(machine), Err(oracle)) => {
5289 assert_eq!(machine, oracle, "diagnostic differs: {sql}");
5290 }
5291 (Ok(_), Err(_)) | (Err(_), Ok(_)) => {
5292 panic!("machine/oracle result class differs for `{sql}`");
5293 }
5294 }
5295 }
5296
5297 fn assert_select_machine_matches_recursive_oracle(sql: &str) {
5298 let mut machine = Parser::from_sql(sql);
5299 let machine_result = machine.parse_select_stmt_tracked(None);
5300 let machine_pos = machine.pos;
5301 let machine_tail = machine.peek_kind().clone();
5302
5303 let mut oracle = Parser::from_sql(sql);
5304 let oracle_result = oracle.parse_select_stmt_inner_tracked(None);
5305 let oracle_pos = oracle.pos;
5306 let oracle_tail = oracle.peek_kind().clone();
5307
5308 assert_eq!(
5309 machine_pos, oracle_pos,
5310 "SELECT parser tail position differs: {sql}"
5311 );
5312 assert_eq!(
5313 machine_tail, oracle_tail,
5314 "SELECT parser tail token differs: {sql}"
5315 );
5316 match (machine_result, oracle_result) {
5317 (Ok(machine), Ok(oracle)) => {
5318 assert_eq!(machine.value, oracle.value, "SELECT AST differs: {sql}");
5319 assert_eq!(
5320 machine.height, oracle.height,
5321 "SELECT height differs: {sql}"
5322 );
5323 }
5324 (Err(machine), Err(oracle)) => {
5325 assert_eq!(machine, oracle, "SELECT diagnostic differs: {sql}");
5326 }
5327 (Ok(_), Err(_)) | (Err(_), Ok(_)) => {
5328 panic!("SELECT machine/oracle result class differs for `{sql}`");
5329 }
5330 }
5331 }
5332
5333 fn bitnot_depth(mut expr: &Expr) -> usize {
5334 let mut depth = 0;
5335 while let Expr::UnaryOp {
5336 op: UnaryOp::BitNot,
5337 expr: inner,
5338 ..
5339 } = expr
5340 {
5341 depth += 1;
5342 expr = inner;
5343 }
5344 depth
5345 }
5346
5347 fn wrap_function_to_height(base: &str, target_height: usize) -> String {
5348 let base_height = parsed_expr_height(base) as usize;
5349 assert!(base_height <= target_height);
5350 let wrappers = target_height - base_height;
5351 format!("{}{base}{}", "abs(".repeat(wrappers), ")".repeat(wrappers))
5352 }
5353
5354 #[test]
5355 fn test_explicit_machine_matches_recursive_oracle_for_shallow_valid_expressions() {
5356 for sql in [
5357 "1",
5358 "-9223372036854775808",
5359 "a.b + c * 2",
5360 "'a'.b + a.'b'",
5361 "attach.x",
5362 "filter.x",
5363 "true.x",
5364 "with.x",
5365 "a.current_date",
5366 "NOT a = b",
5367 "x IS NULL < 2",
5368 "x IS NOT DISTINCT FROM y",
5369 "CAST(x + 1 AS DECIMAL(10, 2))",
5370 "CASE x WHEN 1 THEN y ELSE z END",
5371 "x NOT BETWEEN 1 AND 2",
5372 "x IN (1, 2 + 3)",
5373 "(SELECT 1, 2) IN ((1, 2))",
5374 "(a, b) IN ((SELECT 1))",
5375 "(a, b) IN ((SELECT 1, 2, 3))",
5376 "(a, b) IN ((SELECT 1), (SELECT 2))",
5377 "(SELECT * FROM t) IN (1)",
5378 "x IN (SELECT y FROM t WHERE z > 0 ORDER BY y LIMIT 1)",
5379 "EXISTS (SELECT 1 FROM t WHERE x = y)",
5380 "(1, 2 + 3)",
5381 "value COLLATE \"my col\"",
5382 "doc -> '$.x' || suffix",
5383 "sum(DISTINCT x ORDER BY y DESC) FILTER (WHERE z > 0) OVER (PARTITION BY p ORDER BY q ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)",
5384 ] {
5385 assert_machine_matches_recursive_oracle(sql);
5386 }
5387 }
5388
5389 #[test]
5390 fn test_explicit_machine_matches_recursive_oracle_for_shallow_malformed_expressions() {
5391 for sql in [
5392 "+",
5393 "CASE END",
5394 "CASE WHEN 1 2 END",
5395 "CASE WHEN 1 THEN 2",
5396 "CAST(1 INTEGER)",
5397 "f(DISTINCT)",
5398 "(1,)",
5399 "a.",
5400 "a.select",
5401 "a.nothing",
5402 "cast.x",
5403 "current_date.x",
5404 "raise.x",
5405 "transaction.x",
5406 "a BETWEEN 1 2",
5407 "a IN (1,)",
5408 "(a, b) IN (1)",
5409 "(a, b) IN (+(SELECT 1, 2))",
5410 "(a, b) IN ((1, 2), 3)",
5411 "(a, b) NOT IN ((1, 2, 3))",
5412 "(SELECT 1, 2) IN (1)",
5413 "(SELECT 1, 2) IN ((1, 2), 3)",
5414 "(SELECT 1, 2) NOT IN ((1, 2, 3))",
5415 "a LIKE",
5416 "EXISTS (SELECT)",
5417 "count(* ORDER BY x)",
5418 "t.*",
5419 ] {
5420 assert_machine_matches_recursive_oracle(sql);
5421 }
5422 }
5423
5424 #[test]
5425 fn public_parse_expr_requires_eof_after_one_optional_terminator() {
5426 assert_eq!(
5427 parse_expr("1;")
5428 .expect("one trailing expression terminator must remain valid")
5429 .to_string(),
5430 "1"
5431 );
5432
5433 for (sql, unexpected) in [("1; 2", "2"), ("1; SELECT 2", "SELECT"), ("1;;", ";")] {
5434 let error = parse_expr(sql)
5435 .expect_err("tokens after the optional expression terminator must be rejected");
5436 assert_eq!(error.kind, ParseErrorKind::UnexpectedToken);
5439 assert!(
5440 error.message.contains("unexpected token after expression"),
5441 "unexpected diagnostic for `{sql}`: {error:?}"
5442 );
5443 assert_eq!(
5444 &sql[error.span.start as usize..error.span.end as usize],
5445 unexpected,
5446 "the diagnostic for `{sql}` must point at the first forbidden token"
5447 );
5448 }
5449 }
5450
5451 #[test]
5452 fn test_explicit_select_machine_matches_recursive_shallow_oracle() {
5453 for sql in [
5454 "SELECT 1",
5455 "SELECT DISTINCT t.x AS y, count(*) FROM t INNER JOIN u ON t.id = u.id WHERE t.x > 0 GROUP BY t.x HAVING count(*) > 1 WINDOW w AS (PARTITION BY t.p ORDER BY t.q ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) ORDER BY t.x DESC NULLS LAST LIMIT 5 OFFSET 1",
5456 "SELECT * FROM a CROSS JOIN b ON a.id = b.id",
5457 "SELECT * FROM a, b",
5458 "SELECT * FROM a, b ON a.id = b.id",
5459 "SELECT * FROM a, b USING(id)",
5460 "SELECT filter.* FROM t AS filter",
5461 "SELECT attach.* FROM t AS \"attach\"",
5462 "SELECT attach.x FROM (SELECT 1 AS x) AS \"attach\"",
5463 "SELECT filter.x FROM (SELECT 1 AS x) AS \"filter\"",
5464 "SELECT 't'.*, t.'select' FROM t",
5465 "SELECT 1 'single quoted'",
5466 "SELECT 1 attach",
5467 "SELECT 1 window",
5468 "SELECT * FROM (SELECT 1) 'single quoted'",
5469 "SELECT * FROM (SELECT 1) match",
5470 "SELECT sum(1) OVER attach WINDOW attach AS ()",
5471 "SELECT sum(1) OVER (attach) WINDOW attach AS ()",
5472 "SELECT sum(x) OVER (ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING) FROM t",
5473 "SELECT sum(x) OVER (RANGE BETWEEN CURRENT ROW AND 1 FOLLOWING) FROM t",
5474 "VALUES (1, 2), (3, 4)",
5475 "VALUES (1) ORDER BY 1",
5476 "VALUES (1) LIMIT 1",
5477 "VALUES (1) UNION SELECT 2 ORDER BY 1 LIMIT 1",
5478 "SELECT 1 UNION ALL SELECT 2 INTERSECT SELECT 3",
5479 "SELECT 1 UNION VALUES (2), (3) ORDER BY 1",
5480 "SELECT FROM t",
5481 "SELECT nothing.* FROM t AS \"nothing\"",
5482 "SELECT sum(1) OVER filter",
5483 "SELECT sum(x) OVER (ROWS 1 FOLLOWING) FROM t",
5484 "SELECT sum(x) OVER (ROWS BETWEEN CURRENT ROW AND 1 PRECEDING) FROM t",
5485 "VALUES 1",
5486 ] {
5487 assert_select_machine_matches_recursive_oracle(sql);
5488 }
5489 }
5490
5491 #[test]
5492 fn test_threshold_unary_precedence_associativity_and_spans_are_stable() {
5493 for unary_count in [63_u32, 64] {
5494 let sql = format!("{}1 + (1)", "~".repeat(unary_count as usize));
5495 let parsed = parse_expr(&sql).expect("threshold unary-plus expression must parse");
5496 assert_eq!(
5497 parsed.span(),
5498 Span::new(0, unary_count + 6),
5499 "grouping delimiters must not change the established root span"
5500 );
5501 let Expr::BinaryOp {
5502 left,
5503 op: BinaryOp::Add,
5504 right,
5505 ..
5506 } = &parsed
5507 else {
5508 panic!("unary prefix must not capture the lower-precedence addition");
5509 };
5510 assert_eq!(bitnot_depth(left), unary_count as usize);
5511 assert!(matches!(
5512 right.as_ref(),
5513 Expr::Literal(Literal::Integer(1), _)
5514 ));
5515
5516 let subtraction = format!("{}10 - 3 - 2", "~".repeat(unary_count as usize));
5517 let subtraction =
5518 parse_expr(&subtraction).expect("threshold subtraction expression must parse");
5519 assert!(matches!(
5520 subtraction,
5521 Expr::BinaryOp {
5522 op: BinaryOp::Subtract,
5523 left,
5524 ..
5525 } if matches!(
5526 left.as_ref(),
5527 Expr::BinaryOp {
5528 op: BinaryOp::Subtract,
5529 ..
5530 }
5531 )
5532 ));
5533
5534 let precedence = format!("{}1 + 2 * 3", "~".repeat(unary_count as usize));
5535 let precedence =
5536 parse_expr(&precedence).expect("threshold precedence expression must parse");
5537 assert!(matches!(
5538 precedence,
5539 Expr::BinaryOp {
5540 op: BinaryOp::Add,
5541 right,
5542 ..
5543 } if matches!(
5544 right.as_ref(),
5545 Expr::BinaryOp {
5546 op: BinaryOp::Multiply,
5547 ..
5548 }
5549 )
5550 ));
5551
5552 let parenthesized = format!(
5553 "{}1{}",
5554 "(".repeat(unary_count as usize),
5555 ")".repeat(unary_count as usize)
5556 );
5557 let parenthesized =
5558 parse_expr(&parenthesized).expect("threshold parentheses must parse");
5559 assert_eq!(
5560 parenthesized.span(),
5561 Span::new(unary_count, unary_count + 1)
5562 );
5563 }
5564 }
5565
5566 #[test]
5567 fn test_shallow_machine_uses_only_inline_control_and_value_storage() {
5568 PARSE_MACHINE_STACK_SPILLS.set(0);
5569 let expr = parse_expr("a + b * 2").expect("shallow expression must parse");
5570 assert_eq!(expr.to_string(), "a + b * 2");
5571 assert_eq!(
5572 PARSE_MACHINE_STACK_SPILLS.get(),
5573 0,
5574 "representative shallow parsing must not allocate parser stack spill storage"
5575 );
5576 }
5577
5578 #[test]
5579 fn test_formatter_precedence_associativity_and_migration_scale_stability() {
5580 for (sql, expected) in [
5581 ("a + b * 2", "a + b * 2"),
5582 ("a * (b + c)", "a * (b + c)"),
5583 ("(a - b) - c", "a - b - c"),
5584 ("a - (b - c)", "a - (b - c)"),
5585 ("a / (b / c)", "a / (b / c)"),
5586 ] {
5587 let expr = parse_expr(sql).expect("precedence fixture must parse");
5588 let rendered = expr.to_string();
5589 assert_eq!(rendered, expected);
5590 let reparsed = parse_expr(&rendered).expect("formatted fixture must reparse");
5591 assert_eq!(reparsed.to_string(), rendered);
5592 }
5593
5594 const TERM_COUNT: usize = MAX_PARSE_DEPTH as usize;
5595 for operator in ["AND", "OR"] {
5596 let mut sql = String::new();
5597 for _ in 1..TERM_COUNT {
5598 sql.push_str("flag ");
5599 sql.push_str(operator);
5600 sql.push_str(" (");
5601 }
5602 sql.push_str("flag");
5603 sql.push_str(&")".repeat(TERM_COUNT - 1));
5604
5605 let expr = parse_expr(&sql).expect("migration-scale associative chain must parse");
5606 let rendered = expr.to_string();
5607 assert_eq!(rendered.matches(operator).count(), TERM_COUNT - 1);
5608 assert!(
5609 !rendered.contains('('),
5610 "associative {operator} chain must have a flat canonical form"
5611 );
5612 let reparsed = parse_expr(&rendered).expect("flat migration-scale chain must reparse");
5613 assert_eq!(
5614 reparsed.to_string(),
5615 rendered,
5616 "format-parse-format must be byte-stable for {operator}"
5617 );
5618 }
5619 }
5620
5621 #[test]
5622 fn test_expression_height_exact_1000_1001_flat_infix_boundary() {
5623 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5624 let at_limit = repeated_infix_expression(LIMIT, " + ");
5625 let expr = parse_expr(&at_limit).expect("1000-term left-associated tree has height 1000");
5626 let rendered = expr.to_string();
5627 parse_expr(&rendered).expect("formatted height-1000 expression must remain parseable");
5628
5629 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
5630 assert_expression_depth_error(&over_limit);
5631 }
5632
5633 #[test]
5634 fn test_expression_height_exact_1000_1001_unary_boundary() {
5635 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5636 let at_limit = format!("{}1", "~".repeat(LIMIT - 1));
5637 parse_expr(&at_limit).expect("999 unary nodes plus one leaf have height 1000");
5638
5639 let over_limit = format!("{}1", "~".repeat(LIMIT));
5640 assert_expression_depth_error(&over_limit);
5641 }
5642
5643 #[test]
5644 fn test_expression_height_exact_1000_1001_not_boundary() {
5645 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5646 let at_limit = format!("{}1", "NOT ".repeat(LIMIT - 1));
5647 parse_expr(&at_limit).expect("999 NOT nodes plus one leaf have height 1000");
5648
5649 let over_limit = format!("{}1", "NOT ".repeat(LIMIT));
5650 assert_expression_depth_error(&over_limit);
5651 }
5652
5653 #[test]
5654 fn test_expression_parenthesis_chain_is_stack_safe() {
5655 const PAREN_PAIRS: usize = MAX_PARSE_DEPTH as usize * 2;
5656 let deeply_parenthesized =
5657 format!("{}1{}", "(".repeat(PAREN_PAIRS), ")".repeat(PAREN_PAIRS));
5658 parse_expr(&deeply_parenthesized)
5659 .expect("parentheses do not add AST height or consume the native call stack");
5660 }
5661
5662 #[test]
5663 fn test_expression_prefix_frames_preserve_grouping_and_row_values() {
5664 let grouped = parse_expr("-((1 + 2)) * 3").expect("grouped unary expression must parse");
5665 assert!(matches!(
5666 grouped,
5667 Expr::BinaryOp {
5668 left,
5669 op: BinaryOp::Multiply,
5670 ..
5671 } if matches!(
5672 left.as_ref(),
5673 Expr::UnaryOp {
5674 op: UnaryOp::Negate,
5675 ..
5676 }
5677 )
5678 ));
5679
5680 let row = parse_expr("((1), 2)").expect("nested row value must parse");
5681 assert!(matches!(row, Expr::RowValue(values, _) if values.len() == 2));
5682 }
5683
5684 #[test]
5685 fn test_expression_iterative_prefix_frames_preserve_minimum_integer_literal() {
5686 let mut parser = Parser::from_sql("-9223372036854775808");
5687 let parsed = parser
5688 .parse_expr_tracked()
5689 .expect("minimum signed integer literal must parse");
5690 assert!(matches!(
5691 &parsed.expr,
5692 Expr::Literal(Literal::Integer(i64::MIN), _)
5693 ));
5694 assert_eq!(parsed.height, 1);
5695 assert_eq!(parsed.expr.to_string(), "-9223372036854775808");
5696 }
5697
5698 #[test]
5699 fn test_serializer_regression_double_negated_minimum_integer_round_trips() {
5700 let expr = parse_expr("- -9223372036854775808")
5701 .expect("double-negated minimum integer must parse");
5702 let rendered = expr.to_string();
5703 assert_eq!(rendered, "-(-9223372036854775808)");
5704 let reparsed = parse_expr(&rendered).expect("rendered double negation must remain SQL");
5705 assert_eq!(expr, reparsed);
5706 }
5707
5708 #[test]
5709 fn test_serializer_regression_quoted_collation_name_round_trips() {
5710 let expr =
5711 parse_expr("value COLLATE \"my col\"").expect("quoted collation name must parse");
5712 let rendered = expr.to_string();
5713 assert_eq!(rendered, "value COLLATE \"my col\"");
5714 let reparsed = parse_expr(&rendered).expect("rendered collation must remain SQL");
5715 assert_eq!(expr, reparsed);
5716 }
5717
5718 #[test]
5719 fn test_expression_height_mixed_prefix_and_flat_reductions() {
5720 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5721 const PREFIX_COUNT: usize = 499;
5722 let at_limit = format!(
5723 "{}{}",
5724 "~".repeat(PREFIX_COUNT),
5725 repeated_infix_expression(LIMIT - PREFIX_COUNT, " - ")
5726 );
5727 parse_expr(&at_limit)
5728 .expect("mixed unary and left-associated reductions have exact height 1000");
5729
5730 let over_limit = format!(
5731 "{}{}",
5732 "~".repeat(PREFIX_COUNT),
5733 repeated_infix_expression(LIMIT - PREFIX_COUNT + 1, " - ")
5734 );
5735 assert_expression_depth_error(&over_limit);
5736 }
5737
5738 #[test]
5739 fn test_expression_height_container_adds_one_level() {
5740 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5741 let at_limit = format!("abs({})", repeated_infix_expression(LIMIT - 1, " + "));
5742 parse_expr(&at_limit).expect("function node over height-999 argument has height 1000");
5743
5744 let over_limit = format!("abs({})", repeated_infix_expression(LIMIT, " + "));
5745 assert_expression_depth_error(&over_limit);
5746 }
5747
5748 #[test]
5749 fn test_right_deep_binary_exact_1000_1001_boundary_on_one_mib_stack() {
5750 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5751 let at_limit = right_deep_binary_expression(LIMIT);
5752 let expr = on_one_mib_stack(move || {
5753 parse_expr(&at_limit).expect("right-deep height-1000 expression must parse")
5754 });
5755 assert_expression_depth_error(&right_deep_binary_expression(LIMIT + 1));
5756 drop(expr);
5757 }
5758
5759 #[test]
5760 fn test_single_arg_function_exact_1000_1001_boundary_on_one_mib_stack() {
5761 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5762 let at_limit = single_arg_function_expression(LIMIT);
5763 let expr = on_one_mib_stack(move || {
5764 parse_expr(&at_limit).expect("nested function height-1000 expression must parse")
5765 });
5766 assert_expression_depth_error(&single_arg_function_expression(LIMIT + 1));
5767 drop(expr);
5768 }
5769
5770 #[test]
5771 fn test_scalar_subquery_exact_1000_1001_boundary_on_one_mib_stack() {
5772 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5773 let at_limit = scalar_subquery_expression(LIMIT);
5774 let rendered_selects = on_one_mib_stack(move || {
5775 let expr =
5776 parse_expr(&at_limit).expect("scalar subquery height-1000 expression must parse");
5777 let rendered = expr.to_string();
5778 let select_count = rendered.matches("(SELECT ").count();
5779 drop(rendered);
5780 drop(expr);
5781 select_count
5782 });
5783 assert_eq!(rendered_selects, LIMIT - 1);
5784 assert_expression_depth_error(&scalar_subquery_expression(LIMIT + 1));
5785 }
5786
5787 #[test]
5788 fn test_signed_minimum_and_qualified_bases_round_trip_on_one_mib_stack() {
5789 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5790 for (base, canonical_base) in [
5791 ("-9223372036854775808", "-9223372036854775808"),
5792 ("schema.column", "schema.\"column\""),
5793 ] {
5794 let at_limit = wrap_function_to_height(base, LIMIT);
5795 let (height, rendered) = on_one_mib_stack(move || {
5796 let expr = parse_expr(&at_limit).expect("height-1000 base expression must parse");
5797 let height = normalized_ast_expr_height(&expr);
5798 let rendered = expr.to_string();
5799 let reparsed =
5800 parse_expr(&rendered).expect("formatted height-1000 base must reparse");
5801 assert_eq!(normalized_ast_expr_height(&reparsed), MAX_PARSE_DEPTH);
5802 assert_eq!(rendered, reparsed.to_string());
5803 drop(reparsed);
5804 drop(expr);
5805 (height, rendered)
5806 });
5807 assert_eq!(height, MAX_PARSE_DEPTH);
5808 assert!(rendered.contains(canonical_base));
5809
5810 let over_limit = wrap_function_to_height(base, LIMIT + 1);
5811 let error = on_one_mib_stack(move || {
5812 parse_expr(&over_limit).expect_err("height-1001 base must fail closed")
5813 });
5814 assert_eq!(
5815 error.kind,
5816 ParseErrorKind::ExpressionTooDeep {
5817 max: MAX_PARSE_DEPTH
5818 }
5819 );
5820 }
5821 }
5822
5823 #[test]
5824 fn test_mixed_deep_height_1000_parse_walk_format_and_drop_on_one_mib_stack() {
5825 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5826 let at_limit = mixed_deep_expression(LIMIT);
5827 let (height, rendered_len, walk_visits) = on_one_mib_stack(move || {
5828 let expr = parse_expr(&at_limit)
5829 .expect("mixed unary/function/subquery/binary height-1000 expression must parse");
5830 HEIGHT_WALK_VISITS.set(0);
5831 let height = normalized_ast_expr_height(&expr);
5832 let walk_visits = HEIGHT_WALK_VISITS.get();
5833 let rendered = expr.to_string();
5834 let rendered_len = rendered.len();
5835 drop(rendered);
5836 drop(expr);
5837 (height, rendered_len, walk_visits)
5838 });
5839 assert_eq!(height, MAX_PARSE_DEPTH);
5840 assert!(rendered_len > LIMIT);
5841 assert!(
5842 walk_visits <= at_limit_token_bound(LIMIT),
5843 "heap-backed cached-height walk must remain linear: {walk_visits} visits"
5844 );
5845
5846 let over_limit = mixed_deep_expression(LIMIT + 1);
5847 let error = on_one_mib_stack(move || {
5848 parse_expr(&over_limit).expect_err("mixed height-1001 expression must fail closed")
5849 });
5850 assert_eq!(
5851 error.kind,
5852 ParseErrorKind::ExpressionTooDeep {
5853 max: MAX_PARSE_DEPTH
5854 }
5855 );
5856 }
5857
5858 #[test]
5859 fn test_mixed_select_shape_round_trips_and_drops_on_one_mib_stack_at_exact_limit() {
5860 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5861 let base = "CASE WHEN 5 BETWEEN 1 AND 9 THEN 3 IN (WITH c AS (SELECT x FROM t) SELECT sum(c.x) OVER (PARTITION BY u.p ORDER BY u.q ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) FROM c INNER JOIN u ON c.x = u.x WHERE u.x > 0 GROUP BY c.x HAVING count(*) > 0 ORDER BY c.x LIMIT 1) ELSE 0 END";
5862 let at_limit = wrap_function_to_height(base, LIMIT);
5863 let (height, rendered_len) = on_one_mib_stack(move || {
5864 let expr = parse_expr(&at_limit)
5865 .expect("mixed CASE/BETWEEN/IN/CTE/JOIN/window height-1000 expression must parse");
5866 assert_eq!(normalized_ast_expr_height(&expr), MAX_PARSE_DEPTH);
5867 let rendered = expr.to_string();
5868 let reparsed =
5869 parse_expr(&rendered).expect("formatted mixed height-1000 expression must reparse");
5870 assert_eq!(normalized_ast_expr_height(&reparsed), MAX_PARSE_DEPTH);
5871 let rerendered = reparsed.to_string();
5872 assert_eq!(rendered, rerendered);
5873 let rendered_len = rendered.len();
5874 drop(rerendered);
5875 drop(reparsed);
5876 drop(rendered);
5877 drop(expr);
5878 (MAX_PARSE_DEPTH, rendered_len)
5879 });
5880 assert_eq!(height, MAX_PARSE_DEPTH);
5881 assert!(rendered_len > LIMIT);
5882
5883 let over_limit = wrap_function_to_height(base, LIMIT + 1);
5884 let error = on_one_mib_stack(move || {
5885 parse_expr(&over_limit).expect_err("mixed height-1001 expression must fail closed")
5886 });
5887 assert_eq!(
5888 error.kind,
5889 ParseErrorKind::ExpressionTooDeep {
5890 max: MAX_PARSE_DEPTH
5891 }
5892 );
5893 assert_eq!(
5894 error.message,
5895 format!(
5896 "Expression tree is too large (maximum depth {})",
5897 MAX_PARSE_DEPTH
5898 )
5899 );
5900 }
5901
5902 const fn at_limit_token_bound(height: usize) -> usize {
5903 height * 12
5904 }
5905
5906 #[test]
5907 fn test_998_wrapper_aggregate_filter_machine_steps_are_linear() {
5908 const WRAPPERS: usize = 998;
5909 let sql = format!(
5910 "{}1{} FILTER (WHERE 1)",
5911 "abs(".repeat(WRAPPERS),
5912 ")".repeat(WRAPPERS)
5913 );
5914 let token_count = Parser::from_sql(&sql).tokens.len();
5915 PARSE_MACHINE_STEPS.set(0);
5916 let expr = parse_expr(&sql).expect("near-match aggregate FILTER expression must parse");
5917 let visits = PARSE_MACHINE_STEPS.get();
5918 assert!(
5919 visits <= token_count.saturating_mul(8),
5920 "explicit parser machine revisited tokens superlinearly: {visits} steps for {token_count} tokens"
5921 );
5922 drop(expr);
5923 }
5924
5925 #[test]
5926 fn test_aggregate_order_by_auxiliary_roots_do_not_rescan_descendants() {
5927 let mut sql = "1".to_owned();
5928 for _ in 0..64 {
5929 sql = format!("f(0 ORDER BY {sql})");
5930 }
5931
5932 HEIGHT_WALK_VISITS.set(0);
5933 parse_expr(&sql).expect("nested aggregate ORDER BY expression must parse");
5934 assert_eq!(
5935 HEIGHT_WALK_VISITS.get(),
5936 0,
5937 "independent aggregate ORDER BY roots must not walk completed ASTs"
5938 );
5939 }
5940
5941 #[test]
5942 fn test_subquery_height_contract_matches_sqlite_height_of_select_fields() {
5943 for (sql, expected_height) in [
5944 ("SELECT 1 + 2 + 3", 3),
5945 ("SELECT 0 WHERE 1 + 2 + 3", 3),
5946 ("SELECT 0 GROUP BY 1 + 2 + 3 HAVING 1 + 2 + 3", 3),
5947 (
5948 "SELECT 0 ORDER BY 1 + 2 + 3 LIMIT 1 + 2 + 3 OFFSET 1 + 2 + 3",
5949 4,
5950 ),
5951 ("VALUES (1 + 2 + 3)", 3),
5952 ("SELECT 0 UNION ALL SELECT 1 + 2 + 3", 3),
5953 ] {
5954 assert_eq!(
5955 parsed_select_height(sql),
5956 expected_height,
5957 "official SELECT expression-height field was omitted: {sql}"
5958 );
5959 }
5960
5961 for sql in [
5962 "WITH c AS (SELECT 1 + 2 + 3) SELECT 0",
5963 "SELECT 0 FROM (SELECT 1 + 2 + 3)",
5964 "SELECT 0 FROM json_each(1 + 2 + 3)",
5965 "SELECT 0 FROM a JOIN b ON 1 + 2 + 3",
5966 "SELECT 0 WINDOW w AS (PARTITION BY 1 + 2 + 3 ORDER BY 1 + 2 + 3)",
5967 ] {
5968 assert_eq!(
5969 parsed_select_height(sql),
5970 1,
5971 "independent SQL root was incorrectly charged to its enclosing SELECT: {sql}"
5972 );
5973 }
5974 }
5975
5976 #[test]
5977 fn test_cached_height_matches_sqlite_grammar_rewrites() {
5978 for (sql, expected_height) in [
5979 ("NOT 1", 2),
5980 ("NOT EXISTS (SELECT 1)", 3),
5981 ("1 BETWEEN 2 AND 3", 2),
5982 ("1 NOT BETWEEN 2 AND 3", 3),
5983 ("1 LIKE 2", 2),
5984 ("1 NOT LIKE 2", 3),
5985 ("1 IN ()", 1),
5986 ("1 NOT IN ()", 1),
5987 ("abs(1) IN ()", 3),
5988 ("abs(1) NOT IN ()", 3),
5989 ("1 IN (2)", 3),
5990 ("1 IN (+2)", 4),
5991 ("1 NOT IN (2)", 4),
5992 ("1 IN (2, 3)", 2),
5993 ("1 NOT IN (2, 3)", 3),
5994 ("1 IN (SELECT 1 + 2)", 3),
5995 ("1 IN ((SELECT 1 + 2))", 3),
5996 ("(1, 2) IN ((3, 4))", 2),
5997 ("+1", 2),
5998 ("++1", 2),
5999 ("-+1", 2),
6000 ("(1 + 2 + 3, 4)", 1),
6001 ("(1 + 2 + 3, 4) + 5", 2),
6002 ] {
6003 assert_eq!(
6004 parsed_expr_height(sql),
6005 expected_height,
6006 "cached grammar height mismatch: {sql}"
6007 );
6008 }
6009 }
6010
6011 #[test]
6012 fn test_function_cached_height_excludes_auxiliary_expression_roots() {
6013 for (sql, expected_height) in [
6014 ("sum(1 + 2 + 3)", 4),
6015 ("sum(1 ORDER BY 1 + 2 + 3)", 2),
6016 ("sum(1) FILTER (WHERE 1 + 2 + 3)", 2),
6017 ("sum(1) OVER (ORDER BY 1 + 2 + 3)", 2),
6018 (
6019 "sum(1 ORDER BY 1 + 2 + 3) FILTER (WHERE 1 + 2 + 3) \
6020 OVER (ORDER BY 1 + 2 + 3)",
6021 2,
6022 ),
6023 ] {
6024 assert_eq!(
6025 parsed_expr_height(sql),
6026 expected_height,
6027 "auxiliary root leaked into the aggregate argument height: {sql}"
6028 );
6029 }
6030 }
6031
6032 #[test]
6033 fn test_function_auxiliary_roots_have_independent_1000_1001_boundaries() {
6034 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
6035 let at_limit = repeated_infix_expression(LIMIT, " + ");
6036 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
6037 for sql in [
6038 format!("sum(1) FILTER (WHERE {at_limit})"),
6039 format!("row_number() OVER (ORDER BY {at_limit})"),
6040 format!("group_concat(1 ORDER BY {at_limit})"),
6041 ] {
6042 parse_expr(&sql).expect("height-1000 auxiliary root must remain independently valid");
6043 }
6044 for sql in [
6045 format!("sum(1) FILTER (WHERE {over_limit})"),
6046 format!("row_number() OVER (ORDER BY {over_limit})"),
6047 format!("group_concat(1 ORDER BY {over_limit})"),
6048 ] {
6049 assert_expression_depth_error(&sql);
6050 }
6051 }
6052
6053 #[test]
6054 fn test_select_auxiliary_roots_have_independent_1000_1001_boundaries() {
6055 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
6056 let at_limit = repeated_infix_expression(LIMIT, " + ");
6057 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
6058 for sql in [
6059 format!("(WITH c AS (SELECT {at_limit}) SELECT 0)"),
6060 format!("(SELECT 0 FROM (SELECT {at_limit}))"),
6061 format!("(SELECT 0 FROM json_each({at_limit}))"),
6062 format!("(SELECT 0 FROM a JOIN b ON {at_limit})"),
6063 format!("(SELECT 0 WINDOW w AS (ORDER BY {at_limit}))"),
6064 ] {
6065 parse_expr(&sql).expect("height-1000 independent SELECT root must remain valid");
6066 }
6067 for sql in [
6068 format!("(WITH c AS (SELECT {over_limit}) SELECT 0)"),
6069 format!("(SELECT 0 FROM (SELECT {over_limit}))"),
6070 format!("(SELECT 0 FROM json_each({over_limit}))"),
6071 format!("(SELECT 0 FROM a JOIN b ON {over_limit})"),
6072 format!("(SELECT 0 WINDOW w AS (ORDER BY {over_limit}))"),
6073 ] {
6074 assert_expression_depth_error(&sql);
6075 }
6076 }
6077
6078 #[test]
6079 fn test_nested_subquery_height_is_threaded_without_ast_rescans() {
6080 let sql = scalar_subquery_expression(63);
6081 HEIGHT_WALK_VISITS.set(0);
6082 parse_expr(&sql).expect("tracked nested scalar-subquery height must parse");
6083 assert_eq!(
6084 HEIGHT_WALK_VISITS.get(),
6085 0,
6086 "nested subqueries must return tracked SELECT height in O(1) per parent"
6087 );
6088 }
6089
6090 #[test]
6091 fn test_subquery_height_contract_exact_1000_1001_boundary() {
6092 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
6093 let inner_at_limit = repeated_infix_expression(LIMIT - 1, " + ");
6094 for sql in [
6095 format!("(SELECT {inner_at_limit})"),
6096 format!("EXISTS (SELECT {inner_at_limit})"),
6097 format!("1 IN (SELECT {inner_at_limit})"),
6098 ] {
6099 parse_expr(&sql).expect("height-999 SELECT under one expression node must be accepted");
6100 }
6101
6102 let inner_over_limit = repeated_infix_expression(LIMIT, " + ");
6103 for sql in [
6104 format!("(SELECT {inner_over_limit})"),
6105 format!("EXISTS (SELECT {inner_over_limit})"),
6106 format!("1 IN (SELECT {inner_over_limit})"),
6107 ] {
6108 assert_expression_depth_error(&sql);
6109 }
6110 }
6111
6112 #[test]
6115 fn test_not_lower_precedence_than_comparison() {
6116 let expr = parse("NOT x = y");
6118 match &expr {
6119 Expr::UnaryOp {
6120 op: UnaryOp::Not,
6121 expr: inner,
6122 ..
6123 } => match inner.as_ref() {
6124 Expr::BinaryOp {
6125 op: BinaryOp::Eq, ..
6126 } => {}
6127 other => unreachable!("expected Eq inside NOT, got {other:?}"),
6128 },
6129 other => unreachable!("expected NOT(Eq), got {other:?}"),
6130 }
6131 }
6132
6133 #[test]
6134 fn test_unary_binds_tighter_than_collate() {
6135 let expr = parse("-x COLLATE NOCASE");
6137 match &expr {
6138 Expr::Collate {
6139 expr: inner,
6140 collation,
6141 ..
6142 } => {
6143 assert_eq!(collation, "NOCASE");
6144 assert!(matches!(
6145 inner.as_ref(),
6146 Expr::UnaryOp {
6147 op: UnaryOp::Negate,
6148 ..
6149 }
6150 ));
6151 }
6152 other => unreachable!("expected COLLATE(Negate), got {other:?}"),
6153 }
6154 }
6155
6156 #[test]
6157 fn test_arithmetic_precedence() {
6158 let expr = parse("1 + 2 * 3");
6160 match &expr {
6161 Expr::BinaryOp {
6162 op: BinaryOp::Add,
6163 left,
6164 right,
6165 ..
6166 } => {
6167 assert!(matches!(
6168 left.as_ref(),
6169 Expr::Literal(Literal::Integer(1), _)
6170 ));
6171 assert!(matches!(
6172 right.as_ref(),
6173 Expr::BinaryOp {
6174 op: BinaryOp::Multiply,
6175 ..
6176 }
6177 ));
6178 }
6179 other => unreachable!("expected Add(1, Mul(2,3)), got {other:?}"),
6180 }
6181 }
6182
6183 #[test]
6184 fn test_and_higher_than_or() {
6185 let expr = parse("a OR b AND c");
6187 match &expr {
6188 Expr::BinaryOp {
6189 op: BinaryOp::Or,
6190 right,
6191 ..
6192 } => {
6193 assert!(matches!(
6194 right.as_ref(),
6195 Expr::BinaryOp {
6196 op: BinaryOp::And,
6197 ..
6198 }
6199 ));
6200 }
6201 other => unreachable!("expected Or(a, And(b,c)), got {other:?}"),
6202 }
6203 }
6204
6205 #[test]
6208 fn test_cast_expression() {
6209 let expr = parse("CAST(42 AS INTEGER)");
6210 match &expr {
6211 Expr::Cast {
6212 expr: inner,
6213 type_name,
6214 ..
6215 } => {
6216 assert!(matches!(
6217 inner.as_ref(),
6218 Expr::Literal(Literal::Integer(42), _)
6219 ));
6220 assert_eq!(type_name.name, "INTEGER");
6221 }
6222 other => unreachable!("expected Cast, got {other:?}"),
6223 }
6224 }
6225
6226 #[test]
6227 fn test_cast_float_argument() {
6228 let expr = parse("CAST(x AS DECIMAL(10.5, -2.5))");
6230 match &expr {
6231 Expr::Cast { type_name, .. } => {
6232 assert_eq!(type_name.name, "DECIMAL");
6233 assert_eq!(type_name.arg1.as_deref(), Some("10.5"));
6234 assert_eq!(type_name.arg2.as_deref(), Some("-2.5"));
6235 }
6236 other => unreachable!("expected Cast with float args, got {other:?}"),
6237 }
6238 }
6239
6240 #[test]
6241 fn test_cast_signed_args() {
6242 let expr = parse("CAST(x AS NUMERIC(+5, -5))");
6244 match &expr {
6245 Expr::Cast { type_name, .. } => {
6246 assert_eq!(type_name.name, "NUMERIC");
6247 assert_eq!(type_name.arg1.as_deref(), Some("+5"));
6248 assert_eq!(type_name.arg2.as_deref(), Some("-5"));
6249 }
6250 other => unreachable!("expected Cast with signed args, got {other:?}"),
6251 }
6252 }
6253
6254 #[test]
6257 fn test_case_when_simple() {
6258 let expr = parse(
6259 "CASE x WHEN 1 THEN 'one' WHEN 2 THEN 'two' \
6260 ELSE 'other' END",
6261 );
6262 match &expr {
6263 Expr::Case {
6264 operand: Some(op),
6265 whens,
6266 else_expr: Some(_),
6267 ..
6268 } => {
6269 assert!(matches!(op.as_ref(), Expr::Column(..)));
6270 assert_eq!(whens.len(), 2);
6271 }
6272 other => unreachable!("expected simple CASE, got {other:?}"),
6273 }
6274 }
6275
6276 #[test]
6277 fn test_case_when_searched() {
6278 let expr = parse(
6279 "CASE WHEN x > 0 THEN 'pos' WHEN x < 0 THEN 'neg' \
6280 ELSE 'zero' END",
6281 );
6282 match &expr {
6283 Expr::Case {
6284 operand: None,
6285 whens,
6286 else_expr: Some(_),
6287 ..
6288 } => {
6289 assert_eq!(whens.len(), 2);
6290 assert!(matches!(
6291 &whens[0].0,
6292 Expr::BinaryOp {
6293 op: BinaryOp::Gt,
6294 ..
6295 }
6296 ));
6297 }
6298 other => unreachable!("expected searched CASE, got {other:?}"),
6299 }
6300 }
6301
6302 #[test]
6305 fn test_exists_subquery() {
6306 let expr = parse("EXISTS (SELECT 1)");
6307 assert!(matches!(expr, Expr::Exists { not: false, .. }));
6308 }
6309
6310 #[test]
6311 fn test_not_exists_subquery() {
6312 let expr = parse("NOT EXISTS (SELECT 1)");
6313 assert!(matches!(expr, Expr::Exists { not: true, .. }));
6314 }
6315
6316 #[test]
6317 fn test_exists_subquery_supports_qualified_table_with_alias() {
6318 let expr = parse("EXISTS (SELECT 1 FROM main.users AS u WHERE u.id = 1)");
6319 match expr {
6320 Expr::Exists { subquery, .. } => match subquery.body.select {
6321 SelectCore::Select {
6322 from: Some(from), ..
6323 } => match from.source {
6324 TableOrSubquery::Table { name, alias, .. } => {
6325 assert_eq!(name.schema.as_deref(), Some("main"));
6326 assert_eq!(name.name, "users");
6327 assert_eq!(alias.as_deref(), Some("u"));
6328 }
6329 other => unreachable!("expected table source, got {other:?}"),
6330 },
6331 other => unreachable!("expected SELECT core with FROM, got {other:?}"),
6332 },
6333 other => unreachable!("expected EXISTS subquery, got {other:?}"),
6334 }
6335 }
6336
6337 #[test]
6340 fn test_in_expr_list() {
6341 let expr = parse("x IN (1, 2, 3)");
6342 match &expr {
6343 Expr::In {
6344 not: false,
6345 set: InSet::List(items),
6346 ..
6347 } => assert_eq!(items.len(), 3),
6348 other => unreachable!("expected IN list, got {other:?}"),
6349 }
6350 }
6351
6352 #[test]
6353 fn test_explicit_row_value_in_list_rejects_mismatched_element_arities() {
6354 for (sql, expected_message) in [
6355 (
6356 "(a, b, c) IN ((1, 2))",
6357 "IN(...) element has 2 terms - expected 3",
6358 ),
6359 (
6360 "(a, b) IN ((1, 2, 3))",
6361 "IN(...) element has 3 terms - expected 2",
6362 ),
6363 ("(a, b) IN (1)", "IN(...) element has 1 term - expected 2"),
6364 (
6365 "(a, b) IN ((1, 2), 3)",
6366 "IN(...) element has 1 term - expected 2",
6367 ),
6368 (
6369 "(a, b) NOT IN ((1, 2), (3, 4, 5))",
6370 "IN(...) element has 3 terms - expected 2",
6371 ),
6372 (
6373 "0 AND (a, b) IN (1)",
6374 "IN(...) element has 1 term - expected 2",
6375 ),
6376 (
6377 "(a, b) IN (+(SELECT 1, 2))",
6378 "IN(...) element has 1 term - expected 2",
6379 ),
6380 ] {
6381 let error = parse_expr(sql).expect_err("mismatched vector IN arity must fail parsing");
6382 assert_eq!(
6383 error.kind,
6384 ParseErrorKind::Semantic,
6385 "unexpected kind for `{sql}`"
6386 );
6387 assert_eq!(
6388 error.message, expected_message,
6389 "unexpected error for `{sql}`"
6390 );
6391 }
6392 }
6393
6394 #[test]
6395 fn test_subquery_lhs_defers_in_list_arity_to_semantic_resolution() {
6396 for sql in [
6397 "(SELECT 1, 2) IN (1)",
6398 "(SELECT 1, 2) IN ((1, 2, 3))",
6399 "(VALUES (1, 2, 3)) IN ((1, 2))",
6400 "(SELECT 1, 2 UNION ALL SELECT 3, 4) NOT IN (5)",
6401 "0 AND (SELECT 1, 2) IN (1)",
6402 "(SELECT 1, 2) IN (nosuch_vector_function())",
6403 ] {
6404 let expr = parse_expr(sql).unwrap_or_else(|error| {
6405 panic!("subquery-expression IN semantics must be deferred for `{sql}`: {error}")
6406 });
6407 assert!(
6408 matches!(expr, Expr::In { .. } | Expr::BinaryOp { .. }),
6409 "unexpected AST for `{sql}`"
6410 );
6411 }
6412 }
6413
6414 #[test]
6415 fn test_vector_in_list_accepts_matching_empty_and_singleton_subquery_forms() {
6416 for sql in [
6417 "(a, b) IN ((1, 2), (3, 4))",
6418 "(a, b) NOT IN ((1, 2), (3, 4))",
6419 "(a, b) IN ()",
6420 "(a, b) IN ((SELECT 1, 2))",
6421 "(a, b) IN ((SELECT 1))",
6422 "(a, b) IN ((SELECT 1, 2, 3))",
6423 "(a, b) IN ((SELECT 1), (SELECT 2))",
6428 "(SELECT 1, 2) IN ((1, 2), (3, 4))",
6429 "(VALUES (1, 2), (3, 4)) NOT IN ((1, 2))",
6430 "(SELECT 1, 2 UNION ALL SELECT 3, 4) IN ((1, 2))",
6431 "(SELECT * FROM t) IN (1)",
6433 "(SELECT t.* FROM t) IN ((1, 2, 3))",
6434 "(SELECT 1, 2) IN ((SELECT 1))",
6436 "(SELECT 1, 2) IN (SELECT 1)",
6437 ] {
6438 let expr = parse_expr(sql).unwrap_or_else(|error| {
6439 panic!("matching vector IN list must parse for `{sql}`: {error}")
6440 });
6441 assert!(
6442 matches!(expr, Expr::In { .. }),
6443 "unexpected AST for `{sql}`"
6444 );
6445 }
6446 }
6447
6448 #[test]
6449 fn test_vector_in_list_trailing_comma_syntax_error_precedes_arity() {
6450 let error = parse_expr("(a, b) IN (1,)")
6451 .expect_err("a trailing comma in an IN list must fail parsing");
6452 assert_eq!(error.kind, ParseErrorKind::UnexpectedToken);
6453 assert_eq!(error.message, "unexpected token in expression: RightParen");
6454 }
6455
6456 #[test]
6457 fn test_statement_parsers_reject_vector_in_list_arity_mismatches() {
6458 for (sql, expected_message) in [
6459 (
6460 "SELECT (a, b) IN (1) FROM t",
6461 "IN(...) element has 1 term - expected 2",
6462 ),
6463 (
6464 "UPDATE t SET flag = (a, b) IN ((1, 2, 3))",
6465 "IN(...) element has 3 terms - expected 2",
6466 ),
6467 (
6468 "DELETE FROM t WHERE (a, b) NOT IN ((1, 2), 3)",
6469 "IN(...) element has 1 term - expected 2",
6470 ),
6471 ] {
6472 let error = Parser::from_sql(sql)
6473 .parse_statement()
6474 .expect_err("statement parser must reject mismatched vector IN arity");
6475 assert_eq!(
6476 error.kind,
6477 ParseErrorKind::Semantic,
6478 "unexpected kind for `{sql}`"
6479 );
6480 assert_eq!(
6481 error.message, expected_message,
6482 "unexpected error for `{sql}`"
6483 );
6484 }
6485 }
6486
6487 #[test]
6488 fn test_statement_parsers_defer_subquery_in_list_arity() {
6489 for sql in [
6490 "SELECT (SELECT 1, 2) IN (1)",
6491 "UPDATE t SET flag = (SELECT 1, 2) IN ((1, 2, 3))",
6492 "DELETE FROM t WHERE 0 AND (SELECT 1, 2) NOT IN ((1, 2), 3)",
6493 ] {
6494 Parser::from_sql(sql)
6495 .parse_statement()
6496 .unwrap_or_else(|error| {
6497 panic!("statement semantics must be deferred for `{sql}`: {error}")
6498 });
6499 }
6500 }
6501
6502 #[test]
6503 fn test_in_subquery() {
6504 let expr = parse("x IN (SELECT y FROM t)");
6505 assert!(matches!(
6506 expr,
6507 Expr::In {
6508 not: false,
6509 set: InSet::Subquery(_),
6510 ..
6511 }
6512 ));
6513 }
6514
6515 #[test]
6516 fn test_in_subquery_with_order_by_and_limit() {
6517 let expr =
6519 parse("id NOT IN (SELECT id FROM search_recipes ORDER BY updated_ts DESC LIMIT 5)");
6520 match &expr {
6521 Expr::In {
6522 not: true,
6523 set: InSet::Subquery(stmt),
6524 ..
6525 } => {
6526 assert_eq!(stmt.order_by.len(), 1, "ORDER BY should be parsed");
6527 assert!(stmt.limit.is_some(), "LIMIT should be parsed");
6528 }
6529 other => unreachable!("expected NOT IN subquery, got {other:?}"),
6530 }
6531 }
6532
6533 #[test]
6534 fn test_in_subquery_supports_group_by_and_having() {
6535 let expr = parse("x IN (SELECT y FROM t GROUP BY y HAVING COUNT(*) > 1)");
6536 match expr {
6537 Expr::In {
6538 set: InSet::Subquery(stmt),
6539 ..
6540 } => match stmt.body.select {
6541 SelectCore::Select {
6542 group_by, having, ..
6543 } => {
6544 assert_eq!(group_by.len(), 1, "GROUP BY should be parsed");
6545 assert!(having.is_some(), "HAVING should be parsed");
6546 }
6547 SelectCore::Values(_) => unreachable!("expected SELECT core"),
6548 },
6549 other => unreachable!("expected IN subquery, got {other:?}"),
6550 }
6551 }
6552
6553 #[test]
6554 fn test_not_in() {
6555 let expr = parse("x NOT IN (1, 2)");
6556 assert!(matches!(expr, Expr::In { not: true, .. }));
6557 }
6558
6559 #[test]
6560 fn test_in_table_name() {
6561 let expr = parse("x IN t");
6562 assert!(matches!(
6563 expr,
6564 Expr::In {
6565 not: false,
6566 set: InSet::Table(_),
6567 ..
6568 }
6569 ));
6570 }
6571
6572 #[test]
6573 fn test_not_in_table_name() {
6574 let expr = parse("x NOT IN t");
6575 assert!(matches!(
6576 expr,
6577 Expr::In {
6578 not: true,
6579 set: InSet::Table(_),
6580 ..
6581 }
6582 ));
6583 }
6584
6585 #[test]
6586 fn test_in_schema_table_name() {
6587 let expr = parse("x IN main.t");
6588 match expr {
6589 Expr::In {
6590 set: InSet::Table(name),
6591 ..
6592 } => {
6593 assert_eq!(name.schema.as_deref(), Some("main"));
6594 assert_eq!(name.name, "t");
6595 }
6596 other => unreachable!("expected IN table form, got {other:?}"),
6597 }
6598 }
6599
6600 #[test]
6603 fn test_between_and() {
6604 let expr = parse("x BETWEEN 1 AND 10");
6605 assert!(matches!(expr, Expr::Between { not: false, .. }));
6606 }
6607
6608 #[test]
6609 fn test_not_between() {
6610 let expr = parse("x NOT BETWEEN 1 AND 10");
6611 assert!(matches!(expr, Expr::Between { not: true, .. }));
6612 }
6613
6614 #[test]
6615 fn test_between_does_not_consume_outer_and() {
6616 let expr = parse("x BETWEEN 1 AND 10 AND y = 1");
6618 match &expr {
6619 Expr::BinaryOp {
6620 op: BinaryOp::And,
6621 left,
6622 ..
6623 } => assert!(matches!(left.as_ref(), Expr::Between { .. })),
6624 other => unreachable!("expected AND(BETWEEN, Eq), got {other:?}"),
6625 }
6626 }
6627
6628 #[test]
6631 fn test_like_pattern() {
6632 let expr = parse("name LIKE '%foo%'");
6633 assert!(matches!(
6634 expr,
6635 Expr::Like {
6636 op: LikeOp::Like,
6637 not: false,
6638 escape: None,
6639 ..
6640 }
6641 ));
6642 }
6643
6644 #[test]
6645 fn test_like_escape() {
6646 let expr = parse("name LIKE '%\\%%' ESCAPE '\\'");
6647 assert!(matches!(
6648 expr,
6649 Expr::Like {
6650 op: LikeOp::Like,
6651 escape: Some(_),
6652 ..
6653 }
6654 ));
6655 }
6656
6657 #[test]
6658 fn test_glob_pattern() {
6659 let expr = parse("path GLOB '*.rs'");
6660 assert!(matches!(
6661 expr,
6662 Expr::Like {
6663 op: LikeOp::Glob,
6664 not: false,
6665 ..
6666 }
6667 ));
6668 }
6669
6670 #[test]
6671 fn test_glob_character_class() {
6672 let expr = parse("name GLOB '[a-z]*'");
6673 match &expr {
6674 Expr::Like {
6675 op: LikeOp::Glob,
6676 pattern,
6677 ..
6678 } => assert!(matches!(
6679 pattern.as_ref(),
6680 Expr::Literal(Literal::String(s), _) if s == "[a-z]*"
6681 )),
6682 other => unreachable!("expected GLOB, got {other:?}"),
6683 }
6684 }
6685
6686 #[test]
6689 fn test_collate_override() {
6690 let expr = parse("name COLLATE NOCASE");
6691 match &expr {
6692 Expr::Collate { collation, .. } => {
6693 assert_eq!(collation, "NOCASE");
6694 }
6695 other => unreachable!("expected COLLATE, got {other:?}"),
6696 }
6697 }
6698
6699 #[test]
6702 fn test_json_arrow_operator() {
6703 let expr = parse("data -> 'key'");
6704 assert!(matches!(
6705 expr,
6706 Expr::JsonAccess {
6707 arrow: JsonArrow::Arrow,
6708 ..
6709 }
6710 ));
6711 }
6712
6713 #[test]
6714 fn test_json_double_arrow_operator() {
6715 let expr = parse("data ->> 'key'");
6716 assert!(matches!(
6717 expr,
6718 Expr::JsonAccess {
6719 arrow: JsonArrow::DoubleArrow,
6720 ..
6721 }
6722 ));
6723 }
6724
6725 #[test]
6728 fn test_is_null() {
6729 assert!(matches!(
6730 parse("42"),
6731 Expr::Literal(Literal::Integer(42), _)
6732 ));
6733 assert!(matches!(parse("3.14"), Expr::Literal(Literal::Float(_), _)));
6734 assert!(matches!(
6735 parse("'hello'"),
6736 Expr::Literal(Literal::String(_), _)
6737 ));
6738 assert!(matches!(parse("NULL"), Expr::Literal(Literal::Null, _)));
6739 assert!(matches!(parse("TRUE"), Expr::Literal(Literal::True, _)));
6740 assert!(matches!(parse("FALSE"), Expr::Literal(Literal::False, _)));
6741 }
6742
6743 #[test]
6750 fn test_isnull_eq_isnull_unparenthesized_left_associative() {
6751 let expr = parse("a IS NULL = b IS NULL");
6752 match &expr {
6753 Expr::IsNull {
6754 expr: inner,
6755 not: false,
6756 ..
6757 } => match inner.as_ref() {
6758 Expr::BinaryOp {
6759 op: BinaryOp::Eq,
6760 left,
6761 right,
6762 ..
6763 } => {
6764 assert!(
6765 matches!(left.as_ref(), Expr::IsNull { not: false, .. }),
6766 "expected (a IS NULL) on the left, got {left:?}"
6767 );
6768 assert!(
6769 matches!(right.as_ref(), Expr::Column(..)),
6770 "expected bare column b on the right, got {right:?}"
6771 );
6772 }
6773 other => unreachable!("expected Eq inside IsNull, got {other:?}"),
6774 },
6775 other => unreachable!("expected IsNull(Eq(IsNull(a), b)), got {other:?}"),
6776 }
6777 }
6778
6779 #[test]
6784 fn test_isnull_eq_isnull_parenthesized_round_trip() {
6785 let assert_shape = |expr: &Expr| match expr {
6786 Expr::BinaryOp {
6787 op: BinaryOp::Eq,
6788 left,
6789 right,
6790 ..
6791 } => {
6792 assert!(
6793 matches!(left.as_ref(), Expr::IsNull { not: false, .. }),
6794 "expected IsNull on the left, got {left:?}"
6795 );
6796 assert!(
6797 matches!(right.as_ref(), Expr::IsNull { not: false, .. }),
6798 "expected IsNull on the right, got {right:?}"
6799 );
6800 }
6801 other => unreachable!("expected Eq(IsNull, IsNull), got {other:?}"),
6802 };
6803 let expr = parse("(a IS NULL) = (b IS NULL)");
6804 assert_shape(&expr);
6805 let rendered = expr.to_string();
6806 assert_eq!(rendered, "a IS NULL = (b IS NULL)");
6807 let reparsed = parse(&rendered);
6808 assert_shape(&reparsed);
6809 assert_eq!(reparsed.to_string(), rendered, "round-trip not idempotent");
6810 }
6811
6812 #[test]
6817 fn test_is_null_followed_by_tighter_operator_binds_to_null() {
6818 let expr = parse("1 IS NULL < 2");
6819 match &expr {
6820 Expr::BinaryOp {
6821 op: BinaryOp::Is,
6822 right,
6823 ..
6824 } => assert!(
6825 matches!(
6826 right.as_ref(),
6827 Expr::BinaryOp {
6828 op: BinaryOp::Lt,
6829 ..
6830 }
6831 ),
6832 "expected Lt(NULL, 2) on the right of IS, got {right:?}"
6833 ),
6834 other => unreachable!("expected Is(1, Lt(NULL, 2)), got {other:?}"),
6835 }
6836 }
6837
6838 #[test]
6842 fn test_is_parenthesized_null_folds_to_isnull() {
6843 assert!(matches!(
6844 parse("x IS (NULL)"),
6845 Expr::IsNull { not: false, .. }
6846 ));
6847 assert!(matches!(
6848 parse("x IS NOT (NULL)"),
6849 Expr::IsNull { not: true, .. }
6850 ));
6851 }
6852
6853 #[test]
6854 fn test_placeholders() {
6855 assert!(matches!(
6856 parse("?"),
6857 Expr::Placeholder(PlaceholderType::Anonymous, _)
6858 ));
6859 assert!(matches!(
6860 parse("?1"),
6861 Expr::Placeholder(PlaceholderType::Numbered(1), _)
6862 ));
6863 assert!(matches!(
6864 parse(":name"),
6865 Expr::Placeholder(PlaceholderType::ColonNamed(_), _)
6866 ));
6867 }
6868
6869 #[test]
6872 fn test_column_bare() {
6873 match &parse("x") {
6874 Expr::Column(
6875 ColumnRef {
6876 schema: None,
6877 table: None,
6878 column,
6879 },
6880 _,
6881 ) => assert_eq!(column.as_ref(), "x"),
6882 other => unreachable!("expected bare column, got {other:?}"),
6883 }
6884 }
6885
6886 #[test]
6887 fn test_column_qualified() {
6888 match &parse("t.x") {
6889 Expr::Column(
6890 ColumnRef {
6891 schema: None,
6892 table: Some(t),
6893 column,
6894 },
6895 _,
6896 ) => {
6897 assert_eq!(t.as_ref(), "t");
6898 assert_eq!(column.as_ref(), "x");
6899 }
6900 other => unreachable!("expected qualified column, got {other:?}"),
6901 }
6902 }
6903
6904 #[test]
6905 fn test_column_schema_qualified() {
6906 match &parse("main.t.id") {
6908 Expr::Column(
6909 ColumnRef {
6910 schema: Some(s),
6911 table: Some(t),
6912 column,
6913 },
6914 _,
6915 ) => {
6916 assert_eq!(s.as_ref(), "main");
6917 assert_eq!(t.as_ref(), "t");
6918 assert_eq!(column.as_ref(), "id");
6919 }
6920 other => unreachable!("expected schema-qualified column, got {other:?}"),
6921 }
6922 assert_eq!(parse("main.t.id").to_string(), "main.t.id");
6924 }
6925
6926 #[test]
6927 fn test_qualified_column_retains_dot_height_and_exact_boundary() {
6928 assert_eq!(parsed_expr_height("x"), 1);
6929 assert_eq!(parsed_expr_height("t.x"), 2);
6930
6931 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
6932 let at_limit = format!("{}t.x", "~".repeat(LIMIT - 2));
6933 parse_expr(&at_limit).expect("998 unary nodes plus qualified column have height 1000");
6934
6935 let over_limit = format!("{}t.x", "~".repeat(LIMIT - 1));
6936 assert_expression_depth_error(&over_limit);
6937 }
6938
6939 #[test]
6942 fn test_concat_higher_than_add() {
6943 let expr = parse("a + b || c");
6945 match &expr {
6946 Expr::BinaryOp {
6947 op: BinaryOp::Add,
6948 right,
6949 ..
6950 } => assert!(matches!(
6951 right.as_ref(),
6952 Expr::BinaryOp {
6953 op: BinaryOp::Concat,
6954 ..
6955 }
6956 )),
6957 other => unreachable!("expected Add(a, Concat(b,c)), got {other:?}"),
6958 }
6959 }
6960
6961 #[test]
6964 fn test_parenthesized() {
6965 let expr = parse("(1 + 2) * 3");
6967 match &expr {
6968 Expr::BinaryOp {
6969 op: BinaryOp::Multiply,
6970 left,
6971 ..
6972 } => assert!(matches!(
6973 left.as_ref(),
6974 Expr::BinaryOp {
6975 op: BinaryOp::Add,
6976 ..
6977 }
6978 )),
6979 other => unreachable!("expected Mul(Add, 3), got {other:?}"),
6980 }
6981 }
6982
6983 #[test]
6986 fn test_is_operator() {
6987 assert!(matches!(
6988 parse("a IS b"),
6989 Expr::BinaryOp {
6990 op: BinaryOp::Is,
6991 ..
6992 }
6993 ));
6994 }
6995
6996 #[test]
6997 fn test_is_not_operator() {
6998 assert!(matches!(
6999 parse("a IS NOT b"),
7000 Expr::BinaryOp {
7001 op: BinaryOp::IsNot,
7002 ..
7003 }
7004 ));
7005 }
7006
7007 #[test]
7010 fn test_bitwise_ops() {
7011 let expr = parse("a & b | c");
7013 match &expr {
7014 Expr::BinaryOp {
7015 op: BinaryOp::BitOr,
7016 left,
7017 ..
7018 } => assert!(
7019 matches!(
7020 left.as_ref(),
7021 Expr::BinaryOp {
7022 op: BinaryOp::BitAnd,
7023 ..
7024 }
7025 ),
7026 "bitwise operators should be left-associative"
7027 ),
7028 other => unreachable!("expected BitOr(BitAnd, c), got {other:?}"),
7029 }
7030 }
7031
7032 #[test]
7033 fn test_bitnot() {
7034 assert!(matches!(
7035 parse("~x"),
7036 Expr::UnaryOp {
7037 op: UnaryOp::BitNot,
7038 ..
7039 }
7040 ));
7041 }
7042
7043 #[test]
7046 fn test_complex_where_clause() {
7047 let expr = parse("a > 1 AND b LIKE '%test%' OR NOT c IS NULL");
7048 assert!(matches!(
7049 expr,
7050 Expr::BinaryOp {
7051 op: BinaryOp::Or,
7052 ..
7053 }
7054 ));
7055 }
7056
7057 #[test]
7058 fn test_not_like_pattern() {
7059 assert!(matches!(
7060 parse("name NOT LIKE '%foo'"),
7061 Expr::Like {
7062 op: LikeOp::Like,
7063 not: true,
7064 ..
7065 }
7066 ));
7067 }
7068
7069 #[test]
7070 fn test_subquery_expr() {
7071 assert!(matches!(parse("(SELECT 1)"), Expr::Subquery(..)));
7072 }
7073
7074 #[test]
7082 fn test_pratt_level1_or_left_assoc() {
7083 let expr = parse("a OR b OR c");
7085 match &expr {
7086 Expr::BinaryOp {
7087 op: BinaryOp::Or,
7088 left,
7089 ..
7090 } => assert!(
7091 matches!(
7092 left.as_ref(),
7093 Expr::BinaryOp {
7094 op: BinaryOp::Or,
7095 ..
7096 }
7097 ),
7098 "OR should be left-associative"
7099 ),
7100 other => unreachable!("expected Or(Or(a,b), c), got {other:?}"),
7101 }
7102 }
7103
7104 #[test]
7106 fn test_pratt_level2_and_left_assoc() {
7107 let expr = parse("a AND b AND c");
7109 match &expr {
7110 Expr::BinaryOp {
7111 op: BinaryOp::And,
7112 left,
7113 ..
7114 } => assert!(
7115 matches!(
7116 left.as_ref(),
7117 Expr::BinaryOp {
7118 op: BinaryOp::And,
7119 ..
7120 }
7121 ),
7122 "AND should be left-associative"
7123 ),
7124 other => unreachable!("expected And(And(a,b), c), got {other:?}"),
7125 }
7126 }
7127
7128 #[test]
7130 fn test_pratt_level3_not_higher_than_and() {
7131 let expr = parse("NOT a AND b");
7133 match &expr {
7134 Expr::BinaryOp {
7135 op: BinaryOp::And,
7136 left,
7137 ..
7138 } => assert!(
7139 matches!(
7140 left.as_ref(),
7141 Expr::UnaryOp {
7142 op: UnaryOp::Not,
7143 ..
7144 }
7145 ),
7146 "NOT should bind tighter than AND"
7147 ),
7148 other => unreachable!("expected And(Not(a), b), got {other:?}"),
7149 }
7150 }
7151
7152 #[test]
7154 fn test_pratt_level4_equality_left_assoc() {
7155 let expr = parse("a = b != c");
7157 match &expr {
7158 Expr::BinaryOp {
7159 op: BinaryOp::Ne,
7160 left,
7161 ..
7162 } => assert!(
7163 matches!(
7164 left.as_ref(),
7165 Expr::BinaryOp {
7166 op: BinaryOp::Eq,
7167 ..
7168 }
7169 ),
7170 "equality operators should be left-associative at same level"
7171 ),
7172 other => unreachable!("expected Ne(Eq(a,b), c), got {other:?}"),
7173 }
7174 }
7175
7176 #[test]
7180 fn test_pratt_level4_vs_level5_eq_lt_boundary() {
7181 let expr = parse("a = b < c");
7184 match &expr {
7185 Expr::BinaryOp {
7186 op: BinaryOp::Eq,
7187 right,
7188 ..
7189 } => assert!(
7190 matches!(
7191 right.as_ref(),
7192 Expr::BinaryOp {
7193 op: BinaryOp::Lt,
7194 ..
7195 }
7196 ),
7197 "a = b < c MUST parse as a = (b < c): relational binds tighter"
7198 ),
7199 other => unreachable!("expected Eq(a, Lt(b,c)), got {other:?}"),
7200 }
7201 }
7202
7203 #[test]
7205 fn test_pratt_level4_vs_level5_ne_ge_boundary() {
7206 let expr = parse("a != b >= c");
7208 match &expr {
7209 Expr::BinaryOp {
7210 op: BinaryOp::Ne,
7211 right,
7212 ..
7213 } => assert!(
7214 matches!(
7215 right.as_ref(),
7216 Expr::BinaryOp {
7217 op: BinaryOp::Ge,
7218 ..
7219 }
7220 ),
7221 "a != b >= c must parse as a != (b >= c)"
7222 ),
7223 other => unreachable!("expected Ne(Ge(b,c)), got {other:?}"),
7224 }
7225 }
7226
7227 #[test]
7229 fn test_pratt_level5_relational_left_assoc() {
7230 let expr = parse("a < b >= c");
7232 match &expr {
7233 Expr::BinaryOp {
7234 op: BinaryOp::Ge,
7235 left,
7236 ..
7237 } => assert!(
7238 matches!(
7239 left.as_ref(),
7240 Expr::BinaryOp {
7241 op: BinaryOp::Lt,
7242 ..
7243 }
7244 ),
7245 "relational operators should be left-associative"
7246 ),
7247 other => unreachable!("expected Ge(Lt(a,b), c), got {other:?}"),
7248 }
7249 }
7250
7251 #[test]
7253 fn test_pratt_level6_bitwise_tighter_than_comparison() {
7254 let expr = parse("a < b & c");
7256 match &expr {
7257 Expr::BinaryOp {
7258 op: BinaryOp::Lt,
7259 right,
7260 ..
7261 } => assert!(
7262 matches!(
7263 right.as_ref(),
7264 Expr::BinaryOp {
7265 op: BinaryOp::BitAnd,
7266 ..
7267 }
7268 ),
7269 "bitwise should bind tighter than relational"
7270 ),
7271 other => unreachable!("expected Lt(a, BitAnd(b,c)), got {other:?}"),
7272 }
7273 }
7274
7275 #[test]
7277 fn test_pratt_level6_shifts_left_assoc() {
7278 let expr = parse("a << b >> c");
7280 match &expr {
7281 Expr::BinaryOp {
7282 op: BinaryOp::ShiftRight,
7283 left,
7284 ..
7285 } => assert!(
7286 matches!(
7287 left.as_ref(),
7288 Expr::BinaryOp {
7289 op: BinaryOp::ShiftLeft,
7290 ..
7291 }
7292 ),
7293 "shift operators should be left-associative"
7294 ),
7295 other => unreachable!("expected ShiftRight(ShiftLeft(a,b), c), got {other:?}"),
7296 }
7297 }
7298
7299 #[test]
7301 fn test_pratt_level7_add_sub_left_assoc() {
7302 let expr = parse("a + b - c");
7304 match &expr {
7305 Expr::BinaryOp {
7306 op: BinaryOp::Subtract,
7307 left,
7308 ..
7309 } => assert!(
7310 matches!(
7311 left.as_ref(),
7312 Expr::BinaryOp {
7313 op: BinaryOp::Add,
7314 ..
7315 }
7316 ),
7317 "add/sub should be left-associative"
7318 ),
7319 other => unreachable!("expected Sub(Add(a,b), c), got {other:?}"),
7320 }
7321 }
7322
7323 #[test]
7324 fn test_pratt_level7_add_sub_left_assoc_reverse() {
7325 let expr = parse("a - b + c");
7327 match &expr {
7328 Expr::BinaryOp {
7329 op: BinaryOp::Add,
7330 left,
7331 ..
7332 } => assert!(
7333 matches!(
7334 left.as_ref(),
7335 Expr::BinaryOp {
7336 op: BinaryOp::Subtract,
7337 ..
7338 }
7339 ),
7340 "add/sub should be left-associative"
7341 ),
7342 other => unreachable!("expected Add(Sub(a,b), c), got {other:?}"),
7343 }
7344 }
7345
7346 #[test]
7347 fn test_pratt_level9_concat_tighter_than_mul() {
7348 let expr = parse("a * b || c");
7350 match &expr {
7351 Expr::BinaryOp {
7352 op: BinaryOp::Multiply,
7353 right,
7354 ..
7355 } => assert!(
7356 matches!(
7357 right.as_ref(),
7358 Expr::BinaryOp {
7359 op: BinaryOp::Concat,
7360 ..
7361 }
7362 ),
7363 "concat should bind tighter than multiply"
7364 ),
7365 other => unreachable!("expected Mul(a, Concat(b,c)), got {other:?}"),
7366 }
7367 }
7368
7369 #[test]
7371 fn test_pratt_level8_mul_div_left_assoc() {
7372 let expr = parse("a * b / c");
7374 match &expr {
7375 Expr::BinaryOp {
7376 op: BinaryOp::Divide,
7377 left,
7378 ..
7379 } => assert!(
7380 matches!(
7381 left.as_ref(),
7382 Expr::BinaryOp {
7383 op: BinaryOp::Multiply,
7384 ..
7385 }
7386 ),
7387 "mul/div should be left-associative"
7388 ),
7389 other => unreachable!("expected Div(Mul(a,b), c), got {other:?}"),
7390 }
7391 }
7392
7393 #[test]
7394 fn test_pratt_level8_modulo() {
7395 let expr = parse("a * b % c");
7397 match &expr {
7398 Expr::BinaryOp {
7399 op: BinaryOp::Modulo,
7400 left,
7401 ..
7402 } => assert!(
7403 matches!(
7404 left.as_ref(),
7405 Expr::BinaryOp {
7406 op: BinaryOp::Multiply,
7407 ..
7408 }
7409 ),
7410 "modulo and multiply at same level, left-associative"
7411 ),
7412 other => unreachable!("expected Mod(Mul(a,b), c), got {other:?}"),
7413 }
7414 }
7415
7416 #[test]
7418 fn test_pratt_level9_concat_left_assoc() {
7419 let expr = parse("a || b || c");
7421 match &expr {
7422 Expr::BinaryOp {
7423 op: BinaryOp::Concat,
7424 left,
7425 ..
7426 } => assert!(
7427 matches!(
7428 left.as_ref(),
7429 Expr::BinaryOp {
7430 op: BinaryOp::Concat,
7431 ..
7432 }
7433 ),
7434 "concatenation should be left-associative"
7435 ),
7436 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
7437 }
7438 }
7439
7440 #[test]
7441 fn test_pratt_level9_concat_left_assoc_reverse() {
7442 let expr = parse("a || b || c");
7444 match &expr {
7445 Expr::BinaryOp {
7446 op: BinaryOp::Concat,
7447 left,
7448 ..
7449 } => assert!(
7450 matches!(
7451 left.as_ref(),
7452 Expr::BinaryOp {
7453 op: BinaryOp::Concat,
7454 ..
7455 }
7456 ),
7457 "concatenation should be left-associative"
7458 ),
7459 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
7460 }
7461 }
7462
7463 #[test]
7465 fn test_pratt_level10_collate_tighter_than_concat() {
7466 let expr = parse("a || b COLLATE NOCASE");
7468 match &expr {
7469 Expr::BinaryOp {
7470 op: BinaryOp::Concat,
7471 right,
7472 ..
7473 } => assert!(
7474 matches!(right.as_ref(), Expr::Collate { .. }),
7475 "COLLATE should bind tighter than concat"
7476 ),
7477 other => unreachable!("expected Concat(a, Collate(b)), got {other:?}"),
7478 }
7479 }
7480
7481 #[test]
7483 fn test_pratt_level11_unary_negate_tightest() {
7484 let expr = parse("-a * b");
7486 match &expr {
7487 Expr::BinaryOp {
7488 op: BinaryOp::Multiply,
7489 left,
7490 ..
7491 } => assert!(
7492 matches!(
7493 left.as_ref(),
7494 Expr::UnaryOp {
7495 op: UnaryOp::Negate,
7496 ..
7497 }
7498 ),
7499 "unary minus should bind tighter than multiply"
7500 ),
7501 other => unreachable!("expected Mul(Negate(a), b), got {other:?}"),
7502 }
7503 }
7504
7505 #[test]
7506 fn test_pratt_level11_bitnot_tightest() {
7507 let expr = parse("~a + b");
7509 match &expr {
7510 Expr::BinaryOp {
7511 op: BinaryOp::Add,
7512 left,
7513 ..
7514 } => assert!(
7515 matches!(
7516 left.as_ref(),
7517 Expr::UnaryOp {
7518 op: UnaryOp::BitNot,
7519 ..
7520 }
7521 ),
7522 "bitwise NOT should bind tighter than addition"
7523 ),
7524 other => unreachable!("expected Add(BitNot(a), b), got {other:?}"),
7525 }
7526 }
7527
7528 #[test]
7530 fn test_pratt_escape_not_infix_operator() {
7531 let expr = parse("a LIKE b ESCAPE c");
7533 match &expr {
7534 Expr::Like {
7535 escape: Some(esc), ..
7536 } => assert!(
7537 matches!(esc.as_ref(), Expr::Column(_, _)),
7538 "ESCAPE should be parsed as suffix of LIKE, not standalone infix"
7539 ),
7540 other => unreachable!("expected Like with escape, got {other:?}"),
7541 }
7542 }
7543
7544 #[test]
7545 fn test_pratt_escape_glob_not_infix() {
7546 let expr = parse("a GLOB b ESCAPE c");
7548 match &expr {
7549 Expr::Like {
7550 op: LikeOp::Glob,
7551 escape: Some(_),
7552 ..
7553 } => {}
7554 other => unreachable!("expected Glob with escape, got {other:?}"),
7555 }
7556 }
7557
7558 #[test]
7560 fn test_pratt_error_recovery_multiple_errors() {
7561 use crate::parser::Parser;
7562 let mut p = Parser::from_sql("SELECT +; SELECT *; SELECT 1");
7563 let (stmts, errs) = p.parse_all();
7564 assert!(
7567 !stmts.is_empty(),
7568 "should recover and parse at least one valid statement"
7569 );
7570 assert!(
7571 !errs.is_empty(),
7572 "should collect at least one error from malformed statements"
7573 );
7574 }
7575
7576 #[test]
7578 fn test_pratt_complex_mixed_all_levels() {
7579 let expr = parse("NOT a = b + c * -d OR e < f AND g LIKE h");
7582 match &expr {
7584 Expr::BinaryOp {
7585 op: BinaryOp::Or,
7586 left,
7587 right,
7588 ..
7589 } => {
7590 assert!(
7592 matches!(
7593 left.as_ref(),
7594 Expr::UnaryOp {
7595 op: UnaryOp::Not,
7596 ..
7597 }
7598 ),
7599 "left of OR should be NOT(...)"
7600 );
7601 match right.as_ref() {
7603 Expr::BinaryOp {
7604 op: BinaryOp::And,
7605 left: and_left,
7606 right: and_right,
7607 ..
7608 } => {
7609 assert!(
7610 matches!(
7611 and_left.as_ref(),
7612 Expr::BinaryOp {
7613 op: BinaryOp::Lt,
7614 ..
7615 }
7616 ),
7617 "left of AND should be Lt(e,f)"
7618 );
7619 assert!(
7620 matches!(and_right.as_ref(), Expr::Like { .. }),
7621 "right of AND should be Like(g,h)"
7622 );
7623 }
7624 other => unreachable!("expected And(Lt, Like), got {other:?}"),
7625 }
7626
7627 if let Expr::UnaryOp {
7630 expr: not_inner, ..
7631 } = left.as_ref()
7632 {
7633 if let Expr::BinaryOp {
7634 op: BinaryOp::Eq,
7635 right: eq_right,
7636 ..
7637 } = not_inner.as_ref()
7638 {
7639 if let Expr::BinaryOp {
7640 op: BinaryOp::Add,
7641 right: add_right,
7642 ..
7643 } = eq_right.as_ref()
7644 {
7645 if let Expr::BinaryOp {
7646 op: BinaryOp::Multiply,
7647 right: mul_right,
7648 ..
7649 } = add_right.as_ref()
7650 {
7651 assert!(
7652 matches!(
7653 mul_right.as_ref(),
7654 Expr::UnaryOp {
7655 op: UnaryOp::Negate,
7656 ..
7657 }
7658 ),
7659 "deepest: negate"
7660 );
7661 } else {
7662 unreachable!("expected Mul in add_right");
7663 }
7664 } else {
7665 unreachable!("expected Add in eq_right");
7666 }
7667 } else {
7668 unreachable!("expected Eq inside NOT");
7669 }
7670 }
7671 }
7672 other => unreachable!("expected Or(Not(...), And(...)), got {other:?}"),
7673 }
7674 }
7675
7676 #[test]
7678 fn test_pratt_json_same_precedence_as_concat() {
7679 let expr = parse("a || b -> c");
7681 match &expr {
7682 Expr::JsonAccess {
7683 expr: left,
7684 path: right,
7685 arrow: JsonArrow::Arrow,
7686 ..
7687 } => {
7688 assert!(
7689 matches!(
7690 left.as_ref(),
7691 Expr::BinaryOp {
7692 op: BinaryOp::Concat,
7693 ..
7694 }
7695 ),
7696 "left side should be concat expression"
7697 );
7698 assert!(
7699 matches!(right.as_ref(), Expr::Column(_, _)),
7700 "path should remain the right-hand expression"
7701 );
7702 }
7703 other => unreachable!("expected JsonAccess(Concat(a,b), c), got {other:?}"),
7704 }
7705 }
7706
7707 #[test]
7708 fn test_pratt_double_arrow_same_precedence_as_concat() {
7709 let expr = parse("a || b ->> c");
7710 assert!(
7711 matches!(
7712 expr,
7713 Expr::JsonAccess {
7714 arrow: JsonArrow::DoubleArrow,
7715 ..
7716 }
7717 ),
7718 "double-arrow should parse as JsonAccess at the same precedence level as concat"
7719 );
7720 }
7721}