zvonimir-dd opened a new issue, #2461:
URL: https://github.com/apache/datafusion-sqlparser-rs/issues/2461

   `&` and `->` have the same precedence in PostgreSQL but not in the default 
precedence table, so the
   same expression produces two different trees depending on dialect:
   
   | SQL | `PostgreSqlDialect` | `MySqlDialect` / `GenericDialect` |
   |---|---|---|
   | `a -> b & c` | `((a -> b) & c)` | `(a -> (b & c))` |
   | `a -> b \| c` | `((a -> b) \| c)` | `((a -> b) \| c)` |
   | `a -> b ^ c` | `(a -> (b ^ c))` | `(a -> (b ^ c))` |
   | `a -> b + c` | `(a -> (b + c))` | `(a -> (b + c))` |
   
   `&` is the only row that disagrees.
   
   ### Cause
   
   The default table in `src/dialect/mod.rs` has:
   
   ```rust
   Precedence::Ampersand => 23,
   Precedence::Caret => 22,
   Precedence::Pipe => 21,
   Precedence::Colon => 21,
   Precedence::PgOther => 21,
   ```
   
   `PostgreSqlDialect::prec_value` instead maps `Ampersand`, `Pipe`, `Colon` 
and `PgOther` all to
   `PG_OTHER_PREC` (`src/dialect/postgresql.rs:176-184`), which matches 
`gram.y`, where `&` is just a
   generic `Op` and shares one left-associative level with `->`:
   
   ```
   %left  Op OPERATOR RIGHT_ARROW '|'
   ```
   
   So `Pipe` already agrees with `PgOther` in the default table (both 21), and 
`Caret` is legitimately
   above it, but `Ampersand` at 23 is left as the sole outlier.
   
   ### Candidate fix
   
   ```diff
   -            Precedence::Ampersand => 23,
   +            Precedence::Ampersand => 21,
   ```
   
   The full suite passes unchanged with that applied, so no existing test pins 
the current grouping —
   which is also why this went unnoticed. `Display` for `Expr::BinaryOp` emits 
no parentheses, so a
   mis-grouped tree round-trips to the original SQL and `verified_expr` / 
`verified_stmt` cannot catch
   it; a test would have to assert on the tree.
   
   ### Open question, possibly a separate issue
   
   For MySQL the fix above is necessary but not sufficient. MySQL's `->` / 
`->>` take a quoted JSON path
   on the right-hand side, so there is nothing for MySQL to resolve — 
`col->'$.a' + 1` can only mean
   `(col->'$.a') + 1`. sqlparser parses that right operand as a full expression 
at `PgOther`, giving
   `col -> ('$.a' + 1)`, so `->` under-binds in MySQL against `+`, `*`, `^` and 
friends, not just `&`.
   Making that correct probably means a MySQL-specific precedence for the arrow 
operators rather than
   another adjustment to the shared row, so I've kept it out of scope here — 
happy to split it out if
   a maintainer would prefer it tracked separately.
   
   Surfaced while working on #2436. Related: #2460.
   


-- 
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