@crvouga/sqlite-mem 1.1.1 β 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -1
- package/COMPATIBILITY-AUDIT.md +29 -15
- package/COMPATIBILITY.md +16 -8
- package/README.md +17 -12
- package/compat/coverage.json +779 -729
- package/compat/divergences.json +124 -0
- package/compat/requirements.json +43 -43
- package/compat/scenario-types.ts +63 -0
- package/compat/scenarios.ts +851 -0
- package/compat/smoke-baseline.json +15 -0
- package/dist/api/database.d.ts +12 -3
- package/dist/api/statement.d.ts +1 -1
- package/dist/ast/nodes.d.ts +12 -1
- package/dist/executor/env.d.ts +1 -1
- package/dist/executor/select.d.ts +2 -1
- package/dist/executor/triggers.d.ts +2 -2
- package/dist/expressions/context.d.ts +3 -1
- package/dist/expressions/like.d.ts +3 -2
- package/dist/functions/registry.d.ts +2 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +698 -187
- package/dist/index.js.map +4 -4
- package/dist/lexer/tokenize.d.ts +1 -1
- package/dist/parser/parser.d.ts +2 -2
- package/dist/runtime/clock.d.ts +4 -2
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/options.d.ts +11 -3
- package/dist/runtime/prng.d.ts +11 -0
- package/dist/storage/database-state.d.ts +2 -0
- package/dist/storage/table.d.ts +2 -0
- package/dist/types/value.d.ts +5 -0
- package/dist/unstable.d.ts +3 -3
- package/dist/unstable.js +266 -64
- package/dist/unstable.js.map +3 -3
- package/dist/vtable/fts/table.d.ts +2 -3
- package/package.json +5 -2
package/AGENTS.md
CHANGED
|
@@ -124,13 +124,16 @@ SQLITE_MEM_FUZZ_SEED=12345 SQLITE_MEM_FUZZ_PATH='0:1' bun test tests/fuzz
|
|
|
124
124
|
|
|
125
125
|
| Command | Role |
|
|
126
126
|
| --- | --- |
|
|
127
|
-
| `bun run test:sqlite-compat` | Requirements + fail-closed gate + contract/fuzz/harness |
|
|
127
|
+
| `bun run test:sqlite-compat` | Requirements + fail-closed gate + construct catalog + π + smoke ratchet + contract/fuzz/harness |
|
|
128
128
|
| `bun run inventory` | Oracle `pragma_function_list` / modules vs memory registries |
|
|
129
|
+
| `bun run scenarios` | Construct-level scenario catalog (`compat/scenarios.ts`) + π / smoke gates |
|
|
129
130
|
| `bun run requirements` | Refresh sqlite.org requirements β `compat/requirements.json` + `compat/coverage.json` |
|
|
130
131
|
| `bun run fts-surface` | FTS oracle surface β `compat/fts-oracle-surface.json` |
|
|
131
132
|
|
|
132
133
|
Statuses: **VERIFIED** / **PARTIALLY VERIFIED** / **UNSUPPORTED** / **NOT APPLICABLE**. Do not market PARTIAL as complete. Coverage evidence is directory paths (e.g. `tests/contract/joins/`), not automatic from test filenames.
|
|
133
134
|
|
|
135
|
+
**Catalog vs proof:** `tests/contract/catalog/` IDs must execute; smoke (`SELECT 1 AS v`) is tracked in `compat/smoke-baseline.json`. Documented divergences bind to `compat/divergences.json`. Generated operator/CAST matrices: `tests/contract/matrices/`. Stateful dump-after-each fuzz: `tests/fuzz/stateful.test.ts`. Oracle `sqlite_version()` must be 3.51.0 or 3.53.0.
|
|
136
|
+
|
|
134
137
|
Details: [COMPATIBILITY.md](COMPATIBILITY.md), audit: [COMPATIBILITY-AUDIT.md](COMPATIBILITY-AUDIT.md).
|
|
135
138
|
|
|
136
139
|
## Local gates
|
package/COMPATIBILITY-AUDIT.md
CHANGED
|
@@ -69,34 +69,47 @@ Prepared statements / errors / snapshot:
|
|
|
69
69
|
VERIFIED β schema invalidation re-prepares; SQLM logical round-trip VERIFIED
|
|
70
70
|
|
|
71
71
|
Differential tests:
|
|
72
|
-
Total:
|
|
73
|
-
Passed:
|
|
72
|
+
Total: 872 under `bun test` (contract + fuzz + harness) after hardening pass
|
|
73
|
+
Passed: 872
|
|
74
74
|
Failed: 0
|
|
75
75
|
|
|
76
76
|
Stateful / fuzz:
|
|
77
77
|
Seeds: 0x5a17e0e1 (+ SQLITE_MEM_FUZZ_SEED override)
|
|
78
78
|
Combination fuzz: tests/fuzz/combinations-scope3.test.ts
|
|
79
79
|
FTS fuzz: tests/fuzz/fts.test.ts
|
|
80
|
+
Collate / window / CTE+DML / JSON subtype fuzz extended
|
|
80
81
|
Mismatches: 0
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
1.
|
|
84
|
-
2.
|
|
85
|
-
3.
|
|
86
|
-
4.
|
|
87
|
-
5.
|
|
88
|
-
6.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
Hardening pass (2026-08-19) β incompatibilities found & fixed:
|
|
84
|
+
1. Comparison affinity (INTEGER/TEXT/NUMERIC column vs literal) missing
|
|
85
|
+
2. WITH on UPDATE/DELETE/INSERT VALUES dispatched as SELECT only
|
|
86
|
+
3. Plain INTEGER PRIMARY KEY never reused deleted max rowid
|
|
87
|
+
4. date() `weekday N` modifier unimplemented
|
|
88
|
+
5. REGEXP operator not parsed (now calls missing regexp() like oracle)
|
|
89
|
+
6. last_insert_rowid() stale inside AFTER INSERT triggers
|
|
90
|
+
7. INSTEAD OF triggers never fired; view DML rejected
|
|
91
|
+
8. INSERT/UPDATE OR ROLLBACK / OR FAIL not distinguished
|
|
92
|
+
9. Window GROUPS/RANGE frames, window FILTER, recursive CTE queue edges
|
|
93
|
+
10. Collation-aware GROUP BY; FTS3 matchinfo format variants; external-content delete
|
|
94
|
+
|
|
95
|
+
Remaining known differences / intentional:
|
|
96
|
+
Custom SQLM snapshots; deterministic random()/'now' by default
|
|
97
|
+
(`random: "os"` / `now: "system"` match SQLite entropy and wall clock);
|
|
98
|
+
EXPLAIN stubs (shape contracts only); INDEXED BY no-op (documented);
|
|
99
|
+
ATTACH file path records filename but opens empty in-memory schema;
|
|
100
|
+
some PRAGMA storage no-ops; FTS shadow-table changes() diverge;
|
|
101
|
+
MATERIALIZED/NOT MATERIALIZED stored but both materialize today;
|
|
102
|
+
compile_options / function_list content is sqlite-mem's;
|
|
103
|
+
generate_series is sqlite-mem extension (not in bun:sqlite default);
|
|
93
104
|
BigInt beyond Number.MAX_SAFE_INTEGER without bun safeIntegers;
|
|
94
|
-
NOT APPLICABLE C API / on-disk / VFS surfaces.
|
|
105
|
+
NOT APPLICABLE C API / on-disk / VFS surfaces; uri.html remapped N/A.
|
|
95
106
|
|
|
96
107
|
Final assessment:
|
|
97
108
|
Verified against SQLite 3.51.0 (bun:sqlite). Oracle function/module
|
|
98
109
|
inventory is closed (0 missing). Requirements matrix ingested with
|
|
99
110
|
zero unknown statuses. Gate: `bun run test:sqlite-compat`.
|
|
111
|
+
Hardening pass closed construct-level P0 gaps from docs/PARITY-GAPS.md;
|
|
112
|
+
FTS/EXPLAIN remain PARTIALLY VERIFIED honestly.
|
|
100
113
|
```
|
|
101
114
|
|
|
102
115
|
---
|
|
@@ -144,10 +157,11 @@ Special commands verified:
|
|
|
144
157
|
delete-all / merge / automerge: error parity with oracle where probed
|
|
145
158
|
|
|
146
159
|
Differential tests:
|
|
147
|
-
Passed:
|
|
160
|
+
Passed: 872 (contract + fuzz + harness)
|
|
148
161
|
Failed: 0
|
|
149
162
|
FTS contract: tests/contract/fts/basic.test.ts,
|
|
150
163
|
tests/contract/fts/comprehensive.test.ts
|
|
164
|
+
(+ matchinfo formats, external-content, trigger maintenance)
|
|
151
165
|
|
|
152
166
|
Fuzz cases:
|
|
153
167
|
Generated: fast-check seed 0x5a17e0e1 (override SQLITE_MEM_FUZZ_SEED)
|
package/COMPATIBILITY.md
CHANGED
|
@@ -8,7 +8,15 @@ bun run test:sqlite-compat
|
|
|
8
8
|
|
|
9
9
|
See [COMPATIBILITY-AUDIT.md](COMPATIBILITY-AUDIT.md) for the latest evidence-based audit report.
|
|
10
10
|
|
|
11
|
-
Reference oracle: **SQLite 3.51.0** (`bun:sqlite`). Inventory: `bun run inventory`. Requirements matrix: `bun run requirements` β `compat/requirements.json` + `compat/coverage.json`.
|
|
11
|
+
Reference oracle: **SQLite 3.51.0** (`bun:sqlite`; Linux/Windows bun may report **3.53.0** β see π `oracle-platform-sqlite-version`). Inventory: `bun run inventory`. Construct catalog: `bun run scenarios` β [`compat/scenarios.ts`](compat/scenarios.ts). Divergences: [`compat/divergences.json`](compat/divergences.json). Requirements matrix: `bun run requirements` β `compat/requirements.json` + `compat/coverage.json`.
|
|
12
|
+
|
|
13
|
+
## Proof surface (Phase 1)
|
|
14
|
+
|
|
15
|
+
Differential tests compare a **B-tuple**: rows (plus `typeof` where requested), column names, error category / sqliteCode / message (Tier A exact or Tier B prefix-normalized), `changes`, `total_changes`, `lastInsertRowid`, and autocommit, plus a **logical Dump** (`sqlite_master` names, `table_info`, row payloads with per-column `typeof`, `sqlite_sequence`, selected pragmas).
|
|
16
|
+
|
|
17
|
+
A catalog ID appearing in a test file is **not** proof by itself. Cases whose SQL is `SELECT 1 AS v` are **smoke**; [`compat/smoke-baseline.json`](compat/smoke-baseline.json) ratchets that list downward. Generated matrices live under [`tests/contract/matrices/`](tests/contract/matrices/). Observed memβ oracle diffs must be `known-divergence(id)` from π or **FAILURE** β unexplained diffs are not allowed.
|
|
18
|
+
|
|
19
|
+
Intentional differences are finite and machine-readable in `compat/divergences.json` (SQLM snapshots, seeded `random()`/`now`, ATTACH empty schema, EXPLAIN stubs, INDEXED BY discarded, MATERIALIZED hint ignored, FTS shadow counters, compile_options/function_list, `-0`, JS API extras, snapshot exclusions).
|
|
12
20
|
|
|
13
21
|
## Status vocabulary
|
|
14
22
|
|
|
@@ -36,9 +44,9 @@ Oracle builtins (math, string extras, uuid, ieee754, β¦) and modules (FTS3/4/5,
|
|
|
36
44
|
| Core DML / SELECT / joins / CTE / UPSERT / RETURNING | VERIFIED | Contract + fuzz |
|
|
37
45
|
| STRICT tables / indexes | VERIFIED | STRICT types; partial + expression indexes; leftmost prefix |
|
|
38
46
|
| Expressions / operators / `->` `->>` / row values | VERIFIED | Row-value + precedence contracts |
|
|
39
|
-
| Affinity / NULL / COLLATE | VERIFIED | |
|
|
40
|
-
| Constraints / FK / triggers / views / ATTACH | VERIFIED | Deferred FK, composite FK |
|
|
41
|
-
| Windows (incl. ntile/cume_dist/percent_rank) | VERIFIED | EXCLUDE
|
|
47
|
+
| Affinity / NULL / COLLATE | VERIFIED | Comparison affinity + collation on GROUP BY/JOIN |
|
|
48
|
+
| Constraints / FK / triggers / views / ATTACH | VERIFIED | Deferred FK, composite FK, INSTEAD OF, OR ROLLBACK/FAIL |
|
|
49
|
+
| Windows (incl. ntile/cume_dist/percent_rank) | VERIFIED | EXCLUDE; GROUPS/RANGE frames; window FILTER |
|
|
42
50
|
| JSON1 / JSONB / TVFs | VERIFIED | |
|
|
43
51
|
| Math / string / date extras / uuid / ieee754 | VERIFIED | Scope-3 inventory |
|
|
44
52
|
| FTS3 / FTS4 / FTS5 + MATCH | PARTIALLY VERIFIED | Differential FTS suite + fuzz vs 3.51.0; see FTS matrix below. Shadow-table change counters intentionally diverge. |
|
|
@@ -62,11 +70,11 @@ Reference: **SQLite 3.51.0** (`bun:sqlite`). Inventory: `bun run scripts/fts-ora
|
|
|
62
70
|
| Column filters | VERIFIED |
|
|
63
71
|
| Ranking / bm25 / rank | VERIFIED |
|
|
64
72
|
| highlight / snippet | VERIFIED |
|
|
65
|
-
| matchinfo / offsets (FTS3/4) | PARTIALLY VERIFIED |
|
|
73
|
+
| matchinfo / offsets (FTS3/4) | PARTIALLY VERIFIED | Default + common format strings verified; some FTS4-only formats thinner |
|
|
66
74
|
| Contentless tables | VERIFIED |
|
|
67
|
-
| External content | PARTIALLY VERIFIED |
|
|
75
|
+
| External content | PARTIALLY VERIFIED | Canonical delete/sync covered; backfill/projection edges thinner |
|
|
68
76
|
| Content tables | VERIFIED |
|
|
69
|
-
| Triggers + FTS | PARTIALLY VERIFIED |
|
|
77
|
+
| Triggers + FTS | PARTIALLY VERIFIED | Maintenance sequences covered; advanced edges thinner |
|
|
70
78
|
| Special commands (optimize/rebuild/integrity-check) | VERIFIED |
|
|
71
79
|
| Prefix indexes | VERIFIED |
|
|
72
80
|
| Unicode / adversarial corpus | VERIFIED |
|
|
@@ -76,7 +84,7 @@ Reference: **SQLite 3.51.0** (`bun:sqlite`). Inventory: `bun run scripts/fts-ora
|
|
|
76
84
|
| FTS stateful fuzz | VERIFIED |
|
|
77
85
|
| RTREE / dbstat / bytecode / tables_used | VERIFIED | dbstat synthetic pages; bytecode empty cursor |
|
|
78
86
|
| ANALYZE / REINDEX / VACUUM | VERIFIED | `:memory:` observable parity |
|
|
79
|
-
| EXPLAIN / INDEXED BY | PARTIALLY VERIFIED | Stub shapes / no-ops |
|
|
87
|
+
| EXPLAIN / INDEXED BY | PARTIALLY VERIFIED | Stub shapes / no-ops (missing INDEXED BY errors documented) |
|
|
80
88
|
| Prepared stmt schema invalidation | VERIFIED | Re-prepare after ALTER/DROP; `tests/contract/api/schema-invalidation.test.ts` |
|
|
81
89
|
| On-disk file format / C API | NOT APPLICABLE | |
|
|
82
90
|
|
package/README.md
CHANGED
|
@@ -76,8 +76,9 @@ From the repo root after that install: `bun run example`.
|
|
|
76
76
|
import { Database, SqliteError } from "@crvouga/sqlite-mem";
|
|
77
77
|
|
|
78
78
|
interface DatabaseOptions {
|
|
79
|
-
seed?: number | bigint;
|
|
80
|
-
|
|
79
|
+
seed?: number | bigint; // default 1 β ignored when random is "os"
|
|
80
|
+
random?: "deterministic" | "os"; // default "deterministic"; "os" is CSPRNG like SQLite
|
|
81
|
+
now?: Date | (() => Date) | "system"; // default 2000-01-01T00:00:00.000Z; "system" is wall clock
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
interface Database {
|
|
@@ -171,7 +172,7 @@ Duplicate column names collapse in row objects (last write wins). Use `stmt.resu
|
|
|
171
172
|
- Round-trips ordinary tables, views, indexes, change counters, PRNG state, and clock.
|
|
172
173
|
- **Not** encoded: triggers, ATTACHβd schemas, virtual tables (FTS / RTREE / β¦), `userVersion`.
|
|
173
174
|
- Cannot `restore()` while a transaction is open.
|
|
174
|
-
- `restore()` replaces `now` with a fixed clock from the snapshot (a live `() => Date` is overwritten).
|
|
175
|
+
- `restore()` replaces `now` with a fixed clock from the snapshot (a live `() => Date` is overwritten). `{ now: "system" }` stays live after restore.
|
|
175
176
|
- Equivalent databases produce byte-identical snapshots (schema/rows sorted) **within a single library version**.
|
|
176
177
|
- **Compatibility policy:** newer library versions can always restore older snapshots; older libraries cannot restore newer format versions (`snapshot_version` / `SQLITE_FORMAT`). Corrupt magic yields a distinct error.
|
|
177
178
|
|
|
@@ -181,8 +182,8 @@ The engine is deterministic by default. Invariants:
|
|
|
181
182
|
|
|
182
183
|
| Source | Default | Override / notes |
|
|
183
184
|
| --- | --- | --- |
|
|
184
|
-
| `random()` / `randomblob()` | Seeded xorshift64* (`seed: 1`) | `new Database({ seed })` |
|
|
185
|
-
| `date('now')` / friends | Fixed `2000-01-01T00:00:00.000Z` | `new Database({ now: Date \| (() => Date) })` |
|
|
185
|
+
| `random()` / `randomblob()` | Seeded xorshift64* (`seed: 1`) | `new Database({ seed })` or `{ random: "os" }` for CSPRNG (not rolled back / not restored) |
|
|
186
|
+
| `date('now')` / friends | Fixed `2000-01-01T00:00:00.000Z` | `new Database({ now: Date \| (() => Date) \| "system" })` β `"system"` is wall clock and is **not** frozen by `restore()` |
|
|
186
187
|
| Table scans | Rowid order | Same order after `snapshot`/`restore` |
|
|
187
188
|
| Snapshots | Sorted schema/rows + PRNG state + clock | Restored into PRNG and `now` |
|
|
188
189
|
| Transactions | PRNG rolls back with `ROLLBACK`/`SAVEPOINT` | Matches data rollback |
|
|
@@ -209,14 +210,19 @@ The exports of the main entry (`@crvouga/sqlite-mem`) are **frozen**:
|
|
|
209
210
|
|
|
210
211
|
Goal: drop-in SQL behavior vs SQLite **3.51.0**. Full matrix: [COMPATIBILITY.md](COMPATIBILITY.md).
|
|
211
212
|
|
|
212
|
-
**Intentional differences:** custom `SQLM` snapshots; seeded `random()` / fixed `'now'
|
|
213
|
+
**Intentional differences:** custom `SQLM` snapshots; seeded `random()` / fixed `'now'` by default (`{ random: "os" }` / `{ now: "system" }` match SQLite entropy and wall clock); no C API / on-disk DB / VFS.
|
|
213
214
|
|
|
214
215
|
**Know these thin or partial areas** (do not assume full oracle fidelity):
|
|
215
216
|
|
|
216
217
|
- FTS3/4/5 β largely implemented; shadow-table change counters intentionally diverge; some edges partial
|
|
217
218
|
- `EXPLAIN` / `EXPLAIN QUERY PLAN` β stub shapes, not real bytecode
|
|
218
|
-
- `INDEXED BY` / `NOT INDEXED` β parsed and discarded
|
|
219
|
-
-
|
|
219
|
+
- `INDEXED BY` / `NOT INDEXED` β parsed and discarded (missing indexes do not error)
|
|
220
|
+
- `ATTACH 'file'` β filename is recorded; schema is always a new empty in-memory database
|
|
221
|
+
- `MATERIALIZED` / `NOT MATERIALIZED` β both execute as materialized
|
|
222
|
+
- `PRAGMA compile_options` / `function_list` β sqlite-memβs set, not Bunβs native build
|
|
223
|
+
- Unknown statement `PRAGMA` succeeds with an empty result (SQLite-like). All oracle-exposed `pragma_*` eponymous TVFs are supported (`SELECT * FROM pragma_table_info('t')`, bare `FROM pragma_database_list`, β¦), including **correlated** args such as `FROM table_list AS tl, pragma_table_info(tl.name) AS p` (Kysely SQLite introspector). Storage/journal getters return bun `:memory:`-compatible defaults. `PRAGMA case_sensitive_like` is implemented.
|
|
224
|
+
|
|
225
|
+
**Also supported (oracle-parity):** boolean literals **`TRUE` / `FALSE`** (any case β integers `1` / `0`) and **`IS [NOT] TRUE` / `IS [NOT] FALSE`** (SQLite truthiness, including NULL). A column named `true`/`false` shadows the literal.
|
|
220
226
|
|
|
221
227
|
## Common pitfalls
|
|
222
228
|
|
|
@@ -224,15 +230,15 @@ Goal: drop-in SQL behavior vs SQLite **3.51.0**. Full matrix: [COMPATIBILITY.md]
|
|
|
224
230
|
2. **No named-object binds and no sticky `bind()`** β pass positional rest args / arrays in declaration order to `query` / `run` / `all` / `get` / `result`.
|
|
225
231
|
3. **`query` / `prepare` are single-statement only** β multi-statement scripts belong in `exec()` (which does not take bind parameters).
|
|
226
232
|
4. **`exec` returns `void` and takes no params** β use `db.prepare(β¦).run(β¦)` or `db.query(β¦)` for binds; use `db.changes` / `stmt.run()` for counters.
|
|
227
|
-
5. **`'now'` is not wall-clock** unless you pass `{ now: () => new Date() }`. Default is year 2000.
|
|
228
|
-
6. **`random()` is seeded**, not OS entropy
|
|
233
|
+
5. **`'now'` is not wall-clock** unless you pass `{ now: "system" }` or `{ now: () => new Date() }`. Default is year 2000. `restore()` freezes a snapshot clock except when constructed with `"system"`.
|
|
234
|
+
6. **`random()` is seeded**, not OS entropy, unless you pass `{ random: "os" }`. Snapshots restore the seeded PRNG; OS entropy is not rewound.
|
|
229
235
|
7. **Snapshots are not `.sqlite` files** and do not round-trip FTS / triggers / ATTACH.
|
|
230
236
|
8. **No better-sqlite3 extras** β no `iterate`, `pluck`/`raw`, `safeIntegers` option, `pragma()` helper, `loadExtension`, or SQLite-file `serialize()`.
|
|
231
237
|
9. **Do not bind `Date` objects** β store unixepoch integers or ISO text. Do not bind `DataView` / non-`Uint8Array` typed arrays.
|
|
232
238
|
10. **Do not use `Number.isInteger` for SQL REAL vs INTEGER** β use SQL `typeof()`.
|
|
233
239
|
11. **Do not import `@crvouga/sqlite-mem/unstable` in application code** unless you accept breakage in any release.
|
|
234
240
|
|
|
235
|
-
Working examples beyond this README: `examples/react-vite`, `tests/contract/api/`, `tests/contract/parameters
|
|
241
|
+
Working examples beyond this README: `examples/react-vite`, `tests/contract/api/`, and `tests/contract/parameters/`.
|
|
236
242
|
|
|
237
243
|
## Development
|
|
238
244
|
|
|
@@ -250,7 +256,6 @@ bun run typecheck
|
|
|
250
256
|
bun run test:sqlite-compat # requirements + inventory gate + differential suite
|
|
251
257
|
bun test # contract + fuzz + harness
|
|
252
258
|
bun run build
|
|
253
|
-
bun run test:browser # Playwright smoke (Chrome/Firefox/Safari; CI uses Chromium)
|
|
254
259
|
```
|
|
255
260
|
|
|
256
261
|
See [COMPATIBILITY.md](./COMPATIBILITY.md).
|