From e0afd4b179bd5209be6140c0aa02ef49c5a32707 Mon Sep 17 00:00:00 2001 From: SeanTroyUWO Date: Thu, 7 Sep 2023 14:32:50 -0600 Subject: [PATCH] `ANY` and `ALL` contains their operators (#963) --- src/ast/mod.rs | 28 ++++++++++++++++++++++------ src/parser/mod.rs | 32 ++++++++++++++++++++++++-------- tests/sqlparser_common.rs | 12 ++++++------ 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index a241f9509..41d66166d 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -419,10 +419,18 @@ pub enum Expr { pattern: Box, escape_char: Option, }, - /// Any operation e.g. `1 ANY (1)` or `foo > ANY(bar)`, It will be wrapped in the right side of BinaryExpr - AnyOp(Box), - /// ALL operation e.g. `1 ALL (1)` or `foo > ALL(bar)`, It will be wrapped in the right side of BinaryExpr - AllOp(Box), + /// Any operation e.g. `foo > ANY(bar)`, comparison operator is one of [=, >, <, =>, =<, !=] + AnyOp { + left: Box, + compare_op: BinaryOperator, + right: Box, + }, + /// ALL operation e.g. `foo > ALL(bar)`, comparison operator is one of [=, >, <, =>, =<, !=] + AllOp { + left: Box, + compare_op: BinaryOperator, + right: Box, + }, /// Unary operation e.g. `NOT foo` UnaryOp { op: UnaryOperator, expr: Box }, /// 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}") diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 6902fc565..9de67a51b 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -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 { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 450743360..a9c4130b4 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -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] );