feat: ADR-0036 Phase 2 — validate advanced-mode UPDATE SET literals + retain the value
Mirror Phase 1's capture-at-parse technique on the UPDATE SET assignment list. build_sql_update calls the new capture_set_literals (data.rs), which walks the matched tokens (no reparse, no grammar change) and classifies each top-level `SET col = <rhs>` as a literal (Some, incl. signed numbers) or an expression (None), using paren depth so a comma inside a function call or a `where` inside a scalar subquery is not mistaken for a boundary, and the trailing top-level WHERE is excluded. Command::SqlUpdate gains set_literals; do_sql_update validates the literals against their column types via the shared impl_value_for before the still verbatim update; user_value_for_column reads them so a constraint error names the offending value. WHERE stays unvalidated; execution and command identity are unchanged. Also corrects the stale data.rs header comment (DSL typed slots are wired, not "deferred") and flips ADR-0036 + README to Phases 1–2 implemented. Tests: 1934 passing (+4), 0 failed, 0 skipped, 1 ignored; clippy clean.
This commit is contained in:
@@ -11,8 +11,13 @@ consolidating the two modes and a concrete auto-fill difference confirmed
|
||||
that even the single-row literal case is **not** identical across modes).
|
||||
**Phase 1 implemented 2026-05-26** (`INSERT … VALUES` literal validation +
|
||||
offending-value retention; capture-at-parse, no grammar change, execution
|
||||
unchanged). Phases 2 (`UPDATE … SET` literals) and 3 (completion
|
||||
hinting/highlighting) pending.
|
||||
unchanged). **Phase 2 implemented 2026-05-26** (`UPDATE … SET` literal
|
||||
validation + offending-value retention; the same capture-at-parse technique
|
||||
on the SET assignment list — `capture_set_literals` in `data.rs` —
|
||||
classifying each top-level RHS literal-vs-expression, validating literals in
|
||||
`do_sql_update`, and reading them in `user_value_for_column`; `WHERE` is not
|
||||
validated, execution stays verbatim). Phase 3 (completion
|
||||
hinting/highlighting — the only part needing a grammar change) pending.
|
||||
|
||||
**Augments** **ADR-0030 §4** and **ADR-0033 §10** — it does **not**
|
||||
supersede them and does **not** change the execution model. Advanced-mode
|
||||
@@ -246,8 +251,19 @@ execution), only its `Result` is used.
|
||||
the verbatim insert; the enricher reads them. Covers single- and
|
||||
multi-row, with or without `RETURNING`/`ON CONFLICT`, because execution
|
||||
is untouched.
|
||||
- **Phase 2 — `UPDATE … SET` literal validation** (same technique on the
|
||||
SET assignment list).
|
||||
- **Phase 2 (implemented 2026-05-26) — `UPDATE … SET` literal
|
||||
validation.** The same capture-at-parse technique on the SET assignment
|
||||
list: `build_sql_update` calls `capture_set_literals`, which walks the
|
||||
matched tokens (no reparse) and classifies each *top-level* `SET col =
|
||||
<rhs>` into `(col, Some(Value))` for a bare literal (incl. a signed
|
||||
number) or `(col, None)` for an expression — using paren depth so a comma
|
||||
inside a function call or a `where` inside a scalar subquery is never
|
||||
mistaken for an assignment/clause boundary, and so the trailing top-level
|
||||
`WHERE` predicate is excluded. `Command::SqlUpdate` gains a
|
||||
`set_literals` payload; `do_sql_update` validates the literals against
|
||||
their column types (via the shared `impl_value_for`) before the still
|
||||
verbatim update; `user_value_for_column` reads them so a constraint error
|
||||
names the offending value. `WHERE` is deliberately not validated (§2).
|
||||
- **Phase 3 — completion hinting / highlighting.** This is the *only*
|
||||
part that needs a grammar change: a `Choice(typed-literal-slot,
|
||||
sql_expr)` at each value position (reusing the DSL's live
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user