1use fsqlite_ast::{
20 BinaryOp, ColumnRef, Expr, FunctionArgs, InSet, JsonArrow, LikeOp, Literal, PlaceholderType,
21 RaiseAction, SelectStatement, Span, TypeName, UnaryOp, WindowSpec,
22};
23use std::sync::Arc;
24
25use crate::parser::{ParseError, Parser, is_nonreserved_kw, kw_to_str};
26use crate::token::{Token, TokenKind};
27
28mod bp {
31 pub const OR: (u8, u8) = (1, 2);
33 pub const AND: (u8, u8) = (3, 4);
34 pub const NOT_PREFIX: u8 = 5;
36 pub const EQUALITY: (u8, u8) = (7, 8);
38 pub const COMPARISON: (u8, u8) = (9, 10);
40 pub const BITWISE: (u8, u8) = (13, 14);
42 pub const ADD: (u8, u8) = (15, 16);
44 pub const MUL: (u8, u8) = (17, 18);
46 pub const CONCAT: (u8, u8) = (19, 20);
48 pub const COLLATE: u8 = 21;
50 pub const UNARY: u8 = 23;
52 pub const JSON: (u8, u8) = (19, 20);
54}
55
56impl Parser {
57 pub fn parse_expr(&mut self) -> Result<Expr, ParseError> {
59 self.parse_expr_bp(0)
60 }
61
62 fn parse_expr_bp(&mut self, min_bp: u8) -> Result<Expr, ParseError> {
65 self.with_recursion_guard(|p| p.parse_expr_bp_inner(min_bp))
66 }
67
68 fn parse_expr_bp_inner(&mut self, min_bp: u8) -> Result<Expr, ParseError> {
69 let mut lhs = self.parse_prefix()?;
70
71 loop {
72 if let Some(l_bp) = self.postfix_bp() {
74 if l_bp < min_bp {
75 break;
76 }
77 lhs = self.parse_postfix(lhs)?;
78 continue;
79 }
80
81 if let Some((l_bp, r_bp)) = self.infix_bp() {
83 if l_bp < min_bp {
84 break;
85 }
86 lhs = self.parse_infix(lhs, r_bp)?;
87 continue;
88 }
89
90 break;
91 }
92
93 Ok(lhs)
94 }
95
96 fn peek_kind(&self) -> &TokenKind {
99 self.tokens
100 .get(self.pos)
101 .map_or(&TokenKind::Eof, |t| &t.kind)
102 }
103
104 #[allow(dead_code)]
105 fn peek_span(&self) -> Span {
106 self.tokens.get(self.pos).map_or(Span::ZERO, |t| t.span)
107 }
108
109 fn peek_token(&self) -> Option<&Token> {
110 self.tokens.get(self.pos)
111 }
112
113 fn peek_nth_token(&self, offset: usize) -> Option<&Token> {
114 self.tokens.get(self.pos + offset)
115 }
116
117 fn advance_token(&mut self) -> Token {
118 let tok = self.tokens[self.pos].clone();
119 if tok.kind != TokenKind::Eof {
120 self.pos += 1;
121 }
122 tok
123 }
124
125 fn at_kind(&self, kind: &TokenKind) -> bool {
126 std::mem::discriminant(self.peek_kind()) == std::mem::discriminant(kind)
127 }
128
129 fn eat_kind(&mut self, kind: &TokenKind) -> bool {
130 if self.at_kind(kind) {
131 self.advance_token();
132 true
133 } else {
134 false
135 }
136 }
137
138 fn expect_kind(&mut self, expected: &TokenKind) -> Result<Span, ParseError> {
139 if self.at_kind(expected) {
140 Ok(self.advance_token().span)
141 } else {
142 Err(self.err_here(format!("expected {expected:?}, got {:?}", self.peek_kind())))
143 }
144 }
145
146 fn err_here(&self, message: impl Into<String>) -> ParseError {
147 ParseError::at(message, self.peek_token())
148 }
149
150 #[allow(clippy::too_many_lines)]
153 fn parse_prefix(&mut self) -> Result<Expr, ParseError> {
154 let tok = self.advance_token();
155 match &tok.kind {
156 TokenKind::Integer(i) => Ok(Expr::Literal(Literal::Integer(*i), tok.span)),
158 TokenKind::OversizedInt(s) => match s.parse::<f64>() {
159 Ok(v) if v.is_finite() => Ok(Expr::Literal(Literal::Float(v), tok.span)),
160 Ok(_) => Ok(Expr::Literal(Literal::Float(f64::MAX), tok.span)),
161 Err(_) => Err(ParseError::at("integer out of range", Some(&tok))),
162 },
163 TokenKind::Float(f) => Ok(Expr::Literal(Literal::Float(*f), tok.span)),
164 TokenKind::String(s) => Ok(Expr::Literal(Literal::String(s.clone()), tok.span)),
165 TokenKind::Blob(b) => Ok(Expr::Literal(Literal::Blob(b.clone()), tok.span)),
166 TokenKind::KwNull => Ok(Expr::Literal(Literal::Null, tok.span)),
167 TokenKind::KwTrue => Ok(Expr::Literal(Literal::True, tok.span)),
168 TokenKind::KwFalse => Ok(Expr::Literal(Literal::False, tok.span)),
169 TokenKind::KwCurrentTime => Ok(Expr::Literal(Literal::CurrentTime, tok.span)),
170 TokenKind::KwCurrentDate => Ok(Expr::Literal(Literal::CurrentDate, tok.span)),
171 TokenKind::KwCurrentTimestamp => Ok(Expr::Literal(Literal::CurrentTimestamp, tok.span)),
172
173 TokenKind::Question => Ok(Expr::Placeholder(PlaceholderType::Anonymous, tok.span)),
175 TokenKind::QuestionNum(n) => {
176 Ok(Expr::Placeholder(PlaceholderType::Numbered(*n), tok.span))
177 }
178 TokenKind::ColonParam(s) => Ok(Expr::Placeholder(
179 PlaceholderType::ColonNamed(s.clone()),
180 tok.span,
181 )),
182 TokenKind::AtParam(s) => Ok(Expr::Placeholder(
183 PlaceholderType::AtNamed(s.clone()),
184 tok.span,
185 )),
186 TokenKind::DollarParam(s) => Ok(Expr::Placeholder(
187 PlaceholderType::DollarNamed(s.clone()),
188 tok.span,
189 )),
190
191 TokenKind::Minus => {
193 if let TokenKind::OversizedInt(s) = self.peek_kind() {
195 if s == "9223372036854775808" {
196 let num_span = self.advance_token().span;
197 let span = tok.span.merge(num_span);
198 return Ok(Expr::Literal(Literal::Integer(i64::MIN), span));
199 }
200 }
201 let inner = self.parse_expr_bp(bp::UNARY)?;
202 let span = tok.span.merge(inner.span());
203 Ok(Expr::UnaryOp {
204 op: UnaryOp::Negate,
205 expr: Box::new(inner),
206 span,
207 })
208 }
209 TokenKind::Plus => {
210 let inner = self.parse_expr_bp(bp::UNARY)?;
211 let span = tok.span.merge(inner.span());
212 Ok(Expr::UnaryOp {
213 op: UnaryOp::Plus,
214 expr: Box::new(inner),
215 span,
216 })
217 }
218 TokenKind::Tilde => {
219 let inner = self.parse_expr_bp(bp::UNARY)?;
220 let span = tok.span.merge(inner.span());
221 Ok(Expr::UnaryOp {
222 op: UnaryOp::BitNot,
223 expr: Box::new(inner),
224 span,
225 })
226 }
227
228 TokenKind::KwNot => {
230 if matches!(self.peek_kind(), TokenKind::KwExists) {
232 self.advance_token();
233 self.expect_kind(&TokenKind::LeftParen)?;
234 let subquery = self.parse_subquery_minimal()?;
235 let end = self.expect_kind(&TokenKind::RightParen)?;
236 let span = tok.span.merge(end);
237 return Ok(Expr::Exists {
238 subquery: Box::new(subquery),
239 not: true,
240 span,
241 });
242 }
243 let inner = self.parse_expr_bp(bp::NOT_PREFIX)?;
244 let span = tok.span.merge(inner.span());
245 Ok(Expr::UnaryOp {
246 op: UnaryOp::Not,
247 expr: Box::new(inner),
248 span,
249 })
250 }
251
252 TokenKind::KwExists => {
254 self.expect_kind(&TokenKind::LeftParen)?;
255 let subquery = self.parse_subquery_minimal()?;
256 let end = self.expect_kind(&TokenKind::RightParen)?;
257 let span = tok.span.merge(end);
258 Ok(Expr::Exists {
259 subquery: Box::new(subquery),
260 not: false,
261 span,
262 })
263 }
264
265 TokenKind::KwCast => {
267 self.expect_kind(&TokenKind::LeftParen)?;
268 let inner = self.parse_expr()?;
269 self.expect_kind(&TokenKind::KwAs)?;
270 let type_name = self.parse_type_name()?;
271 let end = self.expect_kind(&TokenKind::RightParen)?;
272 let span = tok.span.merge(end);
273 Ok(Expr::Cast {
274 expr: Box::new(inner),
275 type_name,
276 span,
277 })
278 }
279
280 TokenKind::KwCase => self.parse_case_expr(tok.span),
282
283 TokenKind::KwRaise => {
285 self.expect_kind(&TokenKind::LeftParen)?;
286 let (action, message) = self.parse_raise_args()?;
287 let end = self.expect_kind(&TokenKind::RightParen)?;
288 let span = tok.span.merge(end);
289 Ok(Expr::Raise {
290 action,
291 message,
292 span,
293 })
294 }
295
296 TokenKind::LeftParen => {
298 if matches!(
299 self.peek_kind(),
300 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
301 ) {
302 let subquery = self.parse_subquery_minimal()?;
303 let end = self.expect_kind(&TokenKind::RightParen)?;
304 let span = tok.span.merge(end);
305 return Ok(Expr::Subquery(Box::new(subquery), span));
306 }
307 let first = self.parse_expr()?;
308 if self.eat_kind(&TokenKind::Comma) {
309 let mut exprs = vec![first];
310 loop {
311 exprs.push(self.parse_expr()?);
312 if !self.eat_kind(&TokenKind::Comma) {
313 break;
314 }
315 }
316 let end = self.expect_kind(&TokenKind::RightParen)?;
317 let span = tok.span.merge(end);
318 Ok(Expr::RowValue(exprs, span))
319 } else {
320 self.expect_kind(&TokenKind::RightParen)?;
321 Ok(first)
322 }
323 }
324
325 TokenKind::Id(name) | TokenKind::QuotedId(name, _) => {
327 self.parse_ident_expr(Arc::clone(name), tok.span)
328 }
329
330 TokenKind::KwReplace if matches!(self.peek_kind(), TokenKind::LeftParen) => {
332 self.parse_function_call("replace".to_owned(), tok.span)
333 }
334 TokenKind::KwLike if matches!(self.peek_kind(), TokenKind::LeftParen) => {
340 self.parse_function_call("like".to_owned(), tok.span)
341 }
342 TokenKind::KwGlob if matches!(self.peek_kind(), TokenKind::LeftParen) => {
343 self.parse_function_call("glob".to_owned(), tok.span)
344 }
345 TokenKind::KwRegexp if matches!(self.peek_kind(), TokenKind::LeftParen) => {
346 self.parse_function_call("regexp".to_owned(), tok.span)
347 }
348 TokenKind::KwMatch if matches!(self.peek_kind(), TokenKind::LeftParen) => {
349 self.parse_function_call("match".to_owned(), tok.span)
350 }
351
352 k if is_nonreserved_kw(k) => {
356 let name = kw_to_str(k);
357 self.parse_ident_expr(name, tok.span)
358 }
359
360 _ => Err(ParseError::at(
361 format!("unexpected token in expression: {:?}", tok.kind),
362 Some(&tok),
363 )),
364 }
365 }
366
367 fn parse_ident_expr<S>(&mut self, name: S, start: Span) -> Result<Expr, ParseError>
369 where
370 S: AsRef<str> + Into<Arc<str>>,
371 {
372 if matches!(self.peek_kind(), TokenKind::LeftParen) {
374 return self.parse_function_call(name.as_ref().to_owned(), start);
375 }
376 let name = name.into();
377 if matches!(self.peek_kind(), TokenKind::Dot) {
379 let Some(col_tok) = self.peek_nth_token(1) else {
380 return Err(self.err_here("expected column name after '.'"));
381 };
382 let col_name = match &col_tok.kind {
383 TokenKind::Id(c) | TokenKind::QuotedId(c, _) => Arc::clone(c),
384 TokenKind::Star => Arc::<str>::from("*"),
385 k if k.keyword_str().is_some() => Arc::<str>::from(kw_to_str(k)),
388 _ => {
389 return Err(ParseError::at(
390 format!("expected column name after '.', got {:?}", col_tok.kind),
391 Some(col_tok),
392 ));
393 }
394 };
395 let span = start.merge(col_tok.span);
396 self.pos = self.pos.saturating_add(2);
397 return Ok(Expr::Column(ColumnRef::qualified(name, col_name), span));
398 }
399 Ok(Expr::Column(ColumnRef::bare(name), start))
400 }
401
402 fn postfix_bp(&self) -> Option<u8> {
405 match self.peek_kind() {
406 TokenKind::KwCollate => Some(bp::COLLATE),
407 TokenKind::KwIsnull | TokenKind::KwNotnull => Some(bp::EQUALITY.0),
408 TokenKind::KwNot => {
409 if let Some(next) = self.tokens.get(self.pos + 1) {
410 if matches!(next.kind, TokenKind::KwNull) {
411 return Some(bp::EQUALITY.0);
412 }
413 }
414 None
415 }
416 _ => None,
417 }
418 }
419
420 fn parse_postfix(&mut self, lhs: Expr) -> Result<Expr, ParseError> {
421 let tok = self.advance_token();
422 match &tok.kind {
423 TokenKind::KwCollate => {
424 let collation = match self.parse_identifier() {
425 Ok(s) => s,
426 Err(_) => {
427 return Err(self.err_here("expected collation name after COLLATE"));
428 }
429 };
430 let name_span = self.tokens[self.pos.saturating_sub(1)].span;
431 let span = lhs.span().merge(name_span);
432 Ok(Expr::Collate {
433 expr: Box::new(lhs),
434 collation,
435 span,
436 })
437 }
438 TokenKind::KwIsnull => {
439 let span = lhs.span().merge(tok.span);
440 Ok(Expr::IsNull {
441 expr: Box::new(lhs),
442 not: false,
443 span,
444 })
445 }
446 TokenKind::KwNotnull => {
447 let span = lhs.span().merge(tok.span);
448 Ok(Expr::IsNull {
449 expr: Box::new(lhs),
450 not: true,
451 span,
452 })
453 }
454 TokenKind::KwNot => {
455 let null_tok = self.advance_token(); let span = lhs.span().merge(null_tok.span);
457 Ok(Expr::IsNull {
458 expr: Box::new(lhs),
459 not: true,
460 span,
461 })
462 }
463 other => Err(ParseError::at(
464 format!("unexpected postfix token: {other:?}"),
465 Some(&tok),
466 )),
467 }
468 }
469
470 fn infix_bp(&self) -> Option<(u8, u8)> {
473 match self.peek_kind() {
474 TokenKind::KwOr => Some(bp::OR),
475 TokenKind::KwAnd => Some(bp::AND),
476
477 TokenKind::Eq
478 | TokenKind::EqEq
479 | TokenKind::Ne
480 | TokenKind::LtGt
481 | TokenKind::KwIs
482 | TokenKind::KwLike
483 | TokenKind::KwGlob
484 | TokenKind::KwMatch
485 | TokenKind::KwRegexp
486 | TokenKind::KwBetween
487 | TokenKind::KwIn => Some(bp::EQUALITY),
488
489 TokenKind::KwNot => {
491 let next = self.tokens.get(self.pos + 1).map(|t| &t.kind);
492 match next {
493 Some(
494 TokenKind::KwLike
495 | TokenKind::KwGlob
496 | TokenKind::KwMatch
497 | TokenKind::KwRegexp
498 | TokenKind::KwBetween
499 | TokenKind::KwIn,
500 ) => Some(bp::EQUALITY),
501 _ => None,
502 }
503 }
504
505 TokenKind::Lt | TokenKind::Le | TokenKind::Gt | TokenKind::Ge => Some(bp::COMPARISON),
506
507 TokenKind::Ampersand
508 | TokenKind::Pipe
509 | TokenKind::ShiftLeft
510 | TokenKind::ShiftRight => Some(bp::BITWISE),
511
512 TokenKind::Plus | TokenKind::Minus => Some(bp::ADD),
513 TokenKind::Star | TokenKind::Slash | TokenKind::Percent => Some(bp::MUL),
514 TokenKind::Concat => Some(bp::CONCAT),
515 TokenKind::Arrow | TokenKind::DoubleArrow => Some(bp::JSON),
516
517 _ => None,
518 }
519 }
520
521 #[allow(clippy::too_many_lines)]
522 fn parse_infix(&mut self, lhs: Expr, r_bp: u8) -> Result<Expr, ParseError> {
523 let tok = self.advance_token();
524 match &tok.kind {
525 TokenKind::Plus => self.make_binop(lhs, BinaryOp::Add, r_bp),
527 TokenKind::Minus => self.make_binop(lhs, BinaryOp::Subtract, r_bp),
528 TokenKind::Star => self.make_binop(lhs, BinaryOp::Multiply, r_bp),
529 TokenKind::Slash => self.make_binop(lhs, BinaryOp::Divide, r_bp),
530 TokenKind::Percent => self.make_binop(lhs, BinaryOp::Modulo, r_bp),
531 TokenKind::Concat => self.make_binop(lhs, BinaryOp::Concat, r_bp),
532 TokenKind::Eq | TokenKind::EqEq => self.make_binop(lhs, BinaryOp::Eq, r_bp),
533 TokenKind::Ne | TokenKind::LtGt => self.make_binop(lhs, BinaryOp::Ne, r_bp),
534 TokenKind::Lt => self.make_binop(lhs, BinaryOp::Lt, r_bp),
535 TokenKind::Le => self.make_binop(lhs, BinaryOp::Le, r_bp),
536 TokenKind::Gt => self.make_binop(lhs, BinaryOp::Gt, r_bp),
537 TokenKind::Ge => self.make_binop(lhs, BinaryOp::Ge, r_bp),
538 TokenKind::Ampersand => self.make_binop(lhs, BinaryOp::BitAnd, r_bp),
539 TokenKind::Pipe => self.make_binop(lhs, BinaryOp::BitOr, r_bp),
540 TokenKind::ShiftLeft => self.make_binop(lhs, BinaryOp::ShiftLeft, r_bp),
541 TokenKind::ShiftRight => self.make_binop(lhs, BinaryOp::ShiftRight, r_bp),
542 TokenKind::KwOr => self.make_binop(lhs, BinaryOp::Or, r_bp),
543 TokenKind::KwAnd => self.make_binop(lhs, BinaryOp::And, r_bp),
544
545 TokenKind::KwIs => {
547 let not = self.eat_kind(&TokenKind::KwNot);
548 if self.eat_kind(&TokenKind::KwDistinct) {
549 self.expect_kind(&TokenKind::KwFrom)?;
550 let rhs = self.parse_expr_bp(r_bp)?;
551 let span = lhs.span().merge(rhs.span());
552 let op = if not { BinaryOp::Is } else { BinaryOp::IsNot };
555 return Ok(Expr::BinaryOp {
556 left: Box::new(lhs),
557 op,
558 right: Box::new(rhs),
559 span,
560 });
561 }
562 if matches!(self.peek_kind(), TokenKind::KwNull) {
563 let end = self.advance_token().span;
564 let span = lhs.span().merge(end);
565 return Ok(Expr::IsNull {
566 expr: Box::new(lhs),
567 not,
568 span,
569 });
570 }
571 let rhs = self.parse_expr_bp(r_bp)?;
572 let span = lhs.span().merge(rhs.span());
573 let op = if not { BinaryOp::IsNot } else { BinaryOp::Is };
574 Ok(Expr::BinaryOp {
575 left: Box::new(lhs),
576 op,
577 right: Box::new(rhs),
578 span,
579 })
580 }
581
582 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, false),
584 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, false),
585 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, false),
586 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, false),
587
588 TokenKind::KwBetween => self.parse_between(lhs, false),
590
591 TokenKind::KwIn => self.parse_in(lhs, false),
593
594 TokenKind::Arrow => {
596 let rhs = self.parse_expr_bp(r_bp)?;
597 let span = lhs.span().merge(rhs.span());
598 Ok(Expr::JsonAccess {
599 expr: Box::new(lhs),
600 path: Box::new(rhs),
601 arrow: JsonArrow::Arrow,
602 span,
603 })
604 }
605 TokenKind::DoubleArrow => {
606 let rhs = self.parse_expr_bp(r_bp)?;
607 let span = lhs.span().merge(rhs.span());
608 Ok(Expr::JsonAccess {
609 expr: Box::new(lhs),
610 path: Box::new(rhs),
611 arrow: JsonArrow::DoubleArrow,
612 span,
613 })
614 }
615
616 TokenKind::KwNot => {
618 let next = self.advance_token();
619 match &next.kind {
620 TokenKind::KwLike => self.parse_like(lhs, LikeOp::Like, true),
621 TokenKind::KwGlob => self.parse_like(lhs, LikeOp::Glob, true),
622 TokenKind::KwMatch => self.parse_like(lhs, LikeOp::Match, true),
623 TokenKind::KwRegexp => self.parse_like(lhs, LikeOp::Regexp, true),
624 TokenKind::KwBetween => self.parse_between(lhs, true),
625 TokenKind::KwIn => self.parse_in(lhs, true),
626 _ => Err(ParseError::at(
627 format!(
628 "expected LIKE/GLOB/MATCH/REGEXP/BETWEEN/IN \
629 after NOT, got {:?}",
630 next.kind
631 ),
632 Some(&next),
633 )),
634 }
635 }
636
637 other => Err(ParseError::at(
638 format!("unexpected infix token: {other:?}"),
639 Some(&tok),
640 )),
641 }
642 }
643
644 fn make_binop(&mut self, lhs: Expr, op: BinaryOp, r_bp: u8) -> Result<Expr, ParseError> {
645 let rhs = self.parse_expr_bp(r_bp)?;
646 let span = lhs.span().merge(rhs.span());
647 Ok(Expr::BinaryOp {
648 left: Box::new(lhs),
649 op,
650 right: Box::new(rhs),
651 span,
652 })
653 }
654
655 fn parse_like(&mut self, lhs: Expr, op: LikeOp, not: bool) -> Result<Expr, ParseError> {
658 let pattern = self.parse_expr_bp(bp::EQUALITY.1)?;
659 let escape = if self.eat_kind(&TokenKind::KwEscape) {
660 Some(Box::new(self.parse_expr_bp(bp::EQUALITY.1)?))
663 } else {
664 None
665 };
666 let end = escape.as_ref().map_or_else(|| pattern.span(), |e| e.span());
667 let span = lhs.span().merge(end);
668 Ok(Expr::Like {
669 expr: Box::new(lhs),
670 pattern: Box::new(pattern),
671 escape,
672 op,
673 not,
674 span,
675 })
676 }
677
678 fn parse_between(&mut self, lhs: Expr, not: bool) -> Result<Expr, ParseError> {
679 let low = self.parse_expr_bp(bp::NOT_PREFIX)?;
681 if !self.eat_kind(&TokenKind::KwAnd) {
682 return Err(self.err_here("expected AND in BETWEEN expression"));
683 }
684 let high = self.parse_expr_bp(bp::EQUALITY.1)?;
685 let span = lhs.span().merge(high.span());
686 Ok(Expr::Between {
687 expr: Box::new(lhs),
688 low: Box::new(low),
689 high: Box::new(high),
690 not,
691 span,
692 })
693 }
694
695 fn parse_in(&mut self, lhs: Expr, not: bool) -> Result<Expr, ParseError> {
696 let start = lhs.span();
697
698 if !self.at_kind(&TokenKind::LeftParen) {
700 let table = self.parse_qualified_name()?;
701 let end = self.tokens[self.pos.saturating_sub(1)].span;
702 let span = start.merge(end);
703 return Ok(Expr::In {
704 expr: Box::new(lhs),
705 set: InSet::Table(table),
706 not,
707 span,
708 });
709 }
710
711 self.expect_kind(&TokenKind::LeftParen)?;
712
713 if matches!(
714 self.peek_kind(),
715 TokenKind::KwSelect | TokenKind::KwWith | TokenKind::KwValues
716 ) {
717 let subquery = self.parse_subquery_minimal()?;
718 let end = self.expect_kind(&TokenKind::RightParen)?;
719 let span = start.merge(end);
720 return Ok(Expr::In {
721 expr: Box::new(lhs),
722 set: InSet::Subquery(Box::new(subquery)),
723 not,
724 span,
725 });
726 }
727
728 let mut exprs = Vec::new();
729 if !self.at_kind(&TokenKind::RightParen) {
730 exprs.push(self.parse_expr()?);
731 while self.eat_kind(&TokenKind::Comma) {
732 exprs.push(self.parse_expr()?);
733 }
734 }
735 let end = self.expect_kind(&TokenKind::RightParen)?;
736 let span = start.merge(end);
737 Ok(Expr::In {
738 expr: Box::new(lhs),
739 set: InSet::List(exprs),
740 not,
741 span,
742 })
743 }
744
745 fn parse_case_expr(&mut self, start: Span) -> Result<Expr, ParseError> {
746 let operand = if matches!(self.peek_kind(), TokenKind::KwWhen) {
747 None
748 } else {
749 Some(Box::new(self.parse_expr()?))
750 };
751
752 let mut whens = Vec::new();
753 while self.eat_kind(&TokenKind::KwWhen) {
754 let condition = self.parse_expr()?;
755 if !self.eat_kind(&TokenKind::KwThen) {
756 return Err(self.err_here("expected THEN in CASE expression"));
757 }
758 let result = self.parse_expr()?;
759 whens.push((condition, result));
760 }
761 if whens.is_empty() {
762 return Err(self.err_here("CASE requires at least one WHEN clause"));
763 }
764
765 let else_expr = if self.eat_kind(&TokenKind::KwElse) {
766 Some(Box::new(self.parse_expr()?))
767 } else {
768 None
769 };
770
771 if !self.eat_kind(&TokenKind::KwEnd) {
772 return Err(self.err_here("expected END for CASE expression"));
773 }
774 let end = self.tokens[self.pos.saturating_sub(1)].span;
775 let span = start.merge(end);
776 Ok(Expr::Case {
777 operand,
778 whens,
779 else_expr,
780 span,
781 })
782 }
783
784 fn parse_function_call(&mut self, name: String, start: Span) -> Result<Expr, ParseError> {
785 self.expect_kind(&TokenKind::LeftParen)?;
786
787 let (args, distinct) = if matches!(self.peek_kind(), TokenKind::Star) {
788 if !name.eq_ignore_ascii_case("count") {
789 return Err(self.err_here("'*' can only be used with count() function"));
790 }
791 self.advance_token();
792 (FunctionArgs::Star, false)
793 } else {
794 let distinct = self.eat_kind(&TokenKind::KwDistinct);
795 let args = if matches!(self.peek_kind(), TokenKind::RightParen) {
796 if distinct {
797 return Err(self.err_here("DISTINCT requires at least one argument"));
798 }
799 FunctionArgs::List(Vec::new())
800 } else {
801 let mut list = vec![self.parse_expr()?];
802 while self.eat_kind(&TokenKind::Comma) {
803 list.push(self.parse_expr()?);
804 }
805 FunctionArgs::List(list)
806 };
807 (args, distinct)
808 };
809
810 let order_by = if self.eat_kind(&TokenKind::KwOrder) {
812 self.expect_kind(&TokenKind::KwBy)?;
813 self.parse_comma_sep(Self::parse_ordering_term)?
814 } else {
815 vec![]
816 };
817
818 let mut end = self.expect_kind(&TokenKind::RightParen)?;
819 let filter = if matches!(self.peek_kind(), TokenKind::KwFilter)
822 && self
823 .tokens
824 .get(self.pos + 1)
825 .is_some_and(|t| t.kind == TokenKind::LeftParen)
826 {
827 self.advance_token(); self.expect_kind(&TokenKind::LeftParen)?;
829 self.expect_kind(&TokenKind::KwWhere)?;
830 let predicate = self.parse_expr()?;
831 let filter_end = self.expect_kind(&TokenKind::RightParen)?;
832 end = end.merge(filter_end);
833 Some(Box::new(predicate))
834 } else {
835 None
836 };
837 let over = if matches!(self.peek_kind(), TokenKind::KwOver)
840 && self.tokens.get(self.pos + 1).is_some_and(|t| {
841 matches!(
842 t.kind,
843 TokenKind::LeftParen | TokenKind::Id(_) | TokenKind::QuotedId(_, _)
844 )
845 }) {
846 self.advance_token(); if self.eat_kind(&TokenKind::LeftParen) {
848 let spec = self.parse_window_spec()?;
849 let over_end = self.expect_kind(&TokenKind::RightParen)?;
850 end = end.merge(over_end);
851 Some(spec)
852 } else {
853 let base_window = self.parse_identifier()?;
854 let base_span = self.tokens[self.pos.saturating_sub(1)].span;
855 end = end.merge(base_span);
856 Some(WindowSpec {
857 base_window: Some(base_window),
858 partition_by: Vec::new(),
859 order_by: Vec::new(),
860 frame: None,
861 })
862 }
863 } else {
864 None
865 };
866
867 let span = start.merge(end);
868 Ok(Expr::FunctionCall {
869 name,
870 args,
871 distinct,
872 order_by,
873 filter,
874 over,
875 span,
876 })
877 }
878
879 fn parse_raise_args(&mut self) -> Result<(RaiseAction, Option<String>), ParseError> {
880 let action_tok = self.advance_token();
881 let action = match &action_tok.kind {
882 TokenKind::KwIgnore => RaiseAction::Ignore,
883 TokenKind::KwRollback => RaiseAction::Rollback,
884 TokenKind::KwAbort => RaiseAction::Abort,
885 TokenKind::KwFail => RaiseAction::Fail,
886 _ => {
887 return Err(ParseError::at(
888 "expected IGNORE, ROLLBACK, ABORT, or FAIL in RAISE",
889 Some(&action_tok),
890 ));
891 }
892 };
893 if matches!(action, RaiseAction::Ignore) {
894 return Ok((action, None));
895 }
896 self.expect_kind(&TokenKind::Comma)?;
897 let msg_tok = self.advance_token();
898 let message = match &msg_tok.kind {
899 TokenKind::String(s) => s.clone(),
900 _ => {
901 return Err(ParseError::at(
902 "expected string message in RAISE",
903 Some(&msg_tok),
904 ));
905 }
906 };
907 Ok((action, Some(message)))
908 }
909
910 fn parse_type_name(&mut self) -> Result<TypeName, ParseError> {
911 let mut parts = Vec::new();
912 loop {
913 match self.peek_kind() {
914 TokenKind::Id(_) | TokenKind::QuotedId(_, _) => {
915 let tok = self.advance_token();
916 if let TokenKind::Id(s) | TokenKind::QuotedId(s, _) = &tok.kind {
917 parts.push(s.to_string());
918 } else {
919 unreachable!();
920 }
921 }
922 k if is_nonreserved_kw(k) => {
923 let tok = self.advance_token();
924 parts.push(kw_to_str(&tok.kind));
925 }
926 _ => break,
927 }
928 }
929 if parts.is_empty() {
930 return Err(self.err_here("expected type name"));
931 }
932 let name = parts.join(" ");
933
934 let (arg1, arg2) = if self.eat_kind(&TokenKind::LeftParen) {
935 let a1 = self.parse_type_arg()?;
936 let a2 = if self.eat_kind(&TokenKind::Comma) {
937 Some(self.parse_type_arg()?)
938 } else {
939 None
940 };
941 self.expect_kind(&TokenKind::RightParen)?;
942 (Some(a1), a2)
943 } else {
944 (None, None)
945 };
946
947 Ok(TypeName { name, arg1, arg2 })
948 }
949
950 fn parse_type_arg(&mut self) -> Result<String, ParseError> {
951 let tok = self.advance_token();
952 match &tok.kind {
953 TokenKind::Integer(i) => Ok(i.to_string()),
954 TokenKind::Float(f) => Ok(f.to_string()),
955 TokenKind::Minus => {
956 let next = self.advance_token();
957 match &next.kind {
958 TokenKind::Integer(i) => Ok(format!("-{i}")),
959 TokenKind::OversizedInt(s) => Ok(format!("-{s}")),
960 TokenKind::Float(f) => Ok(format!("-{f}")),
961 _ => Err(ParseError::at(
962 "expected number in type argument",
963 Some(&next),
964 )),
965 }
966 }
967 TokenKind::Plus => {
968 let next = self.advance_token();
969 match &next.kind {
970 TokenKind::Integer(i) => Ok(format!("+{i}")),
971 TokenKind::OversizedInt(s) => Ok(format!("+{s}")),
972 TokenKind::Float(f) => Ok(format!("+{f}")),
973 _ => Err(ParseError::at(
974 "expected number in type argument",
975 Some(&next),
976 )),
977 }
978 }
979 TokenKind::OversizedInt(s) => Ok(s.clone()),
980 TokenKind::Id(s) | TokenKind::QuotedId(s, _) => Ok(s.to_string()),
981 _ => Err(ParseError::at("expected type argument", Some(&tok))),
982 }
983 }
984
985 fn parse_subquery_minimal(&mut self) -> Result<SelectStatement, ParseError> {
987 let with = if self.at_kind(&TokenKind::KwWith) {
988 Some(self.parse_with_clause()?)
989 } else {
990 None
991 };
992 self.parse_select_stmt(with)
993 }
994}
995
996pub fn parse_expr(sql: &str) -> Result<Expr, ParseError> {
998 let mut parser = Parser::from_sql(sql);
999 let expr = parser.parse_expr()?;
1000 if !matches!(parser.peek_kind(), TokenKind::Eof | TokenKind::Semicolon) {
1001 return Err(parser.err_here(format!(
1002 "unexpected token after expression: {:?}",
1003 parser.peek_kind()
1004 )));
1005 }
1006 Ok(expr)
1007}
1008
1009#[cfg(test)]
1010mod tests {
1011 use super::*;
1012 use fsqlite_ast::{SelectCore, TableOrSubquery};
1013
1014 fn parse(sql: &str) -> Expr {
1015 match parse_expr(sql) {
1016 Ok(expr) => expr,
1017 Err(err) => unreachable!("parse error for `{sql}`: {err}"),
1018 }
1019 }
1020
1021 #[test]
1024 fn test_not_lower_precedence_than_comparison() {
1025 let expr = parse("NOT x = y");
1027 match &expr {
1028 Expr::UnaryOp {
1029 op: UnaryOp::Not,
1030 expr: inner,
1031 ..
1032 } => match inner.as_ref() {
1033 Expr::BinaryOp {
1034 op: BinaryOp::Eq, ..
1035 } => {}
1036 other => unreachable!("expected Eq inside NOT, got {other:?}"),
1037 },
1038 other => unreachable!("expected NOT(Eq), got {other:?}"),
1039 }
1040 }
1041
1042 #[test]
1043 fn test_unary_binds_tighter_than_collate() {
1044 let expr = parse("-x COLLATE NOCASE");
1046 match &expr {
1047 Expr::Collate {
1048 expr: inner,
1049 collation,
1050 ..
1051 } => {
1052 assert_eq!(collation, "NOCASE");
1053 assert!(matches!(
1054 inner.as_ref(),
1055 Expr::UnaryOp {
1056 op: UnaryOp::Negate,
1057 ..
1058 }
1059 ));
1060 }
1061 other => unreachable!("expected COLLATE(Negate), got {other:?}"),
1062 }
1063 }
1064
1065 #[test]
1066 fn test_arithmetic_precedence() {
1067 let expr = parse("1 + 2 * 3");
1069 match &expr {
1070 Expr::BinaryOp {
1071 op: BinaryOp::Add,
1072 left,
1073 right,
1074 ..
1075 } => {
1076 assert!(matches!(
1077 left.as_ref(),
1078 Expr::Literal(Literal::Integer(1), _)
1079 ));
1080 assert!(matches!(
1081 right.as_ref(),
1082 Expr::BinaryOp {
1083 op: BinaryOp::Multiply,
1084 ..
1085 }
1086 ));
1087 }
1088 other => unreachable!("expected Add(1, Mul(2,3)), got {other:?}"),
1089 }
1090 }
1091
1092 #[test]
1093 fn test_and_higher_than_or() {
1094 let expr = parse("a OR b AND c");
1096 match &expr {
1097 Expr::BinaryOp {
1098 op: BinaryOp::Or,
1099 right,
1100 ..
1101 } => {
1102 assert!(matches!(
1103 right.as_ref(),
1104 Expr::BinaryOp {
1105 op: BinaryOp::And,
1106 ..
1107 }
1108 ));
1109 }
1110 other => unreachable!("expected Or(a, And(b,c)), got {other:?}"),
1111 }
1112 }
1113
1114 #[test]
1117 fn test_cast_expression() {
1118 let expr = parse("CAST(42 AS INTEGER)");
1119 match &expr {
1120 Expr::Cast {
1121 expr: inner,
1122 type_name,
1123 ..
1124 } => {
1125 assert!(matches!(
1126 inner.as_ref(),
1127 Expr::Literal(Literal::Integer(42), _)
1128 ));
1129 assert_eq!(type_name.name, "INTEGER");
1130 }
1131 other => unreachable!("expected Cast, got {other:?}"),
1132 }
1133 }
1134
1135 #[test]
1136 fn test_cast_float_argument() {
1137 let expr = parse("CAST(x AS DECIMAL(10.5, -2.5))");
1139 match &expr {
1140 Expr::Cast { type_name, .. } => {
1141 assert_eq!(type_name.name, "DECIMAL");
1142 assert_eq!(type_name.arg1.as_deref(), Some("10.5"));
1143 assert_eq!(type_name.arg2.as_deref(), Some("-2.5"));
1144 }
1145 other => unreachable!("expected Cast with float args, got {other:?}"),
1146 }
1147 }
1148
1149 #[test]
1150 fn test_cast_signed_args() {
1151 let expr = parse("CAST(x AS NUMERIC(+5, -5))");
1153 match &expr {
1154 Expr::Cast { type_name, .. } => {
1155 assert_eq!(type_name.name, "NUMERIC");
1156 assert_eq!(type_name.arg1.as_deref(), Some("+5"));
1157 assert_eq!(type_name.arg2.as_deref(), Some("-5"));
1158 }
1159 other => unreachable!("expected Cast with signed args, got {other:?}"),
1160 }
1161 }
1162
1163 #[test]
1166 fn test_case_when_simple() {
1167 let expr = parse(
1168 "CASE x WHEN 1 THEN 'one' WHEN 2 THEN 'two' \
1169 ELSE 'other' END",
1170 );
1171 match &expr {
1172 Expr::Case {
1173 operand: Some(op),
1174 whens,
1175 else_expr: Some(_),
1176 ..
1177 } => {
1178 assert!(matches!(op.as_ref(), Expr::Column(..)));
1179 assert_eq!(whens.len(), 2);
1180 }
1181 other => unreachable!("expected simple CASE, got {other:?}"),
1182 }
1183 }
1184
1185 #[test]
1186 fn test_case_when_searched() {
1187 let expr = parse(
1188 "CASE WHEN x > 0 THEN 'pos' WHEN x < 0 THEN 'neg' \
1189 ELSE 'zero' END",
1190 );
1191 match &expr {
1192 Expr::Case {
1193 operand: None,
1194 whens,
1195 else_expr: Some(_),
1196 ..
1197 } => {
1198 assert_eq!(whens.len(), 2);
1199 assert!(matches!(
1200 &whens[0].0,
1201 Expr::BinaryOp {
1202 op: BinaryOp::Gt,
1203 ..
1204 }
1205 ));
1206 }
1207 other => unreachable!("expected searched CASE, got {other:?}"),
1208 }
1209 }
1210
1211 #[test]
1214 fn test_exists_subquery() {
1215 let expr = parse("EXISTS (SELECT 1)");
1216 assert!(matches!(expr, Expr::Exists { not: false, .. }));
1217 }
1218
1219 #[test]
1220 fn test_not_exists_subquery() {
1221 let expr = parse("NOT EXISTS (SELECT 1)");
1222 assert!(matches!(expr, Expr::Exists { not: true, .. }));
1223 }
1224
1225 #[test]
1226 fn test_exists_subquery_supports_qualified_table_with_alias() {
1227 let expr = parse("EXISTS (SELECT 1 FROM main.users AS u WHERE u.id = 1)");
1228 match expr {
1229 Expr::Exists { subquery, .. } => match subquery.body.select {
1230 SelectCore::Select {
1231 from: Some(from), ..
1232 } => match from.source {
1233 TableOrSubquery::Table { name, alias, .. } => {
1234 assert_eq!(name.schema.as_deref(), Some("main"));
1235 assert_eq!(name.name, "users");
1236 assert_eq!(alias.as_deref(), Some("u"));
1237 }
1238 other => unreachable!("expected table source, got {other:?}"),
1239 },
1240 other => unreachable!("expected SELECT core with FROM, got {other:?}"),
1241 },
1242 other => unreachable!("expected EXISTS subquery, got {other:?}"),
1243 }
1244 }
1245
1246 #[test]
1249 fn test_in_expr_list() {
1250 let expr = parse("x IN (1, 2, 3)");
1251 match &expr {
1252 Expr::In {
1253 not: false,
1254 set: InSet::List(items),
1255 ..
1256 } => assert_eq!(items.len(), 3),
1257 other => unreachable!("expected IN list, got {other:?}"),
1258 }
1259 }
1260
1261 #[test]
1262 fn test_in_subquery() {
1263 let expr = parse("x IN (SELECT y FROM t)");
1264 assert!(matches!(
1265 expr,
1266 Expr::In {
1267 not: false,
1268 set: InSet::Subquery(_),
1269 ..
1270 }
1271 ));
1272 }
1273
1274 #[test]
1275 fn test_in_subquery_with_order_by_and_limit() {
1276 let expr =
1278 parse("id NOT IN (SELECT id FROM search_recipes ORDER BY updated_ts DESC LIMIT 5)");
1279 match &expr {
1280 Expr::In {
1281 not: true,
1282 set: InSet::Subquery(stmt),
1283 ..
1284 } => {
1285 assert_eq!(stmt.order_by.len(), 1, "ORDER BY should be parsed");
1286 assert!(stmt.limit.is_some(), "LIMIT should be parsed");
1287 }
1288 other => unreachable!("expected NOT IN subquery, got {other:?}"),
1289 }
1290 }
1291
1292 #[test]
1293 fn test_in_subquery_supports_group_by_and_having() {
1294 let expr = parse("x IN (SELECT y FROM t GROUP BY y HAVING COUNT(*) > 1)");
1295 match expr {
1296 Expr::In {
1297 set: InSet::Subquery(stmt),
1298 ..
1299 } => match stmt.body.select {
1300 SelectCore::Select {
1301 group_by, having, ..
1302 } => {
1303 assert_eq!(group_by.len(), 1, "GROUP BY should be parsed");
1304 assert!(having.is_some(), "HAVING should be parsed");
1305 }
1306 SelectCore::Values(_) => unreachable!("expected SELECT core"),
1307 },
1308 other => unreachable!("expected IN subquery, got {other:?}"),
1309 }
1310 }
1311
1312 #[test]
1313 fn test_not_in() {
1314 let expr = parse("x NOT IN (1, 2)");
1315 assert!(matches!(expr, Expr::In { not: true, .. }));
1316 }
1317
1318 #[test]
1319 fn test_in_table_name() {
1320 let expr = parse("x IN t");
1321 assert!(matches!(
1322 expr,
1323 Expr::In {
1324 not: false,
1325 set: InSet::Table(_),
1326 ..
1327 }
1328 ));
1329 }
1330
1331 #[test]
1332 fn test_not_in_table_name() {
1333 let expr = parse("x NOT IN t");
1334 assert!(matches!(
1335 expr,
1336 Expr::In {
1337 not: true,
1338 set: InSet::Table(_),
1339 ..
1340 }
1341 ));
1342 }
1343
1344 #[test]
1345 fn test_in_schema_table_name() {
1346 let expr = parse("x IN main.t");
1347 match expr {
1348 Expr::In {
1349 set: InSet::Table(name),
1350 ..
1351 } => {
1352 assert_eq!(name.schema.as_deref(), Some("main"));
1353 assert_eq!(name.name, "t");
1354 }
1355 other => unreachable!("expected IN table form, got {other:?}"),
1356 }
1357 }
1358
1359 #[test]
1362 fn test_between_and() {
1363 let expr = parse("x BETWEEN 1 AND 10");
1364 assert!(matches!(expr, Expr::Between { not: false, .. }));
1365 }
1366
1367 #[test]
1368 fn test_not_between() {
1369 let expr = parse("x NOT BETWEEN 1 AND 10");
1370 assert!(matches!(expr, Expr::Between { not: true, .. }));
1371 }
1372
1373 #[test]
1374 fn test_between_does_not_consume_outer_and() {
1375 let expr = parse("x BETWEEN 1 AND 10 AND y = 1");
1377 match &expr {
1378 Expr::BinaryOp {
1379 op: BinaryOp::And,
1380 left,
1381 ..
1382 } => assert!(matches!(left.as_ref(), Expr::Between { .. })),
1383 other => unreachable!("expected AND(BETWEEN, Eq), got {other:?}"),
1384 }
1385 }
1386
1387 #[test]
1390 fn test_like_pattern() {
1391 let expr = parse("name LIKE '%foo%'");
1392 assert!(matches!(
1393 expr,
1394 Expr::Like {
1395 op: LikeOp::Like,
1396 not: false,
1397 escape: None,
1398 ..
1399 }
1400 ));
1401 }
1402
1403 #[test]
1404 fn test_like_escape() {
1405 let expr = parse("name LIKE '%\\%%' ESCAPE '\\'");
1406 assert!(matches!(
1407 expr,
1408 Expr::Like {
1409 op: LikeOp::Like,
1410 escape: Some(_),
1411 ..
1412 }
1413 ));
1414 }
1415
1416 #[test]
1417 fn test_glob_pattern() {
1418 let expr = parse("path GLOB '*.rs'");
1419 assert!(matches!(
1420 expr,
1421 Expr::Like {
1422 op: LikeOp::Glob,
1423 not: false,
1424 ..
1425 }
1426 ));
1427 }
1428
1429 #[test]
1430 fn test_glob_character_class() {
1431 let expr = parse("name GLOB '[a-z]*'");
1432 match &expr {
1433 Expr::Like {
1434 op: LikeOp::Glob,
1435 pattern,
1436 ..
1437 } => assert!(matches!(
1438 pattern.as_ref(),
1439 Expr::Literal(Literal::String(s), _) if s == "[a-z]*"
1440 )),
1441 other => unreachable!("expected GLOB, got {other:?}"),
1442 }
1443 }
1444
1445 #[test]
1448 fn test_collate_override() {
1449 let expr = parse("name COLLATE NOCASE");
1450 match &expr {
1451 Expr::Collate { collation, .. } => {
1452 assert_eq!(collation, "NOCASE");
1453 }
1454 other => unreachable!("expected COLLATE, got {other:?}"),
1455 }
1456 }
1457
1458 #[test]
1461 fn test_json_arrow_operator() {
1462 let expr = parse("data -> 'key'");
1463 assert!(matches!(
1464 expr,
1465 Expr::JsonAccess {
1466 arrow: JsonArrow::Arrow,
1467 ..
1468 }
1469 ));
1470 }
1471
1472 #[test]
1473 fn test_json_double_arrow_operator() {
1474 let expr = parse("data ->> 'key'");
1475 assert!(matches!(
1476 expr,
1477 Expr::JsonAccess {
1478 arrow: JsonArrow::DoubleArrow,
1479 ..
1480 }
1481 ));
1482 }
1483
1484 #[test]
1487 fn test_is_null() {
1488 assert!(matches!(
1489 parse("42"),
1490 Expr::Literal(Literal::Integer(42), _)
1491 ));
1492 assert!(matches!(parse("3.14"), Expr::Literal(Literal::Float(_), _)));
1493 assert!(matches!(
1494 parse("'hello'"),
1495 Expr::Literal(Literal::String(_), _)
1496 ));
1497 assert!(matches!(parse("NULL"), Expr::Literal(Literal::Null, _)));
1498 assert!(matches!(parse("TRUE"), Expr::Literal(Literal::True, _)));
1499 assert!(matches!(parse("FALSE"), Expr::Literal(Literal::False, _)));
1500 }
1501
1502 #[test]
1503 fn test_placeholders() {
1504 assert!(matches!(
1505 parse("?"),
1506 Expr::Placeholder(PlaceholderType::Anonymous, _)
1507 ));
1508 assert!(matches!(
1509 parse("?1"),
1510 Expr::Placeholder(PlaceholderType::Numbered(1), _)
1511 ));
1512 assert!(matches!(
1513 parse(":name"),
1514 Expr::Placeholder(PlaceholderType::ColonNamed(_), _)
1515 ));
1516 }
1517
1518 #[test]
1521 fn test_column_bare() {
1522 match &parse("x") {
1523 Expr::Column(
1524 ColumnRef {
1525 table: None,
1526 column,
1527 },
1528 _,
1529 ) => assert_eq!(column.as_ref(), "x"),
1530 other => unreachable!("expected bare column, got {other:?}"),
1531 }
1532 }
1533
1534 #[test]
1535 fn test_column_qualified() {
1536 match &parse("t.x") {
1537 Expr::Column(
1538 ColumnRef {
1539 table: Some(t),
1540 column,
1541 },
1542 _,
1543 ) => {
1544 assert_eq!(t.as_ref(), "t");
1545 assert_eq!(column.as_ref(), "x");
1546 }
1547 other => unreachable!("expected qualified column, got {other:?}"),
1548 }
1549 }
1550
1551 #[test]
1554 fn test_concat_higher_than_add() {
1555 let expr = parse("a + b || c");
1557 match &expr {
1558 Expr::BinaryOp {
1559 op: BinaryOp::Add,
1560 right,
1561 ..
1562 } => assert!(matches!(
1563 right.as_ref(),
1564 Expr::BinaryOp {
1565 op: BinaryOp::Concat,
1566 ..
1567 }
1568 )),
1569 other => unreachable!("expected Add(a, Concat(b,c)), got {other:?}"),
1570 }
1571 }
1572
1573 #[test]
1576 fn test_parenthesized() {
1577 let expr = parse("(1 + 2) * 3");
1579 match &expr {
1580 Expr::BinaryOp {
1581 op: BinaryOp::Multiply,
1582 left,
1583 ..
1584 } => assert!(matches!(
1585 left.as_ref(),
1586 Expr::BinaryOp {
1587 op: BinaryOp::Add,
1588 ..
1589 }
1590 )),
1591 other => unreachable!("expected Mul(Add, 3), got {other:?}"),
1592 }
1593 }
1594
1595 #[test]
1598 fn test_is_operator() {
1599 assert!(matches!(
1600 parse("a IS b"),
1601 Expr::BinaryOp {
1602 op: BinaryOp::Is,
1603 ..
1604 }
1605 ));
1606 }
1607
1608 #[test]
1609 fn test_is_not_operator() {
1610 assert!(matches!(
1611 parse("a IS NOT b"),
1612 Expr::BinaryOp {
1613 op: BinaryOp::IsNot,
1614 ..
1615 }
1616 ));
1617 }
1618
1619 #[test]
1622 fn test_bitwise_ops() {
1623 let expr = parse("a & b | c");
1625 match &expr {
1626 Expr::BinaryOp {
1627 op: BinaryOp::BitOr,
1628 left,
1629 ..
1630 } => assert!(
1631 matches!(
1632 left.as_ref(),
1633 Expr::BinaryOp {
1634 op: BinaryOp::BitAnd,
1635 ..
1636 }
1637 ),
1638 "bitwise operators should be left-associative"
1639 ),
1640 other => unreachable!("expected BitOr(BitAnd, c), got {other:?}"),
1641 }
1642 }
1643
1644 #[test]
1645 fn test_bitnot() {
1646 assert!(matches!(
1647 parse("~x"),
1648 Expr::UnaryOp {
1649 op: UnaryOp::BitNot,
1650 ..
1651 }
1652 ));
1653 }
1654
1655 #[test]
1658 fn test_complex_where_clause() {
1659 let expr = parse("a > 1 AND b LIKE '%test%' OR NOT c IS NULL");
1660 assert!(matches!(
1661 expr,
1662 Expr::BinaryOp {
1663 op: BinaryOp::Or,
1664 ..
1665 }
1666 ));
1667 }
1668
1669 #[test]
1670 fn test_not_like_pattern() {
1671 assert!(matches!(
1672 parse("name NOT LIKE '%foo'"),
1673 Expr::Like {
1674 op: LikeOp::Like,
1675 not: true,
1676 ..
1677 }
1678 ));
1679 }
1680
1681 #[test]
1682 fn test_subquery_expr() {
1683 assert!(matches!(parse("(SELECT 1)"), Expr::Subquery(..)));
1684 }
1685
1686 #[test]
1694 fn test_pratt_level1_or_left_assoc() {
1695 let expr = parse("a OR b OR c");
1697 match &expr {
1698 Expr::BinaryOp {
1699 op: BinaryOp::Or,
1700 left,
1701 ..
1702 } => assert!(
1703 matches!(
1704 left.as_ref(),
1705 Expr::BinaryOp {
1706 op: BinaryOp::Or,
1707 ..
1708 }
1709 ),
1710 "OR should be left-associative"
1711 ),
1712 other => unreachable!("expected Or(Or(a,b), c), got {other:?}"),
1713 }
1714 }
1715
1716 #[test]
1718 fn test_pratt_level2_and_left_assoc() {
1719 let expr = parse("a AND b AND c");
1721 match &expr {
1722 Expr::BinaryOp {
1723 op: BinaryOp::And,
1724 left,
1725 ..
1726 } => assert!(
1727 matches!(
1728 left.as_ref(),
1729 Expr::BinaryOp {
1730 op: BinaryOp::And,
1731 ..
1732 }
1733 ),
1734 "AND should be left-associative"
1735 ),
1736 other => unreachable!("expected And(And(a,b), c), got {other:?}"),
1737 }
1738 }
1739
1740 #[test]
1742 fn test_pratt_level3_not_higher_than_and() {
1743 let expr = parse("NOT a AND b");
1745 match &expr {
1746 Expr::BinaryOp {
1747 op: BinaryOp::And,
1748 left,
1749 ..
1750 } => assert!(
1751 matches!(
1752 left.as_ref(),
1753 Expr::UnaryOp {
1754 op: UnaryOp::Not,
1755 ..
1756 }
1757 ),
1758 "NOT should bind tighter than AND"
1759 ),
1760 other => unreachable!("expected And(Not(a), b), got {other:?}"),
1761 }
1762 }
1763
1764 #[test]
1766 fn test_pratt_level4_equality_left_assoc() {
1767 let expr = parse("a = b != c");
1769 match &expr {
1770 Expr::BinaryOp {
1771 op: BinaryOp::Ne,
1772 left,
1773 ..
1774 } => assert!(
1775 matches!(
1776 left.as_ref(),
1777 Expr::BinaryOp {
1778 op: BinaryOp::Eq,
1779 ..
1780 }
1781 ),
1782 "equality operators should be left-associative at same level"
1783 ),
1784 other => unreachable!("expected Ne(Eq(a,b), c), got {other:?}"),
1785 }
1786 }
1787
1788 #[test]
1792 fn test_pratt_level4_vs_level5_eq_lt_boundary() {
1793 let expr = parse("a = b < c");
1796 match &expr {
1797 Expr::BinaryOp {
1798 op: BinaryOp::Eq,
1799 right,
1800 ..
1801 } => assert!(
1802 matches!(
1803 right.as_ref(),
1804 Expr::BinaryOp {
1805 op: BinaryOp::Lt,
1806 ..
1807 }
1808 ),
1809 "a = b < c MUST parse as a = (b < c): relational binds tighter"
1810 ),
1811 other => unreachable!("expected Eq(a, Lt(b,c)), got {other:?}"),
1812 }
1813 }
1814
1815 #[test]
1817 fn test_pratt_level4_vs_level5_ne_ge_boundary() {
1818 let expr = parse("a != b >= c");
1820 match &expr {
1821 Expr::BinaryOp {
1822 op: BinaryOp::Ne,
1823 right,
1824 ..
1825 } => assert!(
1826 matches!(
1827 right.as_ref(),
1828 Expr::BinaryOp {
1829 op: BinaryOp::Ge,
1830 ..
1831 }
1832 ),
1833 "a != b >= c must parse as a != (b >= c)"
1834 ),
1835 other => unreachable!("expected Ne(Ge(b,c)), got {other:?}"),
1836 }
1837 }
1838
1839 #[test]
1841 fn test_pratt_level5_relational_left_assoc() {
1842 let expr = parse("a < b >= c");
1844 match &expr {
1845 Expr::BinaryOp {
1846 op: BinaryOp::Ge,
1847 left,
1848 ..
1849 } => assert!(
1850 matches!(
1851 left.as_ref(),
1852 Expr::BinaryOp {
1853 op: BinaryOp::Lt,
1854 ..
1855 }
1856 ),
1857 "relational operators should be left-associative"
1858 ),
1859 other => unreachable!("expected Ge(Lt(a,b), c), got {other:?}"),
1860 }
1861 }
1862
1863 #[test]
1865 fn test_pratt_level6_bitwise_tighter_than_comparison() {
1866 let expr = parse("a < b & c");
1868 match &expr {
1869 Expr::BinaryOp {
1870 op: BinaryOp::Lt,
1871 right,
1872 ..
1873 } => assert!(
1874 matches!(
1875 right.as_ref(),
1876 Expr::BinaryOp {
1877 op: BinaryOp::BitAnd,
1878 ..
1879 }
1880 ),
1881 "bitwise should bind tighter than relational"
1882 ),
1883 other => unreachable!("expected Lt(a, BitAnd(b,c)), got {other:?}"),
1884 }
1885 }
1886
1887 #[test]
1889 fn test_pratt_level6_shifts_left_assoc() {
1890 let expr = parse("a << b >> c");
1892 match &expr {
1893 Expr::BinaryOp {
1894 op: BinaryOp::ShiftRight,
1895 left,
1896 ..
1897 } => assert!(
1898 matches!(
1899 left.as_ref(),
1900 Expr::BinaryOp {
1901 op: BinaryOp::ShiftLeft,
1902 ..
1903 }
1904 ),
1905 "shift operators should be left-associative"
1906 ),
1907 other => unreachable!("expected ShiftRight(ShiftLeft(a,b), c), got {other:?}"),
1908 }
1909 }
1910
1911 #[test]
1913 fn test_pratt_level7_add_sub_left_assoc() {
1914 let expr = parse("a + b - c");
1916 match &expr {
1917 Expr::BinaryOp {
1918 op: BinaryOp::Subtract,
1919 left,
1920 ..
1921 } => assert!(
1922 matches!(
1923 left.as_ref(),
1924 Expr::BinaryOp {
1925 op: BinaryOp::Add,
1926 ..
1927 }
1928 ),
1929 "add/sub should be left-associative"
1930 ),
1931 other => unreachable!("expected Sub(Add(a,b), c), got {other:?}"),
1932 }
1933 }
1934
1935 #[test]
1936 fn test_pratt_level7_add_sub_left_assoc_reverse() {
1937 let expr = parse("a - b + c");
1939 match &expr {
1940 Expr::BinaryOp {
1941 op: BinaryOp::Add,
1942 left,
1943 ..
1944 } => assert!(
1945 matches!(
1946 left.as_ref(),
1947 Expr::BinaryOp {
1948 op: BinaryOp::Subtract,
1949 ..
1950 }
1951 ),
1952 "add/sub should be left-associative"
1953 ),
1954 other => unreachable!("expected Add(Sub(a,b), c), got {other:?}"),
1955 }
1956 }
1957
1958 #[test]
1959 fn test_pratt_level9_concat_tighter_than_mul() {
1960 let expr = parse("a * b || c");
1962 match &expr {
1963 Expr::BinaryOp {
1964 op: BinaryOp::Multiply,
1965 right,
1966 ..
1967 } => assert!(
1968 matches!(
1969 right.as_ref(),
1970 Expr::BinaryOp {
1971 op: BinaryOp::Concat,
1972 ..
1973 }
1974 ),
1975 "concat should bind tighter than multiply"
1976 ),
1977 other => unreachable!("expected Mul(a, Concat(b,c)), got {other:?}"),
1978 }
1979 }
1980
1981 #[test]
1983 fn test_pratt_level8_mul_div_left_assoc() {
1984 let expr = parse("a * b / c");
1986 match &expr {
1987 Expr::BinaryOp {
1988 op: BinaryOp::Divide,
1989 left,
1990 ..
1991 } => assert!(
1992 matches!(
1993 left.as_ref(),
1994 Expr::BinaryOp {
1995 op: BinaryOp::Multiply,
1996 ..
1997 }
1998 ),
1999 "mul/div should be left-associative"
2000 ),
2001 other => unreachable!("expected Div(Mul(a,b), c), got {other:?}"),
2002 }
2003 }
2004
2005 #[test]
2006 fn test_pratt_level8_modulo() {
2007 let expr = parse("a * b % c");
2009 match &expr {
2010 Expr::BinaryOp {
2011 op: BinaryOp::Modulo,
2012 left,
2013 ..
2014 } => assert!(
2015 matches!(
2016 left.as_ref(),
2017 Expr::BinaryOp {
2018 op: BinaryOp::Multiply,
2019 ..
2020 }
2021 ),
2022 "modulo and multiply at same level, left-associative"
2023 ),
2024 other => unreachable!("expected Mod(Mul(a,b), c), got {other:?}"),
2025 }
2026 }
2027
2028 #[test]
2030 fn test_pratt_level9_concat_left_assoc() {
2031 let expr = parse("a || b || c");
2033 match &expr {
2034 Expr::BinaryOp {
2035 op: BinaryOp::Concat,
2036 left,
2037 ..
2038 } => assert!(
2039 matches!(
2040 left.as_ref(),
2041 Expr::BinaryOp {
2042 op: BinaryOp::Concat,
2043 ..
2044 }
2045 ),
2046 "concatenation should be left-associative"
2047 ),
2048 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
2049 }
2050 }
2051
2052 #[test]
2053 fn test_pratt_level9_concat_left_assoc_reverse() {
2054 let expr = parse("a || b || c");
2056 match &expr {
2057 Expr::BinaryOp {
2058 op: BinaryOp::Concat,
2059 left,
2060 ..
2061 } => assert!(
2062 matches!(
2063 left.as_ref(),
2064 Expr::BinaryOp {
2065 op: BinaryOp::Concat,
2066 ..
2067 }
2068 ),
2069 "concatenation should be left-associative"
2070 ),
2071 other => unreachable!("expected Concat(Concat(a,b), c), got {other:?}"),
2072 }
2073 }
2074
2075 #[test]
2077 fn test_pratt_level10_collate_tighter_than_concat() {
2078 let expr = parse("a || b COLLATE NOCASE");
2080 match &expr {
2081 Expr::BinaryOp {
2082 op: BinaryOp::Concat,
2083 right,
2084 ..
2085 } => assert!(
2086 matches!(right.as_ref(), Expr::Collate { .. }),
2087 "COLLATE should bind tighter than concat"
2088 ),
2089 other => unreachable!("expected Concat(a, Collate(b)), got {other:?}"),
2090 }
2091 }
2092
2093 #[test]
2095 fn test_pratt_level11_unary_negate_tightest() {
2096 let expr = parse("-a * b");
2098 match &expr {
2099 Expr::BinaryOp {
2100 op: BinaryOp::Multiply,
2101 left,
2102 ..
2103 } => assert!(
2104 matches!(
2105 left.as_ref(),
2106 Expr::UnaryOp {
2107 op: UnaryOp::Negate,
2108 ..
2109 }
2110 ),
2111 "unary minus should bind tighter than multiply"
2112 ),
2113 other => unreachable!("expected Mul(Negate(a), b), got {other:?}"),
2114 }
2115 }
2116
2117 #[test]
2118 fn test_pratt_level11_bitnot_tightest() {
2119 let expr = parse("~a + b");
2121 match &expr {
2122 Expr::BinaryOp {
2123 op: BinaryOp::Add,
2124 left,
2125 ..
2126 } => assert!(
2127 matches!(
2128 left.as_ref(),
2129 Expr::UnaryOp {
2130 op: UnaryOp::BitNot,
2131 ..
2132 }
2133 ),
2134 "bitwise NOT should bind tighter than addition"
2135 ),
2136 other => unreachable!("expected Add(BitNot(a), b), got {other:?}"),
2137 }
2138 }
2139
2140 #[test]
2142 fn test_pratt_escape_not_infix_operator() {
2143 let expr = parse("a LIKE b ESCAPE c");
2145 match &expr {
2146 Expr::Like {
2147 escape: Some(esc), ..
2148 } => assert!(
2149 matches!(esc.as_ref(), Expr::Column(_, _)),
2150 "ESCAPE should be parsed as suffix of LIKE, not standalone infix"
2151 ),
2152 other => unreachable!("expected Like with escape, got {other:?}"),
2153 }
2154 }
2155
2156 #[test]
2157 fn test_pratt_escape_glob_not_infix() {
2158 let expr = parse("a GLOB b ESCAPE c");
2160 match &expr {
2161 Expr::Like {
2162 op: LikeOp::Glob,
2163 escape: Some(_),
2164 ..
2165 } => {}
2166 other => unreachable!("expected Glob with escape, got {other:?}"),
2167 }
2168 }
2169
2170 #[test]
2172 fn test_pratt_error_recovery_multiple_errors() {
2173 use crate::parser::Parser;
2174 let mut p = Parser::from_sql("SELECT +; SELECT *; SELECT 1");
2175 let (stmts, errs) = p.parse_all();
2176 assert!(
2179 !stmts.is_empty(),
2180 "should recover and parse at least one valid statement"
2181 );
2182 assert!(
2183 !errs.is_empty(),
2184 "should collect at least one error from malformed statements"
2185 );
2186 }
2187
2188 #[test]
2190 fn test_pratt_complex_mixed_all_levels() {
2191 let expr = parse("NOT a = b + c * -d OR e < f AND g LIKE h");
2194 match &expr {
2196 Expr::BinaryOp {
2197 op: BinaryOp::Or,
2198 left,
2199 right,
2200 ..
2201 } => {
2202 assert!(
2204 matches!(
2205 left.as_ref(),
2206 Expr::UnaryOp {
2207 op: UnaryOp::Not,
2208 ..
2209 }
2210 ),
2211 "left of OR should be NOT(...)"
2212 );
2213 match right.as_ref() {
2215 Expr::BinaryOp {
2216 op: BinaryOp::And,
2217 left: and_left,
2218 right: and_right,
2219 ..
2220 } => {
2221 assert!(
2222 matches!(
2223 and_left.as_ref(),
2224 Expr::BinaryOp {
2225 op: BinaryOp::Lt,
2226 ..
2227 }
2228 ),
2229 "left of AND should be Lt(e,f)"
2230 );
2231 assert!(
2232 matches!(and_right.as_ref(), Expr::Like { .. }),
2233 "right of AND should be Like(g,h)"
2234 );
2235 }
2236 other => unreachable!("expected And(Lt, Like), got {other:?}"),
2237 }
2238
2239 if let Expr::UnaryOp {
2242 expr: not_inner, ..
2243 } = left.as_ref()
2244 {
2245 if let Expr::BinaryOp {
2246 op: BinaryOp::Eq,
2247 right: eq_right,
2248 ..
2249 } = not_inner.as_ref()
2250 {
2251 if let Expr::BinaryOp {
2252 op: BinaryOp::Add,
2253 right: add_right,
2254 ..
2255 } = eq_right.as_ref()
2256 {
2257 if let Expr::BinaryOp {
2258 op: BinaryOp::Multiply,
2259 right: mul_right,
2260 ..
2261 } = add_right.as_ref()
2262 {
2263 assert!(
2264 matches!(
2265 mul_right.as_ref(),
2266 Expr::UnaryOp {
2267 op: UnaryOp::Negate,
2268 ..
2269 }
2270 ),
2271 "deepest: negate"
2272 );
2273 } else {
2274 unreachable!("expected Mul in add_right");
2275 }
2276 } else {
2277 unreachable!("expected Add in eq_right");
2278 }
2279 } else {
2280 unreachable!("expected Eq inside NOT");
2281 }
2282 }
2283 }
2284 other => unreachable!("expected Or(Not(...), And(...)), got {other:?}"),
2285 }
2286 }
2287
2288 #[test]
2290 fn test_pratt_json_same_precedence_as_concat() {
2291 let expr = parse("a || b -> c");
2293 match &expr {
2294 Expr::JsonAccess {
2295 expr: left,
2296 path: right,
2297 arrow: JsonArrow::Arrow,
2298 ..
2299 } => {
2300 assert!(
2301 matches!(
2302 left.as_ref(),
2303 Expr::BinaryOp {
2304 op: BinaryOp::Concat,
2305 ..
2306 }
2307 ),
2308 "left side should be concat expression"
2309 );
2310 assert!(
2311 matches!(right.as_ref(), Expr::Column(_, _)),
2312 "path should remain the right-hand expression"
2313 );
2314 }
2315 other => unreachable!("expected JsonAccess(Concat(a,b), c), got {other:?}"),
2316 }
2317 }
2318
2319 #[test]
2320 fn test_pratt_double_arrow_same_precedence_as_concat() {
2321 let expr = parse("a || b ->> c");
2322 assert!(
2323 matches!(
2324 expr,
2325 Expr::JsonAccess {
2326 arrow: JsonArrow::DoubleArrow,
2327 ..
2328 }
2329 ),
2330 "double-arrow should parse as JsonAccess at the same precedence level as concat"
2331 );
2332 }
2333}