Make BitwiseNot ("~") available for all dialects, not just PostgreSQL (#2081)
Some checks failed
license / Release Audit Tool (RAT) (push) Has been cancelled
Rust / codestyle (push) Has been cancelled
Rust / lint (push) Has been cancelled
Rust / benchmark-lint (push) Has been cancelled
Rust / compile (push) Has been cancelled
Rust / docs (push) Has been cancelled
Rust / compile-no-std (push) Has been cancelled
Rust / test (beta) (push) Has been cancelled
Rust / test (nightly) (push) Has been cancelled
Rust / test (stable) (push) Has been cancelled

This commit is contained in:
Alexander Beedie 2025-10-30 15:57:25 +04:00 committed by GitHub
parent bc6e1d6e1a
commit 308a7231bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 29 deletions

View file

@ -33,35 +33,35 @@ use super::display_separated;
#[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 @@ pub enum UnaryOperator {
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 => "?|",
})

View file

@ -1633,7 +1633,6 @@ impl<'a> Parser<'a> {
| 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 @@ impl<'a> Parser<'a> {
Token::PGSquareRoot => UnaryOperator::PGSquareRoot,
Token::PGCubeRoot => UnaryOperator::PGCubeRoot,
Token::AtSign => UnaryOperator::PGAbs,
Token::Tilde => UnaryOperator::PGBitwiseNot,
_ => unreachable!(),
};
Ok(Expr::UnaryOp {
@ -1651,6 +1649,10 @@ impl<'a> Parser<'a> {
),
})
}
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

View file

@ -17613,3 +17613,22 @@ fn test_parse_alter_user() {
}
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]
);
}
}

View file

@ -2144,13 +2144,11 @@ fn parse_ampersand_arobase() {
#[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!(