grammar+db: 3g — RETURNING on INSERT/UPDATE/DELETE (ADR-0033 §5)
Shared RETURNING_CLAUSE (reuses Phase-2 PROJECTION_LIST, now pub(crate)) as an optional tail on all three SQL DML shapes. `returning: bool` on the Command variants, set by the ast-builders and threaded to the worker. run_returning collects the returned rows as a DataResult (RETURNING mutates + yields in one pass), reusing resolve_select_column_types for bare-column type recovery; computed projections stay typeless. DeleteResult gains a `data` field rendered alongside the cascade summary. Follow-set fix: `returning` is added to the table-source and projection bare-alias follow-sets so an INSERT … SELECT row source stops before RETURNING instead of reading it as a table alias. Auto-fill × RETURNING: build_sql_insert stops row_source before the RETURNING token (keeping it preparable for shortid materialisation), and plan_shortid_autofill re-appends the RETURNING tail so generated shortids surface in RETURNING *. Tests (+17): grammar accept on all three; INSERT/UPDATE/DELETE RETURNING incl. *, aliases, multi-row, type recovery + computed- typeless; auto-fill × RETURNING (single + multi-row distinct ids); INSERT…SELECT…RETURNING execution; UPDATE…RETURNING zero-match; DELETE…RETURNING cascade+rows; app-level render of both. Dev sql_insert/sql_update/sql_delete entry words still removed in 3j. 1562 pass / 0 fail / 1 ignored. Clippy clean.
This commit is contained in:
+14
-5
@@ -1890,16 +1890,21 @@ async fn execute_command_typed(
|
||||
target_table,
|
||||
listed_columns,
|
||||
row_source,
|
||||
returning,
|
||||
} => database
|
||||
.run_sql_insert(sql, src, target_table, listed_columns, row_source)
|
||||
.run_sql_insert(sql, src, target_table, listed_columns, row_source, returning)
|
||||
.await
|
||||
.map(CommandOutcome::Insert),
|
||||
// A SQL `UPDATE` (advanced mode; ADR-0033 §2). Grammar-as-
|
||||
// text: the worker runs the validated `sql` and re-persists
|
||||
// the parsed `target_table`'s CSV. Reuses the DSL update
|
||||
// outcome (affected-row count).
|
||||
Command::SqlUpdate { sql, target_table } => database
|
||||
.run_sql_update(sql, src, target_table)
|
||||
Command::SqlUpdate {
|
||||
sql,
|
||||
target_table,
|
||||
returning,
|
||||
} => database
|
||||
.run_sql_update(sql, src, target_table, returning)
|
||||
.await
|
||||
.map(CommandOutcome::Update),
|
||||
// A SQL `DELETE` (advanced mode; ADR-0033 §1/§7). Grammar-
|
||||
@@ -1908,8 +1913,12 @@ async fn execute_command_typed(
|
||||
// plus every cascade-affected child. Reuses the DSL delete
|
||||
// outcome (affected-row count + per-relationship cascade
|
||||
// summary).
|
||||
Command::SqlDelete { sql, target_table } => database
|
||||
.run_sql_delete(sql, src, target_table)
|
||||
Command::SqlDelete {
|
||||
sql,
|
||||
target_table,
|
||||
returning,
|
||||
} => database
|
||||
.run_sql_delete(sql, src, target_table, returning)
|
||||
.await
|
||||
.map(CommandOutcome::Delete),
|
||||
// `EXPLAIN QUERY PLAN` never executes the wrapped
|
||||
|
||||
Reference in New Issue
Block a user