Skip to content

Commit

Permalink
feat: Support PostgreSQL exponentiation. (#813)
Browse files Browse the repository at this point in the history
* Add Postgres exponent operator

* Parse caret as BinaryOperator::PGExp in PostgreSQL

* Update sqlparser_postgres.rs

* update tests to support PGExp

* cargo fmt

* improve extensibility

* cargo fmt

* redundant code and documentation lionks
  • Loading branch information
michael-2956 authored Mar 2, 2023
1 parent fbbf1a4 commit 1cf913e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/ast/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub enum BinaryOperator {
PGBitwiseXor,
PGBitwiseShiftLeft,
PGBitwiseShiftRight,
PGExp,
PGRegexMatch,
PGRegexIMatch,
PGRegexNotMatch,
Expand Down Expand Up @@ -124,6 +125,7 @@ impl fmt::Display for BinaryOperator {
BinaryOperator::PGBitwiseXor => f.write_str("#"),
BinaryOperator::PGBitwiseShiftLeft => f.write_str("<<"),
BinaryOperator::PGBitwiseShiftRight => f.write_str(">>"),
BinaryOperator::PGExp => f.write_str("^"),
BinaryOperator::PGRegexMatch => f.write_str("~"),
BinaryOperator::PGRegexIMatch => f.write_str("~*"),
BinaryOperator::PGRegexNotMatch => f.write_str("!~"),
Expand Down
10 changes: 9 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,15 @@ impl<'a> Parser<'a> {
Token::Mod => Some(BinaryOperator::Modulo),
Token::StringConcat => Some(BinaryOperator::StringConcat),
Token::Pipe => Some(BinaryOperator::BitwiseOr),
Token::Caret => Some(BinaryOperator::BitwiseXor),
Token::Caret => {
// In PostgreSQL, ^ stands for the exponentiation operation,
// and # stands for XOR. See https://www.postgresql.org/docs/current/functions-math.html
if dialect_of!(self is PostgreSqlDialect) {
Some(BinaryOperator::PGExp)
} else {
Some(BinaryOperator::BitwiseXor)
}
}
Token::Ampersand => Some(BinaryOperator::BitwiseAnd),
Token::Div => Some(BinaryOperator::Divide),
Token::ShiftLeft if dialect_of!(self is PostgreSqlDialect | GenericDialect) => {
Expand Down
21 changes: 16 additions & 5 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1228,16 +1228,27 @@ fn parse_string_agg() {
);
}

/// selects all dialects but PostgreSQL
pub fn all_dialects_but_pg() -> TestedDialects {
TestedDialects {
dialects: all_dialects()
.dialects
.into_iter()
.filter(|x| !x.is::<PostgreSqlDialect>())
.collect(),
}
}

#[test]
fn parse_bitwise_ops() {
let bitwise_ops = &[
("^", BinaryOperator::BitwiseXor),
("|", BinaryOperator::BitwiseOr),
("&", BinaryOperator::BitwiseAnd),
("^", BinaryOperator::BitwiseXor, all_dialects_but_pg()),
("|", BinaryOperator::BitwiseOr, all_dialects()),
("&", BinaryOperator::BitwiseAnd, all_dialects()),
];

for (str_op, op) in bitwise_ops {
let select = verified_only_select(&format!("SELECT a {} b", &str_op));
for (str_op, op, dialects) in bitwise_ops {
let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op));
assert_eq!(
SelectItem::UnnamedExpr(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident::new("a"))),
Expand Down
9 changes: 5 additions & 4 deletions tests/sqlparser_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1322,15 +1322,16 @@ fn parse_pg_returning() {
}

#[test]
fn parse_pg_bitwise_binary_ops() {
let bitwise_ops = &[
// Sharp char cannot be used with Generic Dialect, it conflicts with identifiers
fn parse_pg_binary_ops() {
let binary_ops = &[
// Sharp char and Caret cannot be used with Generic Dialect, it conflicts with identifiers
("#", BinaryOperator::PGBitwiseXor, pg()),
("^", BinaryOperator::PGExp, pg()),
(">>", BinaryOperator::PGBitwiseShiftRight, pg_and_generic()),
("<<", BinaryOperator::PGBitwiseShiftLeft, pg_and_generic()),
];

for (str_op, op, dialects) in bitwise_ops {
for (str_op, op, dialects) in binary_ops {
let select = dialects.verified_only_select(&format!("SELECT a {} b", &str_op));
assert_eq!(
SelectItem::UnnamedExpr(Expr::BinaryOp {
Expand Down

0 comments on commit 1cf913e

Please sign in to comment.