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>,
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
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>),
/// Any operation e.g. `foo > ANY(bar)`, comparison operator is one of [=, >, <, =>, =<, !=]
AnyOp {
left: 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`
UnaryOp { op: UnaryOperator, expr: Box<Expr> },
/// 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
),
},
Expr::AnyOp(expr) => write!(f, "ANY({expr})"),
Expr::AllOp(expr) => write!(f, "ALL({expr})"),
Expr::AnyOp {
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 } => {
if op == &UnaryOperator::PGPostfixFactorial {
write!(f, "{expr}{op}")

View file

@ -1782,16 +1782,32 @@ impl<'a> Parser<'a> {
let right = 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!(),
if !matches!(
op,
BinaryOperator::Gt
| 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 {
left: Box::new(expr),
op,
right,
Ok(match keyword {
Keyword::ALL => Expr::AllOp {
left: Box::new(expr),
compare_op: op,
right: Box::new(right),
},
Keyword::ANY => Expr::AnyOp {
left: Box::new(expr),
compare_op: op,
right: Box::new(right),
},
_ => unreachable!(),
})
} else {
Ok(Expr::BinaryOp {

View file

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