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:
+10
-1
@@ -1583,6 +1583,14 @@ fn user_value_for_column(command: &Command, column: &str) -> Option<crate::dsl::
|
||||
let idx = listed_columns.iter().position(|c| c == column)?;
|
||||
literal_rows[0].get(idx).cloned().flatten()
|
||||
}
|
||||
// ADR-0036 Phase 2: a SQL UPDATE retains its captured `SET`
|
||||
// literals, so a constraint error can name the real value.
|
||||
// Assignments are explicitly named, so (unlike SqlInsert) there is
|
||||
// no positional/multi-row ambiguity — mirror the DSL `Update` case.
|
||||
Command::SqlUpdate { set_literals, .. } => set_literals
|
||||
.iter()
|
||||
.find(|(c, _)| c == column)
|
||||
.and_then(|(_, v)| v.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -2270,8 +2278,9 @@ async fn execute_command_typed(
|
||||
sql,
|
||||
target_table,
|
||||
returning,
|
||||
set_literals,
|
||||
} => database
|
||||
.run_sql_update(sql, src, target_table, returning)
|
||||
.run_sql_update_with_literals(sql, src, target_table, returning, set_literals)
|
||||
.await
|
||||
.map(CommandOutcome::Update),
|
||||
// A SQL `DELETE` (advanced mode; ADR-0033 §1/§7). Grammar-
|
||||
|
||||
Reference in New Issue
Block a user