zvonimir-dd commented on issue #2461:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/issues/2461#issuecomment-5480782388

   I started on the one-line fix proposed above and hit a complication worth 
settling before there's a PR to review: `&` sits in a ladder, so moving it 
changes its relation to every neighbour, not just to `->`. Two other groupings 
flip, and one of them contradicts real MySQL and BigQuery. That turns this into 
a question about what the default table is *for*, which seems like a maintainer 
call rather than something to decide inside a PR.
   
   ### What actually moves
   
   The relevant slice of `Dialect::prec_value` (`src/dialect/mod.rs`), tightest 
first. Note that `Precedence::Caret` covers `<<` and `>>` as well as `^` and 
`#`:
   
   | Precedence | Value | Tokens |
   |---|---|---|
   | `PlusMinus` | 30 | `+` `-` |
   | `Xor` | 24 | `XOR` keyword |
   | `Ampersand` | 23 → **21** | `&` |
   | `Caret` | 22 | `^` `#` `<<` `>>` |
   | `Pipe` / `Colon` / `PgOther` | 21 | `\|`, `:`, `->` `->>` `@>` 
`OPERATOR(…)` |
   | `Between` / `Eq` | 20 | `=` `<` `>` … |
   
   With `Ampersand => 21`, three groupings change:
   
   | Expression | Before | After | Relation that moved |
   |---|---|---|---|
   | `t.a -> 'k' & b` | `t.a -> ('k' & b)` | `(t.a -> 'k') & b` | the reported 
bug — `23 > 21` becomes a tie |
   | `a \| b & c` | `a \| (b & c)` | `(a \| b) & c` | `&` no longer outranks 
`\|` |
   | `a & b ^ c` | `(a & b) ^ c` | `a & (b ^ c)` | `Caret` (22) now outranks 
`&` (21) |
   
   ### How that lands against the engines
   
   - **PostgreSQL** — `&`, `|`, `<<`, `>>` and `->` are a single 
left-associative row in `gram.y` (`%left Op OPERATOR RIGHT_ARROW '|'`), so rows 
1 and 2 become PG-correct. `PostgreSqlDialect` overrides `prec_value` and is 
unaffected either way; the argument here is only that the default table 
describes itself as approximating PG, and `postgresql.rs` shows what that row 
is meant to look like.
   - **MySQL** — the documented order is `^` > `*` `/` `DIV` `%` > `+` `-` > 
`<<` `>>` > `&` > `|`. Row 3 becomes *correct* for MySQL, an improvement. Row 2 
becomes *wrong*: MySQL reads `a | b & c` as `a | (b & c)`.
   - **BigQuery** — C-style `&` > `^` > `|`, which is exactly what the table 
has today. This is the one dialect where both rows 2 and 3 are pure regressions.
   - **SQLite** — `& | << >>` are one level, so row 2 gets closer and row 3 
stays wrong in the opposite direction. SQLite also puts `->`/`->>` *above* `*` 
and `/`, so row 1 is not right for SQLite before or after.
   - **T-SQL** — `+ - & ^ |` are all one level, so rows 2 and 3 are 
approximations either way.
   
   Two things bound the blast radius:
   
   - `Display` for `Expr::BinaryOp` emits no parentheses, so a regrouped tree 
still round-trips to byte-identical SQL. Only AST consumers can observe any of 
this — which is also why no `verified_stmt` test caught the original divergence.
   - The full test suite passes with `Ampersand => 21` applied, so nothing 
in-tree currently pins any of the three groupings.
   
   I also tried the other direction — tying `PgOther` up to 23 to meet `&` 
rather than moving `&` down. It fixes row 1, but breaks the `|`/`->` tie that 
is currently PG-correct and shifts `->` against `^`/`<<`/`>>`, so it trades one 
divergence for two. I don't think a zero-collateral variant exists.
   
   ### The question
   
   1. **`Ampersand => 21` alone** — accept the `&`/`|` tie and the `&`/`^` 
reversal as the price of matching the table's stated PostgreSQL basis. One line 
plus tests.
   2. **`Ampersand => 21` plus `prec_value` overrides on `MySqlDialect` and 
`BigQueryDialect`** that keep `& > ^ > |` (and, for MySQL, `<<`/`>>` above 
`&`). Nothing regresses, but it touches three precedence tables and reopens 
MySQL's ladder more broadly — `XOR` is currently at 24, where MySQL puts it 
between `AND` and `OR`, and `<<`/`>>` are fused with `Caret`.
   3. **Close this as intended behaviour** — treat the bitwise block as 
deliberately C-style and accept that `->` binds looser than `&` outside 
PostgreSQL.
   
   Happy to implement whichever you prefer. Worth noting that the `->`-vs-`&` 
case only bites in dialects that use `->` as an operator, which overlaps with 
#2462 (MySQL `->`/`->>` binding looser than all arithmetic), so it may be 
easier to settle the two together.
   


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