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:
@@ -17,7 +17,7 @@
|
||||
//! later. The worker never inspects the WHERE clause (Amendment 2),
|
||||
//! so no predicate-byte extraction is needed.
|
||||
|
||||
use crate::dsl::grammar::sql_select::{WHERE_CLAUSE, reject_internal_table};
|
||||
use crate::dsl::grammar::sql_select::{RETURNING_CLAUSE, WHERE_CLAUSE, reject_internal_table};
|
||||
use crate::dsl::grammar::{IdentSource, Node, Word};
|
||||
|
||||
/// The `DELETE` target table. `__rdbms_*` rejected (ADR-0030 §6 /
|
||||
@@ -48,6 +48,7 @@ static SQL_DELETE_TAIL_NODES: &[Node] = &[
|
||||
Node::Word(Word::keyword("from")),
|
||||
TARGET_TABLE,
|
||||
Node::Optional(&WHERE_CLAUSE),
|
||||
Node::Optional(&RETURNING_CLAUSE),
|
||||
Node::Optional(&Node::Punct(';')),
|
||||
];
|
||||
|
||||
@@ -123,6 +124,14 @@ mod tests {
|
||||
good("from orders where customer_id in (select id from customers where country = 'DE')");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returning_tail_admitted() {
|
||||
// 3g: optional RETURNING projection_list tail.
|
||||
good("from orders where id = 1 returning *");
|
||||
good("from orders returning id, total");
|
||||
good("from orders where id = 1 returning id as gone;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_target_table_rejected() {
|
||||
bad("from __rdbms_playground_columns");
|
||||
|
||||
Reference in New Issue
Block a user