grammar+db: 3f — SQL DELETE + cascade summary (ADR-0033 §1/§7)
New src/dsl/grammar/sql_delete.rs (FROM <table> [WHERE] [;]), Command::SqlDelete, Request::RunSqlDelete, do_sql_delete worker. do_sql_delete mirrors the DSL do_delete: detect FK cascade by before/after child row-count diffing, re-persist target + every cascade-affected child, history-on-success inside the tx. Reuses CommandOutcome::Delete -> handle_dsl_delete_success, so the per-relationship cascade summary formatter is shared, not duplicated. ADR-0033 Amendment 2: supersedes §7's WHERE-injected pre-count. Its premise (DSL handler builds pre-counts from the typed Expr) was wrong — do_delete uses count-diff. The pre-count would also have broken the §2 parity promise by reporting SET NULL the DSL path doesn't. Count- diff gives exact parity, no WHERE-byte extraction, and withdraws R2. SET NULL reporting deferred for both paths (user-confirmed). Tests: +6 grammar unit, +12 integration (cascade parity with DSL, both R2 subquery cases, before-execute order, no-WHERE, FK-rejection rollback, childless-parent, two-child cascade). 1542 pass / 0 fail / 1 ignored. Clippy clean. Dev sql_delete entry word removed in 3j.
This commit is contained in:
+15
-1
@@ -320,6 +320,18 @@ pub enum Command {
|
||||
sql: String,
|
||||
target_table: String,
|
||||
},
|
||||
/// A SQL `DELETE` validated by the walker (ADR-0033 §1/§7,
|
||||
/// advanced mode). Grammar-as-text: the worker executes `sql`,
|
||||
/// observes any FK cascade by row-count diffing (Amendment 2 —
|
||||
/// the same mechanism the DSL `do_delete` uses), and re-persists
|
||||
/// `target_table`'s CSV plus every cascade-affected child
|
||||
/// (ADR-0030 §11). The worker never inspects the WHERE clause, so
|
||||
/// no predicate is carried here. `RETURNING` (3g) is added by the
|
||||
/// sub-phase that reads it.
|
||||
SqlDelete {
|
||||
sql: String,
|
||||
target_table: String,
|
||||
},
|
||||
/// App-lifecycle command (per ADR-0003). These work in both
|
||||
/// simple and advanced modes; the dispatcher branches on the
|
||||
/// `Command::App(...)` variant before mode-specific routing.
|
||||
@@ -617,6 +629,7 @@ impl Command {
|
||||
Self::Select { .. } => "select",
|
||||
Self::SqlInsert { .. } => "insert into",
|
||||
Self::SqlUpdate { .. } => "update",
|
||||
Self::SqlDelete { .. } => "delete from",
|
||||
Self::App(app) => match app {
|
||||
AppCommand::Quit => "quit",
|
||||
AppCommand::Help => "help",
|
||||
@@ -687,7 +700,8 @@ impl Command {
|
||||
// A SQL `INSERT` carries its parsed target table (for
|
||||
// CSV re-persistence and ok-summary subject).
|
||||
Self::SqlInsert { target_table, .. }
|
||||
| Self::SqlUpdate { target_table, .. } => target_table,
|
||||
| Self::SqlUpdate { target_table, .. }
|
||||
| Self::SqlDelete { target_table, .. } => target_table,
|
||||
// App commands aren't tied to schema entities — the
|
||||
// verb is the most identifying thing. The
|
||||
// display_subject override below provides a richer
|
||||
|
||||
Reference in New Issue
Block a user