@minnowdb/core 0.2.1 → 0.4.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/README.md +23 -32
- package/dist/block-format/block.d.ts +32 -13
- package/dist/block-format/block.js +179 -55
- package/dist/block-format/checksum.d.ts +2 -1
- package/dist/block-format/checksum.js +5 -2
- package/dist/block-format/codecs.d.ts +7 -2
- package/dist/block-format/codecs.js +53 -12
- package/dist/block-format/column.d.ts +3 -2
- package/dist/block-format/column.js +96 -30
- package/dist/block-format/index.d.ts +2 -2
- package/dist/block-format/index.js +2 -2
- package/dist/block-format/physical.d.ts +8 -2
- package/dist/block-format/physical.js +14 -6
- package/dist/block-format/types.d.ts +7 -3
- package/dist/block-format/types.js +0 -1
- package/dist/block-format/unicode.d.ts +11 -0
- package/dist/block-format/unicode.js +46 -0
- package/dist/date-value.d.ts +15 -0
- package/dist/date-value.js +64 -0
- package/dist/engine/artifact-cache.d.ts +2 -1
- package/dist/engine/artifact-cache.js +5 -1
- package/dist/engine/batch.d.ts +11 -3
- package/dist/engine/batch.js +17 -7
- package/dist/engine/buffered-writer.d.ts +2 -1
- package/dist/engine/buffered-writer.js +34 -9
- package/dist/engine/cache-limits.d.ts +25 -0
- package/dist/engine/cache-limits.js +25 -0
- package/dist/engine/catalog.d.ts +24 -5
- package/dist/engine/catalog.js +34 -7
- package/dist/engine/client.d.ts +29 -7
- package/dist/engine/client.js +216 -40
- package/dist/engine/database.d.ts +224 -39
- package/dist/engine/database.js +7475 -1539
- package/dist/engine/defaults.d.ts +4 -8
- package/dist/engine/defaults.js +46 -22
- package/dist/engine/errors.d.ts +19 -1
- package/dist/engine/errors.js +32 -2
- package/dist/engine/fts.d.ts +0 -6
- package/dist/engine/fts.js +41 -14
- package/dist/engine/group-index.d.ts +0 -1
- package/dist/engine/group-index.js +6 -11
- package/dist/engine/index.d.ts +16 -10
- package/dist/engine/index.js +12 -9
- package/dist/engine/join-index.d.ts +0 -1
- package/dist/engine/join-index.js +2 -2
- package/dist/engine/keyed-live.d.ts +57 -0
- package/dist/engine/keyed-live.js +226 -0
- package/dist/engine/live-api.d.ts +4 -0
- package/dist/engine/live-api.js +4 -0
- package/dist/engine/live.d.ts +43 -26
- package/dist/engine/live.js +504 -126
- package/dist/engine/memory.d.ts +2 -1
- package/dist/engine/memory.js +3 -2
- package/dist/engine/optimizer.d.ts +0 -1
- package/dist/engine/optimizer.js +262 -27
- package/dist/engine/query-api.d.ts +3 -0
- package/dist/engine/query-api.js +3 -0
- package/dist/engine/query-cache.d.ts +1 -2
- package/dist/engine/query-cache.js +7 -5
- package/dist/engine/query.d.ts +134 -29
- package/dist/engine/query.js +1668 -372
- package/dist/engine/result-wire.d.ts +0 -1
- package/dist/engine/result-wire.js +2 -2
- package/dist/engine/schema-wire.d.ts +6 -3
- package/dist/engine/schema-wire.js +40 -34
- package/dist/engine/schema.d.ts +156 -80
- package/dist/engine/schema.js +570 -108
- package/dist/engine/sort-keys.d.ts +4 -4
- package/dist/engine/sort-keys.js +44 -29
- package/dist/engine/sql-domains.d.ts +31 -0
- package/dist/engine/sql-domains.js +585 -0
- package/dist/engine/sql-driver.d.ts +19 -0
- package/dist/engine/sql-driver.js +1 -0
- package/dist/engine/sql-json.d.ts +7 -9
- package/dist/engine/sql-json.js +75 -15
- package/dist/engine/sql-semantics.d.ts +8 -3
- package/dist/engine/sql-semantics.js +458 -30
- package/dist/engine/typed-live.d.ts +67 -0
- package/dist/engine/typed-live.js +349 -0
- package/dist/engine/vector.d.ts +12 -2
- package/dist/engine/vector.js +635 -119
- package/dist/engine/worker-host.d.ts +9 -2
- package/dist/engine/worker-host.js +620 -152
- package/dist/engine/worker.d.ts +0 -1
- package/dist/engine/worker.js +3 -3
- package/dist/engine/write-block-planner.d.ts +18 -0
- package/dist/engine/write-block-planner.js +112 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/plan/index.d.ts +3 -4
- package/dist/plan/index.js +3 -4
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/indexeddb.d.ts +99 -51
- package/dist/storage/indexeddb.js +13448 -2660
- package/dist/storage/memory.d.ts +64 -57
- package/dist/storage/memory.js +1042 -128
- package/dist/storage/opfs/files.d.ts +18 -7
- package/dist/storage/opfs/files.js +115 -28
- package/dist/storage/opfs/index.d.ts +1 -1
- package/dist/storage/opfs/index.js +1 -1
- package/dist/storage/opfs/leader.d.ts +409 -75
- package/dist/storage/opfs/leader.js +4621 -650
- package/dist/storage/opfs/rpc.d.ts +15 -3
- package/dist/storage/opfs/rpc.js +224 -2
- package/dist/storage/opfs/snapshot-ledger.d.ts +40 -0
- package/dist/storage/opfs/snapshot-ledger.js +281 -0
- package/dist/storage/opfs/store.d.ts +33 -99
- package/dist/storage/opfs/store.js +453 -364
- package/dist/storage/persistence.d.ts +37 -0
- package/dist/storage/persistence.js +78 -0
- package/dist/storage/snapshot-stream.d.ts +24 -0
- package/dist/storage/snapshot-stream.js +897 -0
- package/dist/storage/snapshot.d.ts +9 -85
- package/dist/storage/snapshot.js +33 -265
- package/dist/storage/toolkit/extents.d.ts +41 -7
- package/dist/storage/toolkit/extents.js +402 -39
- package/dist/storage/toolkit/index.d.ts +4 -5
- package/dist/storage/toolkit/index.js +28 -4
- package/dist/storage/toolkit/record-core.d.ts +182 -55
- package/dist/storage/toolkit/record-core.js +6158 -1331
- package/dist/storage/toolkit/sync-file.d.ts +10 -1
- package/dist/storage/toolkit/sync-file.js +50 -2
- package/dist/storage/toolkit/wal.d.ts +23 -5
- package/dist/storage/toolkit/wal.js +89 -27
- package/dist/storage/toolkit/wire.d.ts +15 -2
- package/dist/storage/toolkit/wire.js +199 -10
- package/dist/storage/types.d.ts +1439 -204
- package/dist/storage/types.js +1745 -141
- package/dist/testing/block-store-conformance.d.ts +0 -1
- package/dist/testing/block-store-conformance.js +1009 -119
- package/dist/testing/index.d.ts +46 -26
- package/dist/testing/index.js +112 -57
- package/dist/testing/opfs-shim.d.ts +13 -3
- package/dist/testing/opfs-shim.js +40 -6
- package/dist/testing/simulator.d.ts +97 -0
- package/dist/testing/simulator.js +591 -0
- package/dist/testing/sqllogictest.d.ts +89 -0
- package/dist/testing/sqllogictest.js +434 -0
- package/dist/transactions/index.d.ts +92 -16
- package/dist/transactions/index.js +1074 -236
- package/dist/worker-protocol/index.d.ts +3 -2
- package/dist/worker-protocol/index.js +2 -5
- package/package.json +53 -3
- package/postgres-feature-profile.json +223 -0
- package/sql-feature-matrix.json +172 -252
- package/dist/block-format/block.d.ts.map +0 -1
- package/dist/block-format/block.js.map +0 -1
- package/dist/block-format/checksum.d.ts.map +0 -1
- package/dist/block-format/checksum.js.map +0 -1
- package/dist/block-format/codecs.d.ts.map +0 -1
- package/dist/block-format/codecs.js.map +0 -1
- package/dist/block-format/column.d.ts.map +0 -1
- package/dist/block-format/column.js.map +0 -1
- package/dist/block-format/index.d.ts.map +0 -1
- package/dist/block-format/index.js.map +0 -1
- package/dist/block-format/physical.d.ts.map +0 -1
- package/dist/block-format/physical.js.map +0 -1
- package/dist/block-format/types.d.ts.map +0 -1
- package/dist/block-format/types.js.map +0 -1
- package/dist/engine/artifact-cache.d.ts.map +0 -1
- package/dist/engine/artifact-cache.js.map +0 -1
- package/dist/engine/batch.d.ts.map +0 -1
- package/dist/engine/batch.js.map +0 -1
- package/dist/engine/buffered-writer.d.ts.map +0 -1
- package/dist/engine/buffered-writer.js.map +0 -1
- package/dist/engine/catalog.d.ts.map +0 -1
- package/dist/engine/catalog.js.map +0 -1
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/coordinator.d.ts +0 -17
- package/dist/engine/coordinator.d.ts.map +0 -1
- package/dist/engine/coordinator.js +0 -60
- package/dist/engine/coordinator.js.map +0 -1
- package/dist/engine/database.d.ts.map +0 -1
- package/dist/engine/database.js.map +0 -1
- package/dist/engine/defaults.d.ts.map +0 -1
- package/dist/engine/defaults.js.map +0 -1
- package/dist/engine/errors.d.ts.map +0 -1
- package/dist/engine/errors.js.map +0 -1
- package/dist/engine/fts.d.ts.map +0 -1
- package/dist/engine/fts.js.map +0 -1
- package/dist/engine/group-index.d.ts.map +0 -1
- package/dist/engine/group-index.js.map +0 -1
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/join-index.d.ts.map +0 -1
- package/dist/engine/join-index.js.map +0 -1
- package/dist/engine/live.d.ts.map +0 -1
- package/dist/engine/live.js.map +0 -1
- package/dist/engine/memory.d.ts.map +0 -1
- package/dist/engine/memory.js.map +0 -1
- package/dist/engine/optimizer.d.ts.map +0 -1
- package/dist/engine/optimizer.js.map +0 -1
- package/dist/engine/query-cache.d.ts.map +0 -1
- package/dist/engine/query-cache.js.map +0 -1
- package/dist/engine/query.d.ts.map +0 -1
- package/dist/engine/query.js.map +0 -1
- package/dist/engine/result-wire.d.ts.map +0 -1
- package/dist/engine/result-wire.js.map +0 -1
- package/dist/engine/schema-wire.d.ts.map +0 -1
- package/dist/engine/schema-wire.js.map +0 -1
- package/dist/engine/schema.d.ts.map +0 -1
- package/dist/engine/schema.js.map +0 -1
- package/dist/engine/sort-keys.d.ts.map +0 -1
- package/dist/engine/sort-keys.js.map +0 -1
- package/dist/engine/sql-json.d.ts.map +0 -1
- package/dist/engine/sql-json.js.map +0 -1
- package/dist/engine/sql-semantics.d.ts.map +0 -1
- package/dist/engine/sql-semantics.js.map +0 -1
- package/dist/engine/vector.d.ts.map +0 -1
- package/dist/engine/vector.js.map +0 -1
- package/dist/engine/worker-host.d.ts.map +0 -1
- package/dist/engine/worker-host.js.map +0 -1
- package/dist/engine/worker.d.ts.map +0 -1
- package/dist/engine/worker.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plan/index.d.ts.map +0 -1
- package/dist/plan/index.js.map +0 -1
- package/dist/storage/fixture-shape.d.ts +0 -42
- package/dist/storage/fixture-shape.d.ts.map +0 -1
- package/dist/storage/fixture-shape.js +0 -146
- package/dist/storage/fixture-shape.js.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/indexeddb.d.ts.map +0 -1
- package/dist/storage/indexeddb.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/opfs/files.d.ts.map +0 -1
- package/dist/storage/opfs/files.js.map +0 -1
- package/dist/storage/opfs/index.d.ts.map +0 -1
- package/dist/storage/opfs/index.js.map +0 -1
- package/dist/storage/opfs/leader.d.ts.map +0 -1
- package/dist/storage/opfs/leader.js.map +0 -1
- package/dist/storage/opfs/rpc.d.ts.map +0 -1
- package/dist/storage/opfs/rpc.js.map +0 -1
- package/dist/storage/opfs/store.d.ts.map +0 -1
- package/dist/storage/opfs/store.js.map +0 -1
- package/dist/storage/snapshot.d.ts.map +0 -1
- package/dist/storage/snapshot.js.map +0 -1
- package/dist/storage/toolkit/extents.d.ts.map +0 -1
- package/dist/storage/toolkit/extents.js.map +0 -1
- package/dist/storage/toolkit/index.d.ts.map +0 -1
- package/dist/storage/toolkit/index.js.map +0 -1
- package/dist/storage/toolkit/record-core.d.ts.map +0 -1
- package/dist/storage/toolkit/record-core.js.map +0 -1
- package/dist/storage/toolkit/sync-file.d.ts.map +0 -1
- package/dist/storage/toolkit/sync-file.js.map +0 -1
- package/dist/storage/toolkit/wal.d.ts.map +0 -1
- package/dist/storage/toolkit/wal.js.map +0 -1
- package/dist/storage/toolkit/wire.d.ts.map +0 -1
- package/dist/storage/toolkit/wire.js.map +0 -1
- package/dist/storage/types.d.ts.map +0 -1
- package/dist/storage/types.js.map +0 -1
- package/dist/testing/block-store-conformance.d.ts.map +0 -1
- package/dist/testing/block-store-conformance.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/opfs-shim.d.ts.map +0 -1
- package/dist/testing/opfs-shim.js.map +0 -1
- package/dist/testing/seeds.d.ts +0 -11
- package/dist/testing/seeds.d.ts.map +0 -1
- package/dist/testing/seeds.js +0 -50
- package/dist/testing/seeds.js.map +0 -1
- package/dist/transactions/index.d.ts.map +0 -1
- package/dist/transactions/index.js.map +0 -1
- package/dist/worker-protocol/index.d.ts.map +0 -1
- package/dist/worker-protocol/index.js.map +0 -1
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
export class SqlLogicParseError extends Error {
|
|
2
|
+
location;
|
|
3
|
+
constructor(message, location) {
|
|
4
|
+
super(`${location.file}:${String(location.line)}: ${message}`);
|
|
5
|
+
this.location = location;
|
|
6
|
+
this.name = "SqlLogicParseError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export class SqlLogicFailure extends Error {
|
|
10
|
+
location;
|
|
11
|
+
sql;
|
|
12
|
+
constructor(message, location, sql, options) {
|
|
13
|
+
super(`${location.file}:${String(location.line)}: ${message}${sql === undefined ? "" : `\n${sql}`}`, options);
|
|
14
|
+
this.location = location;
|
|
15
|
+
this.sql = sql;
|
|
16
|
+
this.name = "SqlLogicFailure";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/** Parses the original SQLite SQLLogicTest format, rejecting unknown extensions. */
|
|
20
|
+
export function parseSqlLogicTest(source, file = "<memory>") {
|
|
21
|
+
const groups = splitRecordGroups(source);
|
|
22
|
+
return groups.map((group) => parseRecord(group, file));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parses a line source one record at a time. The full upstream corpus contains very large files;
|
|
26
|
+
* this form bounds parser memory to the largest individual record instead of the largest file.
|
|
27
|
+
*/
|
|
28
|
+
export async function* parseSqlLogicTestLines(lines, file = "<stream>") {
|
|
29
|
+
let current = [];
|
|
30
|
+
let lineNumber = 0;
|
|
31
|
+
const finish = () => {
|
|
32
|
+
if (current.length === 0)
|
|
33
|
+
return undefined;
|
|
34
|
+
const record = parseRecord({ lines: current }, file);
|
|
35
|
+
current = [];
|
|
36
|
+
return record;
|
|
37
|
+
};
|
|
38
|
+
for await (const original of lines) {
|
|
39
|
+
lineNumber++;
|
|
40
|
+
const text = original.endsWith("\r") ? original.slice(0, -1) : original;
|
|
41
|
+
if (text.startsWith("#"))
|
|
42
|
+
continue;
|
|
43
|
+
if (text.trim().length === 0) {
|
|
44
|
+
const record = finish();
|
|
45
|
+
if (record !== undefined)
|
|
46
|
+
yield record;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
current.push({ text, number: lineNumber });
|
|
50
|
+
}
|
|
51
|
+
const record = finish();
|
|
52
|
+
if (record !== undefined)
|
|
53
|
+
yield record;
|
|
54
|
+
}
|
|
55
|
+
function splitRecordGroups(source) {
|
|
56
|
+
const lines = source.replaceAll("\r\n", "\n").replaceAll("\r", "\n").split("\n");
|
|
57
|
+
const groups = [];
|
|
58
|
+
let current = [];
|
|
59
|
+
const finish = () => {
|
|
60
|
+
if (current.length > 0)
|
|
61
|
+
groups.push({ lines: current });
|
|
62
|
+
current = [];
|
|
63
|
+
};
|
|
64
|
+
for (const [index, text] of lines.entries()) {
|
|
65
|
+
if (text.startsWith("#"))
|
|
66
|
+
continue;
|
|
67
|
+
if (text.trim().length === 0) {
|
|
68
|
+
finish();
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
current.push({ text, number: index + 1 });
|
|
72
|
+
}
|
|
73
|
+
finish();
|
|
74
|
+
return groups;
|
|
75
|
+
}
|
|
76
|
+
function parseRecord(group, file) {
|
|
77
|
+
let index = 0;
|
|
78
|
+
const conditions = [];
|
|
79
|
+
while (index < group.lines.length) {
|
|
80
|
+
const line = requireLine(group, index, file);
|
|
81
|
+
const tokens = tokenizeDirective(line.text);
|
|
82
|
+
if (tokens[0] !== "skipif" && tokens[0] !== "onlyif")
|
|
83
|
+
break;
|
|
84
|
+
if (tokens.length !== 2)
|
|
85
|
+
fail("conditional must name exactly one engine", file, line.number);
|
|
86
|
+
conditions.push({
|
|
87
|
+
kind: tokens[0],
|
|
88
|
+
engine: tokens[1] ?? "",
|
|
89
|
+
location: { file, line: line.number },
|
|
90
|
+
});
|
|
91
|
+
index++;
|
|
92
|
+
}
|
|
93
|
+
const header = requireLine(group, index, file);
|
|
94
|
+
const tokens = tokenizeDirective(header.text);
|
|
95
|
+
const location = { file, line: header.number };
|
|
96
|
+
if (tokens[0] === "statement") {
|
|
97
|
+
if (tokens.length !== 2 || (tokens[1] !== "ok" && tokens[1] !== "error")) {
|
|
98
|
+
fail("statement must be 'statement ok' or 'statement error'", file, header.number);
|
|
99
|
+
}
|
|
100
|
+
const sql = sqlLines(group.lines.slice(index + 1));
|
|
101
|
+
if (sql.length === 0)
|
|
102
|
+
fail("statement has no SQL", file, header.number);
|
|
103
|
+
return {
|
|
104
|
+
kind: "statement",
|
|
105
|
+
expectation: tokens[1],
|
|
106
|
+
sql,
|
|
107
|
+
conditions,
|
|
108
|
+
location,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (tokens[0] === "query") {
|
|
112
|
+
if (tokens.length < 2 || tokens.length > 4) {
|
|
113
|
+
fail("query must be 'query <types> [sort-mode] [label]'", file, header.number);
|
|
114
|
+
}
|
|
115
|
+
const typeString = tokens[1] ?? "";
|
|
116
|
+
const types = [];
|
|
117
|
+
for (const type of typeString)
|
|
118
|
+
types.push(type);
|
|
119
|
+
if (types.length === 0 || types.some((type) => type !== "I" && type !== "R" && type !== "T")) {
|
|
120
|
+
fail("query type string must contain only I, R, and T", file, header.number);
|
|
121
|
+
}
|
|
122
|
+
const sortMode = tokens[2] ?? "nosort";
|
|
123
|
+
if (sortMode !== "nosort" && sortMode !== "rowsort" && sortMode !== "valuesort") {
|
|
124
|
+
fail(`unknown query sort mode '${sortMode}'`, file, header.number);
|
|
125
|
+
}
|
|
126
|
+
const body = group.lines.slice(index + 1);
|
|
127
|
+
const separator = body.findIndex((line) => line.text === "----");
|
|
128
|
+
const queryLines = separator < 0 ? body : body.slice(0, separator);
|
|
129
|
+
const sql = sqlLines(queryLines);
|
|
130
|
+
if (sql.length === 0)
|
|
131
|
+
fail("query has no SQL", file, header.number);
|
|
132
|
+
const expectedLines = separator < 0 ? [] : body.slice(separator + 1).map((line) => line.text);
|
|
133
|
+
return {
|
|
134
|
+
kind: "query",
|
|
135
|
+
types: types,
|
|
136
|
+
sortMode,
|
|
137
|
+
...(tokens[3] === undefined ? {} : { label: tokens[3] }),
|
|
138
|
+
sql,
|
|
139
|
+
expected: parseExpected(expectedLines, file, header.number),
|
|
140
|
+
conditions,
|
|
141
|
+
location,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (conditions.length > 0) {
|
|
145
|
+
fail("conditionals may prefix only a statement or query", file, header.number);
|
|
146
|
+
}
|
|
147
|
+
if (tokens[0] === "hash-threshold") {
|
|
148
|
+
if (tokens.length !== 2 || !isNonNegativeInteger(tokens[1])) {
|
|
149
|
+
fail("hash-threshold must be a non-negative whole number", file, header.number);
|
|
150
|
+
}
|
|
151
|
+
return { kind: "hash-threshold", valueCount: Number(tokens[1]), location };
|
|
152
|
+
}
|
|
153
|
+
if (tokens[0] === "halt") {
|
|
154
|
+
if (tokens.length !== 1 || group.lines.length !== 1) {
|
|
155
|
+
fail("halt does not accept arguments", file, header.number);
|
|
156
|
+
}
|
|
157
|
+
return { kind: "halt", location };
|
|
158
|
+
}
|
|
159
|
+
fail(`unknown SQLLogicTest directive '${tokens[0] ?? ""}'`, file, header.number);
|
|
160
|
+
}
|
|
161
|
+
function parseExpected(lines, file, line) {
|
|
162
|
+
if (lines.length !== 1)
|
|
163
|
+
return { kind: "values", values: lines };
|
|
164
|
+
const match = /^(\d+) values hashing to ([0-9a-fA-F]{32})$/.exec(lines[0] ?? "");
|
|
165
|
+
if (match === null)
|
|
166
|
+
return { kind: "values", values: lines };
|
|
167
|
+
const valueCount = Number(match[1]);
|
|
168
|
+
if (!Number.isSafeInteger(valueCount))
|
|
169
|
+
fail("hashed value count is too large", file, line);
|
|
170
|
+
return { kind: "hash", valueCount, hash: (match[2] ?? "").toLowerCase() };
|
|
171
|
+
}
|
|
172
|
+
function tokenizeDirective(line) {
|
|
173
|
+
return line.trim().split(/\s+/u);
|
|
174
|
+
}
|
|
175
|
+
function sqlLines(lines) {
|
|
176
|
+
return lines.map((line) => line.text).join("\n");
|
|
177
|
+
}
|
|
178
|
+
function requireLine(group, index, file) {
|
|
179
|
+
const line = group.lines[index];
|
|
180
|
+
if (line === undefined) {
|
|
181
|
+
const last = group.lines.at(-1)?.number ?? 1;
|
|
182
|
+
fail("conditional is missing its statement or query", file, last);
|
|
183
|
+
}
|
|
184
|
+
return line;
|
|
185
|
+
}
|
|
186
|
+
function isNonNegativeInteger(value) {
|
|
187
|
+
return value !== undefined && /^\d+$/u.test(value) && Number.isSafeInteger(Number(value));
|
|
188
|
+
}
|
|
189
|
+
function fail(message, file, line) {
|
|
190
|
+
throw new SqlLogicParseError(message, { file, line });
|
|
191
|
+
}
|
|
192
|
+
/** Runs already-parsed records against one empty database connection. */
|
|
193
|
+
export async function runSqlLogicTest(records, database, options = {}) {
|
|
194
|
+
let statements = 0;
|
|
195
|
+
let queries = 0;
|
|
196
|
+
let values = 0;
|
|
197
|
+
let skipped = 0;
|
|
198
|
+
let hashThreshold = 8;
|
|
199
|
+
let halted = false;
|
|
200
|
+
const labels = new Map();
|
|
201
|
+
try {
|
|
202
|
+
for await (const record of records) {
|
|
203
|
+
if (record.kind === "hash-threshold") {
|
|
204
|
+
hashThreshold = record.valueCount;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (record.kind === "halt") {
|
|
208
|
+
halted = true;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
if (shouldSkip(record.conditions, database.engineName)) {
|
|
212
|
+
skipped++;
|
|
213
|
+
if (record.kind === "query" && record.label !== undefined) {
|
|
214
|
+
rememberExpectedLabel(record, labels);
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
try {
|
|
219
|
+
if (record.kind === "statement") {
|
|
220
|
+
statements++;
|
|
221
|
+
await runStatement(record, database);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
queries++;
|
|
225
|
+
const actual = await runQuery(record, database);
|
|
226
|
+
values += actual.length;
|
|
227
|
+
compareExpected(record, actual, hashThreshold);
|
|
228
|
+
rememberActualLabel(record, actual, labels);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
if (error instanceof SqlLogicFailure && options.onFailure?.(error, record) === "continue") {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
finally {
|
|
239
|
+
await database.close();
|
|
240
|
+
}
|
|
241
|
+
return { files: 1, statements, queries, values, skipped, halted, hashThreshold };
|
|
242
|
+
}
|
|
243
|
+
function shouldSkip(conditions, engineName) {
|
|
244
|
+
const engine = engineName.toLowerCase();
|
|
245
|
+
return conditions.some((condition) => {
|
|
246
|
+
const matches = condition.engine.toLowerCase() === engine;
|
|
247
|
+
return condition.kind === "skipif" ? matches : !matches;
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
async function runStatement(record, database) {
|
|
251
|
+
let failure;
|
|
252
|
+
try {
|
|
253
|
+
await database.execute(record.sql);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
failure = error;
|
|
257
|
+
}
|
|
258
|
+
if (record.expectation === "error") {
|
|
259
|
+
if (failure !== undefined)
|
|
260
|
+
return;
|
|
261
|
+
throw new SqlLogicFailure("statement succeeded; expected an error", record.location, record.sql);
|
|
262
|
+
}
|
|
263
|
+
if (failure !== undefined) {
|
|
264
|
+
throw new SqlLogicFailure("statement failed; expected success", record.location, record.sql, {
|
|
265
|
+
cause: failure,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function runQuery(record, database) {
|
|
270
|
+
let result;
|
|
271
|
+
try {
|
|
272
|
+
result = await database.query(record.sql);
|
|
273
|
+
}
|
|
274
|
+
catch (cause) {
|
|
275
|
+
throw new SqlLogicFailure("query failed", record.location, record.sql, { cause });
|
|
276
|
+
}
|
|
277
|
+
if (result.columns.length !== record.types.length) {
|
|
278
|
+
throw new SqlLogicFailure(`wrong column count: expected ${String(record.types.length)}, received ${String(result.columns.length)}`, record.location, record.sql);
|
|
279
|
+
}
|
|
280
|
+
const rows = result.rows.map((row) => result.columns.map((column, index) => renderSqlLogicValue(row[column] ?? null, record.types[index])));
|
|
281
|
+
if (record.sortMode === "rowsort")
|
|
282
|
+
rows.sort(compareRows);
|
|
283
|
+
const flattened = rows.flat();
|
|
284
|
+
if (record.sortMode === "valuesort")
|
|
285
|
+
flattened.sort(compareText);
|
|
286
|
+
return flattened;
|
|
287
|
+
}
|
|
288
|
+
function compareRows(left, right) {
|
|
289
|
+
for (let index = 0; index < left.length; index++) {
|
|
290
|
+
const comparison = compareText(left[index] ?? "", right[index] ?? "");
|
|
291
|
+
if (comparison !== 0)
|
|
292
|
+
return comparison;
|
|
293
|
+
}
|
|
294
|
+
return 0;
|
|
295
|
+
}
|
|
296
|
+
function compareText(left, right) {
|
|
297
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
298
|
+
}
|
|
299
|
+
/** Renders one value with the original SQLite SQLLogicTest adapter rules. */
|
|
300
|
+
export function renderSqlLogicValue(value, type) {
|
|
301
|
+
if (value === null)
|
|
302
|
+
return "NULL";
|
|
303
|
+
if (type === "I") {
|
|
304
|
+
const numeric = typeof value === "boolean" ? Number(value) : Number(value);
|
|
305
|
+
if (!Number.isFinite(numeric))
|
|
306
|
+
return "0";
|
|
307
|
+
return String(Math.trunc(numeric));
|
|
308
|
+
}
|
|
309
|
+
if (type === "R") {
|
|
310
|
+
const numeric = typeof value === "boolean" ? Number(value) : Number(value);
|
|
311
|
+
return Number.isFinite(numeric) ? numeric.toFixed(3) : "0.000";
|
|
312
|
+
}
|
|
313
|
+
const rendered = value instanceof Date ? value.toISOString() : String(value);
|
|
314
|
+
if (rendered.length === 0)
|
|
315
|
+
return "(empty)";
|
|
316
|
+
return rendered.replaceAll(/[^ -~]/gu, "@");
|
|
317
|
+
}
|
|
318
|
+
function compareExpected(record, actual, hashThreshold) {
|
|
319
|
+
const hashed = hashThreshold > 0 && actual.length > hashThreshold;
|
|
320
|
+
if (hashed) {
|
|
321
|
+
if (record.expected.kind !== "hash") {
|
|
322
|
+
throw new SqlLogicFailure(`result exceeds hash-threshold ${String(hashThreshold)} but the expected result is not hashed`, record.location, record.sql);
|
|
323
|
+
}
|
|
324
|
+
const hash = md5Hex(withTrailingNewlines(actual));
|
|
325
|
+
if (record.expected.valueCount !== actual.length || record.expected.hash !== hash) {
|
|
326
|
+
throw new SqlLogicFailure(`wrong result hash: expected ${String(record.expected.valueCount)} values hashing to ${record.expected.hash}, received ${String(actual.length)} values hashing to ${hash}`, record.location, record.sql);
|
|
327
|
+
}
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (record.expected.kind === "hash") {
|
|
331
|
+
throw new SqlLogicFailure(`expected result is hashed but ${String(actual.length)} values do not exceed hash-threshold ${String(hashThreshold)}`, record.location, record.sql);
|
|
332
|
+
}
|
|
333
|
+
if (!equalValues(record.expected.values, actual)) {
|
|
334
|
+
const expected = describeValues(record.expected.values, hashThreshold);
|
|
335
|
+
const received = describeValues(actual, hashThreshold);
|
|
336
|
+
throw new SqlLogicFailure(`wrong result:\nexpected ${expected}\nreceived ${received}`, record.location, record.sql);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function equalValues(expected, actual) {
|
|
340
|
+
return (expected.length === actual.length && expected.every((value, index) => value === actual[index]));
|
|
341
|
+
}
|
|
342
|
+
function describeValues(values, hashThreshold) {
|
|
343
|
+
if (hashThreshold > 0 && values.length > hashThreshold) {
|
|
344
|
+
return `${String(values.length)} values hashing to ${md5Hex(withTrailingNewlines(values))}`;
|
|
345
|
+
}
|
|
346
|
+
return JSON.stringify(values);
|
|
347
|
+
}
|
|
348
|
+
function rememberExpectedLabel(record, labels) {
|
|
349
|
+
if (record.label === undefined)
|
|
350
|
+
return;
|
|
351
|
+
const hash = record.expected.kind === "hash"
|
|
352
|
+
? record.expected.hash
|
|
353
|
+
: md5Hex(withTrailingNewlines(record.expected.values));
|
|
354
|
+
rememberLabel(record.label, hash, record.location, labels);
|
|
355
|
+
}
|
|
356
|
+
function rememberActualLabel(record, values, labels) {
|
|
357
|
+
if (record.label === undefined)
|
|
358
|
+
return;
|
|
359
|
+
rememberLabel(record.label, md5Hex(withTrailingNewlines(values)), record.location, labels);
|
|
360
|
+
}
|
|
361
|
+
function rememberLabel(label, hash, location, labels) {
|
|
362
|
+
const previous = labels.get(label);
|
|
363
|
+
if (previous !== undefined && previous.hash !== hash) {
|
|
364
|
+
throw new SqlLogicFailure(`labeled result '${label}' differs from ${previous.location.file}:${String(previous.location.line)}`, location);
|
|
365
|
+
}
|
|
366
|
+
labels.set(label, { hash, location });
|
|
367
|
+
}
|
|
368
|
+
function withTrailingNewlines(values) {
|
|
369
|
+
return values.map((value) => `${value}\n`).join("");
|
|
370
|
+
}
|
|
371
|
+
/** Small browser-safe MD5 implementation for compatibility with the original corpus hashes. */
|
|
372
|
+
export function md5Hex(input) {
|
|
373
|
+
const bytes = new TextEncoder().encode(input);
|
|
374
|
+
const paddedLength = Math.ceil((bytes.length + 9) / 64) * 64;
|
|
375
|
+
const padded = new Uint8Array(paddedLength);
|
|
376
|
+
padded.set(bytes);
|
|
377
|
+
padded[bytes.length] = 0x80;
|
|
378
|
+
const bitLength = BigInt(bytes.length) * 8n;
|
|
379
|
+
const view = new DataView(padded.buffer);
|
|
380
|
+
view.setUint32(paddedLength - 8, Number(bitLength & 0xffffffffn), true);
|
|
381
|
+
view.setUint32(paddedLength - 4, Number((bitLength >> 32n) & 0xffffffffn), true);
|
|
382
|
+
let a0 = 0x67452301;
|
|
383
|
+
let b0 = 0xefcdab89;
|
|
384
|
+
let c0 = 0x98badcfe;
|
|
385
|
+
let d0 = 0x10325476;
|
|
386
|
+
const words = new Uint32Array(16);
|
|
387
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
388
|
+
for (let index = 0; index < 16; index++)
|
|
389
|
+
words[index] = view.getUint32(offset + index * 4, true);
|
|
390
|
+
let a = a0;
|
|
391
|
+
let b = b0;
|
|
392
|
+
let c = c0;
|
|
393
|
+
let d = d0;
|
|
394
|
+
for (let index = 0; index < 64; index++) {
|
|
395
|
+
const { mix, word } = md5Round(index, b, c, d);
|
|
396
|
+
const rotated = rotateLeft((a + mix + (MD5_CONSTANTS[index] ?? 0) + (words[word] ?? 0)) >>> 0, MD5_SHIFTS[index]);
|
|
397
|
+
a = d;
|
|
398
|
+
d = c;
|
|
399
|
+
c = b;
|
|
400
|
+
b = (b + rotated) >>> 0;
|
|
401
|
+
}
|
|
402
|
+
a0 = (a0 + a) >>> 0;
|
|
403
|
+
b0 = (b0 + b) >>> 0;
|
|
404
|
+
c0 = (c0 + c) >>> 0;
|
|
405
|
+
d0 = (d0 + d) >>> 0;
|
|
406
|
+
}
|
|
407
|
+
return [a0, b0, c0, d0].map(littleEndianHex).join("");
|
|
408
|
+
}
|
|
409
|
+
function md5Round(index, b, c, d) {
|
|
410
|
+
if (index < 16)
|
|
411
|
+
return { mix: (b & c) | (~b & d), word: index };
|
|
412
|
+
if (index < 32)
|
|
413
|
+
return { mix: (d & b) | (~d & c), word: (5 * index + 1) % 16 };
|
|
414
|
+
if (index < 48)
|
|
415
|
+
return { mix: b ^ c ^ d, word: (3 * index + 5) % 16 };
|
|
416
|
+
return { mix: c ^ (b | ~d), word: (7 * index) % 16 };
|
|
417
|
+
}
|
|
418
|
+
function rotateLeft(value, shift) {
|
|
419
|
+
const bits = shift ?? 0;
|
|
420
|
+
return ((value << bits) | (value >>> (32 - bits))) >>> 0;
|
|
421
|
+
}
|
|
422
|
+
function littleEndianHex(value) {
|
|
423
|
+
let output = "";
|
|
424
|
+
for (let index = 0; index < 4; index++) {
|
|
425
|
+
output += ((value >>> (index * 8)) & 0xff).toString(16).padStart(2, "0");
|
|
426
|
+
}
|
|
427
|
+
return output;
|
|
428
|
+
}
|
|
429
|
+
const MD5_SHIFTS = [
|
|
430
|
+
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14,
|
|
431
|
+
20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6,
|
|
432
|
+
10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
|
|
433
|
+
];
|
|
434
|
+
const MD5_CONSTANTS = Array.from({ length: 64 }, (_, index) => Math.floor(Math.abs(Math.sin(index + 1)) * 2 ** 32));
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { type BlockStore, type BlockWrite, type LeaseKind, type LeaseRecord, type ManifestSummary, type RowIdRange, type SegmentRecord, type TransactionRecord, type FtsChanges, type UniqueKeyChanges } from "../storage/
|
|
1
|
+
import { type BlockStore, type BlockWrite, type LeaseKind, type LeaseRecord, MAX_LEASE_TTL_MS, type ManifestSummary, type RowIdRange, type SegmentRecord, type TableRecord, type TransactionRecord, type FtsChanges, type UniqueKeyChanges } from "../storage/types.js";
|
|
2
2
|
export interface TransactionManagerOptions {
|
|
3
3
|
now?: () => Date;
|
|
4
4
|
createId?: () => string;
|
|
5
|
+
/** Durable writer deadline; live transactions renew every third of this interval. */
|
|
6
|
+
transactionTtlMs?: number;
|
|
7
|
+
/** Test seam for deterministic collection of an abandoned transaction reference. */
|
|
8
|
+
createWeakRef?: (transaction: DatabaseTransaction) => {
|
|
9
|
+
deref(): DatabaseTransaction | undefined;
|
|
10
|
+
};
|
|
5
11
|
}
|
|
12
|
+
export declare const DEFAULT_TRANSACTION_TTL_MS = 30000;
|
|
13
|
+
export { MAX_LEASE_TTL_MS };
|
|
6
14
|
export interface RecoveryOptions {
|
|
7
15
|
staleBefore: Date;
|
|
8
16
|
removePendingBlocks?: boolean;
|
|
@@ -23,24 +31,47 @@ export interface OpenLeasedSnapshotOptions {
|
|
|
23
31
|
kind?: LeaseKind;
|
|
24
32
|
version?: number | null;
|
|
25
33
|
}
|
|
34
|
+
export interface BeginDeferredOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Pins the captured snapshot with a renewable durable reader lease until this transaction
|
|
37
|
+
* either persists its own durable owner or finishes. Enabled by default; tightly bounded
|
|
38
|
+
* internal statements that cannot idle may opt out to retain the one-write fast path.
|
|
39
|
+
*/
|
|
40
|
+
durableSnapshot?: boolean;
|
|
41
|
+
}
|
|
26
42
|
export declare class TransactionClosedError extends Error {
|
|
27
43
|
readonly transactionId: string;
|
|
28
44
|
readonly name = "TransactionClosedError";
|
|
29
45
|
constructor(transactionId: string);
|
|
30
46
|
}
|
|
47
|
+
/** Opaque staged-state marker used by SQL SAVEPOINT. */
|
|
48
|
+
export interface TransactionCheckpoint {
|
|
49
|
+
readonly transactionId: string;
|
|
50
|
+
readonly pendingBlockIds: readonly string[];
|
|
51
|
+
readonly pendingSegmentIds: readonly string[];
|
|
52
|
+
readonly uniqueKeyChanges: readonly UniqueKeyChanges[];
|
|
53
|
+
readonly ftsChanges: readonly FtsChanges[];
|
|
54
|
+
readonly compactionJobId: string | null;
|
|
55
|
+
readonly compactionSourceBlockIds: readonly string[];
|
|
56
|
+
readonly levelZeroSegmentLimits: ReadonlyArray<{
|
|
57
|
+
tableId: string;
|
|
58
|
+
limit: number;
|
|
59
|
+
}>;
|
|
60
|
+
readonly changedTableIds: readonly string[];
|
|
61
|
+
readonly logicallyUnchanged: boolean;
|
|
62
|
+
}
|
|
31
63
|
export declare class Snapshot {
|
|
32
|
-
#private;
|
|
33
64
|
private readonly store;
|
|
34
65
|
readonly version: number | null;
|
|
35
|
-
constructor(store: BlockStore, version: number | null
|
|
36
|
-
|
|
37
|
-
|
|
66
|
+
constructor(store: BlockStore, version: number | null);
|
|
67
|
+
hasBlock(id: string): Promise<boolean>;
|
|
68
|
+
hasBlocks(ids: readonly string[]): Promise<boolean[]>;
|
|
38
69
|
getBlock(id: string): Promise<Uint8Array | undefined>;
|
|
39
70
|
}
|
|
40
71
|
export declare class LeasedSnapshot extends Snapshot {
|
|
41
72
|
#private;
|
|
42
73
|
private readonly now;
|
|
43
|
-
constructor(store: BlockStore, version: number | null,
|
|
74
|
+
constructor(store: BlockStore, version: number | null, record: LeaseRecord, now: () => Date);
|
|
44
75
|
get leaseId(): string;
|
|
45
76
|
get expiresAt(): Date;
|
|
46
77
|
getBlock(id: string): Promise<Uint8Array | undefined>;
|
|
@@ -61,15 +92,44 @@ export declare class DatabaseTransaction {
|
|
|
61
92
|
#private;
|
|
62
93
|
private readonly store;
|
|
63
94
|
private readonly now;
|
|
64
|
-
|
|
95
|
+
private readonly ttlMs;
|
|
96
|
+
constructor(store: BlockStore, record: TransactionRecord, now: () => Date, ttlMs: number, createWeakRef: (transaction: DatabaseTransaction) => {
|
|
97
|
+
deref(): DatabaseTransaction | undefined;
|
|
98
|
+
}, options?: {
|
|
65
99
|
persisted?: boolean;
|
|
100
|
+
initialCatalogProbe?: {
|
|
101
|
+
catalogEpoch: number;
|
|
102
|
+
manifestVersion: number | null;
|
|
103
|
+
schemaEpoch: number;
|
|
104
|
+
};
|
|
105
|
+
snapshotLease?: LeasedSnapshot;
|
|
66
106
|
});
|
|
67
107
|
get id(): string;
|
|
68
108
|
get status(): TransactionRecord["status"];
|
|
69
109
|
get snapshotVersion(): number | null;
|
|
70
110
|
get pendingBlockIds(): string[];
|
|
71
111
|
get pendingSegmentIds(): string[];
|
|
72
|
-
|
|
112
|
+
/** Process-local segments retained for a bounded single-shot commit. */
|
|
113
|
+
get deferredSegments(): SegmentRecord[];
|
|
114
|
+
get pendingTableNextRowId(): bigint | undefined;
|
|
115
|
+
get initialCatalogProbe(): {
|
|
116
|
+
catalogEpoch: number;
|
|
117
|
+
manifestVersion: number | null;
|
|
118
|
+
schemaEpoch: number;
|
|
119
|
+
} | undefined;
|
|
120
|
+
/** Exact local commit contribution; undefined until this transaction commits. */
|
|
121
|
+
get committedCatalogContribution(): {
|
|
122
|
+
transaction: TransactionRecord;
|
|
123
|
+
segments: SegmentRecord[];
|
|
124
|
+
initialCatalogProbe?: {
|
|
125
|
+
catalogEpoch: number;
|
|
126
|
+
manifestVersion: number | null;
|
|
127
|
+
schemaEpoch: number;
|
|
128
|
+
};
|
|
129
|
+
} | undefined;
|
|
130
|
+
get compactionSourceBlockIds(): string[];
|
|
131
|
+
/** Extends durable ownership; scope owners call this while user code is legitimately waiting. */
|
|
132
|
+
renew(): Promise<void>;
|
|
73
133
|
/**
|
|
74
134
|
* Counts every registration this transaction carries: staged blocks and segments, unique-key
|
|
75
135
|
* entries, full-text entries, and supersessions. A caller that fails part-way through a
|
|
@@ -78,6 +138,12 @@ export declare class DatabaseTransaction {
|
|
|
78
138
|
* since there is no statement-level rollback inside a transaction.
|
|
79
139
|
*/
|
|
80
140
|
get stagedWorkCount(): number;
|
|
141
|
+
/** Captures all publish-relevant state; row-id/autoincrement reservations deliberately burn. */
|
|
142
|
+
checkpoint(): TransactionCheckpoint;
|
|
143
|
+
/** Conservative retained-size estimate used to refuse savepoint clones before allocating. */
|
|
144
|
+
checkpointRetainedBytes(): number;
|
|
145
|
+
/** Rewinds staged artifacts and every in-memory commit delta to one earlier checkpoint. */
|
|
146
|
+
rollbackTo(checkpoint: TransactionCheckpoint): Promise<void>;
|
|
81
147
|
snapshot(): Promise<Snapshot>;
|
|
82
148
|
getBlock(id: string): Promise<Uint8Array | undefined>;
|
|
83
149
|
stageBlock(id: string, bytes: Uint8Array): Promise<void>;
|
|
@@ -110,6 +176,8 @@ export declare class DatabaseTransaction {
|
|
|
110
176
|
stageSegment(record: SegmentRecord): Promise<void>;
|
|
111
177
|
/** Reconciles a persisted segment whose journal update was interrupted. */
|
|
112
178
|
stageExistingSegment(segmentId: string): Promise<void>;
|
|
179
|
+
/** Atomically adopts an exact unpublished output left by an aborted attempt of this job. */
|
|
180
|
+
adoptAbortedCompactionSegment(record: SegmentRecord, abortedOwner: TransactionRecord): Promise<void>;
|
|
113
181
|
/**
|
|
114
182
|
* Records that this commit changes a table's logical content without staging a segment for
|
|
115
183
|
* it — dropping the table, for instance, whose only publish is the retirement of its blocks.
|
|
@@ -132,7 +200,14 @@ export declare class DatabaseTransaction {
|
|
|
132
200
|
* and token totals summed — so a scope can insert into one FTS table any number of times.
|
|
133
201
|
*/
|
|
134
202
|
setFtsChanges(changes: FtsChanges): void;
|
|
135
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Binds a physical retirement to one persisted compaction job. Stores revalidate the job,
|
|
205
|
+
* source segments, current manifest, and aliases atomically with publication; this in-memory
|
|
206
|
+
* declaration is intent, never authority to hide arbitrary blocks.
|
|
207
|
+
*/
|
|
208
|
+
setCompactionIntent(compactionJobId: string, sourceBlockIds: readonly string[]): void;
|
|
209
|
+
/** Adds an adapter-enforced post-commit level-zero ceiling for one table. */
|
|
210
|
+
limitLevelZeroSegments(tableId: string, limit: number): void;
|
|
136
211
|
commit(): Promise<ManifestSummary>;
|
|
137
212
|
rebase(): Promise<Snapshot>;
|
|
138
213
|
abort(): Promise<void>;
|
|
@@ -142,14 +217,16 @@ export declare class TransactionManager {
|
|
|
142
217
|
private readonly store;
|
|
143
218
|
constructor(store: BlockStore, options?: TransactionManagerOptions);
|
|
144
219
|
begin(): Promise<DatabaseTransaction>;
|
|
220
|
+
/** Atomically reserves an invisible catalog table for a create-and-populate transaction. */
|
|
221
|
+
beginWithPendingTable(record: TableRecord, expectedCatalogEpoch: number): Promise<DatabaseTransaction>;
|
|
145
222
|
/**
|
|
146
|
-
* Begins a transaction
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
223
|
+
* Begins without a transaction record. By default a renewable reader lease durably pins the
|
|
224
|
+
* probed manifest until the first two-step stage hands ownership to a transaction record. The
|
|
225
|
+
* record and lease are both omitted only for internal, uninterrupted single-shot writes that
|
|
226
|
+
* opt out and publish through `writeTransaction`. For writes whose artifacts need no prior
|
|
227
|
+
* reservation; `beginWithReservation` is the shape for the rest.
|
|
151
228
|
*/
|
|
152
|
-
beginDeferred(): Promise<DatabaseTransaction>;
|
|
229
|
+
beginDeferred(options?: BeginDeferredOptions): Promise<DatabaseTransaction>;
|
|
153
230
|
/**
|
|
154
231
|
* Begins a transaction at the current manifest version and optionally reserves row ids and
|
|
155
232
|
* auto-increment values in the same step. Stores implementing the atomic `beginTransaction`
|
|
@@ -186,4 +263,3 @@ export declare class TransactionManager {
|
|
|
186
263
|
removeExpiredLeases(at?: Date): Promise<string[]>;
|
|
187
264
|
recover(options: RecoveryOptions): Promise<RecoveryReport>;
|
|
188
265
|
}
|
|
189
|
-
//# sourceMappingURL=index.d.ts.map
|