mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-27 16:09:09 +00:00
Support BETWEEN
This commit is contained in:
parent
264319347d
commit
786b1cf18a
3 changed files with 58 additions and 0 deletions
|
@ -64,6 +64,13 @@ pub enum ASTNode {
|
||||||
subquery: Box<SQLQuery>,
|
subquery: Box<SQLQuery>,
|
||||||
negated: bool,
|
negated: bool,
|
||||||
},
|
},
|
||||||
|
/// <expr> [ NOT ] BETWEEN <low> AND <high>
|
||||||
|
SQLBetween {
|
||||||
|
expr: Box<ASTNode>,
|
||||||
|
negated: bool,
|
||||||
|
low: Box<ASTNode>,
|
||||||
|
high: Box<ASTNode>,
|
||||||
|
},
|
||||||
/// Binary expression e.g. `1 + 1` or `foo > bar`
|
/// Binary expression e.g. `1 + 1` or `foo > bar`
|
||||||
SQLBinaryExpr {
|
SQLBinaryExpr {
|
||||||
left: Box<ASTNode>,
|
left: Box<ASTNode>,
|
||||||
|
@ -131,6 +138,18 @@ impl ToString for ASTNode {
|
||||||
if *negated { "NOT " } else { "" },
|
if *negated { "NOT " } else { "" },
|
||||||
subquery.to_string()
|
subquery.to_string()
|
||||||
),
|
),
|
||||||
|
ASTNode::SQLBetween {
|
||||||
|
expr,
|
||||||
|
negated,
|
||||||
|
low,
|
||||||
|
high,
|
||||||
|
} => format!(
|
||||||
|
"{} {}BETWEEN {} AND {}",
|
||||||
|
expr.to_string(),
|
||||||
|
if *negated { "NOT " } else { "" },
|
||||||
|
low.to_string(),
|
||||||
|
high.to_string()
|
||||||
|
),
|
||||||
ASTNode::SQLBinaryExpr { left, op, right } => format!(
|
ASTNode::SQLBinaryExpr { left, op, right } => format!(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
left.as_ref().to_string(),
|
left.as_ref().to_string(),
|
||||||
|
|
|
@ -309,6 +309,8 @@ impl Parser {
|
||||||
Token::SQLWord(ref k) if k.keyword == "NOT" => {
|
Token::SQLWord(ref k) if k.keyword == "NOT" => {
|
||||||
if self.parse_keyword("IN") {
|
if self.parse_keyword("IN") {
|
||||||
self.parse_in(expr, true)
|
self.parse_in(expr, true)
|
||||||
|
} else if self.parse_keyword("BETWEEN") {
|
||||||
|
self.parse_between(expr, true)
|
||||||
} else if self.parse_keyword("LIKE") {
|
} else if self.parse_keyword("LIKE") {
|
||||||
Ok(ASTNode::SQLBinaryExpr {
|
Ok(ASTNode::SQLBinaryExpr {
|
||||||
left: Box::new(expr),
|
left: Box::new(expr),
|
||||||
|
@ -323,6 +325,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token::SQLWord(ref k) if k.keyword == "IN" => self.parse_in(expr, false),
|
Token::SQLWord(ref k) if k.keyword == "IN" => self.parse_in(expr, false),
|
||||||
|
Token::SQLWord(ref k) if k.keyword == "BETWEEN" => self.parse_between(expr, false),
|
||||||
Token::DoubleColon => self.parse_pg_cast(expr),
|
Token::DoubleColon => self.parse_pg_cast(expr),
|
||||||
Token::SQLWord(_)
|
Token::SQLWord(_)
|
||||||
| Token::Eq
|
| Token::Eq
|
||||||
|
@ -369,6 +372,19 @@ impl Parser {
|
||||||
Ok(in_op)
|
Ok(in_op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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()?;
|
||||||
|
self.expect_keyword("AND")?;
|
||||||
|
let high = self.parse_prefix()?;
|
||||||
|
Ok(ASTNode::SQLBetween {
|
||||||
|
expr: Box::new(expr),
|
||||||
|
negated,
|
||||||
|
low: Box::new(low),
|
||||||
|
high: Box::new(high),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Parse a postgresql casting style which is in the form of `expr::datatype`
|
/// Parse a postgresql casting style which is in the form of `expr::datatype`
|
||||||
pub fn parse_pg_cast(&mut self, expr: ASTNode) -> Result<ASTNode, ParserError> {
|
pub fn parse_pg_cast(&mut self, expr: ASTNode) -> Result<ASTNode, ParserError> {
|
||||||
Ok(ASTNode::SQLCast {
|
Ok(ASTNode::SQLCast {
|
||||||
|
@ -418,6 +434,7 @@ impl Parser {
|
||||||
&Token::SQLWord(ref k) if k.keyword == "NOT" => Ok(15),
|
&Token::SQLWord(ref k) if k.keyword == "NOT" => Ok(15),
|
||||||
&Token::SQLWord(ref k) if k.keyword == "IS" => Ok(17),
|
&Token::SQLWord(ref k) if k.keyword == "IS" => Ok(17),
|
||||||
&Token::SQLWord(ref k) if k.keyword == "IN" => Ok(20),
|
&Token::SQLWord(ref k) if k.keyword == "IN" => Ok(20),
|
||||||
|
&Token::SQLWord(ref k) if k.keyword == "BETWEEN" => Ok(20),
|
||||||
&Token::SQLWord(ref k) if k.keyword == "LIKE" => Ok(20),
|
&Token::SQLWord(ref k) if k.keyword == "LIKE" => Ok(20),
|
||||||
&Token::Eq | &Token::Lt | &Token::LtEq | &Token::Neq | &Token::Gt | &Token::GtEq => {
|
&Token::Eq | &Token::Lt | &Token::LtEq | &Token::Neq | &Token::Gt | &Token::GtEq => {
|
||||||
Ok(20)
|
Ok(20)
|
||||||
|
|
|
@ -288,6 +288,28 @@ fn parse_in_subquery() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_between() {
|
||||||
|
fn chk(negated: bool) {
|
||||||
|
let sql = &format!(
|
||||||
|
"SELECT * FROM customers WHERE age {}BETWEEN 25 AND 32",
|
||||||
|
if negated { "NOT " } else { "" }
|
||||||
|
);
|
||||||
|
let select = verified_only_select(sql);
|
||||||
|
assert_eq!(
|
||||||
|
ASTNode::SQLBetween {
|
||||||
|
expr: Box::new(ASTNode::SQLIdentifier("age".to_string())),
|
||||||
|
low: Box::new(ASTNode::SQLValue(Value::Long(25))),
|
||||||
|
high: Box::new(ASTNode::SQLValue(Value::Long(32))),
|
||||||
|
negated,
|
||||||
|
},
|
||||||
|
select.selection.unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
chk(false);
|
||||||
|
chk(true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_select_order_by() {
|
fn parse_select_order_by() {
|
||||||
fn chk(sql: &str) {
|
fn chk(sql: &str) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue