@crvouga/sqlite-mem 1.1.2 → 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.
@@ -0,0 +1,851 @@
1
+ import {
2
+ type CatalogSection,
3
+ catalogTestFile,
4
+ type Scenario,
5
+ type ScenarioKind,
6
+ type SectionCode,
7
+ } from "./scenario-types.ts";
8
+
9
+ type Row = [suffix: string, title: string, kind?: ScenarioKind, notes?: string, extraEvidence?: string[]];
10
+
11
+ function divergenceIdFor(id: string): string | undefined {
12
+ if (id.includes("negzero")) return "negzero-canonicalization";
13
+ if (
14
+ id.startsWith("DAT-now") ||
15
+ id === "DAT-mod-08" ||
16
+ id.startsWith("DET-seed") ||
17
+ id === "DET-os-01" ||
18
+ id === "DET-eval-01" ||
19
+ id.startsWith("DET-rb") ||
20
+ id === "TXN-rb-03" ||
21
+ id.startsWith("SNP-now") ||
22
+ id === "SNP-rng-01"
23
+ ) {
24
+ return "deterministic-random-now";
25
+ }
26
+ if (id === "TYP-nan-04" || id === "TYP-nan-05") return "nan-infinity-bind";
27
+ if (id === "JSN-sub-03") return "json-api-unwrap";
28
+ if (id === "SEL-dup-01" || id === "DML-ret-02" || id === "API-ret-03") return "js-api-surface";
29
+ if (id === "CTE-mat-01") return "materialized-hint-ignored";
30
+ if (
31
+ id === "TRG-snap-01" ||
32
+ id.startsWith("SNP-omit") ||
33
+ id === "ATT-snap-01" ||
34
+ id === "FTS-snap-01"
35
+ ) {
36
+ return "snapshot-exclusions";
37
+ }
38
+ if (id === "PRG-fn-01" || id === "PRG-comp-01") return "compile-options-function-list";
39
+ if (id === "PRG-beh-05") return "user-version-snapshot";
40
+ if (id === "FTS-chg-01") return "fts-shadow-counters";
41
+ if (id === "ATT-att-01") return "attach-empty-schema";
42
+ if (id === "TOK-07") return "double-quote-string-fallback";
43
+ if (id === "UNI-surr-01") return "lone-surrogate-bind";
44
+ return undefined;
45
+ }
46
+
47
+ function section(code: SectionCode, title: string, promoted: boolean, items: Row[]): CatalogSection {
48
+ return {
49
+ code,
50
+ title,
51
+ promoted,
52
+ scenarios: items.map(([suffix, rowTitle, kind = "differential", notes, extra]) => {
53
+ const id = `${code}-${suffix}`;
54
+ const extraEvidence = extra ?? [];
55
+ const scenario: Scenario = {
56
+ id,
57
+ title: rowTitle,
58
+ kind,
59
+ evidence: [catalogTestFile(code), ...extraEvidence],
60
+ };
61
+ if (notes !== undefined) scenario.notes = notes;
62
+ if (kind === "documented_divergence") scenario.divergenceId = divergenceIdFor(id);
63
+ return scenario;
64
+ }),
65
+ };
66
+ }
67
+
68
+ const D: ScenarioKind = "documented_divergence";
69
+ const F: ScenarioKind = "fuzz";
70
+ const P: ScenarioKind = "property";
71
+ const E: ScenarioKind = "ecosystem";
72
+
73
+ const HEAD: CatalogSection[] = [
74
+ section("TOK", "Tokenizer & lexical layer", true, [
75
+ ["01", "Keywords are case-insensitive"],
76
+ ["02", "Double-quoted identifiers"],
77
+ ["03", "Backtick-quoted identifiers"],
78
+ ["04", "Bracket-quoted identifiers"],
79
+ ["05", "Embedded quote escaping in identifiers"],
80
+ ["06", "Quoted keywords as identifiers"],
81
+ ["07", "Double-quoted unknown identifier falls back to string literal", D, "mem rejects unknown double-quoted ids"],
82
+ ["08", "String literal '' escape"],
83
+ ["09", "String literals with embedded newlines"],
84
+ ["10", "Empty string literal"],
85
+ ["11", "NUL byte inside TEXT literal"],
86
+ ["12", "Empty blob literal x''"],
87
+ ["13", "Blob literal X'ABCD'"],
88
+ ["14", "Odd-length hex blob literal errors"],
89
+ ["15", "Lowercase hex blob literal"],
90
+ ["16", "Integer literal 1"],
91
+ ["17", "Unary minus on numeric literal"],
92
+ ["18", "Decimal 1.5"],
93
+ ["19", "Leading-dot decimal .5"],
94
+ ["20", "Trailing-dot decimal 5."],
95
+ ["21", "Scientific 1e10"],
96
+ ["22", "Scientific 1E-10"],
97
+ ["23", "Hex integer 0x1A"],
98
+ ["24", "Hex integer overflow beyond 64 bits errors"],
99
+ ["25", "Leading zeros on integers"],
100
+ ["26", "INT64_MAX literal"],
101
+ ["27", "INT64_MAX+1 becomes REAL"],
102
+ ["28", "Huge exponent 9e999 is Inf REAL"],
103
+ ["29", "Line comments -- to EOL"],
104
+ ["30", "Block comments /* */"],
105
+ ["31", "Unterminated block comment at EOF is accepted"],
106
+ ["32", "Comment between tokens"],
107
+ ["33", "Comment-only script"],
108
+ ["34", "Unicode identifiers"],
109
+ ["35", "Unicode string content"],
110
+ ["36", "Identifiers with $ and _"],
111
+ ["37", "Trailing semicolons"],
112
+ ["38", "Repeated semicolons"],
113
+ ["39", "Leading semicolons"],
114
+ ["40", "Empty statement in exec vs prepare/query"],
115
+ ["41", "Tab whitespace"],
116
+ ["42", "CRLF whitespace"],
117
+ ["43", "Form-feed whitespace"],
118
+ ["44", "Vertical-tab whitespace"],
119
+ ]),
120
+ section("PAR", "Parser & statement coverage", true, [
121
+ ["select-01", "SELECT parses"],
122
+ ["values-01", "VALUES statement parses"],
123
+ ["insert-01", "INSERT parses"],
124
+ ["update-01", "UPDATE parses"],
125
+ ["delete-01", "DELETE parses"],
126
+ ["create-table-01", "CREATE TABLE parses"],
127
+ ["create-index-01", "CREATE INDEX parses"],
128
+ ["create-view-01", "CREATE VIEW parses"],
129
+ ["create-trigger-01", "CREATE TRIGGER parses"],
130
+ ["create-vtable-01", "CREATE VIRTUAL TABLE parses"],
131
+ ["drop-table-01", "DROP TABLE parses"],
132
+ ["drop-index-01", "DROP INDEX parses"],
133
+ ["drop-view-01", "DROP VIEW parses"],
134
+ ["drop-trigger-01", "DROP TRIGGER parses"],
135
+ ["alter-01", "ALTER TABLE parses"],
136
+ ["begin-01", "BEGIN/COMMIT/END/ROLLBACK parse"],
137
+ ["savepoint-01", "SAVEPOINT/RELEASE parse"],
138
+ ["pragma-01", "PRAGMA parses"],
139
+ ["attach-01", "ATTACH/DETACH parse"],
140
+ ["analyze-01", "ANALYZE parses"],
141
+ ["reindex-01", "REINDEX parses"],
142
+ ["vacuum-01", "VACUUM parses"],
143
+ ["explain-01", "EXPLAIN parses"],
144
+ ["with-01", "WITH parses"],
145
+ ["prec-01", "OR binds looser than AND"],
146
+ ["prec-02", "AND binds looser than NOT"],
147
+ ["prec-03", "NOT binds looser than comparison"],
148
+ ["collate-01", "COLLATE binds tighter than unary operators"],
149
+ ["like-escape-01", "ESCAPE on LIKE"],
150
+ ["not-like-01", "NOT LIKE"],
151
+ ["not-in-01", "NOT IN"],
152
+ ["not-between-01", "NOT BETWEEN"],
153
+ ["not-glob-01", "NOT GLOB"],
154
+ ["depth-01", "Deeply nested parentheses"],
155
+ ["syntax-01", "Syntax error category at prepare time"],
156
+ ["multi-01", "Multi-statement prepare/query is misuse"],
157
+ ["multi-02", "Multi-statement exec runs all"],
158
+ ["reserved-01", "Reserved-word misuse SELECT FROM t"],
159
+ ]),
160
+ section("TYP", "Storage classes, affinity, coercion", true, [
161
+ ["aff-01", "INT* declared type → INTEGER affinity"],
162
+ ["aff-02", "CHAR/CLOB/TEXT declared type → TEXT affinity"],
163
+ ["aff-03", "BLOB or empty declared type → BLOB affinity"],
164
+ ["aff-04", "REAL/FLOA/DOUB declared type → REAL affinity"],
165
+ ["aff-05", "Other declared types → NUMERIC affinity"],
166
+ ["aff-06", "FLOATING POINT is INTEGER via INT in POINT"],
167
+ ["aff-07", "STRING declared type → NUMERIC"],
168
+ ["ins-01", "'123' into INTEGER stores INTEGER"],
169
+ ["ins-02", "'123abc' into INTEGER stays TEXT"],
170
+ ["ins-03", "'1.0' into INTEGER stores INTEGER 1"],
171
+ ["ins-04", "BLOB never converted by affinity"],
172
+ ["typeof-01", "typeof after insert paths"],
173
+ ["typeof-02", "Integer-valued REAL typeof is real"],
174
+ ["cast-01", "CAST TEXT→INTEGER prefix parse 12abc", undefined, undefined, ["tests/contract/matrices/m2-cast.test.ts"]],
175
+ ["cast-02", "CAST TEXT→INTEGER leading spaces"],
176
+ ["cast-03", "CAST 'abc' AS INTEGER is 0"],
177
+ ["cast-04", "CAST REAL→INTEGER truncates toward zero"],
178
+ ["cast-05", "CAST INTEGER→TEXT formatting"],
179
+ ["cast-06", "CAST anything→BLOB"],
180
+ ["cast-07", "CAST of NULL"],
181
+ ["cast-08", "CAST overflow clamps to int64 extremes"],
182
+ ["cast-09", "CAST '0x10' AS INTEGER is 0"],
183
+ ["cmp-01", "INTEGER vs TEXT with column affinity"],
184
+ ["cmp-02", "Bare literal '10' < 9 comparison"],
185
+ ["sort-01", "NULL sorts first"],
186
+ ["sort-02", "INTEGER/REAL interleave numerically"],
187
+ ["sort-03", "TEXT after numbers"],
188
+ ["sort-04", "BLOB after TEXT"],
189
+ ["int-01", "int64 min round-trip"],
190
+ ["int-02", "int64 max round-trip"],
191
+ ["int-03", "9223372036854775807 + 1 arithmetic"],
192
+ ["int-04", "Values beyond MAX_SAFE_INTEGER as bigint"],
193
+ ["negzero-01", "Bind -0 canonicalized to +0", D, "README determinism"],
194
+ ["negzero-02", "Arithmetic -0 canonicalized to +0", D, "README determinism"],
195
+ ["negzero-03", "min(-0.0, 0.0) is +0", D, "README determinism"],
196
+ ["blob-01", "BLOB comparison is memcmp"],
197
+ ["blob-02", "BLOB differing lengths"],
198
+ ["blob-03", "Empty blob"],
199
+ ["text-01", "TEXT comparison BINARY codepoint/byte order"],
200
+ ["nan-01", "0.0/0.0 is NULL in SQL"],
201
+ ["nan-02", "9e999 Inf REAL"],
202
+ ["nan-03", "1e308*10 overflow behavior"],
203
+ ["nan-04", "JS bind of NaN rejected datatype_mismatch", D],
204
+ ["nan-05", "JS bind of Infinity rejected datatype_mismatch", D],
205
+ ]),
206
+ section("EXP", "Operators & expression semantics", true, [
207
+ ["arith-01", "Addition across types", undefined, undefined, ["tests/contract/matrices/m1-operators.test.ts"]],
208
+ ["arith-02", "Subtraction across types"],
209
+ ["arith-03", "Multiplication across types"],
210
+ ["arith-04", "Integer division truncates toward zero"],
211
+ ["arith-05", "Division by zero is NULL"],
212
+ ["arith-06", "Modulo by zero is NULL"],
213
+ ["arith-07", "Modulo with REAL"],
214
+ ["arith-08", "Integer overflow in + - *"],
215
+ ["concat-01", "|| with NULL"],
216
+ ["concat-02", "|| formats REAL including 1.0"],
217
+ ["concat-03", "|| with blobs"],
218
+ ["concat-04", "concat() NULL handling vs ||"],
219
+ ["concat-05", "concat_ws() NULL handling"],
220
+ ["null-01", "Comparisons with NULL yield NULL"],
221
+ ["is-01", "IS / IS NOT"],
222
+ ["is-02", "IS DISTINCT FROM"],
223
+ ["is-03", "IS NOT DISTINCT FROM"],
224
+ ["between-01", "BETWEEN inclusive bounds"],
225
+ ["between-02", "BETWEEN with NULL operands"],
226
+ ["between-03", "BETWEEN with collation"],
227
+ ["in-01", "IN value list"],
228
+ ["in-02", "NOT IN empty subquery"],
229
+ ["in-03", "1 NOT IN (2, NULL) is NULL"],
230
+ ["in-04", "IN subquery"],
231
+ ["in-05", "Row-value IN SELECT"],
232
+ ["in-06", "IN with table name"],
233
+ ["like-01", "LIKE ASCII case-insensitivity"],
234
+ ["like-02", "LIKE % and _"],
235
+ ["like-03", "LIKE ESCAPE clause"],
236
+ ["like-04", "LIKE multi-char ESCAPE errors"],
237
+ ["like-05", "LIKE non-ASCII case sensitivity"],
238
+ ["like-06", "PRAGMA case_sensitive_like"],
239
+ ["like-07", "LIKE on numbers/blobs/NULL"],
240
+ ["glob-01", "GLOB is case-sensitive"],
241
+ ["glob-02", "GLOB * and ?"],
242
+ ["glob-03", "GLOB [a-z] classes"],
243
+ ["glob-04", "GLOB [^] classes"],
244
+ ["regexp-01", "REGEXP error parity"],
245
+ ["match-01", "MATCH outside FTS error parity"],
246
+ ["bit-01", "Bitwise AND OR NOT"],
247
+ ["bit-02", "Shifts and counts >= 64"],
248
+ ["bit-03", "Negative shift counts"],
249
+ ["bit-04", "Bitwise NULL propagation"],
250
+ ["bit-05", "Bitwise TEXT coerced to INTEGER"],
251
+ ["unary-01", "Unary +"],
252
+ ["unary-02", "Unary - on TEXT"],
253
+ ["not-01", "NOT 'abc' is 1"],
254
+ ["not-02", "NOT '1x' is 0"],
255
+ ["truth-01", "WHERE '1' is true"],
256
+ ["truth-02", "WHERE '1.5' is true"],
257
+ ["truth-03", "WHERE 'abc' is false"],
258
+ ["truth-04", "WHERE 0.5 is true"],
259
+ ["truth-05", "WHERE NULL is false"],
260
+ ["bool-01", "TRUE/FALSE literals"],
261
+ ["bool-02", "Column named true shadows literal"],
262
+ ["bool-03", "IS TRUE/FALSE including NULL"],
263
+ ["case-01", "Simple CASE"],
264
+ ["case-02", "Searched CASE"],
265
+ ["case-03", "CASE NULL base"],
266
+ ["case-04", "CASE without ELSE"],
267
+ ["exists-01", "EXISTS / NOT EXISTS"],
268
+ ["scalar-01", "Scalar subquery zero rows is NULL"],
269
+ ["scalar-02", "Scalar subquery multiple rows takes first"],
270
+ ["scalar-03", "Correlated scalar subquery"],
271
+ ["iif-01", "iif()"],
272
+ ["nullif-01", "nullif()"],
273
+ ["coalesce-01", "coalesce/ifnull"],
274
+ ["row-01", "Row-value equality"],
275
+ ["row-02", "Row-value ordering"],
276
+ ["row-03", "Row-value size mismatch error"],
277
+ ]),
278
+ ];
279
+
280
+ const TAIL: CatalogSection[] = [
281
+ section("FUN", "Built-in scalar functions", true, [
282
+ ["length-01", "length() TEXT codepoints"],
283
+ ["length-02", "length() BLOB bytes"],
284
+ ["length-03", "length() of numbers"],
285
+ ["octet-01", "octet_length()"],
286
+ ["substr-01", "substr negative start"],
287
+ ["substr-02", "substr start 0"],
288
+ ["substr-03", "substr negative length"],
289
+ ["substr-04", "substr on blob"],
290
+ ["substr-05", "substring() alias"],
291
+ ["instr-01", "instr text and blob mixes"],
292
+ ["replace-01", "replace empty pattern"],
293
+ ["upper-01", "upper ASCII-only"],
294
+ ["lower-01", "lower ASCII-only"],
295
+ ["trim-01", "trim/ltrim/rtrim charset"],
296
+ ["hex-01", "hex()"],
297
+ ["unhex-01", "unhex ignore-chars"],
298
+ ["unhex-02", "unhex invalid is NULL"],
299
+ ["quote-01", "quote text blobs REAL NULL"],
300
+ ["char-01", "char multiple codepoints"],
301
+ ["unicode-01", "unicode()"],
302
+ ["soundex-01", "soundex if present"],
303
+ ["printf-01", "printf/format specifiers"],
304
+ ["printf-02", "printf width precision flags"],
305
+ ["printf-03", "printf NULL args"],
306
+ ["abs-01", "abs()"],
307
+ ["abs-02", "abs(int64 min) error parity"],
308
+ ["round-01", "round 2-arg and .5"],
309
+ ["round-02", "round negative precision"],
310
+ ["sign-01", "sign()"],
311
+ ["minmax-01", "scalar min/max ignore NULLs"],
312
+ ["minmax-02", "scalar min/max 1-arg error"],
313
+ ["random-01", "random() range"],
314
+ ["randomblob-01", "randomblob N<=0 is 1 byte"],
315
+ ["zeroblob-01", "zeroblob huge N error"],
316
+ ["hint-01", "likelihood/likely/unlikely pass-through"],
317
+ ["math-01", "trig and hyperbolic domain errors"],
318
+ ["math-02", "ceil/floor/trunc types"],
319
+ ["math-03", "log family and pow"],
320
+ ["math-04", "mod sign behavior"],
321
+ ["math-05", "pi degrees radians"],
322
+ ["typeof-01", "typeof()"],
323
+ ["version-01", "sqlite_version"],
324
+ ["source-01", "sqlite_source_id"],
325
+ ["lastrow-01", "last_insert_rowid() SQL function"],
326
+ ["changes-01", "changes()/total_changes() SQL functions"],
327
+ ["like-fn-01", "like() function form"],
328
+ ["glob-fn-01", "glob() function form"],
329
+ ["coalesce-01", "coalesce 1 arg errors"],
330
+ ["null-01", "NULL argument behavior for scalars"],
331
+ ["arity-01", "wrong-arity errors"],
332
+ ]),
333
+ section("DAT", "Date & time functions", true, [
334
+ ["fn-01", "date()"],
335
+ ["fn-02", "time()"],
336
+ ["fn-03", "datetime()"],
337
+ ["fn-04", "julianday()"],
338
+ ["fn-05", "unixepoch()"],
339
+ ["fn-06", "unixepoch subsec"],
340
+ ["fn-07", "timediff()"],
341
+ ["strftime-01", "strftime common specifiers"],
342
+ ["strftime-02", "strftime remaining specifiers"],
343
+ ["strftime-03", "strftime invalid specifier"],
344
+ ["in-01", "YYYY-MM-DD input"],
345
+ ["in-02", "datetime with T separator"],
346
+ ["in-03", "fractional seconds input"],
347
+ ["in-04", "now input"],
348
+ ["in-05", "julian day number input"],
349
+ ["in-06", "unixepoch auto modifier"],
350
+ ["in-07", "malformed date is NULL"],
351
+ ["in-08", "out-of-range date is NULL"],
352
+ ["mod-01", "plus N days hours minutes"],
353
+ ["mod-02", "plus N months years"],
354
+ ["mod-03", "fractional seconds modifier"],
355
+ ["mod-04", "HH:MM offset modifier"],
356
+ ["mod-05", "start of day/month/year"],
357
+ ["mod-06", "weekday N"],
358
+ ["mod-07", "unixepoch julianday auto modifiers"],
359
+ ["mod-08", "localtime/utc modifiers", D, "fixed default clock"],
360
+ ["mod-09", "subsec floor ceiling"],
361
+ ["mod-10", "invalid modifier is NULL"],
362
+ ["cal-01", "month-end +1 month"],
363
+ ["cal-02", "leap year 2000-02-29"],
364
+ ["cal-03", "1900 is not leap"],
365
+ ["cal-04", "year 0 and 9999 bounds"],
366
+ ["now-01", "default now is 2000-01-01", D, "README"],
367
+ ["now-02", "CURRENT_TIMESTAMP/DATE/TIME", D, "README"],
368
+ ["now-03", "column DEFAULT CURRENT_TIMESTAMP", D, "README"],
369
+ ["now-04", "now system tracks wall clock", D, "README"],
370
+ ["now-05", "now fn called per statement", D, "README"],
371
+ ["now-06", "restore freezes clock", D, "README"],
372
+ ]),
373
+ section("JSN", "JSON", true, [
374
+ ["json-01", "json() minify/validate"],
375
+ ["valid-01", "json_valid"],
376
+ ["valid-02", "json_valid flags"],
377
+ ["errpos-01", "json_error_position"],
378
+ ["arr-01", "json_array"],
379
+ ["obj-01", "json_object"],
380
+ ["obj-02", "json_object odd arg count error"],
381
+ ["quote-01", "json_quote"],
382
+ ["extract-01", "json_extract single path"],
383
+ ["extract-02", "json_extract multi-path"],
384
+ ["arrow-01", "-> JSON result"],
385
+ ["arrow-02", "->> SQL value"],
386
+ ["arrow-03", "integer path shorthand"],
387
+ ["path-01", "$ and $.a.b"],
388
+ ["path-02", "$[0] and $[#-1]"],
389
+ ["path-03", "quoted path keys"],
390
+ ["path-04", "invalid path error"],
391
+ ["set-01", "json_set"],
392
+ ["insert-01", "json_insert"],
393
+ ["replace-01", "json_replace"],
394
+ ["remove-01", "json_remove multi-path order"],
395
+ ["patch-01", "json_patch RFC 7396"],
396
+ ["type-01", "json_type with path"],
397
+ ["len-01", "json_array_length"],
398
+ ["garr-01", "json_group_array"],
399
+ ["gobj-01", "json_group_object"],
400
+ ["each-01", "json_each columns"],
401
+ ["each-02", "json_each correlated"],
402
+ ["tree-01", "json_tree columns"],
403
+ ["sub-01", "JSON subtype into json_array"],
404
+ ["sub-02", "TEXT that looks like JSON vs subtype"],
405
+ ["sub-03", "API unwraps JSON subtype to string", D, "README"],
406
+ ["jsonb-01", "jsonb_* variants"],
407
+ ]),
408
+ section("AGG", "Aggregate functions", true, [
409
+ ["count-01", "count(*) vs count(x)"],
410
+ ["count-02", "count DISTINCT"],
411
+ ["sum-01", "sum empty is NULL"],
412
+ ["sum-02", "total empty is 0.0"],
413
+ ["sum-03", "sum integer overflow errors"],
414
+ ["sum-04", "total overflow is REAL"],
415
+ ["avg-01", "avg always REAL"],
416
+ ["minmax-01", "min/max cross-type"],
417
+ ["minmax-02", "min/max all-NULL"],
418
+ ["gconcat-01", "group_concat default separator"],
419
+ ["gconcat-02", "group_concat custom separator"],
420
+ ["gconcat-03", "string_agg"],
421
+ ["gconcat-04", "group_concat DISTINCT"],
422
+ ["gconcat-05", "group_concat ORDER BY"],
423
+ ["filter-01", "FILTER WHERE on aggregates"],
424
+ ["distinct-01", "DISTINCT inside aggregates"],
425
+ ["distinct-02", "multi-arg DISTINCT error"],
426
+ ["empty-01", "aggregates no GROUP BY on empty table"],
427
+ ["having-01", "HAVING without GROUP BY"],
428
+ ["bare-01", "bare column with max()"],
429
+ ["nested-01", "nested aggregates error"],
430
+ ["where-01", "aggregates in WHERE error"],
431
+ ]),
432
+ section("WIN", "Window functions", true, [
433
+ ["rank-01", "row_number"],
434
+ ["rank-02", "rank"],
435
+ ["rank-03", "dense_rank"],
436
+ ["rank-04", "percent_rank"],
437
+ ["rank-05", "cume_dist"],
438
+ ["ntile-01", "ntile remainder"],
439
+ ["ntile-02", "ntile N<=0 error"],
440
+ ["lag-01", "lag/lead offsets"],
441
+ ["lag-02", "lag/lead default value"],
442
+ ["nth-01", "first_value last_value nth_value"],
443
+ ["agg-01", "aggregates as windows"],
444
+ ["filter-01", "window FILTER"],
445
+ ["part-01", "PARTITION BY multi-key"],
446
+ ["order-01", "window ORDER BY collation"],
447
+ ["order-02", "window NULLS FIRST/LAST"],
448
+ ["frame-01", "ROWS frames"],
449
+ ["frame-02", "RANGE frames"],
450
+ ["frame-03", "GROUPS frames"],
451
+ ["frame-04", "RANGE numeric offsets"],
452
+ ["excl-01", "EXCLUDE NO OTHERS"],
453
+ ["excl-02", "EXCLUDE CURRENT ROW"],
454
+ ["excl-03", "EXCLUDE GROUP"],
455
+ ["excl-04", "EXCLUDE TIES"],
456
+ ["named-01", "WINDOW clause named windows"],
457
+ ["named-02", "window inheritance chaining"],
458
+ ["sub-01", "windows in subqueries"],
459
+ ["empty-01", "window over empty partition"],
460
+ ["peer-01", "RANGE peer/ties semantics"],
461
+ ]),
462
+ section("SEL", "SELECT core semantics", true, [
463
+ ["proj-01", "star projection"],
464
+ ["proj-02", "t.* projection"],
465
+ ["alias-01", "alias in ORDER BY"],
466
+ ["alias-02", "alias in GROUP BY"],
467
+ ["alias-03", "alias in WHERE errors"],
468
+ ["dup-01", "duplicate output names row-object collapse", D, "README values vs rows"],
469
+ ["distinct-01", "DISTINCT NULL dedup"],
470
+ ["distinct-02", "DISTINCT collation"],
471
+ ["group-01", "GROUP BY expression"],
472
+ ["group-02", "GROUP BY ordinal"],
473
+ ["group-03", "GROUP BY alias"],
474
+ ["group-04", "GROUP BY NULLs together"],
475
+ ["group-05", "GROUP BY ordinal out of range"],
476
+ ["having-01", "HAVING aggregates and bare columns"],
477
+ ["order-01", "ORDER BY ordinal alias expression"],
478
+ ["order-02", "ORDER BY COLLATE ASC DESC"],
479
+ ["order-03", "ORDER BY NULLS FIRST/LAST"],
480
+ ["limit-01", "negative LIMIT is unlimited"],
481
+ ["limit-02", "LIMIT x,y swapped form"],
482
+ ["limit-03", "expressions in LIMIT"],
483
+ ["union-01", "UNION vs UNION ALL"],
484
+ ["union-02", "INTERSECT EXCEPT"],
485
+ ["union-03", "compound column-count mismatch"],
486
+ ["union-04", "ORDER BY LIMIT apply to whole compound"],
487
+ ["values-01", "VALUES statement column1 naming"],
488
+ ["sub-01", "subquery in FROM"],
489
+ ["sub-02", "correlated subquery visibility"],
490
+ ]),
491
+ section("JOI", "Joins", true, [
492
+ ["inner-01", "INNER JOIN ON"],
493
+ ["inner-02", "INNER JOIN USING"],
494
+ ["comma-01", "implicit comma join"],
495
+ ["cross-01", "CROSS JOIN"],
496
+ ["left-01", "LEFT JOIN NULL padding"],
497
+ ["left-02", "ON vs WHERE placement"],
498
+ ["left-03", "LEFT JOIN subquery/VALUES"],
499
+ ["right-01", "RIGHT JOIN"],
500
+ ["full-01", "FULL OUTER JOIN"],
501
+ ["natural-01", "NATURAL join matching"],
502
+ ["natural-02", "NATURAL with no common columns"],
503
+ ["natural-03", "NATURAL LEFT"],
504
+ ["using-01", "USING column dedup in star"],
505
+ ["using-02", "qualified names after USING"],
506
+ ["paren-01", "join-tree parenthesization"],
507
+ ["self-01", "self-join aliases"],
508
+ ["mix-01", "three-table mixed join types"],
509
+ ["rowid-01", "join on rowid"],
510
+ ["later-01", "ON referencing later table errors"],
511
+ ]),
512
+ section("CTE", "Common table expressions", true, [
513
+ ["basic-01", "WITH basic"],
514
+ ["multi-01", "multiple CTEs"],
515
+ ["cols-01", "CTE column-name list"],
516
+ ["shadow-01", "CTE shadows real table"],
517
+ ["multi-ref-01", "CTE referenced multiple times"],
518
+ ["chain-01", "CTE references earlier CTE"],
519
+ ["fwd-01", "forward CTE reference errors"],
520
+ ["rec-01", "WITH RECURSIVE UNION dedup"],
521
+ ["rec-02", "WITH RECURSIVE UNION ALL"],
522
+ ["rec-03", "recursive term shape errors"],
523
+ ["rec-04", "LIMIT inside recursion"],
524
+ ["rec-05", "ORDER BY steers recursive queue"],
525
+ ["rec-06", "counter to N fixture"],
526
+ ["mat-01", "MATERIALIZED vs NOT MATERIALIZED", D, "both materialized"],
527
+ ["view-01", "CTE inside views"],
528
+ ["dml-01", "WITH INSERT UPDATE DELETE"],
529
+ ]),
530
+ section("DDL", "Schema definition", true, [
531
+ ["ct-01", "CREATE TABLE IF NOT EXISTS"],
532
+ ["ct-02", "quoted and keyword table names"],
533
+ ["ct-03", "column NOT NULL DEFAULT UNIQUE PK CHECK COLLATE REFERENCES"],
534
+ ["ct-04", "table-level composite PK UNIQUE CHECK FK"],
535
+ ["ct-05", "duplicate name error"],
536
+ ["ipk-01", "INTEGER PRIMARY KEY is rowid alias"],
537
+ ["ipk-02", "INTEGER PRIMARY KEY DESC is not alias"],
538
+ ["ipk-03", "INT PRIMARY KEY is not rowid alias"],
539
+ ["auto-01", "AUTOINCREMENT sqlite_sequence"],
540
+ ["auto-02", "AUTOINCREMENT after deletes"],
541
+ ["auto-03", "AUTOINCREMENT max-rowid SQLITE_FULL"],
542
+ ["wor-01", "WITHOUT ROWID requires PK"],
543
+ ["wor-02", "WITHOUT ROWID no rowid access"],
544
+ ["strict-01", "STRICT allowed types"],
545
+ ["strict-02", "STRICT ANY and WITHOUT ROWID"],
546
+ ["gen-01", "GENERATED ALWAYS VIRTUAL STORED"],
547
+ ["gen-02", "cannot INSERT into generated columns"],
548
+ ["ctas-01", "CREATE TABLE AS SELECT"],
549
+ ["alter-01", "ALTER RENAME TO"],
550
+ ["alter-02", "ALTER RENAME COLUMN"],
551
+ ["alter-03", "ALTER ADD COLUMN restrictions"],
552
+ ["alter-04", "ALTER DROP COLUMN restrictions"],
553
+ ["idx-01", "CREATE UNIQUE INDEX"],
554
+ ["idx-02", "expression and partial indexes"],
555
+ ["idx-03", "indexes never change query results"],
556
+ ["view-01", "CREATE VIEW column list"],
557
+ ["view-02", "DML on plain view errors"],
558
+ ["drop-01", "DROP IF EXISTS and cascade indexes/triggers"],
559
+ ["master-01", "sqlite_schema / sqlite_master shape"],
560
+ ["master-02", "direct writes to sqlite_master rejected"],
561
+ ["temp-01", "TEMP objects name resolution"],
562
+ ["case-01", "case-insensitive schema names"],
563
+ ]),
564
+ section("DML", "Data modification", true, [
565
+ ["ins-01", "INSERT multi-row VALUES"],
566
+ ["ins-02", "INSERT DEFAULT VALUES"],
567
+ ["ins-03", "INSERT SELECT including same table"],
568
+ ["ins-04", "column/value count mismatch"],
569
+ ["ins-05", "explicit rowid insert"],
570
+ ["ins-06", "NULL rowid auto-assign"],
571
+ ["ins-07", "negative rowids"],
572
+ ["ins-08", "rowid reuse after delete"],
573
+ ["or-01", "INSERT OR REPLACE"],
574
+ ["or-02", "INSERT OR IGNORE"],
575
+ ["or-03", "INSERT OR ABORT"],
576
+ ["or-04", "INSERT OR FAIL partial progress"],
577
+ ["or-05", "INSERT OR ROLLBACK kills txn"],
578
+ ["up-01", "UPSERT DO NOTHING"],
579
+ ["up-02", "UPSERT DO UPDATE excluded"],
580
+ ["up-03", "UPSERT conflict target WHERE"],
581
+ ["up-04", "UPSERT target-less"],
582
+ ["up-05", "multiple ON CONFLICT clauses"],
583
+ ["up-06", "UPSERT RETURNING"],
584
+ ["upd-01", "UPDATE expressions"],
585
+ ["upd-02", "UPDATE FROM"],
586
+ ["upd-03", "UPDATE rowid and PK"],
587
+ ["del-01", "DELETE WHERE"],
588
+ ["del-02", "DELETE FROM t changes count"],
589
+ ["ret-01", "RETURNING INSERT UPDATE DELETE"],
590
+ ["ret-02", "RETURNING via run discards rows", D, "API"],
591
+ ["chg-01", "changes lastInsertRowid after DML"],
592
+ ["chg-02", "exec last statement wins counters"],
593
+ ["chg-03", "trigger-driven changes not in db.changes"],
594
+ ["chg-04", "total_changes monotonic"],
595
+ ]),
596
+ section("CON", "Constraints & enforcement", true, [
597
+ ["nn-01", "NOT NULL with conflict clauses"],
598
+ ["uq-01", "UNIQUE allows multiple NULLs"],
599
+ ["uq-02", "UNIQUE composite error message"],
600
+ ["pk-01", "PRIMARY KEY NULL on rowid table auto-assigns"],
601
+ ["pk-02", "PRIMARY KEY NULL on WITHOUT ROWID"],
602
+ ["ck-01", "CHECK NULL result passes"],
603
+ ["ck-02", "CHECK on INSERT and UPDATE"],
604
+ ["fk-01", "foreign_keys default OFF"],
605
+ ["fk-02", "FK ON with parent UNIQUE/PK"],
606
+ ["fk-03", "FK CASCADE SET NULL SET DEFAULT"],
607
+ ["fk-04", "FK RESTRICT NO ACTION"],
608
+ ["fk-05", "DEFERRABLE INITIALLY DEFERRED"],
609
+ ["fk-06", "self-referential FK"],
610
+ ["fk-07", "composite FK"],
611
+ ["fk-08", "FK INSERT OR REPLACE"],
612
+ ["fk-09", "foreign_key_check and foreign_key_list"],
613
+ ["err-01", "constraint_unique sqliteCode"],
614
+ ["err-02", "constraint_notnull sqliteCode"],
615
+ ["err-03", "constraint_check sqliteCode"],
616
+ ["err-04", "constraint_foreignkey sqliteCode"],
617
+ ["err-05", "constraint_primarykey sqliteCode"],
618
+ ]),
619
+ section("TRG", "Triggers", true, [
620
+ ["bi-01", "BEFORE/AFTER INSERT UPDATE DELETE"],
621
+ ["of-01", "UPDATE OF col"],
622
+ ["when-01", "WHEN clause"],
623
+ ["old-01", "OLD/NEW visibility"],
624
+ ["ord-01", "trigger firing order is creation order"],
625
+ ["rec-01", "PRAGMA recursive_triggers"],
626
+ ["raise-01", "RAISE ABORT FAIL ROLLBACK"],
627
+ ["raise-02", "RAISE IGNORE"],
628
+ ["instead-01", "INSTEAD OF on views"],
629
+ ["fk-01", "triggers and FK cascade ordering"],
630
+ ["chg-01", "triggers do not affect db.changes"],
631
+ ["drop-01", "DROP TABLE drops triggers"],
632
+ ["snap-01", "triggers not encoded in snapshots", D, "README"],
633
+ ]),
634
+ section("TXN", "Transactions & savepoints", true, [
635
+ ["begin-01", "BEGIN DEFERRED IMMEDIATE EXCLUSIVE"],
636
+ ["commit-01", "COMMIT and END"],
637
+ ["rb-01", "ROLLBACK"],
638
+ ["nest-01", "nested BEGIN errors"],
639
+ ["commit-02", "COMMIT with no txn errors"],
640
+ ["sp-01", "SAVEPOINT name scoping"],
641
+ ["sp-02", "RELEASE releases through"],
642
+ ["sp-03", "ROLLBACK TO keeps savepoint"],
643
+ ["sp-04", "savepoint outside txn"],
644
+ ["atom-01", "failed multi-row INSERT ABORT atomicity"],
645
+ ["api-01", "db.transaction commit on return"],
646
+ ["api-02", "db.transaction rollback on throw"],
647
+ ["api-03", "nested transaction uses savepoints"],
648
+ ["api-04", "close inside transaction is misuse"],
649
+ ["rb-02", "rollback restores schema"],
650
+ ["rb-03", "rollback restores PRNG", D, "README"],
651
+ ["close-01", "close mid-transaction rolls back"],
652
+ ]),
653
+ section("PRG", "PRAGMA surface", true, [
654
+ ["ti-01", "table_info / table_xinfo"],
655
+ ["idx-01", "index_list index_info index_xinfo"],
656
+ ["db-01", "database_list"],
657
+ ["fk-01", "foreign_key_list"],
658
+ ["fn-01", "function_list", D, "sqlite-mem own set"],
659
+ ["col-01", "collation_list"],
660
+ ["tl-01", "table_list"],
661
+ ["tvf-01", "pragma_* TVFs correlated"],
662
+ ["beh-01", "foreign_keys pragma"],
663
+ ["beh-02", "defer_foreign_keys"],
664
+ ["beh-03", "recursive_triggers"],
665
+ ["beh-04", "case_sensitive_like"],
666
+ ["beh-05", "user_version get/set", D, "snapshot exclusion"],
667
+ ["beh-06", "schema_version bumps on DDL"],
668
+ ["beh-07", "application_id"],
669
+ ["health-01", "integrity_check quick_check ok"],
670
+ ["health-02", "foreign_key_check rows"],
671
+ ["stor-01", "journal_mode memory default"],
672
+ ["stor-02", "encoding UTF-8"],
673
+ ["unk-01", "unknown pragma empty success"],
674
+ ["schema-01", "schema-prefixed pragma"],
675
+ ["comp-01", "compile_options sqlite-mem set", D],
676
+ ]),
677
+ section("COL", "Collations", true, [
678
+ ["bin-01", "BINARY collation"],
679
+ ["nc-01", "NOCASE ASCII-only"],
680
+ ["rt-01", "RTRIM trailing spaces"],
681
+ ["eq-01", "collation on ="],
682
+ ["ord-01", "collation on ORDER BY"],
683
+ ["grp-01", "collation on GROUP BY"],
684
+ ["dist-01", "collation on DISTINCT"],
685
+ ["in-01", "collation on IN BETWEEN"],
686
+ ["res-01", "COLLATE operator beats column"],
687
+ ["res-02", "binary operator uses left collation"],
688
+ ["idx-01", "NOCASE unique index"],
689
+ ["unk-01", "unknown collation error"],
690
+ ]),
691
+ section("FTS", "Full-text search & virtual tables", true, [
692
+ ["f5-01", "FTS5 CREATE VIRTUAL TABLE"],
693
+ ["f5-02", "FTS5 INSERT UPDATE DELETE"],
694
+ ["f5-03", "MATCH AND OR NOT"],
695
+ ["f5-04", "MATCH NEAR phrases prefix"],
696
+ ["f5-05", "column filters"],
697
+ ["f5-06", "rank and bm25"],
698
+ ["f5-07", "highlight snippet"],
699
+ ["f5-08", "fts5 special commands"],
700
+ ["f34-01", "FTS3/4 MATCH"],
701
+ ["f34-02", "matchinfo offsets"],
702
+ ["chg-01", "shadow-table change counters", D, "README"],
703
+ ["snap-01", "virtual tables not in snapshots", D, "README"],
704
+ ["series-01", "generate_series"],
705
+ ]),
706
+ section("ATT", "ATTACH / DETACH / schemas", true, [
707
+ ["att-01", "ATTACH anything is empty in-memory schema", D, "filename ignored for data"],
708
+ ["att-02", "duplicate schema name error"],
709
+ ["det-01", "DETACH unknown name error"],
710
+ ["det-02", "cannot detach main/temp"],
711
+ ["qual-01", "qualified schema.table names"],
712
+ ["res-01", "temp then main then attached resolution"],
713
+ ["amb-01", "ambiguity errors"],
714
+ ["cross-01", "cross-schema queries and joins"],
715
+ ["list-01", "database_list reflects attachments"],
716
+ ["snap-01", "snapshot excludes attached schemas", D, "README"],
717
+ ]),
718
+ section("API", "JavaScript surface contracts", true, [
719
+ ["exec-01", "exec multi-statement void"],
720
+ ["exec-02", "exec rejects binds"],
721
+ ["exec-03", "exec partial failure persists prior"],
722
+ ["query-01", "query single-statement"],
723
+ ["query-02", "query positional binds"],
724
+ ["prep-01", "prepare-time syntax errors"],
725
+ ["prep-02", "prepared statement reuse"],
726
+ ["prep-03", "schema invalidation re-prepare"],
727
+ ["run-01", "run all get result shapes"],
728
+ ["run-02", "get zero rows undefined"],
729
+ ["run-03", "result empty values for zero rows"],
730
+ ["run-04", "run on SELECT discards rows"],
731
+ ["run-05", "all on INSERT RETURNING"],
732
+ ["bind-01", "accepted bind types"],
733
+ ["bind-02", "rejected bind types"],
734
+ ["bind-03", "blob binds are copied"],
735
+ ["named-01", "named params first-occurrence order"],
736
+ ["named-02", "@x $x :x are distinct"],
737
+ ["named-03", "?NNN indexing"],
738
+ ["ret-01", "bigint threshold"],
739
+ ["ret-02", "Uint8Array freshness"],
740
+ ["ret-03", "duplicate column last-write-wins"],
741
+ ["close-01", "close idempotent and misuse after"],
742
+ ["close-02", "Symbol.dispose"],
743
+ ["txn-01", "query inside transaction(fn)"],
744
+ ["sync-01", "methods return non-Promises"],
745
+ ]),
746
+ section("SNP", "Snapshot / restore", true, [
747
+ ["rt-01", "round-trip schema and rows"],
748
+ ["rt-02", "round-trip blobs unicode NUL"],
749
+ ["rt-03", "round-trip counters sqlite_sequence"],
750
+ ["rt-04", "round-trip PRNG and clock"],
751
+ ["byte-01", "byte-identical equivalent DBs"],
752
+ ["hdr-01", "SQLM magic and version"],
753
+ ["hdr-02", "corrupt magic error"],
754
+ ["hdr-03", "truncated blob error"],
755
+ ["hdr-04", "future version snapshot_version"],
756
+ ["txn-01", "restore during txn errors"],
757
+ ["rep-01", "restore replaces entire state"],
758
+ ["now-01", "restore keeps system clock live", D],
759
+ ["now-02", "restore overwrites Date fn", D],
760
+ ["rng-01", "restore with random os does not rewind", D],
761
+ ["omit-01", "triggers not encoded", D],
762
+ ["omit-02", "ATTACH not encoded", D],
763
+ ["omit-03", "virtual tables not encoded", D],
764
+ ["omit-04", "user_version not encoded", D],
765
+ ]),
766
+ section("DET", "Determinism invariants", true, [
767
+ ["seed-01", "same seed identical random streams", D],
768
+ ["seed-02", "different seeds diverge", D],
769
+ ["os-01", "random os full-range int64", D],
770
+ ["eval-01", "PRNG consumption in CASE", D],
771
+ ["rb-01", "PRNG rolls back with ROLLBACK", D],
772
+ ["rb-02", "PRNG does not roll back on COMMIT", D],
773
+ ["scan-01", "full-table scans in rowid order"],
774
+ ["negzero-01", "-0 to +0 at bind affinity arithmetic snapshot", D],
775
+ ]),
776
+ section("ERR", "Error parity", true, [
777
+ ["cat-01", "syntax category and sqliteCode"],
778
+ ["cat-02", "no such table"],
779
+ ["cat-03", "no such column"],
780
+ ["cat-04", "UNIQUE constraint failed message"],
781
+ ["cat-05", "datatype mismatch"],
782
+ ["cat-06", "near syntax error"],
783
+ ["time-01", "syntax at prepare"],
784
+ ["time-02", "no such table at prepare"],
785
+ ["time-03", "constraint at run"],
786
+ ["state-01", "errors leave DB usable"],
787
+ ["inst-01", "instanceof SqliteError"],
788
+ ]),
789
+ section("UNI", "Unicode, encoding, weird text", true, [
790
+ ["utf-01", "multi-byte UTF-8 round-trip"],
791
+ ["len-01", "length counts codepoints"],
792
+ ["astral-01", "astral-plane in length substr instr"],
793
+ ["surr-01", "lone surrogates from JS binds", D],
794
+ ["nul-01", "embedded NUL in TEXT"],
795
+ ["fold-01", "upper/lower/NOCASE/LIKE ASCII only"],
796
+ ["char-01", "char/unicode round trip"],
797
+ ["hex-01", "hex of multi-byte via CAST blob"],
798
+ ]),
799
+ section("LIM", "Limits & pathological inputs", true, [
800
+ ["depth-01", "expression depth near limit"],
801
+ ["cmpd-01", "compound SELECT term count"],
802
+ ["cols-01", "columns per table"],
803
+ ["vals-01", "terms in VALUES"],
804
+ ["in-01", "large IN list"],
805
+ ["ident-01", "identifier length"],
806
+ ["like-01", "LIKE pattern length"],
807
+ ["zero-01", "empty table empty string PK"],
808
+ ["zero-02", "SELECT with no FROM"],
809
+ ["fuzz-01", "past fuzz failures as named contracts"],
810
+ ]),
811
+ section("FZZ", "Differential fuzz & property harness", true, [
812
+ ["diff-01", "grammar-based differential fuzz", F],
813
+ ["join-01", "join-weighted fuzz", F],
814
+ ["aff-01", "affinity coercion fuzz", F],
815
+ ["win-01", "window frame fuzz", F],
816
+ ["up-01", "UPSERT fuzz", F],
817
+ ["date-01", "date modifier fuzz", F],
818
+ ["prop-01", "snapshot restore idempotence", P],
819
+ ["prop-02", "insert then delete snapshot bytes", P],
820
+ ["prop-03", "index-added vs index-free equivalence", P],
821
+ ["prop-04", "transaction throw never ran", P],
822
+ ["prop-05", "exec a;b equivalent split exec", P],
823
+ ["seed-01", "default seed 0x5a17e0e1", F],
824
+ ["replay-01", "SQLITE_MEM_FUZZ_SEED PATH replay", F],
825
+ ["gate-01", "fail-closed catalog mapping", P],
826
+ ]),
827
+ section("ECO", "Ecosystem integration smoke", true, [
828
+ ["kysely-01", "Kysely introspection pragmas", E],
829
+ ["drizzle-01", "Drizzle-style CRUD", E],
830
+ ["knex-01", "Knex-style queries", E],
831
+ ["prisma-01", "Prisma-style introspection", E],
832
+ ["mig-01", "migration-runner transactional DDL", E],
833
+ ["b3-01", "absent better-sqlite3 extras error", E],
834
+ ["readme-01", "README pitfalls as tests", E],
835
+ ["node-01", "Node canonical script smoke", E],
836
+ ]),
837
+ ];
838
+
839
+ export const SCENARIO_CATALOG: CatalogSection[] = [...HEAD, ...TAIL];
840
+
841
+ export function allScenarios(): Scenario[] {
842
+ return SCENARIO_CATALOG.flatMap((section) => section.scenarios);
843
+ }
844
+
845
+ export function scenarioById(): Map<string, Scenario> {
846
+ return new Map(allScenarios().map((scenario) => [scenario.id, scenario]));
847
+ }
848
+
849
+ export function knownScenarioIds(): Set<string> {
850
+ return new Set(allScenarios().map((scenario) => scenario.id));
851
+ }