@crvouga/mockingbird-service-postgres 1.4.0 → 1.5.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/CHANGELOG.md +31 -1
- package/README.md +39 -8
- package/dist/admin.d.ts +13 -0
- package/dist/admin.js +26638 -0
- package/dist/admin.js.map +7 -0
- package/dist/api/database.d.ts +37 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +279 -22
- package/dist/index.js.map +3 -3
- package/dist/runtime/options.d.ts +5 -0
- package/dist/wire/cli.js +338 -29
- package/dist/wire/cli.js.map +4 -4
- package/dist/wire/connection.d.ts +5 -0
- package/dist/wire/index.d.ts +18 -2
- package/dist/wire/index.js +332 -26
- package/dist/wire/index.js.map +4 -4
- package/package.json +8 -1
package/dist/api/database.d.ts
CHANGED
|
@@ -2,10 +2,27 @@ import { type DatabaseOptions, type Int8Mode, type RandomMode } from "../runtime
|
|
|
2
2
|
import type { BindValue, JsValue, QueryRow } from "./bind.js";
|
|
3
3
|
import { type Snapshot } from "./snapshot.js";
|
|
4
4
|
import { Statement } from "./statement.js";
|
|
5
|
+
/** A timeline checkpoint without its retained snapshot value. */
|
|
6
|
+
export interface HistoryCheckpoint {
|
|
7
|
+
id: string;
|
|
8
|
+
branch: string;
|
|
9
|
+
parent: string | null;
|
|
10
|
+
at: number;
|
|
11
|
+
}
|
|
12
|
+
/** Branch heads and checkpoints owned by the shared Timeline. */
|
|
13
|
+
export interface DatabaseHistory {
|
|
14
|
+
readonly size: number;
|
|
15
|
+
head(branch?: string): HistoryCheckpoint | undefined;
|
|
16
|
+
branches(): Readonly<Record<string, string>>;
|
|
17
|
+
checkpoints(): readonly HistoryCheckpoint[];
|
|
18
|
+
}
|
|
5
19
|
/** Additive time-travel controls for read APIs. */
|
|
6
20
|
export interface QueryOptions {
|
|
7
|
-
/**
|
|
8
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Execute against this immutable snapshot, or a timeline checkpoint id,
|
|
23
|
+
* instead of the live database.
|
|
24
|
+
*/
|
|
25
|
+
at?: Snapshot | string;
|
|
9
26
|
}
|
|
10
27
|
/**
|
|
11
28
|
* Pure TypeScript in-memory PostgreSQL database.
|
|
@@ -35,6 +52,8 @@ export declare class Database {
|
|
|
35
52
|
private closed;
|
|
36
53
|
private transactionSequence;
|
|
37
54
|
private apiTransactionDepth;
|
|
55
|
+
private historyBranch;
|
|
56
|
+
private originId;
|
|
38
57
|
constructor(options?: DatabaseOptions);
|
|
39
58
|
/**
|
|
40
59
|
* Execute SQL for its side effects. Multiple semicolon-separated statements
|
|
@@ -65,6 +84,19 @@ export declare class Database {
|
|
|
65
84
|
snapshot(): Snapshot;
|
|
66
85
|
/** Alias for {@link snapshot}, naming the value as a timeline checkpoint. */
|
|
67
86
|
checkpoint(): Snapshot;
|
|
87
|
+
/**
|
|
88
|
+
* Commit the live state onto `branch` (default: the branch this database follows).
|
|
89
|
+
* Does not switch the live database. Illegal inside a transaction.
|
|
90
|
+
*/
|
|
91
|
+
record(branch?: string): HistoryCheckpoint;
|
|
92
|
+
/** Point `name` at a checkpoint without copying rows or switching the live database. */
|
|
93
|
+
fork(name: string, at?: string): HistoryCheckpoint;
|
|
94
|
+
/** Move `branch` to `id` and install that checkpoint as the live database. */
|
|
95
|
+
checkout(id: string, branch?: string): HistoryCheckpoint;
|
|
96
|
+
/** Return the live database to the origin checkpoint on `main`. */
|
|
97
|
+
reset(): HistoryCheckpoint;
|
|
98
|
+
/** Checkpoint ids and branch heads. Values stay inside the timeline. */
|
|
99
|
+
get history(): DatabaseHistory;
|
|
68
100
|
/** Open a copy-on-write branch from `at`, or from the current state when omitted. */
|
|
69
101
|
branch(at?: Snapshot): Database;
|
|
70
102
|
/** Close the database. Further SQL throws. Idempotent. */
|
|
@@ -82,6 +114,9 @@ export declare class Database {
|
|
|
82
114
|
copyFrom(sql: string, data: string): number;
|
|
83
115
|
/** Rows affected by the most recent INSERT / UPDATE / DELETE. */
|
|
84
116
|
get changes(): number;
|
|
117
|
+
private historyError;
|
|
118
|
+
private captureLive;
|
|
119
|
+
private install;
|
|
85
120
|
private prepareSingle;
|
|
86
121
|
}
|
|
87
122
|
export { Snapshot } from "./snapshot.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import "./serialization/codec.js";
|
|
25
25
|
export type { BindValue, JsValue, QueryRow } from "./api/bind.js";
|
|
26
|
-
export { Database, type DatabaseOptions, type QueryOptions, type RegisterFunctionOptions, Snapshot, } from "./api/database.js";
|
|
26
|
+
export { Database, type DatabaseHistory, type DatabaseOptions, type HistoryCheckpoint, type QueryOptions, type RegisterFunctionOptions, Snapshot, } from "./api/database.js";
|
|
27
27
|
export { type ResultSet, type RunResult, Statement } from "./api/statement.js";
|
|
28
28
|
export { type ErrorCategory, PostgresError } from "./errors/error.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,164 @@
|
|
|
1
|
+
// ../../core/dist/timeline.js
|
|
2
|
+
var BRANCH_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/;
|
|
3
|
+
var Timeline = class {
|
|
4
|
+
maxCheckpoints;
|
|
5
|
+
now;
|
|
6
|
+
makeId;
|
|
7
|
+
nodes = /* @__PURE__ */ new Map();
|
|
8
|
+
heads = /* @__PURE__ */ new Map();
|
|
9
|
+
/** Unreferenced nodes in the exact order they became collectible. */
|
|
10
|
+
evictable = /* @__PURE__ */ new Set();
|
|
11
|
+
/** Branch heads plus explicit retainers. Absent means zero. */
|
|
12
|
+
references = /* @__PURE__ */ new Map();
|
|
13
|
+
explicitPins = /* @__PURE__ */ new Map();
|
|
14
|
+
sequence = 0;
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
const max = options.maxCheckpoints ?? 1e3;
|
|
17
|
+
if (!Number.isSafeInteger(max) || max < 1)
|
|
18
|
+
throw new RangeError("maxCheckpoints must be a positive integer");
|
|
19
|
+
this.maxCheckpoints = max;
|
|
20
|
+
this.now = options.now ?? (() => this.sequence);
|
|
21
|
+
this.makeId = options.id ?? ((sequence) => `cp_${sequence.toString(36).padStart(8, "0")}`);
|
|
22
|
+
}
|
|
23
|
+
/** Capture a new immutable value and move `branch` to it. */
|
|
24
|
+
commit(value, options = {}) {
|
|
25
|
+
const branch = options.branch ?? "main";
|
|
26
|
+
this.assertBranch(branch);
|
|
27
|
+
const parent = options.parent === void 0 ? this.heads.get(branch) ?? null : options.parent;
|
|
28
|
+
if (parent !== null && !this.nodes.has(parent))
|
|
29
|
+
throw new RangeError(`no checkpoint ${parent}`);
|
|
30
|
+
const id = this.makeId(++this.sequence);
|
|
31
|
+
if (this.nodes.has(id))
|
|
32
|
+
throw new RangeError(`duplicate checkpoint id ${id}`);
|
|
33
|
+
const checkpoint = Object.freeze({ id, branch, parent, at: this.now(), value });
|
|
34
|
+
this.nodes.set(id, checkpoint);
|
|
35
|
+
this.moveHead(branch, id);
|
|
36
|
+
this.collect(this.maxCheckpoints);
|
|
37
|
+
return checkpoint;
|
|
38
|
+
}
|
|
39
|
+
/** Create a branch pointer without copying its checkpoint value. */
|
|
40
|
+
fork(branch, options = {}) {
|
|
41
|
+
this.assertBranch(branch);
|
|
42
|
+
if (this.heads.has(branch))
|
|
43
|
+
throw new RangeError(`branch already exists: ${branch}`);
|
|
44
|
+
const from = options.from ?? this.heads.get("main");
|
|
45
|
+
if (from === void 0)
|
|
46
|
+
return void 0;
|
|
47
|
+
const checkpoint = this.get(from);
|
|
48
|
+
this.moveHead(branch, checkpoint.id);
|
|
49
|
+
return checkpoint;
|
|
50
|
+
}
|
|
51
|
+
/** Move a branch pointer to an existing checkpoint. */
|
|
52
|
+
checkout(branch, id) {
|
|
53
|
+
this.assertBranch(branch);
|
|
54
|
+
const checkpoint = this.get(id);
|
|
55
|
+
this.moveHead(branch, checkpoint.id);
|
|
56
|
+
return checkpoint;
|
|
57
|
+
}
|
|
58
|
+
get(id) {
|
|
59
|
+
const checkpoint = this.nodes.get(id);
|
|
60
|
+
if (!checkpoint)
|
|
61
|
+
throw new RangeError(`no checkpoint ${id}`);
|
|
62
|
+
return checkpoint;
|
|
63
|
+
}
|
|
64
|
+
head(branch = "main") {
|
|
65
|
+
const id = this.heads.get(branch);
|
|
66
|
+
return id === void 0 ? void 0 : this.get(id);
|
|
67
|
+
}
|
|
68
|
+
hasBranch(branch) {
|
|
69
|
+
return this.heads.has(branch);
|
|
70
|
+
}
|
|
71
|
+
branches() {
|
|
72
|
+
return Object.freeze(Object.fromEntries([...this.heads].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)));
|
|
73
|
+
}
|
|
74
|
+
checkpoints() {
|
|
75
|
+
return [...this.nodes.values()];
|
|
76
|
+
}
|
|
77
|
+
/** Number of retained checkpoints without allocating an array. */
|
|
78
|
+
get size() {
|
|
79
|
+
return this.nodes.size;
|
|
80
|
+
}
|
|
81
|
+
/** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */
|
|
82
|
+
retain(id) {
|
|
83
|
+
const checkpoint = this.get(id);
|
|
84
|
+
this.explicitPins.set(id, (this.explicitPins.get(id) ?? 0) + 1);
|
|
85
|
+
this.addReference(id);
|
|
86
|
+
return checkpoint;
|
|
87
|
+
}
|
|
88
|
+
/** Release one explicit pin. Branch heads remain pinned until moved or deleted. */
|
|
89
|
+
release(id) {
|
|
90
|
+
if (!this.nodes.has(id))
|
|
91
|
+
return false;
|
|
92
|
+
const pins = this.explicitPins.get(id) ?? 0;
|
|
93
|
+
if (pins === 0)
|
|
94
|
+
return false;
|
|
95
|
+
if (pins === 1)
|
|
96
|
+
this.explicitPins.delete(id);
|
|
97
|
+
else
|
|
98
|
+
this.explicitPins.set(id, pins - 1);
|
|
99
|
+
this.removeReference(id);
|
|
100
|
+
this.collect(this.maxCheckpoints);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
deleteBranch(branch) {
|
|
104
|
+
if (branch === "main")
|
|
105
|
+
throw new RangeError("cannot delete main branch");
|
|
106
|
+
const previous = this.heads.get(branch);
|
|
107
|
+
const deleted = this.heads.delete(branch);
|
|
108
|
+
if (previous !== void 0)
|
|
109
|
+
this.removeReference(previous);
|
|
110
|
+
this.collect(this.maxCheckpoints);
|
|
111
|
+
return deleted;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):
|
|
115
|
+
* commits never scan pinned nodes or the retained history. Parents are metadata rather than a
|
|
116
|
+
* storage dependency, so a retained node remains usable after pruning.
|
|
117
|
+
*/
|
|
118
|
+
gc(max = this.maxCheckpoints) {
|
|
119
|
+
if (!Number.isSafeInteger(max) || max < 1)
|
|
120
|
+
throw new RangeError("max must be a positive integer");
|
|
121
|
+
const removed = [];
|
|
122
|
+
this.collect(max, removed);
|
|
123
|
+
return removed;
|
|
124
|
+
}
|
|
125
|
+
collect(max, removed) {
|
|
126
|
+
while (this.nodes.size > max && this.evictable.size > 0) {
|
|
127
|
+
const id = this.evictable.values().next().value;
|
|
128
|
+
this.evictable.delete(id);
|
|
129
|
+
this.nodes.delete(id);
|
|
130
|
+
removed?.push(id);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
moveHead(branch, id) {
|
|
134
|
+
const previous = this.heads.get(branch);
|
|
135
|
+
if (previous === id)
|
|
136
|
+
return;
|
|
137
|
+
if (previous !== void 0)
|
|
138
|
+
this.removeReference(previous);
|
|
139
|
+
this.heads.set(branch, id);
|
|
140
|
+
this.addReference(id);
|
|
141
|
+
}
|
|
142
|
+
addReference(id) {
|
|
143
|
+
this.references.set(id, (this.references.get(id) ?? 0) + 1);
|
|
144
|
+
this.evictable.delete(id);
|
|
145
|
+
}
|
|
146
|
+
removeReference(id) {
|
|
147
|
+
const next = (this.references.get(id) ?? 0) - 1;
|
|
148
|
+
if (next > 0)
|
|
149
|
+
this.references.set(id, next);
|
|
150
|
+
else {
|
|
151
|
+
this.references.delete(id);
|
|
152
|
+
if (this.nodes.has(id))
|
|
153
|
+
this.evictable.add(id);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
assertBranch(branch) {
|
|
157
|
+
if (!BRANCH_PATTERN.test(branch))
|
|
158
|
+
throw new RangeError(`branch must match ${BRANCH_PATTERN}`);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
1
162
|
// src/errors/error.ts
|
|
2
163
|
var CATEGORY_TO_SQLSTATE = {
|
|
3
164
|
syntax: "42601",
|
|
@@ -23111,6 +23272,9 @@ var ADOPT = /* @__PURE__ */ Symbol("postgres-mem.adopt");
|
|
|
23111
23272
|
function isAdopted(value) {
|
|
23112
23273
|
return ADOPT in value;
|
|
23113
23274
|
}
|
|
23275
|
+
function project(point) {
|
|
23276
|
+
return { id: point.id, branch: point.branch, parent: point.parent, at: point.at };
|
|
23277
|
+
}
|
|
23114
23278
|
var Database = class {
|
|
23115
23279
|
/** @internal Engine catalog, tables, session settings. */
|
|
23116
23280
|
state;
|
|
@@ -23131,6 +23295,10 @@ var Database = class {
|
|
|
23131
23295
|
closed = false;
|
|
23132
23296
|
transactionSequence = 0;
|
|
23133
23297
|
apiTransactionDepth = 0;
|
|
23298
|
+
/** @internal Shared checkpoint DAG. Omitted from published declarations. */
|
|
23299
|
+
timeline;
|
|
23300
|
+
historyBranch = "main";
|
|
23301
|
+
originId = "";
|
|
23134
23302
|
constructor(options = {}) {
|
|
23135
23303
|
if (isAdopted(options)) {
|
|
23136
23304
|
this.seed = options.seed;
|
|
@@ -23143,16 +23311,23 @@ var Database = class {
|
|
|
23143
23311
|
this.state.prng = this.prng;
|
|
23144
23312
|
this.state.clock = () => this.now();
|
|
23145
23313
|
this.transactions = txManagerFor(this.state);
|
|
23146
|
-
|
|
23314
|
+
} else {
|
|
23315
|
+
this.seed = options.seed ?? DEFAULT_DATABASE_SEED;
|
|
23316
|
+
this.randomMode = options.random ?? "deterministic";
|
|
23317
|
+
this.systemClock = options.now === "system";
|
|
23318
|
+
this.int8Mode = options.int8 ?? "bigint";
|
|
23319
|
+
this.prng = this.randomMode === "os" ? new OsEntropy() : new Prng(this.seed);
|
|
23320
|
+
this.now = resolveClock(options.now);
|
|
23321
|
+
this.state = new DatabaseState(this.prng, () => this.now());
|
|
23322
|
+
this.transactions = txManagerFor(this.state);
|
|
23147
23323
|
}
|
|
23148
|
-
this.
|
|
23149
|
-
|
|
23150
|
-
|
|
23151
|
-
|
|
23152
|
-
|
|
23153
|
-
this.
|
|
23154
|
-
this.
|
|
23155
|
-
this.transactions = txManagerFor(this.state);
|
|
23324
|
+
this.timeline = new Timeline({
|
|
23325
|
+
now: () => this.now().getTime(),
|
|
23326
|
+
...options.maxCheckpoints !== void 0 ? { maxCheckpoints: options.maxCheckpoints } : {}
|
|
23327
|
+
});
|
|
23328
|
+
const origin = this.timeline.commit(this.captureLive());
|
|
23329
|
+
this.originId = origin.id;
|
|
23330
|
+
this.timeline.retain(origin.id);
|
|
23156
23331
|
}
|
|
23157
23332
|
/**
|
|
23158
23333
|
* Execute SQL for its side effects. Multiple semicolon-separated statements
|
|
@@ -23207,7 +23382,15 @@ var Database = class {
|
|
|
23207
23382
|
/** Execute a single-statement query and return all rows keyed by column name. */
|
|
23208
23383
|
query(sql, params = [], options = {}) {
|
|
23209
23384
|
this.assertOpen();
|
|
23210
|
-
|
|
23385
|
+
const at = options.at;
|
|
23386
|
+
if (typeof at === "string") {
|
|
23387
|
+
try {
|
|
23388
|
+
return this.timeline.get(at).value.open().query(sql, params);
|
|
23389
|
+
} catch (error) {
|
|
23390
|
+
this.historyError(error);
|
|
23391
|
+
}
|
|
23392
|
+
}
|
|
23393
|
+
if (at) return at.open().query(sql, params);
|
|
23211
23394
|
return this.prepareSingle(sql).all(...params);
|
|
23212
23395
|
}
|
|
23213
23396
|
/** Compile a single SQL statement into a reusable {@link Statement}. */
|
|
@@ -23255,23 +23438,77 @@ var Database = class {
|
|
|
23255
23438
|
* {@link Snapshot.open} for a copy-on-write fork.
|
|
23256
23439
|
*/
|
|
23257
23440
|
snapshot() {
|
|
23441
|
+
const point = this.record(this.historyBranch);
|
|
23442
|
+
return this.timeline.get(point.id).value;
|
|
23443
|
+
}
|
|
23444
|
+
/** Alias for {@link snapshot}, naming the value as a timeline checkpoint. */
|
|
23445
|
+
checkpoint() {
|
|
23446
|
+
return this.snapshot();
|
|
23447
|
+
}
|
|
23448
|
+
/**
|
|
23449
|
+
* Commit the live state onto `branch` (default: the branch this database follows).
|
|
23450
|
+
* Does not switch the live database. Illegal inside a transaction.
|
|
23451
|
+
*/
|
|
23452
|
+
record(branch = this.historyBranch) {
|
|
23258
23453
|
this.assertOpen();
|
|
23259
23454
|
if (this.transactions.inTransaction) {
|
|
23260
23455
|
throw pgError("transaction_state", "cannot snapshot during a transaction", "25P01");
|
|
23261
23456
|
}
|
|
23262
|
-
|
|
23263
|
-
this.
|
|
23264
|
-
|
|
23265
|
-
this.
|
|
23266
|
-
|
|
23267
|
-
this.randomMode,
|
|
23268
|
-
this.systemClock,
|
|
23269
|
-
this.int8Mode
|
|
23270
|
-
);
|
|
23457
|
+
try {
|
|
23458
|
+
return project(this.timeline.commit(this.captureLive(), { branch }));
|
|
23459
|
+
} catch (error) {
|
|
23460
|
+
this.historyError(error);
|
|
23461
|
+
}
|
|
23271
23462
|
}
|
|
23272
|
-
/**
|
|
23273
|
-
|
|
23274
|
-
|
|
23463
|
+
/** Point `name` at a checkpoint without copying rows or switching the live database. */
|
|
23464
|
+
fork(name, at) {
|
|
23465
|
+
this.assertOpen();
|
|
23466
|
+
try {
|
|
23467
|
+
const point = this.timeline.fork(name, at !== void 0 ? { from: at } : {});
|
|
23468
|
+
if (!point) throw pgError("misuse", "no checkpoint to fork from", "XX000");
|
|
23469
|
+
return project(point);
|
|
23470
|
+
} catch (error) {
|
|
23471
|
+
if (error instanceof PostgresError) throw error;
|
|
23472
|
+
this.historyError(error);
|
|
23473
|
+
}
|
|
23474
|
+
}
|
|
23475
|
+
/** Move `branch` to `id` and install that checkpoint as the live database. */
|
|
23476
|
+
checkout(id, branch = this.historyBranch) {
|
|
23477
|
+
this.assertOpen();
|
|
23478
|
+
if (this.transactions.inTransaction) {
|
|
23479
|
+
throw pgError("transaction_state", "cannot checkout during a transaction", "25P01");
|
|
23480
|
+
}
|
|
23481
|
+
try {
|
|
23482
|
+
const point = this.timeline.checkout(branch, id);
|
|
23483
|
+
this.historyBranch = branch;
|
|
23484
|
+
this.install(point.value);
|
|
23485
|
+
return project(point);
|
|
23486
|
+
} catch (error) {
|
|
23487
|
+
this.historyError(error);
|
|
23488
|
+
}
|
|
23489
|
+
}
|
|
23490
|
+
/** Return the live database to the origin checkpoint on `main`. */
|
|
23491
|
+
reset() {
|
|
23492
|
+
return this.checkout(this.originId, "main");
|
|
23493
|
+
}
|
|
23494
|
+
/** Checkpoint ids and branch heads. Values stay inside the timeline. */
|
|
23495
|
+
get history() {
|
|
23496
|
+
const timeline = this.timeline;
|
|
23497
|
+
return {
|
|
23498
|
+
get size() {
|
|
23499
|
+
return timeline.size;
|
|
23500
|
+
},
|
|
23501
|
+
head(branch) {
|
|
23502
|
+
const point = timeline.head(branch);
|
|
23503
|
+
return point ? project(point) : void 0;
|
|
23504
|
+
},
|
|
23505
|
+
branches() {
|
|
23506
|
+
return timeline.branches();
|
|
23507
|
+
},
|
|
23508
|
+
checkpoints() {
|
|
23509
|
+
return timeline.checkpoints().map(project);
|
|
23510
|
+
}
|
|
23511
|
+
};
|
|
23275
23512
|
}
|
|
23276
23513
|
/** Open a copy-on-write branch from `at`, or from the current state when omitted. */
|
|
23277
23514
|
branch(at = this.snapshot()) {
|
|
@@ -23316,6 +23553,26 @@ var Database = class {
|
|
|
23316
23553
|
assertOpen() {
|
|
23317
23554
|
if (this.closed) throw pgError("misuse", "Database is closed", "XX000");
|
|
23318
23555
|
}
|
|
23556
|
+
historyError(error) {
|
|
23557
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23558
|
+
throw pgError("misuse", message, "XX000");
|
|
23559
|
+
}
|
|
23560
|
+
captureLive() {
|
|
23561
|
+
return captureSnapshot(
|
|
23562
|
+
this.state,
|
|
23563
|
+
this.prng,
|
|
23564
|
+
this.now,
|
|
23565
|
+
this.seed,
|
|
23566
|
+
this.randomMode,
|
|
23567
|
+
this.systemClock,
|
|
23568
|
+
this.int8Mode
|
|
23569
|
+
);
|
|
23570
|
+
}
|
|
23571
|
+
install(snapshot) {
|
|
23572
|
+
this.state.restoreFrom(snapshot.state.cloneShallow());
|
|
23573
|
+
this.prng.setState(snapshot.prngState);
|
|
23574
|
+
if (!this.systemClock) this.now = fixedClock(new Date(snapshot.nowMs));
|
|
23575
|
+
}
|
|
23319
23576
|
prepareSingle(sql) {
|
|
23320
23577
|
const statements = parse(sql);
|
|
23321
23578
|
if (statements.length === 0) {
|