diff --git a/docs/adr/0052-mode-tagged-history-cross-mode-recall.md b/docs/adr/0052-mode-tagged-history-cross-mode-recall.md index 7fdaabe..5efdb2a 100644 --- a/docs/adr/0052-mode-tagged-history-cross-mode-recall.md +++ b/docs/adr/0052-mode-tagged-history-cross-mode-recall.md @@ -189,9 +189,18 @@ over keeping journaling coupled in the worker (which would have needed the no-op-skip / read-only sites no longer journal; success is journalled at the dispatch layer (`spawn_dsl_dispatch` / `run_replay` / app-command sites). The ring stays `Vec`; `seed_history` / `ProjectSwitched` - are untouched. The vestigial worker `source` plumbing (the `_source` - param on `finalize_persistence` / `do_rebuild_from_text` and the thin - read-only `*_request` wrappers) is left in place — a clean follow-up. + are untouched. The vestigial worker `source` plumbing has since been + **fully unwound** (2026-06-14 follow-up): `_source` removed from + `finalize_persistence` / `do_rebuild_from_text`; the three read-only + `*_request` wrappers inlined and deleted; and — because the cascade ran + deeper than first estimated — the now-dead `source` param dropped from + the ~30 worker handlers (leaf + composite) that only forwarded it, plus + the `source` field removed from the `DescribeTable` / `QueryData` / + `RunSelect` requests and the matching `DatabaseHandle` method parameters + (the ~164 call-site churn was mostly tests). The only `source` left in + the worker is the snapshot/undo label (`snapshot_then` / + `stage_pre_mutation` / `begin_batch`), passed at the match-arm level. + Purely mechanical, compiler-guided, no behaviour change. - **App commands recall bare.** Because they are dispatched outside the `ExecuteDsl`/spawn path, app commands journal **simple** (`advanced = false`) at their own sites, and `submit` excludes them from the ring's diff --git a/docs/adr/README.md b/docs/adr/README.md index abeba31..8aeb407 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -57,4 +57,4 @@ This directory contains the project's ADRs, recorded per - [ADR-0049 — Input-field readline keymap: Esc-clear + Ctrl-A/E/W/K/U (I1b)](0049-input-field-readline-keymap.md) — **Accepted + implemented 2026-06-12 (issue #29)**, closes Gitea **#29** and the deferred **I1b** readline requirement. **Amends ADR-0046**, which listed "readline shortcuts (I1b)" as out-of-scope — that item is now in scope and decided here; orthogonal to ADR-0003's input-*mode* model and extends the I1a single-line cursor editing already shipped. Binds, in the input field (non-modal, non-nav, both modes): **`Esc`** clears a partly-typed command (empty buffer, cursor→0, scroll→0); **`Ctrl-A`/`Ctrl-E`** alias Home/End (line start/end); **`Ctrl-W`** deletes the previous word (readline-style — eats trailing whitespace then the preceding non-whitespace run, UTF-8-safe on char boundaries, only back to the cursor); **`Ctrl-K`** kills to end of line; **`Ctrl-U`** kills to start. **Esc precedence:** a live Tab-completion memo still wins (Esc undoes the completion first, ADR-0022; Esc clears only when no memo) — Esc-once backs out the completion, Esc-again clears. Forks all user-chosen: **single-Esc-clears** (not double-Esc — discoverable over accident-proof; an unsubmitted draft can be lost, a submitted line is always in history); the **full I1b set** (not just the issue's literal Ctrl-A/E + Esc); a **new ADR** (not an ADR-0046 amendment / no-ADR). Cursor-only keys (Ctrl-A/E) leave history navigation intact like Home/End; buffer-mutating keys (Esc-clear, Ctrl-W/K/U) end it like Backspace. Helpers `clear_input`/`delete_prev_word`/`kill_to_end`/`kill_to_start` in `src/app.rs`; **22 new Tier-1 tests, 2458 pass / 0 fail / 0 skip (1 ignored), clippy clean**. OOS: on-screen keybinding hints (issue #27 owns surfacing per-focus keybindings in the bottom status line — this ADR makes the keys *work*, #27 makes them *discoverable*); demo-mode badges for the new chords (ADR-0047 follow-up — Esc already badges `[ESC]`, the glyph-less Ctrl-chords are flagged but not added); multi-line input (I1); word-wise cursor motion (Alt-B/F) / transpose / yank - [ADR-0050 — Incidental-DDL confirmations omit relationship info (structure-only)](0050-incidental-ddl-confirmations-omit-relationships.md) — **Accepted + implemented 2026-06-12 (issue #28)**, closes Gitea **#28**. **Supersedes** the incidental-DDL clause of **ADR-0044 §1** and the relationship-block half of **ADR-0016 §5**. Incidental-DDL confirmation echoes (`create table`, `add`/`drop`/`rename`/`change column`, `add`/`drop index`) now render **structure only** — header + column box + `Indexes:` + constraints — with **no `References:` / `Referenced by:` block** (neither prose nor diagram), even when the table carries relationships the user did not touch. Rationale (owner): a confirmation echo reports the change just made, not untouched relationships; ADR-0044's terse prose was the lesser of "prose vs diagram", but the right answer for these surfaces is **neither**. **Relationship-subject surfaces are unchanged** — `show table`, `add`/`drop relationship`, `show relationship` still render ADR-0044 diagrams; relationships appear only when the user asks for (`show table`) or acts on (`add`/`drop relationship`) one, and are one `show table ` away — **no information lost**. Forks both user-chosen: **scope = all incidental DDL** (not just `add column` — the rationale is uniform, the mental model clean, and it's the simpler edit) and **delete the prose renderer** (not retain it dormant — no dead code). **Mechanism:** the `handle_dsl_success` `matches!` routing is unchanged (relationship-subject → diagrams; else → `render_structure`); the change is one line inside `render_structure` (`output_render.rs` — drop the relationship-block call) since all its callers are incidental DDL, plus deletion of the orphaned `relationship_prose_lines` + `cols_disp` helpers. The prose format survives in ADR-0016 §5 + git history for a future OOS-7 always-prose setting. **Tests:** the prose-presence unit test + its snapshot removed; a new unit test asserts `render_structure` on a description carrying **both** inbound and outbound relationships emits the box but no prose; the misnamed `add_relationship_flow_shows_inbound_section_on_parent` integration test (which sent an `AddColumn`) inverted + renamed to assert the add-column echo omits the prose; the diagram tests (`show table`, `add relationship`) unaffected. **2458 pass / 0 fail / 0 skip (1 ignored), clippy clean**. `requirements.md` unaffected (ADR-tracked refinement of a decided area, like ADR-0044 itself) - [ADR-0051 — Bottom keybinding strip: context- and state-aware](0051-context-state-aware-keybinding-strip.md) — **Accepted + implemented 2026-06-13 (issue #27)**, closes Gitea **#27**. Repurposes the bottom status line into a **keystrokes-only, state-selected** strip (builds on ADR-0046 nav focus, ADR-0003 modes, ADR-0049 the #29 readline keys it now advertises, ADR-0022 the completion memo). A pure `status_bar_bindings(app) -> Vec<(key,label)>` chooses the strip by **priority, first match wins**: (1) **sidebar focus** → `Ctrl-O next pane · ↑↓/PgUp/PgDn scroll · Esc input`; (2) **completion memo live** (`last_completion`) → `Tab/Shift-Tab cycle · Esc cancel · Enter run`; (3) **history navigation** (new `App::is_browsing_history()` exposing the private `history_cursor`) → `↑↓ browse · Esc clear · Enter run`; (4) **editing** (input non-empty) → `Esc clear · Ctrl-A/E home/end · Ctrl-W del word · Enter run` (surfaces the #29 keys, closing ADR-0049's deferred advertisement); (5) **default** (empty) → `Ctrl-O sidebar · Tab complete · ↑ history · Enter run`. Priority is correct because Up clears the completion memo and Tab cancels history nav, so states 2/3 never co-occur, and the five are exhaustive for Input focus. **Typed-command words leave the strip** (`mode advanced`/`mode simple` switch, `:` one-shot) and **mode discovery moves to the empty-input hint** (`resolve_hint_lines`), **simple mode only**: `\`mode advanced\` for SQL` (the verb "type" omitted — the prompt implies it; advanced mode shows **no** pointer per a post-trial user decision — a switcher knows how they got there and `help` covers the way back). The one-shot's old `Backspace cancel one-shot` label is subsumed by the editing state (behaviour intact). Forks all user-chosen: **editing state shows the #29 keys** (vs unadvertised); **`Ctrl-C quit` omitted** from the strip (vs always shown); **no width-drop machinery** — the longest strip (~65 cols) fits all supported widths, so a **width-budget unit test** keeps it lean by construction instead (the user's own observation). Catalog: 12 new `shortcut.*` labels + the `panel.hint_mode_advanced` string added to `en-US.yaml`+`keys.rs` (validator-checked 1:1), 5 now-dead strip strings removed. **Modal-aware strip is OOS** (pre-existing: a modal owns the keyboard and carries its own hints; the strip under it is unchanged-in-kind, not worsened). Tests: 9 Tier-1 unit (per-state key sets — completion/history driven through real key events; width budget; mode-pointer presence/absence), 1 Tier-3 rewritten (`status_bar_is_keystroke_only_and_state_aware`), 15 full-panel snapshots re-accepted (reviewed — strip/hint only). **2467 pass / 0 fail / 0 skip (1 ignored), clippy clean.** OOS: modal-aware strip; a full-key cheatsheet overlay; Ctrl-K/U advertisement (editing strip shows the highest-value subset within the width budget) -- [ADR-0052 — Mode-tagged history for cross-mode recall](0052-mode-tagged-history-cross-mode-recall.md) — **Accepted + implemented 2026-06-13 (issue #30)**, closes Gitea **#30** — the feature (advanced history reusable in simple mode) **and** the bug in its comment (the `:` one-shot prefix lost across sessions). **Amends ADR-0034** (status field gains a `:adv` tag; **journaling moves from the worker to the dispatch layer**), **ADR-0015 §5/§6** (history.log leaves the worker transaction — `commit-db-last` now scopes yaml/csv/db only), and **ADR-0040** (a success-path journal-write failure is best-effort, not fatal); references ADR-0003. **Root cause:** history carried no mode, and the in-memory ring stored the raw `:select 1` while the worker journalled the *stripped* `select 1`, so the `:` was lost on disk. **Fix:** record the submission mode per entry as a **`:adv` suffix on the status token** (`ok`/`ok:adv`/`err`/`err:adv`) — `source` stays last + canonical so replay is unaffected; the in-memory ring (still `Vec`) stores advanced entries in their `: `-prefixed simple-mode runnable form (a leading `:` unambiguously marks advanced since simple DSL never starts with `:`); recall **strips the `:` in advanced mode** (runs as bare SQL) and keeps it in simple mode (runs via the one-shot escape); hydration reconstructs the `: `-prefix from the tag, so cross-session = in-session. **The architectural turn (user's call):** the first draft kept journaling in the worker + threaded the mode down (~30-site plumbing); on review the user asked why the journal is written deep in the worker when the *failure* path already journals at the top of the chain — it shouldn't (history.log is a journal, not state). So **success journaling moved up** to `spawn_dsl_dispatch` / `run_replay` / the app-command sites (next to the failure path), the worker's `finalize_persistence` now writes only yaml/csv, and the journal write became **best-effort** (the command is already committed — consistent with the failure path; a rare disk-full leaves a committed command unjournalled, state intact). **App commands** journal simple (dispatched outside the spawn) and `submit` excludes them from the ring's advanced flag, so `undo`/`mode advanced` recall bare. Forks user-chosen: status-tag format (vs 4th field / `:`-in-source); unified scope; **dispatch-layer best-effort journaling** (vs worker-coupled-fatal). Two `/runda` passes (the second drove the relocation + app-command exclusion). Tests: the 15 worker-level journaling tests retired (worker no longer journals — yaml/csv/operation checks kept), re-covered at the new layer (history.rs status-tag + `:`-reconstruct; app.rs recall matrix; the #30 cross-session regression in `iteration6`; replay tests cover `run_replay` journaling). **2471 pass / 0 fail / 0 skip (1 ignored), clippy clean.** OOS: unwinding the now-vestigial worker `source` plumbing (`_source` params + thin `*_request` wrappers — a clean follow-up); replay re-journaling mode-fidelity (a replayed advanced line re-journals simple — not a regression) +- [ADR-0052 — Mode-tagged history for cross-mode recall](0052-mode-tagged-history-cross-mode-recall.md) — **Accepted + implemented 2026-06-13 (issue #30)**, closes Gitea **#30** — the feature (advanced history reusable in simple mode) **and** the bug in its comment (the `:` one-shot prefix lost across sessions). **Amends ADR-0034** (status field gains a `:adv` tag; **journaling moves from the worker to the dispatch layer**), **ADR-0015 §5/§6** (history.log leaves the worker transaction — `commit-db-last` now scopes yaml/csv/db only), and **ADR-0040** (a success-path journal-write failure is best-effort, not fatal); references ADR-0003. **Root cause:** history carried no mode, and the in-memory ring stored the raw `:select 1` while the worker journalled the *stripped* `select 1`, so the `:` was lost on disk. **Fix:** record the submission mode per entry as a **`:adv` suffix on the status token** (`ok`/`ok:adv`/`err`/`err:adv`) — `source` stays last + canonical so replay is unaffected; the in-memory ring (still `Vec`) stores advanced entries in their `: `-prefixed simple-mode runnable form (a leading `:` unambiguously marks advanced since simple DSL never starts with `:`); recall **strips the `:` in advanced mode** (runs as bare SQL) and keeps it in simple mode (runs via the one-shot escape); hydration reconstructs the `: `-prefix from the tag, so cross-session = in-session. **The architectural turn (user's call):** the first draft kept journaling in the worker + threaded the mode down (~30-site plumbing); on review the user asked why the journal is written deep in the worker when the *failure* path already journals at the top of the chain — it shouldn't (history.log is a journal, not state). So **success journaling moved up** to `spawn_dsl_dispatch` / `run_replay` / the app-command sites (next to the failure path), the worker's `finalize_persistence` now writes only yaml/csv, and the journal write became **best-effort** (the command is already committed — consistent with the failure path; a rare disk-full leaves a committed command unjournalled, state intact). **App commands** journal simple (dispatched outside the spawn) and `submit` excludes them from the ring's advanced flag, so `undo`/`mode advanced` recall bare. Forks user-chosen: status-tag format (vs 4th field / `:`-in-source); unified scope; **dispatch-layer best-effort journaling** (vs worker-coupled-fatal). Two `/runda` passes (the second drove the relocation + app-command exclusion). Tests: the 15 worker-level journaling tests retired (worker no longer journals — yaml/csv/operation checks kept), re-covered at the new layer (history.rs status-tag + `:`-reconstruct; app.rs recall matrix; the #30 cross-session regression in `iteration6`; replay tests cover `run_replay` journaling). **2471 pass / 0 fail / 0 skip (1 ignored), clippy clean.** replay re-journaling mode-fidelity (a replayed advanced line re-journals simple — not a regression). **Follow-up done 2026-06-14:** the vestigial worker `source` plumbing was fully unwound (compiler-guided, no behaviour change) — `_source` removed from `finalize_persistence`/`do_rebuild_from_text`, the three `*_request` wrappers inlined+deleted, the dead `source` param dropped from the ~30 forwarding worker handlers, and the `source` field removed from the `DescribeTable`/`QueryData`/`RunSelect` requests + their `DatabaseHandle` methods (~164 mostly-test call sites); the only worker `source` left is the snapshot/undo label (see ADR-0052 *Consequences*) diff --git a/src/db.rs b/src/db.rs index f6f08b9..80ebb64 100644 --- a/src/db.rs +++ b/src/db.rs @@ -608,7 +608,6 @@ enum Request { }, DescribeTable { name: String, - source: Option, reply: oneshot::Sender>, }, AddRelationship { @@ -748,7 +747,6 @@ enum Request { table: String, filter: Option, limit: Option, - source: Option, reply: oneshot::Sender>, }, /// Run a SQL `SELECT` typed by the user in advanced mode @@ -757,11 +755,11 @@ enum Request { /// prepares and runs the statement and returns the rows as /// a [`DataResult`] (with no playground type information per /// ADR-0030 §6 — computed columns render with neutral - /// alignment). `source` is the literal submitted line, - /// appended to `history.log` for replay (ADR-0030 §11). + /// alignment). The literal submitted line is journalled to + /// `history.log` at the dispatch layer for replay (ADR-0030 §11, + /// ADR-0052). RunSelect { sql: String, - source: Option, reply: oneshot::Sender>, }, /// Run a validated SQL `INSERT` typed in advanced mode @@ -1418,18 +1416,9 @@ impl Database { recv.await.map_err(|_| DbError::WorkerGone)? } - pub async fn describe_table( - &self, - name: String, - source: Option, - ) -> Result { + pub async fn describe_table(&self, name: String) -> Result { let (reply, recv) = oneshot::channel(); - self.send(Request::DescribeTable { - name, - source, - reply, - }) - .await?; + self.send(Request::DescribeTable { name, reply }).await?; recv.await.map_err(|_| DbError::WorkerGone)? } @@ -1608,14 +1597,12 @@ impl Database { table: String, filter: Option, limit: Option, - source: Option, ) -> Result { let (reply, recv) = oneshot::channel(); self.send(Request::QueryData { table, filter, limit, - source, reply, }) .await?; @@ -1624,15 +1611,11 @@ impl Database { /// Run a validated SQL `SELECT` and return the rows /// (ADR-0030 §6, ADR-0031). `sql` is the grammar-validated - /// statement text; `source` is the literal submitted line - /// for `history.log`. - pub async fn run_select( - &self, - sql: String, - source: Option, - ) -> Result { + /// statement text; the literal submitted line is journalled + /// at the dispatch layer (ADR-0052). + pub async fn run_select(&self, sql: String) -> Result { let (reply, recv) = oneshot::channel(); - self.send(Request::RunSelect { sql, source, reply }).await?; + self.send(Request::RunSelect { sql, reply }).await?; recv.await.map_err(|_| DbError::WorkerGone)? } @@ -2235,7 +2218,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_create_table( conn, persistence, - source.as_deref(), &name, &columns, &primary_key, @@ -2272,7 +2254,6 @@ fn handle_request( do_create_table( conn, persistence, - source.as_deref(), &name, &columns, &primary_key, @@ -2290,7 +2271,7 @@ fn handle_request( reply, } => { snapshot_then(snap, batch, conn, source.as_deref(), reply, || { - do_drop_table(conn, persistence, source.as_deref(), &name) + do_drop_table(conn, persistence, &name) }); } Request::SqlDropTable { @@ -2309,7 +2290,7 @@ fn handle_request( let _ = reply.send(result); } else { snapshot_then(snap, batch, conn, source.as_deref(), reply, || { - do_drop_table(conn, persistence, source.as_deref(), &name) + do_drop_table(conn, persistence, &name) .map(|()| DropOutcome::Dropped) }); } @@ -2323,7 +2304,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_add_column( conn, persistence, - source.as_deref(), &table, &column, )); @@ -2338,7 +2318,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_drop_column( conn, persistence, - source.as_deref(), &table, &column, cascade, @@ -2354,7 +2333,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_rename_column( conn, persistence, - source.as_deref(), &table, &old, &new, @@ -2369,7 +2347,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_rename_table( conn, persistence, - source.as_deref(), &table, &new, )); @@ -2385,7 +2362,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_change_column_type( conn, persistence, - source.as_deref(), &table, &column, ty, @@ -2401,17 +2377,8 @@ fn handle_request( Request::ShowRelationship { name, reply } => { let _ = reply.send(do_show_relationship(conn, &name)); } - Request::DescribeTable { - name, - source, - reply, - } => { - let _ = reply.send(do_describe_table_request( - conn, - persistence, - source.as_deref(), - &name, - )); + Request::DescribeTable { name, reply } => { + let _ = reply.send(do_describe_table(conn, &name)); } Request::AddRelationship { name, @@ -2428,7 +2395,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_add_relationship( conn, persistence, - source.as_deref(), name.as_deref(), &parent_table, &parent_columns, @@ -2450,7 +2416,6 @@ fn handle_request( do_create_m2n_relationship( conn, persistence, - source.as_deref(), &t1, &t2, name.as_deref(), @@ -2465,7 +2430,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_drop_relationship( conn, persistence, - source.as_deref(), &selector, )); } @@ -2479,7 +2443,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_add_index( conn, persistence, - source.as_deref(), name.as_deref(), &table, &columns, @@ -2497,7 +2460,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_drop_index( conn, persistence, - source.as_deref(), &selector, )); } @@ -2522,7 +2484,6 @@ fn handle_request( do_drop_index( conn, persistence, - source.as_deref(), &IndexSelector::Named { name: name.clone() }, ) .map(DropIndexOutcome::Dropped) @@ -2555,7 +2516,6 @@ fn handle_request( do_add_index( conn, persistence, - source.as_deref(), name.as_deref(), &table, &columns, @@ -2575,7 +2535,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_add_constraint( conn, persistence, - source.as_deref(), &table, &column, &constraint, @@ -2591,7 +2550,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_drop_constraint( conn, persistence, - source.as_deref(), &table, &column, kind, @@ -2608,7 +2566,6 @@ fn handle_request( do_set_column_default( conn, persistence, - source.as_deref(), &table, &column, &default_sql, @@ -2626,7 +2583,6 @@ fn handle_request( do_alter_add_table_check( conn, persistence, - source.as_deref(), &table, name.as_deref(), &expr_sql, @@ -2640,7 +2596,7 @@ fn handle_request( reply, } => { snapshot_then(snap, batch, conn, source.as_deref(), reply, || { - do_alter_add_unique(conn, persistence, source.as_deref(), &table, &columns) + do_alter_add_unique(conn, persistence, &table, &columns) }); } Request::AlterDropConstraint { @@ -2650,7 +2606,7 @@ fn handle_request( reply, } => { snapshot_then(snap, batch, conn, source.as_deref(), reply, || { - do_drop_constraint_by_name(conn, persistence, source.as_deref(), &table, &name) + do_drop_constraint_by_name(conn, persistence, &table, &name) }); } Request::AlterAddForeignKey { @@ -2664,7 +2620,6 @@ fn handle_request( do_alter_add_foreign_key( conn, persistence, - source.as_deref(), &child_table, name.as_deref(), &fk, @@ -2681,7 +2636,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_insert( conn, persistence, - source.as_deref(), &table, columns.as_deref(), &values, @@ -2701,7 +2655,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_seed( conn, persistence, - source.as_deref(), &table, target_column.as_deref(), count, @@ -2719,7 +2672,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_update( conn, persistence, - source.as_deref(), &table, &assignments, &filter, @@ -2734,7 +2686,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_delete( conn, persistence, - source.as_deref(), &table, &filter, )); @@ -2743,25 +2694,12 @@ fn handle_request( table, filter, limit, - source, reply, } => { - let _ = reply.send(do_query_data_request( - conn, - persistence, - source.as_deref(), - &table, - filter.as_ref(), - limit, - )); + let _ = reply.send(do_query_data(conn, &table, filter.as_ref(), limit)); } - Request::RunSelect { sql, source, reply } => { - let _ = reply.send(do_run_select_request( - conn, - persistence, - source.as_deref(), - &sql, - )); + Request::RunSelect { sql, reply } => { + let _ = reply.send(do_run_select(conn, &sql)); } Request::RunSqlInsert { sql, @@ -2776,7 +2714,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_sql_insert( conn, persistence, - source.as_deref(), &sql, &target_table, &listed_columns, @@ -2796,7 +2733,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_sql_update( conn, persistence, - source.as_deref(), &sql, &target_table, returning, @@ -2813,7 +2749,6 @@ fn handle_request( snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_sql_delete( conn, persistence, - source.as_deref(), &sql, &target_table, returning, @@ -2824,12 +2759,9 @@ fn handle_request( source, reply, } => { - snapshot_then(snap, batch, conn, source.as_deref(), reply, || do_rebuild_from_text( - conn, - persistence, - source.as_deref(), - &project_path, - )); + snapshot_then(snap, batch, conn, source.as_deref(), reply, || { + do_rebuild_from_text(conn, &project_path) + }); } Request::ExplainPlan { query, reply } => { let _ = reply.send(do_explain_plan(conn, &query)); @@ -3063,11 +2995,6 @@ struct Changes { fn finalize_persistence( conn: &Connection, persistence: Option<&Persistence>, - // Vestigial since ADR-0052 (the `history.log` write that used it moved - // to the dispatch layer). Retained so the ~28 worker handlers that - // thread `source` to here keep a use for it, rather than orphaning the - // param across all of them; a later cleanup could unwind that plumbing. - _source: Option<&str>, changes: &Changes, ) -> Result<(), DbError> { let Some(p) = persistence else { @@ -3524,7 +3451,6 @@ pub enum CreateIndexOutcome { fn do_create_table( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, name: &str, columns: &[ColumnSpec], primary_key: &[String], @@ -3708,7 +3634,7 @@ fn do_create_table( rewritten_tables: vec![name.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(description) } @@ -3716,7 +3642,6 @@ fn do_create_table( fn do_drop_table( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, name: &str, ) -> Result<(), DbError> { debug!(table = %name, "drop_table"); @@ -3768,7 +3693,7 @@ fn do_drop_table( rewritten_tables: Vec::new(), deleted_tables: vec![name.to_string()], }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(()) } @@ -3795,7 +3720,6 @@ fn do_drop_table( fn do_add_column( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &ColumnSpec, ) -> Result { @@ -3826,7 +3750,7 @@ fn do_add_column( column.name, ))); } - return do_add_auto_generated_column(conn, persistence, source, table, column); + return do_add_auto_generated_column(conn, persistence, table, column); } // SQLite's `ALTER TABLE ADD COLUMN` cannot express `UNIQUE` // or `CHECK`, and a `NOT NULL` column added that way must @@ -3839,9 +3763,9 @@ fn do_add_column( || column.check_sql.is_some() || (column.not_null && column.default.is_none() && column.default_sql.is_none()) { - do_add_constrained_column_via_rebuild(conn, persistence, source, table, column) + do_add_constrained_column_via_rebuild(conn, persistence, table, column) } else { - do_add_plain_column(conn, persistence, source, table, column) + do_add_plain_column(conn, persistence, table, column) } } @@ -3849,7 +3773,6 @@ fn do_add_column( fn do_add_plain_column( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, spec: &ColumnSpec, ) -> Result { @@ -3886,7 +3809,7 @@ fn do_add_plain_column( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(AddColumnResult { description, @@ -3902,7 +3825,6 @@ fn do_add_plain_column( fn do_add_auto_generated_column( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, spec: &ColumnSpec, ) -> Result { @@ -4009,7 +3931,7 @@ fn do_add_auto_generated_column( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -4034,7 +3956,6 @@ fn do_add_auto_generated_column( fn do_add_constrained_column_via_rebuild( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, spec: &ColumnSpec, ) -> Result { @@ -4109,7 +4030,7 @@ fn do_add_constrained_column_via_rebuild( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -4135,7 +4056,6 @@ fn do_add_constrained_column_via_rebuild( fn do_add_constraint( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, constraint: &Constraint, @@ -4262,7 +4182,7 @@ fn do_add_constraint( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -4278,7 +4198,6 @@ fn do_add_constraint( fn do_drop_constraint( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, kind: ConstraintKind, @@ -4362,7 +4281,7 @@ fn do_drop_constraint( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -4381,7 +4300,6 @@ fn do_drop_constraint( fn do_set_column_default( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, default_sql: &str, @@ -4429,7 +4347,7 @@ fn do_set_column_default( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -4771,7 +4689,6 @@ fn format_auto_fill_add_note(ty: Type, row_count: usize) -> String { fn do_drop_column( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, cascade: bool, @@ -4913,7 +4830,7 @@ fn do_drop_column( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(DropColumnResult { description, @@ -4931,7 +4848,6 @@ fn do_drop_column( fn do_rename_column( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, old: &str, new: &str, @@ -5023,7 +4939,7 @@ fn do_rename_column( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(description) } @@ -5055,7 +4971,6 @@ fn do_rename_column( fn do_rename_table( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, old: &str, new: &str, ) -> Result { @@ -5201,7 +5116,7 @@ fn do_rename_table( rewritten_tables: vec![new.to_string()], deleted_tables: vec![old.to_string()], }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(description) } @@ -5242,7 +5157,6 @@ fn do_rename_table( fn do_change_column_type( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, ty: Type, @@ -5360,7 +5274,7 @@ fn do_change_column_type( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) }; @@ -7445,7 +7359,6 @@ fn resolve_create_table_fks( fn do_create_m2n_relationship( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, t1: &str, t2: &str, name: Option<&str>, @@ -7519,7 +7432,6 @@ fn do_create_m2n_relationship( do_create_table( conn, persistence, - source, &junction, &columns, &primary_key, @@ -7533,7 +7445,6 @@ fn do_create_m2n_relationship( fn do_add_relationship( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, name: Option<&str>, parent_table: &str, parent_columns: &[String], @@ -7688,7 +7599,7 @@ fn do_add_relationship( rewritten_tables: vec![child_table.to_string()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; @@ -7702,7 +7613,6 @@ fn do_add_relationship( fn do_drop_relationship( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, selector: &RelationshipSelector, ) -> Result, DbError> { debug!(selector = ?selector, "drop_relationship"); @@ -7761,7 +7671,7 @@ fn do_drop_relationship( rewritten_tables: vec![child_table_for_persist.clone()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; @@ -7780,7 +7690,6 @@ fn do_drop_relationship( fn do_alter_add_table_check( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, name: Option<&str>, expr_sql: &str, @@ -7873,7 +7782,7 @@ fn do_alter_add_table_check( rewritten_tables: vec![table_owned.clone()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; do_describe_table(conn, table) @@ -7887,7 +7796,6 @@ fn do_alter_add_table_check( fn do_alter_add_unique( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, columns: &[String], ) -> Result { @@ -7942,7 +7850,7 @@ fn do_alter_add_unique( rewritten_tables: vec![table_owned.clone()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; do_describe_table(conn, table) @@ -7955,7 +7863,6 @@ fn do_alter_add_unique( fn do_drop_constraint_by_name( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, name: &str, ) -> Result, DbError> { @@ -7995,7 +7902,7 @@ fn do_drop_constraint_by_name( rewritten_tables: vec![t.clone()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; return Ok(Some(do_describe_table(conn, table)?)); @@ -8014,7 +7921,6 @@ fn do_drop_constraint_by_name( return do_drop_relationship( conn, persistence, - source, &RelationshipSelector::Named { name: name.to_string(), }, @@ -8054,7 +7960,7 @@ fn do_drop_constraint_by_name( rewritten_tables: vec![table_owned.clone()], ..Changes::default() }; - finalize_persistence(tx, persistence, source, &changes)?; + finalize_persistence(tx, persistence, &changes)?; Ok(()) })?; return Ok(Some(do_describe_table(conn, table)?)); @@ -8076,7 +7982,6 @@ fn do_drop_constraint_by_name( fn do_alter_add_foreign_key( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, child_table: &str, name: Option<&str>, fk: &SqlForeignKey, @@ -8118,7 +8023,6 @@ fn do_alter_add_foreign_key( do_add_relationship( conn, persistence, - source, name, &fk.parent_table, &parent_columns, @@ -8187,7 +8091,6 @@ fn index_exists(conn: &Connection, name: &str, user_only: bool) -> Result, - source: Option<&str>, name: Option<&str>, table: &str, columns: &[String], @@ -8269,7 +8172,7 @@ fn do_add_index( schema_dirty: true, ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(description) } @@ -8279,7 +8182,6 @@ fn do_add_index( fn do_drop_index( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, selector: &IndexSelector, ) -> Result { debug!(selector = ?selector, "drop_index"); @@ -8348,28 +8250,14 @@ fn do_drop_index( schema_dirty: true, ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(description) } -/// Read-only wrapper around `do_describe_table` that runs an -/// auxiliary `history.log` append for user-issued -/// `show table` commands. -// ADR-0052: journaling moved to the dispatch layer, so this read-only -// `show table` wrapper no longer appends to `history.log` — the spawn -// journals the `Ok` outcome. Kept as a thin delegate (a later cleanup -// could inline `do_describe_table` at the one call site); `_persistence` -// / `_source` are vestigial. -fn do_describe_table_request( - conn: &Connection, - _persistence: Option<&Persistence>, - _source: Option<&str>, - name: &str, -) -> Result { - do_describe_table(conn, name) -} - +/// Reads a table's user-facing structure (`show table` / `describe`). +/// ADR-0052: journaling moved to the dispatch layer, so this read does +/// not touch `history.log` — the spawn journals the `Ok` outcome. fn do_describe_table(conn: &Connection, name: &str) -> Result { debug!(name = %name, "describe_table"); // Column info — including the ADR-0029 constraints — comes @@ -8846,11 +8734,9 @@ fn sample_parent_key_tuples( /// form 2). `overrides` carries the `set …` clause (D2): per-column /// pins that replace the heuristic generator and drop the column from the /// generic-fill advisory (D13). -#[allow(clippy::too_many_arguments)] fn do_seed( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, target_column: Option<&str>, count: Option, @@ -8866,7 +8752,7 @@ fn do_seed( // Column-fill (D1 form 2) is a distinct UPDATE path. if let Some(col) = target_column { return do_seed_column_fill( - conn, persistence, source, table, col, count, overrides, rng_seed, + conn, persistence, table, col, count, overrides, rng_seed, ); } @@ -9149,7 +9035,7 @@ fn do_seed( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; let data = if preview_rowids.is_empty() { @@ -9330,7 +9216,6 @@ fn seed_override_literal(value: &Value, column: &str) -> Result fn do_seed_column_fill( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, column: &str, count: Option, @@ -9584,7 +9469,7 @@ fn do_seed_column_fill( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; // Preview the first capped rows (D18). @@ -9722,7 +9607,6 @@ fn insert_one_row( fn do_insert( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, user_columns: Option<&[String]>, user_values: &[Value], @@ -9742,7 +9626,7 @@ fn do_insert( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(InsertResult { rows_affected, data }) } @@ -9786,7 +9670,6 @@ fn build_update_sql( fn do_update( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, assignments: &[(String, Value)], filter: &RowFilter, @@ -9839,7 +9722,7 @@ fn do_update( rewritten_tables: vec![table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(UpdateResult { rows_affected, @@ -9887,7 +9770,6 @@ fn build_delete_sql( fn do_delete( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, table: &str, filter: &RowFilter, ) -> Result { @@ -9959,7 +9841,7 @@ fn do_delete( rewritten_tables, ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(DeleteResult { @@ -9976,34 +9858,6 @@ fn do_delete( }) } -/// Read-only `show data` wrapper. ADR-0052: journaling moved to the -/// dispatch layer (`_persistence` / `_source` vestigial). -fn do_query_data_request( - conn: &Connection, - _persistence: Option<&Persistence>, - _source: Option<&str>, - table: &str, - filter: Option<&Expr>, - limit: Option, -) -> Result { - // ADR-0052: journaling moved to the dispatch layer (`_persistence` / - // `_source` vestigial; the spawn journals the `Ok` outcome). - do_query_data(conn, table, filter, limit) -} - -/// Worker handler for `Request::RunSelect` (ADR-0030 §6, ADR-0031). -/// ADR-0052: journaling moved to the dispatch layer, so this no longer -/// appends to `history.log` — the spawn journals the literal line so a -/// replay re-runs it (ADR-0030 §11). -fn do_run_select_request( - conn: &Connection, - _persistence: Option<&Persistence>, - _source: Option<&str>, - sql: &str, -) -> Result { - do_run_select(conn, sql) -} - /// Currently-stored non-NULL values of one column, for shortid /// collision-avoidance (passed to `generate_shortid_batch`). fn existing_shortids( @@ -10251,7 +10105,6 @@ fn plan_autogen_autofill( fn do_sql_insert( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, sql: &str, target_table: &str, listed_columns: &[String], @@ -10341,7 +10194,7 @@ fn do_sql_insert( rewritten_tables: vec![target_table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(InsertResult { rows_affected, @@ -10370,7 +10223,6 @@ fn do_sql_insert( fn do_sql_update( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, sql: &str, target_table: &str, returning: bool, @@ -10423,7 +10275,7 @@ fn do_sql_update( rewritten_tables: vec![target_table.to_string()], ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(UpdateResult { rows_affected, data }) } @@ -10461,7 +10313,6 @@ fn do_sql_update( fn do_sql_delete( conn: &Connection, persistence: Option<&Persistence>, - source: Option<&str>, sql: &str, target_table: &str, returning: bool, @@ -10542,7 +10393,7 @@ fn do_sql_delete( rewritten_tables, ..Changes::default() }; - finalize_persistence(conn, persistence, source, &changes)?; + finalize_persistence(conn, persistence, &changes)?; tx.commit().map_err(DbError::from_rusqlite)?; Ok(DeleteResult { @@ -11104,14 +10955,7 @@ fn read_relationships_inbound( /// the end (regardless of success). A `foreign_key_check` /// before commit verifies the loaded data is consistent — any /// violation aborts with a fatal error. -fn do_rebuild_from_text( - conn: &Connection, - // Vestigial since ADR-0052: `rebuild` is journalled at the dispatch - // layer (`spawn_rebuild`), not here. - _persistence: Option<&Persistence>, - _source: Option<&str>, - project_path: &Path, -) -> Result<(), DbError> { +fn do_rebuild_from_text(conn: &Connection, project_path: &Path) -> Result<(), DbError> { debug!(path = %project_path.display(), "rebuild_from_text"); let yaml_path = project_path.join(PROJECT_YAML); let data_dir = project_path.join(DATA_DIR); @@ -11706,7 +11550,7 @@ mod tests { .await .unwrap(); } - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); let id_col = desc.columns.iter().find(|c| c.name == "id").unwrap(); assert_eq!(id_col.user_type, Some(Type::Serial)); for ty in [Type::Date, Type::DateTime, Type::Decimal, Type::ShortId] { @@ -11737,7 +11581,7 @@ mod tests { None) .await .unwrap(); - let before = db.describe_table("T".to_string(), None).await.unwrap(); + let before = db.describe_table("T".to_string()).await.unwrap(); assert_eq!(before.columns[0].user_type, Some(Type::Date)); // Drop it. @@ -11754,7 +11598,7 @@ mod tests { None) .await .unwrap(); - let after = db.describe_table("T".to_string(), None).await.unwrap(); + let after = db.describe_table("T".to_string()).await.unwrap(); assert_eq!(after.columns[0].user_type, Some(Type::DateTime)); } @@ -11768,7 +11612,7 @@ mod tests { .await .unwrap_or_else(|e| panic!("type {ty} failed: {e}")); } - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); // 5 user columns + the id PK column. assert_eq!(desc.columns.len(), 6); } @@ -11842,7 +11686,7 @@ mod tests { result.client_side_notes ); // Verify the column is populated 1..3. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let seq_idx = data.columns.iter().position(|c| c == "seq").unwrap(); let mut filled: Vec = data .rows @@ -11875,7 +11719,7 @@ mod tests { result.client_side_notes ); // Verify each row has a non-null shortid value. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let tag_idx = data.columns.iter().position(|c| c == "tag").unwrap(); for row in &data.rows { let v = row[tag_idx].as_ref().expect("non-null shortid auto-filled"); @@ -11908,7 +11752,7 @@ mod tests { .await .unwrap(); } - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let seq_idx = data.columns.iter().position(|c| c == "seq").unwrap(); let mut values: Vec = data .rows @@ -11947,7 +11791,7 @@ mod tests { ) .await .unwrap(); - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let seq_idx = data.columns.iter().position(|c| c == "seq").unwrap(); let mut values: Vec = data .rows @@ -12062,7 +11906,7 @@ mod tests { // Row data still accessible (id was preserved); the // dropped column is gone from the projection. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); assert_eq!(data.columns, vec!["id".to_string()]); assert_eq!(data.rows.len(), 1); } @@ -12473,7 +12317,7 @@ mod tests { .await .unwrap(); let orders = db - .describe_table("Orders".to_string(), None) + .describe_table("Orders".to_string()) .await .unwrap(); let outbound = orders @@ -12488,7 +12332,7 @@ mod tests { // Same from the parent perspective via inbound. let customers = db - .describe_table("Customers".to_string(), None) + .describe_table("Customers".to_string()) .await .unwrap(); let inbound = customers @@ -12576,7 +12420,7 @@ mod tests { assert_eq!(note.transformed, 3); assert_eq!(note.lossy, 0); // Data preserved via the per-cell transformer. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); assert_eq!(data.rows.len(), 3); } @@ -12857,7 +12701,7 @@ mod tests { result.client_side ); // Data preserved. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); assert_eq!(data.rows.len(), 3); } @@ -13267,7 +13111,7 @@ mod tests { assert_eq!(note.auto_fill_kind, Some(AutoFillKind::Serial)); // Confirm the filled values: existing 5, fills are 6 // and 7 (continue sequence from MAX+1). - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let code_idx = data.columns.iter().position(|c| c == "code").unwrap(); let mut values: Vec = data .rows @@ -13325,7 +13169,7 @@ mod tests { assert_eq!(note.auto_filled, 2); assert_eq!(note.auto_fill_kind, Some(AutoFillKind::ShortId)); // All three rows now have valid shortids. - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); let tag_idx = data.columns.iter().position(|c| c == "tag").unwrap(); for row in &data.rows { let v = row[tag_idx].as_ref().expect("non-null shortid after fill"); @@ -13392,7 +13236,7 @@ mod tests { #[tokio::test] async fn describe_missing_table_returns_no_such_table() { let db = db(); - let err = db.describe_table("Ghost".to_string(), None).await.unwrap_err(); + let err = db.describe_table("Ghost".to_string()).await.unwrap_err(); match err { DbError::Sqlite { kind, .. } => assert_eq!(kind, SqliteErrorKind::NoSuchTable), other => panic!("unexpected error: {other:?}"), @@ -13437,7 +13281,7 @@ mod tests { None) .await .unwrap(); - let orders = db.describe_table("Orders".to_string(), None).await.unwrap(); + let orders = db.describe_table("Orders".to_string()).await.unwrap(); assert_eq!(orders.outbound_relationships.len(), 1); let rel = &orders.outbound_relationships[0]; assert_eq!(rel.local_columns, vec!["CustId".to_string()]); @@ -13462,7 +13306,7 @@ mod tests { None) .await .unwrap(); - let customers = db.describe_table("Customers".to_string(), None).await.unwrap(); + let customers = db.describe_table("Customers".to_string()).await.unwrap(); assert_eq!(customers.inbound_relationships.len(), 1); let rel = &customers.inbound_relationships[0]; assert_eq!(rel.local_columns, vec!["id".to_string()]); @@ -13486,7 +13330,7 @@ mod tests { None) .await .unwrap(); - let orders = db.describe_table("Orders".to_string(), None).await.unwrap(); + let orders = db.describe_table("Orders".to_string()).await.unwrap(); let rel = &orders.outbound_relationships[0]; assert_eq!(rel.name, "cust_orders"); assert_eq!(rel.on_delete, ReferentialAction::Cascade); @@ -13525,7 +13369,7 @@ mod tests { ) .await .unwrap(); - let orders = db.describe_table("Orders".to_string(), None).await.unwrap(); + let orders = db.describe_table("Orders".to_string()).await.unwrap(); // The auto-created FK column has user_type Int (Serial's // fk_target_type), not Serial. let cust = orders @@ -13675,8 +13519,8 @@ mod tests { }, None) .await .unwrap(); - let orders = db.describe_table("Orders".to_string(), None).await.unwrap(); - let customers = db.describe_table("Customers".to_string(), None).await.unwrap(); + let orders = db.describe_table("Orders".to_string()).await.unwrap(); + let customers = db.describe_table("Customers".to_string()).await.unwrap(); assert!(orders.outbound_relationships.is_empty()); assert!(customers.inbound_relationships.is_empty()); } @@ -13705,7 +13549,7 @@ mod tests { }, None) .await .unwrap(); - let orders = db.describe_table("Orders".to_string(), None).await.unwrap(); + let orders = db.describe_table("Orders".to_string()).await.unwrap(); assert!(orders.outbound_relationships.is_empty()); } @@ -13753,7 +13597,7 @@ mod tests { // Dropping the child is allowed (no inbound relationships // on Orders) and cleans the metadata. db.drop_table("Orders".to_string(), None).await.unwrap(); - let customers = db.describe_table("Customers".to_string(), None).await.unwrap(); + let customers = db.describe_table("Customers".to_string()).await.unwrap(); assert!(customers.inbound_relationships.is_empty()); } @@ -13819,7 +13663,7 @@ mod tests { // After the rebuild, the original columns are still // present with the right user types, and any extra // metadata (Name on Customers) survives. - let customers = db.describe_table("Customers".to_string(), None).await.unwrap(); + let customers = db.describe_table("Customers".to_string()).await.unwrap(); let names: Vec<&str> = customers.columns.iter().map(|c| c.name.as_str()).collect(); assert_eq!(names, vec!["id", "Name"]); let name_col = customers.columns.iter().find(|c| c.name == "Name").unwrap(); @@ -13854,7 +13698,7 @@ mod tests { // The InsertResult itself carries the just-inserted row. assert_eq!(result.data.rows.len(), 1); assert_eq!(result.data.rows[0][1], Some("Alice".to_string())); - let data = db.query_data("Customers".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Customers".to_string(), None, None).await.unwrap(); assert_eq!(data.columns, vec!["id".to_string(), "Name".to_string()]); assert_eq!(data.rows.len(), 1); assert_eq!(data.rows[0][1], Some("Alice".to_string())); @@ -13879,7 +13723,7 @@ mod tests { None) .await .unwrap(); - let data = db.query_data("Tags".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Tags".to_string(), None, None).await.unwrap(); let id = data.rows[0][0].as_ref().expect("auto-generated id"); assert!( id.len() >= 10 && id.len() <= 12, @@ -13898,7 +13742,7 @@ mod tests { None) .await .unwrap(); - let data = db.query_data("Customers".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Customers".to_string(), None, None).await.unwrap(); assert_eq!(data.rows[0][0], Some("99".to_string())); assert_eq!(data.rows[0][1], Some("Bob".to_string())); } @@ -13944,7 +13788,7 @@ mod tests { // The UpdateResult contains only the updated rows. assert_eq!(result.data.rows.len(), 1); assert_eq!(result.data.rows[0][1], Some("Alicia".to_string())); - let data = db.query_data("Customers".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Customers".to_string(), None, None).await.unwrap(); assert_eq!(data.rows[0][1], Some("Alicia".to_string())); assert_eq!(data.rows[1][1], Some("Bob".to_string())); } @@ -14040,7 +13884,7 @@ mod tests { // Carol (45/true) and Dave (35/true) match; Bob (35) is // inactive, Alice (25) is too young. assert_eq!(result.rows_affected, 2); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Alice", "Bob"]); } @@ -14057,7 +13901,7 @@ mod tests { .await .unwrap(); assert_eq!(result.rows_affected, 2); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Bob", "Dave"]); } @@ -14075,7 +13919,7 @@ mod tests { .await .unwrap(); assert_eq!(result.rows_affected, 2); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Bob", "Dave"]); } @@ -14093,7 +13937,7 @@ mod tests { .unwrap(); // Bob (35) and Dave (35) are in range. assert_eq!(result.rows_affected, 2); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Alice", "Carol"]); } @@ -14112,7 +13956,7 @@ mod tests { .await .unwrap(); assert_eq!(result.rows_affected, 2); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Bob", "Dave"]); } @@ -14129,7 +13973,7 @@ mod tests { .await .unwrap(); assert_eq!(result.rows_affected, 1, "only Alice matches `A%`"); - let data = db.query_data("People".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("People".to_string(), None, None).await.unwrap(); assert_eq!(names(&data), vec!["Bob", "Carol", "Dave"]); } @@ -14160,7 +14004,7 @@ mod tests { people_table(&db).await; let (filter, limit) = parse_show("show data People where Active = true"); let data = db - .query_data("People".to_string(), filter, limit, None) + .query_data("People".to_string(), filter, limit) .await .unwrap(); assert_eq!(names(&data), vec!["Alice", "Carol", "Dave"]); @@ -14172,7 +14016,7 @@ mod tests { people_table(&db).await; let (filter, limit) = parse_show("show data People limit 2"); let data = db - .query_data("People".to_string(), filter, limit, None) + .query_data("People".to_string(), filter, limit) .await .unwrap(); // `limit` implies an ORDER BY the primary key, so this @@ -14187,7 +14031,7 @@ mod tests { let (filter, limit) = parse_show("show data People where Age >= 35 limit 1"); let data = db - .query_data("People".to_string(), filter, limit, None) + .query_data("People".to_string(), filter, limit) .await .unwrap(); // Three rows match `Age >= 35` (Bob, Carol, Dave); the @@ -14264,7 +14108,7 @@ mod tests { assert!(!plan.rows.is_empty()); // ADR-0028 §1: EXPLAIN QUERY PLAN never executes. let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); assert_eq!(data.rows.len(), 4, "explain delete must not delete"); @@ -14281,7 +14125,7 @@ mod tests { .unwrap(); let (filter, _) = parse_show("show data People where Active = true"); let data = db - .query_data("People".to_string(), filter, None, None) + .query_data("People".to_string(), filter, None) .await .unwrap(); // Alice, Carol, Dave are still active — nothing ran. @@ -14410,7 +14254,7 @@ mod tests { .await .unwrap(); let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); assert_eq!(data.rows.len(), 4, "explain delete must not delete"); @@ -14426,7 +14270,7 @@ mod tests { .await .unwrap(); let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); assert!( @@ -14462,7 +14306,7 @@ mod tests { .await .unwrap(); let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); assert_eq!(data.rows.len(), 4, "explain insert must not insert"); @@ -14486,7 +14330,7 @@ mod tests { plan.rows, ); let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); assert_eq!(data.rows.len(), 4, "explain insert-select must not insert"); @@ -14622,7 +14466,7 @@ mod tests { .await .unwrap(); let data = db - .query_data("T".to_string(), None, None, None) + .query_data("T".to_string(), None, None) .await .unwrap(); let tier_idx = data.columns.iter().position(|c| c == "tier").unwrap(); @@ -14685,7 +14529,7 @@ mod tests { ) .await .unwrap(); - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); let email = desc.columns.iter().find(|c| c.name == "email").unwrap(); assert!(email.notnull && email.unique, "email keeps NOT NULL + UNIQUE"); let tier = desc.columns.iter().find(|c| c.name == "tier").unwrap(); @@ -14710,7 +14554,7 @@ mod tests { .await .unwrap(); let data = db - .query_data("People".to_string(), None, None, None) + .query_data("People".to_string(), None, None) .await .unwrap(); let idx = data.columns.iter().position(|c| c == "tier").unwrap(); @@ -14755,7 +14599,7 @@ mod tests { ) .await .expect("NOT NULL with no default is fine on an empty table"); - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); assert!(desc.columns.iter().find(|c| c.name == "x").unwrap().notnull); } @@ -14770,7 +14614,7 @@ mod tests { ) .await .unwrap(); - let desc = db.describe_table("People".to_string(), None).await.unwrap(); + let desc = db.describe_table("People".to_string()).await.unwrap(); let tier = desc.columns.iter().find(|c| c.name == "tier").unwrap(); assert!(tier.notnull); assert_eq!(tier.default.as_deref(), Some("0")); @@ -14787,7 +14631,7 @@ mod tests { ) .await .expect("a UNIQUE column with no default is fine — NULLs do not collide"); - let desc = db.describe_table("People".to_string(), None).await.unwrap(); + let desc = db.describe_table("People".to_string()).await.unwrap(); assert!(desc.columns.iter().find(|c| c.name == "badge").unwrap().unique); } @@ -14878,7 +14722,7 @@ mod tests { let (n, c, pk) = parse_create("create table T with pk age(int) check (age >= 0)"); db.create_table(n, c, pk, None).await.unwrap(); - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); let age = desc.columns.iter().find(|c| c.name == "age").unwrap(); let check = age.check.as_deref().expect("age carries a CHECK"); assert!( @@ -14898,7 +14742,7 @@ mod tests { ) .await .expect("a CHECK column adds via the rebuild path"); - let desc = db.describe_table("People".to_string(), None).await.unwrap(); + let desc = db.describe_table("People".to_string()).await.unwrap(); assert!(desc.columns.iter().find(|c| c.name == "score").unwrap().check.is_some()); // An update that violates the check is refused. let bad = db @@ -14932,7 +14776,7 @@ mod tests { ) .await .unwrap(); - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); assert!( desc.columns.iter().find(|c| c.name == "code").unwrap().check.is_some(), "code keeps its CHECK across the rebuild", @@ -15003,7 +14847,7 @@ mod tests { .unwrap(); assert_eq!(result.rows_affected, 1); assert!(result.cascade.is_empty(), "no children to cascade to"); - let data = db.query_data("Customers".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Customers".to_string(), None, None).await.unwrap(); assert_eq!(data.rows.len(), 1); assert_eq!(data.rows[0][1], Some("Bob".to_string())); } @@ -15110,7 +14954,7 @@ mod tests { None) .await .unwrap(); - let orders = db.query_data("Orders".to_string(), None, None, None).await.unwrap(); + let orders = db.query_data("Orders".to_string(), None, None).await.unwrap(); assert!(orders.rows.is_empty(), "child rows should be cascaded"); } @@ -15210,7 +15054,7 @@ mod tests { None) .await .unwrap(); - let data = db.query_data("Flags".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("Flags".to_string(), None, None).await.unwrap(); assert_eq!(data.rows[0][1], Some("true".to_string())); assert_eq!(data.rows[1][1], Some("false".to_string())); } @@ -15232,7 +15076,7 @@ mod tests { None) .await .unwrap(); - let data = db.query_data("T".to_string(), None, None, None).await.unwrap(); + let data = db.query_data("T".to_string(), None, None).await.unwrap(); assert_eq!(data.rows[0][1], None); } @@ -15491,7 +15335,7 @@ mod tests { .await .unwrap(); // Read the schema and confirm `seq` is still unique. - let desc = db.describe_table("T".to_string(), None).await.unwrap(); + let desc = db.describe_table("T".to_string()).await.unwrap(); let seq = desc .columns .iter() @@ -15543,7 +15387,7 @@ mod tests { .unwrap(); let tables = db.list_tables().await.unwrap(); assert_eq!(tables, vec!["Order Lines".to_string()]); - let desc = db.describe_table("Order Lines".to_string(), None).await.unwrap(); + let desc = db.describe_table("Order Lines".to_string()).await.unwrap(); assert_eq!(desc.name, "Order Lines"); } diff --git a/src/runtime.rs b/src/runtime.rs index 0b9667b..ca17a3f 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1190,7 +1190,7 @@ async fn build_schema_cache(database: &Database) -> crate::completion::SchemaCac // miss leaves that table's columns unpopulated and the // walker falls back to the schemaless value-literal list. for name in cache.tables.clone() { - if let Ok(desc) = database.describe_table(name.clone(), None).await { + if let Ok(desc) = database.describe_table(name.clone()).await { // Per-table indexes for the items panel (S2, ADR-0025). // Carry uniqueness so the panel can mark a UNIQUE index // (ADR-0035 §4d). Captured before `desc.columns` is @@ -1650,7 +1650,7 @@ async fn build_show_data_echo( limit: Some(_), .. } => database - .describe_table(name.clone(), None) + .describe_table(name.clone()) .await .map(|desc| { desc.columns @@ -1732,7 +1732,7 @@ async fn collect_echo_lookups( Command::DropIndex { selector: IndexSelector::Columns { table, columns }, } => { - if let Ok(desc) = database.describe_table(table.clone(), None).await + if let Ok(desc) = database.describe_table(table.clone()).await && let Some(idx) = desc.indexes.iter().find(|i| i.columns == *columns) { out.drop_index_name = Some(idx.name.clone()); @@ -1747,7 +1747,7 @@ async fn collect_echo_lookups( child_column, }, } => { - if let Ok(desc) = database.describe_table(child_table.clone(), None).await + if let Ok(desc) = database.describe_table(child_table.clone()).await && let Some(rel) = desc.outbound_relationships.iter().find(|r| { // The Endpoints drop selector is single-column // (ADR-0043 keeps DROP by-endpoints single-column; @@ -1771,7 +1771,7 @@ async fn collect_echo_lookups( // resolver API would be the next step if schemas grow. if let Ok(tables) = database.list_tables().await { for table in tables { - if let Ok(desc) = database.describe_table(table.clone(), None).await + if let Ok(desc) = database.describe_table(table.clone()).await && desc.outbound_relationships.iter().any(|r| r.name == *name) { out.drop_relationship = Some((name.clone(), table.clone())); @@ -1795,8 +1795,8 @@ async fn collect_echo_lookups( // *before* execution to know which `ADD COLUMN` lines to // emit. The parent columns here are the explicit DSL list, // paired positionally with the child list. - let parent_desc = database.describe_table(parent_table.clone(), None).await; - let child_desc = database.describe_table(child_table.clone(), None).await; + let parent_desc = database.describe_table(parent_table.clone()).await; + let child_desc = database.describe_table(child_table.clone()).await; if let (Ok(parent_desc), Ok(child_desc)) = (parent_desc, child_desc) { let mut new_columns: Vec<(String, crate::dsl::types::Type)> = Vec::new(); for (child_col, parent_col) in child_columns.iter().zip(parent_columns) { @@ -2064,7 +2064,7 @@ async fn enrich_check_violation( .await .map(|v| v.to_string()); // The rule itself — the column's compiled CHECK expression. - if let Ok(desc) = database.describe_table(table.to_string(), None).await + if let Ok(desc) = database.describe_table(table.to_string()).await && let Some(col) = desc.columns.iter().find(|c| c.name == column) { facts.check_rule.clone_from(&col.check); @@ -2272,7 +2272,7 @@ async fn user_value_for_column_with_schema( } = command { let desc = database - .describe_table(table.to_string(), None) + .describe_table(table.to_string()) .await .ok()?; // Build the natural-order column list the same way @@ -2311,7 +2311,7 @@ async fn user_value_for_column_with_schema( && literal_rows.len() == 1 { let desc = database - .describe_table(table.to_string(), None) + .describe_table(table.to_string()) .await .ok()?; let idx = desc.columns.iter().position(|c| c.name == column)?; @@ -2930,7 +2930,7 @@ async fn execute_command_typed( .await .map(|d| CommandOutcome::Schema(Some(d))), Command::ShowTable { name } => database - .describe_table(name, src) + .describe_table(name) .await .map(|d| CommandOutcome::Schema(Some(d))), // ADR-0044: a named relationship renders as a diagram (App-side), @@ -2983,14 +2983,14 @@ async fn execute_command_typed( filter, limit, } => database - .query_data(name, filter, limit, src) + .query_data(name, filter, limit) .await .map(CommandOutcome::Query), // A SQL `SELECT` (advanced mode; ADR-0030 §6, ADR-0031). // The grammar walker has already validated `sql` is in // the supported subset; the worker runs it as text. Command::Select { sql } => database - .run_select(sql, src) + .run_select(sql) .await .map(CommandOutcome::Query), // A SQL `INSERT` (advanced mode; ADR-0033 §1). Grammar-as- diff --git a/tests/it/case_insensitive_names.rs b/tests/it/case_insensitive_names.rs index 6b644d6..fe28129 100644 --- a/tests/it/case_insensitive_names.rs +++ b/tests/it/case_insensitive_names.rs @@ -93,7 +93,7 @@ fn rename_column_with_case_variant_table_keeps_metadata_in_step() { .expect("rename column via a case-variant table name"); let desc = r - .block_on(db.describe_table("Items".to_string(), None)) + .block_on(db.describe_table("Items".to_string())) .expect("describe Items"); let amount = desc .columns @@ -126,7 +126,7 @@ fn insert_with_case_variant_table_persists_and_survives_rebuild() { let db = fresh_rebuild(db, &project, &r); let rows = r - .block_on(db.query_data("Items".to_string(), None, None, None)) + .block_on(db.query_data("Items".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 1, "the wrong-case insert survived the rebuild (no data loss)"); @@ -146,7 +146,7 @@ fn add_column_with_case_variant_table_survives_rebuild() { ); let db = fresh_rebuild(db, &project, &r); - let desc = r.block_on(db.describe_table("Items".to_string(), None)).expect("describe"); + let desc = r.block_on(db.describe_table("Items".to_string())).expect("describe"); let qty = desc.columns.iter().find(|c| c.name == "qty").expect("qty added"); assert_eq!(qty.user_type, Some(Type::Int), "qty's user-type survived the rebuild"); // The CHECK is intact too (a negative qty is refused under the real table). @@ -224,12 +224,12 @@ fn add_relationship_with_case_variant_tables_survives_rebuild() { add 1:n relationship from parent.id to child.parent_id\n", ); // The parent's inbound relationship is visible under the stored case. - let p = r.block_on(db.describe_table("Parent".to_string(), None)).expect("describe Parent"); + let p = r.block_on(db.describe_table("Parent".to_string())).expect("describe Parent"); assert_eq!(p.inbound_relationships.len(), 1, "relationship recorded under the stored case"); assert_eq!(p.inbound_relationships[0].other_table, "Child"); let db = fresh_rebuild(db, &project, &r); - let p = r.block_on(db.describe_table("Parent".to_string(), None)).expect("describe Parent"); + let p = r.block_on(db.describe_table("Parent".to_string())).expect("describe Parent"); assert_eq!(p.inbound_relationships.len(), 1, "relationship survived the rebuild"); assert_eq!(p.inbound_relationships[0].other_table, "Child"); } diff --git a/tests/it/compound_fk.rs b/tests/it/compound_fk.rs index 3ca22df..7ab6000 100644 --- a/tests/it/compound_fk.rs +++ b/tests/it/compound_fk.rs @@ -276,7 +276,7 @@ fn compound_fk_declares_enforces_and_round_trips() { ); // describe shows the compound endpoints symmetrically. - let city = db.describe_table("City".to_string(), None).await.unwrap(); + let city = db.describe_table("City".to_string()).await.unwrap(); let outbound = &city.outbound_relationships[0]; assert_eq!( outbound.local_columns, @@ -329,7 +329,7 @@ fn compound_fk_create_fk_makes_both_child_columns() { ) .await .expect("add compound relationship with --create-fk"); - let city = db.describe_table("City".to_string(), None).await.unwrap(); + let city = db.describe_table("City".to_string()).await.unwrap(); for col in ["c_country", "c_code"] { assert!( city.columns.iter().any(|c| c.name == col), @@ -527,7 +527,7 @@ fn compound_fk_survives_rebuild_from_text() { .await; assert!(bad.is_err(), "compound FK still enforced after rebuild from text"); // Endpoints survived the round-trip intact. - let city = db.describe_table("City".to_string(), None).await.unwrap(); + let city = db.describe_table("City".to_string()).await.unwrap(); assert_eq!( city.outbound_relationships[0].other_columns, vec!["country".to_string(), "code".to_string()], @@ -563,7 +563,7 @@ fn compound_fk_undo_removes_the_relationship() { .await .expect("add compound relationship"); assert_eq!( - db.describe_table("City".to_string(), None) + db.describe_table("City".to_string()) .await .unwrap() .outbound_relationships @@ -573,7 +573,7 @@ fn compound_fk_undo_removes_the_relationship() { // One undo step removes the whole relationship (ADR-0013/0006). db.undo().await.unwrap().expect("undo applied"); assert!( - db.describe_table("City".to_string(), None) + db.describe_table("City".to_string()) .await .unwrap() .outbound_relationships diff --git a/tests/it/iteration3_rebuild.rs b/tests/it/iteration3_rebuild.rs index 4361dfb..922811d 100644 --- a/tests/it/iteration3_rebuild.rs +++ b/tests/it/iteration3_rebuild.rs @@ -76,7 +76,7 @@ fn rebuild_restores_schema_only_project() { // Phase 4: confirm Customers exists with the right shape. let desc = rt() - .block_on(async { db.describe_table("Customers".to_string(), None).await }) + .block_on(async { db.describe_table("Customers".to_string()).await }) .expect("describe_table"); assert_eq!(desc.name, "Customers"); let cols: Vec<&str> = desc.columns.iter().map(|c| c.name.as_str()).collect(); @@ -143,7 +143,7 @@ fn rebuild_restores_rows_from_csv() { }); let rows = rt() - .block_on(async { db.query_data("Customers".to_string(), None, None, None).await }) + .block_on(async { db.query_data("Customers".to_string(), None, None).await }) .expect("query_data"); assert_eq!(rows.rows.len(), 2); let names: Vec> = rows.rows.iter().map(|r| r[1].clone()).collect(); @@ -371,7 +371,7 @@ fn rebuild_preserves_created_at_from_yaml() { // Trigger any successful command so project.yaml is // rewritten from the now-rebuilt db state. rt().block_on(async { - db.describe_table("T".to_string(), Some("show table T".to_string())) + db.describe_table("T".to_string()) .await .unwrap(); // describe is read-only; force a rewrite by adding a column. @@ -451,7 +451,7 @@ fn rebuild_restores_indexes() { }); let desc = rt() - .block_on(async { db.describe_table("Customers".to_string(), None).await }) + .block_on(async { db.describe_table("Customers".to_string()).await }) .expect("describe_table"); assert_eq!(desc.indexes.len(), 1, "index should survive rebuild"); assert_eq!(desc.indexes[0].name, "idx_email"); diff --git a/tests/it/iteration4a_rebuild_command.rs b/tests/it/iteration4a_rebuild_command.rs index 8fb6972..ed64a62 100644 --- a/tests/it/iteration4a_rebuild_command.rs +++ b/tests/it/iteration4a_rebuild_command.rs @@ -173,7 +173,7 @@ fn rebuild_against_populated_db_wipes_and_reloads() { .expect("rebuild"); }); let rows = rt() - .block_on(async { db.query_data("Customers".to_string(), None, None, None).await }) + .block_on(async { db.query_data("Customers".to_string(), None, None).await }) .unwrap(); assert_eq!(rows.rows.len(), 1); assert_eq!(rows.rows[0][1].as_deref(), Some("Edna")); diff --git a/tests/it/iteration5_export_import.rs b/tests/it/iteration5_export_import.rs index 09a79fb..62ccee1 100644 --- a/tests/it/iteration5_export_import.rs +++ b/tests/it/iteration5_export_import.rs @@ -362,7 +362,7 @@ fn end_to_end_export_then_import_real_project() { // Round-trip: the inserted row is back. let data_view = rt() - .block_on(async { imported_db.query_data("Customers".to_string(), None, None, None).await }) + .block_on(async { imported_db.query_data("Customers".to_string(), None, None).await }) .expect("query data"); assert_eq!(data_view.rows.len(), 1); // Serial id auto-filled to 1; Name was the inserted value. diff --git a/tests/it/m2n.rs b/tests/it/m2n.rs index 972a8b3..189c37d 100644 --- a/tests/it/m2n.rs +++ b/tests/it/m2n.rs @@ -107,7 +107,7 @@ fn generates_junction_with_compound_pk_and_two_enforced_fks() { assert!(tables.contains(&"Students_Courses".to_string()), "tables: {tables:?}"); // Two FK columns, both part of the compound PK. - let desc = db.describe_table("Students_Courses".to_string(), None).await.unwrap(); + let desc = db.describe_table("Students_Courses".to_string()).await.unwrap(); let cols: Vec<(&str, bool)> = desc.columns.iter().map(|c| (c.name.as_str(), c.primary_key)).collect(); assert_eq!( @@ -191,7 +191,7 @@ fn compound_parent_pk_contributes_one_fk_column_each() { .await .expect("create m:n"); - let desc = db.describe_table("Students_Sections".to_string(), None).await.unwrap(); + let desc = db.describe_table("Students_Sections".to_string()).await.unwrap(); let names: Vec<&str> = desc.columns.iter().map(|c| c.name.as_str()).collect(); assert_eq!(names, vec!["Students_id", "Sections_course_id", "Sections_term"]); // All three form the compound PK. @@ -221,7 +221,7 @@ fn deleting_a_parent_cascades_to_the_junction() { // Deleting the student cascades to the junction (ON DELETE CASCADE). db.delete("Students".to_string(), RowFilter::AllRows, None).await.unwrap(); - let rows = db.query_data("Students_Courses".to_string(), None, None, None).await.unwrap(); + let rows = db.query_data("Students_Courses".to_string(), None, None).await.unwrap(); assert!(rows.rows.is_empty(), "junction rows should cascade-delete, got {:?}", rows.rows); }); } @@ -249,7 +249,7 @@ fn create_m2n_is_one_undo_step() { let tables = db.list_tables().await.unwrap(); assert!(!tables.contains(&"Students_Courses".to_string()), "undo should remove the junction: {tables:?}"); // The parents' relationships are gone too (the junction held them). - let students = db.describe_table("Students".to_string(), None).await.unwrap(); + let students = db.describe_table("Students".to_string()).await.unwrap(); assert!(students.inbound_relationships.is_empty(), "no leftover relationship after undo"); }); } @@ -321,7 +321,7 @@ fn the_junction_can_be_renamed() { assert!(tables.contains(&"Enrollments".to_string()), "tables: {tables:?}"); assert!(!tables.contains(&"Students_Courses".to_string())); // Both relationships survive the rename (rebuild-preserving). - let desc = db.describe_table("Enrollments".to_string(), None).await.unwrap(); + let desc = db.describe_table("Enrollments".to_string()).await.unwrap(); assert_eq!(desc.outbound_relationships.len(), 2, "FKs preserved across rename"); }); } @@ -362,7 +362,7 @@ fn junction_survives_save_and_rebuild() { db.rebuild_from_text(project.path().to_path_buf(), None).await.expect("rebuild"); let tables = db.list_tables().await.unwrap(); assert!(tables.contains(&"Students_Courses".to_string()), "junction survived: {tables:?}"); - let desc = db.describe_table("Students_Courses".to_string(), None).await.unwrap(); + let desc = db.describe_table("Students_Courses".to_string()).await.unwrap(); assert_eq!(desc.outbound_relationships.len(), 2, "both FKs reconstructed"); assert!(desc.columns.iter().all(|c| c.primary_key), "compound PK reconstructed"); }); diff --git a/tests/it/replay_command.rs b/tests/it/replay_command.rs index d003ebf..d5ccb33 100644 --- a/tests/it/replay_command.rs +++ b/tests/it/replay_command.rs @@ -108,13 +108,13 @@ fn replay_runs_advanced_sql_create_table_as_a_write() { // The SQL DDL line actually created the structural table… let desc = rt() - .block_on(async { db.describe_table("Widget".to_string(), None).await }) + .block_on(async { db.describe_table("Widget".to_string()).await }) .expect("describe"); let names: Vec = desc.columns.iter().map(|c| c.name.clone()).collect(); assert_eq!(names, vec!["id".to_string(), "name".to_string()]); // …and the following insert (serial id auto-filled) ran against it. let rows = rt() - .block_on(async { db.query_data("Widget".to_string(), None, None, None).await }) + .block_on(async { db.query_data("Widget".to_string(), None, None).await }) .expect("query") .rows; assert_eq!(rows.len(), 1); @@ -139,7 +139,7 @@ fn replay_three_lines_dispatches_three_commands() { // The dispatched commands actually mutated state. let data_result = rt() - .block_on(async { db.query_data("T".to_string(), None, None, None).await }) + .block_on(async { db.query_data("T".to_string(), None, None).await }) .expect("query_data"); assert_eq!(data_result.rows.len(), 1, "row inserted"); assert_eq!(data_result.rows[0][1].as_deref(), Some("Alice")); @@ -174,7 +174,7 @@ fn replay_of_actual_history_log_runs_ok_commands_and_skips_err() { assert_completed(&events, 3); let data_result = rt() - .block_on(async { db.query_data("T".to_string(), None, None, None).await }) + .block_on(async { db.query_data("T".to_string(), None, None).await }) .expect("query_data"); assert_eq!(data_result.rows.len(), 1, "only the ok INSERT applied"); assert_eq!(data_result.rows[0][1].as_deref(), Some("alpha")); @@ -227,7 +227,7 @@ fn replay_skips_app_lifecycle_commands_silently() { other => panic!("expected ReplayCompleted, got {other:?}"), } let data_result = rt() - .block_on(async { db.query_data("T".to_string(), None, None, None).await }) + .block_on(async { db.query_data("T".to_string(), None, None).await }) .expect("query_data"); assert!( data_result.columns.iter().any(|c| c == "v"), @@ -401,14 +401,14 @@ fn replay_aborts_on_first_parse_failure_and_reports_line() { // but earlier commands stayed applied (table T exists with // the `name` column). let desc = rt() - .block_on(async { db.describe_table("T".to_string(), None).await }) + .block_on(async { db.describe_table("T".to_string()).await }) .expect("describe_table"); assert!( desc.columns.iter().any(|c| c.name == "name"), "earlier add column should have stayed applied" ); let data_result = rt() - .block_on(async { db.query_data("T".to_string(), None, None, None).await }) + .block_on(async { db.query_data("T".to_string(), None, None).await }) .expect("query_data"); assert!( data_result.rows.is_empty(), @@ -467,7 +467,7 @@ fn replay_rejects_wrong_type_value_in_a_hand_built_script() { // The earlier two lines stayed applied; the failing insert // did not run — state is intact. let data_result = rt() - .block_on(async { db.query_data("T".to_string(), None, None, None).await }) + .block_on(async { db.query_data("T".to_string(), None, None).await }) .expect("query_data"); assert!( data_result.rows.is_empty(), @@ -527,7 +527,7 @@ fn replay_skips_nested_replay_with_a_warning() { other => panic!("expected ReplayCompleted (nested replay skipped), got {other:?}"), } // The nested file's table was NOT created (the replay was skipped). - let cols = rt().block_on(async { db.query_data("T".to_string(), None, None, None).await }); + let cols = rt().block_on(async { db.query_data("T".to_string(), None, None).await }); assert!(cols.is_err(), "inner.commands' table T must not exist (nested replay skipped)"); } diff --git a/tests/it/show_list.rs b/tests/it/show_list.rs index f3750e7..a5f9c69 100644 --- a/tests/it/show_list.rs +++ b/tests/it/show_list.rs @@ -462,7 +462,7 @@ fn app_show_table_renders_relationships_as_compact_diagrams() { rt.block_on(seed_schema(&db)); // Orders holds the FK to Customers — an outbound relationship. let desc = rt - .block_on(db.describe_table("Orders".to_string(), None)) + .block_on(db.describe_table("Orders".to_string())) .expect("describe Orders"); let mut app = App::new(); diff --git a/tests/it/sql_alter_table.rs b/tests/it/sql_alter_table.rs index 70c1a97..401b097 100644 --- a/tests/it/sql_alter_table.rs +++ b/tests/it/sql_alter_table.rs @@ -111,7 +111,7 @@ fn e2e_alter_drop_compound_primary_key_member_is_refused() { /// The current user-facing type of column `name` in table `T`. fn col_type(db: &Database, r: &tokio::runtime::Runtime, name: &str) -> Option { - r.block_on(db.describe_table("T".to_string(), None)) + r.block_on(db.describe_table("T".to_string())) .expect("describe") .columns .into_iter() @@ -120,7 +120,7 @@ fn col_type(db: &Database, r: &tokio::runtime::Runtime, name: &str) -> Option Vec { - r.block_on(db.describe_table("T".to_string(), None)) + r.block_on(db.describe_table("T".to_string())) .expect("describe") .columns .into_iter() @@ -163,7 +163,7 @@ fn e2e_alter_table_add_rename_drop_and_raw_default_check() { // The DEFAULT backfilled the pre-existing row to qty = 0. let rows = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 1); @@ -252,7 +252,7 @@ fn e2e_alter_column_type_clean_and_lossy_convert() { } let rows = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 1); @@ -292,7 +292,7 @@ fn e2e_alter_column_type_int_to_serial_is_allowed() { } assert_eq!(col_type(&db, &r, "n"), Some(Type::Serial), "int→serial converted the column"); let rows = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows[0][1].as_deref(), Some("100"), "the existing value is preserved"); @@ -635,7 +635,7 @@ fn e2e_drop_composite_unique_is_one_undo_step() { .expect("write"); r.block_on(run_replay(&db, project.path(), "u.commands")); let has_unique = || { - !r.block_on(db.describe_table("T".to_string(), None)) + !r.block_on(db.describe_table("T".to_string())) .expect("describe") .unique_constraints .is_empty() @@ -878,7 +878,7 @@ fn e2e_describe_shows_table_level_constraints() { "events: {events:?}" ); - let desc = r.block_on(db.describe_table("T".to_string(), None)).expect("describe"); + let desc = r.block_on(db.describe_table("T".to_string())).expect("describe"); assert_eq!( desc.unique_constraints, vec![vec!["a".to_string(), "b".to_string()]], @@ -976,7 +976,7 @@ fn e2e_rename_table_with_rows_csv_follows_and_survives_rebuild() { assert!(!csv_path(&project, "Orders").exists(), "data/Orders.csv removed"); let rows = r - .block_on(db.query_data("Purchases".to_string(), None, None, None)) + .block_on(db.query_data("Purchases".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 2); @@ -991,7 +991,7 @@ fn e2e_rename_table_with_rows_csv_follows_and_survives_rebuild() { "Purchases round-tripped through a fresh rebuild: {tables:?}" ); let rows = r - .block_on(db.query_data("Purchases".to_string(), None, None, None)) + .block_on(db.query_data("Purchases".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 2); @@ -1077,7 +1077,7 @@ fn e2e_rename_fk_parent_updates_metadata_and_still_enforces() { ); // The child's outbound relationship now points at the new parent name. - let c = r.block_on(db.describe_table("C".to_string(), None)).expect("describe C"); + let c = r.block_on(db.describe_table("C".to_string())).expect("describe C"); assert_eq!(c.outbound_relationships.len(), 1); assert_eq!(c.outbound_relationships[0].other_table, "Parent"); @@ -1129,7 +1129,7 @@ fn e2e_rename_fk_child_updates_metadata_and_still_enforces() { ); // The parent's inbound relationship now names the renamed child. - let p = r.block_on(db.describe_table("P".to_string(), None)).expect("describe P"); + let p = r.block_on(db.describe_table("P".to_string())).expect("describe P"); assert_eq!(p.inbound_relationships.len(), 1); assert_eq!(p.inbound_relationships[0].other_table, "Child"); @@ -1168,7 +1168,7 @@ fn e2e_rename_self_referential_table_updates_both_ends() { ); // Both ends of the self-reference now name `Tree`. - let t = r.block_on(db.describe_table("Tree".to_string(), None)).expect("describe Tree"); + let t = r.block_on(db.describe_table("Tree".to_string())).expect("describe Tree"); assert_eq!(t.outbound_relationships[0].other_table, "Tree"); assert_eq!(t.inbound_relationships[0].other_table, "Tree"); @@ -1216,7 +1216,7 @@ fn e2e_rename_table_keeps_its_index_with_a_stale_name() { "events: {events:?}" ); - let u = r.block_on(db.describe_table("Users".to_string(), None)).expect("describe Users"); + let u = r.block_on(db.describe_table("Users".to_string())).expect("describe Users"); assert_eq!(u.indexes.len(), 1, "the index followed the rename"); assert_eq!( u.indexes[0].name, "T_email_idx", @@ -1226,7 +1226,7 @@ fn e2e_rename_table_keeps_its_index_with_a_stale_name() { // Survives a fresh rebuild (recreated from IndexSchema on table Users). let db = fresh_rebuild(db, &project, &r); - let u = r.block_on(db.describe_table("Users".to_string(), None)).expect("describe Users"); + let u = r.block_on(db.describe_table("Users".to_string())).expect("describe Users"); assert_eq!(u.indexes.len(), 1); assert_eq!(u.indexes[0].name, "T_email_idx"); } @@ -1255,7 +1255,7 @@ fn e2e_rename_table_is_one_undo_step() { "undo restored the old table name: {tables:?}" ); assert_eq!( - r.block_on(db.query_data("Orders".to_string(), None, None, None)).expect("query").rows.len(), + r.block_on(db.query_data("Orders".to_string(), None, None)).expect("query").rows.len(), 1, "the row is back under the old name" ); @@ -1427,7 +1427,7 @@ fn e2e_alter_column_set_default_applies() { )) .expect("insert omitting qty"); let rows = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query") .rows; assert_eq!( @@ -1473,7 +1473,7 @@ fn e2e_alter_column_drop_default_removes_it() { )) .expect("insert omitting qty"); let rows = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query") .rows; assert_eq!( diff --git a/tests/it/sql_create_index.rs b/tests/it/sql_create_index.rs index 96a1e99..442022d 100644 --- a/tests/it/sql_create_index.rs +++ b/tests/it/sql_create_index.rs @@ -55,7 +55,7 @@ fn insert_row(db: &Database, r: &tokio::runtime::Runtime, id: i64, email: &str) } fn index(db: &Database, r: &tokio::runtime::Runtime, name: &str) -> Option<(Vec, bool)> { - r.block_on(db.describe_table("T".to_string(), None)) + r.block_on(db.describe_table("T".to_string())) .expect("describe") .indexes .into_iter() diff --git a/tests/it/sql_create_table.rs b/tests/it/sql_create_table.rs index 3ac8564..e2e6474 100644 --- a/tests/it/sql_create_table.rs +++ b/tests/it/sql_create_table.rs @@ -64,7 +64,7 @@ fn created_table_appears_with_playground_types() { assert!(tables.contains(&"Widget".to_string())); let desc = r - .block_on(db.describe_table("Widget".to_string(), None)) + .block_on(db.describe_table("Widget".to_string())) .expect("describe"); let types: Vec<(String, Option)> = desc .columns @@ -98,7 +98,7 @@ fn integer_primary_key_is_plain_int() { )) .expect("create"); let desc = r - .block_on(db.describe_table("T".to_string(), None)) + .block_on(db.describe_table("T".to_string())) .expect("describe"); assert_eq!(desc.columns[0].user_type, Some(Type::Int)); } @@ -137,7 +137,7 @@ fn serial_pk_autoincrements_in_multi_column_table() { } let data = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query"); let id_idx = data .columns @@ -220,7 +220,7 @@ fn table_without_primary_key_is_allowed() { )) .expect("insert into PK-less table"); let data = r - .block_on(db.query_data("Notes".to_string(), None, None, None)) + .block_on(db.query_data("Notes".to_string(), None, None)) .expect("query"); assert_eq!(data.rows.len(), 1); } @@ -299,7 +299,7 @@ fn default_is_applied_when_column_omitted() { )) .expect("insert"); let data = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query"); let n_idx = data.columns.iter().position(|c| c == "n").expect("n column"); assert_eq!(data.rows[0][n_idx].as_deref(), Some("7"), "DEFAULT 7 applied"); @@ -381,7 +381,7 @@ fn check_default_and_composite_unique_survive_rebuild() { // A valid row inserts; DEFAULT n=7 survived. r.block_on(ins("1", "1", "5")).expect("valid row"); let data = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query"); let n_idx = data.columns.iter().position(|c| c == "n").expect("n column"); assert_eq!(data.rows[0][n_idx].as_deref(), Some("7"), "DEFAULT survived rebuild"); @@ -679,7 +679,7 @@ fn sql_create_table_is_one_undo_step() { /// Sorted `id` column values of table `T`. fn ids(db: &Database, r: &tokio::runtime::Runtime) -> Vec> { let d = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query"); let idx = d.columns.iter().position(|c| c == "id").expect("id column"); let mut v: Vec> = d.rows.iter().map(|row| row[idx].clone()).collect(); @@ -801,7 +801,7 @@ fn dropping_a_column_a_table_check_references_fails_cleanly() { // The table is intact: both columns survive (rollback) ... let desc = r - .block_on(db.describe_table("T".to_string(), None)) + .block_on(db.describe_table("T".to_string())) .expect("describe still works"); assert_eq!( desc.columns.iter().map(|c| c.name.clone()).collect::>(), @@ -925,14 +925,14 @@ fn foreign_key_creates_named_relationship_visible_in_describe() { .expect("create child with FK"); // The child has an outbound relationship; the parent an inbound one. - let child = r.block_on(db.describe_table("child".to_string(), None)).expect("describe child"); + let child = r.block_on(db.describe_table("child".to_string())).expect("describe child"); assert_eq!(child.outbound_relationships.len(), 1, "child references parent"); let rel = &child.outbound_relationships[0]; assert_eq!(rel.name, "parent_id_to_child_pid", "auto-named per ADR-0013"); assert_eq!(rel.other_table, "parent"); assert_eq!(rel.local_columns, vec!["pid".to_string()]); - let parent = r.block_on(db.describe_table("parent".to_string(), None)).expect("describe parent"); + let parent = r.block_on(db.describe_table("parent".to_string())).expect("describe parent"); assert_eq!(parent.inbound_relationships.len(), 1, "parent is referenced by child"); } @@ -954,7 +954,7 @@ fn explicit_constraint_name_is_used() { Some("create table child (id serial primary key, pid int, constraint child_to_parent foreign key (pid) references parent(id))".to_string()), )) .expect("create child with named FK"); - let child = r.block_on(db.describe_table("child".to_string(), None)).expect("describe"); + let child = r.block_on(db.describe_table("child".to_string())).expect("describe"); assert_eq!(child.outbound_relationships[0].name, "child_to_parent"); } @@ -974,7 +974,7 @@ fn bare_references_resolves_to_parent_single_column_pk() { Some("create table child (id serial primary key, pid int references parent)".to_string()), )) .expect("create child with bare REFERENCES"); - let child = r.block_on(db.describe_table("child".to_string(), None)).expect("describe"); + let child = r.block_on(db.describe_table("child".to_string())).expect("describe"); assert_eq!(child.outbound_relationships[0].other_columns, vec!["id".to_string()], "resolved to parent PK"); } @@ -1108,7 +1108,7 @@ fn create_table_with_fk_is_one_undo_step() { // parent (now un-referenced) can be described without a dangling rel. r.block_on(db.undo()).expect("undo").expect("a step was undone"); assert!(!r.block_on(db.list_tables()).unwrap().contains(&"child".to_string())); - let parent = r.block_on(db.describe_table("parent".to_string(), None)).expect("describe parent"); + let parent = r.block_on(db.describe_table("parent".to_string())).expect("describe parent"); assert!(parent.inbound_relationships.is_empty(), "the relationship was undone with the table"); } @@ -1152,7 +1152,7 @@ fn foreign_key_on_delete_cascade_takes_effect() { )) .expect("delete parent"); let child_rows = r - .block_on(db.query_data("child".to_string(), None, None, None)) + .block_on(db.query_data("child".to_string(), None, None)) .expect("query child"); assert!(child_rows.rows.is_empty(), "ON DELETE CASCADE removed the child row"); } @@ -1232,7 +1232,7 @@ fn fk_survives_a_rebuild_triggering_column_add() { .expect("add column via rebuild"); // The relationship still exists after the rebuild. - let child = r.block_on(db.describe_table("child".to_string(), None)).expect("describe"); + let child = r.block_on(db.describe_table("child".to_string())).expect("describe"); assert_eq!(child.outbound_relationships.len(), 1, "FK survived the column-add rebuild"); // And the engine still enforces it (now and after a fresh rebuild). insert_parent_row(&db, &r); @@ -1275,7 +1275,7 @@ fn fk_referential_actions_survive_rebuild() { )) .expect("create"); r.block_on(db.rebuild_from_text(p.path().to_path_buf(), None)).expect("rebuild"); - let child = r.block_on(db.describe_table("child".to_string(), None)).expect("describe"); + let child = r.block_on(db.describe_table("child".to_string())).expect("describe"); let rel = &child.outbound_relationships[0]; assert_eq!(rel.on_delete, ReferentialAction::Cascade, "ON DELETE survived rebuild"); assert_eq!(rel.on_update, ReferentialAction::SetNull, "ON UPDATE survived rebuild"); @@ -1299,7 +1299,7 @@ fn dropping_the_child_clears_the_fk_relationship() { .expect("create"); r.block_on(db.drop_table("child".to_string(), Some("drop table child".to_string()))) .expect("drop child"); - let parent = r.block_on(db.describe_table("parent".to_string(), None)).expect("describe parent"); + let parent = r.block_on(db.describe_table("parent".to_string())).expect("describe parent"); assert!(parent.inbound_relationships.is_empty(), "dropping the child cleared the relationship"); } @@ -1341,7 +1341,7 @@ fn bare_self_reference_resolves_to_own_pk() { Some("create table emp (id int primary key, mgr int references emp)".to_string()), )) .expect("create self-referential emp with a bare reference"); - let emp = r.block_on(db.describe_table("emp".to_string(), None)).expect("describe"); + let emp = r.block_on(db.describe_table("emp".to_string())).expect("describe"); assert_eq!(emp.outbound_relationships[0].other_columns, vec!["id".to_string()], "bare self-ref resolved to own PK"); // Enforced: a non-existent manager is rejected. r.block_on(db.insert( diff --git a/tests/it/sql_delete.rs b/tests/it/sql_delete.rs index b91f88b..8f95463 100644 --- a/tests/it/sql_delete.rs +++ b/tests/it/sql_delete.rs @@ -154,7 +154,7 @@ fn delete_without_where_runs_across_all_rows() { let csv = read_csv(&project, "t").unwrap_or_default(); assert!(!csv.contains('a') && !csv.contains('b') && !csv.contains('c'), "no rows left: {csv:?}"); let remaining = rt - .block_on(db.query_data("t".to_string(), None, None, None)) + .block_on(db.query_data("t".to_string(), None, None)) .expect("query t"); assert!(remaining.rows.is_empty(), "table empty after unfiltered delete"); } @@ -302,8 +302,8 @@ fn cascade_to_two_children_reports_both() { assert_eq!(by_child.get("Orders"), Some(&2), "two orders cascaded"); assert_eq!(by_child.get("Reviews"), Some(&1), "one review cascaded"); // Both child CSVs re-persisted to the post-cascade (empty) state. - let orders = rt.block_on(db.query_data("Orders".to_string(), None, None, None)).unwrap(); - let reviews = rt.block_on(db.query_data("Reviews".to_string(), None, None, None)).unwrap(); + let orders = rt.block_on(db.query_data("Orders".to_string(), None, None)).unwrap(); + let reviews = rt.block_on(db.query_data("Reviews".to_string(), None, None)).unwrap(); assert!(orders.rows.is_empty() && reviews.rows.is_empty(), "both children emptied"); let _ = &project; } @@ -361,7 +361,7 @@ fn delete_violating_fk_fails_and_persists_nothing() { let result = run_delete(&db, &rt, input); assert!(result.is_err(), "delete of a referenced parent must be rejected"); // Rolled back: Alice survives. - let customers = rt.block_on(db.query_data("Customers".to_string(), None, None, None)).unwrap(); + let customers = rt.block_on(db.query_data("Customers".to_string(), None, None)).unwrap(); assert_eq!(customers.rows.len(), 1, "parent row preserved after rejected delete"); // No history line for the failed statement (written only on success). let history = std::fs::read_to_string(project.path().join("history.log")).unwrap_or_default(); diff --git a/tests/it/sql_dml_e2e.rs b/tests/it/sql_dml_e2e.rs index 313d643..d316c08 100644 --- a/tests/it/sql_dml_e2e.rs +++ b/tests/it/sql_dml_e2e.rs @@ -149,7 +149,7 @@ fn seed(db: &Database, rt: &tokio::runtime::Runtime, sql: &str) { } fn query(db: &Database, rt: &tokio::runtime::Runtime, table: &str) -> Vec>> { - rt.block_on(db.query_data(table.to_string(), None, None, None)) + rt.block_on(db.query_data(table.to_string(), None, None)) .unwrap_or_else(|e| panic!("query_data {table}: {e:?}")) .rows } diff --git a/tests/it/sql_drop_index.rs b/tests/it/sql_drop_index.rs index ca5f0d5..6ae5127 100644 --- a/tests/it/sql_drop_index.rs +++ b/tests/it/sql_drop_index.rs @@ -55,7 +55,7 @@ fn make_t_with_index(db: &Database, r: &tokio::runtime::Runtime) -> String { } fn index_names(db: &Database, r: &tokio::runtime::Runtime) -> Vec { - r.block_on(db.describe_table("T".to_string(), None)) + r.block_on(db.describe_table("T".to_string())) .expect("describe") .indexes .into_iter() diff --git a/tests/it/sql_drop_table.rs b/tests/it/sql_drop_table.rs index a95bb0e..5ea6550 100644 --- a/tests/it/sql_drop_table.rs +++ b/tests/it/sql_drop_table.rs @@ -150,7 +150,7 @@ fn drop_table_is_one_undo_step_and_restores_data() { assert!(r.block_on(db.undo()).expect("undo").is_some(), "the drop was one undo step"); assert!(r.block_on(db.list_tables()).unwrap().contains(&"T".to_string())); let data = r - .block_on(db.query_data("T".to_string(), None, None, None)) + .block_on(db.query_data("T".to_string(), None, None)) .expect("query"); assert_eq!(data.rows.len(), 1, "the dropped row was restored by undo"); } diff --git a/tests/it/sql_select.rs b/tests/it/sql_select.rs index 14c5654..c3c31d4 100644 --- a/tests/it/sql_select.rs +++ b/tests/it/sql_select.rs @@ -215,7 +215,7 @@ fn decimal_aggregation_display_trims_ieee754_noise() { // The reported case: the aggregate no longer leaks float noise. let agg = rt - .block_on(db.run_select("select sum(price * qty) from Products".to_string(), None)) + .block_on(db.run_select("select sum(price * qty) from Products".to_string())) .expect("aggregate select"); assert_eq!( agg.rows[0][0].as_deref(), @@ -226,7 +226,7 @@ fn decimal_aggregation_display_trims_ieee754_noise() { // Raw decimal column is still exact — TEXT storage preserves // the input string verbatim, including the trailing zero. let raw = rt - .block_on(db.run_select("select price from Products".to_string(), None)) + .block_on(db.run_select("select price from Products".to_string())) .expect("raw decimal select"); let prices: Vec<&str> = raw.rows.iter().map(|r| r[0].as_deref().unwrap()).collect(); assert_eq!( @@ -240,10 +240,7 @@ fn decimal_aggregation_display_trims_ieee754_noise() { fn database_run_select_constant_returns_a_single_row() { let (_p, db, _dir) = open_project_db(); let data = rt() - .block_on(db.run_select( - "select 1".to_string(), - Some("select 1".to_string()), - )) + .block_on(db.run_select("select 1".to_string())) .expect("`select 1` runs clean"); assert_eq!(data.rows.len(), 1, "one result row"); assert_eq!(data.rows[0].len(), 1, "one column"); @@ -288,7 +285,7 @@ fn database_run_select_from_user_table_returns_inserted_rows() { .expect("insert row"); }); let data = rt - .block_on(db.run_select("select Name from T".to_string(), None)) + .block_on(db.run_select("select Name from T".to_string())) .expect("SELECT runs"); assert_eq!(data.rows.len(), 1); assert_eq!(data.rows[0][0].as_deref(), Some("Ada")); @@ -336,7 +333,7 @@ fn database_run_select_recovers_bool_column_type() { .expect("insert row"); }); let data = rt - .block_on(db.run_select("select Active from Products".to_string(), None)) + .block_on(db.run_select("select Active from Products".to_string())) .expect("SELECT runs"); assert_eq!(data.rows.len(), 2); assert_eq!(data.column_types, vec![Some(Type::Bool)]); @@ -374,7 +371,7 @@ fn database_run_select_recovers_text_type_through_alias() { // playground type is recovered. let data = rt .block_on( - db.run_select("select Name as n from Users".to_string(), None), + db.run_select("select Name as n from Users".to_string()), ) .expect("SELECT runs"); assert_eq!(data.columns, vec!["n".to_string()]); @@ -402,7 +399,7 @@ fn database_run_select_computed_expression_stays_typeless() { .expect("insert"); }); let data = rt - .block_on(db.run_select("select Score + 1 from T".to_string(), None)) + .block_on(db.run_select("select Score + 1 from T".to_string())) .expect("SELECT runs"); assert_eq!(data.column_types, vec![None]); } @@ -439,7 +436,6 @@ fn engine_aggregate_in_where_routes_through_catalog() { let err = rt .block_on(db.run_select( "select id from T where count(score) > 0".to_string(), - None, )) .expect_err("engine should reject aggregate in WHERE"); let DbError::Sqlite { .. } = &err else { @@ -512,7 +508,6 @@ fn engine_group_by_missing_routes_through_catalog() { let _ = rt .block_on(db.run_select( "select category, count(*) from T group by category".to_string(), - None, )) .expect("benign GROUP BY query runs"); // Direct unit test on the matcher: ensure a message that @@ -574,7 +569,6 @@ fn engine_scalar_subquery_too_many_rows_routes_through_catalog() { let _ = rt .block_on(db.run_select( "select (select v from T) from T".to_string(), - None, )) .expect("benign scalar subquery query runs"); let synthetic = DbError::Sqlite { @@ -624,13 +618,13 @@ fn database_run_select_type_recovery_works_on_empty_table() { }); // No INSERT — the table is empty. let data_text = rt - .block_on(db.run_select("select col_text from Empty".to_string(), None)) + .block_on(db.run_select("select col_text from Empty".to_string())) .expect("SELECT runs even on empty table"); assert!(data_text.rows.is_empty()); assert_eq!(data_text.column_types, vec![Some(Type::Text)]); let data_blob = rt - .block_on(db.run_select("select col_blob from Empty".to_string(), None)) + .block_on(db.run_select("select col_blob from Empty".to_string())) .expect("SELECT runs even on empty table"); assert!(data_blob.rows.is_empty()); assert_eq!( @@ -723,7 +717,7 @@ fn database_run_select_recovers_all_ten_playground_types() { for (col, expected_type) in cases { let sql = format!("select {col} from AllTypes"); let data = rt - .block_on(db.run_select(sql.clone(), None)) + .block_on(db.run_select(sql.clone())) .expect("SELECT runs"); assert_eq!( data.column_types, diff --git a/tests/it/sql_update.rs b/tests/it/sql_update.rs index 86c7415..88ef502 100644 --- a/tests/it/sql_update.rs +++ b/tests/it/sql_update.rs @@ -501,7 +501,7 @@ fn update_all_rows_flag_in_advanced_updates_every_row() { "the --all-rows update replays through the DSL fall-back; events: {events:?}" ); let rows = rt - .block_on(db.query_data("t".to_string(), None, None, None)) + .block_on(db.query_data("t".to_string(), None, None)) .expect("query") .rows; assert_eq!(rows.len(), 2, "both rows present"); diff --git a/tests/it/undo_snapshots.rs b/tests/it/undo_snapshots.rs index d78ae8e..c0ce5f2 100644 --- a/tests/it/undo_snapshots.rs +++ b/tests/it/undo_snapshots.rs @@ -63,7 +63,7 @@ async fn insert_named(db: &Database, name: &str) { } async fn row_count(db: &Database) -> usize { - db.query_data("Customers".to_string(), None, None, None) + db.query_data("Customers".to_string(), None, None) .await .unwrap() .rows @@ -306,7 +306,7 @@ async fn sql_delete(db: &Database, input: &str) { } async fn count_t(db: &Database) -> usize { - db.query_data("T".to_string(), None, None, None) + db.query_data("T".to_string(), None, None) .await .unwrap() .rows @@ -378,7 +378,7 @@ fn undo_restores_db_and_csv_consistently() { // Both the database read model and the on-disk CSV are // restored — the (db, csv) pair stays consistent. assert_eq!( - db.query_data("T".to_string(), None, None, None) + db.query_data("T".to_string(), None, None) .await .unwrap() .rows