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