Skip to content

Commit fcd2328

Browse files
SQLite: Parse the BETWEEN lower bound up to its AND (#2664)
1 parent a9b10d0 commit fcd2328

5 files changed

Lines changed: 54 additions & 4 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SELECT a BETWEEN b > 1 AND c, a BETWEEN b LIKE 'x' AND c, a BETWEEN b IS NOT NULL AND c, a BETWEEN b NOTNULL AND c, a BETWEEN b BETWEEN 1 AND 2 AND c FROM t;
2+
SELECT 5 BETWEEN 1 AND NULL IS NULL, 5 BETWEEN 1 AND 10 = 1 FROM t

‎src/dialect/mod.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,11 @@ pub trait Dialect: Debug + Any {
11521152
0
11531153
}
11541154

1155+
/// Precedence used to stop parsing the low bound expression of a BETWEEN predicate.
1156+
fn between_low_bound_precedence(&self) -> u8 {
1157+
self.prec_value(Precedence::Between)
1158+
}
1159+
11551160
/// Returns true if this dialect requires the `TABLE` keyword after `DESCRIBE`
11561161
///
11571162
/// Defaults to false.

‎src/dialect/sqlite.rs‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ impl Dialect for SQLiteDialect {
315315
| Keyword::WHERE
316316
)
317317
}
318+
319+
/// Comparison and postfix operators bind within the BETWEEN low bound in SQLite (<https://www.sqlite.org/lang_expr.html>).
320+
fn between_low_bound_precedence(&self) -> u8 {
321+
self.prec_value(Precedence::And)
322+
}
318323
}
319324

320325
/// SQLite permits signed and decimal numeric type modifiers.

‎src/parser/mod.rs‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4614,9 +4614,7 @@ impl<'a> Parser<'a> {
46144614

46154615
/// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed.
46164616
pub fn parse_between(&mut self, expr: Expr, negated: bool) -> Result<Expr, ParserError> {
4617-
// Stop parsing subexpressions for <low> and <high> on tokens with
4618-
// precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
4619-
let low = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
4617+
let low = self.parse_subexpr(self.dialect.between_low_bound_precedence())?;
46204618
self.expect_keyword_is(Keyword::AND)?;
46214619
let high = self.parse_subexpr(self.dialect.prec_value(Precedence::Between))?;
46224620
Ok(Expr::Between {

‎tests/sqlparser_sqlite.rs‎

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,47 @@ fn test_drop_trigger() {
984984
}
985985
}
986986

987+
#[test]
988+
fn parse_between_low_bound_precedence() {
989+
match sqlite().verified_expr("a BETWEEN b > 1 AND c") {
990+
Expr::Between { low, .. } => assert!(
991+
matches!(
992+
*low,
993+
Expr::BinaryOp {
994+
op: BinaryOperator::Gt,
995+
..
996+
}
997+
),
998+
"{low:?}"
999+
),
1000+
other => panic!("expected BETWEEN, got {other:?}"),
1001+
}
1002+
sqlite().verified_expr("a BETWEEN b LIKE 'x' AND c");
1003+
sqlite().verified_expr("a BETWEEN b IS NOT NULL AND c");
1004+
sqlite().expr_parses_to("a BETWEEN b NOTNULL AND c", "a BETWEEN b IS NOT NULL AND c");
1005+
sqlite().verified_expr("a BETWEEN b BETWEEN 1 AND 2 AND c");
1006+
1007+
// Operators after the high bound apply to the whole BETWEEN.
1008+
sqlite().verified_expr("5 BETWEEN 1 AND NULL IS NULL");
1009+
sqlite().verified_expr("5 BETWEEN 1 AND 10 = 1");
1010+
1011+
// The inner AND belongs to the bound expression, so the missing `)` is reported at FROM.
1012+
assert_eq!(
1013+
sqlite().parse_sql_statements("SELECT a BETWEEN (1 AND 2 FROM t"),
1014+
Err(ParserError::ParserError(
1015+
"Expected: ), found: FROM".to_string()
1016+
))
1017+
);
1018+
1019+
assert_eq!(
1020+
TestedDialects::new(vec![Box::new(GenericDialect {})])
1021+
.parse_sql_statements("SELECT a BETWEEN b > 1 AND c FROM t"),
1022+
Err(ParserError::ParserError(
1023+
"Expected: AND, found: >".to_string()
1024+
))
1025+
);
1026+
}
1027+
9871028
#[test]
9881029
fn parse_pattern_operators_bind_at_like_precedence() {
9891030
fn where_operator(sql: &str) -> BinaryOperator {
@@ -1517,7 +1558,6 @@ fn parse_on_conflict_target_predicate() {
15171558
other => panic!("unexpected statement: {other:?}"),
15181559
}
15191560
}
1520-
15211561
fn sqlite() -> TestedDialects {
15221562
TestedDialects::new(vec![Box::new(SQLiteDialect {})])
15231563
}

0 commit comments

Comments
 (0)