@crvouga/sqlite-mem 0.1.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/COMPATIBILITY-AUDIT.md +199 -0
- package/COMPATIBILITY.md +93 -0
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/compat/coverage.json +21896 -0
- package/compat/fts-oracle-surface.json +198 -0
- package/compat/gate-report.json +424 -0
- package/compat/requirements.json +20929 -0
- package/dist/api/database.d.ts +26 -0
- package/dist/api/database.d.ts.map +1 -0
- package/dist/api/statement.d.ts +27 -0
- package/dist/api/statement.d.ts.map +1 -0
- package/dist/ast/nodes.d.ts +451 -0
- package/dist/ast/nodes.d.ts.map +1 -0
- package/dist/constraints/check.d.ts +12 -0
- package/dist/constraints/check.d.ts.map +1 -0
- package/dist/errors/index.d.ts +12 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/executor/attach.d.ts +6 -0
- package/dist/executor/attach.d.ts.map +1 -0
- package/dist/executor/ddl.d.ts +11 -0
- package/dist/executor/ddl.d.ts.map +1 -0
- package/dist/executor/dml.d.ts +7 -0
- package/dist/executor/dml.d.ts.map +1 -0
- package/dist/executor/env.d.ts +62 -0
- package/dist/executor/env.d.ts.map +1 -0
- package/dist/executor/execute.d.ts +5 -0
- package/dist/executor/execute.d.ts.map +1 -0
- package/dist/executor/pragma.d.ts +5 -0
- package/dist/executor/pragma.d.ts.map +1 -0
- package/dist/executor/result.d.ts +18 -0
- package/dist/executor/result.d.ts.map +1 -0
- package/dist/executor/select.d.ts +7 -0
- package/dist/executor/select.d.ts.map +1 -0
- package/dist/executor/simple-select.d.ts +10 -0
- package/dist/executor/simple-select.d.ts.map +1 -0
- package/dist/executor/triggers.d.ts +12 -0
- package/dist/executor/triggers.d.ts.map +1 -0
- package/dist/executor/vtable.d.ts +13 -0
- package/dist/executor/vtable.d.ts.map +1 -0
- package/dist/expressions/context.d.ts +28 -0
- package/dist/expressions/context.d.ts.map +1 -0
- package/dist/expressions/eval.d.ts +5 -0
- package/dist/expressions/eval.d.ts.map +1 -0
- package/dist/expressions/index.d.ts +4 -0
- package/dist/expressions/index.d.ts.map +1 -0
- package/dist/expressions/like.d.ts +5 -0
- package/dist/expressions/like.d.ts.map +1 -0
- package/dist/functions/aggregate.d.ts +9 -0
- package/dist/functions/aggregate.d.ts.map +1 -0
- package/dist/functions/datetime.d.ts +3 -0
- package/dist/functions/datetime.d.ts.map +1 -0
- package/dist/functions/extensions.d.ts +8 -0
- package/dist/functions/extensions.d.ts.map +1 -0
- package/dist/functions/index.d.ts +9 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/json.d.ts +7 -0
- package/dist/functions/json.d.ts.map +1 -0
- package/dist/functions/math.d.ts +3 -0
- package/dist/functions/math.d.ts.map +1 -0
- package/dist/functions/registry.d.ts +38 -0
- package/dist/functions/registry.d.ts.map +1 -0
- package/dist/functions/scalar.d.ts +10 -0
- package/dist/functions/scalar.d.ts.map +1 -0
- package/dist/functions/table-valued.d.ts +9 -0
- package/dist/functions/table-valued.d.ts.map +1 -0
- package/dist/functions/window.d.ts +24 -0
- package/dist/functions/window.d.ts.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12204 -0
- package/dist/index.js.map +7 -0
- package/dist/indexes/index.d.ts +16 -0
- package/dist/indexes/index.d.ts.map +1 -0
- package/dist/json/index.d.ts +8 -0
- package/dist/json/index.d.ts.map +1 -0
- package/dist/json/jsonb.d.ts +43 -0
- package/dist/json/jsonb.d.ts.map +1 -0
- package/dist/json/ops.d.ts +19 -0
- package/dist/json/ops.d.ts.map +1 -0
- package/dist/json/parse.d.ts +14 -0
- package/dist/json/parse.d.ts.map +1 -0
- package/dist/json/path.d.ts +27 -0
- package/dist/json/path.d.ts.map +1 -0
- package/dist/json/stringify.d.ts +5 -0
- package/dist/json/stringify.d.ts.map +1 -0
- package/dist/json/tvf.d.ts +14 -0
- package/dist/json/tvf.d.ts.map +1 -0
- package/dist/json/types.d.ts +30 -0
- package/dist/json/types.d.ts.map +1 -0
- package/dist/lexer/tokenize.d.ts +17 -0
- package/dist/lexer/tokenize.d.ts.map +1 -0
- package/dist/parser/index.d.ts +5 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/parser.d.ts +104 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/planner/access.d.ts +43 -0
- package/dist/planner/access.d.ts.map +1 -0
- package/dist/planner/index.d.ts +4 -0
- package/dist/planner/index.d.ts.map +1 -0
- package/dist/runtime/clock.d.ts +6 -0
- package/dist/runtime/clock.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/options.d.ts +19 -0
- package/dist/runtime/options.d.ts.map +1 -0
- package/dist/runtime/prng.d.ts +20 -0
- package/dist/runtime/prng.d.ts.map +1 -0
- package/dist/schema/catalog.d.ts +15 -0
- package/dist/schema/catalog.d.ts.map +1 -0
- package/dist/serialization/codec.d.ts +12 -0
- package/dist/serialization/codec.d.ts.map +1 -0
- package/dist/serialization/index.d.ts +2 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/storage/database-state.d.ts +86 -0
- package/dist/storage/database-state.d.ts.map +1 -0
- package/dist/storage/index.d.ts +7 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/row.d.ts +11 -0
- package/dist/storage/row.d.ts.map +1 -0
- package/dist/storage/table.d.ts +90 -0
- package/dist/storage/table.d.ts.map +1 -0
- package/dist/transactions/manager.d.ts +20 -0
- package/dist/transactions/manager.d.ts.map +1 -0
- package/dist/types/collation.d.ts +5 -0
- package/dist/types/collation.d.ts.map +1 -0
- package/dist/types/value.d.ts +52 -0
- package/dist/types/value.d.ts.map +1 -0
- package/dist/vtable/fts/options.d.ts +35 -0
- package/dist/vtable/fts/options.d.ts.map +1 -0
- package/dist/vtable/fts/porter.d.ts +3 -0
- package/dist/vtable/fts/porter.d.ts.map +1 -0
- package/dist/vtable/fts/query.d.ts +40 -0
- package/dist/vtable/fts/query.d.ts.map +1 -0
- package/dist/vtable/fts/table.d.ts +80 -0
- package/dist/vtable/fts/table.d.ts.map +1 -0
- package/dist/vtable/fts/tokenize.d.ts +21 -0
- package/dist/vtable/fts/tokenize.d.ts.map +1 -0
- package/dist/vtable/fts5.d.ts +2 -0
- package/dist/vtable/fts5.d.ts.map +1 -0
- package/dist/vtable/index.d.ts +3 -0
- package/dist/vtable/index.d.ts.map +1 -0
- package/dist/vtable/modules.d.ts +66 -0
- package/dist/vtable/modules.d.ts.map +1 -0
- package/package.json +107 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# SQLite3 Compatibility Audit
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
SQLite3 Compatibility Audit
|
|
5
|
+
===========================
|
|
6
|
+
|
|
7
|
+
Reference SQLite version:
|
|
8
|
+
bun:sqlite (SQLite 3.51.0)
|
|
9
|
+
|
|
10
|
+
Reference SQLite compile options:
|
|
11
|
+
ENABLE_MATH_FUNCTIONS, ENABLE_FTS3/4/5, ENABLE_RTREE, ENABLE_DBSTAT_VTAB,
|
|
12
|
+
ENABLE_BYTECODE_VTAB, JSON builtin (not OMIT_JSON), plus Bun/SEE codec flags.
|
|
13
|
+
Full list: `bun run inventory`
|
|
14
|
+
|
|
15
|
+
sqlite-mem version:
|
|
16
|
+
0.1.0
|
|
17
|
+
|
|
18
|
+
Scope:
|
|
19
|
+
Scope 3 — every oracle-exposed SQL builtin/module is in-scope except
|
|
20
|
+
NOT APPLICABLE (C API, on-disk format, VFS/pager/WAL).
|
|
21
|
+
|
|
22
|
+
SQLite requirements reviewed:
|
|
23
|
+
3487 (from sqlite.org requirements matrix → compat/requirements.json)
|
|
24
|
+
|
|
25
|
+
SQLite requirements classification:
|
|
26
|
+
NOT APPLICABLE: see compat/coverage.json counts.notApplicable
|
|
27
|
+
SQL_BEHAVIOR: see counts.sqlBehavior
|
|
28
|
+
unknown: 0 (gate fails if non-zero)
|
|
29
|
+
|
|
30
|
+
Coverage statuses (SQL_BEHAVIOR):
|
|
31
|
+
VERIFIED / PARTIALLY_VERIFIED / UNSUPPORTED — see `bun run requirements`
|
|
32
|
+
Regenerated via scripts/sqlite-requirements.ts + coverage upgrades.
|
|
33
|
+
|
|
34
|
+
SQL grammar / operators / expressions:
|
|
35
|
+
VERIFIED — contracts + row-value comparisons + ->/->> precedence
|
|
36
|
+
|
|
37
|
+
Types / affinity / NULL:
|
|
38
|
+
VERIFIED
|
|
39
|
+
|
|
40
|
+
Functions (oracle surface):
|
|
41
|
+
VERIFIED — inventory missingOracleFunctions = 0 (163 names covered)
|
|
42
|
+
|
|
43
|
+
JSON / JSONB:
|
|
44
|
+
VERIFIED
|
|
45
|
+
|
|
46
|
+
Aggregates / windows:
|
|
47
|
+
VERIFIED — includes string_agg, ntile, cume_dist, percent_rank
|
|
48
|
+
(window EXCLUDE still thinner)
|
|
49
|
+
|
|
50
|
+
CTEs / transactions / savepoints / constraints / FK / triggers:
|
|
51
|
+
VERIFIED (deferred FK thinner → PARTIAL edges)
|
|
52
|
+
|
|
53
|
+
Indexes / views / generated / STRICT / WITHOUT ROWID:
|
|
54
|
+
VERIFIED / PARTIAL per COMPATIBILITY.md
|
|
55
|
+
|
|
56
|
+
PRAGMAs:
|
|
57
|
+
PARTIALLY VERIFIED — schema/FK; storage pragmas N/A or :memory: no-op
|
|
58
|
+
|
|
59
|
+
ATTACH/DETACH:
|
|
60
|
+
VERIFIED (in-memory schemas; temp.schema = main state)
|
|
61
|
+
|
|
62
|
+
Virtual tables / extensions:
|
|
63
|
+
VERIFIED for oracle modules: fts3/4/5, fts5vocab, rtree/rtree_i32,
|
|
64
|
+
dbstat, bytecode, tables_used (bytecode/tables_used empty cursors)
|
|
65
|
+
|
|
66
|
+
ANALYZE / REINDEX / VACUUM:
|
|
67
|
+
VERIFIED (:memory: observable parity)
|
|
68
|
+
|
|
69
|
+
Prepared statements / errors / snapshot:
|
|
70
|
+
PARTIAL / VERIFIED — schema invalidation thin; SQLM logical round-trip VERIFIED
|
|
71
|
+
|
|
72
|
+
Differential tests:
|
|
73
|
+
Total: 656 under `bun test` (contract + fuzz + harness)
|
|
74
|
+
Passed: 656
|
|
75
|
+
Failed: 0
|
|
76
|
+
|
|
77
|
+
Stateful / fuzz:
|
|
78
|
+
Seeds: 0x5a17e0e1 (+ SQLITE_MEM_FUZZ_SEED override)
|
|
79
|
+
Combination fuzz: tests/fuzz/combinations-scope3.test.ts
|
|
80
|
+
FTS fuzz: tests/fuzz/fts.test.ts
|
|
81
|
+
Mismatches: 0
|
|
82
|
+
|
|
83
|
+
New incompatibilities found & fixed (this pass):
|
|
84
|
+
1. Missing ~85 oracle builtins (math/string/date/window/uuid/ieee754/…)
|
|
85
|
+
2. Missing modules FTS3/4, RTREE, dbstat, bytecode, tables_used, fts5vocab
|
|
86
|
+
3. ANALYZE/REINDEX/VACUUM not executed
|
|
87
|
+
4. Row-value comparisons threw misuse instead of SQLite semantics
|
|
88
|
+
5. Inventory asserted builtins absent (Scope-3 inverted)
|
|
89
|
+
6. No requirements-matrix ingest / no test:sqlite-compat gate
|
|
90
|
+
|
|
91
|
+
Remaining known differences:
|
|
92
|
+
Custom SQLM snapshots; deterministic random()/'now';
|
|
93
|
+
EXPLAIN/INDEXED BY stubs/no-ops; some PRAGMA storage no-ops;
|
|
94
|
+
Window EXCLUDE / deferred FK / STRICT / prepared invalidation thinner;
|
|
95
|
+
BigInt beyond Number.MAX_SAFE_INTEGER without bun safeIntegers;
|
|
96
|
+
NOT APPLICABLE C API / on-disk / VFS surfaces.
|
|
97
|
+
|
|
98
|
+
Final assessment:
|
|
99
|
+
Verified against SQLite 3.51.0 (bun:sqlite). Oracle function/module
|
|
100
|
+
inventory is closed (0 missing). Requirements matrix ingested with
|
|
101
|
+
zero unknown statuses. Gate: `bun run test:sqlite-compat`.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## SQLite Full-Text Search Compatibility Audit
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
SQLite Full-Text Search Compatibility Audit
|
|
110
|
+
==========================================
|
|
111
|
+
|
|
112
|
+
Reference SQLite:
|
|
113
|
+
version: 3.51.0 (bun:sqlite)
|
|
114
|
+
source_id: 2025-06-12 13:14:41 f0ca7bba1c5e232e5d279fad6338121ab55af0c8c68c84cdfb18ba5114dcaapl
|
|
115
|
+
compile options: ENABLE_FTS3, ENABLE_FTS3_PARENTHESIS, ENABLE_FTS3_TOKENIZER,
|
|
116
|
+
ENABLE_FTS4, ENABLE_FTS5
|
|
117
|
+
inventory: compat/fts-oracle-surface.json (bun run scripts/fts-oracle-surface.ts)
|
|
118
|
+
|
|
119
|
+
FTS3: PARTIALLY VERIFIED (MATCH, snippet, offsets; matchinfo formats thinner)
|
|
120
|
+
FTS4: PARTIALLY VERIFIED (same surface as FTS3 for tested paths)
|
|
121
|
+
FTS5: PARTIALLY VERIFIED overall — core MATCH/tokenizers/ranking/aux VERIFIED;
|
|
122
|
+
external-content + full matchinfo format strings still thinner
|
|
123
|
+
|
|
124
|
+
Tokenizers verified:
|
|
125
|
+
unicode61 (incl. remove_diacritics 0/1/2), ascii, porter,
|
|
126
|
+
porter unicode61, porter ascii, trigram
|
|
127
|
+
|
|
128
|
+
MATCH grammar verified:
|
|
129
|
+
terms, AND/OR/NOT, implicit AND, phrases, prefix *, column filters
|
|
130
|
+
(col : term / {cols} :), NEAR / NEAR(…, N), parentheses, NEAR-as-term
|
|
131
|
+
|
|
132
|
+
Ranking verified:
|
|
133
|
+
bm25() / rank column — order + scores vs oracle (1e-15 abs epsilon for ULP)
|
|
134
|
+
|
|
135
|
+
Auxiliary functions verified:
|
|
136
|
+
bm25, highlight, snippet (FTS5); snippet, offsets (FTS3/4);
|
|
137
|
+
matchinfo present (default format PARTIAL)
|
|
138
|
+
|
|
139
|
+
Content modes verified:
|
|
140
|
+
normal content tables: VERIFIED
|
|
141
|
+
contentless (content=''): VERIFIED
|
|
142
|
+
external content: PARTIALLY VERIFIED (CREATE accepted; sync/triggers thinner)
|
|
143
|
+
|
|
144
|
+
Special commands verified:
|
|
145
|
+
optimize, rebuild, integrity-check (success + post-command MATCH)
|
|
146
|
+
delete-all / merge / automerge: error parity with oracle where probed
|
|
147
|
+
|
|
148
|
+
Differential tests:
|
|
149
|
+
Passed: 656 (contract + fuzz + harness)
|
|
150
|
+
Failed: 0
|
|
151
|
+
FTS contract: tests/contract/fts/basic.test.ts,
|
|
152
|
+
tests/contract/fts/comprehensive.test.ts
|
|
153
|
+
|
|
154
|
+
Fuzz cases:
|
|
155
|
+
Generated: fast-check seed 0x5a17e0e1 (override SQLITE_MEM_FUZZ_SEED)
|
|
156
|
+
Files: tests/fuzz/fts.test.ts (MATCH queries, tokenizers, stateful DML)
|
|
157
|
+
Mismatches: 0 (after trigram phrase expansion + NEAR-as-term fixes)
|
|
158
|
+
|
|
159
|
+
Stateful cases:
|
|
160
|
+
Operations: INSERT/UPDATE/DELETE/MATCH sequences + txn/savepoint contracts
|
|
161
|
+
Mismatches: 0
|
|
162
|
+
|
|
163
|
+
Compatibility gaps found:
|
|
164
|
+
1. Toy AND-token matcher (replaced)
|
|
165
|
+
2. Aux functions always threw (wired MATCH cursor + real bm25/highlight/snippet)
|
|
166
|
+
3. No CREATE option parsing (tokenize=/content=/prefix=/UNINDEXED)
|
|
167
|
+
4. No FTS5 query language / NEAR / phrases / column filters
|
|
168
|
+
5. False VERIFIED status on fts5.html / fts3.html (downgraded then re-evidenced)
|
|
169
|
+
|
|
170
|
+
Compatibility gaps fixed:
|
|
171
|
+
Positional inverted index; unicode61/ascii/porter/trigram tokenizers;
|
|
172
|
+
FTS5 query parser; BM25 with SQLite IDF floor 1e-6; highlight/snippet;
|
|
173
|
+
contentless mode; special commands; FTS3/4 MATCH + snippet/offsets;
|
|
174
|
+
comparator realEpsilon for ranking ULP only; FTS fuzz suites
|
|
175
|
+
|
|
176
|
+
Regression tests added:
|
|
177
|
+
tests/contract/fts/comprehensive.test.ts
|
|
178
|
+
tests/fuzz/fts.test.ts
|
|
179
|
+
tests/harness/fts-compare.ts
|
|
180
|
+
scripts/fts-oracle-surface.ts
|
|
181
|
+
|
|
182
|
+
Remaining unsupported / thinner functionality:
|
|
183
|
+
- SQLite FTS shadow tables not mirrored (change counters diverge; documented)
|
|
184
|
+
- External-content sync/stale-index edge cases thinner
|
|
185
|
+
- FTS3 matchinfo format-string variants not exhaustively verified
|
|
186
|
+
- fts3tokenize / fts4aux still thin CREATE stubs
|
|
187
|
+
- locale / tokendata / detail=none advanced options accepted but lightly tested
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Verification commands:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
bun run test:sqlite-compat
|
|
194
|
+
bun run scripts/fts-oracle-surface.ts
|
|
195
|
+
bun test tests/contract/fts tests/fuzz/fts.test.ts
|
|
196
|
+
bun run inventory
|
|
197
|
+
bun run requirements
|
|
198
|
+
bun run typecheck
|
|
199
|
+
```
|
package/COMPATIBILITY.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Compatibility
|
|
2
|
+
|
|
3
|
+
Goal: **full SQLite3 SQL dialect behavioral parity** as a drop-in for the same statements against the reference oracle. Compatibility is proven by the differential contract suite and the fail-closed gate:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun run test:sqlite-compat
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
See [COMPATIBILITY-AUDIT.md](COMPATIBILITY-AUDIT.md) for the latest evidence-based audit report.
|
|
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`.
|
|
12
|
+
|
|
13
|
+
## Status vocabulary
|
|
14
|
+
|
|
15
|
+
| Status | Meaning |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| **VERIFIED** | Differential contracts (+ fuzz where applicable) cover happy path **and** meaningful edges vs oracle |
|
|
18
|
+
| **PARTIALLY VERIFIED** | Implemented; coverage thin or known edges remain |
|
|
19
|
+
| **UNSUPPORTED** | Missing from SQL surface (must fail loud; gate fails if oracle-exposed) |
|
|
20
|
+
| **NOT APPLICABLE** | Outside the in-memory dialect surface (C API, on-disk `.sqlite`, VFS/pager/WAL) |
|
|
21
|
+
|
|
22
|
+
## Scope 3 bound
|
|
23
|
+
|
|
24
|
+
Anything a SQLite application can invoke through SQL against this Bun/SQLite **3.51.0** build must match oracle observable behavior, except:
|
|
25
|
+
|
|
26
|
+
1. **Snapshot format** — custom binary codec (`SQLM`), not the on-disk SQLite database file format (logical state still round-trips).
|
|
27
|
+
2. **Deterministic `random()` / `'now'`** — seeded PRNG and fixed clock by default (injectable).
|
|
28
|
+
3. **NOT APPLICABLE** rows in `compat/coverage.json` (C API, VFS, pager, file locking, etc.).
|
|
29
|
+
|
|
30
|
+
Oracle builtins (math, string extras, uuid, ieee754, …) and modules (FTS3/4/5, RTREE, dbstat, bytecode, tables_used) are **in scope**.
|
|
31
|
+
|
|
32
|
+
## Feature matrix (summary)
|
|
33
|
+
|
|
34
|
+
| Area | Status | Notes |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| Core DML / SELECT / joins / CTE / UPSERT / RETURNING | VERIFIED | Contract + fuzz |
|
|
37
|
+
| Expressions / operators / `->` `->>` / row values | VERIFIED | Row-value + precedence contracts |
|
|
38
|
+
| Affinity / NULL / COLLATE | VERIFIED | |
|
|
39
|
+
| Constraints / FK / triggers / views / ATTACH | VERIFIED | Deferred FK thinner → PARTIAL edges |
|
|
40
|
+
| Windows (incl. ntile/cume_dist/percent_rank) | VERIFIED | EXCLUDE still thinner |
|
|
41
|
+
| JSON1 / JSONB / TVFs | VERIFIED | |
|
|
42
|
+
| Math / string / date extras / uuid / ieee754 | VERIFIED | Scope-3 inventory |
|
|
43
|
+
| FTS3 / FTS4 / FTS5 + MATCH | PARTIALLY VERIFIED | Differential FTS suite + fuzz vs 3.51.0; see FTS matrix below. Shadow-table change counters intentionally diverge. |
|
|
44
|
+
|
|
45
|
+
## FTS compatibility matrix
|
|
46
|
+
|
|
47
|
+
Reference: **SQLite 3.51.0** (`bun:sqlite`). Inventory: `bun run scripts/fts-oracle-surface.ts` → `compat/fts-oracle-surface.json`.
|
|
48
|
+
|
|
49
|
+
| Feature | Status |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| FTS3 | PARTIALLY VERIFIED |
|
|
52
|
+
| FTS4 | PARTIALLY VERIFIED |
|
|
53
|
+
| FTS5 | PARTIALLY VERIFIED |
|
|
54
|
+
| Virtual table creation (options/tokenizers) | VERIFIED |
|
|
55
|
+
| Tokenizers (unicode61/ascii/porter/trigram) | VERIFIED |
|
|
56
|
+
| MATCH grammar (AND/OR/NOT/phrase/prefix/NEAR/columns) | VERIFIED |
|
|
57
|
+
| Boolean operators | VERIFIED |
|
|
58
|
+
| Phrases | VERIFIED |
|
|
59
|
+
| Prefix queries | VERIFIED |
|
|
60
|
+
| NEAR | VERIFIED |
|
|
61
|
+
| Column filters | VERIFIED |
|
|
62
|
+
| Ranking / bm25 / rank | VERIFIED |
|
|
63
|
+
| highlight / snippet | VERIFIED |
|
|
64
|
+
| matchinfo / offsets (FTS3/4) | PARTIALLY VERIFIED |
|
|
65
|
+
| Contentless tables | VERIFIED |
|
|
66
|
+
| External content | PARTIALLY VERIFIED |
|
|
67
|
+
| Content tables | VERIFIED |
|
|
68
|
+
| Triggers + FTS | PARTIALLY VERIFIED |
|
|
69
|
+
| Special commands (optimize/rebuild/integrity-check) | VERIFIED |
|
|
70
|
+
| Prefix indexes | VERIFIED |
|
|
71
|
+
| Unicode / adversarial corpus | VERIFIED |
|
|
72
|
+
| Transactions / savepoints | VERIFIED |
|
|
73
|
+
| Error behavior | VERIFIED |
|
|
74
|
+
| FTS differential fuzz | VERIFIED |
|
|
75
|
+
| FTS stateful fuzz | VERIFIED |
|
|
76
|
+
| RTREE / dbstat / bytecode / tables_used | VERIFIED | dbstat synthetic pages; bytecode empty cursor |
|
|
77
|
+
| ANALYZE / REINDEX / VACUUM | VERIFIED | `:memory:` observable parity |
|
|
78
|
+
| EXPLAIN / INDEXED BY | PARTIALLY VERIFIED | Stub shapes / no-ops |
|
|
79
|
+
| Prepared stmt schema invalidation | PARTIALLY VERIFIED | Thin |
|
|
80
|
+
| On-disk file format / C API | NOT APPLICABLE | |
|
|
81
|
+
|
|
82
|
+
## How to verify
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
bun run test:sqlite-compat # requirements + gate + contract/fuzz/harness
|
|
86
|
+
bun run inventory # oracle function/module inventory
|
|
87
|
+
bun run requirements # refresh SQLite.org requirements + coverage
|
|
88
|
+
bun run test:browser # Playwright smoke (not the SQL oracle)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Do not treat isolated unit tests of internal modules as proof of SQLite compatibility. The differential matrix runner is authoritative for SQL behavior; `test:sqlite-compat` is the release gate.
|
|
92
|
+
|
|
93
|
+
**Parity claim:** Verified against **SQLite 3.51.0** (`bun:sqlite`). Features marked **VERIFIED** are oracle-proven. **PARTIALLY VERIFIED** rows must not be marketed as complete. **NOT APPLICABLE** is the only allowed permanent omission from the SQL drop-in claim.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chris Vouga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# sqlite-mem
|
|
2
|
+
|
|
3
|
+
Pure TypeScript, completely in-memory SQLite implementation aiming for **full SQLite3 SQL dialect parity** (same statements → same results).
|
|
4
|
+
|
|
5
|
+
- Runs in modern browsers and Node.js / Bun
|
|
6
|
+
- **Zero** WASM, native bindings, workers, or filesystem dependencies
|
|
7
|
+
- Entire database stored in memory
|
|
8
|
+
- **Verified against SQLite 3.51.0** (`bun:sqlite`) via differential contracts + fail-closed gate
|
|
9
|
+
- Intentional differences: deterministic `random()` / `'now'` by default, and a custom snapshot format (not `.sqlite` files)
|
|
10
|
+
|
|
11
|
+
See [COMPATIBILITY.md](COMPATIBILITY.md) for the matrix and [COMPATIBILITY-AUDIT.md](COMPATIBILITY-AUDIT.md) for the audit report.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun add @crvouga/sqlite-mem
|
|
17
|
+
# or
|
|
18
|
+
npm install @crvouga/sqlite-mem
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { Database } from "@crvouga/sqlite-mem";
|
|
25
|
+
|
|
26
|
+
const db = new Database();
|
|
27
|
+
|
|
28
|
+
db.exec(`
|
|
29
|
+
CREATE TABLE users (
|
|
30
|
+
id INTEGER PRIMARY KEY,
|
|
31
|
+
name TEXT NOT NULL
|
|
32
|
+
)
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
db.exec(`INSERT INTO users (name) VALUES (?)`, ["Alice"]);
|
|
36
|
+
|
|
37
|
+
const users = db.query<{ id: number; name: string }>(`SELECT * FROM users`);
|
|
38
|
+
console.log(users);
|
|
39
|
+
|
|
40
|
+
const snap = db.snapshot();
|
|
41
|
+
const db2 = new Database();
|
|
42
|
+
db2.restore(snap);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
interface Database {
|
|
49
|
+
// seed default 1; now default 2000-01-01T00:00:00.000Z
|
|
50
|
+
constructor(options?: { seed?: number | bigint; now?: Date | (() => Date) });
|
|
51
|
+
exec(sql: string, params?: unknown[]): void;
|
|
52
|
+
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
|
|
53
|
+
prepare(sql: string): Statement;
|
|
54
|
+
transaction<T>(fn: () => T): T;
|
|
55
|
+
snapshot(): Uint8Array;
|
|
56
|
+
restore(snapshot: Uint8Array): void;
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface Statement {
|
|
61
|
+
bind(...params: unknown[]): Statement;
|
|
62
|
+
run(...params: unknown[]): { changes: number; lastInsertRowid: number | bigint };
|
|
63
|
+
all<T = Record<string, unknown>>(...params: unknown[]): T[];
|
|
64
|
+
get<T = Record<string, unknown>>(...params: unknown[]): T | undefined;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Determinism
|
|
69
|
+
|
|
70
|
+
The engine is deterministic by default. Invariants:
|
|
71
|
+
|
|
72
|
+
| Source | Default | Override / notes |
|
|
73
|
+
| --- | --- | --- |
|
|
74
|
+
| `random()` / `randomblob()` | Seeded xorshift64* (`seed: 1`) | `new Database({ seed })` or `{ prng }` |
|
|
75
|
+
| `date('now')` / friends | Fixed `2000-01-01T00:00:00.000Z` | `new Database({ now: Date \| (() => Date) })` |
|
|
76
|
+
| Table scans | Rowid order | Same order after `snapshot`/`restore` |
|
|
77
|
+
| Snapshots | Sorted schema/rows + PRNG state + clock | Restored into PRNG and `now` |
|
|
78
|
+
| Transactions | PRNG rolls back with `ROLLBACK`/`SAVEPOINT` | Matches data rollback |
|
|
79
|
+
| Numbers | IEEE `-0` canonicalized to `+0` | Bind, affinity, and arithmetic |
|
|
80
|
+
|
|
81
|
+
Fuzz / property tests use a fixed seed (`0x5a17e0e1`) and print it on failure:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
bun test tests/fuzz
|
|
85
|
+
SQLITE_MEM_FUZZ_SEED=12345 bun test tests/fuzz
|
|
86
|
+
SQLITE_MEM_FUZZ_SEED=12345 SQLITE_MEM_FUZZ_PATH='0:1' bun test tests/fuzz # exact replay
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Development
|
|
90
|
+
|
|
91
|
+
Requires [Bun](https://bun.sh).
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
bun install
|
|
95
|
+
bun run check # format + lint + typecheck + sqlite-compat suite
|
|
96
|
+
bun run format # write Biome formatting
|
|
97
|
+
bun run lint # Biome lint
|
|
98
|
+
bun run typecheck
|
|
99
|
+
bun run test:sqlite-compat # requirements + inventory gate + differential suite
|
|
100
|
+
bun test # contract + fuzz + harness
|
|
101
|
+
bun run build
|
|
102
|
+
bun run test:browser # Playwright smoke (Chrome/Firefox/Safari)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Contract tests compare the pure TypeScript engine against real SQLite (`bun:sqlite`). See [COMPATIBILITY.md](./COMPATIBILITY.md).
|
|
106
|
+
|
|
107
|
+
## Releasing
|
|
108
|
+
|
|
109
|
+
Publishing is fully automated. You never bump `version` or run `npm publish` by hand.
|
|
110
|
+
|
|
111
|
+
### How a release happens
|
|
112
|
+
|
|
113
|
+
1. Push or merge to `main` with [Conventional Commits](https://www.conventionalcommits.org/).
|
|
114
|
+
2. CI runs commitlint, format/lint/typecheck, build, package verification, tests, browser smoke, and benchmarks.
|
|
115
|
+
3. If every gate is green, [semantic-release](https://semantic-release.gitbook.io/) analyzes commits since the last git tag, bumps semver, publishes to npm, and creates a GitHub Release.
|
|
116
|
+
|
|
117
|
+
| Commit | Version bump |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| `fix: …` | patch (`0.1.0` → `0.1.1`) |
|
|
120
|
+
| `feat: …` | minor (`0.1.0` → `0.2.0`) |
|
|
121
|
+
| `feat!: …` or `BREAKING CHANGE:` footer | major (`0.2.0` → `1.0.0`) |
|
|
122
|
+
| `docs:`, `chore:`, `refactor:`, `test:`, … | no release |
|
|
123
|
+
|
|
124
|
+
Examples:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
feat: add window function support
|
|
128
|
+
fix: handle NULL in UNIQUE constraints
|
|
129
|
+
feat!: rename snapshot() return type
|
|
130
|
+
|
|
131
|
+
chore: tweak CI timeouts
|
|
132
|
+
docs: clarify determinism table
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
PR titles must also follow Conventional Commits (enforced in CI). Prefer squash merges with a conventional title.
|
|
136
|
+
|
|
137
|
+
Local checks:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
bunx commitlint --last --verbose
|
|
141
|
+
bun run build && bun run verify-package
|
|
142
|
+
# dry-run needs a GitHub token for API calls; CI publish uses Trusted Publishing (no NPM_TOKEN)
|
|
143
|
+
bun run release:dry-run
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`package.json` version is `0.0.0-development` on purpose — **git tags** (`v0.1.0`, …) are the source of truth.
|
|
147
|
+
|
|
148
|
+
### One-time setup (maintainers)
|
|
149
|
+
|
|
150
|
+
Do this once so CI can publish. Full checklist: **[docs/SECRETS.md](./docs/SECRETS.md)**.
|
|
151
|
+
|
|
152
|
+
1. **Create the package on npm (once), then Trusted Publishing.** If https://www.npmjs.com/package/@crvouga/sqlite-mem 404s:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm login --auth-type=web
|
|
156
|
+
bun run npm:seed -- --yes
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
npm does not email a publish code — complete 2FA in the browser or authenticator app.
|
|
160
|
+
|
|
161
|
+
Then on [package Access](https://www.npmjs.com/package/@crvouga/sqlite-mem/access) → Trusted Publisher → GitHub Actions (`crvouga/sqlite-mem`, workflow `ci.yml`). Do **not** create an Automation / granular access token for CI.
|
|
162
|
+
2. Confirm GitHub Actions is enabled and can create releases (default `GITHUB_TOKEN` is enough with this workflow’s permissions). No `NPM_TOKEN` repo secret.
|
|
163
|
+
3. Ensure the baseline tag exists and is pushed: `v0.1.0` (semver continues from there; the next `feat` publishes `0.2.0`).
|
|
164
|
+
|
|
165
|
+
Validate the checklist anytime with `bun run secrets:doctor`.
|
|
166
|
+
|
|
167
|
+
After that, every green push to `main` with releasable commits updates npm automatically.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|