Repository navigation
Commit b694e56
Part of #25521
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6270097840
Ruling-ref: 6348891160
Cut 2 of the `sql-driver.ts` split (#24586 ruling A, recorded in
`6270097840`). The claim is `6383192755`. Three `SqlDriver` method
bodies move unedited into a new module,
`packages/drivers/driver-sql/src/sql-driver-raw-execution.ts`: the
public `execute`, its protected refusal terminal `rawStatementFault`,
and the protected `noteRuntimeIndexDdl`, which records the index DDL
`execute` ran.
It is move-only, and the card stays open for the later cuts. Branch
`claude/issue-25521-sql-driver-cut-2`, cut from `origin/main` at
`f7b029896` (cut 1's merge).
**Serial with the file's in-flight PRs.** At claim the PM read no open
PR touching `sql-driver.ts` or `driver-turso/src`. Re-measured after my
first push (14 open PRs, each PR's file list read in full from its head,
merge base to head) and again just before this PR was opened (13 open;
#25617 had merged). None touches `packages/drivers/driver-sql/src/**` or
`packages/drivers/driver-turso/src/**`. `origin/main` moved three
commits past the base meanwhile (#25612, #25615, #25617, now
`cc10e74fe`). None of them touches `driver-sql`, `driver-turso`,
`driver-sqlite-wasm` or a gate script this diff derives, so `main` is
not merged in.
## Seam table (fresh, at `f7b029896`)
`sql-driver.ts` is 21,675 lines. 30-day lines are `git blame
--line-porcelain` lines whose committer time is on or after
2026-09-24T10:03:29Z, 30 days before the base commit. History was
deepened to 2026-09-15 first, and `scripts/pm/git-history.mjs count`
proves 68 commits on the file in that window (19 in the last 7 days). In
all, 3,855 lines (17.8%) are from the last 30 days. The class
`SqlDriver` spans lines 5482-21600 with 347 members: 251 methods (49
public), 32 statics. No public method has an inferred return type; the
one inferred public member is the getter `supports`, in the class head.
Sections are the class's own banner comments, cut by contiguous line
range. "Public" counts public methods, plus public accessors where there
are any:
| Lines | Section | Lines | 30-day lines | Members (public) |
|:--|:--|--:|--:|:--|
| 1-5481 | Module preamble: imports, types, top-level helpers (200
statements) | 5,481 | 1,405 | - |
| 5482-7073 | Class head: fields, statics, constructor, capability
getters (`supports`) | 1,592 | 290 | 88 (1 + 2 accessors) |
| 7074-7505 | Lifecycle | 432 | 155 | 15 (3) |
| 7506-10184 | CRUD (IDataDriver core) | 2,679 | 691 | 45 (7) |
| 10185-10796 | Bulk and batch operations | 612 | 140 | 9 (6) |
| **10797-10922** | **Raw execution (this cut)** | **126** | **12** |
**4 (1)** |
| 10923-11000 | Transactions | 78 | 0 | 7 (5) |
| 11001-11532 | Aggregation | 532 | 61 | 5 (1) |
| 11533-11820 | Distinct | 288 | 20 | 3 (1) |
| 11821-11936 | Window functions | 116 | 4 | 1 (1) |
| 11937-12035 | Query plan analysis | 99 | 1 | 2 (2) |
| 12036-15790 | Schema sync (syncSchema / init) | 3,755 | 373 | 62 (14 +
3 accessors) |
| 15791-15926 | Schema introspection (`listPhysicalColumns`,
`introspectSchema`) | 136 | 65 | 2 (2) |
| 15927-21600 | Internal helpers, including cut 1's five introspection
stubs | 5,674 | 638 | 104 (5) |
| 21601-21675 | After the class: `UniqueConstraintMember`,
`singleColumnUniqueColumns` | 75 | 0 | - |
The limits per area are cut 1's (PR #25614), re-read on this tree:
- **`getBuilder` builders.** Aggregation, Distinct, Window functions,
Query plan analysis, CRUD and Bulk build through `getBuilder`, so a cut
of any of them must first carry the new module into
`check:tenant-chokepoint`'s `SCAN_FILES`, or the gate goes silently
narrower. None of them is cut here.
- **Protected statics.** The hash-shadow family and the row-size
explainers (Internal helpers) read protected statics, so those bodies
stay.
- **`this.FIELD.delete/insert/update(`.** Transactions has one,
`releaseTransaction` (`this.openTransactions.delete(key)`), and Schema
sync has three. Those bodies stay. Raw execution has none:
`noteRuntimeIndexDdl` calls `.delete(` on a local `Set`, and calls
`.get(`, `.set(` and `.values()` on the ledger.
- `insertOnlyUpsertColumns` stays in `sql-driver.ts`, because #8740's
restart line names that symbol in that file. This cut does not touch it.
**Proposed cut 3: Transactions less `releaseTransaction`** (10923-11000,
78 lines, 0 from the last 30 days). That is `beginTransaction`,
`assertBareKnexSafe`, `commit`, `rollback`, `commitTransaction` and
`rollbackTransaction`. Every return type is annotated, and none reads
`getBuilder` or a static. `releaseTransaction` stays, for its
`this.openTransactions.delete(` site. The bodies call it through a
late-bound closure, as `execute` calls `rawStatementFault` here. Schema
introspection (136 lines, 65 from 30 days) is the next candidate after
that.
## Why this area for cut 2
Cut 1 proposed it, and it re-measures clean: 126 lines, 12 from the last
30 days. Its one public member, `execute`, has an annotated return type
(a `Promise` of `unknown`, pinned by
`sql-driver-doors-declared-types.test.ts`). It has no static and no
`getBuilder`, and no `this.FIELD.delete/insert/update(` site. Between
them, the three bodies read only `knex`, `logger`,
`runtimeCreatedIndexes` and each other (`execute` calls
`rawStatementFault` and `noteRuntimeIndexDdl`). The field
`runtimeCreatedIndexes` and its docblock stay on the class: schema sync
also reads the ledger (the index-drift diff in the Schema sync section).
Both subclasses reach the moved bodies. `TursoDriver` overrides
`execute`, calls `super.execute`, and calls `rawStatementFault` at eight
sites. `SqliteWasmDriver` inherits all three.
## The shape (#23050 shape B, as cut 1 applies it)
- The class keeps each method with its name, signature, docblock and
position, because tsup emits members with their JSDoc into the `.d.ts`.
Each body is now one host literal plus `fn.call(host, ...)`, marked
`[#25521 cut 2]`. `execute` drops `async` and returns the moved
function's promise. The other two were never `async`.
- `RawExecutionHost` is new. It types every member as the class member
itself (an indexed access on `SqlDriver`). Each moved function types its
`this` as the `Pick` of the host over exactly the members its body
reads. The generator lists them, and they were checked against the
`this.` reads of each base body. Each stub annotates its literal as the
`ThisParameterType` of the moved function. There is no cast, and no
member becomes public.
- `knex`, `logger` and `runtimeCreatedIndexes` go as getters, so each
read happens when the body makes it. `rawStatementFault` and
`noteRuntimeIndexDdl` go as late-bound closures. So a subclass override
is still the one `execute` reaches:
`sql-driver-21385-refusal-log-line-redaction.test.ts` and
`turso-driver-16019-remote-raw-statement-fault-envelope.test.ts`
override `rawStatementFault` and call `super`. A spy on the instance is
reached the same way.
- `this.logger.warn(...)` keeps its receiver: the getter hands back the
class's logger, and `.warn` is called on it.
- **Module-level declarations.** The bodies read seven top-level
declarations of `sql-driver.ts`: `OWN_STATEMENT_FAULT`,
`INDEX_DDL_PREFIX`, `CREATE_INDEX_DDL`, `DROP_INDEX_DDL`,
`unquoteSqlIdentifier`, `lastIdentifierSegment` and
`rawStatementFaultError`. All seven stay where they are, each gains a
leading `export`, and the new module imports them back. They stay
because `OWN_STATEMENT_FAULT` has readers that did not move (four other
refusal lines). They also stay because tests in four other packages
(`types`, `cli`, `metadata`, `metadata-protocol`) cite
`rawStatementFaultError` "verbatim (`sql-driver.ts`)" by path. Every
value import is read only inside a function body, so the module cycle is
evaluation-safe, as in cut 1. `index.ts` re-exports nothing new, so the
published surface does not move (proof below). This is the one place the
cut differs from cut 1's shape: cut 1 needed no new `export`. It is
recorded as an open question in the report.
- The move was produced by a script from the source text, not retyped:
each method's parameter list, return type and body lines, re-indented
two columns. The three bodies hold no multi-line template literal.
## The published `.d.ts` does not change
Under the series bar (ruling `6348891160`, letter A), measured on base
`f7b029896` and on head `a92731ec`. Both were built against the same
dependency tree: `turbo run build --filter=@objectstack/driver-turso...
--filter=@objectstack/driver-sqlite-wasm...` at base, 9/9 tasks, 0
cached (remote caching disabled). Then `pnpm --filter
@objectstack/driver-sql build` at head.
- This package emits `dist/index.d.ts` and `dist/index.d.mts` (there is
no `.d.cts`). The two are identical to each other at both ends.
- Raw sha256 of both files, base and head, all four the same:
`93da45168e82136b7613944525e47402d5dc6f9f8daa9efa4bdceeaa11b52a89` (cut
1's head hash, unchanged). The raw diff is 0 lines.
- Normalised with the ruling's one-liner verbatim (double-quoted
unions), base = head =
`93da45168e82136b7613944525e47402d5dc6f9f8daa9efa4bdceeaa11b52a89`. This
file has 0 double-quoted unions, so that normaliser rewrites nothing.
- Normalised with the same one-liner, with the quote character swapped
to a single quote (21 lines of this file carry a single-quoted union),
base = head =
`118e992ad8aad590044eb31509dca65e6b321e3410ce846e1e5f5dd34b956e95`. With
a raw diff of 0 lines, the proof rests on raw identity. The single-quote
pass is reported only because the dispatch asked for it.
- Positive control on a copy of the head `dist/index.d.ts`: line 4217,
`protected rawStatementFault(command: string, error: unknown): Error;`,
made public. That gives raw and double-quote-normalised
`47c79477965c2473c4a079afd8c4c8f47bc9f36213ac7dcfa2df99be7f081688` and
single-quote-normalised
`464658c31cd8f7ee5c779054428fe3f8d3c520610061252de5567e05a480ccd2`, each
different from the real hash.
- Export tables: the ESM and CJS bundles each export the same 56 names
at base and head, loaded at runtime (`import()` and `require` of the
built bundles). The sorted list hashes to
`d61a9dd3a02661602b1bb2dbe18152ac43986148f36b2746f40c0884bd8ffdec` on
all four.
- The head build carries the move: `dist/index.mjs` and `dist/index.js`
each contain 8 host `.call(` sites (cut 1's 5 plus these 3).
No changeset: `skip-changeset`, per ruling `6348891160` item 4.
## Proof of move-only
- **Bodies, by AST token** (recursive `getChildren` leaves). Each moved
function's parameters (less the added `this`), return type and body have
the same token sequence as the base method, and `async` matches on all
three. 404 tokens compared, 0 differ.
- **Lines**: 52 body lines compared (16 + 21 + 15, each body after its
opening brace). Each one is the base line with two leading spaces
removed.
- **Negative control**: changing one character inside a string literal
of `rawStatementFault` in a copy of the module makes the check report 1
token and 1 line different, and it exits `PROOF FAILED`.
- **Class side**: 347 members at base and head. The 344 members that did
not move are byte-identical to base, leading trivia included. Each of
the 3 stubs keeps its docblock and signature byte-identical, less
`async` on `execute`.
- **Top level of `sql-driver.ts`**: 200 base statements other than the
class. 193 are byte-identical. 7 are byte-identical except for a leading
`export`. They stay in order. The one new statement is the import of the
new module.
- **Size**: +166 / -57 over 2 files, far under the 3,000-line
manual-merge line. `sql-driver.ts` goes from 21,675 to 21,651 lines, and
`sql-driver-raw-execution.ts` has 133.
## Readers of `sql-driver.ts` by path, checked against the moved text
None needed an edit. Each was read against the moved region
(10797-10922) and run at both ends where it is a gate or test:
- **ADR anchors.**
`scripts/adr-anchors/packages__drivers__driver-sql__src__sql-driver.ts.json`
carries ADR-0053 (`formatOutput`, `presentReadValue`) and ADR-0120 D4.
Neither paragraph describes a moved body, so per card ask 3 the new
module gets no entry of its own. The moved bodies cite no ADR at all.
The docblocks that cite ADR-0048 and ADR-0112 stay on the class.
`check:adr-anchors`: 85 anchored files at base and head. Decision-letter
citations on the anchored surface: 1,871 at base and 1,871 at head.
- **Symbol anchors.** No ADR or platform-checklist anchor names
`execute`, `rawStatementFault`, `noteRuntimeIndexDdl` or the seven
module-level declarations in `sql-driver.ts`, and the stubs keep every
member name anyway. `check:adr-symbol-anchors`: 2,384 anchors resolve at
both ends.
- **`check:tenant-chokepoint`** reads `sql-driver.ts` for `getBuilder`
bindings and for `IS NULL` arms in raw fragments. The moved text has no
`getBuilder`. Its one raw call, `this.knex.raw(command, ...)`, passes a
variable, which that gate does not read (its header names this case as
outside its view). So the gate saw nothing in the moved text, and it
still covers the same population: 24 `getBuilder()` bindings across 3
files at both ends.
- **Logger receivers.** `logger-receiver-detach.test.ts` ③ scans
`sql-driver.ts` for detach-then-call shapes. The moved
`this.logger.warn(` is a direct call, not a finding. The repo-wide
`check:logger-receiver-detach` walks every `packages/**` source, so it
covers the new module: 0 detaches at head.
- **Other source scans**, none of whose patterns occurs in the moved
text: `sql-driver-compile-refusal-seam.test.ts` (no `INVALID_FILTER`
builder), the five `packages/cli` `generate-*.pin.test.ts` files
(`createColumn` and the varchar constants), `check-keyed-text-bounds`
(`varcharColumnChars`), `check-object-def-param-keys` (no `(obj as
any).KEY` read).
- **Path lists** that name the file for cache inputs or fixtures
(`turbo.json`, `scripts/cross-package-test-inputs.mjs`,
`scripts/pm/check-half-states.mjs`,
`scripts/check-changeset-no-major.mjs`, `packages/spec/liveness/*.json`
evidence). The readers they serve read `createColumn`, the varchar
constants or other unmoved symbols.
- **Comment citations** in other packages ("`rawStatementFaultError` …
(`sql-driver.ts`)") stay true, because that function did not move.
- **`driver-turso`** and **`driver-sqlite-wasm`**: their readers of
moved members reach the stubs unchanged. Both suites ran at both ends
(below).
- `check:driver-conformance` at base and head: 55 covered, 0 in the DEBT
ledger, 0 exempt, both times.
## Verification
- `tsc --noEmit` (driver-sql) exit 0. `eslint --no-inline-config` on
both source files exit 0.
- `packages/drivers/driver-sql` suite: base 3,999 tests (3,787 passed, 0
failed, 212 skipped; 247 files), head the same. Compared per test name
and status from vitest's JSON reporter: no test lost, none changed
status, none added.
- `packages/drivers/driver-turso` suite, run against the rebuilt head
`dist`: base 2,526 tests (2,492 passed, 0 failed, 34 skipped; 95 files),
head the same. Per test name and status there is no difference (2,513
distinct names; 13 names repeat).
- `packages/drivers/driver-sqlite-wasm` suite, against the rebuilt head
`dist`: base 704 tests (704 passed; 39 files), head the same, per test
name no difference.
- `dispatch-gates --commands` on this diff, at head `a92731ec`: 55
derived commands, each run with its exit code. `--ran` reconciles 55
derived, 54 run, 1 NOT MEASURED, 0 unrun. The NOT MEASURED one is
`check:dual-build-cjs-loads` (exit 3, PREREQUISITE NOT MET: it needs
every package's `dist`), which CI runs. Two gates first answered exit 3
for prerequisites and then exit 0: `check-plugin-teardown-shape
--self-test` after its pinned fixture commit `621a4876` was fetched, and
`check:lean-entry-closure` after `objectql` was built.
- No reverse verification or ablation: the diff changes no tested
behaviour.
## Acceptance notes
- Seven top-level declarations of `sql-driver.ts` gain `export`, so the
moved bodies can import them without a second copy. The package's public
surface does not change (raw `.d.ts` identity, export tables). Moving
the five declarations only the moved bodies read into the new module was
the alternative. It was not taken: other packages cite
`rawStatementFaultError` in `sql-driver.ts` by path, and
`OWN_STATEMENT_FAULT` would need the export anyway.
- `TursoDriver`'s `execute` override still calls `super.execute`, which
now returns the moved function's promise instead of an `async` method's
promise. A caller awaits the same settlement.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01RvoeGVyNRC3zkVrNsLbm8M)_
Co-authored-by: Claude <noreply@anthropic.com>
1 parent ca80f05 commit b694e56
2 files changed
Lines changed: 166 additions & 57 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
173 | 178 | | |
174 | 179 | | |
175 | 180 | | |
| |||
243 | 248 | | |
244 | 249 | | |
245 | 250 | | |
246 | | - | |
| 251 | + | |
247 | 252 | | |
248 | 253 | | |
249 | 254 | | |
250 | 255 | | |
251 | 256 | | |
252 | | - | |
253 | | - | |
| 257 | + | |
| 258 | + | |
254 | 259 | | |
255 | 260 | | |
256 | 261 | | |
257 | 262 | | |
258 | | - | |
| 263 | + | |
259 | 264 | | |
260 | 265 | | |
261 | 266 | | |
262 | 267 | | |
263 | 268 | | |
264 | 269 | | |
265 | | - | |
| 270 | + | |
266 | 271 | | |
267 | 272 | | |
268 | 273 | | |
| |||
279 | 284 | | |
280 | 285 | | |
281 | 286 | | |
282 | | - | |
| 287 | + | |
283 | 288 | | |
284 | 289 | | |
285 | 290 | | |
| |||
1174 | 1179 | | |
1175 | 1180 | | |
1176 | 1181 | | |
1177 | | - | |
| 1182 | + | |
1178 | 1183 | | |
1179 | 1184 | | |
1180 | 1185 | | |
| |||
10820 | 10825 | | |
10821 | 10826 | | |
10822 | 10827 | | |
10823 | | - | |
10824 | | - | |
10825 | | - | |
10826 | | - | |
10827 | | - | |
10828 | | - | |
10829 | | - | |
10830 | | - | |
10831 | | - | |
10832 | | - | |
10833 | | - | |
10834 | | - | |
10835 | | - | |
10836 | | - | |
10837 | | - | |
| 10828 | + | |
| 10829 | + | |
| 10830 | + | |
| 10831 | + | |
| 10832 | + | |
| 10833 | + | |
10838 | 10834 | | |
10839 | 10835 | | |
10840 | 10836 | | |
| |||
10860 | 10856 | | |
10861 | 10857 | | |
10862 | 10858 | | |
10863 | | - | |
10864 | | - | |
10865 | | - | |
10866 | | - | |
10867 | | - | |
10868 | | - | |
10869 | | - | |
10870 | | - | |
10871 | | - | |
10872 | | - | |
10873 | | - | |
10874 | | - | |
10875 | | - | |
10876 | | - | |
10877 | | - | |
10878 | | - | |
10879 | | - | |
10880 | | - | |
10881 | | - | |
10882 | | - | |
10883 | | - | |
| 10859 | + | |
| 10860 | + | |
| 10861 | + | |
| 10862 | + | |
| 10863 | + | |
| 10864 | + | |
| 10865 | + | |
| 10866 | + | |
| 10867 | + | |
10884 | 10868 | | |
10885 | 10869 | | |
10886 | 10870 | | |
| |||
10904 | 10888 | | |
10905 | 10889 | | |
10906 | 10890 | | |
10907 | | - | |
10908 | | - | |
10909 | | - | |
10910 | | - | |
10911 | | - | |
10912 | | - | |
10913 | | - | |
10914 | | - | |
10915 | | - | |
10916 | | - | |
10917 | | - | |
10918 | | - | |
10919 | | - | |
10920 | | - | |
| 10891 | + | |
| 10892 | + | |
| 10893 | + | |
| 10894 | + | |
| 10895 | + | |
| 10896 | + | |
10921 | 10897 | | |
10922 | 10898 | | |
10923 | 10899 | | |
| |||
0 commit comments