feat: ADR-0036 Phase 3b — live typed-slot hints + highlighting for INSERT VALUES
Give each positional INSERT VALUES position its column identity so a lone
literal gets the column-typed slot (live per-column hint + mismatch
highlight) and any expression falls through to sql_expr — completing the
typed-DML-values feature for the INSERT surface (single/multi-row, Form A
and Form B).
New zero-width Node::SetColumn(&TableColumn) primitive establishes the
active column for the value position that follows (sets current_column +
pending_value_column, like an Ident{writes_column} but without consuming
input); a DynamicSubgrammar emits SetColumn(col) + the shared SET_VALUE
per position. Column mapping mirrors do_sql_insert: Form A → listed
columns; Form B → all columns in declaration order (advanced-mode Form B
auto-fills nothing; an omitted shortid in Form A is auto-filled and has no
VALUES position).
Reconcile with the per-tuple arity diagnostic (ADR-0033 §8.1): a
fixed-length typed Seq would reject wrong-arity tuples and suppress that
post-walk diagnostic, so the tuple value list is an arity-gating lookahead
— a correct-arity tuple uses the typed Seq; a wrong-arity tuple keeps the
type-blind sql_expr repeat so §8.1 fires unchanged. Correct-arity tuples
get full live feedback, including a wrong-kind literal like 'text' into an
int column.
Records ADR-0036 Amendment 1 (Phase 3b detail + the arity reconciliation);
ADR-0036 is now fully implemented.
Tests: 1947 passing (+8), 0 failed, 0 skipped, 1 ignored; clippy clean.
This commit is contained in:
@@ -375,6 +375,25 @@ pub enum Node {
|
||||
/// type-awareness). Not memoized: the output depends on the
|
||||
/// source, not just `ctx`.
|
||||
Lookahead(fn(&WalkContext, &str, usize) -> Self),
|
||||
/// Zero-width node that *establishes the active column* for the
|
||||
/// value slot that follows it (ADR-0036 Phase 3b). Matches the
|
||||
/// empty string and, as a side effect, sets
|
||||
/// `WalkContext::current_column` to the referenced column and
|
||||
/// `pending_value_column` to its name — exactly as an
|
||||
/// `Ident { writes_column: true }` does, but without consuming a
|
||||
/// column identifier from the input.
|
||||
///
|
||||
/// This is the primitive that gives `INSERT … VALUES (…)`
|
||||
/// positions a per-position column identity: the positions are
|
||||
/// positional (no per-position column ident to write
|
||||
/// `current_column`), so a `DynamicSubgrammar` factory
|
||||
/// (`sql_insert::sql_value_list`) emits `SetColumn(colᵢ)` before
|
||||
/// each value position, then the shared boundary-aware `SET_VALUE`
|
||||
/// slot routes a lone literal to that column's typed slot and any
|
||||
/// expression to `sql_expr`. The referenced `TableColumn` is
|
||||
/// leaked by the factory (bounded by the column count, like the
|
||||
/// `DynamicSubgrammar` `Box::leak`).
|
||||
SetColumn(&'static crate::completion::TableColumn),
|
||||
/// Typed value-literal slot (ADR-0024 §Phase D §typed-value-slots).
|
||||
///
|
||||
/// Walks `inner` to consume the literal but records the
|
||||
|
||||
Reference in New Issue
Block a user