Skip to content

Commit ba21ce9

Browse files
committed
Support nested expressions in BETWEEN
`BETWEEN <thing> AND <thing>` allows <thing> to be any expr that doesn't contain boolean operators. (Allowing boolean operators would wreak havoc, because of the repurposing of AND as both a boolean operation and part of the syntax of BETWEEN.)
1 parent 4f944dd commit ba21ce9

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

src/sqlparser.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,9 +478,12 @@ impl Parser {
478478

479479
/// Parses `BETWEEN <low> AND <high>`, assuming the `BETWEEN` keyword was already consumed
480480
pub fn parse_between(&mut self, expr: ASTNode, negated: bool) -> Result<ASTNode, ParserError> {
481-
let low = self.parse_prefix()?;
481+
// Stop parsing subexpressions for <low> and <high> on tokens with
482+
// precedence lower than that of `BETWEEN`, such as `AND`, `IS`, etc.
483+
let prec = self.get_precedence(&Token::make_keyword("BETWEEN"))?;
484+
let low = self.parse_subexpr(prec)?;
482485
self.expect_keyword("AND")?;
483-
let high = self.parse_prefix()?;
486+
let high = self.parse_subexpr(prec)?;
484487
Ok(ASTNode::SQLBetween {
485488
expr: Box::new(expr),
486489
negated,

tests/sqlparser_common.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,55 @@ fn parse_between() {
450450
chk(true);
451451
}
452452

453+
#[test]
454+
fn parse_between_with_expr() {
455+
use self::ASTNode::*;
456+
use self::SQLOperator::*;
457+
let sql = "SELECT * FROM t WHERE 1 BETWEEN 1 + 2 AND 3 + 4 IS NULL";
458+
let select = verified_only_select(sql);
459+
assert_eq!(
460+
ASTNode::SQLIsNull(Box::new(ASTNode::SQLBetween {
461+
expr: Box::new(ASTNode::SQLValue(Value::Long(1))),
462+
low: Box::new(SQLBinaryExpr {
463+
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
464+
op: Plus,
465+
right: Box::new(ASTNode::SQLValue(Value::Long(2))),
466+
}),
467+
high: Box::new(SQLBinaryExpr {
468+
left: Box::new(ASTNode::SQLValue(Value::Long(3))),
469+
op: Plus,
470+
right: Box::new(ASTNode::SQLValue(Value::Long(4))),
471+
}),
472+
negated: false,
473+
})),
474+
select.selection.unwrap()
475+
);
476+
477+
let sql = "SELECT * FROM t WHERE 1 = 1 AND 1 + x BETWEEN 1 AND 2";
478+
let select = verified_only_select(sql);
479+
assert_eq!(
480+
ASTNode::SQLBinaryExpr {
481+
left: Box::new(ASTNode::SQLBinaryExpr {
482+
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
483+
op: SQLOperator::Eq,
484+
right: Box::new(ASTNode::SQLValue(Value::Long(1))),
485+
}),
486+
op: SQLOperator::And,
487+
right: Box::new(ASTNode::SQLBetween {
488+
expr: Box::new(ASTNode::SQLBinaryExpr {
489+
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
490+
op: SQLOperator::Plus,
491+
right: Box::new(ASTNode::SQLIdentifier("x".to_string())),
492+
}),
493+
low: Box::new(ASTNode::SQLValue(Value::Long(1))),
494+
high: Box::new(ASTNode::SQLValue(Value::Long(2))),
495+
negated: false,
496+
}),
497+
},
498+
select.selection.unwrap(),
499+
)
500+
}
501+
453502
#[test]
454503
fn parse_select_order_by() {
455504
fn chk(sql: &str) {

0 commit comments

Comments
 (0)