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