Decides the architecture for SQL in advanced mode (Q1/Q2/Q4): SQL is authored as grammar within the unified grammar tree (ADR-0024) and parsed by the existing walker — not a separate batch parser — so SQL gets the same completion, highlighting, hints, and parse-error reporting as the DSL. Mode gates the SQL forms. DDL routes through the typed Command executor (metadata and the playground type vocabulary preserved); DML and SELECT execute as validated SQL. Engine-neutral posture; DSL→SQL teaching echo; phased plan. Supersedes ADR-0001's sqlparser-rs reservation. Ticks Q4; updates the ADR index and the Q1/Q2 notes. handoff-24 orients the implementation session at Phase 1.
9.0 KiB
Session handoff — 2026-05-19 (24)
Twenty-fourth handover. A design-only session: it wrote and accepted ADR-0030 — Advanced mode: the standard-SQL surface. No code changed. A fresh session implements ADR-0030 from this file + the ADR, starting at Phase 1.
§1. State at handoff
Branch: main. Working tree clean (after this docs
commit). The session's commits since handoff-23 are docs-only —
ADR-0030, the ADR index, the requirements.md updates, and
this handoff. All local; push asynchronously, not blocking.
Tests: unchanged — 1240 passing, 0 failing, 1 ignored
as of a049ff9 (ADR-0029 complete). This session touched no
code. Clippy: clean as of the same commit.
§2. What was decided — ADR-0030
Read docs/adr/0030-advanced-mode-sql-surface.md — the
spec, complete and accepted. Its shape, and why it landed
where it did (the design went through two rounds of user
input — §3 records the reasoning so it is not relitigated):
- SQL is grammar in the unified tree, not a separate parser
(§1). SQL statements are authored as
CommandNode/Nodegrammar in the ADR-0024 tree and parsed by the existing walker.sqlparser-rsis not used — ADR-0001's reservation is superseded. The reason is decisive: a batch SQL parser produces an AST and nothing else; it cannot drive completion, highlighting, or hints. The user requires SQL to have the same ambient assistance as the DSL — and that assistance comes only from the unified grammar tree (ADR-0022/0023/0024). So SQL must live in the tree. - Mode gates the grammar (§2). One grammar tree; simple
mode exposes the DSL subset, advanced mode adds the SQL
forms. Shared entry words (
create,insert, …) get aChoiceof DSL + SQL forms under oneCommandNode(howaddalready holds four sub-commands);selectis a new SQL-only entry word. - Execution split (§4). DDL → a typed
Command→ the existing executor, so metadata, the playground type vocabulary, andSTRICTare preserved. DML andSELECT→ executed as validated SQL (they change no schema, so a typedCommandbuys nothing); the worker re-persists the affected table after DML. - Engine-neutral (§5, §7). Playground type vocabulary,
never engine storage types; no
STRICTsurfaced; engine-neutral errors. Advanced mode is standard SQL, not an engine console. - Assistance for free (§8). Because SQL is in the tree,
the walker gives SQL completion, highlighting, hint prose,
the
[ERR]/[WRN]indicator, and parse-error usage — the same as the DSL, no SQL-specific assistance code. - The DSL→SQL teaching echo (§10). A DSL command run in advanced mode also prints its equivalent SQL.
- Persistence / replay (§11). DDL via
Commandkeepsproject.yamlcorrect; DML re-persists its table;history.logstores the literal line; replay re-runs lines through the one walker.
§3. Decisions the user made (do not relitigate)
- Full SQL scope — DDL + DML + the full
SELECTquery surface (joins, aggregates,GROUP BY/HAVING, subqueries,UNION, CTEs). No pre-emptive cuts; if a slice proves genuinely overwhelming, cutting it is an explicit escalation to the user, never a silent trim. - No fallback to engine types — advanced DDL keeps the
playground's rich type vocabulary. The
SQL → Commandpath for DDL is what guarantees this. - Advanced mode is standard SQL, engine-independent — not a SQLite console; no engine-specifics surface.
- SQL lives in the unified grammar tree (not a separate
batch parser) — chosen specifically so SQL gets full
completion / highlighting / hints. The user understood and
accepted that this means authoring a SQL grammar
ourselves;
sqlparser-rsis dropped. Commandonly where it pays. DDL →Command(buys metadata + types); DML /SELECT→ validated SQL (aCommandbuys nothing).- The DSL→SQL echo shows in advanced mode only.
- The persisted / replayable representation must be
app-enterable syntax —
history.logalready stores the literal line, so this holds.
§4. The phased implementation plan
ADR-0030 §Implementation is canonical. Each phase is
independently shippable and test-guarded. The two large
grammar slices each warrant their own focused ADR when
taken up (precedent: ADR-0026 for the WHERE grammar).
- Foundations + first
SELECT. Mode-gate the grammar (advanced unlocks the SQL nodes). Author the core SQL expression grammar — the ADR-0026 superset (arithmetic, function calls,CASE, the predicate set) — its own ADR. A single-tableSELECT(projection,WHERE,ORDER BY,LIMIT) as a SQLCommandNode→Command::Select→ workerRunSelect→ the existing data-table renderer. Replace the placeholder echo; add the simple-mode "this is SQL" hint. Proves the path end to end with full walker assistance. SELECT— full.JOINs,GROUP BY/HAVING, aggregates, subqueries,UNION, CTEs — its own ADR.- DML.
INSERT/UPDATE/DELETEgrammar; the execute-as-validated-SQL path; the worker re-persist step; settle multi-rowINSERTandshortidauto-fill on a SQLINSERT. - DDL.
CREATE/DROP/ALTER TABLE,CREATE/DROP INDEXgrammar →Command; the §5 type-name map; FK clauses →AddRelationship; may land table-rename (C1). - The DSL→SQL teaching echo (§10).
- Polish —
help sql; engine-neutral error sweep; typing-surface / matrix coverage; theDOC1SQL-surface reference page.
§5. Seams for the implementer (from a code survey)
Anchors for Phase 1:
- The placeholder to replace:
App::submit(src/app.rs~954–1014) — the advanced-mode branch echoes the input withadvanced_mode.not_implemented(~996–1012) and sends nothing to the worker. The DSL dispatch path (dispatch_dsl, ~1089) is what advanced SQL joins. - The grammar tree:
src/dsl/grammar/—mod.rsholdsNode,CommandNode, theREGISTRY;ddl.rs/data.rshold the DSL command grammars;expr.rsholds the ADR-0026 expression grammar (the seed for the SQL expression grammar);shared.rsshared fragments. The walker is insrc/dsl/walker/. SQL grammar is authored here; mode-gating is added to theREGISTRY/ walker. - Command core:
Commandinsrc/dsl/command.rs— add aSelectvariant. Gotcha: every exhaustivematch Commandbreaks (verb/target_table/display_subjectincommand.rs;execute_command_typedinruntime.rs;build_translate_contextinapp.rs;command_kind_labelintests/typing_surface/mod.rs) — the ADR-0028/0029 pattern. - Worker:
Requestenum +handle_request+ theDatabasemethod wrappers insrc/db.rs(~444 on) — addRunSelect(returnsDataResult), and later a "run validated DML + re-persist" request. - Result rendering: a
Selectoutcome →CommandOutcome::Query→AppEvent::DslDataSucceeded→output_render::render_data_table— all reused fromshow data. - Mode:
src/mode.rs(Mode::Simple/Advanced);App::effective_modeand the:-strip inApp::submitalready work — the mode-gated grammar view plugs in there. sqlparser-rsis not used — do not add it (an implementer may keep it only as a test oracle, off the execution path).- Risk: the
Nodetaxonomy / walker may need extension to carry SQL's grammar (deeper recursion for subqueries / CTEs). Expect node-taxonomy work in Phases 1–2; ADR-0030 flags this.
§6. How to take over
- Read this file, then
docs/adr/0030-advanced-mode-sql- surface.md(the spec). ThenCLAUDE.md(working-style rules),docs/requirements.md(Q4ticked;Q1/Q2unblocked), and skimdocs/simple-mode-limitations.md— ADR-0030 §4 commits advanced mode to lifting the expression limits that file records. - Run
cargo test— 1240 passing, 0 failing, 1 ignored. - Run
cargo clippy --all-targets -- -D warnings— clean. - Start ADR-0030 Phase 1. First sub-step is the SQL
expression grammar — write its focused ADR before
authoring it (ADR-0026 is the model and the seed). Then the
single-table
SELECTend to end. Land theCommand:: Selectmatch-arm sweep with the worker request in one commit (the exhaustive-match breakage forces it). - Escalate, do not guess, on anything ADR-0030 left per-phase
— multi-row
INSERT,shortidon SQLINSERT, anyNode-taxonomy extension that changes the walker's contract.
§7. What else is open
ADR-0030 is the active design. Other open clusters, unchanged
from handoff-23 §5 (prioritisation is a user decision):
snapshot/undo U-series (ADR-0006 written, unbuilt); m:n
convenience C4; modify-relationship C3a; the show family
V5; rename-table C1 (may fall out of ADR-0030 Phase 4);
friendly-error sweep H1; CI TT5; session-log / Markdown
export V4.