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