feat: ADR-0036 Phase 1 — validate advanced-mode INSERT literals + show the value
Capture literal VALUES at parse onto Command::SqlInsert (no grammar change, no reparse); validate them against column types before the still-verbatim insert (reusing impl_value_for for DSL-parity wording); read them in the error enricher so a constraint error names the real value. Execution, auto-fill, and command identity unchanged. Adds run_sql_insert_with_literals (runtime path); run_sql_insert stays the no-capture raw entry. Proven: malformed date 2025/01/15 now refused in advanced-mode SQL; replayed UNIQUE shows the real value. Tests +3 (expression runs, multi-row, natural order) + 2 flipped/strengthened. 1930 pass / 0 fail / 0 skip; clippy clean.
This commit is contained in:
+23
-1
@@ -1570,6 +1570,19 @@ fn user_value_for_column(command: &Command, column: &str) -> Option<crate::dsl::
|
||||
.iter()
|
||||
.find(|(c, _)| c == column)
|
||||
.map(|(_, v)| v.clone()),
|
||||
// ADR-0036 Phase 1: a single-row literal SQL INSERT retains its
|
||||
// captured literals, so a constraint error can name the real
|
||||
// value. Explicit column list only here (natural order needs the
|
||||
// schema); multi-row is skipped (which row conflicted is
|
||||
// ambiguous) — both degrade to the neutral "that value".
|
||||
Command::SqlInsert {
|
||||
listed_columns,
|
||||
literal_rows,
|
||||
..
|
||||
} if literal_rows.len() == 1 && !listed_columns.is_empty() => {
|
||||
let idx = listed_columns.iter().position(|c| c == column)?;
|
||||
literal_rows[0].get(idx).cloned().flatten()
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -2236,8 +2249,17 @@ async fn execute_command_typed(
|
||||
listed_columns,
|
||||
row_source,
|
||||
returning,
|
||||
literal_rows,
|
||||
} => database
|
||||
.run_sql_insert(sql, src, target_table, listed_columns, row_source, returning)
|
||||
.run_sql_insert_with_literals(
|
||||
sql,
|
||||
src,
|
||||
target_table,
|
||||
listed_columns,
|
||||
row_source,
|
||||
returning,
|
||||
literal_rows,
|
||||
)
|
||||
.await
|
||||
.map(CommandOutcome::Insert),
|
||||
// A SQL `UPDATE` (advanced mode; ADR-0033 §2). Grammar-as-
|
||||
|
||||
Reference in New Issue
Block a user