Skip to content

Commit 804047c

Browse files
committed
feat: Support ANY/ALL operators (apache#477)
* feat: Support ANY/ALL operators * fix lint
1 parent 81217ce commit 804047c

3 files changed

Lines changed: 56 additions & 5 deletions

File tree

src/ast/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ pub enum Expr {
232232
op: BinaryOperator,
233233
right: Box<Expr>,
234234
},
235+
/// Any operation e.g. `1 ANY (1)` or `foo > ANY(bar)`, It will be wrapped in the right side of BinaryExpr
236+
AnyOp(Box<Expr>),
237+
/// ALL operation e.g. `1 ALL (1)` or `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr
238+
AllOp(Box<Expr>),
235239
/// Unary operation e.g. `NOT foo`
236240
UnaryOp {
237241
op: UnaryOperator,
@@ -395,6 +399,8 @@ impl fmt::Display for Expr {
395399
high
396400
),
397401
Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
402+
Expr::AnyOp(expr) => write!(f, "ANY({})", expr),
403+
Expr::AllOp(expr) => write!(f, "ALL({})", expr),
398404
Expr::UnaryOp { op, expr } => {
399405
if op == &UnaryOperator::PGPostfixFactorial {
400406
write!(f, "{}{}", expr, op)

src/parser.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,7 @@ impl<'a> Parser<'a> {
10521052
/// Parse an operator following an expression
10531053
pub fn parse_infix(&mut self, expr: Expr, precedence: u8) -> Result<Expr, ParserError> {
10541054
let tok = self.next_token();
1055+
10551056
let regular_binary_operator = match &tok {
10561057
Token::Spaceship => Some(BinaryOperator::Spaceship),
10571058
Token::DoubleEq => Some(BinaryOperator::Eq),
@@ -1104,11 +1105,29 @@ impl<'a> Parser<'a> {
11041105
};
11051106

11061107
if let Some(op) = regular_binary_operator {
1107-
Ok(Expr::BinaryOp {
1108-
left: Box::new(expr),
1109-
op,
1110-
right: Box::new(self.parse_subexpr(precedence)?),
1111-
})
1108+
if let Some(keyword) = self.parse_one_of_keywords(&[Keyword::ANY, Keyword::ALL]) {
1109+
self.expect_token(&Token::LParen)?;
1110+
let right = self.parse_subexpr(precedence)?;
1111+
self.expect_token(&Token::RParen)?;
1112+
1113+
let right = match keyword {
1114+
Keyword::ALL => Box::new(Expr::AllOp(Box::new(right))),
1115+
Keyword::ANY => Box::new(Expr::AnyOp(Box::new(right))),
1116+
_ => unreachable!(),
1117+
};
1118+
1119+
Ok(Expr::BinaryOp {
1120+
left: Box::new(expr),
1121+
op,
1122+
right,
1123+
})
1124+
} else {
1125+
Ok(Expr::BinaryOp {
1126+
left: Box::new(expr),
1127+
op,
1128+
right: Box::new(self.parse_subexpr(precedence)?),
1129+
})
1130+
}
11121131
} else if let Token::Word(w) = &tok {
11131132
match w.keyword {
11141133
Keyword::IS => {

tests/sqlparser_common.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,32 @@ fn parse_bitwise_ops() {
991991
}
992992
}
993993

994+
#[test]
995+
fn parse_binary_any() {
996+
let select = verified_only_select("SELECT a = ANY(b)");
997+
assert_eq!(
998+
SelectItem::UnnamedExpr(Expr::BinaryOp {
999+
left: Box::new(Expr::Identifier(Ident::new("a"))),
1000+
op: BinaryOperator::Eq,
1001+
right: Box::new(Expr::AnyOp(Box::new(Expr::Identifier(Ident::new("b"))))),
1002+
}),
1003+
select.projection[0]
1004+
);
1005+
}
1006+
1007+
#[test]
1008+
fn parse_binary_all() {
1009+
let select = verified_only_select("SELECT a = ALL(b)");
1010+
assert_eq!(
1011+
SelectItem::UnnamedExpr(Expr::BinaryOp {
1012+
left: Box::new(Expr::Identifier(Ident::new("a"))),
1013+
op: BinaryOperator::Eq,
1014+
right: Box::new(Expr::AllOp(Box::new(Expr::Identifier(Ident::new("b"))))),
1015+
}),
1016+
select.projection[0]
1017+
);
1018+
}
1019+
9941020
#[test]
9951021
fn parse_logical_xor() {
9961022
let sql = "SELECT true XOR true, false XOR false, true XOR false, false XOR true";

0 commit comments

Comments
 (0)