@crvouga/sqlite-mem 1.9.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/README.md +9 -8
- package/compat/scenarios.ts +9 -3
- package/dist/index.js +803 -482
- package/dist/index.js.map +4 -4
- package/dist/indexes/index.d.ts +2 -0
- package/dist/serialization/codec.d.ts +3 -11
- package/dist/serialization/wire.d.ts +61 -0
- package/dist/storage/columnar-slab.d.ts +52 -0
- package/dist/storage/table.d.ts +13 -0
- package/dist/unstable.js +807 -494
- package/dist/unstable.js.map +4 -4
- package/package.json +1 -1
package/dist/unstable.js
CHANGED
|
@@ -5964,6 +5964,10 @@ var IndexStore = class _IndexStore {
|
|
|
5964
5964
|
rememberKeyValues(key, values) {
|
|
5965
5965
|
this.keyValues.set(key, [...values]);
|
|
5966
5966
|
}
|
|
5967
|
+
/** Key component values for snapshot encode (binary keys). */
|
|
5968
|
+
keyValuesFor(key) {
|
|
5969
|
+
return [...this.keyValues.get(key) ?? []];
|
|
5970
|
+
}
|
|
5967
5971
|
get size() {
|
|
5968
5972
|
return this.entries.size;
|
|
5969
5973
|
}
|
|
@@ -6061,14 +6065,6 @@ function indexKeyValues(columns, row, ctx, table) {
|
|
|
6061
6065
|
return normalizeForCollation(raw, column.collate ?? "BINARY");
|
|
6062
6066
|
});
|
|
6063
6067
|
}
|
|
6064
|
-
function rebuildIndexFromTable(index, table, ctxForRow) {
|
|
6065
|
-
index.store.clear();
|
|
6066
|
-
for (const row of table.scan()) {
|
|
6067
|
-
const ctx = ctxForRow(row);
|
|
6068
|
-
if (index.where && isTruthySql(evalExpr(index.where, ctx)) !== true) continue;
|
|
6069
|
-
index.store.insert(indexKeyValues(index.columns, row, ctx, table), row.rowid, index.unique);
|
|
6070
|
-
}
|
|
6071
|
-
}
|
|
6072
6068
|
function tableRowEvalContext(table, row) {
|
|
6073
6069
|
return {
|
|
6074
6070
|
functions: defaultFunctionRegistry,
|
|
@@ -6089,6 +6085,126 @@ function tableRowEvalContext(table, row) {
|
|
|
6089
6085
|
};
|
|
6090
6086
|
}
|
|
6091
6087
|
|
|
6088
|
+
// src/storage/columnar-slab.ts
|
|
6089
|
+
var PACK_NULL = 0;
|
|
6090
|
+
var PACK_I32 = 1;
|
|
6091
|
+
var PACK_I64 = 2;
|
|
6092
|
+
var PACK_F64 = 3;
|
|
6093
|
+
var PACK_TEXT_INTERN = 4;
|
|
6094
|
+
var PACK_TEXT_INLINE = 5;
|
|
6095
|
+
var PACK_BLOB = 6;
|
|
6096
|
+
var PACK_TAGGED = 7;
|
|
6097
|
+
var ColumnarSlab = class {
|
|
6098
|
+
buffer;
|
|
6099
|
+
rowCount;
|
|
6100
|
+
rowids;
|
|
6101
|
+
columns;
|
|
6102
|
+
intern;
|
|
6103
|
+
rowidIndex = null;
|
|
6104
|
+
constructor(buffer, rowCount, rowids, columns, intern) {
|
|
6105
|
+
this.buffer = buffer;
|
|
6106
|
+
this.rowCount = rowCount;
|
|
6107
|
+
this.rowids = rowids;
|
|
6108
|
+
this.columns = columns;
|
|
6109
|
+
this.intern = intern;
|
|
6110
|
+
}
|
|
6111
|
+
rowIndex(rowid) {
|
|
6112
|
+
this.rowidIndex ??= new Map(this.rowids.map((id, i) => [canonicalRowid(id), i]));
|
|
6113
|
+
const hit = this.rowidIndex.get(canonicalRowid(rowid));
|
|
6114
|
+
if (hit === void 0) return -1;
|
|
6115
|
+
return hit;
|
|
6116
|
+
}
|
|
6117
|
+
cell(rowIndex, col) {
|
|
6118
|
+
if (rowIndex < 0 || rowIndex >= this.rowCount) return null;
|
|
6119
|
+
const column = this.columns[col];
|
|
6120
|
+
if (!column) return null;
|
|
6121
|
+
if (column.nullBitmap && isNull(column.nullBitmap, rowIndex)) return null;
|
|
6122
|
+
return readSlabCell(column, rowIndex, this.intern);
|
|
6123
|
+
}
|
|
6124
|
+
rowAt(rowIndex) {
|
|
6125
|
+
const values = new Array(this.columns.length);
|
|
6126
|
+
for (let c = 0; c < this.columns.length; c++) values[c] = this.cell(rowIndex, c);
|
|
6127
|
+
return { rowid: this.rowids[rowIndex], values };
|
|
6128
|
+
}
|
|
6129
|
+
get(rowid) {
|
|
6130
|
+
const i = this.rowIndex(rowid);
|
|
6131
|
+
if (i < 0) return void 0;
|
|
6132
|
+
return this.rowAt(i);
|
|
6133
|
+
}
|
|
6134
|
+
*scan() {
|
|
6135
|
+
for (let i = 0; i < this.rowCount; i++) yield this.rowAt(i);
|
|
6136
|
+
}
|
|
6137
|
+
materialize() {
|
|
6138
|
+
const map = /* @__PURE__ */ new Map();
|
|
6139
|
+
for (let i = 0; i < this.rowCount; i++) {
|
|
6140
|
+
const row = this.rowAt(i);
|
|
6141
|
+
map.set(row.rowid, row);
|
|
6142
|
+
}
|
|
6143
|
+
return map;
|
|
6144
|
+
}
|
|
6145
|
+
};
|
|
6146
|
+
function canonicalRowid(rowid) {
|
|
6147
|
+
return typeof rowid === "bigint" ? rowid : rowid;
|
|
6148
|
+
}
|
|
6149
|
+
function isNull(bits, i) {
|
|
6150
|
+
return (bits[i >> 3] & 1 << (i & 7)) !== 0;
|
|
6151
|
+
}
|
|
6152
|
+
function readSlabCell(column, rowIndex, intern) {
|
|
6153
|
+
const pack = column.pack;
|
|
6154
|
+
if (pack === PACK_NULL) return null;
|
|
6155
|
+
const nonNullIndex = nonNullRowIndex(column, rowIndex);
|
|
6156
|
+
const view = new DataView(column.payload.buffer, column.payload.byteOffset, column.payload.byteLength);
|
|
6157
|
+
if (pack === PACK_I32) {
|
|
6158
|
+
return view.getInt32(nonNullIndex * 4, true);
|
|
6159
|
+
}
|
|
6160
|
+
if (pack === PACK_I64) {
|
|
6161
|
+
const integer = view.getBigInt64(nonNullIndex * 8, true);
|
|
6162
|
+
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
6163
|
+
}
|
|
6164
|
+
if (pack === PACK_F64) {
|
|
6165
|
+
const value = view.getFloat64(nonNullIndex * 8, true);
|
|
6166
|
+
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
6167
|
+
}
|
|
6168
|
+
if (pack === PACK_TEXT_INTERN) {
|
|
6169
|
+
const id = view.getUint32(nonNullIndex * 4, true);
|
|
6170
|
+
return intern[id] ?? "";
|
|
6171
|
+
}
|
|
6172
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
6173
|
+
const offsets = column.inlineOffsets;
|
|
6174
|
+
const start = offsets[nonNullIndex];
|
|
6175
|
+
const end = nonNullIndex + 1 < offsets.length ? offsets[nonNullIndex + 1] : column.payload.length;
|
|
6176
|
+
return new TextDecoder().decode(column.payload.subarray(start, end));
|
|
6177
|
+
}
|
|
6178
|
+
if (pack === PACK_BLOB) {
|
|
6179
|
+
const blob = column.blobChunks[nonNullIndex];
|
|
6180
|
+
return blob;
|
|
6181
|
+
}
|
|
6182
|
+
if (pack === PACK_TAGGED) {
|
|
6183
|
+
return column.tagged[nonNullIndex] ?? null;
|
|
6184
|
+
}
|
|
6185
|
+
return null;
|
|
6186
|
+
}
|
|
6187
|
+
function nonNullRowIndex(column, rowIndex) {
|
|
6188
|
+
if (!column.nullBitmap) return rowIndex;
|
|
6189
|
+
let idx = 0;
|
|
6190
|
+
for (let i = 0; i < rowIndex; i++) {
|
|
6191
|
+
if (!isNull(column.nullBitmap, i)) idx++;
|
|
6192
|
+
}
|
|
6193
|
+
return idx;
|
|
6194
|
+
}
|
|
6195
|
+
function packKindOf(value) {
|
|
6196
|
+
if (value instanceof SqlReal) return PACK_F64;
|
|
6197
|
+
if (typeof value === "bigint") return PACK_I64;
|
|
6198
|
+
if (typeof value === "number" && Number.isInteger(value)) {
|
|
6199
|
+
return value >= -2147483648 && value <= 2147483647 ? PACK_I32 : PACK_I64;
|
|
6200
|
+
}
|
|
6201
|
+
if (typeof value === "number") return PACK_F64;
|
|
6202
|
+
if (value instanceof SqlJsonText) return PACK_TAGGED;
|
|
6203
|
+
if (typeof value === "string") return PACK_TEXT_INTERN;
|
|
6204
|
+
if (value instanceof Uint8Array) return PACK_BLOB;
|
|
6205
|
+
return PACK_TAGGED;
|
|
6206
|
+
}
|
|
6207
|
+
|
|
6092
6208
|
// src/types/strict.ts
|
|
6093
6209
|
var STRICT_TYPES = /* @__PURE__ */ new Set(["INT", "INTEGER", "REAL", "TEXT", "BLOB", "ANY"]);
|
|
6094
6210
|
function isStrictTypeName(typeName) {
|
|
@@ -7709,6 +7825,8 @@ var Table = class _Table {
|
|
|
7709
7825
|
strict;
|
|
7710
7826
|
/** Clustered PK key string → row for WITHOUT ROWID tables. */
|
|
7711
7827
|
clusteredRows;
|
|
7828
|
+
/** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
|
|
7829
|
+
slab = null;
|
|
7712
7830
|
scanCache = null;
|
|
7713
7831
|
/** Lazy covering hashes: column nameLower → serializeIndexKey → rowids. */
|
|
7714
7832
|
equalityHashes = null;
|
|
@@ -7772,12 +7890,49 @@ var Table = class _Table {
|
|
|
7772
7890
|
return this.integerPrimaryKeyAlias();
|
|
7773
7891
|
}
|
|
7774
7892
|
get(rowid) {
|
|
7893
|
+
if (this.slab) {
|
|
7894
|
+
const hit = this.slab.get(rowid);
|
|
7895
|
+
return hit ?? void 0;
|
|
7896
|
+
}
|
|
7775
7897
|
try {
|
|
7776
|
-
return this.rows.get(
|
|
7898
|
+
return this.rows.get(canonicalRowid2(rowid));
|
|
7777
7899
|
} catch {
|
|
7778
7900
|
return void 0;
|
|
7779
7901
|
}
|
|
7780
7902
|
}
|
|
7903
|
+
/** Row count (slab-backed or map-backed). */
|
|
7904
|
+
rowCount() {
|
|
7905
|
+
return this.slab ? this.slab.rowCount : this.rows.size;
|
|
7906
|
+
}
|
|
7907
|
+
/** Rows sorted by rowid for snapshot encode. */
|
|
7908
|
+
sortedRows() {
|
|
7909
|
+
if (this.slab) return [...this.slab.scan()].map((r) => ({ rowid: r.rowid, values: [...r.values] }));
|
|
7910
|
+
return [...this.rows.values()].sort((a, b) => compareRowids(a.rowid, b.rowid));
|
|
7911
|
+
}
|
|
7912
|
+
/** Attach decoded columnar slab (hydrate path). */
|
|
7913
|
+
attachSlab(slab) {
|
|
7914
|
+
this.slab = slab;
|
|
7915
|
+
this.invalidateScan();
|
|
7916
|
+
}
|
|
7917
|
+
/** Materialize slab into `rows` Map for mutation. */
|
|
7918
|
+
materializeSlab() {
|
|
7919
|
+
if (!this.slab) return;
|
|
7920
|
+
for (const row of this.slab.scan()) this.rows.set(row.rowid, { rowid: row.rowid, values: [...row.values] });
|
|
7921
|
+
this.slab = null;
|
|
7922
|
+
this.invalidateScan();
|
|
7923
|
+
}
|
|
7924
|
+
hasRow(rowid) {
|
|
7925
|
+
if (this.slab) return this.slab.get(rowid) !== void 0;
|
|
7926
|
+
try {
|
|
7927
|
+
return this.rows.has(canonicalRowid2(rowid));
|
|
7928
|
+
} catch {
|
|
7929
|
+
return false;
|
|
7930
|
+
}
|
|
7931
|
+
}
|
|
7932
|
+
allRowids() {
|
|
7933
|
+
if (this.slab) return this.slab.rowids;
|
|
7934
|
+
return this.rows.keys();
|
|
7935
|
+
}
|
|
7781
7936
|
getByKey(value) {
|
|
7782
7937
|
if (value === null || this.withoutRowid) return void 0;
|
|
7783
7938
|
try {
|
|
@@ -7821,20 +7976,21 @@ var Table = class _Table {
|
|
|
7821
7976
|
if (!rowids || rowids.length === 0) return [];
|
|
7822
7977
|
const rows = [];
|
|
7823
7978
|
for (const rowid of rowids) {
|
|
7824
|
-
const row = this.
|
|
7979
|
+
const row = this.get(rowid);
|
|
7825
7980
|
if (row) rows.push(row);
|
|
7826
7981
|
}
|
|
7827
7982
|
return rows;
|
|
7828
7983
|
}
|
|
7829
7984
|
ensureEqualityHash(columnLower) {
|
|
7830
|
-
if (this.frozen || this.
|
|
7985
|
+
if (this.frozen || this.rowCount() < EQUALITY_HASH_MIN_ROWS) return false;
|
|
7831
7986
|
const column = this.columns.find((item) => item.nameLower === columnLower);
|
|
7832
7987
|
if (!column) return false;
|
|
7833
7988
|
this.equalityHashes ??= /* @__PURE__ */ new Map();
|
|
7834
7989
|
if (this.equalityHashes.has(columnLower)) return true;
|
|
7835
7990
|
const map = /* @__PURE__ */ new Map();
|
|
7836
7991
|
const collate = column.collate ?? "BINARY";
|
|
7837
|
-
|
|
7992
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
7993
|
+
for (const row of iter) {
|
|
7838
7994
|
const key = serializeIndexKey([normalizeForCollation(this.cell(row, columnLower), collate)]);
|
|
7839
7995
|
if (key === null) continue;
|
|
7840
7996
|
const bucket = map.get(key);
|
|
@@ -7880,7 +8036,7 @@ var Table = class _Table {
|
|
|
7880
8036
|
if (supplied.rowid !== void 0) {
|
|
7881
8037
|
throw new SqliteError(`table ${this.name} has no column named rowid`, "other");
|
|
7882
8038
|
}
|
|
7883
|
-
const rowid2 =
|
|
8039
|
+
const rowid2 = canonicalRowid2(this.allocateRowid());
|
|
7884
8040
|
const candidate2 = { rowid: rowid2, values };
|
|
7885
8041
|
if (!options?.skipValidate) this.validate(candidate2);
|
|
7886
8042
|
const clusterKey = this.makeClusterKey(values);
|
|
@@ -7899,8 +8055,8 @@ var Table = class _Table {
|
|
|
7899
8055
|
const value = this.cell({ rowid: 0, values }, normalizeColumnName(alias.name));
|
|
7900
8056
|
if (rowid === void 0 && value !== null) rowid = asRowid(value, alias.name);
|
|
7901
8057
|
}
|
|
7902
|
-
rowid =
|
|
7903
|
-
if (this.
|
|
8058
|
+
rowid = canonicalRowid2(rowid ?? this.allocateRowid());
|
|
8059
|
+
if (this.hasRow(rowid)) {
|
|
7904
8060
|
throw new SqliteError(
|
|
7905
8061
|
`UNIQUE constraint failed: ${this.name}.rowid`,
|
|
7906
8062
|
"constraint_primary",
|
|
@@ -7917,7 +8073,7 @@ var Table = class _Table {
|
|
|
7917
8073
|
}
|
|
7918
8074
|
update(rowid, updates) {
|
|
7919
8075
|
this.assertMutable();
|
|
7920
|
-
const key =
|
|
8076
|
+
const key = canonicalRowid2(rowid);
|
|
7921
8077
|
const existing = this.rows.get(key);
|
|
7922
8078
|
if (!existing) return void 0;
|
|
7923
8079
|
const values = existing.values.slice();
|
|
@@ -7952,7 +8108,7 @@ var Table = class _Table {
|
|
|
7952
8108
|
const alias = this.integerPrimaryKeyAlias();
|
|
7953
8109
|
const aliasRow = { rowid: key, values };
|
|
7954
8110
|
const targetKey = alias ? asRowid(this.cell(aliasRow, normalizeColumnName(alias.name)), alias.name) : key;
|
|
7955
|
-
if (targetKey !== key && this.
|
|
8111
|
+
if (targetKey !== key && this.hasRow(targetKey)) {
|
|
7956
8112
|
throw new SqliteError(
|
|
7957
8113
|
`UNIQUE constraint failed: ${this.name}.${alias?.name ?? "rowid"}`,
|
|
7958
8114
|
"constraint_unique",
|
|
@@ -7975,7 +8131,7 @@ var Table = class _Table {
|
|
|
7975
8131
|
}
|
|
7976
8132
|
delete(rowid) {
|
|
7977
8133
|
this.assertMutable();
|
|
7978
|
-
const key =
|
|
8134
|
+
const key = canonicalRowid2(rowid);
|
|
7979
8135
|
const existing = this.rows.get(key);
|
|
7980
8136
|
if (!existing) return false;
|
|
7981
8137
|
if (this.withoutRowid) this.clusteredRows.delete(this.makeClusterKey(existing.values));
|
|
@@ -7987,6 +8143,10 @@ var Table = class _Table {
|
|
|
7987
8143
|
return this.rows.delete(key);
|
|
7988
8144
|
}
|
|
7989
8145
|
*scan() {
|
|
8146
|
+
if (this.slab) {
|
|
8147
|
+
yield* this.slab.scan();
|
|
8148
|
+
return;
|
|
8149
|
+
}
|
|
7990
8150
|
if (!this.scanCache) {
|
|
7991
8151
|
if (this.withoutRowid) {
|
|
7992
8152
|
this.scanCache = [...this.clusteredRows.values()].sort((a, b) => this.comparePrimaryKeys(a, b));
|
|
@@ -8006,7 +8166,16 @@ var Table = class _Table {
|
|
|
8006
8166
|
});
|
|
8007
8167
|
copy.nextRowid = this.nextRowid;
|
|
8008
8168
|
copy.maximumRowid = this.maximumRowid;
|
|
8009
|
-
|
|
8169
|
+
if (this.slab) {
|
|
8170
|
+
let max = null;
|
|
8171
|
+
for (const row of this.slab.scan()) {
|
|
8172
|
+
copy.rows.set(row.rowid, cloneRow(row));
|
|
8173
|
+
if (max === null || compareRowids(row.rowid, max) > 0) max = row.rowid;
|
|
8174
|
+
}
|
|
8175
|
+
copy.maximumRowid = max ?? void 0;
|
|
8176
|
+
} else {
|
|
8177
|
+
for (const [rowid, row] of this.rows) copy.rows.set(rowid, cloneRow(row));
|
|
8178
|
+
}
|
|
8010
8179
|
for (const [clusterKey, row] of this.clusteredRows) copy.clusteredRows.set(clusterKey, cloneRow(row));
|
|
8011
8180
|
return copy;
|
|
8012
8181
|
}
|
|
@@ -8015,13 +8184,15 @@ var Table = class _Table {
|
|
|
8015
8184
|
}
|
|
8016
8185
|
assertMutable() {
|
|
8017
8186
|
if (this.frozen) throw new SqliteError("internal: cannot mutate a frozen table", "other");
|
|
8187
|
+
if (this.slab) this.materializeSlab();
|
|
8018
8188
|
}
|
|
8019
8189
|
/** Rebuild clustered storage after snapshot decode or bulk load. */
|
|
8020
8190
|
rebuildClusteredRows() {
|
|
8021
8191
|
this.maximumRowid = void 0;
|
|
8022
8192
|
if (!this.withoutRowid) return;
|
|
8023
8193
|
this.clusteredRows.clear();
|
|
8024
|
-
|
|
8194
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
8195
|
+
for (const row of iter) {
|
|
8025
8196
|
this.clusteredRows.set(this.makeClusterKey(row.values), row);
|
|
8026
8197
|
}
|
|
8027
8198
|
this.invalidateScan();
|
|
@@ -8145,15 +8316,19 @@ var Table = class _Table {
|
|
|
8145
8316
|
if (!this.columns.some((column) => column.autoincrement)) {
|
|
8146
8317
|
if (this.maximumRowid === void 0) {
|
|
8147
8318
|
this.maximumRowid = null;
|
|
8148
|
-
for (const rowid of this.
|
|
8319
|
+
for (const rowid of this.allRowids()) {
|
|
8320
|
+
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
8321
|
+
}
|
|
8322
|
+
} else if (this.maximumRowid === null && this.rowCount() > 0) {
|
|
8323
|
+
for (const rowid of this.allRowids()) {
|
|
8149
8324
|
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
8150
8325
|
}
|
|
8151
8326
|
}
|
|
8152
8327
|
return this.maximumRowid === null ? 1 : incrementRowid(this.maximumRowid);
|
|
8153
8328
|
}
|
|
8154
8329
|
const maxSigned = 9223372036854775807n;
|
|
8155
|
-
let candidate =
|
|
8156
|
-
while (this.
|
|
8330
|
+
let candidate = canonicalRowid2(this.nextRowid);
|
|
8331
|
+
while (this.hasRow(candidate)) {
|
|
8157
8332
|
if (BigInt(candidate) >= maxSigned) {
|
|
8158
8333
|
throw new SqliteError("database or disk is full", "other", "SQLITE_FULL");
|
|
8159
8334
|
}
|
|
@@ -8193,7 +8368,7 @@ function namedFromArray(table, values) {
|
|
|
8193
8368
|
return named;
|
|
8194
8369
|
}
|
|
8195
8370
|
function asRowid(value, column) {
|
|
8196
|
-
if (typeof value === "bigint") return
|
|
8371
|
+
if (typeof value === "bigint") return canonicalRowid2(value);
|
|
8197
8372
|
if (typeof value === "number" && Number.isSafeInteger(value)) return value;
|
|
8198
8373
|
throw new SqliteError(
|
|
8199
8374
|
`datatype mismatch for INTEGER PRIMARY KEY column: ${column}`,
|
|
@@ -8201,7 +8376,7 @@ function asRowid(value, column) {
|
|
|
8201
8376
|
"SQLITE_MISMATCH"
|
|
8202
8377
|
);
|
|
8203
8378
|
}
|
|
8204
|
-
function
|
|
8379
|
+
function canonicalRowid2(value) {
|
|
8205
8380
|
if (typeof value === "number") {
|
|
8206
8381
|
if (!Number.isSafeInteger(value))
|
|
8207
8382
|
throw new SqliteError("rowid must be a safe integer or bigint", "datatype_mismatch", "SQLITE_MISMATCH");
|
|
@@ -8798,24 +8973,53 @@ function keyOf(name) {
|
|
|
8798
8973
|
return name.toLowerCase();
|
|
8799
8974
|
}
|
|
8800
8975
|
|
|
8801
|
-
// src/serialization/
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8976
|
+
// src/serialization/wire.ts
|
|
8977
|
+
function writeVarintU32(w, value) {
|
|
8978
|
+
let v = value >>> 0;
|
|
8979
|
+
while (v >= 128) {
|
|
8980
|
+
w.u8(v & 127 | 128);
|
|
8981
|
+
v >>>= 7;
|
|
8982
|
+
}
|
|
8983
|
+
w.u8(v);
|
|
8984
|
+
}
|
|
8985
|
+
function readVarintU32(r) {
|
|
8986
|
+
let result = 0;
|
|
8987
|
+
let shift = 0;
|
|
8988
|
+
for (; ; ) {
|
|
8989
|
+
const byte = r.u8();
|
|
8990
|
+
result |= (byte & 127) << shift;
|
|
8991
|
+
if ((byte & 128) === 0) return result >>> 0;
|
|
8992
|
+
shift += 7;
|
|
8993
|
+
if (shift > 28) r.fail();
|
|
8994
|
+
}
|
|
8995
|
+
}
|
|
8807
8996
|
var Writer = class {
|
|
8808
|
-
buf
|
|
8809
|
-
view
|
|
8997
|
+
buf;
|
|
8998
|
+
view;
|
|
8810
8999
|
len = 0;
|
|
9000
|
+
constructor(capacity = 4096) {
|
|
9001
|
+
this.buf = new Uint8Array(capacity);
|
|
9002
|
+
this.view = new DataView(this.buf.buffer);
|
|
9003
|
+
}
|
|
9004
|
+
get position() {
|
|
9005
|
+
return this.len;
|
|
9006
|
+
}
|
|
9007
|
+
reserve(capacity) {
|
|
9008
|
+
if (capacity <= this.buf.length) return;
|
|
9009
|
+
const next = new Uint8Array(capacity);
|
|
9010
|
+
next.set(this.buf.subarray(0, this.len));
|
|
9011
|
+
this.buf = next;
|
|
9012
|
+
this.view = new DataView(next.buffer);
|
|
9013
|
+
}
|
|
8811
9014
|
ensure(needed) {
|
|
8812
9015
|
if (this.len + needed <= this.buf.length) return;
|
|
8813
9016
|
let cap = this.buf.length;
|
|
8814
9017
|
while (cap < this.len + needed) cap *= 2;
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
9018
|
+
this.reserve(cap);
|
|
9019
|
+
}
|
|
9020
|
+
align4() {
|
|
9021
|
+
const pad2 = 4 - (this.len & 3) & 3;
|
|
9022
|
+
for (let i = 0; i < pad2; i++) this.u8(0);
|
|
8819
9023
|
}
|
|
8820
9024
|
u8(value) {
|
|
8821
9025
|
this.ensure(1);
|
|
@@ -8846,52 +9050,28 @@ var Writer = class {
|
|
|
8846
9050
|
this.buf.set(value, this.len);
|
|
8847
9051
|
this.len += value.length;
|
|
8848
9052
|
}
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
this.
|
|
8852
|
-
this.raw(bytes);
|
|
9053
|
+
rawAt(offset, value) {
|
|
9054
|
+
if (offset + value.length > this.len) this.fail();
|
|
9055
|
+
this.buf.set(value, offset);
|
|
8853
9056
|
}
|
|
8854
|
-
|
|
8855
|
-
|
|
9057
|
+
/** Length-prefixed UTF-8 via encodeInto when possible. */
|
|
9058
|
+
text(value) {
|
|
9059
|
+
const encoded = utf8Encode(value);
|
|
9060
|
+
writeVarintU32(this, encoded.length);
|
|
9061
|
+
this.raw(encoded);
|
|
8856
9062
|
}
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
8860
|
-
|
|
8861
|
-
}
|
|
8862
|
-
if (value instanceof SqlReal) {
|
|
8863
|
-
this.u8(2);
|
|
8864
|
-
this.f64(value.value);
|
|
8865
|
-
return;
|
|
8866
|
-
}
|
|
8867
|
-
if (typeof value === "bigint" || typeof value === "number" && Number.isInteger(value)) {
|
|
8868
|
-
this.u8(1);
|
|
8869
|
-
this.i64(BigInt(value));
|
|
8870
|
-
return;
|
|
8871
|
-
}
|
|
8872
|
-
if (typeof value === "number") {
|
|
8873
|
-
this.u8(2);
|
|
8874
|
-
this.f64(value);
|
|
8875
|
-
return;
|
|
8876
|
-
}
|
|
8877
|
-
if (typeof value === "string") {
|
|
8878
|
-
this.u8(3);
|
|
8879
|
-
this.text(value);
|
|
8880
|
-
return;
|
|
8881
|
-
}
|
|
8882
|
-
if (value instanceof SqlJsonText) {
|
|
8883
|
-
this.u8(3);
|
|
8884
|
-
this.text(value.value);
|
|
8885
|
-
return;
|
|
8886
|
-
}
|
|
8887
|
-
this.u8(4);
|
|
8888
|
-
this.u32(value.length);
|
|
8889
|
-
this.raw(value);
|
|
9063
|
+
/** Write UTF-8 at current position without length prefix (intern blob region). */
|
|
9064
|
+
textBytes(value) {
|
|
9065
|
+
const encoded = utf8Encode(value);
|
|
9066
|
+
this.raw(encoded);
|
|
8890
9067
|
}
|
|
8891
9068
|
finish() {
|
|
8892
9069
|
if (this.len === this.buf.length) return this.buf;
|
|
8893
9070
|
return this.buf.subarray(0, this.len).slice();
|
|
8894
9071
|
}
|
|
9072
|
+
fail() {
|
|
9073
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9074
|
+
}
|
|
8895
9075
|
};
|
|
8896
9076
|
var Reader = class {
|
|
8897
9077
|
constructor(bytes) {
|
|
@@ -8901,6 +9081,13 @@ var Reader = class {
|
|
|
8901
9081
|
bytes;
|
|
8902
9082
|
offset = 0;
|
|
8903
9083
|
view;
|
|
9084
|
+
get position() {
|
|
9085
|
+
return this.offset;
|
|
9086
|
+
}
|
|
9087
|
+
skipAlign4() {
|
|
9088
|
+
const pad2 = 4 - (this.offset & 3) & 3;
|
|
9089
|
+
this.offset += pad2;
|
|
9090
|
+
}
|
|
8904
9091
|
u8() {
|
|
8905
9092
|
if (this.offset >= this.bytes.length) this.fail();
|
|
8906
9093
|
return this.bytes[this.offset++];
|
|
@@ -8935,33 +9122,9 @@ var Reader = class {
|
|
|
8935
9122
|
this.offset += length;
|
|
8936
9123
|
return value;
|
|
8937
9124
|
}
|
|
8938
|
-
owned(length) {
|
|
8939
|
-
return this.raw(length).slice();
|
|
8940
|
-
}
|
|
8941
9125
|
text() {
|
|
8942
|
-
|
|
8943
|
-
|
|
8944
|
-
json() {
|
|
8945
|
-
try {
|
|
8946
|
-
return JSON.parse(this.text(), jsonReviver);
|
|
8947
|
-
} catch {
|
|
8948
|
-
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
8949
|
-
}
|
|
8950
|
-
}
|
|
8951
|
-
value() {
|
|
8952
|
-
const tag = this.u8();
|
|
8953
|
-
if (tag === 0) return null;
|
|
8954
|
-
if (tag === 1) {
|
|
8955
|
-
const integer = this.i64();
|
|
8956
|
-
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
8957
|
-
}
|
|
8958
|
-
if (tag === 2) {
|
|
8959
|
-
const value = this.f64();
|
|
8960
|
-
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
8961
|
-
}
|
|
8962
|
-
if (tag === 3) return this.text();
|
|
8963
|
-
if (tag === 4) return this.owned(this.u32());
|
|
8964
|
-
this.fail();
|
|
9126
|
+
const length = readVarintU32(this);
|
|
9127
|
+
return utf8Decode(this.raw(length));
|
|
8965
9128
|
}
|
|
8966
9129
|
remaining() {
|
|
8967
9130
|
return this.bytes.length - this.offset;
|
|
@@ -8973,409 +9136,317 @@ var Reader = class {
|
|
|
8973
9136
|
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
8974
9137
|
}
|
|
8975
9138
|
};
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
|
|
8980
|
-
|
|
8981
|
-
|
|
8982
|
-
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
9000
|
-
|
|
9001
|
-
const rows = [...table.rows.values()].sort((a, b) => compareRowids2(a.rowid, b.rowid));
|
|
9002
|
-
writer.u32(rows.length);
|
|
9003
|
-
for (const row of rows) {
|
|
9004
|
-
writer.value(row.rowid);
|
|
9005
|
-
writer.u32(table.columns.length);
|
|
9006
|
-
for (const column of table.columns) writer.value(table.cell(row, column.nameLower ?? column.name.toLowerCase()));
|
|
9139
|
+
var BJV_NULL = 0;
|
|
9140
|
+
var BJV_FALSE = 1;
|
|
9141
|
+
var BJV_TRUE = 2;
|
|
9142
|
+
var BJV_I32 = 3;
|
|
9143
|
+
var BJV_I64 = 4;
|
|
9144
|
+
var BJV_F64 = 5;
|
|
9145
|
+
var BJV_INTERN = 6;
|
|
9146
|
+
var BJV_STRING = 7;
|
|
9147
|
+
var BJV_BYTES = 8;
|
|
9148
|
+
var BJV_ARRAY = 9;
|
|
9149
|
+
var BJV_OBJECT = 10;
|
|
9150
|
+
function writeBjv(w, value, forceIntern) {
|
|
9151
|
+
if (value === null || value === void 0) {
|
|
9152
|
+
w.u8(BJV_NULL);
|
|
9153
|
+
return;
|
|
9154
|
+
}
|
|
9155
|
+
if (typeof value === "boolean") {
|
|
9156
|
+
w.u8(value ? BJV_TRUE : BJV_FALSE);
|
|
9157
|
+
return;
|
|
9158
|
+
}
|
|
9159
|
+
if (typeof value === "number") {
|
|
9160
|
+
if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
|
|
9161
|
+
w.u8(BJV_I32);
|
|
9162
|
+
w.u32(value | 0);
|
|
9163
|
+
return;
|
|
9007
9164
|
}
|
|
9165
|
+
w.u8(BJV_F64);
|
|
9166
|
+
w.f64(value);
|
|
9167
|
+
return;
|
|
9008
9168
|
}
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
writer.u32(indexes.length);
|
|
9014
|
-
for (const index of indexes) {
|
|
9015
|
-
writer.json({
|
|
9016
|
-
name: index.name,
|
|
9017
|
-
tableName: index.tableName,
|
|
9018
|
-
unique: index.unique,
|
|
9019
|
-
columns: index.columns,
|
|
9020
|
-
where: index.where,
|
|
9021
|
-
originalSql: index.originalSql
|
|
9022
|
-
});
|
|
9169
|
+
if (typeof value === "bigint") {
|
|
9170
|
+
w.u8(BJV_I64);
|
|
9171
|
+
w.i64(value);
|
|
9172
|
+
return;
|
|
9023
9173
|
}
|
|
9024
|
-
if (
|
|
9025
|
-
|
|
9174
|
+
if (typeof value === "string") {
|
|
9175
|
+
w.u8(BJV_INTERN);
|
|
9176
|
+
writeVarintU32(w, forceIntern(value));
|
|
9177
|
+
return;
|
|
9026
9178
|
}
|
|
9027
|
-
if (
|
|
9028
|
-
|
|
9029
|
-
|
|
9179
|
+
if (value instanceof Uint8Array) {
|
|
9180
|
+
w.u8(BJV_BYTES);
|
|
9181
|
+
writeVarintU32(w, value.length);
|
|
9182
|
+
w.raw(value);
|
|
9183
|
+
return;
|
|
9030
9184
|
}
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
return
|
|
9036
|
-
} catch (error) {
|
|
9037
|
-
if (error instanceof SqliteError) throw error;
|
|
9038
|
-
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9185
|
+
if (Array.isArray(value)) {
|
|
9186
|
+
w.u8(BJV_ARRAY);
|
|
9187
|
+
writeVarintU32(w, value.length);
|
|
9188
|
+
for (const item of value) writeBjv(w, item, forceIntern);
|
|
9189
|
+
return;
|
|
9039
9190
|
}
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9191
|
+
if (typeof value === "object") {
|
|
9192
|
+
const entries = Object.entries(value);
|
|
9193
|
+
w.u8(BJV_OBJECT);
|
|
9194
|
+
writeVarintU32(w, entries.length);
|
|
9195
|
+
for (const [k, v] of entries) {
|
|
9196
|
+
w.u8(BJV_INTERN);
|
|
9197
|
+
writeVarintU32(w, forceIntern(k));
|
|
9198
|
+
writeBjv(w, v, forceIntern);
|
|
9199
|
+
}
|
|
9200
|
+
return;
|
|
9049
9201
|
}
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9202
|
+
w.u8(BJV_NULL);
|
|
9203
|
+
}
|
|
9204
|
+
function readBjv(r, intern) {
|
|
9205
|
+
const tag = r.u8();
|
|
9206
|
+
switch (tag) {
|
|
9207
|
+
case BJV_NULL:
|
|
9208
|
+
return null;
|
|
9209
|
+
case BJV_FALSE:
|
|
9210
|
+
return false;
|
|
9211
|
+
case BJV_TRUE:
|
|
9212
|
+
return true;
|
|
9213
|
+
case BJV_I32:
|
|
9214
|
+
return r.u32() | 0;
|
|
9215
|
+
case BJV_I64:
|
|
9216
|
+
return r.i64();
|
|
9217
|
+
case BJV_F64:
|
|
9218
|
+
return r.f64();
|
|
9219
|
+
case BJV_INTERN:
|
|
9220
|
+
return intern[readVarintU32(r)] ?? "";
|
|
9221
|
+
case BJV_STRING:
|
|
9222
|
+
return r.text();
|
|
9223
|
+
case BJV_BYTES:
|
|
9224
|
+
return r.raw(readVarintU32(r)).slice();
|
|
9225
|
+
case BJV_ARRAY: {
|
|
9226
|
+
const count = readVarintU32(r);
|
|
9227
|
+
const out = new Array(count);
|
|
9228
|
+
for (let i = 0; i < count; i++) out[i] = readBjv(r, intern);
|
|
9229
|
+
return out;
|
|
9076
9230
|
}
|
|
9077
|
-
|
|
9078
|
-
|
|
9231
|
+
case BJV_OBJECT: {
|
|
9232
|
+
const count = readVarintU32(r);
|
|
9233
|
+
const out = {};
|
|
9234
|
+
for (let i = 0; i < count; i++) {
|
|
9235
|
+
const key = readBjv(r, intern);
|
|
9236
|
+
out[key] = readBjv(r, intern);
|
|
9237
|
+
}
|
|
9238
|
+
return out;
|
|
9239
|
+
}
|
|
9240
|
+
default:
|
|
9241
|
+
return r.fail();
|
|
9079
9242
|
}
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9243
|
+
}
|
|
9244
|
+
var InternPool = class {
|
|
9245
|
+
counts = /* @__PURE__ */ new Map();
|
|
9246
|
+
ids = /* @__PURE__ */ new Map();
|
|
9247
|
+
list = [];
|
|
9248
|
+
constructor() {
|
|
9249
|
+
this.list.push("");
|
|
9250
|
+
this.ids.set("", 0);
|
|
9084
9251
|
}
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
for (let indexPosition = 0; indexPosition < indexCount; indexPosition++) {
|
|
9088
|
-
const meta = reader.json();
|
|
9089
|
-
const info = { ...meta, store: new IndexStore(meta.name) };
|
|
9090
|
-
state.indexes.set(info.name.toLowerCase(), info);
|
|
9091
|
-
loadedIndexes.push(info);
|
|
9252
|
+
count(s) {
|
|
9253
|
+
this.counts.set(s, (this.counts.get(s) ?? 0) + 1);
|
|
9092
9254
|
}
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9255
|
+
/** Assign ids only to strings seen ≥2 times (plus empty string). */
|
|
9256
|
+
finalize() {
|
|
9257
|
+
for (const [s, c] of this.counts) {
|
|
9258
|
+
if (c >= 2 && !this.ids.has(s)) {
|
|
9259
|
+
const id = this.list.length;
|
|
9260
|
+
this.ids.set(s, id);
|
|
9261
|
+
this.list.push(s);
|
|
9262
|
+
}
|
|
9096
9263
|
}
|
|
9097
|
-
} else {
|
|
9098
|
-
for (const info of loadedIndexes) rebuildIndexStore(state, info);
|
|
9099
|
-
}
|
|
9100
|
-
let runtime = null;
|
|
9101
|
-
if (version >= VERSION_V2) {
|
|
9102
|
-
if (reader.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9103
|
-
runtime = {
|
|
9104
|
-
prngState: reader.u64(),
|
|
9105
|
-
nowMs: finiteNowMs(Number(reader.i64()))
|
|
9106
|
-
};
|
|
9107
9264
|
}
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
writer.u32(entry.rowids.length);
|
|
9117
|
-
for (const id of entry.rowids) writer.value(id);
|
|
9118
|
-
writer.u32(entry.values.length);
|
|
9119
|
-
for (const value of entry.values) writer.value(value);
|
|
9265
|
+
/** Always intern (schema / catalog strings). */
|
|
9266
|
+
forceId(s) {
|
|
9267
|
+
const hit = this.ids.get(s);
|
|
9268
|
+
if (hit !== void 0) return hit;
|
|
9269
|
+
const id = this.list.length;
|
|
9270
|
+
this.ids.set(s, id);
|
|
9271
|
+
this.list.push(s);
|
|
9272
|
+
return id;
|
|
9120
9273
|
}
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9274
|
+
id(s) {
|
|
9275
|
+
const hit = this.ids.get(s);
|
|
9276
|
+
if (hit !== void 0) return hit;
|
|
9277
|
+
return -1;
|
|
9278
|
+
}
|
|
9279
|
+
has(s) {
|
|
9280
|
+
return this.ids.has(s);
|
|
9281
|
+
}
|
|
9282
|
+
};
|
|
9283
|
+
function writeInternTable(w, strings) {
|
|
9284
|
+
writeVarintU32(w, strings.length);
|
|
9285
|
+
if (strings.length === 0) return;
|
|
9286
|
+
const offsets = [];
|
|
9287
|
+
let total = 0;
|
|
9288
|
+
for (const s of strings) {
|
|
9289
|
+
offsets.push(total);
|
|
9290
|
+
total += utf8Encode(s).length;
|
|
9291
|
+
}
|
|
9292
|
+
writeVarintU32(w, total);
|
|
9293
|
+
const base = w.position + offsets.length * 4;
|
|
9294
|
+
for (const off of offsets) w.u32(base + off);
|
|
9295
|
+
for (const s of strings) w.textBytes(s);
|
|
9296
|
+
}
|
|
9297
|
+
function readInternTable(r) {
|
|
9298
|
+
const count = readVarintU32(r);
|
|
9299
|
+
if (count === 0) return [];
|
|
9300
|
+
const total = readVarintU32(r);
|
|
9301
|
+
const offsets = [];
|
|
9302
|
+
for (let i = 0; i < count; i++) offsets.push(r.u32());
|
|
9303
|
+
const blobStart = r.position;
|
|
9304
|
+
const blob = r.raw(total);
|
|
9305
|
+
const intern = new Array(count);
|
|
9126
9306
|
for (let i = 0; i < count; i++) {
|
|
9127
|
-
const
|
|
9128
|
-
const
|
|
9129
|
-
|
|
9130
|
-
for (let r = 0; r < rowidCount; r++) rowids.push(asRowid2(reader.value()));
|
|
9131
|
-
const valueCount = reader.u32();
|
|
9132
|
-
const values = [];
|
|
9133
|
-
for (let v = 0; v < valueCount; v++) values.push(reader.value());
|
|
9134
|
-
entries.set(key, rowids);
|
|
9135
|
-
keyValues.set(key, values);
|
|
9307
|
+
const start = offsets[i] - blobStart;
|
|
9308
|
+
const end = i + 1 < count ? offsets[i + 1] - blobStart : total;
|
|
9309
|
+
intern[i] = utf8Decode(blob.subarray(start, end));
|
|
9136
9310
|
}
|
|
9137
|
-
return
|
|
9138
|
-
}
|
|
9139
|
-
function rebuildIndexStore(state, info) {
|
|
9140
|
-
const table = state.getTable(info.tableName);
|
|
9141
|
-
rebuildIndexFromTable(info, table, (row) => tableRowEvalContext(table, row));
|
|
9142
|
-
}
|
|
9143
|
-
function asRowid2(value) {
|
|
9144
|
-
if (typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint") return value;
|
|
9145
|
-
throw new SqliteError("invalid rowid in snapshot", "other");
|
|
9146
|
-
}
|
|
9147
|
-
function compareNames(a, b) {
|
|
9148
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
9149
|
-
}
|
|
9150
|
-
function finiteNowMs(value) {
|
|
9151
|
-
if (!Number.isFinite(value)) return 0;
|
|
9152
|
-
const max = 864e13;
|
|
9153
|
-
if (value > max) return max;
|
|
9154
|
-
if (value < -max) return -max;
|
|
9155
|
-
return value;
|
|
9156
|
-
}
|
|
9157
|
-
function compareRowids2(a, b) {
|
|
9158
|
-
const left = typeof a === "bigint" ? a : BigInt(a);
|
|
9159
|
-
const right = typeof b === "bigint" ? b : BigInt(b);
|
|
9160
|
-
if (left < right) return -1;
|
|
9161
|
-
if (left > right) return 1;
|
|
9162
|
-
return 0;
|
|
9163
|
-
}
|
|
9164
|
-
function sortedValues(map) {
|
|
9165
|
-
return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
|
|
9166
|
-
}
|
|
9167
|
-
function jsonReplacer(_key, value) {
|
|
9168
|
-
if (typeof value === "bigint") return { $sqlm: "bigint", value: value.toString() };
|
|
9169
|
-
if (value instanceof Uint8Array) return { $sqlm: "blob", value: Array.from(value) };
|
|
9170
|
-
return value;
|
|
9171
|
-
}
|
|
9172
|
-
function jsonReviver(_key, value) {
|
|
9173
|
-
if (!value || typeof value !== "object" || !("$sqlm" in value)) return value;
|
|
9174
|
-
const tagged = value;
|
|
9175
|
-
if (tagged.$sqlm === "bigint") return BigInt(tagged.value);
|
|
9176
|
-
if (tagged.$sqlm === "blob") return Uint8Array.from(tagged.value);
|
|
9177
|
-
return value;
|
|
9311
|
+
return intern;
|
|
9178
9312
|
}
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
var
|
|
9182
|
-
var
|
|
9183
|
-
var PACK_BLOB = 4;
|
|
9184
|
-
var PACK_TAGGED = 5;
|
|
9313
|
+
|
|
9314
|
+
// src/serialization/codec.ts
|
|
9315
|
+
var MAGIC = utf8Encode("SQLM");
|
|
9316
|
+
var VERSION = 5;
|
|
9185
9317
|
var AFFINITIES = ["TEXT", "NUMERIC", "INTEGER", "REAL", "BLOB"];
|
|
9186
|
-
function
|
|
9187
|
-
const
|
|
9188
|
-
const internList = [];
|
|
9189
|
-
const internId = (s) => {
|
|
9190
|
-
const hit = intern.get(s);
|
|
9191
|
-
if (hit !== void 0) return hit;
|
|
9192
|
-
const id = internList.length;
|
|
9193
|
-
intern.set(s, id);
|
|
9194
|
-
internList.push(s);
|
|
9195
|
-
return id;
|
|
9196
|
-
};
|
|
9197
|
-
internId("");
|
|
9318
|
+
function encodeDatabaseState(state, runtime) {
|
|
9319
|
+
const pool = new InternPool();
|
|
9198
9320
|
const tables = sortedValues(state.tables);
|
|
9199
9321
|
const views = sortedValues(state.views);
|
|
9200
9322
|
const indexes = sortedValues(state.indexes);
|
|
9201
9323
|
for (const table of tables) {
|
|
9202
|
-
|
|
9203
|
-
|
|
9324
|
+
pool.count(table.name);
|
|
9325
|
+
pool.count(table.originalSql ?? "");
|
|
9204
9326
|
for (const column of table.columns) {
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9327
|
+
pool.count(column.name);
|
|
9328
|
+
pool.count(column.typeName ?? "");
|
|
9329
|
+
pool.count(column.collate ?? "");
|
|
9208
9330
|
}
|
|
9209
|
-
for (const name of table.indexes)
|
|
9210
|
-
for (const row of table.
|
|
9331
|
+
for (const name of table.indexes) pool.count(name);
|
|
9332
|
+
for (const row of table.sortedRows()) {
|
|
9211
9333
|
for (const value of row.values) {
|
|
9212
|
-
if (typeof value === "string")
|
|
9213
|
-
else if (value instanceof SqlJsonText)
|
|
9334
|
+
if (typeof value === "string") pool.count(value);
|
|
9335
|
+
else if (value instanceof SqlJsonText) pool.count(value.value);
|
|
9214
9336
|
}
|
|
9215
9337
|
}
|
|
9216
9338
|
}
|
|
9217
|
-
const
|
|
9339
|
+
for (const view of views) pool.count(JSON.stringify(view));
|
|
9340
|
+
for (const index of indexes) pool.count(index.name);
|
|
9341
|
+
pool.finalize();
|
|
9342
|
+
forceSchemaIntern(pool, tables, views, indexes);
|
|
9343
|
+
const internId = (s) => pool.id(s);
|
|
9344
|
+
const forceId = (s) => pool.forceId(s);
|
|
9345
|
+
const w = new Writer(64 * 1024);
|
|
9218
9346
|
w.raw(MAGIC);
|
|
9219
9347
|
w.u32(VERSION);
|
|
9220
9348
|
w.u8(state.foreignKeysEnabled ? 1 : 0);
|
|
9221
9349
|
w.u32(state.schemaVersion);
|
|
9222
9350
|
w.u32(state.changes);
|
|
9223
9351
|
w.u32(state.totalChanges);
|
|
9224
|
-
w
|
|
9225
|
-
w.
|
|
9226
|
-
|
|
9227
|
-
w.u32(tables.length);
|
|
9352
|
+
writeTaggedValue(w, state.lastInsertRowid, internId);
|
|
9353
|
+
writeInternTable(w, pool.list);
|
|
9354
|
+
writeVarintU32(w, tables.length);
|
|
9228
9355
|
for (const table of tables) {
|
|
9229
|
-
w
|
|
9230
|
-
w
|
|
9356
|
+
writeVarintU32(w, forceId(table.name));
|
|
9357
|
+
writeVarintU32(w, table.columns.length);
|
|
9231
9358
|
for (const column of table.columns) {
|
|
9232
|
-
w
|
|
9233
|
-
w
|
|
9359
|
+
writeVarintU32(w, forceId(column.name));
|
|
9360
|
+
writeVarintU32(w, forceId(column.typeName ?? ""));
|
|
9234
9361
|
const aff = AFFINITIES.indexOf(column.affinity);
|
|
9235
9362
|
w.u8(aff < 0 ? 2 : aff);
|
|
9236
9363
|
w.u8(
|
|
9237
9364
|
(column.notNull ? 1 : 0) | (column.primaryKey ? 2 : 0) | (column.autoincrement ? 4 : 0) | (column.unique ? 8 : 0)
|
|
9238
9365
|
);
|
|
9239
|
-
w
|
|
9366
|
+
writeVarintU32(w, forceId(column.collate ?? ""));
|
|
9240
9367
|
if (column.defaultExpr) {
|
|
9241
9368
|
w.u8(1);
|
|
9242
|
-
w
|
|
9369
|
+
writeBjv(w, column.defaultExpr, forceId);
|
|
9243
9370
|
} else w.u8(0);
|
|
9244
9371
|
if (column.generated) {
|
|
9245
9372
|
w.u8(1);
|
|
9246
|
-
w
|
|
9373
|
+
writeBjv(w, column.generated, forceId);
|
|
9247
9374
|
} else w.u8(0);
|
|
9248
9375
|
}
|
|
9249
|
-
w
|
|
9250
|
-
w
|
|
9376
|
+
writeBjv(w, table.constraints, forceId);
|
|
9377
|
+
writeVarintU32(w, forceId(table.originalSql ?? ""));
|
|
9251
9378
|
w.u8((table.withoutRowid ? 1 : 0) | (table.strict ? 2 : 0));
|
|
9252
9379
|
const indexNames = [...table.indexes].sort(compareNames);
|
|
9253
|
-
w
|
|
9254
|
-
for (const name of indexNames) w
|
|
9255
|
-
w
|
|
9256
|
-
const rows =
|
|
9257
|
-
w
|
|
9258
|
-
for (const row of rows) w
|
|
9259
|
-
for (let c = 0; c < table.columns.length; c++)
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
w.
|
|
9264
|
-
for (const view of views) w.json(view);
|
|
9265
|
-
w.u32(indexes.length);
|
|
9380
|
+
writeVarintU32(w, indexNames.length);
|
|
9381
|
+
for (const name of indexNames) writeVarintU32(w, forceId(name));
|
|
9382
|
+
writeTaggedValue(w, table.nextRowid, internId);
|
|
9383
|
+
const rows = table.sortedRows();
|
|
9384
|
+
writeVarintU32(w, rows.length);
|
|
9385
|
+
for (const row of rows) writeTaggedValue(w, row.rowid, internId);
|
|
9386
|
+
for (let c = 0; c < table.columns.length; c++) writePackedColumn(w, rows, c, internId);
|
|
9387
|
+
}
|
|
9388
|
+
writeVarintU32(w, views.length);
|
|
9389
|
+
for (const view of views) writeBjv(w, view, forceId);
|
|
9390
|
+
writeVarintU32(w, indexes.length);
|
|
9266
9391
|
for (const index of indexes) {
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
for (const entry of entries) {
|
|
9280
|
-
w.text(entry.key);
|
|
9281
|
-
w.u32(entry.rowids.length);
|
|
9282
|
-
for (const id of entry.rowids) w.value(id);
|
|
9283
|
-
}
|
|
9392
|
+
writeBjv(
|
|
9393
|
+
w,
|
|
9394
|
+
{
|
|
9395
|
+
name: index.name,
|
|
9396
|
+
tableName: index.tableName,
|
|
9397
|
+
unique: index.unique,
|
|
9398
|
+
columns: index.columns,
|
|
9399
|
+
where: index.where,
|
|
9400
|
+
originalSql: index.originalSql
|
|
9401
|
+
},
|
|
9402
|
+
forceId
|
|
9403
|
+
);
|
|
9284
9404
|
}
|
|
9405
|
+
for (const index of indexes) writeIndexStoreBinary(w, index.store, internId);
|
|
9285
9406
|
w.u64(runtime.prngState);
|
|
9286
9407
|
w.i64(BigInt(Math.trunc(runtime.nowMs)));
|
|
9287
9408
|
return w.finish();
|
|
9288
9409
|
}
|
|
9289
|
-
function
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
const bits = new Uint8Array(n + 7 >> 3);
|
|
9296
|
-
let nulls = 0;
|
|
9297
|
-
let kind = null;
|
|
9298
|
-
for (let i = 0; i < n; i++) {
|
|
9299
|
-
const value = rows[i].values[col] ?? null;
|
|
9300
|
-
if (value === null) {
|
|
9301
|
-
bits[i >> 3] = bits[i >> 3] | 1 << (i & 7);
|
|
9302
|
-
nulls++;
|
|
9303
|
-
continue;
|
|
9304
|
-
}
|
|
9305
|
-
const cellKind = packKindOf(value);
|
|
9306
|
-
if (kind === null) kind = cellKind;
|
|
9307
|
-
else if (kind !== cellKind) kind = PACK_TAGGED;
|
|
9308
|
-
}
|
|
9309
|
-
if (nulls === n) {
|
|
9310
|
-
w.u8(PACK_NULL);
|
|
9311
|
-
return;
|
|
9312
|
-
}
|
|
9313
|
-
const pack = kind ?? PACK_TAGGED;
|
|
9314
|
-
w.u8(pack);
|
|
9315
|
-
w.raw(bits);
|
|
9316
|
-
for (let i = 0; i < n; i++) {
|
|
9317
|
-
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9318
|
-
const value = rows[i].values[col];
|
|
9319
|
-
writePackedCell(w, pack, value, internId);
|
|
9410
|
+
function decodeDatabaseState(snapshot) {
|
|
9411
|
+
try {
|
|
9412
|
+
return decodeInner(snapshot);
|
|
9413
|
+
} catch (error) {
|
|
9414
|
+
if (error instanceof SqliteError) throw error;
|
|
9415
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9320
9416
|
}
|
|
9321
9417
|
}
|
|
9322
|
-
function
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
if (
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
if (
|
|
9329
|
-
|
|
9330
|
-
}
|
|
9331
|
-
function writePackedCell(w, pack, value, internId) {
|
|
9332
|
-
if (pack === PACK_INT) {
|
|
9333
|
-
w.i64(typeof value === "bigint" ? value : BigInt(value));
|
|
9334
|
-
return;
|
|
9335
|
-
}
|
|
9336
|
-
if (pack === PACK_FLOAT) {
|
|
9337
|
-
w.f64(value instanceof SqlReal ? value.value : value);
|
|
9338
|
-
return;
|
|
9339
|
-
}
|
|
9340
|
-
if (pack === PACK_TEXT) {
|
|
9341
|
-
const text2 = value instanceof SqlJsonText ? value.value : value;
|
|
9342
|
-
w.u32(internId(text2));
|
|
9343
|
-
return;
|
|
9344
|
-
}
|
|
9345
|
-
if (pack === PACK_BLOB) {
|
|
9346
|
-
const blob = value;
|
|
9347
|
-
w.u32(blob.length);
|
|
9348
|
-
w.raw(blob);
|
|
9349
|
-
return;
|
|
9418
|
+
function decodeInner(snapshot) {
|
|
9419
|
+
const r = new Reader(snapshot);
|
|
9420
|
+
const magic = r.raw(4);
|
|
9421
|
+
if (!magic.every((byte, index) => byte === MAGIC[index]))
|
|
9422
|
+
throw new SqliteError("invalid sqlite-mem snapshot magic", "other");
|
|
9423
|
+
const version = r.u32();
|
|
9424
|
+
if (version !== VERSION) {
|
|
9425
|
+
throw new SqliteError(`unsupported sqlite-mem snapshot version: ${version}`, "snapshot_version", "SQLITE_FORMAT");
|
|
9350
9426
|
}
|
|
9351
|
-
w.value(value);
|
|
9352
|
-
}
|
|
9353
|
-
function decodeV4(reader) {
|
|
9354
9427
|
const state = new DatabaseState();
|
|
9355
|
-
state.foreignKeysEnabled =
|
|
9356
|
-
state.schemaVersion =
|
|
9357
|
-
state.changes =
|
|
9358
|
-
state.totalChanges =
|
|
9359
|
-
state.lastInsertRowid = asRowid2(
|
|
9360
|
-
const
|
|
9361
|
-
const intern = [];
|
|
9362
|
-
for (let i = 0; i < internCount; i++) intern.push(reader.text());
|
|
9428
|
+
state.foreignKeysEnabled = r.u8() !== 0;
|
|
9429
|
+
state.schemaVersion = r.u32();
|
|
9430
|
+
state.changes = r.u32();
|
|
9431
|
+
state.totalChanges = r.u32();
|
|
9432
|
+
state.lastInsertRowid = asRowid2(readTaggedValue(r, []));
|
|
9433
|
+
const intern = readInternTable(r);
|
|
9363
9434
|
const str = (id) => intern[id] ?? "";
|
|
9364
|
-
const tableCount =
|
|
9435
|
+
const tableCount = readVarintU32(r);
|
|
9365
9436
|
for (let t = 0; t < tableCount; t++) {
|
|
9366
|
-
const name = str(
|
|
9367
|
-
const colCount =
|
|
9437
|
+
const name = str(readVarintU32(r));
|
|
9438
|
+
const colCount = readVarintU32(r);
|
|
9368
9439
|
const columns = [];
|
|
9369
9440
|
for (let c = 0; c < colCount; c++) {
|
|
9370
|
-
const colName = str(
|
|
9371
|
-
const typeName = str(
|
|
9372
|
-
const affIndex =
|
|
9373
|
-
const flags =
|
|
9374
|
-
const collate = str(
|
|
9375
|
-
const hasDefault =
|
|
9376
|
-
const defaultExpr = hasDefault ?
|
|
9377
|
-
const hasGenerated =
|
|
9378
|
-
const generated = hasGenerated ?
|
|
9441
|
+
const colName = str(readVarintU32(r));
|
|
9442
|
+
const typeName = str(readVarintU32(r)) || null;
|
|
9443
|
+
const affIndex = r.u8();
|
|
9444
|
+
const flags = r.u8();
|
|
9445
|
+
const collate = str(readVarintU32(r)) || null;
|
|
9446
|
+
const hasDefault = r.u8() === 1;
|
|
9447
|
+
const defaultExpr = hasDefault ? readBjv(r, intern) : null;
|
|
9448
|
+
const hasGenerated = r.u8() === 1;
|
|
9449
|
+
const generated = hasGenerated ? readBjv(r, intern) : null;
|
|
9379
9450
|
columns.push({
|
|
9380
9451
|
name: colName,
|
|
9381
9452
|
nameLower: colName.toLowerCase(),
|
|
@@ -9390,12 +9461,12 @@ function decodeV4(reader) {
|
|
|
9390
9461
|
generated
|
|
9391
9462
|
});
|
|
9392
9463
|
}
|
|
9393
|
-
const constraints =
|
|
9394
|
-
const originalSql = str(
|
|
9395
|
-
const tableFlags =
|
|
9396
|
-
const
|
|
9464
|
+
const constraints = readBjv(r, intern);
|
|
9465
|
+
const originalSql = str(readVarintU32(r)) || null;
|
|
9466
|
+
const tableFlags = r.u8();
|
|
9467
|
+
const indexNameCount = readVarintU32(r);
|
|
9397
9468
|
const indexNames = [];
|
|
9398
|
-
for (let i = 0; i <
|
|
9469
|
+
for (let i = 0; i < indexNameCount; i++) indexNames.push(str(readVarintU32(r)));
|
|
9399
9470
|
const table = new Table(name, columns, {
|
|
9400
9471
|
constraints,
|
|
9401
9472
|
indexes: indexNames,
|
|
@@ -9403,42 +9474,37 @@ function decodeV4(reader) {
|
|
|
9403
9474
|
withoutRowid: (tableFlags & 1) !== 0,
|
|
9404
9475
|
strict: (tableFlags & 2) !== 0
|
|
9405
9476
|
});
|
|
9406
|
-
table.nextRowid = asRowid2(
|
|
9407
|
-
const rowCount =
|
|
9477
|
+
table.nextRowid = asRowid2(readTaggedValue(r, intern));
|
|
9478
|
+
const rowCount = readVarintU32(r);
|
|
9408
9479
|
const rowids = [];
|
|
9409
|
-
for (let
|
|
9410
|
-
const
|
|
9411
|
-
for (let c = 0; c < colCount; c++)
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
for (let c = 0; c < colCount; c++) values.push(cols[c][r] ?? null);
|
|
9415
|
-
const rowid = rowids[r];
|
|
9416
|
-
table.rows.set(rowid, { rowid, values });
|
|
9417
|
-
}
|
|
9418
|
-
table.rebuildClusteredRows();
|
|
9480
|
+
for (let ri = 0; ri < rowCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9481
|
+
const slabColumns = [];
|
|
9482
|
+
for (let c = 0; c < colCount; c++) slabColumns.push(readPackedColumn(r, rowCount, intern));
|
|
9483
|
+
table.attachSlab(new ColumnarSlab(snapshot, rowCount, rowids, slabColumns, intern));
|
|
9484
|
+
if (table.withoutRowid) table.rebuildClusteredRows();
|
|
9419
9485
|
state.tables.set(table.name.toLowerCase(), table);
|
|
9420
9486
|
}
|
|
9421
|
-
const viewCount =
|
|
9487
|
+
const viewCount = readVarintU32(r);
|
|
9422
9488
|
for (let i = 0; i < viewCount; i++) {
|
|
9423
|
-
const view =
|
|
9489
|
+
const view = readBjv(r, intern);
|
|
9424
9490
|
state.views.set(view.name.toLowerCase(), view);
|
|
9425
9491
|
}
|
|
9426
|
-
const indexCount =
|
|
9492
|
+
const indexCount = readVarintU32(r);
|
|
9427
9493
|
const loadedIndexes = [];
|
|
9428
9494
|
for (let i = 0; i < indexCount; i++) {
|
|
9429
|
-
const meta =
|
|
9495
|
+
const meta = readBjv(r, intern);
|
|
9430
9496
|
const info = { ...meta, store: new IndexStore(meta.name) };
|
|
9431
9497
|
state.indexes.set(info.name.toLowerCase(), info);
|
|
9432
9498
|
loadedIndexes.push(info);
|
|
9433
9499
|
}
|
|
9434
9500
|
for (const info of loadedIndexes) {
|
|
9435
|
-
info.store =
|
|
9501
|
+
info.store = readIndexStoreBinary(r, info.name, intern);
|
|
9436
9502
|
const table = state.tables.get(info.tableName.toLowerCase());
|
|
9437
9503
|
if (!table) continue;
|
|
9438
9504
|
for (const entry of info.store.snapshotKeys()) {
|
|
9439
9505
|
const rowid = entry.rowids[0];
|
|
9440
9506
|
if (rowid === void 0) continue;
|
|
9441
|
-
const row = table.
|
|
9507
|
+
const row = table.get(rowid);
|
|
9442
9508
|
if (!row) continue;
|
|
9443
9509
|
info.store.rememberKeyValues(
|
|
9444
9510
|
entry.key,
|
|
@@ -9446,52 +9512,299 @@ function decodeV4(reader) {
|
|
|
9446
9512
|
);
|
|
9447
9513
|
}
|
|
9448
9514
|
}
|
|
9449
|
-
if (
|
|
9450
|
-
const runtime = { prngState:
|
|
9451
|
-
if (!
|
|
9515
|
+
if (r.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9516
|
+
const runtime = { prngState: r.u64(), nowMs: finiteNowMs(Number(r.i64())) };
|
|
9517
|
+
if (!r.done()) throw new SqliteError("snapshot has trailing data", "other");
|
|
9452
9518
|
return { state, runtime };
|
|
9453
9519
|
}
|
|
9454
|
-
function
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
for (let i = 0; i < n; i++) out[i] = null;
|
|
9459
|
-
return out;
|
|
9520
|
+
function writeTaggedValue(w, value, internId) {
|
|
9521
|
+
if (value === null) {
|
|
9522
|
+
w.u8(0);
|
|
9523
|
+
return;
|
|
9460
9524
|
}
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9525
|
+
if (value instanceof SqlReal) {
|
|
9526
|
+
w.u8(2);
|
|
9527
|
+
w.f64(value.value);
|
|
9528
|
+
return;
|
|
9529
|
+
}
|
|
9530
|
+
if (typeof value === "bigint" || typeof value === "number" && Number.isInteger(value)) {
|
|
9531
|
+
w.u8(1);
|
|
9532
|
+
w.i64(BigInt(value));
|
|
9533
|
+
return;
|
|
9534
|
+
}
|
|
9535
|
+
if (typeof value === "number") {
|
|
9536
|
+
w.u8(2);
|
|
9537
|
+
w.f64(value);
|
|
9538
|
+
return;
|
|
9539
|
+
}
|
|
9540
|
+
if (typeof value === "string") {
|
|
9541
|
+
const id = internId(value);
|
|
9542
|
+
if (id >= 0) {
|
|
9543
|
+
w.u8(3);
|
|
9544
|
+
writeVarintU32(w, id);
|
|
9545
|
+
return;
|
|
9466
9546
|
}
|
|
9467
|
-
|
|
9547
|
+
w.u8(4);
|
|
9548
|
+
w.text(value);
|
|
9549
|
+
return;
|
|
9468
9550
|
}
|
|
9469
|
-
|
|
9551
|
+
if (value instanceof SqlJsonText) {
|
|
9552
|
+
w.u8(4);
|
|
9553
|
+
w.text(value.value);
|
|
9554
|
+
return;
|
|
9555
|
+
}
|
|
9556
|
+
w.u8(5);
|
|
9557
|
+
writeVarintU32(w, value.length);
|
|
9558
|
+
w.raw(value);
|
|
9470
9559
|
}
|
|
9471
|
-
function
|
|
9472
|
-
|
|
9473
|
-
|
|
9560
|
+
function readTaggedValue(r, intern) {
|
|
9561
|
+
const tag = r.u8();
|
|
9562
|
+
if (tag === 0) return null;
|
|
9563
|
+
if (tag === 1) {
|
|
9564
|
+
const integer = r.i64();
|
|
9474
9565
|
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
9475
9566
|
}
|
|
9476
|
-
if (
|
|
9477
|
-
const value =
|
|
9567
|
+
if (tag === 2) {
|
|
9568
|
+
const value = r.f64();
|
|
9478
9569
|
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
9479
9570
|
}
|
|
9480
|
-
if (
|
|
9481
|
-
if (
|
|
9482
|
-
return
|
|
9571
|
+
if (tag === 3) return intern[readVarintU32(r)] ?? "";
|
|
9572
|
+
if (tag === 4) return r.text();
|
|
9573
|
+
return r.raw(readVarintU32(r));
|
|
9483
9574
|
}
|
|
9484
|
-
function
|
|
9485
|
-
const
|
|
9575
|
+
function writePackedColumn(w, rows, col, internId) {
|
|
9576
|
+
const n = rows.length;
|
|
9577
|
+
if (n === 0) {
|
|
9578
|
+
w.u8(PACK_NULL);
|
|
9579
|
+
return;
|
|
9580
|
+
}
|
|
9581
|
+
const bits = new Uint8Array(n + 7 >> 3);
|
|
9582
|
+
let nulls = 0;
|
|
9583
|
+
let kind = null;
|
|
9584
|
+
let useInlineText = false;
|
|
9585
|
+
for (let i = 0; i < n; i++) {
|
|
9586
|
+
const value = rows[i].values[col] ?? null;
|
|
9587
|
+
if (value === null) {
|
|
9588
|
+
bits[i >> 3] = bits[i >> 3] | 1 << (i & 7);
|
|
9589
|
+
nulls++;
|
|
9590
|
+
continue;
|
|
9591
|
+
}
|
|
9592
|
+
const cellKind = packKindOf(value);
|
|
9593
|
+
if (kind === null) kind = cellKind;
|
|
9594
|
+
else if (kind !== cellKind) kind = PACK_TAGGED;
|
|
9595
|
+
if (cellKind === PACK_TEXT_INTERN && typeof value === "string" && internId(value) < 0) useInlineText = true;
|
|
9596
|
+
if (value instanceof SqlJsonText) kind = PACK_TAGGED;
|
|
9597
|
+
}
|
|
9598
|
+
if (nulls === n) {
|
|
9599
|
+
w.u8(PACK_NULL);
|
|
9600
|
+
return;
|
|
9601
|
+
}
|
|
9602
|
+
let pack = kind ?? PACK_TAGGED;
|
|
9603
|
+
if (pack === PACK_TEXT_INTERN && useInlineText) pack = PACK_TEXT_INLINE;
|
|
9604
|
+
w.u8(pack);
|
|
9605
|
+
w.raw(bits);
|
|
9606
|
+
if (pack === PACK_I32) {
|
|
9607
|
+
w.align4();
|
|
9608
|
+
for (let i = 0; i < n; i++) {
|
|
9609
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9610
|
+
w.u32(rows[i].values[col]);
|
|
9611
|
+
}
|
|
9612
|
+
return;
|
|
9613
|
+
}
|
|
9614
|
+
if (pack === PACK_I64) {
|
|
9615
|
+
w.align4();
|
|
9616
|
+
for (let i = 0; i < n; i++) {
|
|
9617
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9618
|
+
const v = rows[i].values[col];
|
|
9619
|
+
w.i64(typeof v === "bigint" ? v : BigInt(v));
|
|
9620
|
+
}
|
|
9621
|
+
return;
|
|
9622
|
+
}
|
|
9623
|
+
if (pack === PACK_F64) {
|
|
9624
|
+
w.align4();
|
|
9625
|
+
for (let i = 0; i < n; i++) {
|
|
9626
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9627
|
+
const v = rows[i].values[col];
|
|
9628
|
+
w.f64(v instanceof SqlReal ? v.value : v);
|
|
9629
|
+
}
|
|
9630
|
+
return;
|
|
9631
|
+
}
|
|
9632
|
+
if (pack === PACK_TEXT_INTERN) {
|
|
9633
|
+
w.align4();
|
|
9634
|
+
for (let i = 0; i < n; i++) {
|
|
9635
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9636
|
+
const text2 = rows[i].values[col];
|
|
9637
|
+
w.u32(internId(text2));
|
|
9638
|
+
}
|
|
9639
|
+
return;
|
|
9640
|
+
}
|
|
9641
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
9642
|
+
const offsets = [];
|
|
9643
|
+
let blobLen = 0;
|
|
9644
|
+
for (let i = 0; i < n; i++) {
|
|
9645
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9646
|
+
offsets.push(blobLen);
|
|
9647
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9648
|
+
blobLen += utf8Encode(text2).length;
|
|
9649
|
+
}
|
|
9650
|
+
writeVarintU32(w, offsets.length);
|
|
9651
|
+
for (const off of offsets) writeVarintU32(w, off);
|
|
9652
|
+
writeVarintU32(w, blobLen);
|
|
9653
|
+
for (let i = 0; i < n; i++) {
|
|
9654
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9655
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9656
|
+
w.textBytes(text2);
|
|
9657
|
+
}
|
|
9658
|
+
return;
|
|
9659
|
+
}
|
|
9660
|
+
if (pack === PACK_BLOB) {
|
|
9661
|
+
for (let i = 0; i < n; i++) {
|
|
9662
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9663
|
+
const blob = rows[i].values[col];
|
|
9664
|
+
writeVarintU32(w, blob.length);
|
|
9665
|
+
w.raw(blob);
|
|
9666
|
+
}
|
|
9667
|
+
return;
|
|
9668
|
+
}
|
|
9669
|
+
for (let i = 0; i < n; i++) {
|
|
9670
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9671
|
+
writeTaggedValue(w, rows[i].values[col], internId);
|
|
9672
|
+
}
|
|
9673
|
+
}
|
|
9674
|
+
function readPackedColumn(r, n, intern) {
|
|
9675
|
+
const pack = r.u8();
|
|
9676
|
+
if (pack === PACK_NULL) return { pack, nullBitmap: null, payload: new Uint8Array(0) };
|
|
9677
|
+
const bits = r.raw(n + 7 >> 3);
|
|
9678
|
+
const nonNull = countNonNull(bits, n);
|
|
9679
|
+
if (pack === PACK_I32 || pack === PACK_I64 || pack === PACK_F64 || pack === PACK_TEXT_INTERN) {
|
|
9680
|
+
r.skipAlign4();
|
|
9681
|
+
const width = pack === PACK_I32 || pack === PACK_TEXT_INTERN ? 4 : 8;
|
|
9682
|
+
const payload = r.raw(nonNull * width);
|
|
9683
|
+
return { pack, nullBitmap: bits, payload };
|
|
9684
|
+
}
|
|
9685
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
9686
|
+
const count = readVarintU32(r);
|
|
9687
|
+
const offsets = new Uint32Array(count);
|
|
9688
|
+
for (let i = 0; i < count; i++) offsets[i] = readVarintU32(r);
|
|
9689
|
+
const total = readVarintU32(r);
|
|
9690
|
+
const payload = r.raw(total);
|
|
9691
|
+
return { pack, nullBitmap: bits, payload, inlineOffsets: offsets };
|
|
9692
|
+
}
|
|
9693
|
+
if (pack === PACK_BLOB) {
|
|
9694
|
+
const chunks = [];
|
|
9695
|
+
for (let i = 0; i < n; i++) {
|
|
9696
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9697
|
+
const len = readVarintU32(r);
|
|
9698
|
+
chunks.push(r.raw(len));
|
|
9699
|
+
}
|
|
9700
|
+
return { pack, nullBitmap: bits, payload: new Uint8Array(0), blobChunks: chunks };
|
|
9701
|
+
}
|
|
9702
|
+
const tagged = [];
|
|
9703
|
+
for (let i = 0; i < n; i++) {
|
|
9704
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9705
|
+
tagged.push(readTaggedValue(r, intern));
|
|
9706
|
+
}
|
|
9707
|
+
return { pack: PACK_TAGGED, nullBitmap: bits, payload: new Uint8Array(0), tagged };
|
|
9708
|
+
}
|
|
9709
|
+
function countNonNull(bits, n) {
|
|
9710
|
+
let c = 0;
|
|
9711
|
+
for (let i = 0; i < n; i++) if ((bits[i >> 3] & 1 << (i & 7)) === 0) c++;
|
|
9712
|
+
return c;
|
|
9713
|
+
}
|
|
9714
|
+
function writeIndexStoreBinary(w, store, internId) {
|
|
9715
|
+
const entries = store.snapshotKeys();
|
|
9716
|
+
writeVarintU32(w, entries.length);
|
|
9717
|
+
for (const entry of entries) {
|
|
9718
|
+
const values = store.keyValuesFor(entry.key);
|
|
9719
|
+
writeVarintU32(w, values.length);
|
|
9720
|
+
for (const v of values) writeTaggedValue(w, v, internId);
|
|
9721
|
+
writeVarintU32(w, entry.rowids.length);
|
|
9722
|
+
for (const id of entry.rowids) writeTaggedValue(w, id, internId);
|
|
9723
|
+
}
|
|
9724
|
+
}
|
|
9725
|
+
function readIndexStoreBinary(r, name, intern) {
|
|
9726
|
+
const count = readVarintU32(r);
|
|
9486
9727
|
const entries = /* @__PURE__ */ new Map();
|
|
9728
|
+
const keyValues = /* @__PURE__ */ new Map();
|
|
9487
9729
|
for (let i = 0; i < count; i++) {
|
|
9488
|
-
const
|
|
9489
|
-
const
|
|
9730
|
+
const valueCount = readVarintU32(r);
|
|
9731
|
+
const values = [];
|
|
9732
|
+
for (let v = 0; v < valueCount; v++) values.push(readTaggedValue(r, intern));
|
|
9733
|
+
const key = serializeIndexEntry(values);
|
|
9734
|
+
const rowidCount = readVarintU32(r);
|
|
9490
9735
|
const rowids = [];
|
|
9491
|
-
for (let
|
|
9736
|
+
for (let ri = 0; ri < rowidCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9492
9737
|
entries.set(key, rowids);
|
|
9738
|
+
keyValues.set(key, values);
|
|
9739
|
+
}
|
|
9740
|
+
return new IndexStore(name, entries, keyValues);
|
|
9741
|
+
}
|
|
9742
|
+
function asRowid2(value) {
|
|
9743
|
+
if (typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint") return value;
|
|
9744
|
+
throw new SqliteError("invalid rowid in snapshot", "other");
|
|
9745
|
+
}
|
|
9746
|
+
function compareNames(a, b) {
|
|
9747
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
9748
|
+
}
|
|
9749
|
+
function finiteNowMs(value) {
|
|
9750
|
+
if (!Number.isFinite(value)) return 0;
|
|
9751
|
+
const max = 864e13;
|
|
9752
|
+
if (value > max) return max;
|
|
9753
|
+
if (value < -max) return -max;
|
|
9754
|
+
return value;
|
|
9755
|
+
}
|
|
9756
|
+
function sortedValues(map) {
|
|
9757
|
+
return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
|
|
9758
|
+
}
|
|
9759
|
+
function forceSchemaIntern(pool, tables, views, indexes) {
|
|
9760
|
+
for (const table of tables) {
|
|
9761
|
+
pool.forceId(table.name);
|
|
9762
|
+
pool.forceId(table.originalSql ?? "");
|
|
9763
|
+
for (const column of table.columns) {
|
|
9764
|
+
pool.forceId(column.name);
|
|
9765
|
+
pool.forceId(column.typeName ?? "");
|
|
9766
|
+
pool.forceId(column.collate ?? "");
|
|
9767
|
+
}
|
|
9768
|
+
for (const name of table.indexes) pool.forceId(name);
|
|
9769
|
+
forceBjvStrings(pool, table.constraints);
|
|
9770
|
+
for (const column of table.columns) {
|
|
9771
|
+
if (column.defaultExpr) forceBjvStrings(pool, column.defaultExpr);
|
|
9772
|
+
if (column.generated) forceBjvStrings(pool, column.generated);
|
|
9773
|
+
}
|
|
9774
|
+
}
|
|
9775
|
+
for (const view of views) forceBjvStrings(pool, view);
|
|
9776
|
+
for (const index of indexes) {
|
|
9777
|
+
pool.forceId(index.name);
|
|
9778
|
+
pool.forceId(index.tableName);
|
|
9779
|
+
pool.forceId(index.originalSql ?? "");
|
|
9780
|
+
forceBjvStrings(pool, {
|
|
9781
|
+
name: index.name,
|
|
9782
|
+
tableName: index.tableName,
|
|
9783
|
+
unique: index.unique,
|
|
9784
|
+
columns: index.columns,
|
|
9785
|
+
where: index.where,
|
|
9786
|
+
originalSql: index.originalSql
|
|
9787
|
+
});
|
|
9788
|
+
}
|
|
9789
|
+
}
|
|
9790
|
+
function forceBjvStrings(pool, value) {
|
|
9791
|
+
if (value === null || value === void 0) return;
|
|
9792
|
+
if (typeof value === "string") {
|
|
9793
|
+
pool.forceId(value);
|
|
9794
|
+
return;
|
|
9795
|
+
}
|
|
9796
|
+
if (typeof value === "bigint" || typeof value === "boolean" || typeof value === "number") return;
|
|
9797
|
+
if (value instanceof Uint8Array) return;
|
|
9798
|
+
if (Array.isArray(value)) {
|
|
9799
|
+
for (const item of value) forceBjvStrings(pool, item);
|
|
9800
|
+
return;
|
|
9801
|
+
}
|
|
9802
|
+
if (typeof value === "object") {
|
|
9803
|
+
for (const [k, v] of Object.entries(value)) {
|
|
9804
|
+
pool.forceId(k);
|
|
9805
|
+
forceBjvStrings(pool, v);
|
|
9806
|
+
}
|
|
9493
9807
|
}
|
|
9494
|
-
return new IndexStore(name, entries);
|
|
9495
9808
|
}
|
|
9496
9809
|
export {
|
|
9497
9810
|
DEFAULT_DATABASE_SEED,
|