From 516b4ecd595bd67023c63a839f2fd921861fa57b Mon Sep 17 00:00:00 2001 From: SeanTroyUWO Date: Sat, 2 Sep 2023 17:00:58 -0700 Subject: [PATCH 1/2] Raises the precedence of the `ANY` and `ALL` keywords, and makes the comparison operators which precede them a variation of them. --- src/ast/mod.rs | 20 +++++++++++++------ src/parser/mod.rs | 42 ++++++++++++++++++++++++++++++--------- tests/sqlparser_common.rs | 12 +++++------ 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index a241f9509..3fea60e5d 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,8 @@ 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 846215249..36a632b15 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1773,17 +1773,41 @@ 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, + // 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, + // }) + + + 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 { left: Box::new(expr), diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 3fdf3d211..0e28fa72c 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -1553,10 +1553,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] ); @@ -1566,10 +1566,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] ); From f61942097570fa46f2d590af591ff273e48b948b Mon Sep 17 00:00:00 2001 From: SeanTroyUWO Date: Sun, 3 Sep 2023 10:46:49 -0700 Subject: [PATCH 2/2] appeases clippy and removes comments --- src/ast/mod.rs | 20 ++++++++++++++------ src/parser/mod.rs | 38 +++++++++++++++----------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 3fea60e5d..41d66166d 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -420,16 +420,16 @@ pub enum Expr { escape_char: Option, }, /// Any operation e.g. `foo > ANY(bar)`, comparison operator is one of [=, >, <, =>, =<, !=] - AnyOp{ + AnyOp { left: Box, compare_op: BinaryOperator, - right: Box + right: Box, }, /// ALL operation e.g. `foo > ALL(bar)`, comparison operator is one of [=, >, <, =>, =<, !=] - AllOp{ + AllOp { left: Box, compare_op: BinaryOperator, - right: Box + right: Box, }, /// Unary operation e.g. `NOT foo` UnaryOp { op: UnaryOperator, expr: Box }, @@ -732,8 +732,16 @@ impl fmt::Display for Expr { pattern ), }, - 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::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 36a632b15..22a3d2c96 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1773,41 +1773,33 @@ impl<'a> Parser<'a> { let right = self.parse_subexpr(precedence)?; self.expect_token(&Token::RParen)?; - 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}")) - }; - - // 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, - // }) - + 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(match keyword { - Keyword::ALL => Expr::AllOp{ + Keyword::ALL => Expr::AllOp { left: Box::new(expr), compare_op: op, right: Box::new(right), }, - Keyword::ANY => Expr::AnyOp{ + Keyword::ANY => Expr::AnyOp { left: Box::new(expr), compare_op: op, right: Box::new(right), }, _ => unreachable!(), }) - } else { Ok(Expr::BinaryOp { left: Box::new(expr),