555149da3c
Phase 3 of ADR-0030's SQL-surface roadmap. Status: Proposed. Statement shapes (§1): single- and multi-row INSERT, INSERT…SELECT (recursing through ADR-0032's SQL_SELECT_COMPOUND), UPDATE with SET assignment list, DELETE, all three optionally followed by RETURNING projection_list. Full UPSERT (ON CONFLICT … DO NOTHING / DO UPDATE with the SQLite/PostgreSQL `excluded` pseudo-table) on INSERT. Dispatch (§2): SQL-first / DSL-fallback in Advanced mode via Choice(SQL_shape, DSL_shape) per shared entry word. Requires a new walker capability — Node::Guard(fn), a zero-byte-consumption gating node — landed as the first sub-phase's work (R1 mitigation budgeted). Execution (§10): three typed Command variants (SqlInsert / SqlUpdate / SqlDelete) carrying target_table, listed_columns, and a returning: bool flag. Worker handlers know per-kind specialisations: shortid auto-fill (§6, parity with DSL), cascade summary (§7, WHERE byte-range injection into pre-count subqueries), DataResult routing on RETURNING (§5). Diagnostics (§8): three new keys (insert_arity_mismatch ERROR, auto_column_overridden WARNING, not_null_missing WARNING) with positive + negative test requirements. OOS list (§13): DEFAULT VALUES (seed feature), SQLite OR-prefixes, UPDATE FROM, WITH-prefixed DML, indexed-by hints, multi-statement batches. Implementation notes: eleven phased sub-phases (3a–3k) each with explicit exit gates + written DA gates. Ordering puts Node::Guard scaffolding (3a) FIRST so the dispatch mechanism is proven before DML grammar lands on top. Initial DA review (Initial DA review section) recorded seven critiques that were resolved before status moved to Proposed; a second-pass DA surfaced an eighth (Node::Guard wasn't an existing walker capability) and added it to §2 + sub-phase 3a's scope.
Architecture Decision Records
This directory contains the project's ADRs, recorded per ADR-0000.
Index
- ADR-0000 — Record architecture decisions
- ADR-0001 — Language and TUI framework
- ADR-0002 — Database engine
- ADR-0003 — Input modes and command dispatch
- ADR-0004 — Project file format
- ADR-0005 — Column type vocabulary
- ADR-0006 — Undo snapshots and replay log
- ADR-0007 — Sharing and export
- ADR-0008 — Testing approach
- ADR-0009 — DSL command syntax conventions
- ADR-0010 — Database access via a dedicated worker thread
- ADR-0011 — Foreign-key column type compatibility
- ADR-0012 — Internal metadata for user-facing column types
- ADR-0013 — Relationships, naming, and the rebuild-table strategy
- ADR-0014 — Data operations, value literals, and the auto-show pattern
- ADR-0015 — Project storage runtime
- ADR-0016 — Pretty table rendering for data and structure views
- ADR-0017 — Column type-change compatibility
- ADR-0018 — Auto-fill contracts for
serialandshortidcolumns - ADR-0019 — Friendly error layer (H1) and i18n message catalog
- ADR-0020 — Tokenization layer for the DSL parser
- ADR-0021 — Parser-as-source-of-truth for H1a (per-command usage in parse errors)
- ADR-0022 — Ambient typing assistance: colour, hint panel, completion (I3 + I4)
- ADR-0023 — Unified declarative grammar tree — direction (superseded for execution detail by ADR-0024)
- ADR-0024 — Unified grammar tree: execution plan — Accepted, the executable spec — implemented (Phases A–F; Phase F shipped "minimal",
parser.rsretained as the router — see the ADR's Phase F implementation note) - ADR-0025 — Indexes — Accepted,
add index/drop index, persistence, rebuild-table preservation, and items-list display (C3index portion +S2) - ADR-0026 — Complex WHERE expressions — Accepted, stratified recursive expression grammar (
AND/OR/NOT, comparisons,LIKE,IS NULL,IN,BETWEEN) forupdate/delete/show datafilters;show datagainswhere+limit; adds theSubgrammarnode and a recursiveExprAST (C5a) - ADR-0027 — Input-field validity indicator — Accepted, a debounced
[ERR]/[WRN]marker at the input row's right edge, backed by a walker diagnostics-severity model (parse-outcome + schema-existence); advisory, never blocks submission (S6); Amendment 1 adds aLIKE-on-numeric-column WARNING - ADR-0028 — Query plans (
EXPLAIN QUERY PLAN) — Accepted, anexplainprefix command overshow data/update/delete; an annotated, span-styled plan tree; introduces theOutputLinestyled-runs mechanism (ADR-0016's deferred per-span styling) (QA1/QA2) - ADR-0029 — Column constraints (NOT NULL / UNIQUE / CHECK / DEFAULT) — Accepted, the four column-level constraints declared in the column-spec suffix (
create table/add column) and modified on existing columns viaadd constraint …/drop constraint …; a pre-flight dry-run guards populated columns;CHECKreuses the ADR-0026 expression grammar viaSubgrammar(C3) - ADR-0030 — Advanced mode: the standard-SQL surface — Accepted, SQL added as grammar within the unified grammar tree (ADR-0024), not a separate batch parser — so SQL gets the same completion / highlighting / hints / parse-errors as the DSL; mode gates the SQL forms; DDL routes through the typed
Commandexecutor (metadata + type vocabulary preserved), DML andSELECTexecute as validated SQL; engine-neutral posture, the DSL→SQL teaching echo; supersedes ADR-0001'ssqlparser-rsreservation; phased plan (Q1/Q2/Q4) - ADR-0031 — The SQL expression grammar — Accepted, the stratified SQL expression grammar fragment commissioned by ADR-0030 §3: a single precedence ladder (
OR/AND/NOT, the comparison/LIKE/IN/BETWEEN/IS NULLpredicate set, arithmetic incl.||, function calls,CASE) — the superset of ADR-0026's DSLWHEREgrammar, authored as a parallel fragment so simple mode is untouched; pure validation, builds no AST (consumers run/store SQL as text per ADR-0030 §4/§6); reuses ADR-0026'sSubgrammarrecursion + depth cap unchanged; subquery expressions and qualified column refs deferred to ADR-0030 Phase 2 - ADR-0032 — The full SQL
SELECTgrammar — Accepted, the Phase-2 grammar commissioned by ADR-0030 §3: fullSELECTwithINNER/LEFT/RIGHT/FULL OUTER/CROSSjoins,GROUP BY/HAVING, all four set ops (UNION/UNION ALL/INTERSECT/EXCEPT),WITHandWITH RECURSIVECTEs,LIMIT … OFFSET,DISTINCT,t.*, and bare-alias projection (lifting Phase-1 §4.2); additive extensions to ADR-0031'ssql_exprfor scalar subqueries,IN (SELECT …),[NOT] EXISTS, and qualified column refs (redeeming ADR-0031 §7 OOS-1/OOS-2); grammar-recursion viaSubgrammar(&SQL_SELECT_COMPOUND)reuses ADR-0026'sMAX_SUBGRAMMAR_DEPTH = 64cap unchanged; softens ADR-0030 §8's "ambient assistance comes for free" claim: completion scope needs newWalkContextaccumulators (afrom_scope_stackofScopeFrames holdingfrom_scope/cte_bindings/projection_aliases), a new walker node variantNode::ScopedSubgrammar(&Node)as the push/pop trigger (existingNode::Subgrammarunchanged so DSLExprandsql_exprrecursion are unaffected), qualified-prefix completion narrowing, body-projection-derived CTE column resolution (soSELECT *and explicit-projection CTE bodies both yield real column completion pastcte_alias.|), and a post-walk fixup pass that re-resolves projection-list identifier highlighting/validity onceFROMis parsed (the projection-before-FROM problem); classifies every Phase-2 validation case against ADR-0027's ERROR/WARNING guideline (§11): five newdiagnostic.*keys for parse-time-detectable cases (unknown qualifier, ambiguous column, projection-alias misplaced, CTE/compound arity mismatch) plus eightengine.*translation keys; a MatchedPath-walking predicate-warnings variant that closes the Phase-1 gap where SQLWHEREexpressions emitted noLIKE-on-numeric /= NULL/ type-mismatch warnings (ADR-0027 Amendment 1 finally extends to the SQL surface); adds a worker-side post-prepare type-resolution pass via engine column-origin metadata so bare column refs recover their playground type (partially lifting Phase-1 §4.5, the bool→0/1 case) —Cargo.tomlgainscolumn_metadatato rusqlite features (verified against pinned 0.39.0);__rdbms_*rejection extended to every new table-source slot; Amendment 1 narrows §12's resolution rule from a grammar-side structural classification to "trust the engine's column-origin metadata verbatim" after an empirical probe showed origin metadata follows through non-recursive CTEs, scalar subqueries, derived tables, set ops, and joins — the one structural exception is recursive CTE result columns, which return None and stay typeless; Amendment 2 records that §10.6's "rewrite the highlight class" prescription is realised via the two-pass schema-existence diagnostic + the renderer's diagnostic-overlay path (no separate per-byte rewrite step needed; no new HighlightClass variant), and that the projection-before-FROM completion narrowing has been improved by ansrc/completion.rslook-ahead probe when the leading walk'sfrom_scopeis empty but the full input parses - ADR-0033 — The full SQL DML grammar (
INSERT/UPDATE/DELETE) — Proposed, the Phase-3 grammar commissioned by ADR-0030 §3: single- and multi-rowINSERT(incl.INSERT … SELECTrecursing through ADR-0032'sSQL_SELECT_COMPOUND),UPDATEwithSETassignment list,DELETE, all three optionally followed byRETURNING projection_list, plus fullON CONFLICT … DO NOTHING / DO UPDATEUPSERT on INSERT; fixes the DSL-vs-SQL dispatch architecture for shared entry words (insert/update/delete): SQL-first / DSL-fallback in Advanced mode via aChoice(SQL_shape, DSL_shape)per shape, gated by a new walker capabilityNode::Guard(fn)— a zero-byte-consumption gating node that fails the enclosing Seq with aValidationError; carriesCommand::SqlInsert/SqlUpdate/SqlDeletevariants anddo_sql_*worker handlers each of which knows the target table (for re-persistence) and thereturning: boolflag (for DataResult routing);shortidauto-fill mirrors the DSLdo_insertmechanism via worker post-fill; SQL DELETE produces the same per-relationship cascade summary the DSL DELETE does (ADR-0014 parity), with the WHERE-clause source bytes re-injected into per-child pre-count subqueries; three new walker diagnostics (insert_arity_mismatchERROR,auto_column_overriddenWARNING,not_null_missingWARNING) with positive + negative tests each; OOS list explicitly carves outDEFAULT VALUES(the project's planned seed feature), SQLite-specificOR REPLACE/OR IGNORE/OR ABORT/OR FAIL/OR ROLLBACKprefixes,UPDATE FROMmulti-table updates, and WITH-prefixed DML; theexcludedkeyword insideON CONFLICT DO UPDATEis a deliberate carve-out from ADR-0030 §7's engine-neutral posture (no standard-SQL UPSERT spelling exists that SQLite and PostgreSQL share); eleven phased sub-phases each with explicit exit gates + written DA gate, opening withNode::Guardmechanism scaffolding before any DML grammar lands; initial DA review recorded seven critiques that were resolved before status moved to Proposed