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: format!("unexpected token in expression: {kind:?}"),
2183 span: token_span,
2184 line,
2185 col,
2186 });
2187 }
2188 };
2189 self.push_expr_tail(parsed, min_bp);
2190 Ok(())
2191 }
2192
2193 fn identifier_or_function(
2194 &mut self,
2195 name: Arc<str>,
2196 start: Span,
2197 min_bp: u8,
2198 ) -> Result<(), ParseError> {
2199 if self.parser.at_kind(&TokenKind::LeftParen) {
2200 return self.start_function(name.to_string(), start, min_bp);
2201 }
2202 let parsed = if self.parser.at_kind(&TokenKind::Dot) {
2203 let Some(column_token) = self.parser.tokens.get(self.parser.pos + 1).cloned() else {
2204 return Err(self.parser.err_here("expected column name after '.'"));
2205 };
2206 let column = match &column_token.kind {
2207 TokenKind::Id(column) | TokenKind::QuotedId(column, _) => Arc::clone(column),
2208 TokenKind::String(column) => Arc::<str>::from(column.as_str()),
2209 kind if starts_post_dot_identifier(kind) => Arc::<str>::from(kw_to_str(kind)),
2210 _ => {
2211 return Err(ParseError::at(
2212 format!(
2213 "expected column name after '.', got {:?}",
2214 column_token.kind
2215 ),
2216 Some(&column_token),
2217 ));
2218 }
2219 };
2220 self.parser.pos = self.parser.pos.saturating_add(2);
2221 self.parser.finish_expr(
2222 Expr::Column(
2223 ColumnRef::qualified(name, column),
2224 start.merge(column_token.span),
2225 ),
2226 2,
2227 false,
2228 false,
2229 )?
2230 } else {
2231 ParsedExpr::leaf(Expr::Column(ColumnRef::bare(name), start))
2232 };
2233 self.push_expr_tail(parsed, min_bp);
2234 Ok(())
2235 }
2236
2237 fn start_function(
2238 &mut self,
2239 name: String,
2240 start: Span,
2241 outer_min_bp: u8,
2242 ) -> Result<(), ParseError> {
2243 self.parser.expect_kind(&TokenKind::LeftParen)?;
2244 let mut build = FunctionBuild {
2245 name,
2246 start,
2247 args: FunctionArgs::List(Vec::new()),
2248 distinct: false,
2249 height: 0,
2250 order_by: Vec::new(),
2251 filter: None,
2252 over: None,
2253 end: start,
2254 };
2255 if self.parser.eat_kind(&TokenKind::Star) {
2256 build.args = if build.name.eq_ignore_ascii_case("count") {
2262 FunctionArgs::Star
2263 } else {
2264 FunctionArgs::List(Vec::new())
2265 };
2266 self.controls.push(ParseControl::FunctionClose {
2267 outer_min_bp,
2268 build,
2269 });
2270 } else {
2271 build.distinct = self.parser.eat_kind(&TokenKind::KwDistinct);
2272 if self.parser.at_kind(&TokenKind::RightParen) {
2273 if build.distinct {
2274 return Err(self
2275 .parser
2276 .err_here("DISTINCT requires at least one argument"));
2277 }
2278 self.controls.push(ParseControl::FunctionOrderStart {
2279 outer_min_bp,
2280 build,
2281 });
2282 } else {
2283 self.controls.push(ParseControl::FunctionArgDone {
2284 outer_min_bp,
2285 build,
2286 });
2287 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2288 }
2289 }
2290 Ok(())
2291 }
2292
2293 #[allow(clippy::too_many_lines)]
2294 fn expr_tail(&mut self, min_bp: u8) -> Result<(), ParseError> {
2295 let lhs = self.pop_expr()?;
2296 if let Some(left_bp) = self.parser.postfix_bp()
2297 && left_bp >= min_bp
2298 {
2299 let parsed = self.parser.parse_postfix(lhs)?;
2300 self.push_expr_tail(parsed, min_bp);
2301 return Ok(());
2302 }
2303 let Some((left_bp, right_bp)) = self.parser.infix_bp() else {
2304 self.values.push(MachineValue::Expr(lhs));
2305 return Ok(());
2306 };
2307 if left_bp < min_bp {
2308 self.values.push(MachineValue::Expr(lhs));
2309 return Ok(());
2310 }
2311
2312 let token = self.parser.advance_token();
2313 let simple = match &token.kind {
2314 TokenKind::Plus => Some(BinaryOp::Add),
2315 TokenKind::Minus => Some(BinaryOp::Subtract),
2316 TokenKind::Star => Some(BinaryOp::Multiply),
2317 TokenKind::Slash => Some(BinaryOp::Divide),
2318 TokenKind::Percent => Some(BinaryOp::Modulo),
2319 TokenKind::Concat => Some(BinaryOp::Concat),
2320 TokenKind::Eq | TokenKind::EqEq => Some(BinaryOp::Eq),
2321 TokenKind::Ne | TokenKind::LtGt => Some(BinaryOp::Ne),
2322 TokenKind::Lt => Some(BinaryOp::Lt),
2323 TokenKind::Le => Some(BinaryOp::Le),
2324 TokenKind::Gt => Some(BinaryOp::Gt),
2325 TokenKind::Ge => Some(BinaryOp::Ge),
2326 TokenKind::Ampersand => Some(BinaryOp::BitAnd),
2327 TokenKind::Pipe => Some(BinaryOp::BitOr),
2328 TokenKind::ShiftLeft => Some(BinaryOp::ShiftLeft),
2329 TokenKind::ShiftRight => Some(BinaryOp::ShiftRight),
2330 TokenKind::KwOr => Some(BinaryOp::Or),
2331 TokenKind::KwAnd => Some(BinaryOp::And),
2332 _ => None,
2333 };
2334 if let Some(op) = simple {
2335 self.controls.push(ParseControl::BinaryDone {
2336 outer_min_bp: min_bp,
2337 lhs,
2338 op,
2339 });
2340 self.controls
2341 .push(ParseControl::ExprStart { min_bp: right_bp });
2342 return Ok(());
2343 }
2344 match &token.kind {
2345 TokenKind::KwIs => {
2346 let not = self.parser.eat_kind(&TokenKind::KwNot);
2347 if self.parser.eat_kind(&TokenKind::KwDistinct) {
2348 self.parser.expect_kind(&TokenKind::KwFrom)?;
2349 self.controls.push(ParseControl::BinaryDone {
2350 outer_min_bp: min_bp,
2351 lhs,
2352 op: if not { BinaryOp::Is } else { BinaryOp::IsNot },
2353 });
2354 } else {
2355 self.controls.push(ParseControl::IsDone {
2356 outer_min_bp: min_bp,
2357 lhs,
2358 not,
2359 });
2360 }
2361 self.controls
2362 .push(ParseControl::ExprStart { min_bp: right_bp });
2363 }
2364 TokenKind::KwLike | TokenKind::KwGlob | TokenKind::KwMatch | TokenKind::KwRegexp => {
2365 let op = match &token.kind {
2366 TokenKind::KwLike => LikeOp::Like,
2367 TokenKind::KwGlob => LikeOp::Glob,
2368 TokenKind::KwMatch => LikeOp::Match,
2369 TokenKind::KwRegexp => LikeOp::Regexp,
2370 _ => unreachable!(),
2371 };
2372 self.controls.push(ParseControl::LikePatternDone {
2373 outer_min_bp: min_bp,
2374 lhs,
2375 op,
2376 not: false,
2377 });
2378 self.controls.push(ParseControl::ExprStart {
2379 min_bp: bp::EQUALITY.1,
2380 });
2381 }
2382 TokenKind::KwBetween => {
2383 self.controls.push(ParseControl::BetweenLowDone {
2384 outer_min_bp: min_bp,
2385 lhs,
2386 not: false,
2387 });
2388 self.controls.push(ParseControl::ExprStart {
2389 min_bp: bp::NOT_PREFIX,
2390 });
2391 }
2392 TokenKind::KwIn => self.start_in(lhs, false, min_bp)?,
2393 TokenKind::Arrow => {
2394 self.controls.push(ParseControl::JsonDone {
2395 outer_min_bp: min_bp,
2396 lhs,
2397 arrow: JsonArrow::Arrow,
2398 });
2399 self.controls
2400 .push(ParseControl::ExprStart { min_bp: right_bp });
2401 }
2402 TokenKind::DoubleArrow => {
2403 self.controls.push(ParseControl::JsonDone {
2404 outer_min_bp: min_bp,
2405 lhs,
2406 arrow: JsonArrow::DoubleArrow,
2407 });
2408 self.controls
2409 .push(ParseControl::ExprStart { min_bp: right_bp });
2410 }
2411 TokenKind::KwNot => {
2412 let next = self.parser.advance_token();
2413 match &next.kind {
2414 TokenKind::KwLike
2415 | TokenKind::KwGlob
2416 | TokenKind::KwMatch
2417 | TokenKind::KwRegexp => {
2418 let op = match &next.kind {
2419 TokenKind::KwLike => LikeOp::Like,
2420 TokenKind::KwGlob => LikeOp::Glob,
2421 TokenKind::KwMatch => LikeOp::Match,
2422 TokenKind::KwRegexp => LikeOp::Regexp,
2423 _ => unreachable!(),
2424 };
2425 self.controls.push(ParseControl::LikePatternDone {
2426 outer_min_bp: min_bp,
2427 lhs,
2428 op,
2429 not: true,
2430 });
2431 self.controls.push(ParseControl::ExprStart {
2432 min_bp: bp::EQUALITY.1,
2433 });
2434 }
2435 TokenKind::KwBetween => {
2436 self.controls.push(ParseControl::BetweenLowDone {
2437 outer_min_bp: min_bp,
2438 lhs,
2439 not: true,
2440 });
2441 self.controls.push(ParseControl::ExprStart {
2442 min_bp: bp::NOT_PREFIX,
2443 });
2444 }
2445 TokenKind::KwIn => self.start_in(lhs, true, min_bp)?,
2446 _ => {
2447 return Err(ParseError::at(
2448 format!(
2449 "expected LIKE/GLOB/MATCH/REGEXP/BETWEEN/IN after NOT, got {:?}",
2450 next.kind
2451 ),
2452 Some(&next),
2453 ));
2454 }
2455 }
2456 }
2457 other => {
2458 return Err(ParseError::at(
2459 format!("unexpected infix token: {other:?}"),
2460 Some(&token),
2461 ));
2462 }
2463 }
2464 Ok(())
2465 }
2466
2467 fn start_in(&mut self, lhs: ParsedExpr, not: bool, outer_min_bp: u8) -> Result<(), ParseError> {
2468 let start = lhs.expr.span();
2469 if !self.parser.eat_kind(&TokenKind::LeftParen) {
2470 let table = self.parser.parse_qualified_name()?;
2471 let end = self.parser.tokens[self.parser.pos.saturating_sub(1)].span;
2472 let height = lhs.height;
2473 let has_function = lhs.has_function;
2474 let parsed = self.parser.checked_expr(
2475 Expr::In {
2476 expr: Box::new(lhs.expr),
2477 set: InSet::Table(table),
2478 not,
2479 span: start.merge(end),
2480 },
2481 height,
2482 false,
2483 has_function,
2484 )?;
2485 let parsed = if not {
2486 self.parser.add_cached_parent(parsed)?
2487 } else {
2488 parsed
2489 };
2490 self.push_expr_tail(parsed, outer_min_bp);
2491 } else if matches!(
2492 self.parser.peek_kind(),
2493 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
2494 ) {
2495 self.controls.push(ParseControl::InSelectDone {
2496 outer_min_bp,
2497 lhs,
2498 not,
2499 start,
2500 });
2501 self.controls.push(ParseControl::SubqueryStart);
2502 } else if self.parser.at_kind(&TokenKind::RightParen) {
2503 let end = self.parser.expect_kind(&TokenKind::RightParen)?;
2504 self.finish_in_list(outer_min_bp, lhs, not, Vec::new(), start.merge(end))?;
2505 } else {
2506 self.controls.push(ParseControl::InItemDone {
2507 outer_min_bp,
2508 lhs,
2509 not,
2510 items: Vec::new(),
2511 start,
2512 });
2513 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2514 }
2515 Ok(())
2516 }
2517
2518 fn finish_case(
2519 &mut self,
2520 outer_min_bp: u8,
2521 build: CaseBuild,
2522 else_expr: Option<ParsedExpr>,
2523 ) -> Result<(), ParseError> {
2524 if !self.parser.eat_kind(&TokenKind::KwEnd) {
2525 return Err(self.parser.err_here("expected END for CASE expression"));
2526 }
2527 let end = self.parser.tokens[self.parser.pos.saturating_sub(1)].span;
2528 let mut height = build.operand.as_ref().map_or(0, |expr| expr.height);
2529 let mut is_constant = build.operand.as_ref().is_none_or(|expr| expr.is_constant);
2530 let mut has_function = build.operand.as_ref().is_some_and(|expr| expr.has_function);
2531 for (condition, result) in &build.whens {
2532 height = height.max(condition.height).max(result.height);
2533 is_constant &= condition.is_constant && result.is_constant;
2534 has_function |= condition.has_function || result.has_function;
2535 }
2536 if let Some(expr) = &else_expr {
2537 height = height.max(expr.height);
2538 is_constant &= expr.is_constant;
2539 has_function |= expr.has_function;
2540 }
2541 let parsed = self.parser.checked_expr(
2542 Expr::Case {
2543 operand: build.operand.map(|expr| Box::new(expr.expr)),
2544 whens: build
2545 .whens
2546 .into_iter()
2547 .map(|(condition, result)| (condition.expr, result.expr))
2548 .collect(),
2549 else_expr: else_expr.map(|expr| Box::new(expr.expr)),
2550 span: build.start.merge(end),
2551 },
2552 height,
2553 is_constant,
2554 has_function,
2555 )?;
2556 self.push_expr_tail(parsed, outer_min_bp);
2557 Ok(())
2558 }
2559
2560 fn finish_like(
2561 &mut self,
2562 outer_min_bp: u8,
2563 lhs: ParsedExpr,
2564 pattern: ParsedExpr,
2565 escape: Option<ParsedExpr>,
2566 op: LikeOp,
2567 not: bool,
2568 ) -> Result<(), ParseError> {
2569 let end = escape
2570 .as_ref()
2571 .map_or_else(|| pattern.expr.span(), |expr| expr.expr.span());
2572 let height = escape.as_ref().map_or_else(
2573 || lhs.height.max(pattern.height),
2574 |expr| lhs.height.max(pattern.height).max(expr.height),
2575 );
2576 let span = lhs.expr.span().merge(end);
2577 let parsed = self.parser.checked_expr(
2578 Expr::Like {
2579 expr: Box::new(lhs.expr),
2580 pattern: Box::new(pattern.expr),
2581 escape: escape.map(|expr| Box::new(expr.expr)),
2582 op,
2583 not,
2584 span,
2585 },
2586 height,
2587 false,
2588 true,
2589 )?;
2590 let parsed = if not {
2591 self.parser.add_cached_parent(parsed)?
2592 } else {
2593 parsed
2594 };
2595 self.push_expr_tail(parsed, outer_min_bp);
2596 Ok(())
2597 }
2598
2599 fn finish_in_list(
2600 &mut self,
2601 outer_min_bp: u8,
2602 lhs: ParsedExpr,
2603 not: bool,
2604 items: Vec<ParsedExpr>,
2605 span: Span,
2606 ) -> Result<(), ParseError> {
2607 if let Some(message) = vector_in_list_arity_error(&lhs.expr, &items) {
2608 return Err(self.parser.err_here(message));
2609 }
2610 let item_height = items.iter().map(|item| item.height).max().unwrap_or(0);
2611 let items_are_constant = items.iter().all(|item| item.is_constant);
2612 let item_has_function = items.iter().any(|item| item.has_function);
2613 let singleton_constant = matches!(items.as_slice(), [item] if item.is_constant)
2614 && lhs.root != CachedRoot::Vector;
2615 let singleton_subquery =
2616 matches!(items.as_slice(), [item] if item.root == CachedRoot::ScalarSubquery);
2617 let lhs_height = lhs.height;
2618 let lhs_is_constant = lhs.is_constant;
2619 let lhs_has_function = lhs.has_function;
2620 let expr = Expr::In {
2621 expr: Box::new(lhs.expr),
2622 set: InSet::List(items.into_iter().map(|item| item.expr).collect()),
2623 not,
2624 span,
2625 };
2626 let parsed = if item_height == 0 {
2627 if lhs_has_function {
2628 self.parser
2629 .finish_expr(expr, lhs_height.saturating_add(1), false, true)?
2630 } else {
2631 self.parser.finish_expr(expr, 1, true, false)?
2632 }
2633 } else {
2634 let cached_child_height = if singleton_constant {
2635 lhs_height.max(item_height.saturating_add(1))
2636 } else if singleton_subquery {
2637 lhs_height.max(item_height.saturating_sub(1))
2638 } else {
2639 lhs_height.max(item_height)
2640 };
2641 let parsed = self.parser.checked_expr(
2642 expr,
2643 cached_child_height,
2644 lhs_is_constant && items_are_constant,
2645 lhs_has_function || item_has_function,
2646 )?;
2647 if not {
2648 self.parser.add_cached_parent(parsed)?
2649 } else {
2650 parsed
2651 }
2652 };
2653 self.push_expr_tail(parsed, outer_min_bp);
2654 Ok(())
2655 }
2656
2657 fn window_start(&mut self) -> Result<(), ParseError> {
2658 let has_base_window = starts_window_base_name(self.parser.peek_kind());
2659 let build = WindowBuild {
2660 base_window: if has_base_window {
2661 Some(self.parser.parse_window_name()?)
2662 } else {
2663 None
2664 },
2665 partition_by: Vec::new(),
2666 order_by: Vec::new(),
2667 };
2668 if self.parser.eat_kind(&TokenKind::KwPartition) {
2669 self.parser.expect_kw(&TokenKind::KwBy)?;
2670 self.controls
2671 .push(ParseControl::WindowPartitionDone { build });
2672 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2673 } else {
2674 self.controls.push(ParseControl::WindowOrderStart { build });
2675 }
2676 Ok(())
2677 }
2678
2679 fn window_frame_start(&mut self, build: WindowBuild) {
2680 let frame_type = if self.parser.eat_kind(&TokenKind::KwRows) {
2681 Some(FrameType::Rows)
2682 } else if self.parser.eat_kind(&TokenKind::KwRange) {
2683 Some(FrameType::Range)
2684 } else if self.parser.eat_kind(&TokenKind::KwGroups) {
2685 Some(FrameType::Groups)
2686 } else {
2687 None
2688 };
2689 let Some(frame_type) = frame_type else {
2690 self.values.push(MachineValue::Window(WindowSpec {
2691 window_ref: build.base_window.map(WindowReference::Base),
2692 partition_by: build.partition_by,
2693 order_by: build.order_by,
2694 frame: None,
2695 }));
2696 return;
2697 };
2698 let between = self.parser.eat_kind(&TokenKind::KwBetween);
2699 self.controls.push(ParseControl::WindowFirstBoundDone {
2700 build,
2701 frame_type,
2702 between,
2703 });
2704 self.controls.push(ParseControl::FrameBoundStart);
2705 }
2706
2707 fn frame_bound_start(&mut self) -> Result<(), ParseError> {
2708 let origin = self
2709 .parser
2710 .peek_token()
2711 .cloned()
2712 .ok_or_else(|| self.parser.err_here("expected window frame bound"))?;
2713 if self.parser.eat_kind(&TokenKind::KwUnbounded) {
2714 let bound = if self.parser.eat_kind(&TokenKind::KwPreceding) {
2715 FrameBound::UnboundedPreceding
2716 } else {
2717 self.parser.expect_kw(&TokenKind::KwFollowing)?;
2718 FrameBound::UnboundedFollowing
2719 };
2720 self.values.push(MachineValue::FrameBound(ParsedFrameBound {
2721 value: bound,
2722 origin,
2723 }));
2724 } else if matches!(
2725 self.parser.peek_kind(),
2726 TokenKind::Id(value) if value.eq_ignore_ascii_case("CURRENT")
2727 ) {
2728 self.parser.advance_token();
2729 self.parser.expect_kw(&TokenKind::KwRow)?;
2730 self.values.push(MachineValue::FrameBound(ParsedFrameBound {
2731 value: FrameBound::CurrentRow,
2732 origin,
2733 }));
2734 } else {
2735 self.controls
2736 .push(ParseControl::FrameBoundExprDone { origin });
2737 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2738 }
2739 Ok(())
2740 }
2741
2742 fn finish_frame(
2743 &mut self,
2744 frame_type: FrameType,
2745 start: FrameBound,
2746 end: Option<FrameBound>,
2747 ) -> Result<FrameSpec, ParseError> {
2748 let exclude = if self.parser.eat_kind(&TokenKind::KwExclude) {
2749 if self.parser.eat_kind(&TokenKind::KwNo) {
2750 let others = self.parser.parse_identifier()?;
2751 if !others.eq_ignore_ascii_case("OTHERS") {
2752 return Err(self.parser.err_here("expected OTHERS"));
2753 }
2754 Some(FrameExclude::NoOthers)
2755 } else if self.parser.eat_kind(&TokenKind::KwTies) {
2756 Some(FrameExclude::Ties)
2757 } else if self.parser.eat_kind(&TokenKind::KwGroup) {
2758 Some(FrameExclude::Group)
2759 } else if matches!(
2760 self.parser.peek_kind(),
2761 TokenKind::Id(value) if value.eq_ignore_ascii_case("CURRENT")
2762 ) {
2763 self.parser.advance_token();
2764 self.parser.expect_kw(&TokenKind::KwRow)?;
2765 Some(FrameExclude::CurrentRow)
2766 } else {
2767 return Err(self
2768 .parser
2769 .err_here("expected NO OTHERS, TIES, GROUP, or CURRENT ROW after EXCLUDE"));
2770 }
2771 } else {
2772 None
2773 };
2774 Ok(FrameSpec {
2775 frame_type,
2776 start,
2777 end,
2778 exclude,
2779 })
2780 }
2781
2782 fn step_select(&mut self, control: ParseControl) -> Result<(), ParseError> {
2783 match control {
2784 ParseControl::SelectStart { with } => {
2785 self.controls
2786 .push(ParseControl::SelectFirstCoreDone { with });
2787 self.controls.push(ParseControl::CoreStart);
2788 Ok(())
2789 }
2790 ParseControl::SelectFirstCoreDone { with } => {
2791 let core = self.pop_core()?;
2792 self.continue_select_body(SelectBuild {
2793 with,
2794 height: core.height,
2795 first: core.value,
2796 compounds: Vec::new(),
2797 order_by: Vec::new(),
2798 });
2799 Ok(())
2800 }
2801 ParseControl::SelectCompoundDone { mut build, op } => {
2802 let core = self.pop_core()?;
2803 build.height = build.height.max(core.height);
2804 build.compounds.push((op, core.value));
2805 self.continue_select_body(build);
2806 Ok(())
2807 }
2808 ParseControl::SelectOrderStart { build } => {
2809 let final_core = build
2810 .compounds
2811 .last()
2812 .map_or(&build.first, |(_, core)| core);
2813 if matches!(final_core, SelectCore::Values(_))
2814 && matches!(
2815 self.parser.peek_kind(),
2816 TokenKind::KwOrder | TokenKind::KwLimit
2817 )
2818 {
2819 return Err(self
2820 .parser
2821 .err_here("ORDER BY / LIMIT clause is not allowed after a VALUES term"));
2822 }
2823 if self.parser.eat_kind(&TokenKind::KwOrder) {
2824 self.parser.expect_kw(&TokenKind::KwBy)?;
2825 self.controls.push(ParseControl::SelectOrderDone { build });
2826 self.controls.push(ParseControl::OrderingStart);
2827 } else {
2828 self.start_select_limit(build)?;
2829 }
2830 Ok(())
2831 }
2832 ParseControl::SelectOrderDone { mut build } => {
2833 let term = self.pop_ordering()?;
2834 build.height = build.height.max(term.height);
2835 build.order_by.push(term.value);
2836 if self.parser.eat_kind(&TokenKind::Comma) {
2837 self.controls.push(ParseControl::SelectOrderDone { build });
2838 self.controls.push(ParseControl::OrderingStart);
2839 } else {
2840 self.start_select_limit(build)?;
2841 }
2842 Ok(())
2843 }
2844 ParseControl::SelectLimitFirstDone { build } => {
2845 let first = self.pop_expr()?;
2846 if self.parser.eat_kind(&TokenKind::KwOffset) {
2847 self.controls.push(ParseControl::SelectLimitSecondDone {
2848 build,
2849 first,
2850 comma_form: false,
2851 });
2852 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2853 } else if self.parser.eat_kind(&TokenKind::Comma) {
2854 self.controls.push(ParseControl::SelectLimitSecondDone {
2855 build,
2856 first,
2857 comma_form: true,
2858 });
2859 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2860 } else {
2861 let height = self.parser.checked_cached_parent_height(first.height)?;
2862 self.finish_select(
2863 build,
2864 HeightTracked {
2865 value: Some(LimitClause {
2866 limit: first.expr,
2867 offset: None,
2868 }),
2869 height,
2870 },
2871 )?;
2872 }
2873 Ok(())
2874 }
2875 ParseControl::SelectLimitSecondDone {
2876 build,
2877 first,
2878 comma_form,
2879 } => {
2880 let second = self.pop_expr()?;
2881 let height = self
2882 .parser
2883 .checked_cached_parent_height(first.height.max(second.height))?;
2884 let limit = if comma_form {
2885 LimitClause {
2886 limit: second.expr,
2887 offset: Some(first.expr),
2888 }
2889 } else {
2890 LimitClause {
2891 limit: first.expr,
2892 offset: Some(second.expr),
2893 }
2894 };
2895 self.finish_select(
2896 build,
2897 HeightTracked {
2898 value: Some(limit),
2899 height,
2900 },
2901 )
2902 }
2903 ParseControl::CoreStart => self.core_start(),
2904 ParseControl::CoreColumnStart { build } => self.core_column_start(build),
2905 ParseControl::CoreColumnDone { mut build } => {
2906 let expr = self.pop_expr()?;
2907 build.height = build.height.max(expr.height);
2908 build.columns.push(ResultColumn::Expr {
2909 expr: expr.expr,
2910 alias: self.parser.try_result_alias()?,
2911 });
2912 if self.parser.eat_kind(&TokenKind::Comma) {
2913 self.controls.push(ParseControl::CoreColumnStart { build });
2914 } else {
2915 self.controls.push(ParseControl::CoreAfterColumns { build });
2916 }
2917 Ok(())
2918 }
2919 ParseControl::CoreAfterColumns { build } => {
2920 if self.parser.eat_kind(&TokenKind::KwFrom) {
2921 self.controls.push(ParseControl::CoreFromDone { build });
2922 self.controls.push(ParseControl::FromStart);
2923 } else {
2924 self.continue_core_where(build)?;
2925 }
2926 Ok(())
2927 }
2928 ParseControl::CoreFromDone { mut build } => {
2929 build.from = Some(self.pop_from()?);
2930 self.continue_core_where(build)
2931 }
2932 ParseControl::CoreWhereDone { mut build } => {
2933 let expr = self.pop_expr()?;
2934 build.height = build.height.max(expr.height);
2935 build.where_clause = Some(Box::new(expr.expr));
2936 self.continue_core_group(build)
2937 }
2938 ParseControl::CoreGroupDone { mut build } => {
2939 let expr = self.pop_expr()?;
2940 build.height = build.height.max(expr.height);
2941 build.group_by.push(expr.expr);
2942 if self.parser.eat_kind(&TokenKind::Comma) {
2943 self.controls.push(ParseControl::CoreGroupDone { build });
2944 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2945 } else {
2946 self.continue_core_having(build);
2947 }
2948 Ok(())
2949 }
2950 ParseControl::CoreHavingDone { mut build } => {
2951 let expr = self.pop_expr()?;
2952 build.height = build.height.max(expr.height);
2953 build.having = Some(Box::new(expr.expr));
2954 self.continue_core_windows(build);
2955 Ok(())
2956 }
2957 ParseControl::CoreWindowStart { build } => {
2958 let name = self.parser.parse_window_name()?;
2959 self.parser.expect_kw(&TokenKind::KwAs)?;
2960 self.parser.expect_token(&TokenKind::LeftParen)?;
2961 self.controls
2962 .push(ParseControl::CoreWindowDone { build, name });
2963 self.controls.push(ParseControl::WindowStart);
2964 Ok(())
2965 }
2966 ParseControl::CoreWindowDone { mut build, name } => {
2967 let spec = self.pop_window()?;
2968 self.parser.expect_token(&TokenKind::RightParen)?;
2969 build.windows.push(WindowDef { name, spec });
2970 if self.parser.eat_kind(&TokenKind::Comma) {
2971 self.controls.push(ParseControl::CoreWindowStart { build });
2972 } else {
2973 self.finish_core(build);
2974 }
2975 Ok(())
2976 }
2977 ParseControl::ValuesRowStart {
2978 rows,
2979 height,
2980 force_union_all_from,
2981 } => {
2982 self.parser.expect_token(&TokenKind::LeftParen)?;
2983 self.controls.push(ParseControl::ValuesItemDone {
2984 rows,
2985 row: Vec::new(),
2986 height,
2987 force_union_all_from,
2988 });
2989 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
2990 Ok(())
2991 }
2992 ParseControl::ValuesItemDone {
2993 mut rows,
2994 mut row,
2995 mut height,
2996 mut force_union_all_from,
2997 } => {
2998 let expr = self.pop_expr()?;
2999 height = height.max(expr.height);
3000 row.push(expr.expr);
3001 if self.parser.eat_kind(&TokenKind::Comma) {
3002 self.controls.push(ParseControl::ValuesItemDone {
3003 rows,
3004 row,
3005 height,
3006 force_union_all_from,
3007 });
3008 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3009 } else {
3010 self.parser.expect_token(&TokenKind::RightParen)?;
3011 if force_union_all_from.is_none() && self.parser.has_with {
3012 force_union_all_from = Some(rows.len());
3013 }
3014 rows.push(row);
3015 if self.parser.eat_kind(&TokenKind::Comma) {
3016 self.controls.push(ParseControl::ValuesRowStart {
3017 rows,
3018 height,
3019 force_union_all_from,
3020 });
3021 } else {
3022 self.values.push(MachineValue::Core(HeightTracked {
3023 value: SelectCore::Values(ValuesClause::parsed(
3024 rows,
3025 force_union_all_from,
3026 )),
3027 height,
3028 }));
3029 }
3030 }
3031 Ok(())
3032 }
3033 ParseControl::FromStart => {
3034 self.controls.push(ParseControl::FromSourceDone);
3035 self.controls.push(ParseControl::TableStart);
3036 Ok(())
3037 }
3038 ParseControl::FromSourceDone => {
3039 let source = self.pop_table()?;
3040 self.continue_from(FromBuild {
3041 source,
3042 joins: Vec::new(),
3043 })
3044 }
3045 ParseControl::FromTableDone { build, join_type } => {
3046 let table = self.pop_table()?;
3047 if self.parser.eat_kind(&TokenKind::KwOn) {
3048 self.controls.push(ParseControl::FromJoinConstraintDone {
3049 build,
3050 join_type,
3051 table,
3052 });
3053 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3054 return Ok(());
3055 }
3056 let constraint = if self.parser.eat_kind(&TokenKind::KwUsing) {
3057 self.parser.expect_token(&TokenKind::LeftParen)?;
3058 let mut columns = vec![self.parser.parse_identifier()?];
3059 while self.parser.eat_kind(&TokenKind::Comma) {
3060 columns.push(self.parser.parse_identifier()?);
3061 }
3062 self.parser.expect_token(&TokenKind::RightParen)?;
3063 Some(JoinConstraint::Using(columns))
3064 } else {
3065 None
3066 };
3067 self.append_join(build, join_type, table, constraint)
3068 }
3069 ParseControl::FromJoinConstraintDone {
3070 build,
3071 join_type,
3072 table,
3073 } => {
3074 let expr = self.pop_expr()?;
3075 self.append_join(build, join_type, table, Some(JoinConstraint::On(expr.expr)))
3076 }
3077 ParseControl::TableStart => self.table_start(),
3078 ParseControl::TableSubqueryDone => {
3079 let select = self.pop_select()?;
3080 self.parser.expect_token(&TokenKind::RightParen)?;
3081 self.values
3082 .push(MachineValue::Table(TableOrSubquery::Subquery {
3083 query: Box::new(select.value),
3084 alias: self.parser.try_table_alias()?,
3085 }));
3086 Ok(())
3087 }
3088 ParseControl::TableParenJoinDone => {
3089 let from = self.pop_from()?;
3090 self.parser.expect_token(&TokenKind::RightParen)?;
3091 self.values
3092 .push(MachineValue::Table(TableOrSubquery::ParenJoin(Box::new(
3093 from,
3094 ))));
3095 Ok(())
3096 }
3097 ParseControl::TableFunctionArgDone { name, mut args } => {
3098 args.push(self.pop_expr()?.expr);
3099 if self.parser.eat_kind(&TokenKind::Comma) {
3100 self.controls
3101 .push(ParseControl::TableFunctionArgDone { name, args });
3102 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3103 } else {
3104 self.parser.expect_token(&TokenKind::RightParen)?;
3105 self.values
3106 .push(MachineValue::Table(TableOrSubquery::TableFunction {
3107 name,
3108 args,
3109 alias: self.parser.try_table_alias()?,
3110 }));
3111 }
3112 Ok(())
3113 }
3114 ParseControl::WithStart => self.with_start(),
3115 ParseControl::CteQueryDone {
3116 recursive,
3117 mut ctes,
3118 name,
3119 columns,
3120 materialized,
3121 } => {
3122 let query = self.pop_select()?;
3123 self.parser.expect_token(&TokenKind::RightParen)?;
3124 ctes.push(Cte {
3125 name,
3126 columns,
3127 materialized,
3128 query: query.value,
3129 });
3130 if self.parser.eat_kind(&TokenKind::Comma) {
3131 self.start_cte(recursive, ctes)?;
3132 } else {
3133 self.values
3134 .push(MachineValue::With(WithClause { recursive, ctes }));
3135 }
3136 Ok(())
3137 }
3138 _ => Err(self
3139 .parser
3140 .err_here("internal expression parser control reached SELECT dispatcher")),
3141 }
3142 }
3143
3144 fn continue_select_body(&mut self, build: SelectBuild) {
3145 let op = if self.parser.eat_kind(&TokenKind::KwUnion) {
3146 Some(if self.parser.eat_kind(&TokenKind::KwAll) {
3147 CompoundOp::UnionAll
3148 } else {
3149 CompoundOp::Union
3150 })
3151 } else if self.parser.eat_kind(&TokenKind::KwIntersect) {
3152 Some(CompoundOp::Intersect)
3153 } else if self.parser.eat_kind(&TokenKind::KwExcept) {
3154 Some(CompoundOp::Except)
3155 } else {
3156 None
3157 };
3158 if let Some(op) = op {
3159 self.controls
3160 .push(ParseControl::SelectCompoundDone { build, op });
3161 self.controls.push(ParseControl::CoreStart);
3162 } else {
3163 self.controls.push(ParseControl::SelectOrderStart { build });
3164 }
3165 }
3166
3167 fn start_select_limit(&mut self, build: SelectBuild) -> Result<(), ParseError> {
3168 if self.parser.eat_kind(&TokenKind::KwLimit) {
3169 self.controls
3170 .push(ParseControl::SelectLimitFirstDone { build });
3171 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3172 } else {
3173 self.finish_select(
3174 build,
3175 HeightTracked {
3176 value: None,
3177 height: 0,
3178 },
3179 )?;
3180 }
3181 Ok(())
3182 }
3183
3184 fn finish_select(
3185 &mut self,
3186 mut build: SelectBuild,
3187 limit: HeightTracked<Option<LimitClause>>,
3188 ) -> Result<(), ParseError> {
3189 build.height = build.height.max(limit.height);
3190 let final_core = build
3191 .compounds
3192 .last()
3193 .map_or(&build.first, |(_, core)| core);
3194 if matches!(final_core, SelectCore::Values(_))
3195 && (!build.order_by.is_empty() || limit.value.is_some())
3196 {
3197 return Err(self
3198 .parser
3199 .err_here("ORDER BY / LIMIT clause is not allowed after a VALUES term"));
3200 }
3201 self.values.push(MachineValue::Select(HeightTracked {
3202 value: SelectStatement {
3203 with: build.with,
3204 body: SelectBody {
3205 select: build.first,
3206 compounds: build.compounds,
3207 },
3208 order_by: build.order_by,
3209 limit: limit.value,
3210 },
3211 height: build.height,
3212 }));
3213 Ok(())
3214 }
3215
3216 fn core_start(&mut self) -> Result<(), ParseError> {
3217 if self.parser.eat_kind(&TokenKind::KwValues) {
3218 self.controls.push(ParseControl::ValuesRowStart {
3219 rows: Vec::new(),
3220 height: 0,
3221 force_union_all_from: None,
3222 });
3223 return Ok(());
3224 }
3225 self.parser.expect_kw(&TokenKind::KwSelect)?;
3226 let distinct = if self.parser.eat_kind(&TokenKind::KwDistinct) {
3227 Distinctness::Distinct
3228 } else {
3229 let _ = self.parser.eat_kind(&TokenKind::KwAll);
3230 Distinctness::All
3231 };
3232 self.controls.push(ParseControl::CoreColumnStart {
3233 build: CoreBuild {
3234 distinct,
3235 columns: Vec::new(),
3236 height: 0,
3237 from: None,
3238 where_clause: None,
3239 group_by: Vec::new(),
3240 having: None,
3241 windows: Vec::new(),
3242 },
3243 });
3244 Ok(())
3245 }
3246
3247 fn core_column_start(&mut self, mut build: CoreBuild) -> Result<(), ParseError> {
3248 if self.parser.eat_kind(&TokenKind::Star) {
3249 build.columns.push(ResultColumn::Star);
3250 if self.parser.eat_kind(&TokenKind::Comma) {
3251 self.controls.push(ParseControl::CoreColumnStart { build });
3252 } else {
3253 self.controls.push(ParseControl::CoreAfterColumns { build });
3254 }
3255 return Ok(());
3256 }
3257 if starts_table_star_qualifier(self.parser.peek_kind())
3258 && self
3259 .parser
3260 .tokens
3261 .get(self.parser.pos + 1)
3262 .is_some_and(|token| token.kind == TokenKind::Dot)
3263 {
3264 let table_star = self
3265 .parser
3266 .tokens
3267 .get(self.parser.pos + 2)
3268 .is_some_and(|token| token.kind == TokenKind::Star);
3269 let schema_table_star = self
3270 .parser
3271 .tokens
3272 .get(self.parser.pos + 2)
3273 .is_some_and(|token| starts_table_star_qualifier(&token.kind))
3274 && self
3275 .parser
3276 .tokens
3277 .get(self.parser.pos + 3)
3278 .is_some_and(|token| token.kind == TokenKind::Dot)
3279 && self
3280 .parser
3281 .tokens
3282 .get(self.parser.pos + 4)
3283 .is_some_and(|token| token.kind == TokenKind::Star);
3284 if table_star || schema_table_star {
3285 let first = self.parser.parse_table_star_qualifier()?;
3286 self.parser.expect_token(&TokenKind::Dot)?;
3287 let name = if schema_table_star {
3288 let second = self.parser.parse_table_star_qualifier()?;
3289 self.parser.expect_token(&TokenKind::Dot)?;
3290 QualifiedName::qualified(first, second)
3291 } else {
3292 QualifiedName::bare(first)
3293 };
3294 self.parser.expect_token(&TokenKind::Star)?;
3295 build.columns.push(ResultColumn::TableStar(name));
3296 if self.parser.eat_kind(&TokenKind::Comma) {
3297 self.controls.push(ParseControl::CoreColumnStart { build });
3298 } else {
3299 self.controls.push(ParseControl::CoreAfterColumns { build });
3300 }
3301 return Ok(());
3302 }
3303 }
3304 self.controls.push(ParseControl::CoreColumnDone { build });
3305 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3306 Ok(())
3307 }
3308
3309 fn continue_core_where(&mut self, build: CoreBuild) -> Result<(), ParseError> {
3310 if self.parser.eat_kind(&TokenKind::KwWhere) {
3311 self.controls.push(ParseControl::CoreWhereDone { build });
3312 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3313 } else {
3314 self.continue_core_group(build)?;
3315 }
3316 Ok(())
3317 }
3318
3319 fn continue_core_group(&mut self, build: CoreBuild) -> Result<(), ParseError> {
3320 if self.parser.eat_kind(&TokenKind::KwGroup) {
3321 self.parser.expect_kw(&TokenKind::KwBy)?;
3322 self.controls.push(ParseControl::CoreGroupDone { build });
3323 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3324 } else {
3325 self.continue_core_having(build);
3326 }
3327 Ok(())
3328 }
3329
3330 fn continue_core_having(&mut self, build: CoreBuild) {
3331 if self.parser.eat_kind(&TokenKind::KwHaving) {
3332 self.controls.push(ParseControl::CoreHavingDone { build });
3333 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3334 } else {
3335 self.continue_core_windows(build);
3336 }
3337 }
3338
3339 fn continue_core_windows(&mut self, build: CoreBuild) {
3340 if self.parser.eat_kind(&TokenKind::KwWindow) {
3341 self.controls.push(ParseControl::CoreWindowStart { build });
3342 } else {
3343 self.finish_core(build);
3344 }
3345 }
3346
3347 fn finish_core(&mut self, build: CoreBuild) {
3348 self.values.push(MachineValue::Core(HeightTracked {
3349 value: SelectCore::Select {
3350 distinct: build.distinct,
3351 columns: build.columns,
3352 from: build.from,
3353 where_clause: build.where_clause,
3354 group_by: build.group_by,
3355 having: build.having,
3356 windows: build.windows,
3357 },
3358 height: build.height,
3359 }));
3360 }
3361
3362 fn continue_from(&mut self, build: FromBuild) -> Result<(), ParseError> {
3363 let join_type = if let Some(join_type) = self.parser.try_join_type()? {
3364 Some(join_type)
3365 } else if self.parser.eat_kind(&TokenKind::Comma) {
3366 Some(JoinType {
3367 natural: false,
3368 kind: JoinKind::Cross,
3369 })
3370 } else {
3371 None
3372 };
3373 if let Some(join_type) = join_type {
3374 self.controls
3375 .push(ParseControl::FromTableDone { build, join_type });
3376 self.controls.push(ParseControl::TableStart);
3377 } else {
3378 self.values.push(MachineValue::From(FromClause {
3379 source: build.source,
3380 joins: build.joins,
3381 }));
3382 }
3383 Ok(())
3384 }
3385
3386 fn append_join(
3387 &mut self,
3388 mut build: FromBuild,
3389 join_type: JoinType,
3390 table: TableOrSubquery,
3391 constraint: Option<JoinConstraint>,
3392 ) -> Result<(), ParseError> {
3393 if join_type.natural && constraint.is_some() {
3394 return Err(self
3395 .parser
3396 .err_here("a NATURAL join may not have an ON or USING clause"));
3397 }
3398 build.joins.push(JoinClause {
3399 join_type,
3400 table,
3401 constraint,
3402 });
3403 self.continue_from(build)
3404 }
3405
3406 fn table_start(&mut self) -> Result<(), ParseError> {
3407 if self.parser.eat_kind(&TokenKind::LeftParen) {
3408 if matches!(
3409 self.parser.peek_kind(),
3410 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
3411 ) {
3412 self.controls.push(ParseControl::TableSubqueryDone);
3413 self.controls.push(ParseControl::SubqueryStart);
3414 } else {
3415 self.controls.push(ParseControl::TableParenJoinDone);
3416 self.controls.push(ParseControl::FromStart);
3417 }
3418 return Ok(());
3419 }
3420 let name = self.parser.parse_qualified_name()?;
3421 if name.schema.is_none() && self.parser.eat_kind(&TokenKind::LeftParen) {
3422 if self.parser.eat_kind(&TokenKind::RightParen) {
3423 self.values
3424 .push(MachineValue::Table(TableOrSubquery::TableFunction {
3425 name: name.name,
3426 args: Vec::new(),
3427 alias: self.parser.try_table_alias()?,
3428 }));
3429 } else {
3430 self.controls.push(ParseControl::TableFunctionArgDone {
3431 name: name.name,
3432 args: Vec::new(),
3433 });
3434 self.controls.push(ParseControl::ExprStart { min_bp: 0 });
3435 }
3436 return Ok(());
3437 }
3438 self.values
3439 .push(MachineValue::Table(TableOrSubquery::Table {
3440 name,
3441 alias: self.parser.try_table_alias()?,
3442 index_hint: self.parser.parse_index_hint()?,
3443 time_travel: self.parser.parse_time_travel_clause()?,
3444 }));
3445 Ok(())
3446 }
3447
3448 fn with_start(&mut self) -> Result<(), ParseError> {
3449 self.parser.expect_kw(&TokenKind::KwWith)?;
3450 self.parser.has_with = true;
3451 let recursive = self.parser.eat_kind(&TokenKind::KwRecursive);
3452 self.start_cte(recursive, Vec::new())
3453 }
3454
3455 fn start_cte(&mut self, recursive: bool, ctes: Vec<Cte>) -> Result<(), ParseError> {
3456 let name = self.parser.parse_identifier()?;
3457 let columns = if self.parser.eat_kind(&TokenKind::LeftParen) {
3458 let mut columns = vec![self.parser.parse_identifier()?];
3459 while self.parser.eat_kind(&TokenKind::Comma) {
3460 columns.push(self.parser.parse_identifier()?);
3461 }
3462 self.parser.expect_token(&TokenKind::RightParen)?;
3463 columns
3464 } else {
3465 Vec::new()
3466 };
3467 self.parser.expect_kw(&TokenKind::KwAs)?;
3468 let materialized = if self.parser.eat_kind(&TokenKind::KwNot) {
3469 self.parser.expect_kw(&TokenKind::KwMaterialized)?;
3470 Some(CteMaterialized::NotMaterialized)
3471 } else if self.parser.eat_kind(&TokenKind::KwMaterialized) {
3472 Some(CteMaterialized::Materialized)
3473 } else {
3474 None
3475 };
3476 self.parser.expect_token(&TokenKind::LeftParen)?;
3477 self.controls.push(ParseControl::CteQueryDone {
3478 recursive,
3479 ctes,
3480 name,
3481 columns,
3482 materialized,
3483 });
3484 self.controls.push(ParseControl::SubqueryStart);
3485 Ok(())
3486 }
3487}
3488
3489impl Parser {
3490 pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
3492 self.parse_expr_tracked().map(|parsed| parsed.expr)
3493 }
3494
3495 pub(crate) fn parse_expr_tracked(&mut self) -> Result<ParsedExpr, ParseError> {
3496 ParseMachine::for_expr(self).run_expr()
3497 }
3498
3499 pub(crate) fn parse_select_tracked_machine(
3500 &mut self,
3501 with: Option<WithClause>,
3502 ) -> Result<HeightTracked<SelectStatement>, ParseError> {
3503 ParseMachine::for_select(self, with).run_select()
3504 }
3505
3506 pub(crate) fn parse_with_clause_machine(&mut self) -> Result<WithClause, ParseError> {
3507 ParseMachine::for_with(self).run_with()
3508 }
3509
3510 pub(crate) fn parse_from_clause_machine(&mut self) -> Result<FromClause, ParseError> {
3511 ParseMachine::for_from(self).run_from()
3512 }
3513
3514 fn finish_expr(
3515 &self,
3516 expr: Expr,
3517 height: u32,
3518 is_constant: bool,
3519 has_function: bool,
3520 ) -> Result<ParsedExpr, ParseError> {
3521 if height > MAX_PARSE_DEPTH {
3522 return Err(ParseError::expression_too_deep(
3523 MAX_PARSE_DEPTH,
3524 self.peek_token(),
3525 ));
3526 }
3527 let root = match &expr {
3528 Expr::UnaryOp {
3529 op: UnaryOp::Plus, ..
3530 } => CachedRoot::UnaryPlus,
3531 Expr::RowValue(..) => CachedRoot::Vector,
3532 Expr::Subquery(..) => CachedRoot::ScalarSubquery,
3533 _ => CachedRoot::Other,
3534 };
3535 Ok(ParsedExpr {
3536 expr,
3537 height,
3538 is_constant,
3539 has_function,
3540 root,
3541 })
3542 }
3543
3544 fn checked_expr(
3545 &self,
3546 expr: Expr,
3547 max_child_height: u32,
3548 is_constant: bool,
3549 has_function: bool,
3550 ) -> Result<ParsedExpr, ParseError> {
3551 let height = max_child_height.saturating_add(1);
3552 self.finish_expr(expr, height, is_constant, has_function)
3553 }
3554
3555 fn add_cached_parent(&self, mut parsed: ParsedExpr) -> Result<ParsedExpr, ParseError> {
3556 parsed.height = parsed.height.saturating_add(1);
3557 if parsed.height > MAX_PARSE_DEPTH {
3558 return Err(ParseError::expression_too_deep(
3559 MAX_PARSE_DEPTH,
3560 self.peek_token(),
3561 ));
3562 }
3563 parsed.root = CachedRoot::Other;
3564 Ok(parsed)
3565 }
3566
3567 fn finish_unary(
3568 &self,
3569 op: UnaryOp,
3570 mut inner: ParsedExpr,
3571 span: Span,
3572 ) -> Result<ParsedExpr, ParseError> {
3573 if matches!(op, UnaryOp::Plus | UnaryOp::Negate)
3574 && inner.root == CachedRoot::UnaryPlus
3575 && let Expr::UnaryOp {
3576 op: inner_op,
3577 span: inner_span,
3578 ..
3579 } = &mut inner.expr
3580 {
3581 *inner_op = op;
3582 *inner_span = span;
3583 inner.root = if op == UnaryOp::Plus {
3584 CachedRoot::UnaryPlus
3585 } else {
3586 CachedRoot::Other
3587 };
3588 return Ok(inner);
3589 }
3590
3591 let height = inner.height;
3592 let is_constant = inner.is_constant;
3593 let has_function = inner.has_function;
3594 self.checked_expr(
3595 Expr::UnaryOp {
3596 op,
3597 expr: Box::new(inner.expr),
3598 span,
3599 },
3600 height,
3601 is_constant,
3602 has_function,
3603 )
3604 }
3605
3606 #[cfg(test)]
3609 fn parse_expr_bp(&mut self, min_bp: u8) -> Result<ParsedExpr, ParseError> {
3610 self.with_recursion_guard(|p| p.parse_expr_bp_inner(min_bp))
3611 }
3612
3613 #[cfg(test)]
3614 fn parse_expr_bp_inner(&mut self, min_bp: u8) -> Result<ParsedExpr, ParseError> {
3615 let prefixes = self.collect_prefix_frames();
3616 let mut lhs = self.parse_prefix()?;
3617
3618 for prefix in prefixes.into_iter().rev() {
3619 match prefix {
3620 DeepExprFrame::Unary { op, span, right_bp } => {
3621 lhs = self.parse_expr_tail(lhs, right_bp)?;
3622 let span = span.merge(lhs.expr.span());
3623 lhs = self.finish_unary(op, lhs, span)?;
3624 }
3625 DeepExprFrame::Parenthesis { span } => {
3626 lhs = self.finish_parenthesized_frame(lhs, span)?;
3627 }
3628 }
3629 }
3630
3631 self.parse_expr_tail(lhs, min_bp)
3632 }
3633
3634 #[cfg(test)]
3635 fn parse_expr_tail(
3636 &mut self,
3637 mut lhs: ParsedExpr,
3638 min_bp: u8,
3639 ) -> Result<ParsedExpr, ParseError> {
3640 loop {
3641 if let Some(l_bp) = self.postfix_bp() {
3643 if l_bp < min_bp {
3644 break;
3645 }
3646 lhs = self.parse_postfix(lhs)?;
3647 continue;
3648 }
3649
3650 if let Some((l_bp, r_bp)) = self.infix_bp() {
3652 if l_bp < min_bp {
3653 break;
3654 }
3655 lhs = self.parse_infix(lhs, r_bp)?;
3656 continue;
3657 }
3658
3659 break;
3660 }
3661
3662 Ok(lhs)
3663 }
3664
3665 #[cfg(test)]
3666 fn collect_prefix_frames(&mut self) -> Vec<DeepExprFrame> {
3667 let mut prefixes = Vec::new();
3668 loop {
3669 let unary = match self.peek_kind() {
3670 TokenKind::Minus => {
3671 let folds_i64_min = matches!(
3672 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3673 Some(TokenKind::OversizedInt(value)) if value == "9223372036854775808"
3674 );
3675 if folds_i64_min {
3676 break;
3677 }
3678 Some((UnaryOp::Negate, bp::UNARY))
3679 }
3680 TokenKind::Plus => Some((UnaryOp::Plus, bp::UNARY)),
3681 TokenKind::Tilde => Some((UnaryOp::BitNot, bp::UNARY)),
3682 TokenKind::KwNot => {
3683 if matches!(
3684 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3685 Some(TokenKind::KwExists)
3686 ) {
3687 break;
3688 }
3689 Some((UnaryOp::Not, bp::NOT_PREFIX))
3690 }
3691 TokenKind::LeftParen => {
3692 let starts_subquery = matches!(
3693 self.tokens.get(self.pos + 1).map(|token| &token.kind),
3694 Some(TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues)
3695 );
3696 if starts_subquery {
3697 break;
3698 }
3699 let token = self.advance_token();
3700 prefixes.push(DeepExprFrame::Parenthesis { span: token.span });
3701 continue;
3702 }
3703 _ => break,
3704 };
3705 let Some((op, right_bp)) = unary else {
3706 break;
3707 };
3708 let token = self.advance_token();
3709 prefixes.push(DeepExprFrame::Unary {
3710 op,
3711 span: token.span,
3712 right_bp,
3713 });
3714 }
3715 prefixes
3716 }
3717
3718 #[cfg(test)]
3719 fn finish_parenthesized_frame(
3720 &mut self,
3721 mut first: ParsedExpr,
3722 start: Span,
3723 ) -> Result<ParsedExpr, ParseError> {
3724 first = self.parse_expr_tail(first, 0)?;
3725 if self.eat_kind(&TokenKind::Comma) {
3726 let mut is_constant = first.is_constant;
3727 let mut has_function = first.has_function;
3728 let mut exprs = vec![first.expr];
3729 loop {
3730 let parsed = self.parse_expr_bp(0)?;
3731 is_constant &= parsed.is_constant;
3732 has_function |= parsed.has_function;
3733 exprs.push(parsed.expr);
3734 if !self.eat_kind(&TokenKind::Comma) {
3735 break;
3736 }
3737 }
3738 let end = self.expect_kind(&TokenKind::RightParen)?;
3739 return self.finish_expr(
3740 Expr::RowValue(exprs, start.merge(end)),
3741 1,
3742 is_constant,
3743 has_function,
3744 );
3745 }
3746 self.expect_kind(&TokenKind::RightParen)?;
3747 Ok(first)
3748 }
3749
3750 fn peek_kind(&self) -> &TokenKind {
3753 self.tokens
3754 .get(self.pos)
3755 .map_or(&TokenKind::Eof, |t| &t.kind)
3756 }
3757
3758 fn peek_token(&self) -> Option<&Token> {
3759 self.tokens.get(self.pos)
3760 }
3761
3762 #[cfg(test)]
3763 fn peek_nth_token(&self, offset: usize) -> Option<&Token> {
3764 self.tokens.get(self.pos + offset)
3765 }
3766
3767 fn advance_token(&mut self) -> Token {
3768 let tok = self.tokens[self.pos].clone();
3769 if tok.kind != TokenKind::Eof {
3770 self.pos += 1;
3771 }
3772 tok
3773 }
3774
3775 fn at_kind(&self, kind: &TokenKind) -> bool {
3776 std::mem::discriminant(self.peek_kind()) == std::mem::discriminant(kind)
3777 }
3778
3779 fn eat_kind(&mut self, kind: &TokenKind) -> bool {
3780 if self.at_kind(kind) {
3781 self.advance_token();
3782 true
3783 } else {
3784 false
3785 }
3786 }
3787
3788 fn expect_kind(&mut self, expected: &TokenKind) -> Result<Span, ParseError> {
3789 if self.at_kind(expected) {
3790 Ok(self.advance_token().span)
3791 } else {
3792 Err(self.err_here(format!("expected {expected:?}, got {:?}", self.peek_kind())))
3793 }
3794 }
3795
3796 fn err_here(&self, message: impl Into<String>) -> ParseError {
3797 ParseError::at(message, self.peek_token())
3798 }
3799
3800 #[cfg(test)]
3803 #[allow(clippy::too_many_lines)]
3804 fn parse_prefix(&mut self) -> Result<ParsedExpr, ParseError> {
3805 let Token {
3806 kind,
3807 span: token_span,
3808 line,
3809 col,
3810 } = self.advance_token();
3811 if self.at_kind(&TokenKind::Dot) && starts_table_star_qualifier(&kind) {
3812 let name = match &kind {
3813 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => Arc::clone(name),
3814 TokenKind::String(name) => Arc::<str>::from(name.as_str()),
3815 keyword => Arc::<str>::from(kw_to_str(keyword)),
3816 };
3817 return self.parse_ident_expr(name, token_span);
3818 }
3819 match kind {
3820 TokenKind::Integer(i) => Ok(ParsedExpr::leaf(Expr::Literal(
3822 Literal::Integer(i),
3823 token_span,
3824 ))),
3825 TokenKind::OversizedInt(s) => match s.parse::<f64>() {
3829 Ok(v) => Ok(ParsedExpr::leaf(Expr::Literal(
3830 Literal::Float(v),
3831 token_span,
3832 ))),
3833 Err(_) => Err(ParseError {
3834 kind: crate::parser::ParseErrorKind::Syntax,
3835 message: "integer out of range".to_owned(),
3836 span: token_span,
3837 line,
3838 col,
3839 }),
3840 },
3841 TokenKind::Float(f) => Ok(ParsedExpr::leaf(Expr::Literal(
3842 Literal::Float(f),
3843 token_span,
3844 ))),
3845 TokenKind::String(s) if matches!(self.peek_kind(), TokenKind::Dot) => {
3846 self.parse_ident_expr(s, token_span)
3847 }
3848 TokenKind::String(s) => Ok(ParsedExpr::leaf(Expr::Literal(
3849 Literal::String(s),
3850 token_span,
3851 ))),
3852 TokenKind::Blob(b) => Ok(ParsedExpr::leaf(Expr::Literal(
3853 Literal::Blob(b),
3854 token_span,
3855 ))),
3856 TokenKind::KwNull => Ok(ParsedExpr::leaf(Expr::Literal(Literal::Null, token_span))),
3857 TokenKind::KwTrue => Ok(ParsedExpr::leaf(Expr::Literal(Literal::True, token_span))),
3858 TokenKind::KwFalse => Ok(ParsedExpr::leaf(Expr::Literal(Literal::False, token_span))),
3859 TokenKind::KwCurrentTime => Ok(ParsedExpr::leaf(Expr::Literal(
3860 Literal::CurrentTime,
3861 token_span,
3862 ))),
3863 TokenKind::KwCurrentDate => Ok(ParsedExpr::leaf(Expr::Literal(
3864 Literal::CurrentDate,
3865 token_span,
3866 ))),
3867 TokenKind::KwCurrentTimestamp => Ok(ParsedExpr::leaf(Expr::Literal(
3868 Literal::CurrentTimestamp,
3869 token_span,
3870 ))),
3871
3872 TokenKind::Question => Ok(ParsedExpr::leaf(Expr::Placeholder(
3874 PlaceholderType::Anonymous,
3875 token_span,
3876 ))),
3877 TokenKind::QuestionNum(n) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3878 PlaceholderType::Numbered(n),
3879 token_span,
3880 ))),
3881 TokenKind::ColonParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3882 PlaceholderType::ColonNamed(s),
3883 token_span,
3884 ))),
3885 TokenKind::AtParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3886 PlaceholderType::AtNamed(s),
3887 token_span,
3888 ))),
3889 TokenKind::DollarParam(s) => Ok(ParsedExpr::leaf(Expr::Placeholder(
3890 PlaceholderType::DollarNamed(s),
3891 token_span,
3892 ))),
3893
3894 TokenKind::Minus => {
3896 if let TokenKind::OversizedInt(s) = self.peek_kind()
3900 && s == "9223372036854775808"
3901 {
3902 let num_span = self.advance_token().span;
3903 let span = token_span.merge(num_span);
3904 return self.finish_expr(
3905 Expr::Literal(Literal::Integer(i64::MIN), span),
3906 1,
3907 true,
3908 false,
3909 );
3910 }
3911 let inner = self.parse_expr_bp(bp::UNARY)?;
3912 let span = token_span.merge(inner.expr.span());
3913 self.finish_unary(UnaryOp::Negate, inner, span)
3914 }
3915 TokenKind::Plus => {
3916 let inner = self.parse_expr_bp(bp::UNARY)?;
3917 let span = token_span.merge(inner.expr.span());
3918 self.finish_unary(UnaryOp::Plus, inner, span)
3919 }
3920 TokenKind::Tilde => {
3921 let inner = self.parse_expr_bp(bp::UNARY)?;
3922 let span = token_span.merge(inner.expr.span());
3923 self.finish_unary(UnaryOp::BitNot, inner, span)
3924 }
3925
3926 TokenKind::KwNot => {
3928 if matches!(self.peek_kind(), TokenKind::KwExists) {
3930 self.advance_token();
3931 self.expect_kind(&TokenKind::LeftParen)?;
3932 let subquery = self.parse_subquery_minimal()?;
3933 let end = self.expect_kind(&TokenKind::RightParen)?;
3934 let span = token_span.merge(end);
3935 let height = subquery.height;
3936 let exists = self.checked_expr(
3937 Expr::Exists {
3938 subquery: Box::new(subquery.value),
3939 not: true,
3940 span,
3941 },
3942 height,
3943 false,
3944 false,
3945 )?;
3946 return self.add_cached_parent(exists);
3947 }
3948 let inner = self.parse_expr_bp(bp::NOT_PREFIX)?;
3949 let span = token_span.merge(inner.expr.span());
3950 self.finish_unary(UnaryOp::Not, inner, span)
3951 }
3952
3953 TokenKind::KwExists => {
3955 self.expect_kind(&TokenKind::LeftParen)?;
3956 let subquery = self.parse_subquery_minimal()?;
3957 let end = self.expect_kind(&TokenKind::RightParen)?;
3958 let span = token_span.merge(end);
3959 let height = subquery.height;
3960 self.checked_expr(
3961 Expr::Exists {
3962 subquery: Box::new(subquery.value),
3963 not: false,
3964 span,
3965 },
3966 height,
3967 false,
3968 false,
3969 )
3970 }
3971
3972 TokenKind::KwCast => {
3974 self.expect_kind(&TokenKind::LeftParen)?;
3975 let inner = self.parse_expr_bp(0)?;
3976 self.expect_kind(&TokenKind::KwAs)?;
3977 let type_name = self.parse_type_name()?;
3978 let end = self.expect_kind(&TokenKind::RightParen)?;
3979 let span = token_span.merge(end);
3980 let height = inner.height;
3981 let is_constant = inner.is_constant;
3982 let has_function = inner.has_function;
3983 self.checked_expr(
3984 Expr::Cast {
3985 expr: Box::new(inner.expr),
3986 type_name,
3987 span,
3988 },
3989 height,
3990 is_constant,
3991 has_function,
3992 )
3993 }
3994
3995 TokenKind::KwCase => self.parse_case_expr(token_span),
3997
3998 TokenKind::KwRaise => {
4000 self.expect_kind(&TokenKind::LeftParen)?;
4001 let (action, message) = self.parse_raise_args()?;
4002 let end = self.expect_kind(&TokenKind::RightParen)?;
4003 let span = token_span.merge(end);
4004 Ok(ParsedExpr::leaf(Expr::Raise {
4005 action,
4006 message,
4007 span,
4008 }))
4009 }
4010
4011 TokenKind::LeftParen => {
4013 if matches!(
4014 self.peek_kind(),
4015 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
4016 ) {
4017 let subquery = self.parse_subquery_minimal()?;
4018 let end = self.expect_kind(&TokenKind::RightParen)?;
4019 let span = token_span.merge(end);
4020 return self.checked_expr(
4021 Expr::Subquery(Box::new(subquery.value), span),
4022 subquery.height,
4023 false,
4024 false,
4025 );
4026 }
4027 let first = self.parse_expr_bp(0)?;
4028 if self.eat_kind(&TokenKind::Comma) {
4029 let mut is_constant = first.is_constant;
4030 let mut has_function = first.has_function;
4031 let mut exprs = vec![first.expr];
4032 loop {
4033 let parsed = self.parse_expr_bp(0)?;
4034 is_constant &= parsed.is_constant;
4035 has_function |= parsed.has_function;
4036 exprs.push(parsed.expr);
4037 if !self.eat_kind(&TokenKind::Comma) {
4038 break;
4039 }
4040 }
4041 let end = self.expect_kind(&TokenKind::RightParen)?;
4042 let span = token_span.merge(end);
4043 self.finish_expr(Expr::RowValue(exprs, span), 1, is_constant, has_function)
4044 } else {
4045 self.expect_kind(&TokenKind::RightParen)?;
4046 Ok(first)
4047 }
4048 }
4049
4050 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => {
4052 self.parse_ident_expr(name, token_span)
4053 }
4054
4055 TokenKind::KwReplace if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4057 self.parse_function_call("replace".to_owned(), token_span)
4058 }
4059 TokenKind::KwLike if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4065 self.parse_function_call("like".to_owned(), token_span)
4066 }
4067 TokenKind::KwGlob if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4068 self.parse_function_call("glob".to_owned(), token_span)
4069 }
4070 TokenKind::KwRegexp if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4071 self.parse_function_call("regexp".to_owned(), token_span)
4072 }
4073 TokenKind::KwMatch if matches!(self.peek_kind(), TokenKind::LeftParen) => {
4074 self.parse_function_call("match".to_owned(), token_span)
4075 }
4076
4077 k if is_nonreserved_kw(&k) => {
4081 let name = kw_to_str(&k);
4082 self.parse_ident_expr(name, token_span)
4083 }
4084
4085 kind => Err(ParseError {
4086 kind: crate::parser::ParseErrorKind::Syntax,
4087 message: format!("unexpected token in expression: {kind:?}"),
4088 span: token_span,
4089 line,
4090 col,
4091 }),
4092 }
4093 }
4094
4095 #[cfg(test)]
4097 fn parse_ident_expr<S>(&mut self, name: S, start: Span) -> Result<ParsedExpr, ParseError>
4098 where
4099 S: AsRef<str> + Into<Arc<str>>,
4100 {
4101 if matches!(self.peek_kind(), TokenKind::LeftParen) {
4103 return self.parse_function_call(name.as_ref().to_owned(), start);
4104 }
4105 let name = name.into();
4106 if matches!(self.peek_kind(), TokenKind::Dot) {
4108 let Some(col_tok) = self.peek_nth_token(1) else {
4109 return Err(self.err_here("expected column name after '.'"));
4110 };
4111 let col_name = match &col_tok.kind {
4112 TokenKind::Id(c) | TokenKind::QuotedId(c, _) => Arc::clone(c),
4113 TokenKind::String(c) => Arc::<str>::from(c.as_str()),
4114 k if starts_post_dot_identifier(k) => Arc::<str>::from(kw_to_str(k)),
4115 _ => {
4116 return Err(ParseError::at(
4117 format!("expected column name after '.', got {:?}", col_tok.kind),
4118 Some(col_tok),
4119 ));
4120 }
4121 };
4122 let span = start.merge(col_tok.span);
4123 self.pos = self.pos.saturating_add(2);
4124 return self.finish_expr(
4125 Expr::Column(ColumnRef::qualified(name, col_name), span),
4126 2,
4127 false,
4128 false,
4129 );
4130 }
4131 Ok(ParsedExpr::leaf(Expr::Column(ColumnRef::bare(name), start)))
4132 }
4133
4134 fn postfix_bp(&self) -> Option<u8> {
4137 match self.peek_kind() {
4138 TokenKind::KwCollate => Some(bp::COLLATE),
4139 TokenKind::KwIsnull | TokenKind::KwNotnull => Some(bp::EQUALITY.0),
4140 TokenKind::KwNot => {
4141 if let Some(next) = self.tokens.get(self.pos + 1)
4142 && matches!(next.kind, TokenKind::KwNull)
4143 {
4144 return Some(bp::EQUALITY.0);
4145 }
4146 None
4147 }
4148 _ => None,
4149 }
4150 }
4151
4152 fn parse_postfix(&mut self, lhs: ParsedExpr) -> Result<ParsedExpr, ParseError> {
4153 let tok = self.advance_token();
4154 match &tok.kind {
4155 TokenKind::KwCollate => {
4156 let collation = match self.parse_identifier() {
4157 Ok(s) => s,
4158 Err(_) => {
4159 return Err(self.err_here("expected collation name after COLLATE"));
4160 }
4161 };
4162 let name_span = self.tokens[self.pos.saturating_sub(1)].span;
4163 let span = lhs.expr.span().merge(name_span);
4164 let height = lhs.height;
4165 let is_constant = lhs.is_constant;
4166 let has_function = lhs.has_function;
4167 self.checked_expr(
4168 Expr::Collate {
4169 expr: Box::new(lhs.expr),
4170 collation,
4171 span,
4172 },
4173 height,
4174 is_constant,
4175 has_function,
4176 )
4177 }
4178 TokenKind::KwIsnull => {
4179 let span = lhs.expr.span().merge(tok.span);
4180 let height = lhs.height;
4181 let is_constant = lhs.is_constant;
4182 let has_function = lhs.has_function;
4183 self.checked_expr(
4184 Expr::IsNull {
4185 expr: Box::new(lhs.expr),
4186 not: false,
4187 span,
4188 },
4189 height,
4190 is_constant,
4191 has_function,
4192 )
4193 }
4194 TokenKind::KwNotnull => {
4195 let span = lhs.expr.span().merge(tok.span);
4196 let height = lhs.height;
4197 let is_constant = lhs.is_constant;
4198 let has_function = lhs.has_function;
4199 self.checked_expr(
4200 Expr::IsNull {
4201 expr: Box::new(lhs.expr),
4202 not: true,
4203 span,
4204 },
4205 height,
4206 is_constant,
4207 has_function,
4208 )
4209 }
4210 TokenKind::KwNot => {
4211 let null_tok = self.advance_token(); let span = lhs.expr.span().merge(null_tok.span);
4213 let height = lhs.height;
4214 let is_constant = lhs.is_constant;
4215 let has_function = lhs.has_function;
4216 self.checked_expr(
4217 Expr::IsNull {
4218 expr: Box::new(lhs.expr),
4219 not: true,
4220 span,
4221 },
4222 height,
4223 is_constant,
4224 has_function,
4225 )
4226 }
4227 other => Err(ParseError::at(
4228 format!("unexpected postfix token: {other:?}"),
4229 Some(&tok),
4230 )),
4231 }
4232 }
4233
4234 fn infix_bp(&self) -> Option<(u8, u8)> {
4237 match self.peek_kind() {
4238 TokenKind::KwOr => Some(bp::OR),
4239 TokenKind::KwAnd => Some(bp::AND),
4240
4241 TokenKind::Eq
4242 | TokenKind::EqEq
4243 | TokenKind::Ne
4244 | TokenKind::LtGt
4245 | TokenKind::KwIs
4246 | TokenKind::KwLike
4247 | TokenKind::KwGlob
4248 | TokenKind::KwMatch
4249 | TokenKind::KwRegexp
4250 | TokenKind::KwBetween
4251 | TokenKind::KwIn => Some(bp::EQUALITY),
4252
4253 TokenKind::KwNot => {
4255 let next = self.tokens.get(self.pos + 1).map(|t| &t.kind);
4256 match next {
4257 Some(
4258 TokenKind::KwLike
4259 | TokenKind::KwGlob
4260 | TokenKind::KwMatch
4261 | TokenKind::KwRegexp
4262 | TokenKind::KwBetween
4263 | TokenKind::KwIn,
4264 ) => Some(bp::EQUALITY),
4265 _ => None,
4266 }
4267 }
4268
4269 TokenKind::Lt | TokenKind::Le | TokenKind::Gt | TokenKind::Ge => Some(bp::COMPARISON),
4270
4271 TokenKind::Ampersand
4272 | TokenKind::Pipe
4273 | TokenKind::ShiftLeft
4274 | TokenKind::ShiftRight => Some(bp::BITWISE),
4275
4276 TokenKind::Plus | TokenKind::Minus => Some(bp::ADD),
4277 TokenKind::Star | TokenKind::Slash | TokenKind::Percent => Some(bp::MUL),
4278 TokenKind::Concat => Some(bp::CONCAT),
4279 TokenKind::Arrow | TokenKind::DoubleArrow => Some(bp::JSON),
4280
4281 _ => None,
4282 }
4283 }
4284
4285 #[cfg(test)]
4286 #[allow(clippy::too_many_lines)]
4287 fn parse_infix(&mut self, lhs: ParsedExpr, r_bp: u8) -> Result<ParsedExpr, ParseError> {
4288 let tok = self.advance_token();
4289 match &tok.kind {
4290 TokenKind::Plus => self.make_binop(lhs, BinaryOp::Add, r_bp),
4292 TokenKind::Minus => self.make_binop(lhs, BinaryOp::Subtract, r_bp),
4293 TokenKind::Star => self.make_binop(lhs, BinaryOp::Multiply, r_bp),
4294 TokenKind::Slash => self.make_binop(lhs, BinaryOp::Divide, r_bp),
4295 TokenKind::Percent => self.make_binop(lhs, BinaryOp::Modulo, r_bp),
4296 TokenKind::Concat => self.make_binop(lhs, BinaryOp::Concat, r_bp),
4297 TokenKind::Eq | TokenKind::EqEq => self.make_binop(lhs, BinaryOp::Eq, r_bp),
4298 TokenKind::Ne | TokenKind::LtGt => self.make_binop(lhs, BinaryOp::Ne, r_bp),
4299 TokenKind::Lt => self.make_binop(lhs, BinaryOp::Lt, r_bp),
4300 TokenKind::Le => self.make_binop(lhs, BinaryOp::Le, r_bp),
4301 TokenKind::Gt => self.make_binop(lhs, BinaryOp::Gt, r_bp),
4302 TokenKind::Ge => self.make_binop(lhs, BinaryOp::Ge, r_bp),
4303 TokenKind::Ampersand => self.make_binop(lhs, BinaryOp::BitAnd, r_bp),
4304 TokenKind::Pipe => self.make_binop(lhs, BinaryOp::BitOr, r_bp),
4305 TokenKind::ShiftLeft => self.make_binop(lhs, BinaryOp::ShiftLeft, r_bp),
4306 TokenKind::ShiftRight => self.make_binop(lhs, BinaryOp::ShiftRight, r_bp),
4307 TokenKind::KwOr => self.make_binop(lhs, BinaryOp::Or, r_bp),
4308 TokenKind::KwAnd => self.make_binop(lhs, BinaryOp::And, r_bp),
4309
4310 TokenKind::KwIs => {
4312 let not = self.eat_kind(&TokenKind::KwNot);
4313 if self.eat_kind(&TokenKind::KwDistinct) {
4314 self.expect_kind(&TokenKind::KwFrom)?;
4315 let rhs = self.parse_expr_bp(r_bp)?;
4316 let span = lhs.expr.span().merge(rhs.expr.span());
4317 let height = lhs.height.max(rhs.height);
4318 let is_constant = lhs.is_constant && rhs.is_constant;
4319 let has_function = lhs.has_function || rhs.has_function;
4320 let op = if not { BinaryOp::Is } else { BinaryOp::IsNot };
4323 return self.checked_expr(
4324 Expr::BinaryOp {
4325 left: Box::new(lhs.expr),
4326 op,
4327 right: Box::new(rhs.expr),
4328 span,
4329 },
4330 height,
4331 is_constant,
4332 has_function,
4333 );
4334 }
4335 let rhs = self.parse_expr_bp(r_bp)?;
4336 let span = lhs.expr.span().merge(rhs.expr.span());
4337 if matches!(&rhs.expr, Expr::Literal(Literal::Null, _)) {
4345 let height = lhs.height;
4346 let is_constant = lhs.is_constant;
4347 let has_function = lhs.has_function;
4348 return self.checked_expr(
4349 Expr::IsNull {
4350 expr: Box::new(lhs.expr),
4351 not,
4352 span,
4353 },
4354 height,
4355 is_constant,
4356 has_function,
4357 );
4358 }
4359 let op = if not { BinaryOp::IsNot } else { BinaryOp::Is };
4360 let height = lhs.height.max(rhs.height);
4361 let is_constant = lhs.is_constant && rhs.is_constant;
4362 let has_function = lhs.has_function || rhs.has_function;
4363 self.checked_expr(
4364 Expr::BinaryOp {
4365 left: Box::new(lhs.expr),
4366 op,
4367 right: Box::new(rhs.expr),
4368 span,
4369 },
4370 height,
4371 is_constant,
4372 has_function,
4373 )
4374 }
4375
4376 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, false),
4378 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, false),
4379 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, false),
4380 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, false),
4381
4382 TokenKind::KwBetween => self.parse_between(lhs, false),
4384
4385 TokenKind::KwIn => self.parse_in(lhs, false),
4387
4388 TokenKind::Arrow => {
4390 let rhs = self.parse_expr_bp(r_bp)?;
4391 let span = lhs.expr.span().merge(rhs.expr.span());
4392 let height = lhs.height.max(rhs.height);
4393 let is_constant = false;
4394 let has_function = true;
4395 self.checked_expr(
4396 Expr::JsonAccess {
4397 expr: Box::new(lhs.expr),
4398 path: Box::new(rhs.expr),
4399 arrow: JsonArrow::Arrow,
4400 span,
4401 },
4402 height,
4403 is_constant,
4404 has_function,
4405 )
4406 }
4407 TokenKind::DoubleArrow => {
4408 let rhs = self.parse_expr_bp(r_bp)?;
4409 let span = lhs.expr.span().merge(rhs.expr.span());
4410 let height = lhs.height.max(rhs.height);
4411 let is_constant = false;
4412 let has_function = true;
4413 self.checked_expr(
4414 Expr::JsonAccess {
4415 expr: Box::new(lhs.expr),
4416 path: Box::new(rhs.expr),
4417 arrow: JsonArrow::DoubleArrow,
4418 span,
4419 },
4420 height,
4421 is_constant,
4422 has_function,
4423 )
4424 }
4425
4426 TokenKind::KwNot => {
4428 let next = self.advance_token();
4429 match &next.kind {
4430 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, true),
4431 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, true),
4432 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, true),
4433 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, true),
4434 TokenKind::KwBetween => self.parse_between(lhs, true),
4435 TokenKind::KwIn => self.parse_in(lhs, true),
4436 _ => Err(ParseError::at(
4437 format!(
4438 "expected LIKE/GLOB/MATCH/REGEXP/BETWEEN/IN \
4439 after NOT, got {:?}",
4440 next.kind
4441 ),
4442 Some(&next),
4443 )),
4444 }
4445 }
4446
4447 other => Err(ParseError::at(
4448 format!("unexpected infix token: {other:?}"),
4449 Some(&tok),
4450 )),
4451 }
4452 }
4453
4454 #[cfg(test)]
4455 fn make_binop(
4456 &mut self,
4457 lhs: ParsedExpr,
4458 op: BinaryOp,
4459 r_bp: u8,
4460 ) -> Result<ParsedExpr, ParseError> {
4461 let rhs = self.parse_expr_bp(r_bp)?;
4462 let span = lhs.expr.span().merge(rhs.expr.span());
4463 let height = lhs.height.max(rhs.height);
4464 let is_constant = lhs.is_constant && rhs.is_constant;
4465 let has_function = lhs.has_function || rhs.has_function;
4466 self.checked_expr(
4467 Expr::BinaryOp {
4468 left: Box::new(lhs.expr),
4469 op,
4470 right: Box::new(rhs.expr),
4471 span,
4472 },
4473 height,
4474 is_constant,
4475 has_function,
4476 )
4477 }
4478
4479 #[cfg(test)]
4482 fn parse_like(
4483 &mut self,
4484 lhs: ParsedExpr,
4485 op: LikeOp,
4486 not: bool,
4487 ) -> Result<ParsedExpr, ParseError> {
4488 let pattern = self.parse_expr_bp(bp::EQUALITY.1)?;
4489 let escape = if self.eat_kind(&TokenKind::KwEscape) {
4490 Some(self.parse_expr_bp(bp::EQUALITY.1)?)
4493 } else {
4494 None
4495 };
4496 let end = escape
4497 .as_ref()
4498 .map_or_else(|| pattern.expr.span(), |e| e.expr.span());
4499 let span = lhs.expr.span().merge(end);
4500 let height = escape.as_ref().map_or_else(
4501 || lhs.height.max(pattern.height),
4502 |parsed| lhs.height.max(pattern.height).max(parsed.height),
4503 );
4504 let parsed = self.checked_expr(
4505 Expr::Like {
4506 expr: Box::new(lhs.expr),
4507 pattern: Box::new(pattern.expr),
4508 escape: escape.map(|parsed| Box::new(parsed.expr)),
4509 op,
4510 not,
4511 span,
4512 },
4513 height,
4514 false,
4515 true,
4516 )?;
4517 if not {
4518 self.add_cached_parent(parsed)
4519 } else {
4520 Ok(parsed)
4521 }
4522 }
4523
4524 #[cfg(test)]
4525 fn parse_between(&mut self, lhs: ParsedExpr, not: bool) -> Result<ParsedExpr, ParseError> {
4526 let low = self.parse_expr_bp(bp::NOT_PREFIX)?;
4528 if !self.eat_kind(&TokenKind::KwAnd) {
4529 return Err(self.err_here("expected AND in BETWEEN expression"));
4530 }
4531 let high = self.parse_expr_bp(bp::EQUALITY.1)?;
4532 let span = lhs.expr.span().merge(high.expr.span());
4533 let height = lhs.height.max(low.height).max(high.height);
4534 let is_constant = lhs.is_constant && low.is_constant && high.is_constant;
4535 let has_function = lhs.has_function || low.has_function || high.has_function;
4536 let parsed = self.checked_expr(
4537 Expr::Between {
4538 expr: Box::new(lhs.expr),
4539 low: Box::new(low.expr),
4540 high: Box::new(high.expr),
4541 not,
4542 span,
4543 },
4544 height,
4545 is_constant,
4546 has_function,
4547 )?;
4548 if not {
4549 self.add_cached_parent(parsed)
4550 } else {
4551 Ok(parsed)
4552 }
4553 }
4554
4555 #[cfg(test)]
4556 fn parse_in(&mut self, lhs: ParsedExpr, not: bool) -> Result<ParsedExpr, ParseError> {
4557 let start = lhs.expr.span();
4558
4559 if !self.at_kind(&TokenKind::LeftParen) {
4561 let table = self.parse_qualified_name()?;
4562 let end = self.tokens[self.pos.saturating_sub(1)].span;
4563 let span = start.merge(end);
4564 let height = lhs.height;
4565 let has_function = lhs.has_function;
4566 let parsed = self.checked_expr(
4567 Expr::In {
4568 expr: Box::new(lhs.expr),
4569 set: InSet::Table(table),
4570 not,
4571 span,
4572 },
4573 height,
4574 false,
4575 has_function,
4576 )?;
4577 return if not {
4578 self.add_cached_parent(parsed)
4579 } else {
4580 Ok(parsed)
4581 };
4582 }
4583
4584 self.expect_kind(&TokenKind::LeftParen)?;
4585
4586 if matches!(
4587 self.peek_kind(),
4588 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
4589 ) {
4590 let subquery = self.parse_subquery_minimal()?;
4591 let end = self.expect_kind(&TokenKind::RightParen)?;
4592 let span = start.merge(end);
4593 let height = lhs.height.max(subquery.height);
4594 let has_function = lhs.has_function;
4595 let parsed = self.checked_expr(
4596 Expr::In {
4597 expr: Box::new(lhs.expr),
4598 set: InSet::Subquery(Box::new(subquery.value)),
4599 not,
4600 span,
4601 },
4602 height,
4603 false,
4604 has_function,
4605 )?;
4606 return if not {
4607 self.add_cached_parent(parsed)
4608 } else {
4609 Ok(parsed)
4610 };
4611 }
4612
4613 let mut parsed_items = Vec::new();
4614 if !self.at_kind(&TokenKind::RightParen) {
4615 let item = self.parse_expr_bp(0)?;
4616 parsed_items.push(item);
4617 while self.eat_kind(&TokenKind::Comma) {
4618 let item = self.parse_expr_bp(0)?;
4619 parsed_items.push(item);
4620 }
4621 }
4622 let end = self.expect_kind(&TokenKind::RightParen)?;
4623 if let Some(message) = vector_in_list_arity_error(&lhs.expr, &parsed_items) {
4624 return Err(self.err_here(message));
4625 }
4626 let span = start.merge(end);
4627 let item_height = parsed_items
4628 .iter()
4629 .map(|item| item.height)
4630 .max()
4631 .unwrap_or(0);
4632 let items_are_constant = parsed_items.iter().all(|item| item.is_constant);
4633 let item_has_function = parsed_items.iter().any(|item| item.has_function);
4634 let singleton_constant = matches!(parsed_items.as_slice(), [item] if item.is_constant)
4635 && lhs.root != CachedRoot::Vector;
4636 let singleton_subquery =
4637 matches!(parsed_items.as_slice(), [item] if item.root == CachedRoot::ScalarSubquery);
4638 let exprs = parsed_items.into_iter().map(|parsed| parsed.expr).collect();
4639 let lhs_height = lhs.height;
4640 let lhs_is_constant = lhs.is_constant;
4641 let lhs_has_function = lhs.has_function;
4642 let expr = Expr::In {
4643 expr: Box::new(lhs.expr),
4644 set: InSet::List(exprs),
4645 not,
4646 span,
4647 };
4648
4649 if item_height == 0 {
4650 if lhs_has_function {
4651 return self.finish_expr(expr, lhs_height.saturating_add(1), false, true);
4652 }
4653 return self.finish_expr(expr, 1, true, false);
4654 }
4655
4656 let cached_child_height = if singleton_constant {
4657 lhs_height.max(item_height.saturating_add(1))
4658 } else if singleton_subquery {
4659 lhs_height.max(item_height.saturating_sub(1))
4660 } else {
4661 lhs_height.max(item_height)
4662 };
4663 let parsed = self.checked_expr(
4664 expr,
4665 cached_child_height,
4666 lhs_is_constant && items_are_constant,
4667 lhs_has_function || item_has_function,
4668 )?;
4669 if not {
4670 self.add_cached_parent(parsed)
4671 } else {
4672 Ok(parsed)
4673 }
4674 }
4675
4676 #[cfg(test)]
4677 fn parse_case_expr(&mut self, start: Span) -> Result<ParsedExpr, ParseError> {
4678 let operand = if matches!(self.peek_kind(), TokenKind::KwWhen) {
4679 None
4680 } else {
4681 Some(self.parse_expr_bp(0)?)
4682 };
4683
4684 let mut whens = Vec::new();
4685 while self.eat_kind(&TokenKind::KwWhen) {
4686 let condition = self.parse_expr_bp(0)?;
4687 if !self.eat_kind(&TokenKind::KwThen) {
4688 return Err(self.err_here("expected THEN in CASE expression"));
4689 }
4690 let result = self.parse_expr_bp(0)?;
4691 whens.push((condition, result));
4692 }
4693 if whens.is_empty() {
4694 return Err(self.err_here("CASE requires at least one WHEN clause"));
4695 }
4696
4697 let else_expr = if self.eat_kind(&TokenKind::KwElse) {
4698 Some(self.parse_expr_bp(0)?)
4699 } else {
4700 None
4701 };
4702
4703 if !self.eat_kind(&TokenKind::KwEnd) {
4704 return Err(self.err_here("expected END for CASE expression"));
4705 }
4706 let end = self.tokens[self.pos.saturating_sub(1)].span;
4707 let span = start.merge(end);
4708 let mut height = operand.as_ref().map_or(0, |parsed| parsed.height);
4709 let mut is_constant = operand.as_ref().is_none_or(|parsed| parsed.is_constant);
4710 let mut has_function = operand.as_ref().is_some_and(|parsed| parsed.has_function);
4711 for (condition, result) in &whens {
4712 height = height.max(condition.height).max(result.height);
4713 is_constant &= condition.is_constant && result.is_constant;
4714 has_function |= condition.has_function || result.has_function;
4715 }
4716 if let Some(parsed) = &else_expr {
4717 height = height.max(parsed.height);
4718 is_constant &= parsed.is_constant;
4719 has_function |= parsed.has_function;
4720 }
4721 self.checked_expr(
4722 Expr::Case {
4723 operand: operand.map(|parsed| Box::new(parsed.expr)),
4724 whens: whens
4725 .into_iter()
4726 .map(|(condition, result)| (condition.expr, result.expr))
4727 .collect(),
4728 else_expr: else_expr.map(|parsed| Box::new(parsed.expr)),
4729 span,
4730 },
4731 height,
4732 is_constant,
4733 has_function,
4734 )
4735 }
4736
4737 #[cfg(test)]
4738 fn parse_function_call(&mut self, name: String, start: Span) -> Result<ParsedExpr, ParseError> {
4739 self.expect_kind(&TokenKind::LeftParen)?;
4740
4741 let (args, distinct, height) = if matches!(self.peek_kind(), TokenKind::Star) {
4742 self.advance_token();
4743 if name.eq_ignore_ascii_case("count") {
4746 (FunctionArgs::Star, false, 0)
4747 } else {
4748 (FunctionArgs::List(Vec::new()), false, 0)
4749 }
4750 } else {
4751 let distinct = self.eat_kind(&TokenKind::KwDistinct);
4752 let (args, height) = if matches!(self.peek_kind(), TokenKind::RightParen) {
4753 if distinct {
4754 return Err(self.err_here("DISTINCT requires at least one argument"));
4755 }
4756 (FunctionArgs::List(Vec::new()), 0)
4757 } else {
4758 let first = self.parse_expr_bp(0)?;
4759 let mut height = first.height;
4760 let mut list = vec![first.expr];
4761 while self.eat_kind(&TokenKind::Comma) {
4762 let parsed = self.parse_expr_bp(0)?;
4763 height = height.max(parsed.height);
4764 list.push(parsed.expr);
4765 }
4766 (FunctionArgs::List(list), height)
4767 };
4768 (args, distinct, height)
4769 };
4770
4771 let order_by =
4773 if matches!(&args, FunctionArgs::List(_)) && self.eat_kind(&TokenKind::KwOrder) {
4774 self.expect_kind(&TokenKind::KwBy)?;
4775 self.parse_comma_sep(Self::parse_ordering_term)?
4776 } else {
4777 vec![]
4778 };
4779
4780 let mut end = self.expect_kind(&TokenKind::RightParen)?;
4781 let filter = if matches!(self.peek_kind(), TokenKind::KwFilter)
4784 && self
4785 .tokens
4786 .get(self.pos + 1)
4787 .is_some_and(|t| t.kind == TokenKind::LeftParen)
4788 {
4789 self.advance_token(); self.expect_kind(&TokenKind::LeftParen)?;
4791 self.expect_kind(&TokenKind::KwWhere)?;
4792 let predicate = self.parse_expr()?;
4793 let filter_end = self.expect_kind(&TokenKind::RightParen)?;
4794 end = end.merge(filter_end);
4795 Some(Box::new(predicate))
4796 } else {
4797 None
4798 };
4799 let over = if matches!(self.peek_kind(), TokenKind::KwOver)
4802 && self.tokens.get(self.pos + 1).is_some_and(|t| {
4803 matches!(t.kind, TokenKind::LeftParen) || starts_bare_window_name(&t.kind)
4804 }) {
4805 self.advance_token(); if self.eat_kind(&TokenKind::LeftParen) {
4807 let spec = self.parse_window_spec()?;
4808 let over_end = self.expect_kind(&TokenKind::RightParen)?;
4809 end = end.merge(over_end);
4810 Some(spec)
4811 } else {
4812 let base_window = self.parse_window_name()?;
4813 let base_span = self.tokens[self.pos.saturating_sub(1)].span;
4814 end = end.merge(base_span);
4815 Some(WindowSpec {
4816 window_ref: Some(WindowReference::Direct(base_window)),
4817 partition_by: Vec::new(),
4818 order_by: Vec::new(),
4819 frame: None,
4820 })
4821 }
4822 } else {
4823 None
4824 };
4825
4826 let span = start.merge(end);
4827 self.checked_expr(
4828 Expr::FunctionCall {
4829 name,
4830 args,
4831 distinct,
4832 order_by,
4833 filter,
4834 over,
4835 span,
4836 },
4837 height,
4838 false,
4839 true,
4840 )
4841 }
4842
4843 fn parse_raise_args(&mut self) -> Result<(RaiseAction, Option<String>), ParseError> {
4844 let action_tok = self.advance_token();
4845 let action = match &action_tok.kind {
4846 TokenKind::KwIgnore => RaiseAction::Ignore,
4847 TokenKind::KwRollback => RaiseAction::Rollback,
4848 TokenKind::KwAbort => RaiseAction::Abort,
4849 TokenKind::KwFail => RaiseAction::Fail,
4850 _ => {
4851 return Err(ParseError::at(
4852 "expected IGNORE, ROLLBACK, ABORT, or FAIL in RAISE",
4853 Some(&action_tok),
4854 ));
4855 }
4856 };
4857 if matches!(action, RaiseAction::Ignore) {
4858 return Ok((action, None));
4859 }
4860 self.expect_kind(&TokenKind::Comma)?;
4861 let msg_tok = self.advance_token();
4862 let message = match &msg_tok.kind {
4863 TokenKind::String(s) => s.clone(),
4864 _ => {
4865 return Err(ParseError::at(
4866 "expected string message in RAISE",
4867 Some(&msg_tok),
4868 ));
4869 }
4870 };
4871 Ok((action, Some(message)))
4872 }
4873
4874 fn parse_type_name(&mut self) -> Result<TypeName, ParseError> {
4875 let mut parts = Vec::new();
4876 loop {
4877 match self.peek_kind() {
4878 TokenKind::Id(_) | TokenKind::QuotedId(_, _) => {
4879 let tok = self.advance_token();
4880 if let TokenKind::Id(s) | TokenKind::QuotedId(s, _) = &tok.kind {
4881 parts.push(s.to_string());
4882 } else {
4883 unreachable!();
4884 }
4885 }
4886 k if is_nonreserved_kw(k) => {
4887 let tok = self.advance_token();
4888 parts.push(kw_to_str(&tok.kind));
4889 }
4890 _ => break,
4891 }
4892 }
4893 if parts.is_empty() {
4894 return Err(self.err_here("expected type name"));
4895 }
4896 let name = parts.join(" ");
4897
4898 let (arg1, arg2) = if self.eat_kind(&TokenKind::LeftParen) {
4899 let a1 = self.parse_type_arg()?;
4900 let a2 = if self.eat_kind(&TokenKind::Comma) {
4901 Some(self.parse_type_arg()?)
4902 } else {
4903 None
4904 };
4905 self.expect_kind(&TokenKind::RightParen)?;
4906 (Some(a1), a2)
4907 } else {
4908 (None, None)
4909 };
4910
4911 Ok(TypeName { name, arg1, arg2 })
4912 }
4913
4914 fn parse_type_arg(&mut self) -> Result<String, ParseError> {
4915 let tok = self.advance_token();
4916 match &tok.kind {
4917 TokenKind::Integer(i) => Ok(i.to_string()),
4918 TokenKind::Float(f) => Ok(f.to_string()),
4919 TokenKind::Minus => {
4920 let next = self.advance_token();
4921 match &next.kind {
4922 TokenKind::Integer(i) => Ok(format!("-{i}")),
4923 TokenKind::OversizedInt(s) => Ok(format!("-{s}")),
4924 TokenKind::Float(f) => Ok(format!("-{f}")),
4925 _ => Err(ParseError::at(
4926 "expected number in type argument",
4927 Some(&next),
4928 )),
4929 }
4930 }
4931 TokenKind::Plus => {
4932 let next = self.advance_token();
4933 match &next.kind {
4934 TokenKind::Integer(i) => Ok(format!("+{i}")),
4935 TokenKind::OversizedInt(s) => Ok(format!("+{s}")),
4936 TokenKind::Float(f) => Ok(format!("+{f}")),
4937 _ => Err(ParseError::at(
4938 "expected number in type argument",
4939 Some(&next),
4940 )),
4941 }
4942 }
4943 TokenKind::OversizedInt(s) => Ok(s.clone()),
4944 TokenKind::Id(s) | TokenKind::QuotedId(s, _) => Ok(s.to_string()),
4945 _ => Err(ParseError::at("expected type argument", Some(&tok))),
4946 }
4947 }
4948
4949 #[cfg(test)]
4951 fn parse_subquery_minimal(&mut self) -> Result<HeightTracked<SelectStatement>, ParseError> {
4952 let with = if self.at_kind(&TokenKind::KwWith) {
4953 Some(ParseMachine::for_with(self).run_with()?)
4954 } else {
4955 None
4956 };
4957 ParseMachine::for_select(self, with).run_select()
4958 }
4959}
4960
4961pub fn parse_expr(sql: &str) -> Result<Expr, ParseError> {
4963 let mut parser = Parser::from_sql(sql);
4964 let expr = parser.parse_expr()?;
4965 let _ = parser.eat(&TokenKind::Semicolon);
4966 if !parser.at_eof() {
4967 return Err(parser.err_here(format!(
4968 "unexpected token after expression: {:?}",
4969 parser.peek_kind()
4970 )));
4971 }
4972 Ok(expr)
4973}
4974
4975#[cfg(test)]
4976mod tests {
4977 use super::*;
4978 use crate::parser::ParseErrorKind;
4979 use fsqlite_ast::{BoundCollation, SelectCore, TableOrSubquery};
4980 use fsqlite_types::{SqliteValue, TypeAffinity};
4981
4982 fn parse(sql: &str) -> Expr {
4983 match parse_expr(sql) {
4984 Ok(expr) => expr,
4985 Err(err) => unreachable!("parse error for `{sql}`: {err}"),
4986 }
4987 }
4988
4989 fn repeated_infix_expression(term_count: usize, operator: &str) -> String {
4990 std::iter::repeat_n("1", term_count)
4991 .collect::<Vec<_>>()
4992 .join(operator)
4993 }
4994
4995 fn assert_expression_depth_error(sql: &str) {
4996 let error = parse_expr(sql).expect_err("expression height 1001 must fail closed");
4997 assert_eq!(
4998 error.kind,
4999 ParseErrorKind::ExpressionTooDeep {
5000 max: MAX_PARSE_DEPTH
5001 }
5002 );
5003 assert_eq!(
5004 error.message,
5005 format!(
5006 "Expression tree is too large (maximum depth {})",
5007 MAX_PARSE_DEPTH
5008 )
5009 );
5010 assert!(error.is_expression_too_deep());
5011 }
5012
5013 fn right_deep_binary_expression(height: usize) -> String {
5014 format!("{}1{}", "1 + (".repeat(height - 1), ")".repeat(height - 1))
5015 }
5016
5017 fn single_arg_function_expression(height: usize) -> String {
5018 format!("{}1{}", "abs(".repeat(height - 1), ")".repeat(height - 1))
5019 }
5020
5021 fn scalar_subquery_expression(height: usize) -> String {
5022 format!(
5023 "{}1{}",
5024 "(SELECT ".repeat(height - 1),
5025 ")".repeat(height - 1)
5026 )
5027 }
5028
5029 fn on_one_mib_stack<T: Send + 'static>(task: impl FnOnce() -> T + Send + 'static) -> T {
5030 std::thread::Builder::new()
5031 .stack_size(1024 * 1024)
5032 .spawn(task)
5033 .expect("1 MiB parser thread must spawn")
5034 .join()
5035 .expect("parser task must not overflow or panic")
5036 }
5037
5038 fn parsed_select_height(sql: &str) -> u32 {
5039 let mut parser = Parser::from_sql(sql);
5040 let select = parser
5041 .parse_subquery_minimal()
5042 .expect("SELECT fixture must parse");
5043 assert_eq!(
5044 select.height,
5045 normalized_ast_select_height(&select.value),
5046 "tracked SELECT height diverged from the normalized AST test oracle"
5047 );
5048 select.height
5049 }
5050
5051 fn parsed_expr_height(sql: &str) -> u32 {
5052 let mut parser = Parser::from_sql(sql);
5053 let parsed = parser
5054 .parse_expr_tracked()
5055 .expect("expression fixture must parse");
5056 assert!(
5057 matches!(parser.peek_kind(), TokenKind::Eof | TokenKind::Semicolon),
5058 "expression fixture left an unparsed token: {sql}"
5059 );
5060 assert_eq!(
5061 parsed.height,
5062 normalized_ast_expr_height(&parsed.expr),
5063 "tracked expression height diverged from the normalized AST test oracle: {sql}"
5064 );
5065 parsed.height
5066 }
5067
5068 #[test]
5069 fn bound_outer_value_has_constant_leaf_facts() {
5070 let expr = Expr::BoundOuterValue {
5071 value: SqliteValue::Integer(42),
5072 collation: BoundCollation::Named("NOCASE".to_owned()),
5073 affinity: Some(TypeAffinity::Integer),
5074 span: Span::ZERO,
5075 };
5076
5077 let parsed = ParsedExpr::leaf(expr.clone());
5078 assert_eq!(parsed.height, 1);
5079 assert!(parsed.is_constant);
5080 assert!(!parsed.has_function);
5081
5082 let facts = cached_facts_from_tasks(vec![CachedHeightTask::Expr(&expr)]);
5083 assert_eq!(facts.height, 1);
5084 assert!(facts.is_constant);
5085 assert!(!facts.has_function);
5086 }
5087
5088 fn mixed_deep_expression(height: usize) -> String {
5089 let mut prefix = String::new();
5090 let mut closing_count = 0;
5091 for index in 1..height {
5092 if index % 7 == 0 {
5093 prefix.push('(');
5094 closing_count += 1;
5095 }
5096 match index % 4 {
5097 0 => prefix.push('~'),
5098 1 => {
5099 prefix.push_str("abs(");
5100 closing_count += 1;
5101 }
5102 2 => {
5103 prefix.push_str("(SELECT ");
5104 closing_count += 1;
5105 }
5106 _ => {
5107 prefix.push_str("1 + (");
5108 closing_count += 1;
5109 }
5110 }
5111 }
5112 prefix.push('1');
5113 prefix.push_str(&")".repeat(closing_count));
5114 prefix
5115 }
5116
5117 fn assert_machine_matches_recursive_oracle(sql: &str) {
5118 let mut machine = Parser::from_sql(sql);
5119 let machine_result = machine.parse_expr_tracked();
5120 let machine_pos = machine.pos;
5121 let machine_tail = machine.peek_kind().clone();
5122
5123 let mut oracle = Parser::from_sql(sql);
5124 let oracle_result = oracle.parse_expr_bp(0);
5125 let oracle_pos = oracle.pos;
5126 let oracle_tail = oracle.peek_kind().clone();
5127
5128 assert_eq!(
5129 machine_pos, oracle_pos,
5130 "parser tail position differs: {sql}"
5131 );
5132 assert_eq!(
5133 machine_tail, oracle_tail,
5134 "parser tail token differs: {sql}"
5135 );
5136 match (machine_result, oracle_result) {
5137 (Ok(machine), Ok(oracle)) => {
5138 assert_eq!(machine.expr, oracle.expr, "AST or spans differ: {sql}");
5139 assert_eq!(machine.height, oracle.height, "height differs: {sql}");
5140 assert_eq!(
5141 machine.is_constant, oracle.is_constant,
5142 "constant fact differs: {sql}"
5143 );
5144 assert_eq!(
5145 machine.has_function, oracle.has_function,
5146 "function fact differs: {sql}"
5147 );
5148 assert_eq!(machine.root, oracle.root, "root fact differs: {sql}");
5149 }
5150 (Err(machine), Err(oracle)) => {
5151 assert_eq!(machine, oracle, "diagnostic differs: {sql}");
5152 }
5153 (Ok(_), Err(_)) | (Err(_), Ok(_)) => {
5154 panic!("machine/oracle result class differs for `{sql}`");
5155 }
5156 }
5157 }
5158
5159 fn assert_select_machine_matches_recursive_oracle(sql: &str) {
5160 let mut machine = Parser::from_sql(sql);
5161 let machine_result = machine.parse_select_stmt_tracked(None);
5162 let machine_pos = machine.pos;
5163 let machine_tail = machine.peek_kind().clone();
5164
5165 let mut oracle = Parser::from_sql(sql);
5166 let oracle_result = oracle.parse_select_stmt_inner_tracked(None);
5167 let oracle_pos = oracle.pos;
5168 let oracle_tail = oracle.peek_kind().clone();
5169
5170 assert_eq!(
5171 machine_pos, oracle_pos,
5172 "SELECT parser tail position differs: {sql}"
5173 );
5174 assert_eq!(
5175 machine_tail, oracle_tail,
5176 "SELECT parser tail token differs: {sql}"
5177 );
5178 match (machine_result, oracle_result) {
5179 (Ok(machine), Ok(oracle)) => {
5180 assert_eq!(machine.value, oracle.value, "SELECT AST differs: {sql}");
5181 assert_eq!(
5182 machine.height, oracle.height,
5183 "SELECT height differs: {sql}"
5184 );
5185 }
5186 (Err(machine), Err(oracle)) => {
5187 assert_eq!(machine, oracle, "SELECT diagnostic differs: {sql}");
5188 }
5189 (Ok(_), Err(_)) | (Err(_), Ok(_)) => {
5190 panic!("SELECT machine/oracle result class differs for `{sql}`");
5191 }
5192 }
5193 }
5194
5195 fn bitnot_depth(mut expr: &Expr) -> usize {
5196 let mut depth = 0;
5197 while let Expr::UnaryOp {
5198 op: UnaryOp::BitNot,
5199 expr: inner,
5200 ..
5201 } = expr
5202 {
5203 depth += 1;
5204 expr = inner;
5205 }
5206 depth
5207 }
5208
5209 fn wrap_function_to_height(base: &str, target_height: usize) -> String {
5210 let base_height = parsed_expr_height(base) as usize;
5211 assert!(base_height <= target_height);
5212 let wrappers = target_height - base_height;
5213 format!("{}{base}{}", "abs(".repeat(wrappers), ")".repeat(wrappers))
5214 }
5215
5216 #[test]
5217 fn test_explicit_machine_matches_recursive_oracle_for_shallow_valid_expressions() {
5218 for sql in [
5219 "1",
5220 "-9223372036854775808",
5221 "a.b + c * 2",
5222 "'a'.b + a.'b'",
5223 "attach.x",
5224 "filter.x",
5225 "true.x",
5226 "with.x",
5227 "a.current_date",
5228 "NOT a = b",
5229 "x IS NULL < 2",
5230 "x IS NOT DISTINCT FROM y",
5231 "CAST(x + 1 AS DECIMAL(10, 2))",
5232 "CASE x WHEN 1 THEN y ELSE z END",
5233 "x NOT BETWEEN 1 AND 2",
5234 "x IN (1, 2 + 3)",
5235 "(SELECT 1, 2) IN ((1, 2))",
5236 "(a, b) IN ((SELECT 1))",
5237 "(a, b) IN ((SELECT 1, 2, 3))",
5238 "(a, b) IN ((SELECT 1), (SELECT 2))",
5239 "(SELECT * FROM t) IN (1)",
5240 "x IN (SELECT y FROM t WHERE z > 0 ORDER BY y LIMIT 1)",
5241 "EXISTS (SELECT 1 FROM t WHERE x = y)",
5242 "(1, 2 + 3)",
5243 "value COLLATE \"my col\"",
5244 "doc -> '$.x' || suffix",
5245 "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)",
5246 ] {
5247 assert_machine_matches_recursive_oracle(sql);
5248 }
5249 }
5250
5251 #[test]
5252 fn test_explicit_machine_matches_recursive_oracle_for_shallow_malformed_expressions() {
5253 for sql in [
5254 "+",
5255 "CASE END",
5256 "CASE WHEN 1 2 END",
5257 "CASE WHEN 1 THEN 2",
5258 "CAST(1 INTEGER)",
5259 "f(DISTINCT)",
5260 "(1,)",
5261 "a.",
5262 "a.select",
5263 "a.nothing",
5264 "cast.x",
5265 "current_date.x",
5266 "raise.x",
5267 "transaction.x",
5268 "a BETWEEN 1 2",
5269 "a IN (1,)",
5270 "(a, b) IN (1)",
5271 "(a, b) IN (+(SELECT 1, 2))",
5272 "(a, b) IN ((1, 2), 3)",
5273 "(a, b) NOT IN ((1, 2, 3))",
5274 "(SELECT 1, 2) IN (1)",
5275 "(SELECT 1, 2) IN ((1, 2), 3)",
5276 "(SELECT 1, 2) NOT IN ((1, 2, 3))",
5277 "a LIKE",
5278 "EXISTS (SELECT)",
5279 "count(* ORDER BY x)",
5280 "t.*",
5281 ] {
5282 assert_machine_matches_recursive_oracle(sql);
5283 }
5284 }
5285
5286 #[test]
5287 fn public_parse_expr_requires_eof_after_one_optional_terminator() {
5288 assert_eq!(
5289 parse_expr("1;")
5290 .expect("one trailing expression terminator must remain valid")
5291 .to_string(),
5292 "1"
5293 );
5294
5295 for (sql, unexpected) in [("1; 2", "2"), ("1; SELECT 2", "SELECT"), ("1;;", ";")] {
5296 let error = parse_expr(sql)
5297 .expect_err("tokens after the optional expression terminator must be rejected");
5298 assert_eq!(error.kind, ParseErrorKind::Syntax);
5299 assert!(
5300 error.message.contains("unexpected token after expression"),
5301 "unexpected diagnostic for `{sql}`: {error:?}"
5302 );
5303 assert_eq!(
5304 &sql[error.span.start as usize..error.span.end as usize],
5305 unexpected,
5306 "the diagnostic for `{sql}` must point at the first forbidden token"
5307 );
5308 }
5309 }
5310
5311 #[test]
5312 fn test_explicit_select_machine_matches_recursive_shallow_oracle() {
5313 for sql in [
5314 "SELECT 1",
5315 "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",
5316 "SELECT * FROM a CROSS JOIN b ON a.id = b.id",
5317 "SELECT * FROM a, b",
5318 "SELECT * FROM a, b ON a.id = b.id",
5319 "SELECT * FROM a, b USING(id)",
5320 "SELECT filter.* FROM t AS filter",
5321 "SELECT attach.* FROM t AS \"attach\"",
5322 "SELECT attach.x FROM (SELECT 1 AS x) AS \"attach\"",
5323 "SELECT filter.x FROM (SELECT 1 AS x) AS \"filter\"",
5324 "SELECT 't'.*, t.'select' FROM t",
5325 "SELECT 1 'single quoted'",
5326 "SELECT 1 attach",
5327 "SELECT 1 window",
5328 "SELECT * FROM (SELECT 1) 'single quoted'",
5329 "SELECT * FROM (SELECT 1) match",
5330 "SELECT sum(1) OVER attach WINDOW attach AS ()",
5331 "SELECT sum(1) OVER (attach) WINDOW attach AS ()",
5332 "SELECT sum(x) OVER (ROWS BETWEEN 1 PRECEDING AND 2 PRECEDING) FROM t",
5333 "SELECT sum(x) OVER (RANGE BETWEEN CURRENT ROW AND 1 FOLLOWING) FROM t",
5334 "VALUES (1, 2), (3, 4)",
5335 "VALUES (1) ORDER BY 1",
5336 "VALUES (1) LIMIT 1",
5337 "VALUES (1) UNION SELECT 2 ORDER BY 1 LIMIT 1",
5338 "SELECT 1 UNION ALL SELECT 2 INTERSECT SELECT 3",
5339 "SELECT 1 UNION VALUES (2), (3) ORDER BY 1",
5340 "SELECT FROM t",
5341 "SELECT nothing.* FROM t AS \"nothing\"",
5342 "SELECT sum(1) OVER filter",
5343 "SELECT sum(x) OVER (ROWS 1 FOLLOWING) FROM t",
5344 "SELECT sum(x) OVER (ROWS BETWEEN CURRENT ROW AND 1 PRECEDING) FROM t",
5345 "VALUES 1",
5346 ] {
5347 assert_select_machine_matches_recursive_oracle(sql);
5348 }
5349 }
5350
5351 #[test]
5352 fn test_threshold_unary_precedence_associativity_and_spans_are_stable() {
5353 for unary_count in [63_u32, 64] {
5354 let sql = format!("{}1 + (1)", "~".repeat(unary_count as usize));
5355 let parsed = parse_expr(&sql).expect("threshold unary-plus expression must parse");
5356 assert_eq!(
5357 parsed.span(),
5358 Span::new(0, unary_count + 6),
5359 "grouping delimiters must not change the established root span"
5360 );
5361 let Expr::BinaryOp {
5362 left,
5363 op: BinaryOp::Add,
5364 right,
5365 ..
5366 } = &parsed
5367 else {
5368 panic!("unary prefix must not capture the lower-precedence addition");
5369 };
5370 assert_eq!(bitnot_depth(left), unary_count as usize);
5371 assert!(matches!(
5372 right.as_ref(),
5373 Expr::Literal(Literal::Integer(1), _)
5374 ));
5375
5376 let subtraction = format!("{}10 - 3 - 2", "~".repeat(unary_count as usize));
5377 let subtraction =
5378 parse_expr(&subtraction).expect("threshold subtraction expression must parse");
5379 assert!(matches!(
5380 subtraction,
5381 Expr::BinaryOp {
5382 op: BinaryOp::Subtract,
5383 left,
5384 ..
5385 } if matches!(
5386 left.as_ref(),
5387 Expr::BinaryOp {
5388 op: BinaryOp::Subtract,
5389 ..
5390 }
5391 )
5392 ));
5393
5394 let precedence = format!("{}1 + 2 * 3", "~".repeat(unary_count as usize));
5395 let precedence =
5396 parse_expr(&precedence).expect("threshold precedence expression must parse");
5397 assert!(matches!(
5398 precedence,
5399 Expr::BinaryOp {
5400 op: BinaryOp::Add,
5401 right,
5402 ..
5403 } if matches!(
5404 right.as_ref(),
5405 Expr::BinaryOp {
5406 op: BinaryOp::Multiply,
5407 ..
5408 }
5409 )
5410 ));
5411
5412 let parenthesized = format!(
5413 "{}1{}",
5414 "(".repeat(unary_count as usize),
5415 ")".repeat(unary_count as usize)
5416 );
5417 let parenthesized =
5418 parse_expr(&parenthesized).expect("threshold parentheses must parse");
5419 assert_eq!(
5420 parenthesized.span(),
5421 Span::new(unary_count, unary_count + 1)
5422 );
5423 }
5424 }
5425
5426 #[test]
5427 fn test_shallow_machine_uses_only_inline_control_and_value_storage() {
5428 PARSE_MACHINE_STACK_SPILLS.set(0);
5429 let expr = parse_expr("a + b * 2").expect("shallow expression must parse");
5430 assert_eq!(expr.to_string(), "a + b * 2");
5431 assert_eq!(
5432 PARSE_MACHINE_STACK_SPILLS.get(),
5433 0,
5434 "representative shallow parsing must not allocate parser stack spill storage"
5435 );
5436 }
5437
5438 #[test]
5439 fn test_formatter_precedence_associativity_and_migration_scale_stability() {
5440 for (sql, expected) in [
5441 ("a + b * 2", "a + b * 2"),
5442 ("a * (b + c)", "a * (b + c)"),
5443 ("(a - b) - c", "a - b - c"),
5444 ("a - (b - c)", "a - (b - c)"),
5445 ("a / (b / c)", "a / (b / c)"),
5446 ] {
5447 let expr = parse_expr(sql).expect("precedence fixture must parse");
5448 let rendered = expr.to_string();
5449 assert_eq!(rendered, expected);
5450 let reparsed = parse_expr(&rendered).expect("formatted fixture must reparse");
5451 assert_eq!(reparsed.to_string(), rendered);
5452 }
5453
5454 const TERM_COUNT: usize = MAX_PARSE_DEPTH as usize;
5455 for operator in ["AND", "OR"] {
5456 let mut sql = String::new();
5457 for _ in 1..TERM_COUNT {
5458 sql.push_str("flag ");
5459 sql.push_str(operator);
5460 sql.push_str(" (");
5461 }
5462 sql.push_str("flag");
5463 sql.push_str(&")".repeat(TERM_COUNT - 1));
5464
5465 let expr = parse_expr(&sql).expect("migration-scale associative chain must parse");
5466 let rendered = expr.to_string();
5467 assert_eq!(rendered.matches(operator).count(), TERM_COUNT - 1);
5468 assert!(
5469 !rendered.contains('('),
5470 "associative {operator} chain must have a flat canonical form"
5471 );
5472 let reparsed = parse_expr(&rendered).expect("flat migration-scale chain must reparse");
5473 assert_eq!(
5474 reparsed.to_string(),
5475 rendered,
5476 "format-parse-format must be byte-stable for {operator}"
5477 );
5478 }
5479 }
5480
5481 #[test]
5482 fn test_expression_height_exact_1000_1001_flat_infix_boundary() {
5483 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5484 let at_limit = repeated_infix_expression(LIMIT, " + ");
5485 let expr = parse_expr(&at_limit).expect("1000-term left-associated tree has height 1000");
5486 let rendered = expr.to_string();
5487 parse_expr(&rendered).expect("formatted height-1000 expression must remain parseable");
5488
5489 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
5490 assert_expression_depth_error(&over_limit);
5491 }
5492
5493 #[test]
5494 fn test_expression_height_exact_1000_1001_unary_boundary() {
5495 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5496 let at_limit = format!("{}1", "~".repeat(LIMIT - 1));
5497 parse_expr(&at_limit).expect("999 unary nodes plus one leaf have height 1000");
5498
5499 let over_limit = format!("{}1", "~".repeat(LIMIT));
5500 assert_expression_depth_error(&over_limit);
5501 }
5502
5503 #[test]
5504 fn test_expression_height_exact_1000_1001_not_boundary() {
5505 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5506 let at_limit = format!("{}1", "NOT ".repeat(LIMIT - 1));
5507 parse_expr(&at_limit).expect("999 NOT nodes plus one leaf have height 1000");
5508
5509 let over_limit = format!("{}1", "NOT ".repeat(LIMIT));
5510 assert_expression_depth_error(&over_limit);
5511 }
5512
5513 #[test]
5514 fn test_expression_parenthesis_chain_is_stack_safe() {
5515 const PAREN_PAIRS: usize = MAX_PARSE_DEPTH as usize * 2;
5516 let deeply_parenthesized =
5517 format!("{}1{}", "(".repeat(PAREN_PAIRS), ")".repeat(PAREN_PAIRS));
5518 parse_expr(&deeply_parenthesized)
5519 .expect("parentheses do not add AST height or consume the native call stack");
5520 }
5521
5522 #[test]
5523 fn test_expression_prefix_frames_preserve_grouping_and_row_values() {
5524 let grouped = parse_expr("-((1 + 2)) * 3").expect("grouped unary expression must parse");
5525 assert!(matches!(
5526 grouped,
5527 Expr::BinaryOp {
5528 left,
5529 op: BinaryOp::Multiply,
5530 ..
5531 } if matches!(
5532 left.as_ref(),
5533 Expr::UnaryOp {
5534 op: UnaryOp::Negate,
5535 ..
5536 }
5537 )
5538 ));
5539
5540 let row = parse_expr("((1), 2)").expect("nested row value must parse");
5541 assert!(matches!(row, Expr::RowValue(values, _) if values.len() == 2));
5542 }
5543
5544 #[test]
5545 fn test_expression_iterative_prefix_frames_preserve_minimum_integer_literal() {
5546 let mut parser = Parser::from_sql("-9223372036854775808");
5547 let parsed = parser
5548 .parse_expr_tracked()
5549 .expect("minimum signed integer literal must parse");
5550 assert!(matches!(
5551 &parsed.expr,
5552 Expr::Literal(Literal::Integer(i64::MIN), _)
5553 ));
5554 assert_eq!(parsed.height, 1);
5555 assert_eq!(parsed.expr.to_string(), "-9223372036854775808");
5556 }
5557
5558 #[test]
5559 fn test_serializer_regression_double_negated_minimum_integer_round_trips() {
5560 let expr = parse_expr("- -9223372036854775808")
5561 .expect("double-negated minimum integer must parse");
5562 let rendered = expr.to_string();
5563 assert_eq!(rendered, "-(-9223372036854775808)");
5564 let reparsed = parse_expr(&rendered).expect("rendered double negation must remain SQL");
5565 assert_eq!(expr, reparsed);
5566 }
5567
5568 #[test]
5569 fn test_serializer_regression_quoted_collation_name_round_trips() {
5570 let expr =
5571 parse_expr("value COLLATE \"my col\"").expect("quoted collation name must parse");
5572 let rendered = expr.to_string();
5573 assert_eq!(rendered, "value COLLATE \"my col\"");
5574 let reparsed = parse_expr(&rendered).expect("rendered collation must remain SQL");
5575 assert_eq!(expr, reparsed);
5576 }
5577
5578 #[test]
5579 fn test_expression_height_mixed_prefix_and_flat_reductions() {
5580 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5581 const PREFIX_COUNT: usize = 499;
5582 let at_limit = format!(
5583 "{}{}",
5584 "~".repeat(PREFIX_COUNT),
5585 repeated_infix_expression(LIMIT - PREFIX_COUNT, " - ")
5586 );
5587 parse_expr(&at_limit)
5588 .expect("mixed unary and left-associated reductions have exact height 1000");
5589
5590 let over_limit = format!(
5591 "{}{}",
5592 "~".repeat(PREFIX_COUNT),
5593 repeated_infix_expression(LIMIT - PREFIX_COUNT + 1, " - ")
5594 );
5595 assert_expression_depth_error(&over_limit);
5596 }
5597
5598 #[test]
5599 fn test_expression_height_container_adds_one_level() {
5600 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5601 let at_limit = format!("abs({})", repeated_infix_expression(LIMIT - 1, " + "));
5602 parse_expr(&at_limit).expect("function node over height-999 argument has height 1000");
5603
5604 let over_limit = format!("abs({})", repeated_infix_expression(LIMIT, " + "));
5605 assert_expression_depth_error(&over_limit);
5606 }
5607
5608 #[test]
5609 fn test_right_deep_binary_exact_1000_1001_boundary_on_one_mib_stack() {
5610 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5611 let at_limit = right_deep_binary_expression(LIMIT);
5612 let expr = on_one_mib_stack(move || {
5613 parse_expr(&at_limit).expect("right-deep height-1000 expression must parse")
5614 });
5615 assert_expression_depth_error(&right_deep_binary_expression(LIMIT + 1));
5616 drop(expr);
5617 }
5618
5619 #[test]
5620 fn test_single_arg_function_exact_1000_1001_boundary_on_one_mib_stack() {
5621 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5622 let at_limit = single_arg_function_expression(LIMIT);
5623 let expr = on_one_mib_stack(move || {
5624 parse_expr(&at_limit).expect("nested function height-1000 expression must parse")
5625 });
5626 assert_expression_depth_error(&single_arg_function_expression(LIMIT + 1));
5627 drop(expr);
5628 }
5629
5630 #[test]
5631 fn test_scalar_subquery_exact_1000_1001_boundary_on_one_mib_stack() {
5632 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5633 let at_limit = scalar_subquery_expression(LIMIT);
5634 let rendered_selects = on_one_mib_stack(move || {
5635 let expr =
5636 parse_expr(&at_limit).expect("scalar subquery height-1000 expression must parse");
5637 let rendered = expr.to_string();
5638 let select_count = rendered.matches("(SELECT ").count();
5639 drop(rendered);
5640 drop(expr);
5641 select_count
5642 });
5643 assert_eq!(rendered_selects, LIMIT - 1);
5644 assert_expression_depth_error(&scalar_subquery_expression(LIMIT + 1));
5645 }
5646
5647 #[test]
5648 fn test_signed_minimum_and_qualified_bases_round_trip_on_one_mib_stack() {
5649 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5650 for (base, canonical_base) in [
5651 ("-9223372036854775808", "-9223372036854775808"),
5652 ("schema.column", "schema.\"column\""),
5653 ] {
5654 let at_limit = wrap_function_to_height(base, LIMIT);
5655 let (height, rendered) = on_one_mib_stack(move || {
5656 let expr = parse_expr(&at_limit).expect("height-1000 base expression must parse");
5657 let height = normalized_ast_expr_height(&expr);
5658 let rendered = expr.to_string();
5659 let reparsed =
5660 parse_expr(&rendered).expect("formatted height-1000 base must reparse");
5661 assert_eq!(normalized_ast_expr_height(&reparsed), MAX_PARSE_DEPTH);
5662 assert_eq!(rendered, reparsed.to_string());
5663 drop(reparsed);
5664 drop(expr);
5665 (height, rendered)
5666 });
5667 assert_eq!(height, MAX_PARSE_DEPTH);
5668 assert!(rendered.contains(canonical_base));
5669
5670 let over_limit = wrap_function_to_height(base, LIMIT + 1);
5671 let error = on_one_mib_stack(move || {
5672 parse_expr(&over_limit).expect_err("height-1001 base must fail closed")
5673 });
5674 assert_eq!(
5675 error.kind,
5676 ParseErrorKind::ExpressionTooDeep {
5677 max: MAX_PARSE_DEPTH
5678 }
5679 );
5680 }
5681 }
5682
5683 #[test]
5684 fn test_mixed_deep_height_1000_parse_walk_format_and_drop_on_one_mib_stack() {
5685 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5686 let at_limit = mixed_deep_expression(LIMIT);
5687 let (height, rendered_len, walk_visits) = on_one_mib_stack(move || {
5688 let expr = parse_expr(&at_limit)
5689 .expect("mixed unary/function/subquery/binary height-1000 expression must parse");
5690 HEIGHT_WALK_VISITS.set(0);
5691 let height = normalized_ast_expr_height(&expr);
5692 let walk_visits = HEIGHT_WALK_VISITS.get();
5693 let rendered = expr.to_string();
5694 let rendered_len = rendered.len();
5695 drop(rendered);
5696 drop(expr);
5697 (height, rendered_len, walk_visits)
5698 });
5699 assert_eq!(height, MAX_PARSE_DEPTH);
5700 assert!(rendered_len > LIMIT);
5701 assert!(
5702 walk_visits <= at_limit_token_bound(LIMIT),
5703 "heap-backed cached-height walk must remain linear: {walk_visits} visits"
5704 );
5705
5706 let over_limit = mixed_deep_expression(LIMIT + 1);
5707 let error = on_one_mib_stack(move || {
5708 parse_expr(&over_limit).expect_err("mixed height-1001 expression must fail closed")
5709 });
5710 assert_eq!(
5711 error.kind,
5712 ParseErrorKind::ExpressionTooDeep {
5713 max: MAX_PARSE_DEPTH
5714 }
5715 );
5716 }
5717
5718 #[test]
5719 fn test_mixed_select_shape_round_trips_and_drops_on_one_mib_stack_at_exact_limit() {
5720 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5721 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";
5722 let at_limit = wrap_function_to_height(base, LIMIT);
5723 let (height, rendered_len) = on_one_mib_stack(move || {
5724 let expr = parse_expr(&at_limit)
5725 .expect("mixed CASE/BETWEEN/IN/CTE/JOIN/window height-1000 expression must parse");
5726 assert_eq!(normalized_ast_expr_height(&expr), MAX_PARSE_DEPTH);
5727 let rendered = expr.to_string();
5728 let reparsed =
5729 parse_expr(&rendered).expect("formatted mixed height-1000 expression must reparse");
5730 assert_eq!(normalized_ast_expr_height(&reparsed), MAX_PARSE_DEPTH);
5731 let rerendered = reparsed.to_string();
5732 assert_eq!(rendered, rerendered);
5733 let rendered_len = rendered.len();
5734 drop(rerendered);
5735 drop(reparsed);
5736 drop(rendered);
5737 drop(expr);
5738 (MAX_PARSE_DEPTH, rendered_len)
5739 });
5740 assert_eq!(height, MAX_PARSE_DEPTH);
5741 assert!(rendered_len > LIMIT);
5742
5743 let over_limit = wrap_function_to_height(base, LIMIT + 1);
5744 let error = on_one_mib_stack(move || {
5745 parse_expr(&over_limit).expect_err("mixed height-1001 expression must fail closed")
5746 });
5747 assert_eq!(
5748 error.kind,
5749 ParseErrorKind::ExpressionTooDeep {
5750 max: MAX_PARSE_DEPTH
5751 }
5752 );
5753 assert_eq!(
5754 error.message,
5755 format!(
5756 "Expression tree is too large (maximum depth {})",
5757 MAX_PARSE_DEPTH
5758 )
5759 );
5760 }
5761
5762 const fn at_limit_token_bound(height: usize) -> usize {
5763 height * 12
5764 }
5765
5766 #[test]
5767 fn test_998_wrapper_aggregate_filter_machine_steps_are_linear() {
5768 const WRAPPERS: usize = 998;
5769 let sql = format!(
5770 "{}1{} FILTER (WHERE 1)",
5771 "abs(".repeat(WRAPPERS),
5772 ")".repeat(WRAPPERS)
5773 );
5774 let token_count = Parser::from_sql(&sql).tokens.len();
5775 PARSE_MACHINE_STEPS.set(0);
5776 let expr = parse_expr(&sql).expect("near-match aggregate FILTER expression must parse");
5777 let visits = PARSE_MACHINE_STEPS.get();
5778 assert!(
5779 visits <= token_count.saturating_mul(8),
5780 "explicit parser machine revisited tokens superlinearly: {visits} steps for {token_count} tokens"
5781 );
5782 drop(expr);
5783 }
5784
5785 #[test]
5786 fn test_aggregate_order_by_auxiliary_roots_do_not_rescan_descendants() {
5787 let mut sql = "1".to_owned();
5788 for _ in 0..64 {
5789 sql = format!("f(0 ORDER BY {sql})");
5790 }
5791
5792 HEIGHT_WALK_VISITS.set(0);
5793 parse_expr(&sql).expect("nested aggregate ORDER BY expression must parse");
5794 assert_eq!(
5795 HEIGHT_WALK_VISITS.get(),
5796 0,
5797 "independent aggregate ORDER BY roots must not walk completed ASTs"
5798 );
5799 }
5800
5801 #[test]
5802 fn test_subquery_height_contract_matches_sqlite_height_of_select_fields() {
5803 for (sql, expected_height) in [
5804 ("SELECT 1 + 2 + 3", 3),
5805 ("SELECT 0 WHERE 1 + 2 + 3", 3),
5806 ("SELECT 0 GROUP BY 1 + 2 + 3 HAVING 1 + 2 + 3", 3),
5807 (
5808 "SELECT 0 ORDER BY 1 + 2 + 3 LIMIT 1 + 2 + 3 OFFSET 1 + 2 + 3",
5809 4,
5810 ),
5811 ("VALUES (1 + 2 + 3)", 3),
5812 ("SELECT 0 UNION ALL SELECT 1 + 2 + 3", 3),
5813 ] {
5814 assert_eq!(
5815 parsed_select_height(sql),
5816 expected_height,
5817 "official SELECT expression-height field was omitted: {sql}"
5818 );
5819 }
5820
5821 for sql in [
5822 "WITH c AS (SELECT 1 + 2 + 3) SELECT 0",
5823 "SELECT 0 FROM (SELECT 1 + 2 + 3)",
5824 "SELECT 0 FROM json_each(1 + 2 + 3)",
5825 "SELECT 0 FROM a JOIN b ON 1 + 2 + 3",
5826 "SELECT 0 WINDOW w AS (PARTITION BY 1 + 2 + 3 ORDER BY 1 + 2 + 3)",
5827 ] {
5828 assert_eq!(
5829 parsed_select_height(sql),
5830 1,
5831 "independent SQL root was incorrectly charged to its enclosing SELECT: {sql}"
5832 );
5833 }
5834 }
5835
5836 #[test]
5837 fn test_cached_height_matches_sqlite_grammar_rewrites() {
5838 for (sql, expected_height) in [
5839 ("NOT 1", 2),
5840 ("NOT EXISTS (SELECT 1)", 3),
5841 ("1 BETWEEN 2 AND 3", 2),
5842 ("1 NOT BETWEEN 2 AND 3", 3),
5843 ("1 LIKE 2", 2),
5844 ("1 NOT LIKE 2", 3),
5845 ("1 IN ()", 1),
5846 ("1 NOT IN ()", 1),
5847 ("abs(1) IN ()", 3),
5848 ("abs(1) NOT IN ()", 3),
5849 ("1 IN (2)", 3),
5850 ("1 IN (+2)", 4),
5851 ("1 NOT IN (2)", 4),
5852 ("1 IN (2, 3)", 2),
5853 ("1 NOT IN (2, 3)", 3),
5854 ("1 IN (SELECT 1 + 2)", 3),
5855 ("1 IN ((SELECT 1 + 2))", 3),
5856 ("(1, 2) IN ((3, 4))", 2),
5857 ("+1", 2),
5858 ("++1", 2),
5859 ("-+1", 2),
5860 ("(1 + 2 + 3, 4)", 1),
5861 ("(1 + 2 + 3, 4) + 5", 2),
5862 ] {
5863 assert_eq!(
5864 parsed_expr_height(sql),
5865 expected_height,
5866 "cached grammar height mismatch: {sql}"
5867 );
5868 }
5869 }
5870
5871 #[test]
5872 fn test_function_cached_height_excludes_auxiliary_expression_roots() {
5873 for (sql, expected_height) in [
5874 ("sum(1 + 2 + 3)", 4),
5875 ("sum(1 ORDER BY 1 + 2 + 3)", 2),
5876 ("sum(1) FILTER (WHERE 1 + 2 + 3)", 2),
5877 ("sum(1) OVER (ORDER BY 1 + 2 + 3)", 2),
5878 (
5879 "sum(1 ORDER BY 1 + 2 + 3) FILTER (WHERE 1 + 2 + 3) \
5880 OVER (ORDER BY 1 + 2 + 3)",
5881 2,
5882 ),
5883 ] {
5884 assert_eq!(
5885 parsed_expr_height(sql),
5886 expected_height,
5887 "auxiliary root leaked into the aggregate argument height: {sql}"
5888 );
5889 }
5890 }
5891
5892 #[test]
5893 fn test_function_auxiliary_roots_have_independent_1000_1001_boundaries() {
5894 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5895 let at_limit = repeated_infix_expression(LIMIT, " + ");
5896 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
5897 for sql in [
5898 format!("sum(1) FILTER (WHERE {at_limit})"),
5899 format!("row_number() OVER (ORDER BY {at_limit})"),
5900 format!("group_concat(1 ORDER BY {at_limit})"),
5901 ] {
5902 parse_expr(&sql).expect("height-1000 auxiliary root must remain independently valid");
5903 }
5904 for sql in [
5905 format!("sum(1) FILTER (WHERE {over_limit})"),
5906 format!("row_number() OVER (ORDER BY {over_limit})"),
5907 format!("group_concat(1 ORDER BY {over_limit})"),
5908 ] {
5909 assert_expression_depth_error(&sql);
5910 }
5911 }
5912
5913 #[test]
5914 fn test_select_auxiliary_roots_have_independent_1000_1001_boundaries() {
5915 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5916 let at_limit = repeated_infix_expression(LIMIT, " + ");
5917 let over_limit = repeated_infix_expression(LIMIT + 1, " + ");
5918 for sql in [
5919 format!("(WITH c AS (SELECT {at_limit}) SELECT 0)"),
5920 format!("(SELECT 0 FROM (SELECT {at_limit}))"),
5921 format!("(SELECT 0 FROM json_each({at_limit}))"),
5922 format!("(SELECT 0 FROM a JOIN b ON {at_limit})"),
5923 format!("(SELECT 0 WINDOW w AS (ORDER BY {at_limit}))"),
5924 ] {
5925 parse_expr(&sql).expect("height-1000 independent SELECT root must remain valid");
5926 }
5927 for sql in [
5928 format!("(WITH c AS (SELECT {over_limit}) SELECT 0)"),
5929 format!("(SELECT 0 FROM (SELECT {over_limit}))"),
5930 format!("(SELECT 0 FROM json_each({over_limit}))"),
5931 format!("(SELECT 0 FROM a JOIN b ON {over_limit})"),
5932 format!("(SELECT 0 WINDOW w AS (ORDER BY {over_limit}))"),
5933 ] {
5934 assert_expression_depth_error(&sql);
5935 }
5936 }
5937
5938 #[test]
5939 fn test_nested_subquery_height_is_threaded_without_ast_rescans() {
5940 let sql = scalar_subquery_expression(63);
5941 HEIGHT_WALK_VISITS.set(0);
5942 parse_expr(&sql).expect("tracked nested scalar-subquery height must parse");
5943 assert_eq!(
5944 HEIGHT_WALK_VISITS.get(),
5945 0,
5946 "nested subqueries must return tracked SELECT height in O(1) per parent"
5947 );
5948 }
5949
5950 #[test]
5951 fn test_subquery_height_contract_exact_1000_1001_boundary() {
5952 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
5953 let inner_at_limit = repeated_infix_expression(LIMIT - 1, " + ");
5954 for sql in [
5955 format!("(SELECT {inner_at_limit})"),
5956 format!("EXISTS (SELECT {inner_at_limit})"),
5957 format!("1 IN (SELECT {inner_at_limit})"),
5958 ] {
5959 parse_expr(&sql).expect("height-999 SELECT under one expression node must be accepted");
5960 }
5961
5962 let inner_over_limit = repeated_infix_expression(LIMIT, " + ");
5963 for sql in [
5964 format!("(SELECT {inner_over_limit})"),
5965 format!("EXISTS (SELECT {inner_over_limit})"),
5966 format!("1 IN (SELECT {inner_over_limit})"),
5967 ] {
5968 assert_expression_depth_error(&sql);
5969 }
5970 }
5971
5972 #[test]
5975 fn test_not_lower_precedence_than_comparison() {
5976 let expr = parse("NOT x = y");
5978 match &expr {
5979 Expr::UnaryOp {
5980 op: UnaryOp::Not,
5981 expr: inner,
5982 ..
5983 } => match inner.as_ref() {
5984 Expr::BinaryOp {
5985 op: BinaryOp::Eq, ..
5986 } => {}
5987 other => unreachable!("expected Eq inside NOT, got {other:?}"),
5988 },
5989 other => unreachable!("expected NOT(Eq), got {other:?}"),
5990 }
5991 }
5992
5993 #[test]
5994 fn test_unary_binds_tighter_than_collate() {
5995 let expr = parse("-x COLLATE NOCASE");
5997 match &expr {
5998 Expr::Collate {
5999 expr: inner,
6000 collation,
6001 ..
6002 } => {
6003 assert_eq!(collation, "NOCASE");
6004 assert!(matches!(
6005 inner.as_ref(),
6006 Expr::UnaryOp {
6007 op: UnaryOp::Negate,
6008 ..
6009 }
6010 ));
6011 }
6012 other => unreachable!("expected COLLATE(Negate), got {other:?}"),
6013 }
6014 }
6015
6016 #[test]
6017 fn test_arithmetic_precedence() {
6018 let expr = parse("1 + 2 * 3");
6020 match &expr {
6021 Expr::BinaryOp {
6022 op: BinaryOp::Add,
6023 left,
6024 right,
6025 ..
6026 } => {
6027 assert!(matches!(
6028 left.as_ref(),
6029 Expr::Literal(Literal::Integer(1), _)
6030 ));
6031 assert!(matches!(
6032 right.as_ref(),
6033 Expr::BinaryOp {
6034 op: BinaryOp::Multiply,
6035 ..
6036 }
6037 ));
6038 }
6039 other => unreachable!("expected Add(1, Mul(2,3)), got {other:?}"),
6040 }
6041 }
6042
6043 #[test]
6044 fn test_and_higher_than_or() {
6045 let expr = parse("a OR b AND c");
6047 match &expr {
6048 Expr::BinaryOp {
6049 op: BinaryOp::Or,
6050 right,
6051 ..
6052 } => {
6053 assert!(matches!(
6054 right.as_ref(),
6055 Expr::BinaryOp {
6056 op: BinaryOp::And,
6057 ..
6058 }
6059 ));
6060 }
6061 other => unreachable!("expected Or(a, And(b,c)), got {other:?}"),
6062 }
6063 }
6064
6065 #[test]
6068 fn test_cast_expression() {
6069 let expr = parse("CAST(42 AS INTEGER)");
6070 match &expr {
6071 Expr::Cast {
6072 expr: inner,
6073 type_name,
6074 ..
6075 } => {
6076 assert!(matches!(
6077 inner.as_ref(),
6078 Expr::Literal(Literal::Integer(42), _)
6079 ));
6080 assert_eq!(type_name.name, "INTEGER");
6081 }
6082 other => unreachable!("expected Cast, got {other:?}"),
6083 }
6084 }
6085
6086 #[test]
6087 fn test_cast_float_argument() {
6088 let expr = parse("CAST(x AS DECIMAL(10.5, -2.5))");
6090 match &expr {
6091 Expr::Cast { type_name, .. } => {
6092 assert_eq!(type_name.name, "DECIMAL");
6093 assert_eq!(type_name.arg1.as_deref(), Some("10.5"));
6094 assert_eq!(type_name.arg2.as_deref(), Some("-2.5"));
6095 }
6096 other => unreachable!("expected Cast with float args, got {other:?}"),
6097 }
6098 }
6099
6100 #[test]
6101 fn test_cast_signed_args() {
6102 let expr = parse("CAST(x AS NUMERIC(+5, -5))");
6104 match &expr {
6105 Expr::Cast { type_name, .. } => {
6106 assert_eq!(type_name.name, "NUMERIC");
6107 assert_eq!(type_name.arg1.as_deref(), Some("+5"));
6108 assert_eq!(type_name.arg2.as_deref(), Some("-5"));
6109 }
6110 other => unreachable!("expected Cast with signed args, got {other:?}"),
6111 }
6112 }
6113
6114 #[test]
6117 fn test_case_when_simple() {
6118 let expr = parse(
6119 "CASE x WHEN 1 THEN 'one' WHEN 2 THEN 'two' \
6120 ELSE 'other' END",
6121 );
6122 match &expr {
6123 Expr::Case {
6124 operand: Some(op),
6125 whens,
6126 else_expr: Some(_),
6127 ..
6128 } => {
6129 assert!(matches!(op.as_ref(), Expr::Column(..)));
6130 assert_eq!(whens.len(), 2);
6131 }
6132 other => unreachable!("expected simple CASE, got {other:?}"),
6133 }
6134 }
6135
6136 #[test]
6137 fn test_case_when_searched() {
6138 let expr = parse(
6139 "CASE WHEN x > 0 THEN 'pos' WHEN x < 0 THEN 'neg' \
6140 ELSE 'zero' END",
6141 );
6142 match &expr {
6143 Expr::Case {
6144 operand: None,
6145 whens,
6146 else_expr: Some(_),
6147 ..
6148 } => {
6149 assert_eq!(whens.len(), 2);
6150 assert!(matches!(
6151 &whens[0].0,
6152 Expr::BinaryOp {
6153 op: BinaryOp::Gt,
6154 ..
6155 }
6156 ));
6157 }
6158 other => unreachable!("expected searched CASE, got {other:?}"),
6159 }
6160 }
6161
6162 #[test]
6165 fn test_exists_subquery() {
6166 let expr = parse("EXISTS (SELECT 1)");
6167 assert!(matches!(expr, Expr::Exists { not: false, .. }));
6168 }
6169
6170 #[test]
6171 fn test_not_exists_subquery() {
6172 let expr = parse("NOT EXISTS (SELECT 1)");
6173 assert!(matches!(expr, Expr::Exists { not: true, .. }));
6174 }
6175
6176 #[test]
6177 fn test_exists_subquery_supports_qualified_table_with_alias() {
6178 let expr = parse("EXISTS (SELECT 1 FROM main.users AS u WHERE u.id = 1)");
6179 match expr {
6180 Expr::Exists { subquery, .. } => match subquery.body.select {
6181 SelectCore::Select {
6182 from: Some(from), ..
6183 } => match from.source {
6184 TableOrSubquery::Table { name, alias, .. } => {
6185 assert_eq!(name.schema.as_deref(), Some("main"));
6186 assert_eq!(name.name, "users");
6187 assert_eq!(alias.as_deref(), Some("u"));
6188 }
6189 other => unreachable!("expected table source, got {other:?}"),
6190 },
6191 other => unreachable!("expected SELECT core with FROM, got {other:?}"),
6192 },
6193 other => unreachable!("expected EXISTS subquery, got {other:?}"),
6194 }
6195 }
6196
6197 #[test]
6200 fn test_in_expr_list() {
6201 let expr = parse("x IN (1, 2, 3)");
6202 match &expr {
6203 Expr::In {
6204 not: false,
6205 set: InSet::List(items),
6206 ..
6207 } => assert_eq!(items.len(), 3),
6208 other => unreachable!("expected IN list, got {other:?}"),
6209 }
6210 }
6211
6212 #[test]
6213 fn test_explicit_row_value_in_list_rejects_mismatched_element_arities() {
6214 for (sql, expected_message) in [
6215 (
6216 "(a, b, c) IN ((1, 2))",
6217 "IN(...) element has 2 terms - expected 3",
6218 ),
6219 (
6220 "(a, b) IN ((1, 2, 3))",
6221 "IN(...) element has 3 terms - expected 2",
6222 ),
6223 ("(a, b) IN (1)", "IN(...) element has 1 term - expected 2"),
6224 (
6225 "(a, b) IN ((1, 2), 3)",
6226 "IN(...) element has 1 term - expected 2",
6227 ),
6228 (
6229 "(a, b) NOT IN ((1, 2), (3, 4, 5))",
6230 "IN(...) element has 3 terms - expected 2",
6231 ),
6232 (
6233 "0 AND (a, b) IN (1)",
6234 "IN(...) element has 1 term - expected 2",
6235 ),
6236 (
6237 "(a, b) IN (+(SELECT 1, 2))",
6238 "IN(...) element has 1 term - expected 2",
6239 ),
6240 ] {
6241 let error = parse_expr(sql).expect_err("mismatched vector IN arity must fail parsing");
6242 assert_eq!(
6243 error.kind,
6244 ParseErrorKind::Syntax,
6245 "unexpected kind for `{sql}`"
6246 );
6247 assert_eq!(
6248 error.message, expected_message,
6249 "unexpected error for `{sql}`"
6250 );
6251 }
6252 }
6253
6254 #[test]
6255 fn test_subquery_lhs_defers_in_list_arity_to_semantic_resolution() {
6256 for sql in [
6257 "(SELECT 1, 2) IN (1)",
6258 "(SELECT 1, 2) IN ((1, 2, 3))",
6259 "(VALUES (1, 2, 3)) IN ((1, 2))",
6260 "(SELECT 1, 2 UNION ALL SELECT 3, 4) NOT IN (5)",
6261 "0 AND (SELECT 1, 2) IN (1)",
6262 "(SELECT 1, 2) IN (nosuch_vector_function())",
6263 ] {
6264 let expr = parse_expr(sql).unwrap_or_else(|error| {
6265 panic!("subquery-expression IN semantics must be deferred for `{sql}`: {error}")
6266 });
6267 assert!(
6268 matches!(expr, Expr::In { .. } | Expr::BinaryOp { .. }),
6269 "unexpected AST for `{sql}`"
6270 );
6271 }
6272 }
6273
6274 #[test]
6275 fn test_vector_in_list_accepts_matching_empty_and_singleton_subquery_forms() {
6276 for sql in [
6277 "(a, b) IN ((1, 2), (3, 4))",
6278 "(a, b) NOT IN ((1, 2), (3, 4))",
6279 "(a, b) IN ()",
6280 "(a, b) IN ((SELECT 1, 2))",
6281 "(a, b) IN ((SELECT 1))",
6282 "(a, b) IN ((SELECT 1, 2, 3))",
6283 "(a, b) IN ((SELECT 1), (SELECT 2))",
6288 "(SELECT 1, 2) IN ((1, 2), (3, 4))",
6289 "(VALUES (1, 2), (3, 4)) NOT IN ((1, 2))",
6290 "(SELECT 1, 2 UNION ALL SELECT 3, 4) IN ((1, 2))",
6291 "(SELECT * FROM t) IN (1)",
6293 "(SELECT t.* FROM t) IN ((1, 2, 3))",
6294 "(SELECT 1, 2) IN ((SELECT 1))",
6296 "(SELECT 1, 2) IN (SELECT 1)",
6297 ] {
6298 let expr = parse_expr(sql).unwrap_or_else(|error| {
6299 panic!("matching vector IN list must parse for `{sql}`: {error}")
6300 });
6301 assert!(
6302 matches!(expr, Expr::In { .. }),
6303 "unexpected AST for `{sql}`"
6304 );
6305 }
6306 }
6307
6308 #[test]
6309 fn test_vector_in_list_trailing_comma_syntax_error_precedes_arity() {
6310 let error = parse_expr("(a, b) IN (1,)")
6311 .expect_err("a trailing comma in an IN list must fail parsing");
6312 assert_eq!(error.kind, ParseErrorKind::Syntax);
6313 assert_eq!(error.message, "unexpected token in expression: RightParen");
6314 }
6315
6316 #[test]
6317 fn test_statement_parsers_reject_vector_in_list_arity_mismatches() {
6318 for (sql, expected_message) in [
6319 (
6320 "SELECT (a, b) IN (1) FROM t",
6321 "IN(...) element has 1 term - expected 2",
6322 ),
6323 (
6324 "UPDATE t SET flag = (a, b) IN ((1, 2, 3))",
6325 "IN(...) element has 3 terms - expected 2",
6326 ),
6327 (
6328 "DELETE FROM t WHERE (a, b) NOT IN ((1, 2), 3)",
6329 "IN(...) element has 1 term - expected 2",
6330 ),
6331 ] {
6332 let error = Parser::from_sql(sql)
6333 .parse_statement()
6334 .expect_err("statement parser must reject mismatched vector IN arity");
6335 assert_eq!(
6336 error.kind,
6337 ParseErrorKind::Syntax,
6338 "unexpected kind for `{sql}`"
6339 );
6340 assert_eq!(
6341 error.message, expected_message,
6342 "unexpected error for `{sql}`"
6343 );
6344 }
6345 }
6346
6347 #[test]
6348 fn test_statement_parsers_defer_subquery_in_list_arity() {
6349 for sql in [
6350 "SELECT (SELECT 1, 2) IN (1)",
6351 "UPDATE t SET flag = (SELECT 1, 2) IN ((1, 2, 3))",
6352 "DELETE FROM t WHERE 0 AND (SELECT 1, 2) NOT IN ((1, 2), 3)",
6353 ] {
6354 Parser::from_sql(sql)
6355 .parse_statement()
6356 .unwrap_or_else(|error| {
6357 panic!("statement semantics must be deferred for `{sql}`: {error}")
6358 });
6359 }
6360 }
6361
6362 #[test]
6363 fn test_in_subquery() {
6364 let expr = parse("x IN (SELECT y FROM t)");
6365 assert!(matches!(
6366 expr,
6367 Expr::In {
6368 not: false,
6369 set: InSet::Subquery(_),
6370 ..
6371 }
6372 ));
6373 }
6374
6375 #[test]
6376 fn test_in_subquery_with_order_by_and_limit() {
6377 let expr =
6379 parse("id NOT IN (SELECT id FROM search_recipes ORDER BY updated_ts DESC LIMIT 5)");
6380 match &expr {
6381 Expr::In {
6382 not: true,
6383 set: InSet::Subquery(stmt),
6384 ..
6385 } => {
6386 assert_eq!(stmt.order_by.len(), 1, "ORDER BY should be parsed");
6387 assert!(stmt.limit.is_some(), "LIMIT should be parsed");
6388 }
6389 other => unreachable!("expected NOT IN subquery, got {other:?}"),
6390 }
6391 }
6392
6393 #[test]
6394 fn test_in_subquery_supports_group_by_and_having() {
6395 let expr = parse("x IN (SELECT y FROM t GROUP BY y HAVING COUNT(*) > 1)");
6396 match expr {
6397 Expr::In {
6398 set: InSet::Subquery(stmt),
6399 ..
6400 } => match stmt.body.select {
6401 SelectCore::Select {
6402 group_by, having, ..
6403 } => {
6404 assert_eq!(group_by.len(), 1, "GROUP BY should be parsed");
6405 assert!(having.is_some(), "HAVING should be parsed");
6406 }
6407 SelectCore::Values(_) => unreachable!("expected SELECT core"),
6408 },
6409 other => unreachable!("expected IN subquery, got {other:?}"),
6410 }
6411 }
6412
6413 #[test]
6414 fn test_not_in() {
6415 let expr = parse("x NOT IN (1, 2)");
6416 assert!(matches!(expr, Expr::In { not: true, .. }));
6417 }
6418
6419 #[test]
6420 fn test_in_table_name() {
6421 let expr = parse("x IN t");
6422 assert!(matches!(
6423 expr,
6424 Expr::In {
6425 not: false,
6426 set: InSet::Table(_),
6427 ..
6428 }
6429 ));
6430 }
6431
6432 #[test]
6433 fn test_not_in_table_name() {
6434 let expr = parse("x NOT IN t");
6435 assert!(matches!(
6436 expr,
6437 Expr::In {
6438 not: true,
6439 set: InSet::Table(_),
6440 ..
6441 }
6442 ));
6443 }
6444
6445 #[test]
6446 fn test_in_schema_table_name() {
6447 let expr = parse("x IN main.t");
6448 match expr {
6449 Expr::In {
6450 set: InSet::Table(name),
6451 ..
6452 } => {
6453 assert_eq!(name.schema.as_deref(), Some("main"));
6454 assert_eq!(name.name, "t");
6455 }
6456 other => unreachable!("expected IN table form, got {other:?}"),
6457 }
6458 }
6459
6460 #[test]
6463 fn test_between_and() {
6464 let expr = parse("x BETWEEN 1 AND 10");
6465 assert!(matches!(expr, Expr::Between { not: false, .. }));
6466 }
6467
6468 #[test]
6469 fn test_not_between() {
6470 let expr = parse("x NOT BETWEEN 1 AND 10");
6471 assert!(matches!(expr, Expr::Between { not: true, .. }));
6472 }
6473
6474 #[test]
6475 fn test_between_does_not_consume_outer_and() {
6476 let expr = parse("x BETWEEN 1 AND 10 AND y = 1");
6478 match &expr {
6479 Expr::BinaryOp {
6480 op: BinaryOp::And,
6481 left,
6482 ..
6483 } => assert!(matches!(left.as_ref(), Expr::Between { .. })),
6484 other => unreachable!("expected AND(BETWEEN, Eq), got {other:?}"),
6485 }
6486 }
6487
6488 #[test]
6491 fn test_like_pattern() {
6492 let expr = parse("name LIKE '%foo%'");
6493 assert!(matches!(
6494 expr,
6495 Expr::Like {
6496 op: LikeOp::Like,
6497 not: false,
6498 escape: None,
6499 ..
6500 }
6501 ));
6502 }
6503
6504 #[test]
6505 fn test_like_escape() {
6506 let expr = parse("name LIKE '%\\%%' ESCAPE '\\'");
6507 assert!(matches!(
6508 expr,
6509 Expr::Like {
6510 op: LikeOp::Like,
6511 escape: Some(_),
6512 ..
6513 }
6514 ));
6515 }
6516
6517 #[test]
6518 fn test_glob_pattern() {
6519 let expr = parse("path GLOB '*.rs'");
6520 assert!(matches!(
6521 expr,
6522 Expr::Like {
6523 op: LikeOp::Glob,
6524 not: false,
6525 ..
6526 }
6527 ));
6528 }
6529
6530 #[test]
6531 fn test_glob_character_class() {
6532 let expr = parse("name GLOB '[a-z]*'");
6533 match &expr {
6534 Expr::Like {
6535 op: LikeOp::Glob,
6536 pattern,
6537 ..
6538 } => assert!(matches!(
6539 pattern.as_ref(),
6540 Expr::Literal(Literal::String(s), _) if s == "[a-z]*"
6541 )),
6542 other => unreachable!("expected GLOB, got {other:?}"),
6543 }
6544 }
6545
6546 #[test]
6549 fn test_collate_override() {
6550 let expr = parse("name COLLATE NOCASE");
6551 match &expr {
6552 Expr::Collate { collation, .. } => {
6553 assert_eq!(collation, "NOCASE");
6554 }
6555 other => unreachable!("expected COLLATE, got {other:?}"),
6556 }
6557 }
6558
6559 #[test]
6562 fn test_json_arrow_operator() {
6563 let expr = parse("data -> 'key'");
6564 assert!(matches!(
6565 expr,
6566 Expr::JsonAccess {
6567 arrow: JsonArrow::Arrow,
6568 ..
6569 }
6570 ));
6571 }
6572
6573 #[test]
6574 fn test_json_double_arrow_operator() {
6575 let expr = parse("data ->> 'key'");
6576 assert!(matches!(
6577 expr,
6578 Expr::JsonAccess {
6579 arrow: JsonArrow::DoubleArrow,
6580 ..
6581 }
6582 ));
6583 }
6584
6585 #[test]
6588 fn test_is_null() {
6589 assert!(matches!(
6590 parse("42"),
6591 Expr::Literal(Literal::Integer(42), _)
6592 ));
6593 assert!(matches!(parse("3.14"), Expr::Literal(Literal::Float(_), _)));
6594 assert!(matches!(
6595 parse("'hello'"),
6596 Expr::Literal(Literal::String(_), _)
6597 ));
6598 assert!(matches!(parse("NULL"), Expr::Literal(Literal::Null, _)));
6599 assert!(matches!(parse("TRUE"), Expr::Literal(Literal::True, _)));
6600 assert!(matches!(parse("FALSE"), Expr::Literal(Literal::False, _)));
6601 }
6602
6603 #[test]
6610 fn test_isnull_eq_isnull_unparenthesized_left_associative() {
6611 let expr = parse("a IS NULL = b IS NULL");
6612 match &expr {
6613 Expr::IsNull {
6614 expr: inner,
6615 not: false,
6616 ..
6617 } => match inner.as_ref() {
6618 Expr::BinaryOp {
6619 op: BinaryOp::Eq,
6620 left,
6621 right,
6622 ..
6623 } => {
6624 assert!(
6625 matches!(left.as_ref(), Expr::IsNull { not: false, .. }),
6626 "expected (a IS NULL) on the left, got {left:?}"
6627 );
6628 assert!(
6629 matches!(right.as_ref(), Expr::Column(..)),
6630 "expected bare column b on the right, got {right:?}"
6631 );
6632 }
6633 other => unreachable!("expected Eq inside IsNull, got {other:?}"),
6634 },
6635 other => unreachable!("expected IsNull(Eq(IsNull(a), b)), got {other:?}"),
6636 }
6637 }
6638
6639 #[test]
6644 fn test_isnull_eq_isnull_parenthesized_round_trip() {
6645 let assert_shape = |expr: &Expr| match expr {
6646 Expr::BinaryOp {
6647 op: BinaryOp::Eq,
6648 left,
6649 right,
6650 ..
6651 } => {
6652 assert!(
6653 matches!(left.as_ref(), Expr::IsNull { not: false, .. }),
6654 "expected IsNull on the left, got {left:?}"
6655 );
6656 assert!(
6657 matches!(right.as_ref(), Expr::IsNull { not: false, .. }),
6658 "expected IsNull on the right, got {right:?}"
6659 );
6660 }
6661 other => unreachable!("expected Eq(IsNull, IsNull), got {other:?}"),
6662 };
6663 let expr = parse("(a IS NULL) = (b IS NULL)");
6664 assert_shape(&expr);
6665 let rendered = expr.to_string();
6666 assert_eq!(rendered, "a IS NULL = (b IS NULL)");
6667 let reparsed = parse(&rendered);
6668 assert_shape(&reparsed);
6669 assert_eq!(reparsed.to_string(), rendered, "round-trip not idempotent");
6670 }
6671
6672 #[test]
6677 fn test_is_null_followed_by_tighter_operator_binds_to_null() {
6678 let expr = parse("1 IS NULL < 2");
6679 match &expr {
6680 Expr::BinaryOp {
6681 op: BinaryOp::Is,
6682 right,
6683 ..
6684 } => assert!(
6685 matches!(
6686 right.as_ref(),
6687 Expr::BinaryOp {
6688 op: BinaryOp::Lt,
6689 ..
6690 }
6691 ),
6692 "expected Lt(NULL, 2) on the right of IS, got {right:?}"
6693 ),
6694 other => unreachable!("expected Is(1, Lt(NULL, 2)), got {other:?}"),
6695 }
6696 }
6697
6698 #[test]
6702 fn test_is_parenthesized_null_folds_to_isnull() {
6703 assert!(matches!(
6704 parse("x IS (NULL)"),
6705 Expr::IsNull { not: false, .. }
6706 ));
6707 assert!(matches!(
6708 parse("x IS NOT (NULL)"),
6709 Expr::IsNull { not: true, .. }
6710 ));
6711 }
6712
6713 #[test]
6714 fn test_placeholders() {
6715 assert!(matches!(
6716 parse("?"),
6717 Expr::Placeholder(PlaceholderType::Anonymous, _)
6718 ));
6719 assert!(matches!(
6720 parse("?1"),
6721 Expr::Placeholder(PlaceholderType::Numbered(1), _)
6722 ));
6723 assert!(matches!(
6724 parse(":name"),
6725 Expr::Placeholder(PlaceholderType::ColonNamed(_), _)
6726 ));
6727 }
6728
6729 #[test]
6732 fn test_column_bare() {
6733 match &parse("x") {
6734 Expr::Column(
6735 ColumnRef {
6736 table: None,
6737 column,
6738 },
6739 _,
6740 ) => assert_eq!(column.as_ref(), "x"),
6741 other => unreachable!("expected bare column, got {other:?}"),
6742 }
6743 }
6744
6745 #[test]
6746 fn test_column_qualified() {
6747 match &parse("t.x") {
6748 Expr::Column(
6749 ColumnRef {
6750 table: Some(t),
6751 column,
6752 },
6753 _,
6754 ) => {
6755 assert_eq!(t.as_ref(), "t");
6756 assert_eq!(column.as_ref(), "x");
6757 }
6758 other => unreachable!("expected qualified column, got {other:?}"),
6759 }
6760 }
6761
6762 #[test]
6763 fn test_qualified_column_retains_dot_height_and_exact_boundary() {
6764 assert_eq!(parsed_expr_height("x"), 1);
6765 assert_eq!(parsed_expr_height("t.x"), 2);
6766
6767 const LIMIT: usize = MAX_PARSE_DEPTH as usize;
6768 let at_limit = format!("{}t.x", "~".repeat(LIMIT - 2));
6769 parse_expr(&at_limit).expect("998 unary nodes plus qualified column have height 1000");
6770
6771 let over_limit = format!("{}t.x", "~".repeat(LIMIT - 1));
6772 assert_expression_depth_error(&over_limit);
6773 }
6774
6775 #[test]
6778 fn test_concat_higher_than_add() {
6779 let expr = parse("a + b || c");
6781 match &expr {
6782 Expr::BinaryOp {
6783 op: BinaryOp::Add,
6784 right,
6785 ..
6786 } => assert!(matches!(
6787 right.as_ref(),
6788 Expr::BinaryOp {
6789 op: BinaryOp::Concat,
6790 ..
6791 }
6792 )),
6793 other => unreachable!("expected Add(a, Concat(b,c)), got {other:?}"),
6794 }
6795 }
6796
6797 #[test]
6800 fn test_parenthesized() {
6801 let expr = parse("(1 + 2) * 3");
6803 match &expr {
6804 Expr::BinaryOp {
6805 op: BinaryOp::Multiply,
6806 left,
6807 ..
6808 } => assert!(matches!(
6809 left.as_ref(),
6810 Expr::BinaryOp {
6811 op: BinaryOp::Add,
6812 ..
6813 }
6814 )),
6815 other => unreachable!("expected Mul(Add, 3), got {other:?}"),
6816 }
6817 }
6818
6819 #[test]
6822 fn test_is_operator() {
6823 assert!(matches!(
6824 parse("a IS b"),
6825 Expr::BinaryOp {
6826 op: BinaryOp::Is,
6827 ..
6828 }
6829 ));
6830 }
6831
6832 #[test]
6833 fn test_is_not_operator() {
6834 assert!(matches!(
6835 parse("a IS NOT b"),
6836 Expr::BinaryOp {
6837 op: BinaryOp::IsNot,
6838 ..
6839 }
6840 ));
6841 }
6842
6843 #[test]
6846 fn test_bitwise_ops() {
6847 let expr = parse("a & b | c");
6849 match &expr {
6850 Expr::BinaryOp {
6851 op: BinaryOp::BitOr,
6852 left,
6853 ..
6854 } => assert!(
6855 matches!(
6856 left.as_ref(),
6857 Expr::BinaryOp {
6858 op: BinaryOp::BitAnd,
6859 ..
6860 }
6861 ),
6862 "bitwise operators should be left-associative"
6863 ),
6864 other => unreachable!("expected BitOr(BitAnd, c), got {other:?}"),
6865 }
6866 }
6867
6868 #[test]
6869 fn test_bitnot() {
6870 assert!(matches!(
6871 parse("~x"),
6872 Expr::UnaryOp {
6873 op: UnaryOp::BitNot,
6874 ..
6875 }
6876 ));
6877 }
6878
6879 #[test]
6882 fn test_complex_where_clause() {
6883 let expr = parse("a > 1 AND b LIKE '%test%' OR NOT c IS NULL");
6884 assert!(matches!(
6885 expr,
6886 Expr::BinaryOp {
6887 op: BinaryOp::Or,
6888 ..
6889 }
6890 ));
6891 }
6892
6893 #[test]
6894 fn test_not_like_pattern() {
6895 assert!(matches!(
6896 parse("name NOT LIKE '%foo'"),
6897 Expr::Like {
6898 op: LikeOp::Like,
6899 not: true,
6900 ..
6901 }
6902 ));
6903 }
6904
6905 #[test]
6906 fn test_subquery_expr() {
6907 assert!(matches!(parse("(SELECT 1)"), Expr::Subquery(..)));
6908 }
6909
6910 #[test]
6918 fn test_pratt_level1_or_left_assoc() {
6919 let expr = parse("a OR b OR c");
6921 match &expr {
6922 Expr::BinaryOp {
6923 op: BinaryOp::Or,
6924 left,
6925 ..
6926 } => assert!(
6927 matches!(
6928 left.as_ref(),
6929 Expr::BinaryOp {
6930 op: BinaryOp::Or,
6931 ..
6932 }
6933 ),
6934 "OR should be left-associative"
6935 ),
6936 other => unreachable!("expected Or(Or(a,b), c), got {other:?}"),
6937 }
6938 }
6939
6940 #[test]
6942 fn test_pratt_level2_and_left_assoc() {
6943 let expr = parse("a AND b AND c");
6945 match &expr {
6946 Expr::BinaryOp {
6947 op: BinaryOp::And,
6948 left,
6949 ..
6950 } => assert!(
6951 matches!(
6952 left.as_ref(),
6953 Expr::BinaryOp {
6954 op: BinaryOp::And,
6955 ..
6956 }
6957 ),
6958 "AND should be left-associative"
6959 ),
6960 other => unreachable!("expected And(And(a,b), c), got {other:?}"),
6961 }
6962 }
6963
6964 #[test]
6966 fn test_pratt_level3_not_higher_than_and() {
6967 let expr = parse("NOT a AND b");
6969 match &expr {
6970 Expr::BinaryOp {
6971 op: BinaryOp::And,
6972 left,
6973 ..
6974 } => assert!(
6975 matches!(
6976 left.as_ref(),
6977 Expr::UnaryOp {
6978 op: UnaryOp::Not,
6979 ..
6980 }
6981 ),
6982 "NOT should bind tighter than AND"
6983 ),
6984 other => unreachable!("expected And(Not(a), b), got {other:?}"),
6985 }
6986 }
6987
6988 #[test]
6990 fn test_pratt_level4_equality_left_assoc() {
6991 let expr = parse("a = b != c");
6993 match &expr {
6994 Expr::BinaryOp {
6995 op: BinaryOp::Ne,
6996 left,
6997 ..
6998 } => assert!(
6999 matches!(
7000 left.as_ref(),
7001 Expr::BinaryOp {
7002 op: BinaryOp::Eq,
7003 ..
7004 }
7005 ),
7006 "equality operators should be left-associative at same level"
7007 ),
7008 other => unreachable!("expected Ne(Eq(a,b), c), got {other:?}"),
7009 }
7010 }
7011
7012 #[test]
7016 fn test_pratt_level4_vs_level5_eq_lt_boundary() {
7017 let expr = parse("a = b < c");
7020 match &expr {
7021 Expr::BinaryOp {
7022 op: BinaryOp::Eq,
7023 right,
7024 ..
7025 } => assert!(
7026 matches!(
7027 right.as_ref(),
7028 Expr::BinaryOp {
7029 op: BinaryOp::Lt,
7030 ..
7031 }
7032 ),
7033 "a = b < c MUST parse as a = (b < c): relational binds tighter"
7034 ),
7035 other => unreachable!("expected Eq(a, Lt(b,c)), got {other:?}"),
7036 }
7037 }
7038
7039 #[test]
7041 fn test_pratt_level4_vs_level5_ne_ge_boundary() {
7042 let expr = parse("a != b >= c");
7044 match &expr {
7045 Expr::BinaryOp {
7046 op: BinaryOp::Ne,
7047 right,
7048 ..
7049 } => assert!(
7050 matches!(
7051 right.as_ref(),
7052 Expr::BinaryOp {
7053 op: BinaryOp::Ge,
7054 ..
7055 }
7056 ),
7057 "a != b >= c must parse as a != (b >= c)"
7058 ),
7059 other => unreachable!("expected Ne(Ge(b,c)), got {other:?}"),
7060 }
7061 }
7062
7063 #[test]
7065 fn test_pratt_level5_relational_left_assoc() {
7066 let expr = parse("a < b >= c");
7068 match &expr {
7069 Expr::BinaryOp {
7070 op: BinaryOp::Ge,
7071 left,
7072 ..
7073 } => assert!(
7074 matches!(
7075 left.as_ref(),
7076 Expr::BinaryOp {
7077 op: BinaryOp::Lt,
7078 ..
7079 }
7080 ),
7081 "relational operators should be left-associative"
7082 ),
7083 other => unreachable!("expected Ge(Lt(a,b), c), got {other:?}"),
7084 }
7085 }
7086
7087 #[test]
7089 fn test_pratt_level6_bitwise_tighter_than_comparison() {
7090 let expr = parse("a < b & c");
7092 match &expr {
7093 Expr::BinaryOp {
7094 op: BinaryOp::Lt,
7095 right,
7096 ..
7097 } => assert!(
7098 matches!(
7099 right.as_ref(),
7100 Expr::BinaryOp {
7101 op: BinaryOp::BitAnd,
7102 ..
7103 }
7104 ),
7105 "bitwise should bind tighter than relational"
7106 ),
7107 other => unreachable!("expected Lt(a, BitAnd(b,c)), got {other:?}"),
7108 }
7109 }
7110
7111 #[test]
7113 fn test_pratt_level6_shifts_left_assoc() {
7114 let expr = parse("a << b >> c");
7116 match &expr {
7117 Expr::BinaryOp {
7118 op: BinaryOp::ShiftRight,
7119 left,
7120 ..
7121 } => assert!(
7122 matches!(
7123 left.as_ref(),
7124 Expr::BinaryOp {
7125 op: BinaryOp::ShiftLeft,
7126 ..
7127 }
7128 ),
7129 "shift operators should be left-associative"
7130 ),
7131 other => unreachable!("expected ShiftRight(ShiftLeft(a,b), c), got {other:?}"),
7132 }
7133 }
7134
7135 #[test]
7137 fn test_pratt_level7_add_sub_left_assoc() {
7138 let expr = parse("a + b - c");
7140 match &expr {
7141 Expr::BinaryOp {
7142 op: BinaryOp::Subtract,
7143 left,
7144 ..
7145 } => assert!(
7146 matches!(
7147 left.as_ref(),
7148 Expr::BinaryOp {
7149 op: BinaryOp::Add,
7150 ..
7151 }
7152 ),
7153 "add/sub should be left-associative"
7154 ),
7155 other => unreachable!("expected Sub(Add(a,b), c), got {other:?}"),
7156 }
7157 }
7158
7159 #[test]
7160 fn test_pratt_level7_add_sub_left_assoc_reverse() {
7161 let expr = parse("a - b + c");
7163 match &expr {
7164 Expr::BinaryOp {
7165 op: BinaryOp::Add,
7166 left,
7167 ..
7168 } => assert!(
7169 matches!(
7170 left.as_ref(),
7171 Expr::BinaryOp {
7172 op: BinaryOp::Subtract,
7173 ..
7174 }
7175 ),
7176 "add/sub should be left-associative"
7177 ),
7178 other => unreachable!("expected Add(Sub(a,b), c), got {other:?}"),
7179 }
7180 }
7181
7182 #[test]
7183 fn test_pratt_level9_concat_tighter_than_mul() {
7184 let expr = parse("a * b || c");
7186 match &expr {
7187 Expr::BinaryOp {
7188 op: BinaryOp::Multiply,
7189 right,
7190 ..
7191 } => assert!(
7192 matches!(
7193 right.as_ref(),
7194 Expr::BinaryOp {
7195 op: BinaryOp::Concat,
7196 ..
7197 }
7198 ),
7199 "concat should bind tighter than multiply"
7200 ),
7201 other => unreachable!("expected Mul(a, Concat(b,c)), got {other:?}"),
7202 }
7203 }
7204
7205 #[test]
7207 fn test_pratt_level8_mul_div_left_assoc() {
7208 let expr = parse("a * b / c");
7210 match &expr {
7211 Expr::BinaryOp {
7212 op: BinaryOp::Divide,
7213 left,
7214 ..
7215 } => assert!(
7216 matches!(
7217 left.as_ref(),
7218 Expr::BinaryOp {
7219 op: BinaryOp::Multiply,
7220 ..
7221 }
7222 ),
7223 "mul/div should be left-associative"
7224 ),
7225 other => unreachable!("expected Div(Mul(a,b), c), got {other:?}"),
7226 }
7227 }
7228
7229 #[test]
7230 fn test_pratt_level8_modulo() {
7231 let expr = parse("a * b % c");
7233 match &expr {
7234 Expr::BinaryOp {
7235 op: BinaryOp::Modulo,
7236 left,
7237 ..
7238 } => assert!(
7239 matches!(
7240 left.as_ref(),
7241 Expr::BinaryOp {
7242 op: BinaryOp::Multiply,
7243 ..
7244 }
7245 ),
7246 "modulo and multiply at same level, left-associative"
7247 ),
7248 other => unreachable!("expected Mod(Mul(a,b), c), got {other:?}"),
7249 }
7250 }
7251
7252 #[test]
7254 fn test_pratt_level9_concat_left_assoc() {
7255 let expr = parse("a || b || c");
7257 match &expr {
7258 Expr::BinaryOp {
7259 op: BinaryOp::Concat,
7260 left,
7261 ..
7262 } => assert!(
7263 matches!(
7264 left.as_ref(),
7265 Expr::BinaryOp {
7266 op: BinaryOp::Concat,
7267 ..
7268 }
7269 ),
7270 "concatenation should be left-associative"
7271 ),
7272 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
7273 }
7274 }
7275
7276 #[test]
7277 fn test_pratt_level9_concat_left_assoc_reverse() {
7278 let expr = parse("a || b || c");
7280 match &expr {
7281 Expr::BinaryOp {
7282 op: BinaryOp::Concat,
7283 left,
7284 ..
7285 } => assert!(
7286 matches!(
7287 left.as_ref(),
7288 Expr::BinaryOp {
7289 op: BinaryOp::Concat,
7290 ..
7291 }
7292 ),
7293 "concatenation should be left-associative"
7294 ),
7295 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
7296 }
7297 }
7298
7299 #[test]
7301 fn test_pratt_level10_collate_tighter_than_concat() {
7302 let expr = parse("a || b COLLATE NOCASE");
7304 match &expr {
7305 Expr::BinaryOp {
7306 op: BinaryOp::Concat,
7307 right,
7308 ..
7309 } => assert!(
7310 matches!(right.as_ref(), Expr::Collate { .. }),
7311 "COLLATE should bind tighter than concat"
7312 ),
7313 other => unreachable!("expected Concat(a, Collate(b)), got {other:?}"),
7314 }
7315 }
7316
7317 #[test]
7319 fn test_pratt_level11_unary_negate_tightest() {
7320 let expr = parse("-a * b");
7322 match &expr {
7323 Expr::BinaryOp {
7324 op: BinaryOp::Multiply,
7325 left,
7326 ..
7327 } => assert!(
7328 matches!(
7329 left.as_ref(),
7330 Expr::UnaryOp {
7331 op: UnaryOp::Negate,
7332 ..
7333 }
7334 ),
7335 "unary minus should bind tighter than multiply"
7336 ),
7337 other => unreachable!("expected Mul(Negate(a), b), got {other:?}"),
7338 }
7339 }
7340
7341 #[test]
7342 fn test_pratt_level11_bitnot_tightest() {
7343 let expr = parse("~a + b");
7345 match &expr {
7346 Expr::BinaryOp {
7347 op: BinaryOp::Add,
7348 left,
7349 ..
7350 } => assert!(
7351 matches!(
7352 left.as_ref(),
7353 Expr::UnaryOp {
7354 op: UnaryOp::BitNot,
7355 ..
7356 }
7357 ),
7358 "bitwise NOT should bind tighter than addition"
7359 ),
7360 other => unreachable!("expected Add(BitNot(a), b), got {other:?}"),
7361 }
7362 }
7363
7364 #[test]
7366 fn test_pratt_escape_not_infix_operator() {
7367 let expr = parse("a LIKE b ESCAPE c");
7369 match &expr {
7370 Expr::Like {
7371 escape: Some(esc), ..
7372 } => assert!(
7373 matches!(esc.as_ref(), Expr::Column(_, _)),
7374 "ESCAPE should be parsed as suffix of LIKE, not standalone infix"
7375 ),
7376 other => unreachable!("expected Like with escape, got {other:?}"),
7377 }
7378 }
7379
7380 #[test]
7381 fn test_pratt_escape_glob_not_infix() {
7382 let expr = parse("a GLOB b ESCAPE c");
7384 match &expr {
7385 Expr::Like {
7386 op: LikeOp::Glob,
7387 escape: Some(_),
7388 ..
7389 } => {}
7390 other => unreachable!("expected Glob with escape, got {other:?}"),
7391 }
7392 }
7393
7394 #[test]
7396 fn test_pratt_error_recovery_multiple_errors() {
7397 use crate::parser::Parser;
7398 let mut p = Parser::from_sql("SELECT +; SELECT *; SELECT 1");
7399 let (stmts, errs) = p.parse_all();
7400 assert!(
7403 !stmts.is_empty(),
7404 "should recover and parse at least one valid statement"
7405 );
7406 assert!(
7407 !errs.is_empty(),
7408 "should collect at least one error from malformed statements"
7409 );
7410 }
7411
7412 #[test]
7414 fn test_pratt_complex_mixed_all_levels() {
7415 let expr = parse("NOT a = b + c * -d OR e < f AND g LIKE h");
7418 match &expr {
7420 Expr::BinaryOp {
7421 op: BinaryOp::Or,
7422 left,
7423 right,
7424 ..
7425 } => {
7426 assert!(
7428 matches!(
7429 left.as_ref(),
7430 Expr::UnaryOp {
7431 op: UnaryOp::Not,
7432 ..
7433 }
7434 ),
7435 "left of OR should be NOT(...)"
7436 );
7437 match right.as_ref() {
7439 Expr::BinaryOp {
7440 op: BinaryOp::And,
7441 left: and_left,
7442 right: and_right,
7443 ..
7444 } => {
7445 assert!(
7446 matches!(
7447 and_left.as_ref(),
7448 Expr::BinaryOp {
7449 op: BinaryOp::Lt,
7450 ..
7451 }
7452 ),
7453 "left of AND should be Lt(e,f)"
7454 );
7455 assert!(
7456 matches!(and_right.as_ref(), Expr::Like { .. }),
7457 "right of AND should be Like(g,h)"
7458 );
7459 }
7460 other => unreachable!("expected And(Lt, Like), got {other:?}"),
7461 }
7462
7463 if let Expr::UnaryOp {
7466 expr: not_inner, ..
7467 } = left.as_ref()
7468 {
7469 if let Expr::BinaryOp {
7470 op: BinaryOp::Eq,
7471 right: eq_right,
7472 ..
7473 } = not_inner.as_ref()
7474 {
7475 if let Expr::BinaryOp {
7476 op: BinaryOp::Add,
7477 right: add_right,
7478 ..
7479 } = eq_right.as_ref()
7480 {
7481 if let Expr::BinaryOp {
7482 op: BinaryOp::Multiply,
7483 right: mul_right,
7484 ..
7485 } = add_right.as_ref()
7486 {
7487 assert!(
7488 matches!(
7489 mul_right.as_ref(),
7490 Expr::UnaryOp {
7491 op: UnaryOp::Negate,
7492 ..
7493 }
7494 ),
7495 "deepest: negate"
7496 );
7497 } else {
7498 unreachable!("expected Mul in add_right");
7499 }
7500 } else {
7501 unreachable!("expected Add in eq_right");
7502 }
7503 } else {
7504 unreachable!("expected Eq inside NOT");
7505 }
7506 }
7507 }
7508 other => unreachable!("expected Or(Not(...), And(...)), got {other:?}"),
7509 }
7510 }
7511
7512 #[test]
7514 fn test_pratt_json_same_precedence_as_concat() {
7515 let expr = parse("a || b -> c");
7517 match &expr {
7518 Expr::JsonAccess {
7519 expr: left,
7520 path: right,
7521 arrow: JsonArrow::Arrow,
7522 ..
7523 } => {
7524 assert!(
7525 matches!(
7526 left.as_ref(),
7527 Expr::BinaryOp {
7528 op: BinaryOp::Concat,
7529 ..
7530 }
7531 ),
7532 "left side should be concat expression"
7533 );
7534 assert!(
7535 matches!(right.as_ref(), Expr::Column(_, _)),
7536 "path should remain the right-hand expression"
7537 );
7538 }
7539 other => unreachable!("expected JsonAccess(Concat(a,b), c), got {other:?}"),
7540 }
7541 }
7542
7543 #[test]
7544 fn test_pratt_double_arrow_same_precedence_as_concat() {
7545 let expr = parse("a || b ->> c");
7546 assert!(
7547 matches!(
7548 expr,
7549 Expr::JsonAccess {
7550 arrow: JsonArrow::DoubleArrow,
7551 ..
7552 }
7553 ),
7554 "double-arrow should parse as JsonAccess at the same precedence level as concat"
7555 );
7556 }
7557}