@crvouga/sqlite-mem 1.10.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/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/index.js
CHANGED
|
@@ -2914,6 +2914,10 @@ var IndexStore = class _IndexStore {
|
|
|
2914
2914
|
rememberKeyValues(key, values) {
|
|
2915
2915
|
this.keyValues.set(key, [...values]);
|
|
2916
2916
|
}
|
|
2917
|
+
/** Key component values for snapshot encode (binary keys). */
|
|
2918
|
+
keyValuesFor(key) {
|
|
2919
|
+
return [...this.keyValues.get(key) ?? []];
|
|
2920
|
+
}
|
|
2917
2921
|
get size() {
|
|
2918
2922
|
return this.entries.size;
|
|
2919
2923
|
}
|
|
@@ -4645,6 +4649,8 @@ var Table = class _Table {
|
|
|
4645
4649
|
strict;
|
|
4646
4650
|
/** Clustered PK key string → row for WITHOUT ROWID tables. */
|
|
4647
4651
|
clusteredRows;
|
|
4652
|
+
/** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
|
|
4653
|
+
slab = null;
|
|
4648
4654
|
scanCache = null;
|
|
4649
4655
|
/** Lazy covering hashes: column nameLower → serializeIndexKey → rowids. */
|
|
4650
4656
|
equalityHashes = null;
|
|
@@ -4708,12 +4714,49 @@ var Table = class _Table {
|
|
|
4708
4714
|
return this.integerPrimaryKeyAlias();
|
|
4709
4715
|
}
|
|
4710
4716
|
get(rowid) {
|
|
4717
|
+
if (this.slab) {
|
|
4718
|
+
const hit = this.slab.get(rowid);
|
|
4719
|
+
return hit ?? void 0;
|
|
4720
|
+
}
|
|
4711
4721
|
try {
|
|
4712
4722
|
return this.rows.get(canonicalRowid(rowid));
|
|
4713
4723
|
} catch {
|
|
4714
4724
|
return void 0;
|
|
4715
4725
|
}
|
|
4716
4726
|
}
|
|
4727
|
+
/** Row count (slab-backed or map-backed). */
|
|
4728
|
+
rowCount() {
|
|
4729
|
+
return this.slab ? this.slab.rowCount : this.rows.size;
|
|
4730
|
+
}
|
|
4731
|
+
/** Rows sorted by rowid for snapshot encode. */
|
|
4732
|
+
sortedRows() {
|
|
4733
|
+
if (this.slab) return [...this.slab.scan()].map((r) => ({ rowid: r.rowid, values: [...r.values] }));
|
|
4734
|
+
return [...this.rows.values()].sort((a, b) => compareRowids(a.rowid, b.rowid));
|
|
4735
|
+
}
|
|
4736
|
+
/** Attach decoded columnar slab (hydrate path). */
|
|
4737
|
+
attachSlab(slab) {
|
|
4738
|
+
this.slab = slab;
|
|
4739
|
+
this.invalidateScan();
|
|
4740
|
+
}
|
|
4741
|
+
/** Materialize slab into `rows` Map for mutation. */
|
|
4742
|
+
materializeSlab() {
|
|
4743
|
+
if (!this.slab) return;
|
|
4744
|
+
for (const row of this.slab.scan()) this.rows.set(row.rowid, { rowid: row.rowid, values: [...row.values] });
|
|
4745
|
+
this.slab = null;
|
|
4746
|
+
this.invalidateScan();
|
|
4747
|
+
}
|
|
4748
|
+
hasRow(rowid) {
|
|
4749
|
+
if (this.slab) return this.slab.get(rowid) !== void 0;
|
|
4750
|
+
try {
|
|
4751
|
+
return this.rows.has(canonicalRowid(rowid));
|
|
4752
|
+
} catch {
|
|
4753
|
+
return false;
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4756
|
+
allRowids() {
|
|
4757
|
+
if (this.slab) return this.slab.rowids;
|
|
4758
|
+
return this.rows.keys();
|
|
4759
|
+
}
|
|
4717
4760
|
getByKey(value) {
|
|
4718
4761
|
if (value === null || this.withoutRowid) return void 0;
|
|
4719
4762
|
try {
|
|
@@ -4757,20 +4800,21 @@ var Table = class _Table {
|
|
|
4757
4800
|
if (!rowids || rowids.length === 0) return [];
|
|
4758
4801
|
const rows = [];
|
|
4759
4802
|
for (const rowid of rowids) {
|
|
4760
|
-
const row = this.
|
|
4803
|
+
const row = this.get(rowid);
|
|
4761
4804
|
if (row) rows.push(row);
|
|
4762
4805
|
}
|
|
4763
4806
|
return rows;
|
|
4764
4807
|
}
|
|
4765
4808
|
ensureEqualityHash(columnLower) {
|
|
4766
|
-
if (this.frozen || this.
|
|
4809
|
+
if (this.frozen || this.rowCount() < EQUALITY_HASH_MIN_ROWS) return false;
|
|
4767
4810
|
const column = this.columns.find((item) => item.nameLower === columnLower);
|
|
4768
4811
|
if (!column) return false;
|
|
4769
4812
|
this.equalityHashes ??= /* @__PURE__ */ new Map();
|
|
4770
4813
|
if (this.equalityHashes.has(columnLower)) return true;
|
|
4771
4814
|
const map = /* @__PURE__ */ new Map();
|
|
4772
4815
|
const collate = column.collate ?? "BINARY";
|
|
4773
|
-
|
|
4816
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
4817
|
+
for (const row of iter) {
|
|
4774
4818
|
const key = serializeIndexKey([normalizeForCollation(this.cell(row, columnLower), collate)]);
|
|
4775
4819
|
if (key === null) continue;
|
|
4776
4820
|
const bucket = map.get(key);
|
|
@@ -4836,7 +4880,7 @@ var Table = class _Table {
|
|
|
4836
4880
|
if (rowid === void 0 && value !== null) rowid = asRowid(value, alias.name);
|
|
4837
4881
|
}
|
|
4838
4882
|
rowid = canonicalRowid(rowid ?? this.allocateRowid());
|
|
4839
|
-
if (this.
|
|
4883
|
+
if (this.hasRow(rowid)) {
|
|
4840
4884
|
throw new SqliteError(
|
|
4841
4885
|
`UNIQUE constraint failed: ${this.name}.rowid`,
|
|
4842
4886
|
"constraint_primary",
|
|
@@ -4888,7 +4932,7 @@ var Table = class _Table {
|
|
|
4888
4932
|
const alias = this.integerPrimaryKeyAlias();
|
|
4889
4933
|
const aliasRow = { rowid: key, values };
|
|
4890
4934
|
const targetKey = alias ? asRowid(this.cell(aliasRow, normalizeColumnName(alias.name)), alias.name) : key;
|
|
4891
|
-
if (targetKey !== key && this.
|
|
4935
|
+
if (targetKey !== key && this.hasRow(targetKey)) {
|
|
4892
4936
|
throw new SqliteError(
|
|
4893
4937
|
`UNIQUE constraint failed: ${this.name}.${alias?.name ?? "rowid"}`,
|
|
4894
4938
|
"constraint_unique",
|
|
@@ -4923,6 +4967,10 @@ var Table = class _Table {
|
|
|
4923
4967
|
return this.rows.delete(key);
|
|
4924
4968
|
}
|
|
4925
4969
|
*scan() {
|
|
4970
|
+
if (this.slab) {
|
|
4971
|
+
yield* this.slab.scan();
|
|
4972
|
+
return;
|
|
4973
|
+
}
|
|
4926
4974
|
if (!this.scanCache) {
|
|
4927
4975
|
if (this.withoutRowid) {
|
|
4928
4976
|
this.scanCache = [...this.clusteredRows.values()].sort((a, b) => this.comparePrimaryKeys(a, b));
|
|
@@ -4942,7 +4990,16 @@ var Table = class _Table {
|
|
|
4942
4990
|
});
|
|
4943
4991
|
copy.nextRowid = this.nextRowid;
|
|
4944
4992
|
copy.maximumRowid = this.maximumRowid;
|
|
4945
|
-
|
|
4993
|
+
if (this.slab) {
|
|
4994
|
+
let max = null;
|
|
4995
|
+
for (const row of this.slab.scan()) {
|
|
4996
|
+
copy.rows.set(row.rowid, cloneRow(row));
|
|
4997
|
+
if (max === null || compareRowids(row.rowid, max) > 0) max = row.rowid;
|
|
4998
|
+
}
|
|
4999
|
+
copy.maximumRowid = max ?? void 0;
|
|
5000
|
+
} else {
|
|
5001
|
+
for (const [rowid, row] of this.rows) copy.rows.set(rowid, cloneRow(row));
|
|
5002
|
+
}
|
|
4946
5003
|
for (const [clusterKey, row] of this.clusteredRows) copy.clusteredRows.set(clusterKey, cloneRow(row));
|
|
4947
5004
|
return copy;
|
|
4948
5005
|
}
|
|
@@ -4951,13 +5008,15 @@ var Table = class _Table {
|
|
|
4951
5008
|
}
|
|
4952
5009
|
assertMutable() {
|
|
4953
5010
|
if (this.frozen) throw new SqliteError("internal: cannot mutate a frozen table", "other");
|
|
5011
|
+
if (this.slab) this.materializeSlab();
|
|
4954
5012
|
}
|
|
4955
5013
|
/** Rebuild clustered storage after snapshot decode or bulk load. */
|
|
4956
5014
|
rebuildClusteredRows() {
|
|
4957
5015
|
this.maximumRowid = void 0;
|
|
4958
5016
|
if (!this.withoutRowid) return;
|
|
4959
5017
|
this.clusteredRows.clear();
|
|
4960
|
-
|
|
5018
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
5019
|
+
for (const row of iter) {
|
|
4961
5020
|
this.clusteredRows.set(this.makeClusterKey(row.values), row);
|
|
4962
5021
|
}
|
|
4963
5022
|
this.invalidateScan();
|
|
@@ -5081,7 +5140,11 @@ var Table = class _Table {
|
|
|
5081
5140
|
if (!this.columns.some((column) => column.autoincrement)) {
|
|
5082
5141
|
if (this.maximumRowid === void 0) {
|
|
5083
5142
|
this.maximumRowid = null;
|
|
5084
|
-
for (const rowid of this.
|
|
5143
|
+
for (const rowid of this.allRowids()) {
|
|
5144
|
+
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
5145
|
+
}
|
|
5146
|
+
} else if (this.maximumRowid === null && this.rowCount() > 0) {
|
|
5147
|
+
for (const rowid of this.allRowids()) {
|
|
5085
5148
|
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
5086
5149
|
}
|
|
5087
5150
|
}
|
|
@@ -5089,7 +5152,7 @@ var Table = class _Table {
|
|
|
5089
5152
|
}
|
|
5090
5153
|
const maxSigned = 9223372036854775807n;
|
|
5091
5154
|
let candidate = canonicalRowid(this.nextRowid);
|
|
5092
|
-
while (this.
|
|
5155
|
+
while (this.hasRow(candidate)) {
|
|
5093
5156
|
if (BigInt(candidate) >= maxSigned) {
|
|
5094
5157
|
throw new SqliteError("database or disk is full", "other", "SQLITE_FULL");
|
|
5095
5158
|
}
|
|
@@ -9051,24 +9114,173 @@ function tableRowEvalContext(table, row) {
|
|
|
9051
9114
|
};
|
|
9052
9115
|
}
|
|
9053
9116
|
|
|
9054
|
-
// src/
|
|
9055
|
-
var
|
|
9056
|
-
var
|
|
9057
|
-
var
|
|
9058
|
-
var
|
|
9059
|
-
var
|
|
9117
|
+
// src/storage/columnar-slab.ts
|
|
9118
|
+
var PACK_NULL = 0;
|
|
9119
|
+
var PACK_I32 = 1;
|
|
9120
|
+
var PACK_I64 = 2;
|
|
9121
|
+
var PACK_F64 = 3;
|
|
9122
|
+
var PACK_TEXT_INTERN = 4;
|
|
9123
|
+
var PACK_TEXT_INLINE = 5;
|
|
9124
|
+
var PACK_BLOB = 6;
|
|
9125
|
+
var PACK_TAGGED = 7;
|
|
9126
|
+
var ColumnarSlab = class {
|
|
9127
|
+
buffer;
|
|
9128
|
+
rowCount;
|
|
9129
|
+
rowids;
|
|
9130
|
+
columns;
|
|
9131
|
+
intern;
|
|
9132
|
+
rowidIndex = null;
|
|
9133
|
+
constructor(buffer, rowCount, rowids, columns, intern) {
|
|
9134
|
+
this.buffer = buffer;
|
|
9135
|
+
this.rowCount = rowCount;
|
|
9136
|
+
this.rowids = rowids;
|
|
9137
|
+
this.columns = columns;
|
|
9138
|
+
this.intern = intern;
|
|
9139
|
+
}
|
|
9140
|
+
rowIndex(rowid) {
|
|
9141
|
+
this.rowidIndex ??= new Map(this.rowids.map((id, i) => [canonicalRowid2(id), i]));
|
|
9142
|
+
const hit = this.rowidIndex.get(canonicalRowid2(rowid));
|
|
9143
|
+
if (hit === void 0) return -1;
|
|
9144
|
+
return hit;
|
|
9145
|
+
}
|
|
9146
|
+
cell(rowIndex, col) {
|
|
9147
|
+
if (rowIndex < 0 || rowIndex >= this.rowCount) return null;
|
|
9148
|
+
const column = this.columns[col];
|
|
9149
|
+
if (!column) return null;
|
|
9150
|
+
if (column.nullBitmap && isNull(column.nullBitmap, rowIndex)) return null;
|
|
9151
|
+
return readSlabCell(column, rowIndex, this.intern);
|
|
9152
|
+
}
|
|
9153
|
+
rowAt(rowIndex) {
|
|
9154
|
+
const values = new Array(this.columns.length);
|
|
9155
|
+
for (let c = 0; c < this.columns.length; c++) values[c] = this.cell(rowIndex, c);
|
|
9156
|
+
return { rowid: this.rowids[rowIndex], values };
|
|
9157
|
+
}
|
|
9158
|
+
get(rowid) {
|
|
9159
|
+
const i = this.rowIndex(rowid);
|
|
9160
|
+
if (i < 0) return void 0;
|
|
9161
|
+
return this.rowAt(i);
|
|
9162
|
+
}
|
|
9163
|
+
*scan() {
|
|
9164
|
+
for (let i = 0; i < this.rowCount; i++) yield this.rowAt(i);
|
|
9165
|
+
}
|
|
9166
|
+
materialize() {
|
|
9167
|
+
const map = /* @__PURE__ */ new Map();
|
|
9168
|
+
for (let i = 0; i < this.rowCount; i++) {
|
|
9169
|
+
const row = this.rowAt(i);
|
|
9170
|
+
map.set(row.rowid, row);
|
|
9171
|
+
}
|
|
9172
|
+
return map;
|
|
9173
|
+
}
|
|
9174
|
+
};
|
|
9175
|
+
function canonicalRowid2(rowid) {
|
|
9176
|
+
return typeof rowid === "bigint" ? rowid : rowid;
|
|
9177
|
+
}
|
|
9178
|
+
function isNull(bits, i) {
|
|
9179
|
+
return (bits[i >> 3] & 1 << (i & 7)) !== 0;
|
|
9180
|
+
}
|
|
9181
|
+
function readSlabCell(column, rowIndex, intern) {
|
|
9182
|
+
const pack2 = column.pack;
|
|
9183
|
+
if (pack2 === PACK_NULL) return null;
|
|
9184
|
+
const nonNullIndex = nonNullRowIndex(column, rowIndex);
|
|
9185
|
+
const view = new DataView(column.payload.buffer, column.payload.byteOffset, column.payload.byteLength);
|
|
9186
|
+
if (pack2 === PACK_I32) {
|
|
9187
|
+
return view.getInt32(nonNullIndex * 4, true);
|
|
9188
|
+
}
|
|
9189
|
+
if (pack2 === PACK_I64) {
|
|
9190
|
+
const integer = view.getBigInt64(nonNullIndex * 8, true);
|
|
9191
|
+
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
9192
|
+
}
|
|
9193
|
+
if (pack2 === PACK_F64) {
|
|
9194
|
+
const value = view.getFloat64(nonNullIndex * 8, true);
|
|
9195
|
+
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
9196
|
+
}
|
|
9197
|
+
if (pack2 === PACK_TEXT_INTERN) {
|
|
9198
|
+
const id = view.getUint32(nonNullIndex * 4, true);
|
|
9199
|
+
return intern[id] ?? "";
|
|
9200
|
+
}
|
|
9201
|
+
if (pack2 === PACK_TEXT_INLINE) {
|
|
9202
|
+
const offsets = column.inlineOffsets;
|
|
9203
|
+
const start = offsets[nonNullIndex];
|
|
9204
|
+
const end = nonNullIndex + 1 < offsets.length ? offsets[nonNullIndex + 1] : column.payload.length;
|
|
9205
|
+
return new TextDecoder().decode(column.payload.subarray(start, end));
|
|
9206
|
+
}
|
|
9207
|
+
if (pack2 === PACK_BLOB) {
|
|
9208
|
+
const blob = column.blobChunks[nonNullIndex];
|
|
9209
|
+
return blob;
|
|
9210
|
+
}
|
|
9211
|
+
if (pack2 === PACK_TAGGED) {
|
|
9212
|
+
return column.tagged[nonNullIndex] ?? null;
|
|
9213
|
+
}
|
|
9214
|
+
return null;
|
|
9215
|
+
}
|
|
9216
|
+
function nonNullRowIndex(column, rowIndex) {
|
|
9217
|
+
if (!column.nullBitmap) return rowIndex;
|
|
9218
|
+
let idx = 0;
|
|
9219
|
+
for (let i = 0; i < rowIndex; i++) {
|
|
9220
|
+
if (!isNull(column.nullBitmap, i)) idx++;
|
|
9221
|
+
}
|
|
9222
|
+
return idx;
|
|
9223
|
+
}
|
|
9224
|
+
function packKindOf(value) {
|
|
9225
|
+
if (value instanceof SqlReal) return PACK_F64;
|
|
9226
|
+
if (typeof value === "bigint") return PACK_I64;
|
|
9227
|
+
if (typeof value === "number" && Number.isInteger(value)) {
|
|
9228
|
+
return value >= -2147483648 && value <= 2147483647 ? PACK_I32 : PACK_I64;
|
|
9229
|
+
}
|
|
9230
|
+
if (typeof value === "number") return PACK_F64;
|
|
9231
|
+
if (value instanceof SqlJsonText) return PACK_TAGGED;
|
|
9232
|
+
if (typeof value === "string") return PACK_TEXT_INTERN;
|
|
9233
|
+
if (value instanceof Uint8Array) return PACK_BLOB;
|
|
9234
|
+
return PACK_TAGGED;
|
|
9235
|
+
}
|
|
9236
|
+
|
|
9237
|
+
// src/serialization/wire.ts
|
|
9238
|
+
function writeVarintU32(w, value) {
|
|
9239
|
+
let v = value >>> 0;
|
|
9240
|
+
while (v >= 128) {
|
|
9241
|
+
w.u8(v & 127 | 128);
|
|
9242
|
+
v >>>= 7;
|
|
9243
|
+
}
|
|
9244
|
+
w.u8(v);
|
|
9245
|
+
}
|
|
9246
|
+
function readVarintU32(r) {
|
|
9247
|
+
let result = 0;
|
|
9248
|
+
let shift = 0;
|
|
9249
|
+
for (; ; ) {
|
|
9250
|
+
const byte = r.u8();
|
|
9251
|
+
result |= (byte & 127) << shift;
|
|
9252
|
+
if ((byte & 128) === 0) return result >>> 0;
|
|
9253
|
+
shift += 7;
|
|
9254
|
+
if (shift > 28) r.fail();
|
|
9255
|
+
}
|
|
9256
|
+
}
|
|
9060
9257
|
var Writer = class {
|
|
9061
|
-
buf
|
|
9062
|
-
view
|
|
9258
|
+
buf;
|
|
9259
|
+
view;
|
|
9063
9260
|
len = 0;
|
|
9261
|
+
constructor(capacity = 4096) {
|
|
9262
|
+
this.buf = new Uint8Array(capacity);
|
|
9263
|
+
this.view = new DataView(this.buf.buffer);
|
|
9264
|
+
}
|
|
9265
|
+
get position() {
|
|
9266
|
+
return this.len;
|
|
9267
|
+
}
|
|
9268
|
+
reserve(capacity) {
|
|
9269
|
+
if (capacity <= this.buf.length) return;
|
|
9270
|
+
const next = new Uint8Array(capacity);
|
|
9271
|
+
next.set(this.buf.subarray(0, this.len));
|
|
9272
|
+
this.buf = next;
|
|
9273
|
+
this.view = new DataView(next.buffer);
|
|
9274
|
+
}
|
|
9064
9275
|
ensure(needed) {
|
|
9065
9276
|
if (this.len + needed <= this.buf.length) return;
|
|
9066
9277
|
let cap = this.buf.length;
|
|
9067
9278
|
while (cap < this.len + needed) cap *= 2;
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9279
|
+
this.reserve(cap);
|
|
9280
|
+
}
|
|
9281
|
+
align4() {
|
|
9282
|
+
const pad2 = 4 - (this.len & 3) & 3;
|
|
9283
|
+
for (let i = 0; i < pad2; i++) this.u8(0);
|
|
9072
9284
|
}
|
|
9073
9285
|
u8(value) {
|
|
9074
9286
|
this.ensure(1);
|
|
@@ -9099,52 +9311,28 @@ var Writer = class {
|
|
|
9099
9311
|
this.buf.set(value, this.len);
|
|
9100
9312
|
this.len += value.length;
|
|
9101
9313
|
}
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
this.
|
|
9105
|
-
this.raw(bytes);
|
|
9314
|
+
rawAt(offset, value) {
|
|
9315
|
+
if (offset + value.length > this.len) this.fail();
|
|
9316
|
+
this.buf.set(value, offset);
|
|
9106
9317
|
}
|
|
9107
|
-
|
|
9108
|
-
|
|
9318
|
+
/** Length-prefixed UTF-8 via encodeInto when possible. */
|
|
9319
|
+
text(value) {
|
|
9320
|
+
const encoded = utf8Encode(value);
|
|
9321
|
+
writeVarintU32(this, encoded.length);
|
|
9322
|
+
this.raw(encoded);
|
|
9109
9323
|
}
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
}
|
|
9115
|
-
if (value instanceof SqlReal) {
|
|
9116
|
-
this.u8(2);
|
|
9117
|
-
this.f64(value.value);
|
|
9118
|
-
return;
|
|
9119
|
-
}
|
|
9120
|
-
if (typeof value === "bigint" || typeof value === "number" && Number.isInteger(value)) {
|
|
9121
|
-
this.u8(1);
|
|
9122
|
-
this.i64(BigInt(value));
|
|
9123
|
-
return;
|
|
9124
|
-
}
|
|
9125
|
-
if (typeof value === "number") {
|
|
9126
|
-
this.u8(2);
|
|
9127
|
-
this.f64(value);
|
|
9128
|
-
return;
|
|
9129
|
-
}
|
|
9130
|
-
if (typeof value === "string") {
|
|
9131
|
-
this.u8(3);
|
|
9132
|
-
this.text(value);
|
|
9133
|
-
return;
|
|
9134
|
-
}
|
|
9135
|
-
if (value instanceof SqlJsonText) {
|
|
9136
|
-
this.u8(3);
|
|
9137
|
-
this.text(value.value);
|
|
9138
|
-
return;
|
|
9139
|
-
}
|
|
9140
|
-
this.u8(4);
|
|
9141
|
-
this.u32(value.length);
|
|
9142
|
-
this.raw(value);
|
|
9324
|
+
/** Write UTF-8 at current position without length prefix (intern blob region). */
|
|
9325
|
+
textBytes(value) {
|
|
9326
|
+
const encoded = utf8Encode(value);
|
|
9327
|
+
this.raw(encoded);
|
|
9143
9328
|
}
|
|
9144
9329
|
finish() {
|
|
9145
9330
|
if (this.len === this.buf.length) return this.buf;
|
|
9146
9331
|
return this.buf.subarray(0, this.len).slice();
|
|
9147
9332
|
}
|
|
9333
|
+
fail() {
|
|
9334
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9335
|
+
}
|
|
9148
9336
|
};
|
|
9149
9337
|
var Reader = class {
|
|
9150
9338
|
constructor(bytes) {
|
|
@@ -9154,6 +9342,13 @@ var Reader = class {
|
|
|
9154
9342
|
bytes;
|
|
9155
9343
|
offset = 0;
|
|
9156
9344
|
view;
|
|
9345
|
+
get position() {
|
|
9346
|
+
return this.offset;
|
|
9347
|
+
}
|
|
9348
|
+
skipAlign4() {
|
|
9349
|
+
const pad2 = 4 - (this.offset & 3) & 3;
|
|
9350
|
+
this.offset += pad2;
|
|
9351
|
+
}
|
|
9157
9352
|
u8() {
|
|
9158
9353
|
if (this.offset >= this.bytes.length) this.fail();
|
|
9159
9354
|
return this.bytes[this.offset++];
|
|
@@ -9188,33 +9383,9 @@ var Reader = class {
|
|
|
9188
9383
|
this.offset += length;
|
|
9189
9384
|
return value;
|
|
9190
9385
|
}
|
|
9191
|
-
owned(length) {
|
|
9192
|
-
return this.raw(length).slice();
|
|
9193
|
-
}
|
|
9194
9386
|
text() {
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
json() {
|
|
9198
|
-
try {
|
|
9199
|
-
return JSON.parse(this.text(), jsonReviver);
|
|
9200
|
-
} catch {
|
|
9201
|
-
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9202
|
-
}
|
|
9203
|
-
}
|
|
9204
|
-
value() {
|
|
9205
|
-
const tag = this.u8();
|
|
9206
|
-
if (tag === 0) return null;
|
|
9207
|
-
if (tag === 1) {
|
|
9208
|
-
const integer = this.i64();
|
|
9209
|
-
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
9210
|
-
}
|
|
9211
|
-
if (tag === 2) {
|
|
9212
|
-
const value = this.f64();
|
|
9213
|
-
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
9214
|
-
}
|
|
9215
|
-
if (tag === 3) return this.text();
|
|
9216
|
-
if (tag === 4) return this.owned(this.u32());
|
|
9217
|
-
this.fail();
|
|
9387
|
+
const length = readVarintU32(this);
|
|
9388
|
+
return utf8Decode(this.raw(length));
|
|
9218
9389
|
}
|
|
9219
9390
|
remaining() {
|
|
9220
9391
|
return this.bytes.length - this.offset;
|
|
@@ -9226,409 +9397,317 @@ var Reader = class {
|
|
|
9226
9397
|
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9227
9398
|
}
|
|
9228
9399
|
};
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
const rows = [...table.rows.values()].sort((a, b) => compareRowids2(a.rowid, b.rowid));
|
|
9255
|
-
writer.u32(rows.length);
|
|
9256
|
-
for (const row of rows) {
|
|
9257
|
-
writer.value(row.rowid);
|
|
9258
|
-
writer.u32(table.columns.length);
|
|
9259
|
-
for (const column of table.columns) writer.value(table.cell(row, column.nameLower ?? column.name.toLowerCase()));
|
|
9400
|
+
var BJV_NULL = 0;
|
|
9401
|
+
var BJV_FALSE = 1;
|
|
9402
|
+
var BJV_TRUE = 2;
|
|
9403
|
+
var BJV_I32 = 3;
|
|
9404
|
+
var BJV_I64 = 4;
|
|
9405
|
+
var BJV_F64 = 5;
|
|
9406
|
+
var BJV_INTERN = 6;
|
|
9407
|
+
var BJV_STRING = 7;
|
|
9408
|
+
var BJV_BYTES = 8;
|
|
9409
|
+
var BJV_ARRAY = 9;
|
|
9410
|
+
var BJV_OBJECT = 10;
|
|
9411
|
+
function writeBjv(w, value, forceIntern) {
|
|
9412
|
+
if (value === null || value === void 0) {
|
|
9413
|
+
w.u8(BJV_NULL);
|
|
9414
|
+
return;
|
|
9415
|
+
}
|
|
9416
|
+
if (typeof value === "boolean") {
|
|
9417
|
+
w.u8(value ? BJV_TRUE : BJV_FALSE);
|
|
9418
|
+
return;
|
|
9419
|
+
}
|
|
9420
|
+
if (typeof value === "number") {
|
|
9421
|
+
if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
|
|
9422
|
+
w.u8(BJV_I32);
|
|
9423
|
+
w.u32(value | 0);
|
|
9424
|
+
return;
|
|
9260
9425
|
}
|
|
9426
|
+
w.u8(BJV_F64);
|
|
9427
|
+
w.f64(value);
|
|
9428
|
+
return;
|
|
9261
9429
|
}
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9265
|
-
|
|
9266
|
-
writer.u32(indexes.length);
|
|
9267
|
-
for (const index of indexes) {
|
|
9268
|
-
writer.json({
|
|
9269
|
-
name: index.name,
|
|
9270
|
-
tableName: index.tableName,
|
|
9271
|
-
unique: index.unique,
|
|
9272
|
-
columns: index.columns,
|
|
9273
|
-
where: index.where,
|
|
9274
|
-
originalSql: index.originalSql
|
|
9275
|
-
});
|
|
9430
|
+
if (typeof value === "bigint") {
|
|
9431
|
+
w.u8(BJV_I64);
|
|
9432
|
+
w.i64(value);
|
|
9433
|
+
return;
|
|
9276
9434
|
}
|
|
9277
|
-
if (
|
|
9278
|
-
|
|
9435
|
+
if (typeof value === "string") {
|
|
9436
|
+
w.u8(BJV_INTERN);
|
|
9437
|
+
writeVarintU32(w, forceIntern(value));
|
|
9438
|
+
return;
|
|
9279
9439
|
}
|
|
9280
|
-
if (
|
|
9281
|
-
|
|
9282
|
-
|
|
9440
|
+
if (value instanceof Uint8Array) {
|
|
9441
|
+
w.u8(BJV_BYTES);
|
|
9442
|
+
writeVarintU32(w, value.length);
|
|
9443
|
+
w.raw(value);
|
|
9444
|
+
return;
|
|
9283
9445
|
}
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
return
|
|
9289
|
-
} catch (error) {
|
|
9290
|
-
if (error instanceof SqliteError) throw error;
|
|
9291
|
-
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9446
|
+
if (Array.isArray(value)) {
|
|
9447
|
+
w.u8(BJV_ARRAY);
|
|
9448
|
+
writeVarintU32(w, value.length);
|
|
9449
|
+
for (const item of value) writeBjv(w, item, forceIntern);
|
|
9450
|
+
return;
|
|
9292
9451
|
}
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9452
|
+
if (typeof value === "object") {
|
|
9453
|
+
const entries = Object.entries(value);
|
|
9454
|
+
w.u8(BJV_OBJECT);
|
|
9455
|
+
writeVarintU32(w, entries.length);
|
|
9456
|
+
for (const [k, v] of entries) {
|
|
9457
|
+
w.u8(BJV_INTERN);
|
|
9458
|
+
writeVarintU32(w, forceIntern(k));
|
|
9459
|
+
writeBjv(w, v, forceIntern);
|
|
9460
|
+
}
|
|
9461
|
+
return;
|
|
9302
9462
|
}
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
|
|
9323
|
-
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9463
|
+
w.u8(BJV_NULL);
|
|
9464
|
+
}
|
|
9465
|
+
function readBjv(r, intern) {
|
|
9466
|
+
const tag = r.u8();
|
|
9467
|
+
switch (tag) {
|
|
9468
|
+
case BJV_NULL:
|
|
9469
|
+
return null;
|
|
9470
|
+
case BJV_FALSE:
|
|
9471
|
+
return false;
|
|
9472
|
+
case BJV_TRUE:
|
|
9473
|
+
return true;
|
|
9474
|
+
case BJV_I32:
|
|
9475
|
+
return r.u32() | 0;
|
|
9476
|
+
case BJV_I64:
|
|
9477
|
+
return r.i64();
|
|
9478
|
+
case BJV_F64:
|
|
9479
|
+
return r.f64();
|
|
9480
|
+
case BJV_INTERN:
|
|
9481
|
+
return intern[readVarintU32(r)] ?? "";
|
|
9482
|
+
case BJV_STRING:
|
|
9483
|
+
return r.text();
|
|
9484
|
+
case BJV_BYTES:
|
|
9485
|
+
return r.raw(readVarintU32(r)).slice();
|
|
9486
|
+
case BJV_ARRAY: {
|
|
9487
|
+
const count = readVarintU32(r);
|
|
9488
|
+
const out = new Array(count);
|
|
9489
|
+
for (let i = 0; i < count; i++) out[i] = readBjv(r, intern);
|
|
9490
|
+
return out;
|
|
9329
9491
|
}
|
|
9330
|
-
|
|
9331
|
-
|
|
9492
|
+
case BJV_OBJECT: {
|
|
9493
|
+
const count = readVarintU32(r);
|
|
9494
|
+
const out = {};
|
|
9495
|
+
for (let i = 0; i < count; i++) {
|
|
9496
|
+
const key = readBjv(r, intern);
|
|
9497
|
+
out[key] = readBjv(r, intern);
|
|
9498
|
+
}
|
|
9499
|
+
return out;
|
|
9500
|
+
}
|
|
9501
|
+
default:
|
|
9502
|
+
return r.fail();
|
|
9332
9503
|
}
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9504
|
+
}
|
|
9505
|
+
var InternPool = class {
|
|
9506
|
+
counts = /* @__PURE__ */ new Map();
|
|
9507
|
+
ids = /* @__PURE__ */ new Map();
|
|
9508
|
+
list = [];
|
|
9509
|
+
constructor() {
|
|
9510
|
+
this.list.push("");
|
|
9511
|
+
this.ids.set("", 0);
|
|
9337
9512
|
}
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
for (let indexPosition = 0; indexPosition < indexCount; indexPosition++) {
|
|
9341
|
-
const meta = reader.json();
|
|
9342
|
-
const info = { ...meta, store: new IndexStore(meta.name) };
|
|
9343
|
-
state.indexes.set(info.name.toLowerCase(), info);
|
|
9344
|
-
loadedIndexes.push(info);
|
|
9513
|
+
count(s) {
|
|
9514
|
+
this.counts.set(s, (this.counts.get(s) ?? 0) + 1);
|
|
9345
9515
|
}
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9516
|
+
/** Assign ids only to strings seen ≥2 times (plus empty string). */
|
|
9517
|
+
finalize() {
|
|
9518
|
+
for (const [s, c] of this.counts) {
|
|
9519
|
+
if (c >= 2 && !this.ids.has(s)) {
|
|
9520
|
+
const id = this.list.length;
|
|
9521
|
+
this.ids.set(s, id);
|
|
9522
|
+
this.list.push(s);
|
|
9523
|
+
}
|
|
9349
9524
|
}
|
|
9350
|
-
} else {
|
|
9351
|
-
for (const info of loadedIndexes) rebuildIndexStore(state, info);
|
|
9352
|
-
}
|
|
9353
|
-
let runtime = null;
|
|
9354
|
-
if (version >= VERSION_V2) {
|
|
9355
|
-
if (reader.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9356
|
-
runtime = {
|
|
9357
|
-
prngState: reader.u64(),
|
|
9358
|
-
nowMs: finiteNowMs(Number(reader.i64()))
|
|
9359
|
-
};
|
|
9360
9525
|
}
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
writer.u32(entry.rowids.length);
|
|
9370
|
-
for (const id of entry.rowids) writer.value(id);
|
|
9371
|
-
writer.u32(entry.values.length);
|
|
9372
|
-
for (const value of entry.values) writer.value(value);
|
|
9526
|
+
/** Always intern (schema / catalog strings). */
|
|
9527
|
+
forceId(s) {
|
|
9528
|
+
const hit = this.ids.get(s);
|
|
9529
|
+
if (hit !== void 0) return hit;
|
|
9530
|
+
const id = this.list.length;
|
|
9531
|
+
this.ids.set(s, id);
|
|
9532
|
+
this.list.push(s);
|
|
9533
|
+
return id;
|
|
9373
9534
|
}
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9535
|
+
id(s) {
|
|
9536
|
+
const hit = this.ids.get(s);
|
|
9537
|
+
if (hit !== void 0) return hit;
|
|
9538
|
+
return -1;
|
|
9539
|
+
}
|
|
9540
|
+
has(s) {
|
|
9541
|
+
return this.ids.has(s);
|
|
9542
|
+
}
|
|
9543
|
+
};
|
|
9544
|
+
function writeInternTable(w, strings) {
|
|
9545
|
+
writeVarintU32(w, strings.length);
|
|
9546
|
+
if (strings.length === 0) return;
|
|
9547
|
+
const offsets = [];
|
|
9548
|
+
let total = 0;
|
|
9549
|
+
for (const s of strings) {
|
|
9550
|
+
offsets.push(total);
|
|
9551
|
+
total += utf8Encode(s).length;
|
|
9552
|
+
}
|
|
9553
|
+
writeVarintU32(w, total);
|
|
9554
|
+
const base = w.position + offsets.length * 4;
|
|
9555
|
+
for (const off of offsets) w.u32(base + off);
|
|
9556
|
+
for (const s of strings) w.textBytes(s);
|
|
9557
|
+
}
|
|
9558
|
+
function readInternTable(r) {
|
|
9559
|
+
const count = readVarintU32(r);
|
|
9560
|
+
if (count === 0) return [];
|
|
9561
|
+
const total = readVarintU32(r);
|
|
9562
|
+
const offsets = [];
|
|
9563
|
+
for (let i = 0; i < count; i++) offsets.push(r.u32());
|
|
9564
|
+
const blobStart = r.position;
|
|
9565
|
+
const blob = r.raw(total);
|
|
9566
|
+
const intern = new Array(count);
|
|
9379
9567
|
for (let i = 0; i < count; i++) {
|
|
9380
|
-
const
|
|
9381
|
-
const
|
|
9382
|
-
|
|
9383
|
-
for (let r = 0; r < rowidCount; r++) rowids.push(asRowid2(reader.value()));
|
|
9384
|
-
const valueCount = reader.u32();
|
|
9385
|
-
const values = [];
|
|
9386
|
-
for (let v = 0; v < valueCount; v++) values.push(reader.value());
|
|
9387
|
-
entries.set(key, rowids);
|
|
9388
|
-
keyValues.set(key, values);
|
|
9568
|
+
const start = offsets[i] - blobStart;
|
|
9569
|
+
const end = i + 1 < count ? offsets[i + 1] - blobStart : total;
|
|
9570
|
+
intern[i] = utf8Decode(blob.subarray(start, end));
|
|
9389
9571
|
}
|
|
9390
|
-
return
|
|
9391
|
-
}
|
|
9392
|
-
function rebuildIndexStore(state, info) {
|
|
9393
|
-
const table = state.getTable(info.tableName);
|
|
9394
|
-
rebuildIndexFromTable(info, table, (row) => tableRowEvalContext(table, row));
|
|
9395
|
-
}
|
|
9396
|
-
function asRowid2(value) {
|
|
9397
|
-
if (typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint") return value;
|
|
9398
|
-
throw new SqliteError("invalid rowid in snapshot", "other");
|
|
9399
|
-
}
|
|
9400
|
-
function compareNames(a, b) {
|
|
9401
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
9402
|
-
}
|
|
9403
|
-
function finiteNowMs(value) {
|
|
9404
|
-
if (!Number.isFinite(value)) return 0;
|
|
9405
|
-
const max = 864e13;
|
|
9406
|
-
if (value > max) return max;
|
|
9407
|
-
if (value < -max) return -max;
|
|
9408
|
-
return value;
|
|
9409
|
-
}
|
|
9410
|
-
function compareRowids2(a, b) {
|
|
9411
|
-
const left = typeof a === "bigint" ? a : BigInt(a);
|
|
9412
|
-
const right = typeof b === "bigint" ? b : BigInt(b);
|
|
9413
|
-
if (left < right) return -1;
|
|
9414
|
-
if (left > right) return 1;
|
|
9415
|
-
return 0;
|
|
9416
|
-
}
|
|
9417
|
-
function sortedValues(map) {
|
|
9418
|
-
return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
|
|
9419
|
-
}
|
|
9420
|
-
function jsonReplacer(_key, value) {
|
|
9421
|
-
if (typeof value === "bigint") return { $sqlm: "bigint", value: value.toString() };
|
|
9422
|
-
if (value instanceof Uint8Array) return { $sqlm: "blob", value: Array.from(value) };
|
|
9423
|
-
return value;
|
|
9424
|
-
}
|
|
9425
|
-
function jsonReviver(_key, value) {
|
|
9426
|
-
if (!value || typeof value !== "object" || !("$sqlm" in value)) return value;
|
|
9427
|
-
const tagged = value;
|
|
9428
|
-
if (tagged.$sqlm === "bigint") return BigInt(tagged.value);
|
|
9429
|
-
if (tagged.$sqlm === "blob") return Uint8Array.from(tagged.value);
|
|
9430
|
-
return value;
|
|
9572
|
+
return intern;
|
|
9431
9573
|
}
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
var
|
|
9435
|
-
var
|
|
9436
|
-
var PACK_BLOB = 4;
|
|
9437
|
-
var PACK_TAGGED = 5;
|
|
9574
|
+
|
|
9575
|
+
// src/serialization/codec.ts
|
|
9576
|
+
var MAGIC = utf8Encode("SQLM");
|
|
9577
|
+
var VERSION = 5;
|
|
9438
9578
|
var AFFINITIES = ["TEXT", "NUMERIC", "INTEGER", "REAL", "BLOB"];
|
|
9439
|
-
function
|
|
9440
|
-
const
|
|
9441
|
-
const internList = [];
|
|
9442
|
-
const internId = (s) => {
|
|
9443
|
-
const hit = intern.get(s);
|
|
9444
|
-
if (hit !== void 0) return hit;
|
|
9445
|
-
const id = internList.length;
|
|
9446
|
-
intern.set(s, id);
|
|
9447
|
-
internList.push(s);
|
|
9448
|
-
return id;
|
|
9449
|
-
};
|
|
9450
|
-
internId("");
|
|
9579
|
+
function encodeDatabaseState(state, runtime) {
|
|
9580
|
+
const pool = new InternPool();
|
|
9451
9581
|
const tables = sortedValues(state.tables);
|
|
9452
9582
|
const views = sortedValues(state.views);
|
|
9453
9583
|
const indexes = sortedValues(state.indexes);
|
|
9454
9584
|
for (const table of tables) {
|
|
9455
|
-
|
|
9456
|
-
|
|
9585
|
+
pool.count(table.name);
|
|
9586
|
+
pool.count(table.originalSql ?? "");
|
|
9457
9587
|
for (const column of table.columns) {
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9588
|
+
pool.count(column.name);
|
|
9589
|
+
pool.count(column.typeName ?? "");
|
|
9590
|
+
pool.count(column.collate ?? "");
|
|
9461
9591
|
}
|
|
9462
|
-
for (const name of table.indexes)
|
|
9463
|
-
for (const row of table.
|
|
9592
|
+
for (const name of table.indexes) pool.count(name);
|
|
9593
|
+
for (const row of table.sortedRows()) {
|
|
9464
9594
|
for (const value of row.values) {
|
|
9465
|
-
if (typeof value === "string")
|
|
9466
|
-
else if (value instanceof SqlJsonText)
|
|
9595
|
+
if (typeof value === "string") pool.count(value);
|
|
9596
|
+
else if (value instanceof SqlJsonText) pool.count(value.value);
|
|
9467
9597
|
}
|
|
9468
9598
|
}
|
|
9469
9599
|
}
|
|
9470
|
-
const
|
|
9600
|
+
for (const view of views) pool.count(JSON.stringify(view));
|
|
9601
|
+
for (const index of indexes) pool.count(index.name);
|
|
9602
|
+
pool.finalize();
|
|
9603
|
+
forceSchemaIntern(pool, tables, views, indexes);
|
|
9604
|
+
const internId = (s) => pool.id(s);
|
|
9605
|
+
const forceId = (s) => pool.forceId(s);
|
|
9606
|
+
const w = new Writer(64 * 1024);
|
|
9471
9607
|
w.raw(MAGIC);
|
|
9472
9608
|
w.u32(VERSION);
|
|
9473
9609
|
w.u8(state.foreignKeysEnabled ? 1 : 0);
|
|
9474
9610
|
w.u32(state.schemaVersion);
|
|
9475
9611
|
w.u32(state.changes);
|
|
9476
9612
|
w.u32(state.totalChanges);
|
|
9477
|
-
w
|
|
9478
|
-
w.
|
|
9479
|
-
|
|
9480
|
-
w.u32(tables.length);
|
|
9613
|
+
writeTaggedValue(w, state.lastInsertRowid, internId);
|
|
9614
|
+
writeInternTable(w, pool.list);
|
|
9615
|
+
writeVarintU32(w, tables.length);
|
|
9481
9616
|
for (const table of tables) {
|
|
9482
|
-
w
|
|
9483
|
-
w
|
|
9617
|
+
writeVarintU32(w, forceId(table.name));
|
|
9618
|
+
writeVarintU32(w, table.columns.length);
|
|
9484
9619
|
for (const column of table.columns) {
|
|
9485
|
-
w
|
|
9486
|
-
w
|
|
9620
|
+
writeVarintU32(w, forceId(column.name));
|
|
9621
|
+
writeVarintU32(w, forceId(column.typeName ?? ""));
|
|
9487
9622
|
const aff = AFFINITIES.indexOf(column.affinity);
|
|
9488
9623
|
w.u8(aff < 0 ? 2 : aff);
|
|
9489
9624
|
w.u8(
|
|
9490
9625
|
(column.notNull ? 1 : 0) | (column.primaryKey ? 2 : 0) | (column.autoincrement ? 4 : 0) | (column.unique ? 8 : 0)
|
|
9491
9626
|
);
|
|
9492
|
-
w
|
|
9627
|
+
writeVarintU32(w, forceId(column.collate ?? ""));
|
|
9493
9628
|
if (column.defaultExpr) {
|
|
9494
9629
|
w.u8(1);
|
|
9495
|
-
w
|
|
9630
|
+
writeBjv(w, column.defaultExpr, forceId);
|
|
9496
9631
|
} else w.u8(0);
|
|
9497
9632
|
if (column.generated) {
|
|
9498
9633
|
w.u8(1);
|
|
9499
|
-
w
|
|
9634
|
+
writeBjv(w, column.generated, forceId);
|
|
9500
9635
|
} else w.u8(0);
|
|
9501
9636
|
}
|
|
9502
|
-
w
|
|
9503
|
-
w
|
|
9637
|
+
writeBjv(w, table.constraints, forceId);
|
|
9638
|
+
writeVarintU32(w, forceId(table.originalSql ?? ""));
|
|
9504
9639
|
w.u8((table.withoutRowid ? 1 : 0) | (table.strict ? 2 : 0));
|
|
9505
9640
|
const indexNames = [...table.indexes].sort(compareNames);
|
|
9506
|
-
w
|
|
9507
|
-
for (const name of indexNames) w
|
|
9508
|
-
w
|
|
9509
|
-
const rows =
|
|
9510
|
-
w
|
|
9511
|
-
for (const row of rows) w
|
|
9512
|
-
for (let c = 0; c < table.columns.length; c++)
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
w.
|
|
9517
|
-
for (const view of views) w.json(view);
|
|
9518
|
-
w.u32(indexes.length);
|
|
9641
|
+
writeVarintU32(w, indexNames.length);
|
|
9642
|
+
for (const name of indexNames) writeVarintU32(w, forceId(name));
|
|
9643
|
+
writeTaggedValue(w, table.nextRowid, internId);
|
|
9644
|
+
const rows = table.sortedRows();
|
|
9645
|
+
writeVarintU32(w, rows.length);
|
|
9646
|
+
for (const row of rows) writeTaggedValue(w, row.rowid, internId);
|
|
9647
|
+
for (let c = 0; c < table.columns.length; c++) writePackedColumn(w, rows, c, internId);
|
|
9648
|
+
}
|
|
9649
|
+
writeVarintU32(w, views.length);
|
|
9650
|
+
for (const view of views) writeBjv(w, view, forceId);
|
|
9651
|
+
writeVarintU32(w, indexes.length);
|
|
9519
9652
|
for (const index of indexes) {
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
for (const entry of entries) {
|
|
9533
|
-
w.text(entry.key);
|
|
9534
|
-
w.u32(entry.rowids.length);
|
|
9535
|
-
for (const id of entry.rowids) w.value(id);
|
|
9536
|
-
}
|
|
9653
|
+
writeBjv(
|
|
9654
|
+
w,
|
|
9655
|
+
{
|
|
9656
|
+
name: index.name,
|
|
9657
|
+
tableName: index.tableName,
|
|
9658
|
+
unique: index.unique,
|
|
9659
|
+
columns: index.columns,
|
|
9660
|
+
where: index.where,
|
|
9661
|
+
originalSql: index.originalSql
|
|
9662
|
+
},
|
|
9663
|
+
forceId
|
|
9664
|
+
);
|
|
9537
9665
|
}
|
|
9666
|
+
for (const index of indexes) writeIndexStoreBinary(w, index.store, internId);
|
|
9538
9667
|
w.u64(runtime.prngState);
|
|
9539
9668
|
w.i64(BigInt(Math.trunc(runtime.nowMs)));
|
|
9540
9669
|
return w.finish();
|
|
9541
9670
|
}
|
|
9542
|
-
function
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
const bits = new Uint8Array(n + 7 >> 3);
|
|
9549
|
-
let nulls = 0;
|
|
9550
|
-
let kind = null;
|
|
9551
|
-
for (let i = 0; i < n; i++) {
|
|
9552
|
-
const value = rows[i].values[col] ?? null;
|
|
9553
|
-
if (value === null) {
|
|
9554
|
-
bits[i >> 3] = bits[i >> 3] | 1 << (i & 7);
|
|
9555
|
-
nulls++;
|
|
9556
|
-
continue;
|
|
9557
|
-
}
|
|
9558
|
-
const cellKind = packKindOf(value);
|
|
9559
|
-
if (kind === null) kind = cellKind;
|
|
9560
|
-
else if (kind !== cellKind) kind = PACK_TAGGED;
|
|
9561
|
-
}
|
|
9562
|
-
if (nulls === n) {
|
|
9563
|
-
w.u8(PACK_NULL);
|
|
9564
|
-
return;
|
|
9565
|
-
}
|
|
9566
|
-
const pack2 = kind ?? PACK_TAGGED;
|
|
9567
|
-
w.u8(pack2);
|
|
9568
|
-
w.raw(bits);
|
|
9569
|
-
for (let i = 0; i < n; i++) {
|
|
9570
|
-
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9571
|
-
const value = rows[i].values[col];
|
|
9572
|
-
writePackedCell(w, pack2, value, internId);
|
|
9671
|
+
function decodeDatabaseState(snapshot) {
|
|
9672
|
+
try {
|
|
9673
|
+
return decodeInner(snapshot);
|
|
9674
|
+
} catch (error) {
|
|
9675
|
+
if (error instanceof SqliteError) throw error;
|
|
9676
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9573
9677
|
}
|
|
9574
9678
|
}
|
|
9575
|
-
function
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
if (
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
if (
|
|
9582
|
-
|
|
9583
|
-
}
|
|
9584
|
-
function writePackedCell(w, pack2, value, internId) {
|
|
9585
|
-
if (pack2 === PACK_INT) {
|
|
9586
|
-
w.i64(typeof value === "bigint" ? value : BigInt(value));
|
|
9587
|
-
return;
|
|
9588
|
-
}
|
|
9589
|
-
if (pack2 === PACK_FLOAT) {
|
|
9590
|
-
w.f64(value instanceof SqlReal ? value.value : value);
|
|
9591
|
-
return;
|
|
9592
|
-
}
|
|
9593
|
-
if (pack2 === PACK_TEXT) {
|
|
9594
|
-
const text2 = value instanceof SqlJsonText ? value.value : value;
|
|
9595
|
-
w.u32(internId(text2));
|
|
9596
|
-
return;
|
|
9597
|
-
}
|
|
9598
|
-
if (pack2 === PACK_BLOB) {
|
|
9599
|
-
const blob = value;
|
|
9600
|
-
w.u32(blob.length);
|
|
9601
|
-
w.raw(blob);
|
|
9602
|
-
return;
|
|
9679
|
+
function decodeInner(snapshot) {
|
|
9680
|
+
const r = new Reader(snapshot);
|
|
9681
|
+
const magic = r.raw(4);
|
|
9682
|
+
if (!magic.every((byte, index) => byte === MAGIC[index]))
|
|
9683
|
+
throw new SqliteError("invalid sqlite-mem snapshot magic", "other");
|
|
9684
|
+
const version = r.u32();
|
|
9685
|
+
if (version !== VERSION) {
|
|
9686
|
+
throw new SqliteError(`unsupported sqlite-mem snapshot version: ${version}`, "snapshot_version", "SQLITE_FORMAT");
|
|
9603
9687
|
}
|
|
9604
|
-
w.value(value);
|
|
9605
|
-
}
|
|
9606
|
-
function decodeV4(reader) {
|
|
9607
9688
|
const state = new DatabaseState();
|
|
9608
|
-
state.foreignKeysEnabled =
|
|
9609
|
-
state.schemaVersion =
|
|
9610
|
-
state.changes =
|
|
9611
|
-
state.totalChanges =
|
|
9612
|
-
state.lastInsertRowid = asRowid2(
|
|
9613
|
-
const
|
|
9614
|
-
const intern = [];
|
|
9615
|
-
for (let i = 0; i < internCount; i++) intern.push(reader.text());
|
|
9689
|
+
state.foreignKeysEnabled = r.u8() !== 0;
|
|
9690
|
+
state.schemaVersion = r.u32();
|
|
9691
|
+
state.changes = r.u32();
|
|
9692
|
+
state.totalChanges = r.u32();
|
|
9693
|
+
state.lastInsertRowid = asRowid2(readTaggedValue(r, []));
|
|
9694
|
+
const intern = readInternTable(r);
|
|
9616
9695
|
const str = (id) => intern[id] ?? "";
|
|
9617
|
-
const tableCount =
|
|
9696
|
+
const tableCount = readVarintU32(r);
|
|
9618
9697
|
for (let t = 0; t < tableCount; t++) {
|
|
9619
|
-
const name = str(
|
|
9620
|
-
const colCount =
|
|
9698
|
+
const name = str(readVarintU32(r));
|
|
9699
|
+
const colCount = readVarintU32(r);
|
|
9621
9700
|
const columns = [];
|
|
9622
9701
|
for (let c = 0; c < colCount; c++) {
|
|
9623
|
-
const colName = str(
|
|
9624
|
-
const typeName = str(
|
|
9625
|
-
const affIndex =
|
|
9626
|
-
const flags =
|
|
9627
|
-
const collate = str(
|
|
9628
|
-
const hasDefault =
|
|
9629
|
-
const defaultExpr = hasDefault ?
|
|
9630
|
-
const hasGenerated =
|
|
9631
|
-
const generated = hasGenerated ?
|
|
9702
|
+
const colName = str(readVarintU32(r));
|
|
9703
|
+
const typeName = str(readVarintU32(r)) || null;
|
|
9704
|
+
const affIndex = r.u8();
|
|
9705
|
+
const flags = r.u8();
|
|
9706
|
+
const collate = str(readVarintU32(r)) || null;
|
|
9707
|
+
const hasDefault = r.u8() === 1;
|
|
9708
|
+
const defaultExpr = hasDefault ? readBjv(r, intern) : null;
|
|
9709
|
+
const hasGenerated = r.u8() === 1;
|
|
9710
|
+
const generated = hasGenerated ? readBjv(r, intern) : null;
|
|
9632
9711
|
columns.push({
|
|
9633
9712
|
name: colName,
|
|
9634
9713
|
nameLower: colName.toLowerCase(),
|
|
@@ -9643,12 +9722,12 @@ function decodeV4(reader) {
|
|
|
9643
9722
|
generated
|
|
9644
9723
|
});
|
|
9645
9724
|
}
|
|
9646
|
-
const constraints =
|
|
9647
|
-
const originalSql = str(
|
|
9648
|
-
const tableFlags =
|
|
9649
|
-
const
|
|
9725
|
+
const constraints = readBjv(r, intern);
|
|
9726
|
+
const originalSql = str(readVarintU32(r)) || null;
|
|
9727
|
+
const tableFlags = r.u8();
|
|
9728
|
+
const indexNameCount = readVarintU32(r);
|
|
9650
9729
|
const indexNames = [];
|
|
9651
|
-
for (let i = 0; i <
|
|
9730
|
+
for (let i = 0; i < indexNameCount; i++) indexNames.push(str(readVarintU32(r)));
|
|
9652
9731
|
const table = new Table(name, columns, {
|
|
9653
9732
|
constraints,
|
|
9654
9733
|
indexes: indexNames,
|
|
@@ -9656,42 +9735,37 @@ function decodeV4(reader) {
|
|
|
9656
9735
|
withoutRowid: (tableFlags & 1) !== 0,
|
|
9657
9736
|
strict: (tableFlags & 2) !== 0
|
|
9658
9737
|
});
|
|
9659
|
-
table.nextRowid = asRowid2(
|
|
9660
|
-
const rowCount =
|
|
9738
|
+
table.nextRowid = asRowid2(readTaggedValue(r, intern));
|
|
9739
|
+
const rowCount = readVarintU32(r);
|
|
9661
9740
|
const rowids = [];
|
|
9662
|
-
for (let
|
|
9663
|
-
const
|
|
9664
|
-
for (let c = 0; c < colCount; c++)
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
for (let c = 0; c < colCount; c++) values.push(cols[c][r] ?? null);
|
|
9668
|
-
const rowid = rowids[r];
|
|
9669
|
-
table.rows.set(rowid, { rowid, values });
|
|
9670
|
-
}
|
|
9671
|
-
table.rebuildClusteredRows();
|
|
9741
|
+
for (let ri = 0; ri < rowCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9742
|
+
const slabColumns = [];
|
|
9743
|
+
for (let c = 0; c < colCount; c++) slabColumns.push(readPackedColumn(r, rowCount, intern));
|
|
9744
|
+
table.attachSlab(new ColumnarSlab(snapshot, rowCount, rowids, slabColumns, intern));
|
|
9745
|
+
if (table.withoutRowid) table.rebuildClusteredRows();
|
|
9672
9746
|
state.tables.set(table.name.toLowerCase(), table);
|
|
9673
9747
|
}
|
|
9674
|
-
const viewCount =
|
|
9748
|
+
const viewCount = readVarintU32(r);
|
|
9675
9749
|
for (let i = 0; i < viewCount; i++) {
|
|
9676
|
-
const view =
|
|
9750
|
+
const view = readBjv(r, intern);
|
|
9677
9751
|
state.views.set(view.name.toLowerCase(), view);
|
|
9678
9752
|
}
|
|
9679
|
-
const indexCount =
|
|
9753
|
+
const indexCount = readVarintU32(r);
|
|
9680
9754
|
const loadedIndexes = [];
|
|
9681
9755
|
for (let i = 0; i < indexCount; i++) {
|
|
9682
|
-
const meta =
|
|
9756
|
+
const meta = readBjv(r, intern);
|
|
9683
9757
|
const info = { ...meta, store: new IndexStore(meta.name) };
|
|
9684
9758
|
state.indexes.set(info.name.toLowerCase(), info);
|
|
9685
9759
|
loadedIndexes.push(info);
|
|
9686
9760
|
}
|
|
9687
9761
|
for (const info of loadedIndexes) {
|
|
9688
|
-
info.store =
|
|
9762
|
+
info.store = readIndexStoreBinary(r, info.name, intern);
|
|
9689
9763
|
const table = state.tables.get(info.tableName.toLowerCase());
|
|
9690
9764
|
if (!table) continue;
|
|
9691
9765
|
for (const entry of info.store.snapshotKeys()) {
|
|
9692
9766
|
const rowid = entry.rowids[0];
|
|
9693
9767
|
if (rowid === void 0) continue;
|
|
9694
|
-
const row = table.
|
|
9768
|
+
const row = table.get(rowid);
|
|
9695
9769
|
if (!row) continue;
|
|
9696
9770
|
info.store.rememberKeyValues(
|
|
9697
9771
|
entry.key,
|
|
@@ -9699,52 +9773,299 @@ function decodeV4(reader) {
|
|
|
9699
9773
|
);
|
|
9700
9774
|
}
|
|
9701
9775
|
}
|
|
9702
|
-
if (
|
|
9703
|
-
const runtime = { prngState:
|
|
9704
|
-
if (!
|
|
9776
|
+
if (r.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9777
|
+
const runtime = { prngState: r.u64(), nowMs: finiteNowMs(Number(r.i64())) };
|
|
9778
|
+
if (!r.done()) throw new SqliteError("snapshot has trailing data", "other");
|
|
9705
9779
|
return { state, runtime };
|
|
9706
9780
|
}
|
|
9707
|
-
function
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
for (let i = 0; i < n; i++) out[i] = null;
|
|
9712
|
-
return out;
|
|
9781
|
+
function writeTaggedValue(w, value, internId) {
|
|
9782
|
+
if (value === null) {
|
|
9783
|
+
w.u8(0);
|
|
9784
|
+
return;
|
|
9713
9785
|
}
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9786
|
+
if (value instanceof SqlReal) {
|
|
9787
|
+
w.u8(2);
|
|
9788
|
+
w.f64(value.value);
|
|
9789
|
+
return;
|
|
9790
|
+
}
|
|
9791
|
+
if (typeof value === "bigint" || typeof value === "number" && Number.isInteger(value)) {
|
|
9792
|
+
w.u8(1);
|
|
9793
|
+
w.i64(BigInt(value));
|
|
9794
|
+
return;
|
|
9795
|
+
}
|
|
9796
|
+
if (typeof value === "number") {
|
|
9797
|
+
w.u8(2);
|
|
9798
|
+
w.f64(value);
|
|
9799
|
+
return;
|
|
9800
|
+
}
|
|
9801
|
+
if (typeof value === "string") {
|
|
9802
|
+
const id = internId(value);
|
|
9803
|
+
if (id >= 0) {
|
|
9804
|
+
w.u8(3);
|
|
9805
|
+
writeVarintU32(w, id);
|
|
9806
|
+
return;
|
|
9719
9807
|
}
|
|
9720
|
-
|
|
9808
|
+
w.u8(4);
|
|
9809
|
+
w.text(value);
|
|
9810
|
+
return;
|
|
9721
9811
|
}
|
|
9722
|
-
|
|
9812
|
+
if (value instanceof SqlJsonText) {
|
|
9813
|
+
w.u8(4);
|
|
9814
|
+
w.text(value.value);
|
|
9815
|
+
return;
|
|
9816
|
+
}
|
|
9817
|
+
w.u8(5);
|
|
9818
|
+
writeVarintU32(w, value.length);
|
|
9819
|
+
w.raw(value);
|
|
9723
9820
|
}
|
|
9724
|
-
function
|
|
9725
|
-
|
|
9726
|
-
|
|
9821
|
+
function readTaggedValue(r, intern) {
|
|
9822
|
+
const tag = r.u8();
|
|
9823
|
+
if (tag === 0) return null;
|
|
9824
|
+
if (tag === 1) {
|
|
9825
|
+
const integer = r.i64();
|
|
9727
9826
|
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
9728
9827
|
}
|
|
9729
|
-
if (
|
|
9730
|
-
const value =
|
|
9828
|
+
if (tag === 2) {
|
|
9829
|
+
const value = r.f64();
|
|
9731
9830
|
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
9732
9831
|
}
|
|
9733
|
-
if (
|
|
9734
|
-
if (
|
|
9735
|
-
return
|
|
9832
|
+
if (tag === 3) return intern[readVarintU32(r)] ?? "";
|
|
9833
|
+
if (tag === 4) return r.text();
|
|
9834
|
+
return r.raw(readVarintU32(r));
|
|
9835
|
+
}
|
|
9836
|
+
function writePackedColumn(w, rows, col, internId) {
|
|
9837
|
+
const n = rows.length;
|
|
9838
|
+
if (n === 0) {
|
|
9839
|
+
w.u8(PACK_NULL);
|
|
9840
|
+
return;
|
|
9841
|
+
}
|
|
9842
|
+
const bits = new Uint8Array(n + 7 >> 3);
|
|
9843
|
+
let nulls = 0;
|
|
9844
|
+
let kind = null;
|
|
9845
|
+
let useInlineText = false;
|
|
9846
|
+
for (let i = 0; i < n; i++) {
|
|
9847
|
+
const value = rows[i].values[col] ?? null;
|
|
9848
|
+
if (value === null) {
|
|
9849
|
+
bits[i >> 3] = bits[i >> 3] | 1 << (i & 7);
|
|
9850
|
+
nulls++;
|
|
9851
|
+
continue;
|
|
9852
|
+
}
|
|
9853
|
+
const cellKind = packKindOf(value);
|
|
9854
|
+
if (kind === null) kind = cellKind;
|
|
9855
|
+
else if (kind !== cellKind) kind = PACK_TAGGED;
|
|
9856
|
+
if (cellKind === PACK_TEXT_INTERN && typeof value === "string" && internId(value) < 0) useInlineText = true;
|
|
9857
|
+
if (value instanceof SqlJsonText) kind = PACK_TAGGED;
|
|
9858
|
+
}
|
|
9859
|
+
if (nulls === n) {
|
|
9860
|
+
w.u8(PACK_NULL);
|
|
9861
|
+
return;
|
|
9862
|
+
}
|
|
9863
|
+
let pack2 = kind ?? PACK_TAGGED;
|
|
9864
|
+
if (pack2 === PACK_TEXT_INTERN && useInlineText) pack2 = PACK_TEXT_INLINE;
|
|
9865
|
+
w.u8(pack2);
|
|
9866
|
+
w.raw(bits);
|
|
9867
|
+
if (pack2 === PACK_I32) {
|
|
9868
|
+
w.align4();
|
|
9869
|
+
for (let i = 0; i < n; i++) {
|
|
9870
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9871
|
+
w.u32(rows[i].values[col]);
|
|
9872
|
+
}
|
|
9873
|
+
return;
|
|
9874
|
+
}
|
|
9875
|
+
if (pack2 === PACK_I64) {
|
|
9876
|
+
w.align4();
|
|
9877
|
+
for (let i = 0; i < n; i++) {
|
|
9878
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9879
|
+
const v = rows[i].values[col];
|
|
9880
|
+
w.i64(typeof v === "bigint" ? v : BigInt(v));
|
|
9881
|
+
}
|
|
9882
|
+
return;
|
|
9883
|
+
}
|
|
9884
|
+
if (pack2 === PACK_F64) {
|
|
9885
|
+
w.align4();
|
|
9886
|
+
for (let i = 0; i < n; i++) {
|
|
9887
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9888
|
+
const v = rows[i].values[col];
|
|
9889
|
+
w.f64(v instanceof SqlReal ? v.value : v);
|
|
9890
|
+
}
|
|
9891
|
+
return;
|
|
9892
|
+
}
|
|
9893
|
+
if (pack2 === PACK_TEXT_INTERN) {
|
|
9894
|
+
w.align4();
|
|
9895
|
+
for (let i = 0; i < n; i++) {
|
|
9896
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9897
|
+
const text2 = rows[i].values[col];
|
|
9898
|
+
w.u32(internId(text2));
|
|
9899
|
+
}
|
|
9900
|
+
return;
|
|
9901
|
+
}
|
|
9902
|
+
if (pack2 === PACK_TEXT_INLINE) {
|
|
9903
|
+
const offsets = [];
|
|
9904
|
+
let blobLen = 0;
|
|
9905
|
+
for (let i = 0; i < n; i++) {
|
|
9906
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9907
|
+
offsets.push(blobLen);
|
|
9908
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9909
|
+
blobLen += utf8Encode(text2).length;
|
|
9910
|
+
}
|
|
9911
|
+
writeVarintU32(w, offsets.length);
|
|
9912
|
+
for (const off of offsets) writeVarintU32(w, off);
|
|
9913
|
+
writeVarintU32(w, blobLen);
|
|
9914
|
+
for (let i = 0; i < n; i++) {
|
|
9915
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9916
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9917
|
+
w.textBytes(text2);
|
|
9918
|
+
}
|
|
9919
|
+
return;
|
|
9920
|
+
}
|
|
9921
|
+
if (pack2 === PACK_BLOB) {
|
|
9922
|
+
for (let i = 0; i < n; i++) {
|
|
9923
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9924
|
+
const blob = rows[i].values[col];
|
|
9925
|
+
writeVarintU32(w, blob.length);
|
|
9926
|
+
w.raw(blob);
|
|
9927
|
+
}
|
|
9928
|
+
return;
|
|
9929
|
+
}
|
|
9930
|
+
for (let i = 0; i < n; i++) {
|
|
9931
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9932
|
+
writeTaggedValue(w, rows[i].values[col], internId);
|
|
9933
|
+
}
|
|
9934
|
+
}
|
|
9935
|
+
function readPackedColumn(r, n, intern) {
|
|
9936
|
+
const pack2 = r.u8();
|
|
9937
|
+
if (pack2 === PACK_NULL) return { pack: pack2, nullBitmap: null, payload: new Uint8Array(0) };
|
|
9938
|
+
const bits = r.raw(n + 7 >> 3);
|
|
9939
|
+
const nonNull = countNonNull(bits, n);
|
|
9940
|
+
if (pack2 === PACK_I32 || pack2 === PACK_I64 || pack2 === PACK_F64 || pack2 === PACK_TEXT_INTERN) {
|
|
9941
|
+
r.skipAlign4();
|
|
9942
|
+
const width = pack2 === PACK_I32 || pack2 === PACK_TEXT_INTERN ? 4 : 8;
|
|
9943
|
+
const payload = r.raw(nonNull * width);
|
|
9944
|
+
return { pack: pack2, nullBitmap: bits, payload };
|
|
9945
|
+
}
|
|
9946
|
+
if (pack2 === PACK_TEXT_INLINE) {
|
|
9947
|
+
const count = readVarintU32(r);
|
|
9948
|
+
const offsets = new Uint32Array(count);
|
|
9949
|
+
for (let i = 0; i < count; i++) offsets[i] = readVarintU32(r);
|
|
9950
|
+
const total = readVarintU32(r);
|
|
9951
|
+
const payload = r.raw(total);
|
|
9952
|
+
return { pack: pack2, nullBitmap: bits, payload, inlineOffsets: offsets };
|
|
9953
|
+
}
|
|
9954
|
+
if (pack2 === PACK_BLOB) {
|
|
9955
|
+
const chunks = [];
|
|
9956
|
+
for (let i = 0; i < n; i++) {
|
|
9957
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9958
|
+
const len = readVarintU32(r);
|
|
9959
|
+
chunks.push(r.raw(len));
|
|
9960
|
+
}
|
|
9961
|
+
return { pack: pack2, nullBitmap: bits, payload: new Uint8Array(0), blobChunks: chunks };
|
|
9962
|
+
}
|
|
9963
|
+
const tagged = [];
|
|
9964
|
+
for (let i = 0; i < n; i++) {
|
|
9965
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9966
|
+
tagged.push(readTaggedValue(r, intern));
|
|
9967
|
+
}
|
|
9968
|
+
return { pack: PACK_TAGGED, nullBitmap: bits, payload: new Uint8Array(0), tagged };
|
|
9736
9969
|
}
|
|
9737
|
-
function
|
|
9738
|
-
|
|
9970
|
+
function countNonNull(bits, n) {
|
|
9971
|
+
let c = 0;
|
|
9972
|
+
for (let i = 0; i < n; i++) if ((bits[i >> 3] & 1 << (i & 7)) === 0) c++;
|
|
9973
|
+
return c;
|
|
9974
|
+
}
|
|
9975
|
+
function writeIndexStoreBinary(w, store, internId) {
|
|
9976
|
+
const entries = store.snapshotKeys();
|
|
9977
|
+
writeVarintU32(w, entries.length);
|
|
9978
|
+
for (const entry of entries) {
|
|
9979
|
+
const values = store.keyValuesFor(entry.key);
|
|
9980
|
+
writeVarintU32(w, values.length);
|
|
9981
|
+
for (const v of values) writeTaggedValue(w, v, internId);
|
|
9982
|
+
writeVarintU32(w, entry.rowids.length);
|
|
9983
|
+
for (const id of entry.rowids) writeTaggedValue(w, id, internId);
|
|
9984
|
+
}
|
|
9985
|
+
}
|
|
9986
|
+
function readIndexStoreBinary(r, name, intern) {
|
|
9987
|
+
const count = readVarintU32(r);
|
|
9739
9988
|
const entries = /* @__PURE__ */ new Map();
|
|
9989
|
+
const keyValues = /* @__PURE__ */ new Map();
|
|
9740
9990
|
for (let i = 0; i < count; i++) {
|
|
9741
|
-
const
|
|
9742
|
-
const
|
|
9991
|
+
const valueCount = readVarintU32(r);
|
|
9992
|
+
const values = [];
|
|
9993
|
+
for (let v = 0; v < valueCount; v++) values.push(readTaggedValue(r, intern));
|
|
9994
|
+
const key = serializeIndexEntry(values);
|
|
9995
|
+
const rowidCount = readVarintU32(r);
|
|
9743
9996
|
const rowids = [];
|
|
9744
|
-
for (let
|
|
9997
|
+
for (let ri = 0; ri < rowidCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9745
9998
|
entries.set(key, rowids);
|
|
9999
|
+
keyValues.set(key, values);
|
|
10000
|
+
}
|
|
10001
|
+
return new IndexStore(name, entries, keyValues);
|
|
10002
|
+
}
|
|
10003
|
+
function asRowid2(value) {
|
|
10004
|
+
if (typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint") return value;
|
|
10005
|
+
throw new SqliteError("invalid rowid in snapshot", "other");
|
|
10006
|
+
}
|
|
10007
|
+
function compareNames(a, b) {
|
|
10008
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
10009
|
+
}
|
|
10010
|
+
function finiteNowMs(value) {
|
|
10011
|
+
if (!Number.isFinite(value)) return 0;
|
|
10012
|
+
const max = 864e13;
|
|
10013
|
+
if (value > max) return max;
|
|
10014
|
+
if (value < -max) return -max;
|
|
10015
|
+
return value;
|
|
10016
|
+
}
|
|
10017
|
+
function sortedValues(map) {
|
|
10018
|
+
return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
|
|
10019
|
+
}
|
|
10020
|
+
function forceSchemaIntern(pool, tables, views, indexes) {
|
|
10021
|
+
for (const table of tables) {
|
|
10022
|
+
pool.forceId(table.name);
|
|
10023
|
+
pool.forceId(table.originalSql ?? "");
|
|
10024
|
+
for (const column of table.columns) {
|
|
10025
|
+
pool.forceId(column.name);
|
|
10026
|
+
pool.forceId(column.typeName ?? "");
|
|
10027
|
+
pool.forceId(column.collate ?? "");
|
|
10028
|
+
}
|
|
10029
|
+
for (const name of table.indexes) pool.forceId(name);
|
|
10030
|
+
forceBjvStrings(pool, table.constraints);
|
|
10031
|
+
for (const column of table.columns) {
|
|
10032
|
+
if (column.defaultExpr) forceBjvStrings(pool, column.defaultExpr);
|
|
10033
|
+
if (column.generated) forceBjvStrings(pool, column.generated);
|
|
10034
|
+
}
|
|
10035
|
+
}
|
|
10036
|
+
for (const view of views) forceBjvStrings(pool, view);
|
|
10037
|
+
for (const index of indexes) {
|
|
10038
|
+
pool.forceId(index.name);
|
|
10039
|
+
pool.forceId(index.tableName);
|
|
10040
|
+
pool.forceId(index.originalSql ?? "");
|
|
10041
|
+
forceBjvStrings(pool, {
|
|
10042
|
+
name: index.name,
|
|
10043
|
+
tableName: index.tableName,
|
|
10044
|
+
unique: index.unique,
|
|
10045
|
+
columns: index.columns,
|
|
10046
|
+
where: index.where,
|
|
10047
|
+
originalSql: index.originalSql
|
|
10048
|
+
});
|
|
10049
|
+
}
|
|
10050
|
+
}
|
|
10051
|
+
function forceBjvStrings(pool, value) {
|
|
10052
|
+
if (value === null || value === void 0) return;
|
|
10053
|
+
if (typeof value === "string") {
|
|
10054
|
+
pool.forceId(value);
|
|
10055
|
+
return;
|
|
10056
|
+
}
|
|
10057
|
+
if (typeof value === "bigint" || typeof value === "boolean" || typeof value === "number") return;
|
|
10058
|
+
if (value instanceof Uint8Array) return;
|
|
10059
|
+
if (Array.isArray(value)) {
|
|
10060
|
+
for (const item of value) forceBjvStrings(pool, item);
|
|
10061
|
+
return;
|
|
10062
|
+
}
|
|
10063
|
+
if (typeof value === "object") {
|
|
10064
|
+
for (const [k, v] of Object.entries(value)) {
|
|
10065
|
+
pool.forceId(k);
|
|
10066
|
+
forceBjvStrings(pool, v);
|
|
10067
|
+
}
|
|
9746
10068
|
}
|
|
9747
|
-
return new IndexStore(name, entries);
|
|
9748
10069
|
}
|
|
9749
10070
|
|
|
9750
10071
|
// src/api/snapshot.ts
|
|
@@ -11098,7 +11419,7 @@ function lookupTableRows(from, where, env) {
|
|
|
11098
11419
|
const row = table.get(rowid);
|
|
11099
11420
|
if (row) rows.push(row);
|
|
11100
11421
|
}
|
|
11101
|
-
rows.sort((a, b) =>
|
|
11422
|
+
rows.sort((a, b) => compareRowids2(a.rowid, b.rowid));
|
|
11102
11423
|
return { table, alias, rows, coveredColumns: new Set(best.columns) };
|
|
11103
11424
|
}
|
|
11104
11425
|
for (const eq of resolved) {
|
|
@@ -11106,7 +11427,7 @@ function lookupTableRows(from, where, env) {
|
|
|
11106
11427
|
if (isRowidName(eq.column)) continue;
|
|
11107
11428
|
const hashed = table.lookupEquality(col, eq.value);
|
|
11108
11429
|
if (!hashed) continue;
|
|
11109
|
-
hashed.sort((a, b) =>
|
|
11430
|
+
hashed.sort((a, b) => compareRowids2(a.rowid, b.rowid));
|
|
11110
11431
|
return { table, alias, rows: hashed, coveredColumns: /* @__PURE__ */ new Set([col]) };
|
|
11111
11432
|
}
|
|
11112
11433
|
const range = rangeAgainstConst(where) ?? rangeFromBetween(where);
|
|
@@ -11188,7 +11509,7 @@ function considerIndexLookup(best, candidate) {
|
|
|
11188
11509
|
if (!best || candidate.prefixLen > best.prefixLen) return { best: candidate, stop: false };
|
|
11189
11510
|
return { best, stop: false };
|
|
11190
11511
|
}
|
|
11191
|
-
function
|
|
11512
|
+
function compareRowids2(left, right) {
|
|
11192
11513
|
const a = typeof left === "bigint" ? left : BigInt(left);
|
|
11193
11514
|
const b = typeof right === "bigint" ? right : BigInt(right);
|
|
11194
11515
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
@@ -11290,7 +11611,7 @@ function tryJoinProbe(right, on, env) {
|
|
|
11290
11611
|
const row = table.get(rowid);
|
|
11291
11612
|
if (row) rows.push(row);
|
|
11292
11613
|
}
|
|
11293
|
-
rows.sort((a, b) =>
|
|
11614
|
+
rows.sort((a, b) => compareRowids2(a.rowid, b.rowid));
|
|
11294
11615
|
return rows;
|
|
11295
11616
|
}
|
|
11296
11617
|
};
|