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