Make `BitwiseNot` ("~") available for all dialects, not just PostgreSQL (#2081)
diff --git a/src/ast/operator.rs b/src/ast/operator.rs
index d0bb05e..58c401f 100644
--- a/src/ast/operator.rs
+++ b/src/ast/operator.rs
@@ -33,35 +33,35 @@
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum UnaryOperator {
+ /// `@-@` Length or circumference (PostgreSQL/Redshift geometric operator)
+ /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
+ AtDashAt,
+ /// Unary logical not operator: e.g. `! false` (Hive-specific)
+ BangNot,
+ /// Bitwise Not, e.g. `~9`
+ BitwiseNot,
+ /// `@@` Center (PostgreSQL/Redshift geometric operator)
+ /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
+ DoubleAt,
+ /// `#` Number of points in path or polygon (PostgreSQL/Redshift geometric operator)
+ /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
+ Hash,
/// Plus, e.g. `+9`
Plus,
/// Minus, e.g. `-9`
Minus,
/// Not, e.g. `NOT(true)`
Not,
- /// Bitwise Not, e.g. `~9` (PostgreSQL-specific)
- PGBitwiseNot,
- /// Square root, e.g. `|/9` (PostgreSQL-specific)
- PGSquareRoot,
+ /// Absolute value, e.g. `@ -9` (PostgreSQL-specific)
+ PGAbs,
/// Cube root, e.g. `||/27` (PostgreSQL-specific)
PGCubeRoot,
/// Factorial, e.g. `9!` (PostgreSQL-specific)
PGPostfixFactorial,
/// Factorial, e.g. `!!9` (PostgreSQL-specific)
PGPrefixFactorial,
- /// Absolute value, e.g. `@ -9` (PostgreSQL-specific)
- PGAbs,
- /// Unary logical not operator: e.g. `! false` (Hive-specific)
- BangNot,
- /// `#` Number of points in path or polygon (PostgreSQL/Redshift geometric operator)
- /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
- Hash,
- /// `@-@` Length or circumference (PostgreSQL/Redshift geometric operator)
- /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
- AtDashAt,
- /// `@@` Center (PostgreSQL/Redshift geometric operator)
- /// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
- DoubleAt,
+ /// Square root, e.g. `|/9` (PostgreSQL-specific)
+ PGSquareRoot,
/// `?-` Is horizontal? (PostgreSQL/Redshift geometric operator)
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
QuestionDash,
@@ -73,19 +73,19 @@
impl fmt::Display for UnaryOperator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
- UnaryOperator::Plus => "+",
+ UnaryOperator::AtDashAt => "@-@",
+ UnaryOperator::BangNot => "!",
+ UnaryOperator::BitwiseNot => "~",
+ UnaryOperator::DoubleAt => "@@",
+ UnaryOperator::Hash => "#",
UnaryOperator::Minus => "-",
UnaryOperator::Not => "NOT",
- UnaryOperator::PGBitwiseNot => "~",
- UnaryOperator::PGSquareRoot => "|/",
+ UnaryOperator::PGAbs => "@",
UnaryOperator::PGCubeRoot => "||/",
UnaryOperator::PGPostfixFactorial => "!",
UnaryOperator::PGPrefixFactorial => "!!",
- UnaryOperator::PGAbs => "@",
- UnaryOperator::BangNot => "!",
- UnaryOperator::Hash => "#",
- UnaryOperator::AtDashAt => "@-@",
- UnaryOperator::DoubleAt => "@@",
+ UnaryOperator::PGSquareRoot => "|/",
+ UnaryOperator::Plus => "+",
UnaryOperator::QuestionDash => "?-",
UnaryOperator::QuestionPipe => "?|",
})
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 1248c91..9a01e51 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -1633,7 +1633,6 @@
| tok @ Token::PGSquareRoot
| tok @ Token::PGCubeRoot
| tok @ Token::AtSign
- | tok @ Token::Tilde
if dialect_is!(dialect is PostgreSqlDialect) =>
{
let op = match tok {
@@ -1641,7 +1640,6 @@
Token::PGSquareRoot => UnaryOperator::PGSquareRoot,
Token::PGCubeRoot => UnaryOperator::PGCubeRoot,
Token::AtSign => UnaryOperator::PGAbs,
- Token::Tilde => UnaryOperator::PGBitwiseNot,
_ => unreachable!(),
};
Ok(Expr::UnaryOp {
@@ -1651,6 +1649,10 @@
),
})
}
+ Token::Tilde => Ok(Expr::UnaryOp {
+ op: UnaryOperator::BitwiseNot,
+ expr: Box::new(self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?),
+ }),
tok @ Token::Sharp
| tok @ Token::AtDashAt
| tok @ Token::AtAt
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 99b7ac3..f1ba5df 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -17613,3 +17613,22 @@
}
verified_stmt("ALTER USER u1 SET DEFAULT_SECONDARY_ROLES=('ALL'), PASSWORD='secret', WORKLOAD_IDENTITY=(TYPE=AWS, ARN='arn:aws:iam::123456789:r1/')");
}
+
+#[test]
+fn parse_generic_unary_ops() {
+ let unary_ops = &[
+ ("~", UnaryOperator::BitwiseNot),
+ ("-", UnaryOperator::Minus),
+ ("+", UnaryOperator::Plus),
+ ];
+ for (str_op, op) in unary_ops {
+ let select = verified_only_select(&format!("SELECT {}expr", &str_op));
+ assert_eq!(
+ UnnamedExpr(UnaryOp {
+ op: *op,
+ expr: Box::new(Identifier(Ident::new("expr"))),
+ }),
+ select.projection[0]
+ );
+ }
+}
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index bcc1542..9ba0fb9 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -2144,13 +2144,11 @@
#[test]
fn parse_pg_unary_ops() {
let pg_unary_ops = &[
- ("~", UnaryOperator::PGBitwiseNot),
("|/", UnaryOperator::PGSquareRoot),
("||/", UnaryOperator::PGCubeRoot),
("!!", UnaryOperator::PGPrefixFactorial),
("@", UnaryOperator::PGAbs),
];
-
for (str_op, op) in pg_unary_ops {
let select = pg().verified_only_select(&format!("SELECT {}a", &str_op));
assert_eq!(