ANY and ALL contains their operators (#963)

This commit is contained in:
SeanTroyUWO 2023-09-07 14:32:50 -06:00 committed by GitHub
parent b02c3f87ec
commit e0afd4b179
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 20 deletions

View file

@ -419,10 +419,18 @@ pub enum Expr {
pattern: Box<Expr>, pattern: Box<Expr>,
escape_char: Option<char>, escape_char: Option<char>,
}, },
/// Any operation e.g. `1 ANY (1)` or `foo > ANY(bar)`, It will be wrapped in the right side of BinaryExpr /// Any operation e.g. `foo > ANY(bar)`, comparison operator is one of [=, >, <, =>, =<, !=]
AnyOp(Box<Expr>), AnyOp {
/// ALL operation e.g. `1 ALL (1)` or `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr left: Box<Expr>,
AllOp(Box<Expr>), compare_op: BinaryOperator,
right: Box<Expr>,
},
/// ALL operation e.g. `foo > ALL(bar)`, comparison operator is one of [=, >, <, =>, =<, !=]
AllOp {
left: Box<Expr>,
compare_op: BinaryOperator,
right: Box<Expr>,
},
/// Unary operation e.g. `NOT foo` /// Unary operation e.g. `NOT foo`
UnaryOp { op: UnaryOperator, expr: Box<Expr> }, UnaryOp { op: UnaryOperator, expr: Box<Expr> },
/// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))` /// CAST an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))`
@ -724,8 +732,16 @@ impl fmt::Display for Expr {
pattern pattern
), ),
}, },
Expr::AnyOp(expr) => write!(f, "ANY({expr})"), Expr::AnyOp {
Expr::AllOp(expr) => write!(f, "ALL({expr})"), left,
compare_op,
right,
} => write!(f, "{left} {compare_op} ANY({right})"),
Expr::AllOp {
left,
compare_op,
right,
} => write!(f, "{left} {compare_op} ALL({right})"),
Expr::UnaryOp { op, expr } => { Expr::UnaryOp { op, expr } => {
if op == &UnaryOperator::PGPostfixFactorial { if op == &UnaryOperator::PGPostfixFactorial {
write!(f, "{expr}{op}") write!(f, "{expr}{op}")

View file

@ -1782,16 +1782,32 @@ impl<'a> Parser<'a> {
let right = self.parse_subexpr(precedence)?; let right = self.parse_subexpr(precedence)?;
self.expect_token(&Token::RParen)?; self.expect_token(&Token::RParen)?;
let right = match keyword { if !matches!(
Keyword::ALL => Box::new(Expr::AllOp(Box::new(right))), op,
Keyword::ANY => Box::new(Expr::AnyOp(Box::new(right))), BinaryOperator::Gt
_ => unreachable!(), | BinaryOperator::Lt
| BinaryOperator::GtEq
| BinaryOperator::LtEq
| BinaryOperator::Eq
| BinaryOperator::NotEq
) {
return parser_err!(format!(
"Expected one of [=, >, <, =>, =<, !=] as comparison operator, found: {op}"
));
}; };
Ok(Expr::BinaryOp { Ok(match keyword {
Keyword::ALL => Expr::AllOp {
left: Box::new(expr), left: Box::new(expr),
op, compare_op: op,
right, right: Box::new(right),
},
Keyword::ANY => Expr::AnyOp {
left: Box::new(expr),
compare_op: op,
right: Box::new(right),
},
_ => unreachable!(),
}) })
} else { } else {
Ok(Expr::BinaryOp { Ok(Expr::BinaryOp {

View file

@ -1558,10 +1558,10 @@ fn parse_bitwise_ops() {
fn parse_binary_any() { fn parse_binary_any() {
let select = verified_only_select("SELECT a = ANY(b)"); let select = verified_only_select("SELECT a = ANY(b)");
assert_eq!( assert_eq!(
SelectItem::UnnamedExpr(Expr::BinaryOp { SelectItem::UnnamedExpr(Expr::AnyOp {
left: Box::new(Expr::Identifier(Ident::new("a"))), left: Box::new(Expr::Identifier(Ident::new("a"))),
op: BinaryOperator::Eq, compare_op: BinaryOperator::Eq,
right: Box::new(Expr::AnyOp(Box::new(Expr::Identifier(Ident::new("b"))))), right: Box::new(Expr::Identifier(Ident::new("b"))),
}), }),
select.projection[0] select.projection[0]
); );
@ -1571,10 +1571,10 @@ fn parse_binary_any() {
fn parse_binary_all() { fn parse_binary_all() {
let select = verified_only_select("SELECT a = ALL(b)"); let select = verified_only_select("SELECT a = ALL(b)");
assert_eq!( assert_eq!(
SelectItem::UnnamedExpr(Expr::BinaryOp { SelectItem::UnnamedExpr(Expr::AllOp {
left: Box::new(Expr::Identifier(Ident::new("a"))), left: Box::new(Expr::Identifier(Ident::new("a"))),
op: BinaryOperator::Eq, compare_op: BinaryOperator::Eq,
right: Box::new(Expr::AllOp(Box::new(Expr::Identifier(Ident::new("b"))))), right: Box::new(Expr::Identifier(Ident::new("b"))),
}), }),
select.projection[0] select.projection[0]
); );