kumarUjjawal opened a new issue, #2819:
URL: https://github.com/apache/datafusion-sqlparser-rs/issues/2819

   ## Problem
   
   In `PostgreSqlDialect`, a unary minus binds more loosely than `^`. The 
parser reads `-1 ^ 0` as `-(1 ^ 0)`.
   
   In PostgreSQL, unary minus binds more tightly than `^` ([operator precedence 
table](https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-PRECEDENCE)).
 PostgreSQL reads `-1 ^ 0` as `(-1) ^ 0`.
   
   ## Reproduction
   
   At `main` (`d1c1790e3`):
   
   ```rust
   use sqlparser::dialect::PostgreSqlDialect;
   use sqlparser::parser::Parser;
   
   let ast = Parser::parse_sql(&PostgreSqlDialect {}, "SELECT -1 ^ 0").unwrap();
   println!("{ast:#?}");
   ```
   
   The projection expression is (spans removed):
   
   ```text
   UnaryOp {
       op: Minus,
       expr: BinaryOp {
           left: Value(Number("1", false)),
           op: PGExp,
           right: Value(Number("0", false)),
       },
   }
   ```
   
   The expected expression is:
   
   ```text
   BinaryOp {
       left: UnaryOp { op: Minus, expr: Value(Number("1", false)) },
       op: PGExp,
       right: Value(Number("0", false)),
   }
   ```
   
   `SELECT -2 ^ 2` and `SELECT +2 ^ 2` parse the same way.
   
   ## Effect on query results
   
   The grouping changes the result:
   
   | Query | PostgreSQL 17 | DuckDB | DataFusion (PostgreSQL dialect) |
   |---|---|---|---|
   | `SELECT -1 ^ 0` | 1 | 1 | -1 |
   | `SELECT -2 ^ 2` | 4 | 4 | -4 |
   
   DataFusion tracks this in apache/datafusion#27094.
   
   ## Cause
   
   `parse_prefix_inner` parses the operand of a unary `-` or `+` at 
`Precedence::MulDivModOp` 
([src/parser/mod.rs#L1967-L1979](https://github.com/apache/datafusion-sqlparser-rs/blob/d1c1790e3b80dbc325d94072bb5fc0670aef0d08/src/parser/mod.rs#L1967-L1979)):
   
   ```rust
   tok @ Token::Minus | tok @ Token::Plus => {
       // ...
       Ok(Expr::UnaryOp {
           op,
           expr: Box::new(
               
self.parse_subexpr(self.dialect.prec_value(Precedence::MulDivModOp))?,
           ),
       })
   }
   ```
   
   `PostgreSqlDialect` sets `CARET_PREC` (100) above `MUL_DIV_MOD_OP_PREC` (90) 
([src/dialect/postgresql.rs#L213-L214](https://github.com/apache/datafusion-sqlparser-rs/blob/d1c1790e3b80dbc325d94072bb5fc0670aef0d08/src/dialect/postgresql.rs#L213-L214)).
 So the operand of the minus also takes the `^` that follows.
   
   For the PostgreSQL dialect, the operand of a unary `-` or `+` must be parsed 
at a precedence above `CARET_PREC`. In the PostgreSQL table, unary `+` and `-` 
are also above `COLLATE` and `AT`.
   
   The generic dialect is not affected in this way: there, `Caret` is below 
`MulDivModOp`.
   
   Related: #814 (precedence of `~`).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to