apache / apache/datafusion-sqlparser-rs

MySQL `->` / `->>` bind too loosely against arithmetic and bitwise operators

Offen
#2,462 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
Rust
Sterne
3.5k
Forks
772
Ø Merge
4 T. 9 Std.
Gemergte PRs (30 T.)
17

Beschreibung

Split out of #2461, where this was raised as an open question.

MySQL's `->` / `->>` bind more tightly than every arithmetic, shift and bitwise operator: the
right-hand side is a quoted JSON path, and `col->path` is defined as equivalent to
`JSON_EXTRACT(col, path)`
([docs](https://dev.mysql.com/doc/refman/8.4/en/json-search-functions.html)). sqlparser gives the
arrow operators `Precedence::PgOther` (21), which sits *below* `+` / `-` / `*`, so the arrow
under-binds on both sides:

| SQL | sqlparser (`MySqlDialect`, `GenericDialect`) | MySQL |
|---|---|---|
| `c -> '$.a' + 1` | `c -> ('$.a' + 1)` | `(c -> '$.a') + 1` |
| `c ->> '$.a' + 1` | `c ->> ('$.a' + 1)` | `(c ->> '$.a') + 1` |
| `c -> '$.a' * 2` | `c -> ('$.a' * 2)` | `(c -> '$.a') * 2` |
| `1 + c -> '$.a'` | `(1 + c) -> '$.a'` | `1 + (c -> '$.a')` |

Comparisons are already correct, since `Eq` (20) is below `PgOther` (21):
`c -> '$.a' = 1` → `((c -> '$.a') = 1)`.

As in the sibling issues, `Display` for `Expr::BinaryOp` emits no parentheses, so a mis-grouped tree
round-trips to the original SQL — `verified_expr` / `verified_stmt` cannot catch this, only a test
asserting on the tree can.

### Why this is not a fix to the shared row

`PgOther` = 21 is *correct* for PostgreSQL. In `gram.y` the arrow shares one left-associative level
with `|` and generic operators, below `+` / `-`:

```
%left Op OPERATOR RIGHT_ARROW '|'
```

and `PostgreSqlDialect` behaves accordingly today (`a -> b + c` → `a -> (b + c)`). So the two engines
genuinely disagree about where the arrow sits, and a single shared precedence row cannot be right for
both.

### Possible approaches

1. Add a dedicated `Precedence` variant for the arrow operators, defaulting to the current
`PgOther` value so PostgreSQL and every other dialect are unchanged, and have `MySqlDialect` place
it above `MulDivModOp`. This is the narrowest option.
2. Give `MySqlDialect` its own `prec_value` the way `PostgreSqlDialect` has one. That duplicates the
whole table, and would also move `@>`, `<@` and `CustomBinaryOperator`, which is probably not
intended.

I'd lean towards (1), but I don't want to presume — happy to implement whichever a maintainer
prefers.

Two open questions for whoever picks this up:

- Should `GenericDialect` follow MySQL here? It currently produces the same grouping as MySQL, but
Generic is a permissive superset, so this seems like a judgment call rather than a clear bug.
- How high should the MySQL arrow sit exactly? Since the right operand is lexically a path string in
real MySQL, anything above `MulDivModOp` gives correct results for valid input; placing it near
`DoubleColon` would match the grammar most literally.

No existing test pins the current grouping — the only MySQL arrow trees asserted are single-operator
ones inside a `CAST` (`tests/sqlparser_mysql.rs:879-910`).

Related: #2436, #2460, #2461.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Rechercherichtung

Beginnen Sie mit dem Lesen der Precedence definition und der Precedence-Behandlung von MySqlDialect und vergleichen Sie anschließend PostgreSqlDialect::prec_value mit den vorhandenen Assertions in tests/sqlparser_mysql.rs:879-910. Die Arbeit ist abgeschlossen, wenn MySQL-Pfeilausdrücke über arithmetischen und bitweisen Operatoren gruppiert werden, das PostgreSQL-Verhalten unverändert bleibt und Tests auf Tree-Ebene beide Seiten des Operators abdecken.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
mysql, rust, sql
Bereich
compilers, databases
Issue-Typ
Bug
Schwierigkeit
4/5
Geschätzter Aufwand
3-5 Tage
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
48/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.