Merge pull request #80 from benesch/between-expr

Support nested expressions in BETWEEN
This commit is contained in:
Nickolay Ponomarev 2019-05-30 02:37:06 +03:00 committed by GitHub
commit d80f9f3a7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 2 deletions

View file

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

View file

@ -497,6 +497,55 @@ fn parse_between() {
chk(true);
}
#[test]
fn parse_between_with_expr() {
use self::ASTNode::*;
use self::SQLOperator::*;
let sql = "SELECT * FROM t WHERE 1 BETWEEN 1 + 2 AND 3 + 4 IS NULL";
let select = verified_only_select(sql);
assert_eq!(
ASTNode::SQLIsNull(Box::new(ASTNode::SQLBetween {
expr: Box::new(ASTNode::SQLValue(Value::Long(1))),
low: Box::new(SQLBinaryExpr {
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
op: Plus,
right: Box::new(ASTNode::SQLValue(Value::Long(2))),
}),
high: Box::new(SQLBinaryExpr {
left: Box::new(ASTNode::SQLValue(Value::Long(3))),
op: Plus,
right: Box::new(ASTNode::SQLValue(Value::Long(4))),
}),
negated: false,
})),
select.selection.unwrap()
);
let sql = "SELECT * FROM t WHERE 1 = 1 AND 1 + x BETWEEN 1 AND 2";
let select = verified_only_select(sql);
assert_eq!(
ASTNode::SQLBinaryExpr {
left: Box::new(ASTNode::SQLBinaryExpr {
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
op: SQLOperator::Eq,
right: Box::new(ASTNode::SQLValue(Value::Long(1))),
}),
op: SQLOperator::And,
right: Box::new(ASTNode::SQLBetween {
expr: Box::new(ASTNode::SQLBinaryExpr {
left: Box::new(ASTNode::SQLValue(Value::Long(1))),
op: SQLOperator::Plus,
right: Box::new(ASTNode::SQLIdentifier("x".to_string())),
}),
low: Box::new(ASTNode::SQLValue(Value::Long(1))),
high: Box::new(ASTNode::SQLValue(Value::Long(2))),
negated: false,
}),
},
select.selection.unwrap(),
)
}
#[test]
fn parse_select_order_by() {
fn chk(sql: &str) {