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