@crvouga/sqlite-mem 1.10.0 → 1.12.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 +4180 -3869
- 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 +58 -0
- package/dist/storage/table.d.ts +13 -0
- package/dist/unstable.js +842 -547
- 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
|
}
|
|
@@ -6033,60 +6037,141 @@ function sameRowid(left, right) {
|
|
|
6033
6037
|
return typeof left === "bigint" || typeof right === "bigint" ? BigInt(left) === BigInt(right) : left === right;
|
|
6034
6038
|
}
|
|
6035
6039
|
|
|
6036
|
-
// src/storage/
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
|
|
6041
|
-
|
|
6042
|
-
|
|
6043
|
-
|
|
6044
|
-
|
|
6040
|
+
// src/storage/columnar-slab.ts
|
|
6041
|
+
var PACK_NULL = 0;
|
|
6042
|
+
var PACK_I32 = 1;
|
|
6043
|
+
var PACK_I64 = 2;
|
|
6044
|
+
var PACK_F64 = 3;
|
|
6045
|
+
var PACK_TEXT_INTERN = 4;
|
|
6046
|
+
var PACK_TEXT_INLINE = 5;
|
|
6047
|
+
var PACK_BLOB = 6;
|
|
6048
|
+
var PACK_TAGGED = 7;
|
|
6049
|
+
function prepareSlabColumn(column, rowCount, nonNull) {
|
|
6050
|
+
if (column.payload.length > 0) {
|
|
6051
|
+
column.view = new DataView(column.payload.buffer, column.payload.byteOffset, column.payload.byteLength);
|
|
6052
|
+
}
|
|
6053
|
+
if (!column.nullBitmap || nonNull === rowCount) {
|
|
6054
|
+
column.nullBitmap = null;
|
|
6055
|
+
column.nonNullRank = void 0;
|
|
6056
|
+
return column;
|
|
6045
6057
|
}
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
function cloneRow(row) {
|
|
6049
|
-
const values = new Array(row.values.length);
|
|
6050
|
-
for (let i = 0; i < row.values.length; i++) values[i] = cloneSqlValue(row.values[i]);
|
|
6051
|
-
return { rowid: row.rowid, values };
|
|
6052
|
-
}
|
|
6053
|
-
function isValueArray(values) {
|
|
6054
|
-
return Array.isArray(values);
|
|
6058
|
+
column.nonNullRank = buildNonNullRank(column.nullBitmap, rowCount);
|
|
6059
|
+
return column;
|
|
6055
6060
|
}
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
});
|
|
6063
|
-
}
|
|
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);
|
|
6061
|
+
function buildNonNullRank(bits, n) {
|
|
6062
|
+
const rank = new Uint32Array(n);
|
|
6063
|
+
let k = 0;
|
|
6064
|
+
for (let i = 0; i < n; i++) {
|
|
6065
|
+
rank[i] = k;
|
|
6066
|
+
if ((bits[i >> 3] & 1 << (i & 7)) === 0) k++;
|
|
6070
6067
|
}
|
|
6068
|
+
return rank;
|
|
6071
6069
|
}
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6070
|
+
var ColumnarSlab = class {
|
|
6071
|
+
buffer;
|
|
6072
|
+
rowCount;
|
|
6073
|
+
rowids;
|
|
6074
|
+
columns;
|
|
6075
|
+
intern;
|
|
6076
|
+
rowidIndex = null;
|
|
6077
|
+
constructor(buffer, rowCount, rowids, columns, intern) {
|
|
6078
|
+
this.buffer = buffer;
|
|
6079
|
+
this.rowCount = rowCount;
|
|
6080
|
+
this.rowids = rowids;
|
|
6081
|
+
this.columns = columns;
|
|
6082
|
+
this.intern = intern;
|
|
6083
|
+
}
|
|
6084
|
+
rowIndex(rowid) {
|
|
6085
|
+
this.rowidIndex ??= new Map(this.rowids.map((id, i) => [canonicalRowid(id), i]));
|
|
6086
|
+
const hit = this.rowidIndex.get(canonicalRowid(rowid));
|
|
6087
|
+
if (hit === void 0) return -1;
|
|
6088
|
+
return hit;
|
|
6089
|
+
}
|
|
6090
|
+
cell(rowIndex, col) {
|
|
6091
|
+
if (rowIndex < 0 || rowIndex >= this.rowCount) return null;
|
|
6092
|
+
const column = this.columns[col];
|
|
6093
|
+
if (!column) return null;
|
|
6094
|
+
if (column.nullBitmap && isNull(column.nullBitmap, rowIndex)) return null;
|
|
6095
|
+
return readSlabCell(column, rowIndex, this.intern);
|
|
6096
|
+
}
|
|
6097
|
+
rowAt(rowIndex) {
|
|
6098
|
+
const values = new Array(this.columns.length);
|
|
6099
|
+
for (let c = 0; c < this.columns.length; c++) values[c] = this.cell(rowIndex, c);
|
|
6100
|
+
return { rowid: this.rowids[rowIndex], values };
|
|
6101
|
+
}
|
|
6102
|
+
get(rowid) {
|
|
6103
|
+
const i = this.rowIndex(rowid);
|
|
6104
|
+
if (i < 0) return void 0;
|
|
6105
|
+
return this.rowAt(i);
|
|
6106
|
+
}
|
|
6107
|
+
*scan() {
|
|
6108
|
+
for (let i = 0; i < this.rowCount; i++) yield this.rowAt(i);
|
|
6109
|
+
}
|
|
6110
|
+
materialize() {
|
|
6111
|
+
const map = /* @__PURE__ */ new Map();
|
|
6112
|
+
for (let i = 0; i < this.rowCount; i++) {
|
|
6113
|
+
const row = this.rowAt(i);
|
|
6114
|
+
map.set(row.rowid, row);
|
|
6088
6115
|
}
|
|
6089
|
-
|
|
6116
|
+
return map;
|
|
6117
|
+
}
|
|
6118
|
+
};
|
|
6119
|
+
function canonicalRowid(rowid) {
|
|
6120
|
+
return typeof rowid === "bigint" ? rowid : rowid;
|
|
6121
|
+
}
|
|
6122
|
+
function isNull(bits, i) {
|
|
6123
|
+
return (bits[i >> 3] & 1 << (i & 7)) !== 0;
|
|
6124
|
+
}
|
|
6125
|
+
function nonNullRowIndex(column, rowIndex) {
|
|
6126
|
+
if (!column.nullBitmap) return rowIndex;
|
|
6127
|
+
return column.nonNullRank?.[rowIndex] ?? rowIndex;
|
|
6128
|
+
}
|
|
6129
|
+
function readSlabCell(column, rowIndex, intern) {
|
|
6130
|
+
const pack = column.pack;
|
|
6131
|
+
if (pack === PACK_NULL) return null;
|
|
6132
|
+
const nonNullIndex = nonNullRowIndex(column, rowIndex);
|
|
6133
|
+
const view = column.view;
|
|
6134
|
+
if (pack === PACK_I32) {
|
|
6135
|
+
return view.getInt32(nonNullIndex * 4, true);
|
|
6136
|
+
}
|
|
6137
|
+
if (pack === PACK_I64) {
|
|
6138
|
+
const integer = view.getBigInt64(nonNullIndex * 8, true);
|
|
6139
|
+
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
6140
|
+
}
|
|
6141
|
+
if (pack === PACK_F64) {
|
|
6142
|
+
const value = view.getFloat64(nonNullIndex * 8, true);
|
|
6143
|
+
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
6144
|
+
}
|
|
6145
|
+
if (pack === PACK_TEXT_INTERN) {
|
|
6146
|
+
const id = view.getUint32(nonNullIndex * 4, true);
|
|
6147
|
+
return intern[id] ?? "";
|
|
6148
|
+
}
|
|
6149
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
6150
|
+
const offsets = column.inlineOffsets;
|
|
6151
|
+
const start = offsets[nonNullIndex];
|
|
6152
|
+
const end = nonNullIndex + 1 < offsets.length ? offsets[nonNullIndex + 1] : column.payload.length;
|
|
6153
|
+
return utf8Decode(column.payload.subarray(start, end));
|
|
6154
|
+
}
|
|
6155
|
+
if (pack === PACK_BLOB) {
|
|
6156
|
+
const blob = column.blobChunks[nonNullIndex];
|
|
6157
|
+
return blob;
|
|
6158
|
+
}
|
|
6159
|
+
if (pack === PACK_TAGGED) {
|
|
6160
|
+
return column.tagged[nonNullIndex] ?? null;
|
|
6161
|
+
}
|
|
6162
|
+
return null;
|
|
6163
|
+
}
|
|
6164
|
+
function packKindOf(value) {
|
|
6165
|
+
if (value instanceof SqlReal) return PACK_F64;
|
|
6166
|
+
if (typeof value === "bigint") return PACK_I64;
|
|
6167
|
+
if (typeof value === "number" && Number.isInteger(value)) {
|
|
6168
|
+
return value >= -2147483648 && value <= 2147483647 ? PACK_I32 : PACK_I64;
|
|
6169
|
+
}
|
|
6170
|
+
if (typeof value === "number") return PACK_F64;
|
|
6171
|
+
if (value instanceof SqlJsonText) return PACK_TAGGED;
|
|
6172
|
+
if (typeof value === "string") return PACK_TEXT_INTERN;
|
|
6173
|
+
if (value instanceof Uint8Array) return PACK_BLOB;
|
|
6174
|
+
return PACK_TAGGED;
|
|
6090
6175
|
}
|
|
6091
6176
|
|
|
6092
6177
|
// src/types/strict.ts
|
|
@@ -7695,6 +7780,27 @@ var FtsVocabVirtualTable = class _FtsVocabVirtualTable {
|
|
|
7695
7780
|
}
|
|
7696
7781
|
};
|
|
7697
7782
|
|
|
7783
|
+
// src/storage/row.ts
|
|
7784
|
+
function normalizeColumnName(name) {
|
|
7785
|
+
return name.toLowerCase();
|
|
7786
|
+
}
|
|
7787
|
+
function rowValues(values) {
|
|
7788
|
+
const result = /* @__PURE__ */ new Map();
|
|
7789
|
+
const entries = values instanceof Map ? values.entries() : Object.entries(values);
|
|
7790
|
+
for (const [name, value] of entries) {
|
|
7791
|
+
result.set(normalizeColumnName(name), value);
|
|
7792
|
+
}
|
|
7793
|
+
return result;
|
|
7794
|
+
}
|
|
7795
|
+
function cloneRow(row) {
|
|
7796
|
+
const values = new Array(row.values.length);
|
|
7797
|
+
for (let i = 0; i < row.values.length; i++) values[i] = cloneSqlValue(row.values[i]);
|
|
7798
|
+
return { rowid: row.rowid, values };
|
|
7799
|
+
}
|
|
7800
|
+
function isValueArray(values) {
|
|
7801
|
+
return Array.isArray(values);
|
|
7802
|
+
}
|
|
7803
|
+
|
|
7698
7804
|
// src/storage/table.ts
|
|
7699
7805
|
var EQUALITY_HASH_MIN_ROWS = 16;
|
|
7700
7806
|
var Table = class _Table {
|
|
@@ -7709,6 +7815,8 @@ var Table = class _Table {
|
|
|
7709
7815
|
strict;
|
|
7710
7816
|
/** Clustered PK key string → row for WITHOUT ROWID tables. */
|
|
7711
7817
|
clusteredRows;
|
|
7818
|
+
/** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
|
|
7819
|
+
slab = null;
|
|
7712
7820
|
scanCache = null;
|
|
7713
7821
|
/** Lazy covering hashes: column nameLower → serializeIndexKey → rowids. */
|
|
7714
7822
|
equalityHashes = null;
|
|
@@ -7772,12 +7880,49 @@ var Table = class _Table {
|
|
|
7772
7880
|
return this.integerPrimaryKeyAlias();
|
|
7773
7881
|
}
|
|
7774
7882
|
get(rowid) {
|
|
7883
|
+
if (this.slab) {
|
|
7884
|
+
const hit = this.slab.get(rowid);
|
|
7885
|
+
return hit ?? void 0;
|
|
7886
|
+
}
|
|
7775
7887
|
try {
|
|
7776
|
-
return this.rows.get(
|
|
7888
|
+
return this.rows.get(canonicalRowid2(rowid));
|
|
7777
7889
|
} catch {
|
|
7778
7890
|
return void 0;
|
|
7779
7891
|
}
|
|
7780
7892
|
}
|
|
7893
|
+
/** Row count (slab-backed or map-backed). */
|
|
7894
|
+
rowCount() {
|
|
7895
|
+
return this.slab ? this.slab.rowCount : this.rows.size;
|
|
7896
|
+
}
|
|
7897
|
+
/** Rows sorted by rowid for snapshot encode. */
|
|
7898
|
+
sortedRows() {
|
|
7899
|
+
if (this.slab) return [...this.slab.scan()].map((r) => ({ rowid: r.rowid, values: [...r.values] }));
|
|
7900
|
+
return [...this.rows.values()].sort((a, b) => compareRowids(a.rowid, b.rowid));
|
|
7901
|
+
}
|
|
7902
|
+
/** Attach decoded columnar slab (hydrate path). */
|
|
7903
|
+
attachSlab(slab) {
|
|
7904
|
+
this.slab = slab;
|
|
7905
|
+
this.invalidateScan();
|
|
7906
|
+
}
|
|
7907
|
+
/** Materialize slab into `rows` Map for mutation. */
|
|
7908
|
+
materializeSlab() {
|
|
7909
|
+
if (!this.slab) return;
|
|
7910
|
+
for (const row of this.slab.scan()) this.rows.set(row.rowid, { rowid: row.rowid, values: [...row.values] });
|
|
7911
|
+
this.slab = null;
|
|
7912
|
+
this.invalidateScan();
|
|
7913
|
+
}
|
|
7914
|
+
hasRow(rowid) {
|
|
7915
|
+
if (this.slab) return this.slab.get(rowid) !== void 0;
|
|
7916
|
+
try {
|
|
7917
|
+
return this.rows.has(canonicalRowid2(rowid));
|
|
7918
|
+
} catch {
|
|
7919
|
+
return false;
|
|
7920
|
+
}
|
|
7921
|
+
}
|
|
7922
|
+
allRowids() {
|
|
7923
|
+
if (this.slab) return this.slab.rowids;
|
|
7924
|
+
return this.rows.keys();
|
|
7925
|
+
}
|
|
7781
7926
|
getByKey(value) {
|
|
7782
7927
|
if (value === null || this.withoutRowid) return void 0;
|
|
7783
7928
|
try {
|
|
@@ -7821,20 +7966,21 @@ var Table = class _Table {
|
|
|
7821
7966
|
if (!rowids || rowids.length === 0) return [];
|
|
7822
7967
|
const rows = [];
|
|
7823
7968
|
for (const rowid of rowids) {
|
|
7824
|
-
const row = this.
|
|
7969
|
+
const row = this.get(rowid);
|
|
7825
7970
|
if (row) rows.push(row);
|
|
7826
7971
|
}
|
|
7827
7972
|
return rows;
|
|
7828
7973
|
}
|
|
7829
7974
|
ensureEqualityHash(columnLower) {
|
|
7830
|
-
if (this.frozen || this.
|
|
7975
|
+
if (this.frozen || this.rowCount() < EQUALITY_HASH_MIN_ROWS) return false;
|
|
7831
7976
|
const column = this.columns.find((item) => item.nameLower === columnLower);
|
|
7832
7977
|
if (!column) return false;
|
|
7833
7978
|
this.equalityHashes ??= /* @__PURE__ */ new Map();
|
|
7834
7979
|
if (this.equalityHashes.has(columnLower)) return true;
|
|
7835
7980
|
const map = /* @__PURE__ */ new Map();
|
|
7836
7981
|
const collate = column.collate ?? "BINARY";
|
|
7837
|
-
|
|
7982
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
7983
|
+
for (const row of iter) {
|
|
7838
7984
|
const key = serializeIndexKey([normalizeForCollation(this.cell(row, columnLower), collate)]);
|
|
7839
7985
|
if (key === null) continue;
|
|
7840
7986
|
const bucket = map.get(key);
|
|
@@ -7880,7 +8026,7 @@ var Table = class _Table {
|
|
|
7880
8026
|
if (supplied.rowid !== void 0) {
|
|
7881
8027
|
throw new SqliteError(`table ${this.name} has no column named rowid`, "other");
|
|
7882
8028
|
}
|
|
7883
|
-
const rowid2 =
|
|
8029
|
+
const rowid2 = canonicalRowid2(this.allocateRowid());
|
|
7884
8030
|
const candidate2 = { rowid: rowid2, values };
|
|
7885
8031
|
if (!options?.skipValidate) this.validate(candidate2);
|
|
7886
8032
|
const clusterKey = this.makeClusterKey(values);
|
|
@@ -7899,8 +8045,8 @@ var Table = class _Table {
|
|
|
7899
8045
|
const value = this.cell({ rowid: 0, values }, normalizeColumnName(alias.name));
|
|
7900
8046
|
if (rowid === void 0 && value !== null) rowid = asRowid(value, alias.name);
|
|
7901
8047
|
}
|
|
7902
|
-
rowid =
|
|
7903
|
-
if (this.
|
|
8048
|
+
rowid = canonicalRowid2(rowid ?? this.allocateRowid());
|
|
8049
|
+
if (this.hasRow(rowid)) {
|
|
7904
8050
|
throw new SqliteError(
|
|
7905
8051
|
`UNIQUE constraint failed: ${this.name}.rowid`,
|
|
7906
8052
|
"constraint_primary",
|
|
@@ -7917,7 +8063,7 @@ var Table = class _Table {
|
|
|
7917
8063
|
}
|
|
7918
8064
|
update(rowid, updates) {
|
|
7919
8065
|
this.assertMutable();
|
|
7920
|
-
const key =
|
|
8066
|
+
const key = canonicalRowid2(rowid);
|
|
7921
8067
|
const existing = this.rows.get(key);
|
|
7922
8068
|
if (!existing) return void 0;
|
|
7923
8069
|
const values = existing.values.slice();
|
|
@@ -7952,7 +8098,7 @@ var Table = class _Table {
|
|
|
7952
8098
|
const alias = this.integerPrimaryKeyAlias();
|
|
7953
8099
|
const aliasRow = { rowid: key, values };
|
|
7954
8100
|
const targetKey = alias ? asRowid(this.cell(aliasRow, normalizeColumnName(alias.name)), alias.name) : key;
|
|
7955
|
-
if (targetKey !== key && this.
|
|
8101
|
+
if (targetKey !== key && this.hasRow(targetKey)) {
|
|
7956
8102
|
throw new SqliteError(
|
|
7957
8103
|
`UNIQUE constraint failed: ${this.name}.${alias?.name ?? "rowid"}`,
|
|
7958
8104
|
"constraint_unique",
|
|
@@ -7975,7 +8121,7 @@ var Table = class _Table {
|
|
|
7975
8121
|
}
|
|
7976
8122
|
delete(rowid) {
|
|
7977
8123
|
this.assertMutable();
|
|
7978
|
-
const key =
|
|
8124
|
+
const key = canonicalRowid2(rowid);
|
|
7979
8125
|
const existing = this.rows.get(key);
|
|
7980
8126
|
if (!existing) return false;
|
|
7981
8127
|
if (this.withoutRowid) this.clusteredRows.delete(this.makeClusterKey(existing.values));
|
|
@@ -7987,6 +8133,10 @@ var Table = class _Table {
|
|
|
7987
8133
|
return this.rows.delete(key);
|
|
7988
8134
|
}
|
|
7989
8135
|
*scan() {
|
|
8136
|
+
if (this.slab) {
|
|
8137
|
+
yield* this.slab.scan();
|
|
8138
|
+
return;
|
|
8139
|
+
}
|
|
7990
8140
|
if (!this.scanCache) {
|
|
7991
8141
|
if (this.withoutRowid) {
|
|
7992
8142
|
this.scanCache = [...this.clusteredRows.values()].sort((a, b) => this.comparePrimaryKeys(a, b));
|
|
@@ -8006,7 +8156,16 @@ var Table = class _Table {
|
|
|
8006
8156
|
});
|
|
8007
8157
|
copy.nextRowid = this.nextRowid;
|
|
8008
8158
|
copy.maximumRowid = this.maximumRowid;
|
|
8009
|
-
|
|
8159
|
+
if (this.slab) {
|
|
8160
|
+
let max = null;
|
|
8161
|
+
for (const row of this.slab.scan()) {
|
|
8162
|
+
copy.rows.set(row.rowid, cloneRow(row));
|
|
8163
|
+
if (max === null || compareRowids(row.rowid, max) > 0) max = row.rowid;
|
|
8164
|
+
}
|
|
8165
|
+
copy.maximumRowid = max ?? void 0;
|
|
8166
|
+
} else {
|
|
8167
|
+
for (const [rowid, row] of this.rows) copy.rows.set(rowid, cloneRow(row));
|
|
8168
|
+
}
|
|
8010
8169
|
for (const [clusterKey, row] of this.clusteredRows) copy.clusteredRows.set(clusterKey, cloneRow(row));
|
|
8011
8170
|
return copy;
|
|
8012
8171
|
}
|
|
@@ -8015,13 +8174,15 @@ var Table = class _Table {
|
|
|
8015
8174
|
}
|
|
8016
8175
|
assertMutable() {
|
|
8017
8176
|
if (this.frozen) throw new SqliteError("internal: cannot mutate a frozen table", "other");
|
|
8177
|
+
if (this.slab) this.materializeSlab();
|
|
8018
8178
|
}
|
|
8019
8179
|
/** Rebuild clustered storage after snapshot decode or bulk load. */
|
|
8020
8180
|
rebuildClusteredRows() {
|
|
8021
8181
|
this.maximumRowid = void 0;
|
|
8022
8182
|
if (!this.withoutRowid) return;
|
|
8023
8183
|
this.clusteredRows.clear();
|
|
8024
|
-
|
|
8184
|
+
const iter = this.slab ? this.slab.scan() : this.rows.values();
|
|
8185
|
+
for (const row of iter) {
|
|
8025
8186
|
this.clusteredRows.set(this.makeClusterKey(row.values), row);
|
|
8026
8187
|
}
|
|
8027
8188
|
this.invalidateScan();
|
|
@@ -8145,15 +8306,19 @@ var Table = class _Table {
|
|
|
8145
8306
|
if (!this.columns.some((column) => column.autoincrement)) {
|
|
8146
8307
|
if (this.maximumRowid === void 0) {
|
|
8147
8308
|
this.maximumRowid = null;
|
|
8148
|
-
for (const rowid of this.
|
|
8309
|
+
for (const rowid of this.allRowids()) {
|
|
8310
|
+
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
8311
|
+
}
|
|
8312
|
+
} else if (this.maximumRowid === null && this.rowCount() > 0) {
|
|
8313
|
+
for (const rowid of this.allRowids()) {
|
|
8149
8314
|
if (this.maximumRowid === null || compareRowids(rowid, this.maximumRowid) > 0) this.maximumRowid = rowid;
|
|
8150
8315
|
}
|
|
8151
8316
|
}
|
|
8152
8317
|
return this.maximumRowid === null ? 1 : incrementRowid(this.maximumRowid);
|
|
8153
8318
|
}
|
|
8154
8319
|
const maxSigned = 9223372036854775807n;
|
|
8155
|
-
let candidate =
|
|
8156
|
-
while (this.
|
|
8320
|
+
let candidate = canonicalRowid2(this.nextRowid);
|
|
8321
|
+
while (this.hasRow(candidate)) {
|
|
8157
8322
|
if (BigInt(candidate) >= maxSigned) {
|
|
8158
8323
|
throw new SqliteError("database or disk is full", "other", "SQLITE_FULL");
|
|
8159
8324
|
}
|
|
@@ -8193,7 +8358,7 @@ function namedFromArray(table, values) {
|
|
|
8193
8358
|
return named;
|
|
8194
8359
|
}
|
|
8195
8360
|
function asRowid(value, column) {
|
|
8196
|
-
if (typeof value === "bigint") return
|
|
8361
|
+
if (typeof value === "bigint") return canonicalRowid2(value);
|
|
8197
8362
|
if (typeof value === "number" && Number.isSafeInteger(value)) return value;
|
|
8198
8363
|
throw new SqliteError(
|
|
8199
8364
|
`datatype mismatch for INTEGER PRIMARY KEY column: ${column}`,
|
|
@@ -8201,7 +8366,7 @@ function asRowid(value, column) {
|
|
|
8201
8366
|
"SQLITE_MISMATCH"
|
|
8202
8367
|
);
|
|
8203
8368
|
}
|
|
8204
|
-
function
|
|
8369
|
+
function canonicalRowid2(value) {
|
|
8205
8370
|
if (typeof value === "number") {
|
|
8206
8371
|
if (!Number.isSafeInteger(value))
|
|
8207
8372
|
throw new SqliteError("rowid must be a safe integer or bigint", "datatype_mismatch", "SQLITE_MISMATCH");
|
|
@@ -8798,24 +8963,53 @@ function keyOf(name) {
|
|
|
8798
8963
|
return name.toLowerCase();
|
|
8799
8964
|
}
|
|
8800
8965
|
|
|
8801
|
-
// src/serialization/
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8966
|
+
// src/serialization/wire.ts
|
|
8967
|
+
function writeVarintU32(w, value) {
|
|
8968
|
+
let v = value >>> 0;
|
|
8969
|
+
while (v >= 128) {
|
|
8970
|
+
w.u8(v & 127 | 128);
|
|
8971
|
+
v >>>= 7;
|
|
8972
|
+
}
|
|
8973
|
+
w.u8(v);
|
|
8974
|
+
}
|
|
8975
|
+
function readVarintU32(r) {
|
|
8976
|
+
let result = 0;
|
|
8977
|
+
let shift = 0;
|
|
8978
|
+
for (; ; ) {
|
|
8979
|
+
const byte = r.u8();
|
|
8980
|
+
result |= (byte & 127) << shift;
|
|
8981
|
+
if ((byte & 128) === 0) return result >>> 0;
|
|
8982
|
+
shift += 7;
|
|
8983
|
+
if (shift > 28) r.fail();
|
|
8984
|
+
}
|
|
8985
|
+
}
|
|
8807
8986
|
var Writer = class {
|
|
8808
|
-
buf
|
|
8809
|
-
view
|
|
8987
|
+
buf;
|
|
8988
|
+
view;
|
|
8810
8989
|
len = 0;
|
|
8990
|
+
constructor(capacity = 4096) {
|
|
8991
|
+
this.buf = new Uint8Array(capacity);
|
|
8992
|
+
this.view = new DataView(this.buf.buffer);
|
|
8993
|
+
}
|
|
8994
|
+
get position() {
|
|
8995
|
+
return this.len;
|
|
8996
|
+
}
|
|
8997
|
+
reserve(capacity) {
|
|
8998
|
+
if (capacity <= this.buf.length) return;
|
|
8999
|
+
const next = new Uint8Array(capacity);
|
|
9000
|
+
next.set(this.buf.subarray(0, this.len));
|
|
9001
|
+
this.buf = next;
|
|
9002
|
+
this.view = new DataView(next.buffer);
|
|
9003
|
+
}
|
|
8811
9004
|
ensure(needed) {
|
|
8812
9005
|
if (this.len + needed <= this.buf.length) return;
|
|
8813
9006
|
let cap = this.buf.length;
|
|
8814
9007
|
while (cap < this.len + needed) cap *= 2;
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
9008
|
+
this.reserve(cap);
|
|
9009
|
+
}
|
|
9010
|
+
align4() {
|
|
9011
|
+
const pad2 = 4 - (this.len & 3) & 3;
|
|
9012
|
+
for (let i = 0; i < pad2; i++) this.u8(0);
|
|
8819
9013
|
}
|
|
8820
9014
|
u8(value) {
|
|
8821
9015
|
this.ensure(1);
|
|
@@ -8846,52 +9040,28 @@ var Writer = class {
|
|
|
8846
9040
|
this.buf.set(value, this.len);
|
|
8847
9041
|
this.len += value.length;
|
|
8848
9042
|
}
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
this.
|
|
8852
|
-
this.raw(bytes);
|
|
9043
|
+
rawAt(offset, value) {
|
|
9044
|
+
if (offset + value.length > this.len) this.fail();
|
|
9045
|
+
this.buf.set(value, offset);
|
|
8853
9046
|
}
|
|
8854
|
-
|
|
8855
|
-
|
|
9047
|
+
/** Length-prefixed UTF-8 via encodeInto when possible. */
|
|
9048
|
+
text(value) {
|
|
9049
|
+
const encoded = utf8Encode(value);
|
|
9050
|
+
writeVarintU32(this, encoded.length);
|
|
9051
|
+
this.raw(encoded);
|
|
8856
9052
|
}
|
|
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);
|
|
9053
|
+
/** Write UTF-8 at current position without length prefix (intern blob region). */
|
|
9054
|
+
textBytes(value) {
|
|
9055
|
+
const encoded = utf8Encode(value);
|
|
9056
|
+
this.raw(encoded);
|
|
8890
9057
|
}
|
|
8891
9058
|
finish() {
|
|
8892
9059
|
if (this.len === this.buf.length) return this.buf;
|
|
8893
9060
|
return this.buf.subarray(0, this.len).slice();
|
|
8894
9061
|
}
|
|
9062
|
+
fail() {
|
|
9063
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9064
|
+
}
|
|
8895
9065
|
};
|
|
8896
9066
|
var Reader = class {
|
|
8897
9067
|
constructor(bytes) {
|
|
@@ -8901,6 +9071,13 @@ var Reader = class {
|
|
|
8901
9071
|
bytes;
|
|
8902
9072
|
offset = 0;
|
|
8903
9073
|
view;
|
|
9074
|
+
get position() {
|
|
9075
|
+
return this.offset;
|
|
9076
|
+
}
|
|
9077
|
+
skipAlign4() {
|
|
9078
|
+
const pad2 = 4 - (this.offset & 3) & 3;
|
|
9079
|
+
this.offset += pad2;
|
|
9080
|
+
}
|
|
8904
9081
|
u8() {
|
|
8905
9082
|
if (this.offset >= this.bytes.length) this.fail();
|
|
8906
9083
|
return this.bytes[this.offset++];
|
|
@@ -8935,33 +9112,9 @@ var Reader = class {
|
|
|
8935
9112
|
this.offset += length;
|
|
8936
9113
|
return value;
|
|
8937
9114
|
}
|
|
8938
|
-
owned(length) {
|
|
8939
|
-
return this.raw(length).slice();
|
|
8940
|
-
}
|
|
8941
9115
|
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();
|
|
9116
|
+
const length = readVarintU32(this);
|
|
9117
|
+
return utf8Decode(this.raw(length));
|
|
8965
9118
|
}
|
|
8966
9119
|
remaining() {
|
|
8967
9120
|
return this.bytes.length - this.offset;
|
|
@@ -8973,409 +9126,321 @@ var Reader = class {
|
|
|
8973
9126
|
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
8974
9127
|
}
|
|
8975
9128
|
};
|
|
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()));
|
|
9129
|
+
var BJV_NULL = 0;
|
|
9130
|
+
var BJV_FALSE = 1;
|
|
9131
|
+
var BJV_TRUE = 2;
|
|
9132
|
+
var BJV_I32 = 3;
|
|
9133
|
+
var BJV_I64 = 4;
|
|
9134
|
+
var BJV_F64 = 5;
|
|
9135
|
+
var BJV_INTERN = 6;
|
|
9136
|
+
var BJV_STRING = 7;
|
|
9137
|
+
var BJV_BYTES = 8;
|
|
9138
|
+
var BJV_ARRAY = 9;
|
|
9139
|
+
var BJV_OBJECT = 10;
|
|
9140
|
+
function writeBjv(w, value, forceIntern) {
|
|
9141
|
+
if (value === null || value === void 0) {
|
|
9142
|
+
w.u8(BJV_NULL);
|
|
9143
|
+
return;
|
|
9144
|
+
}
|
|
9145
|
+
if (typeof value === "boolean") {
|
|
9146
|
+
w.u8(value ? BJV_TRUE : BJV_FALSE);
|
|
9147
|
+
return;
|
|
9148
|
+
}
|
|
9149
|
+
if (typeof value === "number") {
|
|
9150
|
+
if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
|
|
9151
|
+
w.u8(BJV_I32);
|
|
9152
|
+
w.u32(value | 0);
|
|
9153
|
+
return;
|
|
9007
9154
|
}
|
|
9155
|
+
w.u8(BJV_F64);
|
|
9156
|
+
w.f64(value);
|
|
9157
|
+
return;
|
|
9008
9158
|
}
|
|
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
|
-
});
|
|
9159
|
+
if (typeof value === "bigint") {
|
|
9160
|
+
w.u8(BJV_I64);
|
|
9161
|
+
w.i64(value);
|
|
9162
|
+
return;
|
|
9023
9163
|
}
|
|
9024
|
-
if (
|
|
9025
|
-
|
|
9164
|
+
if (typeof value === "string") {
|
|
9165
|
+
w.u8(BJV_INTERN);
|
|
9166
|
+
writeVarintU32(w, forceIntern(value));
|
|
9167
|
+
return;
|
|
9026
9168
|
}
|
|
9027
|
-
if (
|
|
9028
|
-
|
|
9029
|
-
|
|
9169
|
+
if (value instanceof Uint8Array) {
|
|
9170
|
+
w.u8(BJV_BYTES);
|
|
9171
|
+
writeVarintU32(w, value.length);
|
|
9172
|
+
w.raw(value);
|
|
9173
|
+
return;
|
|
9030
9174
|
}
|
|
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");
|
|
9175
|
+
if (Array.isArray(value)) {
|
|
9176
|
+
w.u8(BJV_ARRAY);
|
|
9177
|
+
writeVarintU32(w, value.length);
|
|
9178
|
+
for (const item of value) writeBjv(w, item, forceIntern);
|
|
9179
|
+
return;
|
|
9039
9180
|
}
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9181
|
+
if (typeof value === "object") {
|
|
9182
|
+
const entries = Object.entries(value);
|
|
9183
|
+
w.u8(BJV_OBJECT);
|
|
9184
|
+
writeVarintU32(w, entries.length);
|
|
9185
|
+
for (const [k, v] of entries) {
|
|
9186
|
+
w.u8(BJV_INTERN);
|
|
9187
|
+
writeVarintU32(w, forceIntern(k));
|
|
9188
|
+
writeBjv(w, v, forceIntern);
|
|
9189
|
+
}
|
|
9190
|
+
return;
|
|
9049
9191
|
}
|
|
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
|
-
|
|
9192
|
+
w.u8(BJV_NULL);
|
|
9193
|
+
}
|
|
9194
|
+
function readBjv(r, intern) {
|
|
9195
|
+
const tag = r.u8();
|
|
9196
|
+
switch (tag) {
|
|
9197
|
+
case BJV_NULL:
|
|
9198
|
+
return null;
|
|
9199
|
+
case BJV_FALSE:
|
|
9200
|
+
return false;
|
|
9201
|
+
case BJV_TRUE:
|
|
9202
|
+
return true;
|
|
9203
|
+
case BJV_I32:
|
|
9204
|
+
return r.u32() | 0;
|
|
9205
|
+
case BJV_I64:
|
|
9206
|
+
return r.i64();
|
|
9207
|
+
case BJV_F64:
|
|
9208
|
+
return r.f64();
|
|
9209
|
+
case BJV_INTERN:
|
|
9210
|
+
return intern[readVarintU32(r)] ?? "";
|
|
9211
|
+
case BJV_STRING:
|
|
9212
|
+
return r.text();
|
|
9213
|
+
case BJV_BYTES:
|
|
9214
|
+
return r.raw(readVarintU32(r)).slice();
|
|
9215
|
+
case BJV_ARRAY: {
|
|
9216
|
+
const count = readVarintU32(r);
|
|
9217
|
+
const out = new Array(count);
|
|
9218
|
+
for (let i = 0; i < count; i++) out[i] = readBjv(r, intern);
|
|
9219
|
+
return out;
|
|
9076
9220
|
}
|
|
9077
|
-
|
|
9078
|
-
|
|
9221
|
+
case BJV_OBJECT: {
|
|
9222
|
+
const count = readVarintU32(r);
|
|
9223
|
+
const out = {};
|
|
9224
|
+
for (let i = 0; i < count; i++) {
|
|
9225
|
+
const key = readBjv(r, intern);
|
|
9226
|
+
out[key] = readBjv(r, intern);
|
|
9227
|
+
}
|
|
9228
|
+
return out;
|
|
9229
|
+
}
|
|
9230
|
+
default:
|
|
9231
|
+
return r.fail();
|
|
9079
9232
|
}
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9233
|
+
}
|
|
9234
|
+
var InternPool = class {
|
|
9235
|
+
counts = /* @__PURE__ */ new Map();
|
|
9236
|
+
ids = /* @__PURE__ */ new Map();
|
|
9237
|
+
list = [];
|
|
9238
|
+
constructor() {
|
|
9239
|
+
this.list.push("");
|
|
9240
|
+
this.ids.set("", 0);
|
|
9084
9241
|
}
|
|
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);
|
|
9242
|
+
count(s) {
|
|
9243
|
+
this.counts.set(s, (this.counts.get(s) ?? 0) + 1);
|
|
9092
9244
|
}
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9245
|
+
/** Assign ids only to strings seen ≥2 times (plus empty string). */
|
|
9246
|
+
finalize() {
|
|
9247
|
+
for (const [s, c] of this.counts) {
|
|
9248
|
+
if (c >= 2 && !this.ids.has(s)) {
|
|
9249
|
+
const id = this.list.length;
|
|
9250
|
+
this.ids.set(s, id);
|
|
9251
|
+
this.list.push(s);
|
|
9252
|
+
}
|
|
9096
9253
|
}
|
|
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
9254
|
}
|
|
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);
|
|
9255
|
+
/** Always intern (schema / catalog strings). */
|
|
9256
|
+
forceId(s) {
|
|
9257
|
+
const hit = this.ids.get(s);
|
|
9258
|
+
if (hit !== void 0) return hit;
|
|
9259
|
+
const id = this.list.length;
|
|
9260
|
+
this.ids.set(s, id);
|
|
9261
|
+
this.list.push(s);
|
|
9262
|
+
return id;
|
|
9120
9263
|
}
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9264
|
+
id(s) {
|
|
9265
|
+
const hit = this.ids.get(s);
|
|
9266
|
+
if (hit !== void 0) return hit;
|
|
9267
|
+
return -1;
|
|
9268
|
+
}
|
|
9269
|
+
has(s) {
|
|
9270
|
+
return this.ids.has(s);
|
|
9271
|
+
}
|
|
9272
|
+
};
|
|
9273
|
+
function writeInternTable(w, strings) {
|
|
9274
|
+
writeVarintU32(w, strings.length);
|
|
9275
|
+
if (strings.length === 0) return;
|
|
9276
|
+
const offsets = [];
|
|
9277
|
+
let total = 0;
|
|
9278
|
+
for (const s of strings) {
|
|
9279
|
+
offsets.push(total);
|
|
9280
|
+
total += utf8Encode(s).length;
|
|
9281
|
+
}
|
|
9282
|
+
writeVarintU32(w, total);
|
|
9283
|
+
const base = w.position + offsets.length * 4;
|
|
9284
|
+
for (const off of offsets) w.u32(base + off);
|
|
9285
|
+
for (const s of strings) w.textBytes(s);
|
|
9286
|
+
}
|
|
9287
|
+
function readInternTable(r) {
|
|
9288
|
+
const count = readVarintU32(r);
|
|
9289
|
+
if (count === 0) return [];
|
|
9290
|
+
const total = readVarintU32(r);
|
|
9291
|
+
const offsets = [];
|
|
9292
|
+
for (let i = 0; i < count; i++) offsets.push(r.u32());
|
|
9293
|
+
const blobStart = r.position;
|
|
9294
|
+
const blob = r.raw(total);
|
|
9295
|
+
const intern = new Array(count);
|
|
9126
9296
|
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);
|
|
9297
|
+
const start = offsets[i] - blobStart;
|
|
9298
|
+
const end = i + 1 < count ? offsets[i + 1] - blobStart : total;
|
|
9299
|
+
intern[i] = utf8Decode(blob.subarray(start, end));
|
|
9136
9300
|
}
|
|
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;
|
|
9301
|
+
return intern;
|
|
9178
9302
|
}
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
var
|
|
9182
|
-
var
|
|
9183
|
-
var PACK_BLOB = 4;
|
|
9184
|
-
var PACK_TAGGED = 5;
|
|
9303
|
+
|
|
9304
|
+
// src/serialization/codec.ts
|
|
9305
|
+
var MAGIC = utf8Encode("SQLM");
|
|
9306
|
+
var VERSION = 5;
|
|
9185
9307
|
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("");
|
|
9308
|
+
function encodeDatabaseState(state, runtime) {
|
|
9309
|
+
const pool = new InternPool();
|
|
9198
9310
|
const tables = sortedValues(state.tables);
|
|
9199
9311
|
const views = sortedValues(state.views);
|
|
9200
9312
|
const indexes = sortedValues(state.indexes);
|
|
9313
|
+
const tableRows = [];
|
|
9201
9314
|
for (const table of tables) {
|
|
9202
|
-
|
|
9203
|
-
|
|
9315
|
+
pool.count(table.name);
|
|
9316
|
+
pool.count(table.originalSql ?? "");
|
|
9204
9317
|
for (const column of table.columns) {
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9318
|
+
pool.count(column.name);
|
|
9319
|
+
pool.count(column.typeName ?? "");
|
|
9320
|
+
pool.count(column.collate ?? "");
|
|
9208
9321
|
}
|
|
9209
|
-
for (const name of table.indexes)
|
|
9210
|
-
|
|
9322
|
+
for (const name of table.indexes) pool.count(name);
|
|
9323
|
+
const rows = table.sortedRows();
|
|
9324
|
+
tableRows.push(rows);
|
|
9325
|
+
for (const row of rows) {
|
|
9211
9326
|
for (const value of row.values) {
|
|
9212
|
-
if (typeof value === "string")
|
|
9213
|
-
else if (value instanceof SqlJsonText)
|
|
9327
|
+
if (typeof value === "string") pool.count(value);
|
|
9328
|
+
else if (value instanceof SqlJsonText) pool.count(value.value);
|
|
9214
9329
|
}
|
|
9215
9330
|
}
|
|
9216
9331
|
}
|
|
9217
|
-
const
|
|
9332
|
+
for (const view of views) pool.count(JSON.stringify(view));
|
|
9333
|
+
for (const index of indexes) pool.count(index.name);
|
|
9334
|
+
pool.finalize();
|
|
9335
|
+
forceSchemaIntern(pool, tables, views, indexes);
|
|
9336
|
+
const internId = (s) => pool.id(s);
|
|
9337
|
+
const forceId = (s) => pool.forceId(s);
|
|
9338
|
+
const w = new Writer(64 * 1024);
|
|
9218
9339
|
w.raw(MAGIC);
|
|
9219
9340
|
w.u32(VERSION);
|
|
9220
9341
|
w.u8(state.foreignKeysEnabled ? 1 : 0);
|
|
9221
9342
|
w.u32(state.schemaVersion);
|
|
9222
9343
|
w.u32(state.changes);
|
|
9223
9344
|
w.u32(state.totalChanges);
|
|
9224
|
-
w
|
|
9225
|
-
w.
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
w
|
|
9230
|
-
w
|
|
9345
|
+
writeTaggedValue(w, state.lastInsertRowid, internId);
|
|
9346
|
+
writeInternTable(w, pool.list);
|
|
9347
|
+
writeVarintU32(w, tables.length);
|
|
9348
|
+
for (let t = 0; t < tables.length; t++) {
|
|
9349
|
+
const table = tables[t];
|
|
9350
|
+
writeVarintU32(w, forceId(table.name));
|
|
9351
|
+
writeVarintU32(w, table.columns.length);
|
|
9231
9352
|
for (const column of table.columns) {
|
|
9232
|
-
w
|
|
9233
|
-
w
|
|
9353
|
+
writeVarintU32(w, forceId(column.name));
|
|
9354
|
+
writeVarintU32(w, forceId(column.typeName ?? ""));
|
|
9234
9355
|
const aff = AFFINITIES.indexOf(column.affinity);
|
|
9235
9356
|
w.u8(aff < 0 ? 2 : aff);
|
|
9236
9357
|
w.u8(
|
|
9237
9358
|
(column.notNull ? 1 : 0) | (column.primaryKey ? 2 : 0) | (column.autoincrement ? 4 : 0) | (column.unique ? 8 : 0)
|
|
9238
9359
|
);
|
|
9239
|
-
w
|
|
9360
|
+
writeVarintU32(w, forceId(column.collate ?? ""));
|
|
9240
9361
|
if (column.defaultExpr) {
|
|
9241
9362
|
w.u8(1);
|
|
9242
|
-
w
|
|
9363
|
+
writeBjv(w, column.defaultExpr, forceId);
|
|
9243
9364
|
} else w.u8(0);
|
|
9244
9365
|
if (column.generated) {
|
|
9245
9366
|
w.u8(1);
|
|
9246
|
-
w
|
|
9367
|
+
writeBjv(w, column.generated, forceId);
|
|
9247
9368
|
} else w.u8(0);
|
|
9248
9369
|
}
|
|
9249
|
-
w
|
|
9250
|
-
w
|
|
9370
|
+
writeBjv(w, table.constraints, forceId);
|
|
9371
|
+
writeVarintU32(w, forceId(table.originalSql ?? ""));
|
|
9251
9372
|
w.u8((table.withoutRowid ? 1 : 0) | (table.strict ? 2 : 0));
|
|
9252
9373
|
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);
|
|
9266
|
-
for (const index of indexes) {
|
|
9267
|
-
w.json({
|
|
9268
|
-
name: index.name,
|
|
9269
|
-
tableName: index.tableName,
|
|
9270
|
-
unique: index.unique,
|
|
9271
|
-
columns: index.columns,
|
|
9272
|
-
where: index.where,
|
|
9273
|
-
originalSql: index.originalSql
|
|
9274
|
-
});
|
|
9275
|
-
}
|
|
9374
|
+
writeVarintU32(w, indexNames.length);
|
|
9375
|
+
for (const name of indexNames) writeVarintU32(w, forceId(name));
|
|
9376
|
+
writeTaggedValue(w, table.nextRowid, internId);
|
|
9377
|
+
const rows = tableRows[t];
|
|
9378
|
+
writeVarintU32(w, rows.length);
|
|
9379
|
+
for (const row of rows) writeTaggedValue(w, row.rowid, internId);
|
|
9380
|
+
for (let c = 0; c < table.columns.length; c++) writePackedColumn(w, rows, c, internId);
|
|
9381
|
+
}
|
|
9382
|
+
writeVarintU32(w, views.length);
|
|
9383
|
+
for (const view of views) writeBjv(w, view, forceId);
|
|
9384
|
+
writeVarintU32(w, indexes.length);
|
|
9276
9385
|
for (const index of indexes) {
|
|
9277
|
-
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
9386
|
+
writeBjv(
|
|
9387
|
+
w,
|
|
9388
|
+
{
|
|
9389
|
+
name: index.name,
|
|
9390
|
+
tableName: index.tableName,
|
|
9391
|
+
unique: index.unique,
|
|
9392
|
+
columns: index.columns,
|
|
9393
|
+
where: index.where,
|
|
9394
|
+
originalSql: index.originalSql
|
|
9395
|
+
},
|
|
9396
|
+
forceId
|
|
9397
|
+
);
|
|
9284
9398
|
}
|
|
9399
|
+
for (const index of indexes) writeIndexStoreBinary(w, index.store, internId);
|
|
9285
9400
|
w.u64(runtime.prngState);
|
|
9286
9401
|
w.i64(BigInt(Math.trunc(runtime.nowMs)));
|
|
9287
9402
|
return w.finish();
|
|
9288
9403
|
}
|
|
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);
|
|
9404
|
+
function decodeDatabaseState(snapshot) {
|
|
9405
|
+
try {
|
|
9406
|
+
return decodeInner(snapshot);
|
|
9407
|
+
} catch (error) {
|
|
9408
|
+
if (error instanceof SqliteError) throw error;
|
|
9409
|
+
throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9320
9410
|
}
|
|
9321
9411
|
}
|
|
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;
|
|
9412
|
+
function decodeInner(snapshot) {
|
|
9413
|
+
const r = new Reader(snapshot);
|
|
9414
|
+
const magic = r.raw(4);
|
|
9415
|
+
if (!magic.every((byte, index) => byte === MAGIC[index]))
|
|
9416
|
+
throw new SqliteError("invalid sqlite-mem snapshot magic", "other");
|
|
9417
|
+
const version = r.u32();
|
|
9418
|
+
if (version !== VERSION) {
|
|
9419
|
+
throw new SqliteError(`unsupported sqlite-mem snapshot version: ${version}`, "snapshot_version", "SQLITE_FORMAT");
|
|
9350
9420
|
}
|
|
9351
|
-
w.value(value);
|
|
9352
|
-
}
|
|
9353
|
-
function decodeV4(reader) {
|
|
9354
9421
|
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());
|
|
9422
|
+
state.foreignKeysEnabled = r.u8() !== 0;
|
|
9423
|
+
state.schemaVersion = r.u32();
|
|
9424
|
+
state.changes = r.u32();
|
|
9425
|
+
state.totalChanges = r.u32();
|
|
9426
|
+
state.lastInsertRowid = asRowid2(readTaggedValue(r, []));
|
|
9427
|
+
const intern = readInternTable(r);
|
|
9363
9428
|
const str = (id) => intern[id] ?? "";
|
|
9364
|
-
const tableCount =
|
|
9429
|
+
const tableCount = readVarintU32(r);
|
|
9365
9430
|
for (let t = 0; t < tableCount; t++) {
|
|
9366
|
-
const name = str(
|
|
9367
|
-
const colCount =
|
|
9431
|
+
const name = str(readVarintU32(r));
|
|
9432
|
+
const colCount = readVarintU32(r);
|
|
9368
9433
|
const columns = [];
|
|
9369
9434
|
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 ?
|
|
9435
|
+
const colName = str(readVarintU32(r));
|
|
9436
|
+
const typeName = str(readVarintU32(r)) || null;
|
|
9437
|
+
const affIndex = r.u8();
|
|
9438
|
+
const flags = r.u8();
|
|
9439
|
+
const collate = str(readVarintU32(r)) || null;
|
|
9440
|
+
const hasDefault = r.u8() === 1;
|
|
9441
|
+
const defaultExpr = hasDefault ? readBjv(r, intern) : null;
|
|
9442
|
+
const hasGenerated = r.u8() === 1;
|
|
9443
|
+
const generated = hasGenerated ? readBjv(r, intern) : null;
|
|
9379
9444
|
columns.push({
|
|
9380
9445
|
name: colName,
|
|
9381
9446
|
nameLower: colName.toLowerCase(),
|
|
@@ -9390,12 +9455,12 @@ function decodeV4(reader) {
|
|
|
9390
9455
|
generated
|
|
9391
9456
|
});
|
|
9392
9457
|
}
|
|
9393
|
-
const constraints =
|
|
9394
|
-
const originalSql = str(
|
|
9395
|
-
const tableFlags =
|
|
9396
|
-
const
|
|
9458
|
+
const constraints = readBjv(r, intern);
|
|
9459
|
+
const originalSql = str(readVarintU32(r)) || null;
|
|
9460
|
+
const tableFlags = r.u8();
|
|
9461
|
+
const indexNameCount = readVarintU32(r);
|
|
9397
9462
|
const indexNames = [];
|
|
9398
|
-
for (let i = 0; i <
|
|
9463
|
+
for (let i = 0; i < indexNameCount; i++) indexNames.push(str(readVarintU32(r)));
|
|
9399
9464
|
const table = new Table(name, columns, {
|
|
9400
9465
|
constraints,
|
|
9401
9466
|
indexes: indexNames,
|
|
@@ -9403,95 +9468,325 @@ function decodeV4(reader) {
|
|
|
9403
9468
|
withoutRowid: (tableFlags & 1) !== 0,
|
|
9404
9469
|
strict: (tableFlags & 2) !== 0
|
|
9405
9470
|
});
|
|
9406
|
-
table.nextRowid = asRowid2(
|
|
9407
|
-
const rowCount =
|
|
9471
|
+
table.nextRowid = asRowid2(readTaggedValue(r, intern));
|
|
9472
|
+
const rowCount = readVarintU32(r);
|
|
9408
9473
|
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();
|
|
9474
|
+
for (let ri = 0; ri < rowCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9475
|
+
const slabColumns = [];
|
|
9476
|
+
for (let c = 0; c < colCount; c++) slabColumns.push(readPackedColumn(r, rowCount, intern));
|
|
9477
|
+
table.attachSlab(new ColumnarSlab(snapshot, rowCount, rowids, slabColumns, intern));
|
|
9478
|
+
if (table.withoutRowid) table.rebuildClusteredRows();
|
|
9419
9479
|
state.tables.set(table.name.toLowerCase(), table);
|
|
9420
9480
|
}
|
|
9421
|
-
const viewCount =
|
|
9481
|
+
const viewCount = readVarintU32(r);
|
|
9422
9482
|
for (let i = 0; i < viewCount; i++) {
|
|
9423
|
-
const view =
|
|
9483
|
+
const view = readBjv(r, intern);
|
|
9424
9484
|
state.views.set(view.name.toLowerCase(), view);
|
|
9425
9485
|
}
|
|
9426
|
-
const indexCount =
|
|
9486
|
+
const indexCount = readVarintU32(r);
|
|
9427
9487
|
const loadedIndexes = [];
|
|
9428
9488
|
for (let i = 0; i < indexCount; i++) {
|
|
9429
|
-
const meta =
|
|
9489
|
+
const meta = readBjv(r, intern);
|
|
9430
9490
|
const info = { ...meta, store: new IndexStore(meta.name) };
|
|
9431
9491
|
state.indexes.set(info.name.toLowerCase(), info);
|
|
9432
9492
|
loadedIndexes.push(info);
|
|
9433
9493
|
}
|
|
9434
9494
|
for (const info of loadedIndexes) {
|
|
9435
|
-
info.store =
|
|
9436
|
-
const table = state.tables.get(info.tableName.toLowerCase());
|
|
9437
|
-
if (!table) continue;
|
|
9438
|
-
for (const entry of info.store.snapshotKeys()) {
|
|
9439
|
-
const rowid = entry.rowids[0];
|
|
9440
|
-
if (rowid === void 0) continue;
|
|
9441
|
-
const row = table.rows.get(rowid);
|
|
9442
|
-
if (!row) continue;
|
|
9443
|
-
info.store.rememberKeyValues(
|
|
9444
|
-
entry.key,
|
|
9445
|
-
indexKeyValues(info.columns, row, tableRowEvalContext(table, row), table)
|
|
9446
|
-
);
|
|
9447
|
-
}
|
|
9495
|
+
info.store = readIndexStoreBinary(r, info.name, intern);
|
|
9448
9496
|
}
|
|
9449
|
-
if (
|
|
9450
|
-
const runtime = { prngState:
|
|
9451
|
-
if (!
|
|
9497
|
+
if (r.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
|
|
9498
|
+
const runtime = { prngState: r.u64(), nowMs: finiteNowMs(Number(r.i64())) };
|
|
9499
|
+
if (!r.done()) throw new SqliteError("snapshot has trailing data", "other");
|
|
9452
9500
|
return { state, runtime };
|
|
9453
9501
|
}
|
|
9454
|
-
function
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
for (let i = 0; i < n; i++) out[i] = null;
|
|
9459
|
-
return out;
|
|
9502
|
+
function writeTaggedValue(w, value, internId) {
|
|
9503
|
+
if (value === null) {
|
|
9504
|
+
w.u8(0);
|
|
9505
|
+
return;
|
|
9460
9506
|
}
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9507
|
+
if (value instanceof SqlReal) {
|
|
9508
|
+
w.u8(2);
|
|
9509
|
+
w.f64(value.value);
|
|
9510
|
+
return;
|
|
9511
|
+
}
|
|
9512
|
+
if (typeof value === "bigint" || typeof value === "number" && Number.isInteger(value)) {
|
|
9513
|
+
w.u8(1);
|
|
9514
|
+
w.i64(BigInt(value));
|
|
9515
|
+
return;
|
|
9516
|
+
}
|
|
9517
|
+
if (typeof value === "number") {
|
|
9518
|
+
w.u8(2);
|
|
9519
|
+
w.f64(value);
|
|
9520
|
+
return;
|
|
9521
|
+
}
|
|
9522
|
+
if (typeof value === "string") {
|
|
9523
|
+
const id = internId(value);
|
|
9524
|
+
if (id >= 0) {
|
|
9525
|
+
w.u8(3);
|
|
9526
|
+
writeVarintU32(w, id);
|
|
9527
|
+
return;
|
|
9466
9528
|
}
|
|
9467
|
-
|
|
9529
|
+
w.u8(4);
|
|
9530
|
+
w.text(value);
|
|
9531
|
+
return;
|
|
9468
9532
|
}
|
|
9469
|
-
|
|
9533
|
+
if (value instanceof SqlJsonText) {
|
|
9534
|
+
w.u8(4);
|
|
9535
|
+
w.text(value.value);
|
|
9536
|
+
return;
|
|
9537
|
+
}
|
|
9538
|
+
w.u8(5);
|
|
9539
|
+
writeVarintU32(w, value.length);
|
|
9540
|
+
w.raw(value);
|
|
9470
9541
|
}
|
|
9471
|
-
function
|
|
9472
|
-
|
|
9473
|
-
|
|
9542
|
+
function readTaggedValue(r, intern) {
|
|
9543
|
+
const tag = r.u8();
|
|
9544
|
+
if (tag === 0) return null;
|
|
9545
|
+
if (tag === 1) {
|
|
9546
|
+
const integer = r.i64();
|
|
9474
9547
|
return integer <= BigInt(Number.MAX_SAFE_INTEGER) && integer >= BigInt(Number.MIN_SAFE_INTEGER) ? Number(integer) : integer;
|
|
9475
9548
|
}
|
|
9476
|
-
if (
|
|
9477
|
-
const value =
|
|
9549
|
+
if (tag === 2) {
|
|
9550
|
+
const value = r.f64();
|
|
9478
9551
|
return Number.isInteger(value) && Number.isFinite(value) ? asSqlReal(value) : value;
|
|
9479
9552
|
}
|
|
9480
|
-
if (
|
|
9481
|
-
if (
|
|
9482
|
-
return
|
|
9553
|
+
if (tag === 3) return intern[readVarintU32(r)] ?? "";
|
|
9554
|
+
if (tag === 4) return r.text();
|
|
9555
|
+
return r.raw(readVarintU32(r));
|
|
9483
9556
|
}
|
|
9484
|
-
function
|
|
9485
|
-
const
|
|
9557
|
+
function writePackedColumn(w, rows, col, internId) {
|
|
9558
|
+
const n = rows.length;
|
|
9559
|
+
if (n === 0) {
|
|
9560
|
+
w.u8(PACK_NULL);
|
|
9561
|
+
return;
|
|
9562
|
+
}
|
|
9563
|
+
const bits = new Uint8Array(n + 7 >> 3);
|
|
9564
|
+
let nulls = 0;
|
|
9565
|
+
let kind = null;
|
|
9566
|
+
let useInlineText = false;
|
|
9567
|
+
for (let i = 0; i < n; i++) {
|
|
9568
|
+
const value = rows[i].values[col] ?? null;
|
|
9569
|
+
if (value === null) {
|
|
9570
|
+
bits[i >> 3] = bits[i >> 3] | 1 << (i & 7);
|
|
9571
|
+
nulls++;
|
|
9572
|
+
continue;
|
|
9573
|
+
}
|
|
9574
|
+
const cellKind = packKindOf(value);
|
|
9575
|
+
if (kind === null) kind = cellKind;
|
|
9576
|
+
else if (kind !== cellKind) kind = PACK_TAGGED;
|
|
9577
|
+
if (cellKind === PACK_TEXT_INTERN && typeof value === "string" && internId(value) < 0) useInlineText = true;
|
|
9578
|
+
if (value instanceof SqlJsonText) kind = PACK_TAGGED;
|
|
9579
|
+
}
|
|
9580
|
+
if (nulls === n) {
|
|
9581
|
+
w.u8(PACK_NULL);
|
|
9582
|
+
return;
|
|
9583
|
+
}
|
|
9584
|
+
let pack = kind ?? PACK_TAGGED;
|
|
9585
|
+
if (pack === PACK_TEXT_INTERN && useInlineText) pack = PACK_TEXT_INLINE;
|
|
9586
|
+
w.u8(pack);
|
|
9587
|
+
w.raw(bits);
|
|
9588
|
+
if (pack === PACK_I32) {
|
|
9589
|
+
w.align4();
|
|
9590
|
+
for (let i = 0; i < n; i++) {
|
|
9591
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9592
|
+
w.u32(rows[i].values[col]);
|
|
9593
|
+
}
|
|
9594
|
+
return;
|
|
9595
|
+
}
|
|
9596
|
+
if (pack === PACK_I64) {
|
|
9597
|
+
w.align4();
|
|
9598
|
+
for (let i = 0; i < n; i++) {
|
|
9599
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9600
|
+
const v = rows[i].values[col];
|
|
9601
|
+
w.i64(typeof v === "bigint" ? v : BigInt(v));
|
|
9602
|
+
}
|
|
9603
|
+
return;
|
|
9604
|
+
}
|
|
9605
|
+
if (pack === PACK_F64) {
|
|
9606
|
+
w.align4();
|
|
9607
|
+
for (let i = 0; i < n; i++) {
|
|
9608
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9609
|
+
const v = rows[i].values[col];
|
|
9610
|
+
w.f64(v instanceof SqlReal ? v.value : v);
|
|
9611
|
+
}
|
|
9612
|
+
return;
|
|
9613
|
+
}
|
|
9614
|
+
if (pack === PACK_TEXT_INTERN) {
|
|
9615
|
+
w.align4();
|
|
9616
|
+
for (let i = 0; i < n; i++) {
|
|
9617
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9618
|
+
const text2 = rows[i].values[col];
|
|
9619
|
+
w.u32(internId(text2));
|
|
9620
|
+
}
|
|
9621
|
+
return;
|
|
9622
|
+
}
|
|
9623
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
9624
|
+
const offsets = [];
|
|
9625
|
+
let blobLen = 0;
|
|
9626
|
+
for (let i = 0; i < n; i++) {
|
|
9627
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9628
|
+
offsets.push(blobLen);
|
|
9629
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9630
|
+
blobLen += utf8Encode(text2).length;
|
|
9631
|
+
}
|
|
9632
|
+
writeVarintU32(w, offsets.length);
|
|
9633
|
+
for (const off of offsets) writeVarintU32(w, off);
|
|
9634
|
+
writeVarintU32(w, blobLen);
|
|
9635
|
+
for (let i = 0; i < n; i++) {
|
|
9636
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9637
|
+
const text2 = rows[i].values[col] instanceof SqlJsonText ? rows[i].values[col].value : rows[i].values[col];
|
|
9638
|
+
w.textBytes(text2);
|
|
9639
|
+
}
|
|
9640
|
+
return;
|
|
9641
|
+
}
|
|
9642
|
+
if (pack === PACK_BLOB) {
|
|
9643
|
+
for (let i = 0; i < n; i++) {
|
|
9644
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9645
|
+
const blob = rows[i].values[col];
|
|
9646
|
+
writeVarintU32(w, blob.length);
|
|
9647
|
+
w.raw(blob);
|
|
9648
|
+
}
|
|
9649
|
+
return;
|
|
9650
|
+
}
|
|
9651
|
+
for (let i = 0; i < n; i++) {
|
|
9652
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9653
|
+
writeTaggedValue(w, rows[i].values[col], internId);
|
|
9654
|
+
}
|
|
9655
|
+
}
|
|
9656
|
+
function readPackedColumn(r, n, intern) {
|
|
9657
|
+
const pack = r.u8();
|
|
9658
|
+
if (pack === PACK_NULL) return prepareSlabColumn({ pack, nullBitmap: null, payload: new Uint8Array(0) }, n, 0);
|
|
9659
|
+
const bits = r.raw(n + 7 >> 3);
|
|
9660
|
+
const nonNull = countNonNull(bits, n);
|
|
9661
|
+
if (pack === PACK_I32 || pack === PACK_I64 || pack === PACK_F64 || pack === PACK_TEXT_INTERN) {
|
|
9662
|
+
r.skipAlign4();
|
|
9663
|
+
const width = pack === PACK_I32 || pack === PACK_TEXT_INTERN ? 4 : 8;
|
|
9664
|
+
const payload = r.raw(nonNull * width);
|
|
9665
|
+
return prepareSlabColumn({ pack, nullBitmap: bits, payload }, n, nonNull);
|
|
9666
|
+
}
|
|
9667
|
+
if (pack === PACK_TEXT_INLINE) {
|
|
9668
|
+
const count = readVarintU32(r);
|
|
9669
|
+
const offsets = new Uint32Array(count);
|
|
9670
|
+
for (let i = 0; i < count; i++) offsets[i] = readVarintU32(r);
|
|
9671
|
+
const total = readVarintU32(r);
|
|
9672
|
+
const payload = r.raw(total);
|
|
9673
|
+
return prepareSlabColumn({ pack, nullBitmap: bits, payload, inlineOffsets: offsets }, n, nonNull);
|
|
9674
|
+
}
|
|
9675
|
+
if (pack === PACK_BLOB) {
|
|
9676
|
+
const chunks = [];
|
|
9677
|
+
for (let i = 0; i < n; i++) {
|
|
9678
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9679
|
+
const len = readVarintU32(r);
|
|
9680
|
+
chunks.push(r.raw(len));
|
|
9681
|
+
}
|
|
9682
|
+
return prepareSlabColumn({ pack, nullBitmap: bits, payload: new Uint8Array(0), blobChunks: chunks }, n, nonNull);
|
|
9683
|
+
}
|
|
9684
|
+
const tagged = [];
|
|
9685
|
+
for (let i = 0; i < n; i++) {
|
|
9686
|
+
if (bits[i >> 3] & 1 << (i & 7)) continue;
|
|
9687
|
+
tagged.push(readTaggedValue(r, intern));
|
|
9688
|
+
}
|
|
9689
|
+
return prepareSlabColumn({ pack: PACK_TAGGED, nullBitmap: bits, payload: new Uint8Array(0), tagged }, n, nonNull);
|
|
9690
|
+
}
|
|
9691
|
+
function countNonNull(bits, n) {
|
|
9692
|
+
let c = 0;
|
|
9693
|
+
for (let i = 0; i < n; i++) if ((bits[i >> 3] & 1 << (i & 7)) === 0) c++;
|
|
9694
|
+
return c;
|
|
9695
|
+
}
|
|
9696
|
+
function writeIndexStoreBinary(w, store, internId) {
|
|
9697
|
+
const entries = store.snapshotKeys();
|
|
9698
|
+
writeVarintU32(w, entries.length);
|
|
9699
|
+
for (const entry of entries) {
|
|
9700
|
+
const values = store.keyValuesFor(entry.key);
|
|
9701
|
+
writeVarintU32(w, values.length);
|
|
9702
|
+
for (const v of values) writeTaggedValue(w, v, internId);
|
|
9703
|
+
writeVarintU32(w, entry.rowids.length);
|
|
9704
|
+
for (const id of entry.rowids) writeTaggedValue(w, id, internId);
|
|
9705
|
+
}
|
|
9706
|
+
}
|
|
9707
|
+
function readIndexStoreBinary(r, name, intern) {
|
|
9708
|
+
const count = readVarintU32(r);
|
|
9486
9709
|
const entries = /* @__PURE__ */ new Map();
|
|
9710
|
+
const keyValues = /* @__PURE__ */ new Map();
|
|
9487
9711
|
for (let i = 0; i < count; i++) {
|
|
9488
|
-
const
|
|
9489
|
-
const
|
|
9712
|
+
const valueCount = readVarintU32(r);
|
|
9713
|
+
const values = [];
|
|
9714
|
+
for (let v = 0; v < valueCount; v++) values.push(readTaggedValue(r, intern));
|
|
9715
|
+
const key = serializeIndexEntry(values);
|
|
9716
|
+
const rowidCount = readVarintU32(r);
|
|
9490
9717
|
const rowids = [];
|
|
9491
|
-
for (let
|
|
9718
|
+
for (let ri = 0; ri < rowidCount; ri++) rowids.push(asRowid2(readTaggedValue(r, intern)));
|
|
9492
9719
|
entries.set(key, rowids);
|
|
9720
|
+
keyValues.set(key, values);
|
|
9721
|
+
}
|
|
9722
|
+
return new IndexStore(name, entries, keyValues);
|
|
9723
|
+
}
|
|
9724
|
+
function asRowid2(value) {
|
|
9725
|
+
if (typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint") return value;
|
|
9726
|
+
throw new SqliteError("invalid rowid in snapshot", "other");
|
|
9727
|
+
}
|
|
9728
|
+
function compareNames(a, b) {
|
|
9729
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
9730
|
+
}
|
|
9731
|
+
function finiteNowMs(value) {
|
|
9732
|
+
if (!Number.isFinite(value)) return 0;
|
|
9733
|
+
const max = 864e13;
|
|
9734
|
+
if (value > max) return max;
|
|
9735
|
+
if (value < -max) return -max;
|
|
9736
|
+
return value;
|
|
9737
|
+
}
|
|
9738
|
+
function sortedValues(map) {
|
|
9739
|
+
return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
|
|
9740
|
+
}
|
|
9741
|
+
function forceSchemaIntern(pool, tables, views, indexes) {
|
|
9742
|
+
for (const table of tables) {
|
|
9743
|
+
pool.forceId(table.name);
|
|
9744
|
+
pool.forceId(table.originalSql ?? "");
|
|
9745
|
+
for (const column of table.columns) {
|
|
9746
|
+
pool.forceId(column.name);
|
|
9747
|
+
pool.forceId(column.typeName ?? "");
|
|
9748
|
+
pool.forceId(column.collate ?? "");
|
|
9749
|
+
}
|
|
9750
|
+
for (const name of table.indexes) pool.forceId(name);
|
|
9751
|
+
forceBjvStrings(pool, table.constraints);
|
|
9752
|
+
for (const column of table.columns) {
|
|
9753
|
+
if (column.defaultExpr) forceBjvStrings(pool, column.defaultExpr);
|
|
9754
|
+
if (column.generated) forceBjvStrings(pool, column.generated);
|
|
9755
|
+
}
|
|
9756
|
+
}
|
|
9757
|
+
for (const view of views) forceBjvStrings(pool, view);
|
|
9758
|
+
for (const index of indexes) {
|
|
9759
|
+
pool.forceId(index.name);
|
|
9760
|
+
pool.forceId(index.tableName);
|
|
9761
|
+
pool.forceId(index.originalSql ?? "");
|
|
9762
|
+
forceBjvStrings(pool, {
|
|
9763
|
+
name: index.name,
|
|
9764
|
+
tableName: index.tableName,
|
|
9765
|
+
unique: index.unique,
|
|
9766
|
+
columns: index.columns,
|
|
9767
|
+
where: index.where,
|
|
9768
|
+
originalSql: index.originalSql
|
|
9769
|
+
});
|
|
9770
|
+
}
|
|
9771
|
+
}
|
|
9772
|
+
function forceBjvStrings(pool, value) {
|
|
9773
|
+
if (value === null || value === void 0) return;
|
|
9774
|
+
if (typeof value === "string") {
|
|
9775
|
+
pool.forceId(value);
|
|
9776
|
+
return;
|
|
9777
|
+
}
|
|
9778
|
+
if (typeof value === "bigint" || typeof value === "boolean" || typeof value === "number") return;
|
|
9779
|
+
if (value instanceof Uint8Array) return;
|
|
9780
|
+
if (Array.isArray(value)) {
|
|
9781
|
+
for (const item of value) forceBjvStrings(pool, item);
|
|
9782
|
+
return;
|
|
9783
|
+
}
|
|
9784
|
+
if (typeof value === "object") {
|
|
9785
|
+
for (const [k, v] of Object.entries(value)) {
|
|
9786
|
+
pool.forceId(k);
|
|
9787
|
+
forceBjvStrings(pool, v);
|
|
9788
|
+
}
|
|
9493
9789
|
}
|
|
9494
|
-
return new IndexStore(name, entries);
|
|
9495
9790
|
}
|
|
9496
9791
|
export {
|
|
9497
9792
|
DEFAULT_DATABASE_SEED,
|