mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-26 15:39:12 +00:00
feat: Support ANY/ALL operators (#477)
* feat: Support ANY/ALL operators * fix lint
This commit is contained in:
parent
e68bdae5f2
commit
8ef5fc8624
3 changed files with 56 additions and 5 deletions
|
@ -270,6 +270,10 @@ pub enum Expr {
|
||||||
op: BinaryOperator,
|
op: BinaryOperator,
|
||||||
right: Box<Expr>,
|
right: Box<Expr>,
|
||||||
},
|
},
|
||||||
|
/// Any operation e.g. `1 ANY (1)` or `foo > ANY(bar)`, It will be wrapped in the right side of BinaryExpr
|
||||||
|
AnyOp(Box<Expr>),
|
||||||
|
/// ALL operation e.g. `1 ALL (1)` or `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr
|
||||||
|
AllOp(Box<Expr>),
|
||||||
/// Unary operation e.g. `NOT foo`
|
/// Unary operation e.g. `NOT foo`
|
||||||
UnaryOp {
|
UnaryOp {
|
||||||
op: UnaryOperator,
|
op: UnaryOperator,
|
||||||
|
@ -433,6 +437,8 @@ impl fmt::Display for Expr {
|
||||||
high
|
high
|
||||||
),
|
),
|
||||||
Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
|
Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
|
||||||
|
Expr::AnyOp(expr) => write!(f, "ANY({})", expr),
|
||||||
|
Expr::AllOp(expr) => write!(f, "ALL({})", expr),
|
||||||
Expr::UnaryOp { op, expr } => {
|
Expr::UnaryOp { op, expr } => {
|
||||||
if op == &UnaryOperator::PGPostfixFactorial {
|
if op == &UnaryOperator::PGPostfixFactorial {
|
||||||
write!(f, "{}{}", expr, op)
|
write!(f, "{}{}", expr, op)
|
||||||
|
|
|
@ -1060,6 +1060,7 @@ impl<'a> Parser<'a> {
|
||||||
/// Parse an operator following an expression
|
/// Parse an operator following an expression
|
||||||
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
|
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
|
||||||
let tok = self.next_token();
|
let tok = self.next_token();
|
||||||
|
|
||||||
let regular_binary_operator = match &tok {
|
let regular_binary_operator = match &tok {
|
||||||
Token::Spaceship => Some(BinaryOperator::Spaceship),
|
Token::Spaceship => Some(BinaryOperator::Spaceship),
|
||||||
Token::DoubleEq => Some(BinaryOperator::Eq),
|
Token::DoubleEq => Some(BinaryOperator::Eq),
|
||||||
|
@ -1112,11 +1113,29 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(op) = regular_binary_operator {
|
if let Some(op) = regular_binary_operator {
|
||||||
Ok(Expr::BinaryOp {
|
if let Some(keyword) = self.parse_one_of_keywords(&[Keyword::ANY, Keyword::ALL]) {
|
||||||
left: Box::new(expr),
|
self.expect_token(&Token::LParen)?;
|
||||||
op,
|
let right = self.parse_subexpr(precedence)?;
|
||||||
right: Box::new(self.parse_subexpr(precedence)?),
|
self.expect_token(&Token::RParen)?;
|
||||||
})
|
|
||||||
|
let right = match keyword {
|
||||||
|
Keyword::ALL => Box::new(Expr::AllOp(Box::new(right))),
|
||||||
|
Keyword::ANY => Box::new(Expr::AnyOp(Box::new(right))),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Expr::BinaryOp {
|
||||||
|
left: Box::new(expr),
|
||||||
|
op,
|
||||||
|
right,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(Expr::BinaryOp {
|
||||||
|
left: Box::new(expr),
|
||||||
|
op,
|
||||||
|
right: Box::new(self.parse_subexpr(precedence)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if let Token::Word(w) = &tok {
|
} else if let Token::Word(w) = &tok {
|
||||||
match w.keyword {
|
match w.keyword {
|
||||||
Keyword::IS => {
|
Keyword::IS => {
|
||||||
|
|
|
@ -998,6 +998,32 @@ fn parse_bitwise_ops() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_binary_any() {
|
||||||
|
let select = verified_only_select("SELECT a = ANY(b)");
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Identifier(Ident::new("a"))),
|
||||||
|
op: BinaryOperator::Eq,
|
||||||
|
right: Box::new(Expr::AnyOp(Box::new(Expr::Identifier(Ident::new("b"))))),
|
||||||
|
}),
|
||||||
|
select.projection[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_binary_all() {
|
||||||
|
let select = verified_only_select("SELECT a = ALL(b)");
|
||||||
|
assert_eq!(
|
||||||
|
SelectItem::UnnamedExpr(Expr::BinaryOp {
|
||||||
|
left: Box::new(Expr::Identifier(Ident::new("a"))),
|
||||||
|
op: BinaryOperator::Eq,
|
||||||
|
right: Box::new(Expr::AllOp(Box::new(Expr::Identifier(Ident::new("b"))))),
|
||||||
|
}),
|
||||||
|
select.projection[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_logical_xor() {
|
fn parse_logical_xor() {
|
||||||
let sql = "SELECT true XOR true, false XOR false, true XOR false, false XOR true";
|
let sql = "SELECT true XOR true, false XOR false, true XOR false, false XOR true";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue