@crvouga/sqlite-mem 1.11.0 → 1.13.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.
@@ -1,5 +1,5 @@
1
- import type { Rowid } from "./row.js";
2
1
  import { type SqlValue } from "../types/value.js";
2
+ import type { Rowid } from "./row.js";
3
3
  /** Column pack tags (SQLM v5). */
4
4
  export declare const PACK_NULL = 0;
5
5
  export declare const PACK_I32 = 1;
@@ -14,6 +14,10 @@ export interface SlabColumn {
14
14
  nullBitmap: Uint8Array | null;
15
15
  /** Typed payload or inline blob region inside `buffer`. */
16
16
  payload: Uint8Array;
17
+ /** Cached view over `payload` (avoid per-cell DataView alloc). */
18
+ view?: DataView;
19
+ /** Prefix count of non-null cells before each row (when nulls exist). */
20
+ nonNullRank?: Uint32Array;
17
21
  /** For PACK_TEXT_INLINE: u32 offsets into payload per row. */
18
22
  inlineOffsets?: Uint32Array;
19
23
  /** For PACK_TAGGED: decoded values per non-null row in order. */
@@ -21,6 +25,8 @@ export interface SlabColumn {
21
25
  /** For PACK_BLOB: one entry per non-null row. */
22
26
  blobChunks?: Uint8Array[];
23
27
  }
28
+ /** Attach decode helpers; drop an all-zero null bitmap. */
29
+ export declare function prepareSlabColumn(column: SlabColumn, rowCount: number, nonNull: number): SlabColumn;
24
30
  /** Frozen columnar row storage; zero-copy views into snapshot buffer. */
25
31
  export declare class ColumnarSlab {
26
32
  readonly buffer: Uint8Array;
package/dist/unstable.js CHANGED
@@ -6037,54 +6037,6 @@ function sameRowid(left, right) {
6037
6037
  return typeof left === "bigint" || typeof right === "bigint" ? BigInt(left) === BigInt(right) : left === right;
6038
6038
  }
6039
6039
 
6040
- // src/storage/row.ts
6041
- function normalizeColumnName(name) {
6042
- return name.toLowerCase();
6043
- }
6044
- function rowValues(values) {
6045
- const result = /* @__PURE__ */ new Map();
6046
- const entries = values instanceof Map ? values.entries() : Object.entries(values);
6047
- for (const [name, value] of entries) {
6048
- result.set(normalizeColumnName(name), value);
6049
- }
6050
- return result;
6051
- }
6052
- function cloneRow(row) {
6053
- const values = new Array(row.values.length);
6054
- for (let i = 0; i < row.values.length; i++) values[i] = cloneSqlValue(row.values[i]);
6055
- return { rowid: row.rowid, values };
6056
- }
6057
- function isValueArray(values) {
6058
- return Array.isArray(values);
6059
- }
6060
-
6061
- // src/indexes/keys.ts
6062
- function indexKeyValues(columns, row, ctx, table) {
6063
- return columns.map((column) => {
6064
- const raw = column.expr && ctx ? evalExpr(column.expr, ctx) : table ? table.cell(row, normalizeColumnName(column.name)) : null;
6065
- return normalizeForCollation(raw, column.collate ?? "BINARY");
6066
- });
6067
- }
6068
- function tableRowEvalContext(table, row) {
6069
- return {
6070
- functions: defaultFunctionRegistry,
6071
- resolveColumn: (qualifier, name) => {
6072
- if (qualifier && qualifier.toLowerCase() !== table.name.toLowerCase()) {
6073
- throw new SqliteError(`no such column: ${qualifier}.${name}`, "no_such_column");
6074
- }
6075
- const key = name.toLowerCase();
6076
- if (key === "rowid" || key === "_rowid_" || key === "oid") return row.rowid;
6077
- if (!table.hasColumn(key) && key !== "rowid") {
6078
- throw new SqliteError(`no such column: ${name}`, "no_such_column");
6079
- }
6080
- return table.cell(row, key);
6081
- },
6082
- getParameter: () => {
6083
- throw new SqliteError("parameters are not allowed in index predicates", "misuse");
6084
- }
6085
- };
6086
- }
6087
-
6088
6040
  // src/storage/columnar-slab.ts
6089
6041
  var PACK_NULL = 0;
6090
6042
  var PACK_I32 = 1;
@@ -6094,6 +6046,27 @@ var PACK_TEXT_INTERN = 4;
6094
6046
  var PACK_TEXT_INLINE = 5;
6095
6047
  var PACK_BLOB = 6;
6096
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;
6057
+ }
6058
+ column.nonNullRank = buildNonNullRank(column.nullBitmap, rowCount);
6059
+ return column;
6060
+ }
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++;
6067
+ }
6068
+ return rank;
6069
+ }
6097
6070
  var ColumnarSlab = class {
6098
6071
  buffer;
6099
6072
  rowCount;
@@ -6149,11 +6122,15 @@ function canonicalRowid(rowid) {
6149
6122
  function isNull(bits, i) {
6150
6123
  return (bits[i >> 3] & 1 << (i & 7)) !== 0;
6151
6124
  }
6125
+ function nonNullRowIndex(column, rowIndex) {
6126
+ if (!column.nullBitmap) return rowIndex;
6127
+ return column.nonNullRank?.[rowIndex] ?? rowIndex;
6128
+ }
6152
6129
  function readSlabCell(column, rowIndex, intern) {
6153
6130
  const pack = column.pack;
6154
6131
  if (pack === PACK_NULL) return null;
6155
6132
  const nonNullIndex = nonNullRowIndex(column, rowIndex);
6156
- const view = new DataView(column.payload.buffer, column.payload.byteOffset, column.payload.byteLength);
6133
+ const view = column.view;
6157
6134
  if (pack === PACK_I32) {
6158
6135
  return view.getInt32(nonNullIndex * 4, true);
6159
6136
  }
@@ -6173,7 +6150,7 @@ function readSlabCell(column, rowIndex, intern) {
6173
6150
  const offsets = column.inlineOffsets;
6174
6151
  const start = offsets[nonNullIndex];
6175
6152
  const end = nonNullIndex + 1 < offsets.length ? offsets[nonNullIndex + 1] : column.payload.length;
6176
- return new TextDecoder().decode(column.payload.subarray(start, end));
6153
+ return utf8Decode(column.payload.subarray(start, end));
6177
6154
  }
6178
6155
  if (pack === PACK_BLOB) {
6179
6156
  const blob = column.blobChunks[nonNullIndex];
@@ -6184,14 +6161,6 @@ function readSlabCell(column, rowIndex, intern) {
6184
6161
  }
6185
6162
  return null;
6186
6163
  }
6187
- function nonNullRowIndex(column, rowIndex) {
6188
- if (!column.nullBitmap) return rowIndex;
6189
- let idx = 0;
6190
- for (let i = 0; i < rowIndex; i++) {
6191
- if (!isNull(column.nullBitmap, i)) idx++;
6192
- }
6193
- return idx;
6194
- }
6195
6164
  function packKindOf(value) {
6196
6165
  if (value instanceof SqlReal) return PACK_F64;
6197
6166
  if (typeof value === "bigint") return PACK_I64;
@@ -7811,6 +7780,27 @@ var FtsVocabVirtualTable = class _FtsVocabVirtualTable {
7811
7780
  }
7812
7781
  };
7813
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
+
7814
7804
  // src/storage/table.ts
7815
7805
  var EQUALITY_HASH_MIN_ROWS = 16;
7816
7806
  var Table = class _Table {
@@ -9320,6 +9310,7 @@ function encodeDatabaseState(state, runtime) {
9320
9310
  const tables = sortedValues(state.tables);
9321
9311
  const views = sortedValues(state.views);
9322
9312
  const indexes = sortedValues(state.indexes);
9313
+ const tableRows = [];
9323
9314
  for (const table of tables) {
9324
9315
  pool.count(table.name);
9325
9316
  pool.count(table.originalSql ?? "");
@@ -9329,7 +9320,9 @@ function encodeDatabaseState(state, runtime) {
9329
9320
  pool.count(column.collate ?? "");
9330
9321
  }
9331
9322
  for (const name of table.indexes) pool.count(name);
9332
- for (const row of table.sortedRows()) {
9323
+ const rows = table.sortedRows();
9324
+ tableRows.push(rows);
9325
+ for (const row of rows) {
9333
9326
  for (const value of row.values) {
9334
9327
  if (typeof value === "string") pool.count(value);
9335
9328
  else if (value instanceof SqlJsonText) pool.count(value.value);
@@ -9352,7 +9345,8 @@ function encodeDatabaseState(state, runtime) {
9352
9345
  writeTaggedValue(w, state.lastInsertRowid, internId);
9353
9346
  writeInternTable(w, pool.list);
9354
9347
  writeVarintU32(w, tables.length);
9355
- for (const table of tables) {
9348
+ for (let t = 0; t < tables.length; t++) {
9349
+ const table = tables[t];
9356
9350
  writeVarintU32(w, forceId(table.name));
9357
9351
  writeVarintU32(w, table.columns.length);
9358
9352
  for (const column of table.columns) {
@@ -9380,7 +9374,7 @@ function encodeDatabaseState(state, runtime) {
9380
9374
  writeVarintU32(w, indexNames.length);
9381
9375
  for (const name of indexNames) writeVarintU32(w, forceId(name));
9382
9376
  writeTaggedValue(w, table.nextRowid, internId);
9383
- const rows = table.sortedRows();
9377
+ const rows = tableRows[t];
9384
9378
  writeVarintU32(w, rows.length);
9385
9379
  for (const row of rows) writeTaggedValue(w, row.rowid, internId);
9386
9380
  for (let c = 0; c < table.columns.length; c++) writePackedColumn(w, rows, c, internId);
@@ -9499,18 +9493,6 @@ function decodeInner(snapshot) {
9499
9493
  }
9500
9494
  for (const info of loadedIndexes) {
9501
9495
  info.store = readIndexStoreBinary(r, info.name, intern);
9502
- const table = state.tables.get(info.tableName.toLowerCase());
9503
- if (!table) continue;
9504
- for (const entry of info.store.snapshotKeys()) {
9505
- const rowid = entry.rowids[0];
9506
- if (rowid === void 0) continue;
9507
- const row = table.get(rowid);
9508
- if (!row) continue;
9509
- info.store.rememberKeyValues(
9510
- entry.key,
9511
- indexKeyValues(info.columns, row, tableRowEvalContext(table, row), table)
9512
- );
9513
- }
9514
9496
  }
9515
9497
  if (r.remaining() < 16) throw new SqliteError("invalid or truncated sqlite-mem snapshot", "other");
9516
9498
  const runtime = { prngState: r.u64(), nowMs: finiteNowMs(Number(r.i64())) };
@@ -9673,14 +9655,14 @@ function writePackedColumn(w, rows, col, internId) {
9673
9655
  }
9674
9656
  function readPackedColumn(r, n, intern) {
9675
9657
  const pack = r.u8();
9676
- if (pack === PACK_NULL) return { pack, nullBitmap: null, payload: new Uint8Array(0) };
9658
+ if (pack === PACK_NULL) return prepareSlabColumn({ pack, nullBitmap: null, payload: new Uint8Array(0) }, n, 0);
9677
9659
  const bits = r.raw(n + 7 >> 3);
9678
9660
  const nonNull = countNonNull(bits, n);
9679
9661
  if (pack === PACK_I32 || pack === PACK_I64 || pack === PACK_F64 || pack === PACK_TEXT_INTERN) {
9680
9662
  r.skipAlign4();
9681
9663
  const width = pack === PACK_I32 || pack === PACK_TEXT_INTERN ? 4 : 8;
9682
9664
  const payload = r.raw(nonNull * width);
9683
- return { pack, nullBitmap: bits, payload };
9665
+ return prepareSlabColumn({ pack, nullBitmap: bits, payload }, n, nonNull);
9684
9666
  }
9685
9667
  if (pack === PACK_TEXT_INLINE) {
9686
9668
  const count = readVarintU32(r);
@@ -9688,7 +9670,7 @@ function readPackedColumn(r, n, intern) {
9688
9670
  for (let i = 0; i < count; i++) offsets[i] = readVarintU32(r);
9689
9671
  const total = readVarintU32(r);
9690
9672
  const payload = r.raw(total);
9691
- return { pack, nullBitmap: bits, payload, inlineOffsets: offsets };
9673
+ return prepareSlabColumn({ pack, nullBitmap: bits, payload, inlineOffsets: offsets }, n, nonNull);
9692
9674
  }
9693
9675
  if (pack === PACK_BLOB) {
9694
9676
  const chunks = [];
@@ -9697,14 +9679,14 @@ function readPackedColumn(r, n, intern) {
9697
9679
  const len = readVarintU32(r);
9698
9680
  chunks.push(r.raw(len));
9699
9681
  }
9700
- return { pack, nullBitmap: bits, payload: new Uint8Array(0), blobChunks: chunks };
9682
+ return prepareSlabColumn({ pack, nullBitmap: bits, payload: new Uint8Array(0), blobChunks: chunks }, n, nonNull);
9701
9683
  }
9702
9684
  const tagged = [];
9703
9685
  for (let i = 0; i < n; i++) {
9704
9686
  if (bits[i >> 3] & 1 << (i & 7)) continue;
9705
9687
  tagged.push(readTaggedValue(r, intern));
9706
9688
  }
9707
- return { pack: PACK_TAGGED, nullBitmap: bits, payload: new Uint8Array(0), tagged };
9689
+ return prepareSlabColumn({ pack: PACK_TAGGED, nullBitmap: bits, payload: new Uint8Array(0), tagged }, n, nonNull);
9708
9690
  }
9709
9691
  function countNonNull(bits, n) {
9710
9692
  let c = 0;