@crvouga/mockingbird-service-postgres 3.11.0 → 3.12.1

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/wire/cli.js CHANGED
@@ -1,5 +1,251 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // ../../core/dist/fork-map.js
4
+ var ForkMap = class _ForkMap {
5
+ owner = {};
6
+ index = { owner: this.owner, groups: [] };
7
+ order = { owner: this.owner, cells: [] };
8
+ shift = 0;
9
+ length = 0;
10
+ count = 0;
11
+ nextSequence = 0;
12
+ layout = 0;
13
+ cleared = 0;
14
+ version = 0;
15
+ constructor(entries) {
16
+ if (entries)
17
+ for (const [key, value] of entries)
18
+ this.set(key, value);
19
+ }
20
+ get size() {
21
+ return this.count;
22
+ }
23
+ get [Symbol.toStringTag]() {
24
+ return "Map";
25
+ }
26
+ fork() {
27
+ const copy = new _ForkMap();
28
+ copy.index = this.index;
29
+ copy.order = this.order;
30
+ copy.shift = this.shift;
31
+ copy.length = this.length;
32
+ copy.count = this.count;
33
+ copy.nextSequence = this.nextSequence;
34
+ this.owner = {};
35
+ return copy;
36
+ }
37
+ /** Visit changed hash buckets only. Values must be replaced, rather than mutated in place. */
38
+ *changes(previous) {
39
+ if (previous?.index === this.index)
40
+ return;
41
+ for (let group = 0; group < 32; group++) {
42
+ const currentGroup = this.index.groups[group];
43
+ const oldGroup = previous?.index.groups[group];
44
+ if (currentGroup === oldGroup)
45
+ continue;
46
+ for (let bucket = 0; bucket < 32; bucket++) {
47
+ const current = currentGroup?.buckets[bucket]?.data;
48
+ const old = oldGroup?.buckets[bucket]?.data;
49
+ if (current === old)
50
+ continue;
51
+ if (current)
52
+ for (const [key, entry] of current) {
53
+ const before = old?.get(key);
54
+ if (!before || !Object.is(before.value, entry.value) || before.sequence !== entry.sequence)
55
+ yield { key, value: entry.value, deleted: false };
56
+ }
57
+ if (old) {
58
+ for (const key of old.keys())
59
+ if (!current?.has(key))
60
+ yield { key, deleted: true };
61
+ }
62
+ }
63
+ }
64
+ }
65
+ get(key) {
66
+ return this.find(key)?.value;
67
+ }
68
+ has(key) {
69
+ return this.find(key) !== void 0;
70
+ }
71
+ set(key, value) {
72
+ if (typeof key === "number" && key === 0)
73
+ key = 0;
74
+ const hash2 = hashKey(key);
75
+ const existing = this.bucket(hash2)?.get(key);
76
+ if (existing && Object.is(existing.value, value))
77
+ return this;
78
+ const entry = existing ? { ...existing, value } : { key, value, position: this.length++, sequence: this.nextSequence++ };
79
+ this.writableBucket(hash2).set(key, entry);
80
+ this.writeOrder(entry.position, entry);
81
+ if (!existing)
82
+ this.count++;
83
+ this.version++;
84
+ return this;
85
+ }
86
+ delete(key) {
87
+ const hash2 = hashKey(key);
88
+ const entry = this.bucket(hash2)?.get(key);
89
+ if (!entry)
90
+ return false;
91
+ this.writableBucket(hash2).delete(key);
92
+ this.writeOrder(entry.position, void 0);
93
+ this.count--;
94
+ this.version++;
95
+ if (this.length > 1024 && this.length > this.count * 2)
96
+ this.compact();
97
+ return true;
98
+ }
99
+ clear() {
100
+ this.index = { owner: this.owner, groups: [] };
101
+ this.order = { owner: this.owner, cells: [] };
102
+ this.shift = this.length = this.count = this.nextSequence = 0;
103
+ this.layout++;
104
+ this.cleared++;
105
+ this.version++;
106
+ }
107
+ entries() {
108
+ return this.iterate(0);
109
+ }
110
+ keys() {
111
+ return this.iterate(1);
112
+ }
113
+ values() {
114
+ return this.iterate(2);
115
+ }
116
+ [Symbol.iterator]() {
117
+ return this.entries();
118
+ }
119
+ forEach(callback, thisArg) {
120
+ for (const [key, value] of this)
121
+ callback.call(thisArg, value, key, this);
122
+ }
123
+ find(key) {
124
+ return this.bucket(hashKey(key))?.get(key);
125
+ }
126
+ bucket(hash2) {
127
+ return this.index.groups[hash2 >>> 5 & 31]?.buckets[hash2 & 31]?.data;
128
+ }
129
+ writableBucket(hash2) {
130
+ if (this.index.owner !== this.owner)
131
+ this.index = { owner: this.owner, groups: this.index.groups.slice() };
132
+ const groupIndex = hash2 >>> 5 & 31;
133
+ let group = this.index.groups[groupIndex];
134
+ if (!group || group.owner !== this.owner) {
135
+ group = { owner: this.owner, buckets: group?.buckets.slice() ?? [] };
136
+ this.index.groups[groupIndex] = group;
137
+ }
138
+ const at = hash2 & 31;
139
+ let bucket = group.buckets[at];
140
+ if (!bucket || bucket.owner !== this.owner) {
141
+ bucket = { owner: this.owner, data: bucket ? this.copyBucket(bucket.data) : /* @__PURE__ */ new Map() };
142
+ group.buckets[at] = bucket;
143
+ }
144
+ return bucket.data;
145
+ }
146
+ copyBucket(bucket) {
147
+ return new Map(bucket);
148
+ }
149
+ leaf(position) {
150
+ let node = this.order;
151
+ for (let shift = this.shift; shift > 0; shift -= 5)
152
+ node = node.cells[Math.floor(position / 2 ** shift) & 31];
153
+ return node;
154
+ }
155
+ writeOrder(position, entry) {
156
+ while (position >= 2 ** (this.shift + 5)) {
157
+ this.order = { owner: this.owner, cells: [this.order] };
158
+ this.shift += 5;
159
+ }
160
+ if (this.order.owner !== this.owner)
161
+ this.order = { owner: this.owner, cells: this.order.cells.slice() };
162
+ let node = this.order;
163
+ for (let shift = this.shift; shift > 0; shift -= 5) {
164
+ const at = Math.floor(position / 2 ** shift) & 31;
165
+ let child = node.cells[at];
166
+ if (!child || child.owner !== this.owner) {
167
+ child = { owner: this.owner, cells: child?.cells.slice() ?? [] };
168
+ node.cells[at] = child;
169
+ }
170
+ node = child;
171
+ }
172
+ node.cells[position & 31] = entry;
173
+ }
174
+ compact() {
175
+ const entries = [];
176
+ for (let position = 0; position < this.length; position++) {
177
+ const entry = this.leaf(position).cells[position & 31];
178
+ if (entry)
179
+ entries.push(entry);
180
+ }
181
+ this.index = { owner: this.owner, groups: [] };
182
+ this.order = { owner: this.owner, cells: [] };
183
+ this.shift = this.length = this.count = 0;
184
+ for (const original of entries) {
185
+ const entry = { ...original, position: this.length++ };
186
+ this.writableBucket(hashKey(entry.key)).set(entry.key, entry);
187
+ this.writeOrder(entry.position, entry);
188
+ this.count++;
189
+ }
190
+ this.layout++;
191
+ }
192
+ *iterate(kind) {
193
+ let position = 0;
194
+ let layout = this.layout;
195
+ let cleared = this.cleared;
196
+ let lastSequence = -1;
197
+ let version = -1;
198
+ let leaf;
199
+ let page = -1;
200
+ for (; ; ) {
201
+ if (cleared !== this.cleared) {
202
+ position = 0;
203
+ lastSequence = -1;
204
+ cleared = this.cleared;
205
+ }
206
+ if (layout !== this.layout) {
207
+ position = 0;
208
+ while (position < this.length) {
209
+ const entry2 = this.leaf(position).cells[position & 31];
210
+ if (entry2 && entry2.sequence > lastSequence)
211
+ break;
212
+ position++;
213
+ }
214
+ layout = this.layout;
215
+ }
216
+ if (position >= this.length)
217
+ return;
218
+ const nextPage = Math.floor(position / 32);
219
+ if (page !== nextPage || version !== this.version) {
220
+ leaf = this.leaf(position);
221
+ page = nextPage;
222
+ version = this.version;
223
+ }
224
+ const entry = leaf?.cells[position++ & 31];
225
+ if (!entry)
226
+ continue;
227
+ lastSequence = entry.sequence;
228
+ yield kind === 0 ? [entry.key, entry.value] : kind === 1 ? entry.key : entry.value;
229
+ }
230
+ }
231
+ };
232
+ function hashKey(key) {
233
+ if (typeof key === "number" && Number.isInteger(key))
234
+ return mix((key | 0) ^ (key / 4294967296 | 0));
235
+ if (typeof key === "bigint")
236
+ return mix(Number(BigInt.asIntN(32, key ^ key >> 32n)));
237
+ const text = String(key);
238
+ let hash2 = 2166136261;
239
+ for (let i = 0; i < text.length; i++)
240
+ hash2 = Math.imul(hash2 ^ text.charCodeAt(i), 16777619);
241
+ return hash2;
242
+ }
243
+ function mix(value) {
244
+ value = Math.imul(value ^ value >>> 16, 73244475);
245
+ value = Math.imul(value ^ value >>> 16, 73244475);
246
+ return value ^ value >>> 16;
247
+ }
248
+
3
249
  // ../../core/dist/timeline.js
4
250
  var BRANCH_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/;
5
251
  var Timeline = class {
@@ -3798,7 +4044,7 @@ async function preflightFleet(config, options2) {
3798
4044
  break;
3799
4045
  }
3800
4046
  }
3801
- targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.11.0" });
4047
+ targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.12.1" });
3802
4048
  } catch (error) {
3803
4049
  throw new Error(`service ${name2}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
3804
4050
  }
@@ -10358,10 +10604,81 @@ function parseArrayText(t, text, ctx) {
10358
10604
 
10359
10605
  // src/storage/database-state.ts
10360
10606
  var TableData = class _TableData {
10607
+ /** @internal Optional physical row journal; IDs remain stable across heap splices. */
10608
+ durableChanges = null;
10609
+ durableNextId = 0;
10610
+ durableEpoch;
10611
+ durableUnsafe = false;
10612
+ durableIds;
10613
+ enableDurabilityTracking(ids, nextId) {
10614
+ if (this.durableChanges && !this.durableUnsafe && !ids) return;
10615
+ this.materializeSlab();
10616
+ this.durableIds = /* @__PURE__ */ new WeakMap();
10617
+ this.durableChanges = new ForkMap();
10618
+ this.durableNextId = nextId ?? this.#rows.length;
10619
+ for (let i = 0; i < this.#rows.length; i++) this.durableIds.set(this.#rows[i], ids?.[i] ?? i);
10620
+ this.durableEpoch = {};
10621
+ this.durableUnsafe = false;
10622
+ }
10623
+ durableRowId(row) {
10624
+ const id = this.durableIds?.get(row);
10625
+ if (id === void 0) throw new Error("Untracked durable row");
10626
+ return id;
10627
+ }
10628
+ disableDurabilityTracking() {
10629
+ this.durableChanges = null;
10630
+ this.durableIds = void 0;
10631
+ this.durableEpoch = void 0;
10632
+ this.durableUnsafe = false;
10633
+ }
10634
+ recordDurableRow(row, previous) {
10635
+ if (!this.durableChanges) return;
10636
+ const id = (previous && this.durableIds?.get(previous)) ?? this.durableIds?.get(row) ?? this.durableNextId++;
10637
+ this.durableIds.set(row, id);
10638
+ this.durableChanges.set(id, { row, xmin: this.rowXmins.get(row) ?? 2 });
10639
+ }
10640
+ recordDurableDelete(row) {
10641
+ if (this.durableChanges) this.durableChanges.set(this.durableRowId(row), { row: null, xmin: 0 });
10642
+ }
10643
+ /** @internal Metadata twin with no visits/copies of existing rows or index entries. */
10644
+ emptyForDurability() {
10645
+ const copy = new _TableData(this.schema, this.name, this.columns, this.oid, this.temp);
10646
+ copy.constraints = this.constraints;
10647
+ copy.triggers = this.triggers;
10648
+ copy.unlogged = this.unlogged;
10649
+ return copy;
10650
+ }
10651
+ /** @internal Serialization/SQL scans must not count as public native-array exposure. */
10652
+ serializationRows() {
10653
+ this.materializeSlab();
10654
+ return this.materializedRows();
10655
+ }
10656
+ /** @internal Internal mutable array access, with ordinary public mutableRows kept intact. */
10657
+ writeRows() {
10658
+ return this.serializationRows();
10659
+ }
10660
+ /** @internal Ordinary snapshot branches must not inherit a persistence journal. */
10661
+ untrackedFork() {
10662
+ const copy = this.emptyForDurability();
10663
+ copy.rowXmins = this.rowXmins;
10664
+ copy.slabXmins = this.slabXmins;
10665
+ if (this.slab) copy.slab = this.slab;
10666
+ else {
10667
+ copy.#rows = this.#rows;
10668
+ copy.#rowPatches = this.#rowPatches?.fork() ?? null;
10669
+ copy.#rowsShared = this.#rowsShared = true;
10670
+ copy.tuplesShared = this.tuplesShared = true;
10671
+ }
10672
+ copy.indexStores = this.indexStores ? new Map([...this.indexStores].map(([name2, store]) => [name2, store.clone()])) : null;
10673
+ return copy;
10674
+ }
10361
10675
  name;
10362
10676
  schema;
10363
10677
  columns;
10364
- rows;
10678
+ #rows = [];
10679
+ #rowPatches = null;
10680
+ #rowsShared = false;
10681
+ #rowsExposed = false;
10365
10682
  rowXmins = /* @__PURE__ */ new WeakMap();
10366
10683
  slabXmins = null;
10367
10684
  /** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
@@ -10377,22 +10694,54 @@ var TableData = class _TableData {
10377
10694
  shareCount = 0;
10378
10695
  /** Derived unique/btree index maps; null until built or invalidated. */
10379
10696
  indexStores = null;
10697
+ /** DML replaces tuples; DDL must detach them before changing cells in place. */
10698
+ tuplesShared = false;
10380
10699
  constructor(schema, name2, columns, oid, temp = false) {
10381
10700
  this.schema = schema;
10382
10701
  this.name = name2;
10383
10702
  this.columns = columns;
10384
- this.rows = [];
10703
+ Object.defineProperty(this, "rows", {
10704
+ enumerable: true,
10705
+ configurable: true,
10706
+ get: this.nativeRows,
10707
+ set: this.setNativeRows
10708
+ });
10385
10709
  this.constraints = [];
10386
10710
  this.triggers = [];
10387
10711
  this.temp = temp;
10388
10712
  this.oid = oid;
10389
10713
  }
10390
10714
  rowCount() {
10391
- return this.slab ? this.slab.rowCount : this.rows.length;
10715
+ return this.slab ? this.slab.rowCount : this.#rows.length;
10392
10716
  }
10393
10717
  rowAt(index) {
10394
10718
  if (this.slab) return this.slab.rowAt(index);
10395
- return this.rows[index] ?? [];
10719
+ return this.#rowPatches?.get(index) ?? this.#rows[index] ?? [];
10720
+ }
10721
+ /** Replace an existing tuple without copying the array of unchanged row references. */
10722
+ replaceRow(index, row) {
10723
+ if (this.durableChanges) this.recordDurableRow(row, this.rowAt(index));
10724
+ if (this.#rowPatches) this.#rowPatches.set(index, row);
10725
+ else this.#rows[index] = row;
10726
+ }
10727
+ materializedRows() {
10728
+ if (this.#rowsShared) this.#rows = this.#rows.slice();
10729
+ if (this.#rowPatches) for (const [index, row] of this.#rowPatches) this.#rows[index] = row;
10730
+ this.#rowPatches = null;
10731
+ this.#rowsShared = false;
10732
+ return this.#rows;
10733
+ }
10734
+ nativeRows() {
10735
+ if (this.durableChanges) this.durableUnsafe = true;
10736
+ this.#rowsExposed = true;
10737
+ return this.materializedRows();
10738
+ }
10739
+ setNativeRows(rows) {
10740
+ if (this.durableChanges) this.durableUnsafe = true;
10741
+ this.#rows = rows;
10742
+ this.#rowPatches = null;
10743
+ this.#rowsShared = false;
10744
+ this.#rowsExposed = true;
10396
10745
  }
10397
10746
  /** All rows for scans; materializes slab once into `rows` when needed. */
10398
10747
  allRows() {
@@ -10401,13 +10750,15 @@ var TableData = class _TableData {
10401
10750
  }
10402
10751
  attachSlab(slab) {
10403
10752
  this.slab = slab;
10404
- this.rows = [];
10753
+ this.#rows = [];
10754
+ this.#rowPatches = null;
10755
+ this.#rowsShared = false;
10405
10756
  }
10406
10757
  materializeSlab() {
10407
10758
  if (!this.slab) return;
10408
- this.rows = this.slab.materialize();
10759
+ this.#rows = this.slab.materialize();
10409
10760
  if (this.slabXmins)
10410
- this.rows.forEach((row, index) => {
10761
+ this.#rows.forEach((row, index) => {
10411
10762
  this.rowXmins.set(row, this.slabXmins[index] ?? 2);
10412
10763
  });
10413
10764
  this.slabXmins = null;
@@ -10431,7 +10782,7 @@ var TableData = class _TableData {
10431
10782
  columnIndex(name2) {
10432
10783
  return this.columns.findIndex((c) => c.name === name2);
10433
10784
  }
10434
- clone() {
10785
+ cloneMetadata() {
10435
10786
  const t = new _TableData(
10436
10787
  this.schema,
10437
10788
  this.name,
@@ -10439,21 +10790,68 @@ var TableData = class _TableData {
10439
10790
  this.oid,
10440
10791
  this.temp
10441
10792
  );
10793
+ t.unlogged = this.unlogged;
10794
+ t.durableChanges = this.durableChanges?.fork() ?? null;
10795
+ t.durableIds = this.durableIds;
10796
+ t.durableNextId = this.durableNextId;
10797
+ t.durableEpoch = this.durableEpoch;
10798
+ t.durableUnsafe = this.durableUnsafe;
10799
+ t.constraints = this.constraints.map((c) => ({ ...c }));
10800
+ t.triggers = this.triggers.map((tr) => ({ ...tr }));
10801
+ t.indexStores = this.indexStores ? new Map([...this.indexStores].map(([k, v]) => [k, v.clone()])) : null;
10802
+ return t;
10803
+ }
10804
+ clone() {
10805
+ const t = this.cloneMetadata();
10806
+ if (t.durableChanges) t.durableUnsafe = true;
10442
10807
  if (this.slab) {
10443
- t.rows = this.slab.materialize().map((r) => r.slice());
10808
+ t.#rows = this.slab.materialize().map((r) => r.slice());
10444
10809
  } else {
10445
- t.rows = this.rows.map((r) => r.slice());
10810
+ t.#rows = this.materializedRows().map((r) => r.slice());
10446
10811
  }
10447
- t.rows.forEach((row, index) => {
10448
- const xmin = this.slabXmins?.[index] ?? this.rowXmins.get(this.rows[index]);
10812
+ t.#rows.forEach((row, index) => {
10813
+ const xmin = this.slabXmins?.[index] ?? this.rowXmins.get(this.#rows[index]);
10449
10814
  if (xmin !== void 0) t.rowXmins.set(row, xmin);
10450
10815
  });
10451
- t.unlogged = this.unlogged;
10452
- t.constraints = this.constraints.map((c) => ({ ...c }));
10453
- t.triggers = this.triggers.map((tr) => ({ ...tr }));
10454
- t.indexStores = this.indexStores ? new Map([...this.indexStores].map(([k, v]) => [k, v.clone()])) : null;
10455
10816
  return t;
10456
10817
  }
10818
+ /** DML creates new tuple arrays; retain existing tuples and xmin bindings until DDL. */
10819
+ cloneForDml() {
10820
+ if (this.triggers.length > 0) return this.cloneForWrite();
10821
+ const t = this.cloneMetadata();
10822
+ t.rowXmins = this.rowXmins;
10823
+ if (this.slab) {
10824
+ t.#rows = this.slab.materialize();
10825
+ if (this.slabXmins) {
10826
+ for (let index = 0; index < t.#rows.length; index++)
10827
+ t.rowXmins.set(t.#rows[index], this.slabXmins[index] ?? 2);
10828
+ }
10829
+ } else {
10830
+ if (this.#rows.length >= 4096 && !this.#rowsExposed) {
10831
+ this.#rowPatches ??= new ForkMap();
10832
+ t.#rowPatches = this.#rowPatches.fork();
10833
+ t.#rows = this.#rows;
10834
+ t.#rowsShared = this.#rowsShared = true;
10835
+ } else t.#rows = this.materializedRows().slice();
10836
+ this.tuplesShared = true;
10837
+ }
10838
+ t.tuplesShared = true;
10839
+ return t;
10840
+ }
10841
+ /** A live DML fork can be unfrozen while its unchanged tuples still belong to history. */
10842
+ ownTuples() {
10843
+ if (this.durableChanges) this.durableUnsafe = true;
10844
+ if (!this.tuplesShared) return;
10845
+ const xmins = /* @__PURE__ */ new WeakMap();
10846
+ this.rows = this.rows.map((row) => {
10847
+ const copy = row.slice();
10848
+ const xmin = this.rowXmins.get(row);
10849
+ if (xmin !== void 0) xmins.set(copy, xmin);
10850
+ return copy;
10851
+ });
10852
+ this.rowXmins = xmins;
10853
+ this.tuplesShared = false;
10854
+ }
10457
10855
  /** Independent writable copy (row tuples copied so ALTER COLUMN is isolated). */
10458
10856
  cloneForWrite() {
10459
10857
  const t = this.clone();
@@ -10807,12 +11205,21 @@ var DatabaseState = class _DatabaseState {
10807
11205
  }
10808
11206
  }
10809
11207
  ensureWritableTable(table) {
10810
- if (!table.frozen) return table;
11208
+ if (!table.frozen) {
11209
+ table.ownTuples();
11210
+ return table;
11211
+ }
10811
11212
  const schema = this.schemas.get(table.schema);
10812
11213
  const copy = table.cloneForWrite();
10813
11214
  schema?.tables.set(table.name, copy);
10814
11215
  return copy;
10815
11216
  }
11217
+ ensureWritableTableForDml(table) {
11218
+ if (!table.frozen) return table;
11219
+ const copy = table.cloneForDml();
11220
+ this.schemas.get(table.schema)?.tables.set(table.name, copy);
11221
+ return copy;
11222
+ }
10816
11223
  ensureWritableSequence(seq) {
10817
11224
  if ((seq.shareCount ?? 0) === 0) return seq;
10818
11225
  const schema = this.schemas.get(seq.schema);
@@ -13928,7 +14335,7 @@ function evalPgcryptoFunction(ctx, fn, args2) {
13928
14335
  // src/functions/hash-fns.ts
13929
14336
  var utf83 = new TextEncoder();
13930
14337
  var rot = (x, k) => (x << k | x >>> 32 - k) >>> 0;
13931
- function mix(s) {
14338
+ function mix2(s) {
13932
14339
  s[0] = s[0] - s[2] >>> 0;
13933
14340
  s[0] = (s[0] ^ rot(s[2], 4)) >>> 0;
13934
14341
  s[2] = s[2] + s[1] >>> 0;
@@ -13972,7 +14379,7 @@ function hashAny(k, seed) {
13972
14379
  const bits = BigInt.asUintN(64, seed);
13973
14380
  s[0] = s[0] + Number(bits >> 32n) >>> 0;
13974
14381
  s[1] = s[1] + Number(bits & 0xffffffffn) >>> 0;
13975
- mix(s);
14382
+ mix2(s);
13976
14383
  }
13977
14384
  let at = 0;
13978
14385
  let len = k.length;
@@ -13980,7 +14387,7 @@ function hashAny(k, seed) {
13980
14387
  s[0] = s[0] + word(k, at) >>> 0;
13981
14388
  s[1] = s[1] + word(k, at + 4) >>> 0;
13982
14389
  s[2] = s[2] + word(k, at + 8) >>> 0;
13983
- mix(s);
14390
+ mix2(s);
13984
14391
  }
13985
14392
  for (let i = len - 1; i >= 0; i--) {
13986
14393
  const byte = k[at + i];
@@ -20552,6 +20959,21 @@ var IndexStore = class _IndexStore {
20552
20959
  name;
20553
20960
  unique;
20554
20961
  entries = /* @__PURE__ */ new Map();
20962
+ integerKeys = null;
20963
+ shared = false;
20964
+ ownedBuckets = /* @__PURE__ */ new WeakSet();
20965
+ writableBucket(key, bucket) {
20966
+ if (this.ownedBuckets.has(bucket)) return bucket;
20967
+ const copy = bucket.slice();
20968
+ this.entries.set(key, copy);
20969
+ this.ownedBuckets.add(copy);
20970
+ return copy;
20971
+ }
20972
+ detach() {
20973
+ if (!this.shared) return;
20974
+ if (!(this.entries instanceof ForkMap)) this.entries = new Map(this.entries);
20975
+ this.shared = false;
20976
+ }
20555
20977
  constructor(name2, unique = false) {
20556
20978
  this.name = name2;
20557
20979
  this.unique = unique;
@@ -20570,36 +20992,78 @@ var IndexStore = class _IndexStore {
20570
20992
  }
20571
20993
  insert(key, rowIdx) {
20572
20994
  if (this.unique) this.checkUnique(key, rowIdx);
20995
+ this.detach();
20996
+ this.integerKeys = null;
20573
20997
  const existing = this.entries.get(key);
20574
20998
  if (!existing) {
20575
- this.entries.set(key, [rowIdx]);
20999
+ const bucket = [rowIdx];
21000
+ this.ownedBuckets.add(bucket);
21001
+ this.entries.set(key, bucket);
20576
21002
  return;
20577
21003
  }
20578
21004
  if (existing.includes(rowIdx)) return;
20579
- existing.push(rowIdx);
21005
+ this.writableBucket(key, existing).push(rowIdx);
20580
21006
  }
20581
21007
  remove(key, rowIdx) {
20582
21008
  const existing = this.entries.get(key);
20583
21009
  if (!existing) return;
20584
21010
  const at = existing.indexOf(rowIdx);
20585
21011
  if (at < 0) return;
20586
- existing.splice(at, 1);
20587
- if (existing.length === 0) this.entries.delete(key);
21012
+ this.detach();
21013
+ this.integerKeys = null;
21014
+ if (existing.length === 1) this.entries.delete(key);
21015
+ else {
21016
+ const remaining = this.writableBucket(key, existing);
21017
+ remaining.splice(at, 1);
21018
+ this.entries.set(key, remaining);
21019
+ }
20588
21020
  }
20589
21021
  lookup(key) {
20590
21022
  return this.entries.get(key) ?? [];
20591
21023
  }
21024
+ /** Ordered access for a single int2/int4 key (the planner validates the key type). */
21025
+ integerRange(lower, upper, includeLower, includeUpper) {
21026
+ const keys = this.integerKeys ??= [...this.entries].map(([key, rows]) => ({ value: Number(key.slice(1)), rows })).sort((a, b) => a.value - b.value);
21027
+ let lo = 0;
21028
+ let hi = keys.length;
21029
+ while (lo < hi) {
21030
+ const mid = lo + hi >>> 1;
21031
+ const value = keys[mid].value;
21032
+ if (value < lower || !includeLower && value === lower) lo = mid + 1;
21033
+ else hi = mid;
21034
+ }
21035
+ const result = [];
21036
+ for (let i = lo; i < keys.length; i++) {
21037
+ const key = keys[i];
21038
+ if (key.value > upper || !includeUpper && key.value === upper) break;
21039
+ result.push(...key.rows);
21040
+ }
21041
+ return result.sort((a, b) => a - b);
21042
+ }
20592
21043
  clear() {
20593
- this.entries.clear();
21044
+ this.entries = /* @__PURE__ */ new Map();
21045
+ this.shared = false;
21046
+ this.integerKeys = null;
20594
21047
  }
20595
21048
  clone() {
20596
21049
  const copy = new _IndexStore(this.name, this.unique);
20597
- for (const [key, rowids] of this.entries) copy.entries.set(key, [...rowids]);
21050
+ if (this.entries.size >= 4096 && !(this.entries instanceof ForkMap)) this.entries = new ForkMap(this.entries);
21051
+ copy.entries = this.entries instanceof ForkMap ? this.entries.fork() : this.entries;
21052
+ copy.integerKeys = this.integerKeys;
21053
+ copy.shared = true;
21054
+ this.shared = true;
21055
+ this.ownedBuckets = /* @__PURE__ */ new WeakSet();
20598
21056
  return copy;
20599
21057
  }
20600
21058
  };
20601
21059
 
20602
21060
  // src/indexes/maintain.ts
21061
+ function prepareDmlIndexStores(env, table) {
21062
+ if (table.indexStores || !table.frozen || table.triggers.length > 0) return;
21063
+ const specs = uniqueSpecsFor(env, table);
21064
+ if (specs.some((spec) => spec.where || spec.keys.some((key) => key.expr))) return;
21065
+ ensureIndexStores(env, table);
21066
+ }
20603
21067
  function ensureIndexStores(env, table) {
20604
21068
  if (table.indexStores) return table.indexStores;
20605
21069
  const stores = /* @__PURE__ */ new Map();
@@ -20650,8 +21114,19 @@ function indexRemoveRow(env, table, rowIdx, row) {
20650
21114
  }
20651
21115
  }
20652
21116
  function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
20653
- indexRemoveRow(env, table, rowIdx, oldRow);
20654
- indexInsertRow(env, table, rowIdx, newRow);
21117
+ const specs = uniqueSpecsFor(env, table);
21118
+ if (specs.some((spec) => spec.where || spec.keys.some((key) => key.expr))) {
21119
+ indexRemoveRow(env, table, rowIdx, oldRow);
21120
+ indexInsertRow(env, table, rowIdx, newRow);
21121
+ return;
21122
+ }
21123
+ for (const spec of specs) {
21124
+ const before = uniqueKeyOf(env, table, spec, oldRow);
21125
+ const after = uniqueKeyOf(env, table, spec, newRow);
21126
+ if (before === after) continue;
21127
+ if (before !== null) table.indexStores?.get(spec.name)?.remove(before, rowIdx);
21128
+ if (after !== null) indexStoreFor(env, table, spec).insert(after, rowIdx);
21129
+ }
20655
21130
  }
20656
21131
  function rebuildTableIndexes(env, table) {
20657
21132
  table.indexStores = null;
@@ -20868,6 +21343,82 @@ function conjunctions(expr) {
20868
21343
  }
20869
21344
  return [expr];
20870
21345
  }
21346
+ function tryPointRowIndices(env, table, alias, where) {
21347
+ const eqs = [];
21348
+ for (const part of conjunctions(where)) {
21349
+ const eq = equalityAgainstConst(part);
21350
+ if (!eq || !["param", "number_lit", "string_lit", "bool_lit", "null_lit"].includes(eq.valueExpr.type)) return null;
21351
+ if (part.type !== "binop") return null;
21352
+ const column = part.left.type === "colref" ? part.left : part.right;
21353
+ if (column.type !== "colref") return null;
21354
+ if (column.parts.length > 1 && column.parts[column.parts.length - 2] !== alias) return null;
21355
+ eqs.push(eq);
21356
+ }
21357
+ for (const spec of uniqueSpecsFor(env, table)) {
21358
+ if (spec.where || spec.keys.length !== eqs.length || spec.keys.some((key2) => key2.expr) || !eqs.every((eq, index) => eq.column === spec.columnNames[index]))
21359
+ continue;
21360
+ const values = table.columns.map(() => null);
21361
+ let matches2 = true;
21362
+ for (let index = 0; index < spec.keys.length; index++) {
21363
+ const key2 = spec.keys[index];
21364
+ const column = table.columns[key2.colIdx];
21365
+ const eq = eqs[index];
21366
+ if (!column || !eq || column.domain) {
21367
+ matches2 = false;
21368
+ break;
21369
+ }
21370
+ const value = evalExpr(env.ctx, makeEvalScope(env, null), eq.valueExpr);
21371
+ if (value.t !== column.type.id && !(column.type.id === "text" && value.t === "unknown" && typeof value.v === "string")) {
21372
+ matches2 = false;
21373
+ break;
21374
+ }
21375
+ values[key2.colIdx] = value.v;
21376
+ }
21377
+ if (!matches2) continue;
21378
+ const key = uniqueKeyOf(env, table, spec, values);
21379
+ return { indices: key === null ? [] : indexStoreFor(env, table, spec).lookup(key), indexName: spec.name };
21380
+ }
21381
+ return null;
21382
+ }
21383
+ function recordIndexScan(env, table, name2) {
21384
+ const schema = env.ctx.state.schemas.get(table.schema);
21385
+ const index = schema?.indexes.get(name2);
21386
+ if (schema && index) {
21387
+ const lastScan = env.ctx.state.clock().getTime();
21388
+ schema.indexes.set(name2, { ...index, scans: (index.scans ?? 0n) + 1n, lastScan });
21389
+ }
21390
+ }
21391
+ function tryRangeRowIndices(env, table, alias, where) {
21392
+ const parts = conjunctions(where);
21393
+ if (parts.length !== 2) return null;
21394
+ const bounds = [];
21395
+ for (const part of parts) {
21396
+ if (part.type !== "binop" || ![">", ">=", "<", "<="].includes(part.op)) return null;
21397
+ const column2 = part.left.type === "colref" ? part.left : part.right;
21398
+ const value = part.left.type === "colref" ? part.right : part.left;
21399
+ if (column2.type !== "colref" || column2.parts.length > 2 || column2.parts.length === 2 && column2.parts[0] !== alias || !["param", "number_lit"].includes(value.type))
21400
+ return null;
21401
+ const op = part.left === column2 ? part.op : { ">": "<", ">=": "<=", "<": ">", "<=": ">=" }[part.op];
21402
+ bounds.push({ column: column2.parts.at(-1), op, value });
21403
+ }
21404
+ const lower = bounds.find((bound) => bound.op === ">" || bound.op === ">=");
21405
+ const upper = bounds.find((bound) => bound.op === "<" || bound.op === "<=");
21406
+ if (!lower || !upper || lower.column !== upper.column) return null;
21407
+ const column = table.columns.find((column2) => column2.name === lower.column);
21408
+ if (!column || column.domain || !["int2", "int4"].includes(column.type.id)) return null;
21409
+ for (const spec of uniqueSpecsFor(env, table)) {
21410
+ if (spec.where || spec.keys.length !== 1 || spec.keys[0].expr || spec.columnNames[0] !== lower.column) continue;
21411
+ const low = evalExpr(env.ctx, makeEvalScope(env, null), lower.value);
21412
+ const high = evalExpr(env.ctx, makeEvalScope(env, null), upper.value);
21413
+ if (low.t !== column.type.id || high.t !== column.type.id || typeof low.v !== "number" || typeof high.v !== "number")
21414
+ return null;
21415
+ return {
21416
+ indices: indexStoreFor(env, table, spec).integerRange(low.v, high.v, lower.op === ">=", upper.op === "<="),
21417
+ indexName: spec.name
21418
+ };
21419
+ }
21420
+ return null;
21421
+ }
20871
21422
  function tryIndexedTableRows(env, table, alias, where) {
20872
21423
  const parts = conjunctions(where);
20873
21424
  const eqs = [];
@@ -20904,12 +21455,7 @@ function tryIndexedTableRows(env, table, alias, where) {
20904
21455
  const key = uniqueKeyOf(env, table, spec, probeRow);
20905
21456
  if (key === null) return [];
20906
21457
  const hits = indexStoreFor(env, table, spec).lookup(key);
20907
- const schema = env.ctx.state.schemas.get(table.schema);
20908
- const index = schema?.indexes.get(spec.name);
20909
- if (schema && index) {
20910
- const lastScan = env.ctx.state.clock().getTime();
20911
- schema.indexes.set(spec.name, { ...index, scans: (index.scans ?? 0n) + 1n, lastScan });
20912
- }
21458
+ recordIndexScan(env, table, spec.name);
20913
21459
  return hits.map((i) => table.rowAt(i));
20914
21460
  }
20915
21461
  function tryIndexedFromItem(env, item, where) {
@@ -26885,7 +27431,7 @@ function renameWithAliases(rel4, label, colAliases, what) {
26885
27431
  }));
26886
27432
  return { columns, rows: rel4.rows };
26887
27433
  }
26888
- function materializeItem(env, item, scope) {
27434
+ function materializeItem(env, item, scope, shapeOnly = false) {
26889
27435
  switch (item.type) {
26890
27436
  case "from_table": {
26891
27437
  const label = item.alias ?? item.name[item.name.length - 1];
@@ -26904,7 +27450,7 @@ function materializeItem(env, item, scope) {
26904
27450
  ...table.columns.map((c) => ({ name: c.name, type: c.type.id, mod: c.type.mod, table: label })),
26905
27451
  { name: "xmin", type: "xid", table: label, hidden: true, system: true }
26906
27452
  ],
26907
- rows: table.rows.map((row) => [...row, table.rowXmins.get(row) ?? 2])
27453
+ rows: shapeOnly ? [] : table.serializationRows().map((row) => [...row, table.rowXmins.get(row) ?? 2])
26908
27454
  };
26909
27455
  return { rel: renameWithAliases(rel4, label, item.colAliases, label), rangeVars: /* @__PURE__ */ new Set([label]) };
26910
27456
  }
@@ -28177,14 +28723,30 @@ function checkPredicateType(env, columns, rangeVars, e, kind, extras) {
28177
28723
  function executeCore(env0, core, orderBy, opts) {
28178
28724
  const env = env0;
28179
28725
  const ctx = env.ctx;
28180
- const source = buildFrom(env, core.from, core.where);
28726
+ const item = core.from.length === 1 ? core.from[0] : null;
28727
+ const pointTable = item?.type === "from_table" && !item.colAliases?.length && !(item.name.length === 1 && env.ctes.has(item.name[0])) ? env.ctx.state.findTable(item.name) : null;
28728
+ const point = pointTable && core.where && item?.type === "from_table" ? tryPointRowIndices(env, pointTable, item.alias ?? item.name[item.name.length - 1], core.where) : null;
28729
+ const range = !point && pointTable && core.where && item?.type === "from_table" ? tryRangeRowIndices(env, pointTable, item.alias ?? item.name[item.name.length - 1], core.where) : null;
28730
+ const access = point ?? range;
28731
+ const source = access && item ? materializeItem(env, item, env.outer, true) : buildFrom(env, core.from, core.where);
28181
28732
  const srcCols = source.rel.columns;
28182
28733
  const rangeVars = source.rangeVars;
28183
28734
  const rowScope = (row) => new RowScope(srcCols, row, env.outer, rangeVars);
28184
28735
  let srcRows = source.rel.rows;
28185
28736
  if (core.where) {
28186
28737
  checkPredicateType(env, srcCols, rangeVars, core.where, "WHERE");
28187
- if (core.from.length === 1) {
28738
+ if (access && pointTable) {
28739
+ pointTable.materializeSlab();
28740
+ srcRows = access.indices.map((index) => {
28741
+ const row = pointTable.rowAt(index);
28742
+ return [...row, pointTable.rowXmins.get(row) ?? 2];
28743
+ });
28744
+ if (range) {
28745
+ const where = core.where;
28746
+ srcRows = srcRows.filter((row) => evalPredicate2(env, rowScope(row), where));
28747
+ }
28748
+ recordIndexScan(env, pointTable, access.indexName);
28749
+ } else if (core.from.length === 1) {
28188
28750
  const indexed = tryIndexedFromItem(env, core.from[0], core.where);
28189
28751
  if (indexed !== null) {
28190
28752
  srcRows = indexed;
@@ -28365,11 +28927,11 @@ function executeCore(env0, core, orderBy, opts) {
28365
28927
  }
28366
28928
  }
28367
28929
  }
28368
- const item = { name: `__ord${orderExprs.length}`, kind: "expr", colIdx: -1, expr: ob.expr, hidden: true };
28930
+ const item2 = { name: `__ord${orderExprs.length}`, kind: "expr", colIdx: -1, expr: ob.expr, hidden: true };
28369
28931
  const spec = { colIdx: projItems.length, dir, nullsFirst };
28370
- projItems.push(item);
28932
+ projItems.push(item2);
28371
28933
  sortSpecs.push(spec);
28372
- orderExprs.push({ item, spec });
28934
+ orderExprs.push({ item: item2, spec });
28373
28935
  }
28374
28936
  if (core.distinct && !core.distinct.on && sortSpecs.length > 0 && !opts?.hasLimit) {
28375
28937
  const used = new Set(sortSpecs.map((s) => s.colIdx));
@@ -28743,7 +29305,7 @@ var TransactionManager = class {
28743
29305
  return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
28744
29306
  }
28745
29307
  restore(snap) {
28746
- this.state.restoreFrom(snap.state);
29308
+ this.state.restoreFrom(snap.state.cloneShallow());
28747
29309
  this.state.prng.setState(snap.prngState);
28748
29310
  }
28749
29311
  thawOnce() {
@@ -28843,7 +29405,10 @@ function withStatementRollback(env, fn) {
28843
29405
  function requireTargetTable(env, parts, verb) {
28844
29406
  const state = env.ctx.state;
28845
29407
  const table = state.findTable(parts);
28846
- if (table) return state.ensureWritableTable(table);
29408
+ if (table) {
29409
+ prepareDmlIndexStores(env, table);
29410
+ return state.ensureWritableTableForDml(table);
29411
+ }
28847
29412
  const view = state.findView(parts);
28848
29413
  if (view) {
28849
29414
  throw pgError("wrong_object_type", `cannot ${verb} view "${view.name}"`, "42809");
@@ -29011,7 +29576,7 @@ function resolveArbiters(env, table, clause) {
29011
29576
  return matches2.map((spec) => ({ spec }));
29012
29577
  }
29013
29578
  function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, where) {
29014
- const rows = table.mutableRows();
29579
+ const rows = table.writeRows();
29015
29580
  const existing = rows[existingIdx];
29016
29581
  const cols = [
29017
29582
  ...table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
@@ -29023,7 +29588,7 @@ function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, whe
29023
29588
  applyUpdateSets(env, table, sets, scope, updated);
29024
29589
  computeGeneratedColumns(env, table, updated);
29025
29590
  table.rowXmins.set(updated, env.ctx.rowVersionXid());
29026
- rows[existingIdx] = updated;
29591
+ table.replaceRow(existingIdx, updated);
29027
29592
  indexUpdateRow(env, table, existingIdx, existing, updated);
29028
29593
  checkNotNull(env, table, updated);
29029
29594
  checkChecks(env, table, updated);
@@ -29035,7 +29600,7 @@ function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, whe
29035
29600
  function executeInsert(env0, stmt) {
29036
29601
  const env = applyWith(env0, stmt.with);
29037
29602
  const table = requireTargetTable(env, stmt.table, "insert into");
29038
- const rows = table.mutableRows();
29603
+ const rows = table.writeRows();
29039
29604
  const label = stmt.alias ?? table.name;
29040
29605
  const colIdxs = insertTargetColumns(env, table, stmt);
29041
29606
  const sourceRows = insertSourceRows(env, stmt, colIdxs);
@@ -29119,6 +29684,7 @@ function executeInsert(env0, stmt) {
29119
29684
  checkForeignKeys(env, table, newRow);
29120
29685
  table.rowXmins.set(newRow, env.ctx.rowVersionXid());
29121
29686
  rows.push(newRow);
29687
+ table.recordDurableRow(newRow);
29122
29688
  indexInsertRow(env, table, rows.length - 1, newRow);
29123
29689
  insertedCount++;
29124
29690
  insertedRows.push(newRow);
@@ -29211,13 +29777,17 @@ function executeUpdate(env0, stmt) {
29211
29777
  const label = stmt.alias ?? table.name;
29212
29778
  fireStatementTriggers(env, table, "before", "update");
29213
29779
  const fromSource = stmt.from.length > 0 ? buildFrom(env, stmt.from) : null;
29214
- const rows = table.mutableRows();
29215
29780
  const targetCols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label }));
29216
29781
  const updatedRows = [];
29217
29782
  const replacedRows = [];
29218
29783
  let updateCount = 0;
29219
- for (let ri = 0; ri < rows.length; ri++) {
29220
- const oldRow = rows[ri];
29784
+ const point = !fromSource && stmt.where && table.triggers.length === 0 && !table.columns.some((column) => column.generated || column.domain) && !table.constraints.some((constraint) => constraint.kind === "check") && stmt.sets.every(
29785
+ (set) => set.columns.every((column) => column.subscripts === null && column.fields.length === 0) && "type" in set.value && isPureUpdateValue(set.value)
29786
+ ) && referencingConstraints(env, table).length === 0 ? tryPointRowIndices(env, table, label, stmt.where) : null;
29787
+ const rows = point ? null : table.writeRows();
29788
+ for (let candidate = 0; candidate < (point ? point.indices.length : rows.length); candidate++) {
29789
+ const ri = point ? point.indices[candidate] : candidate;
29790
+ const oldRow = point ? table.rowAt(ri) : rows[ri];
29221
29791
  let matchScope = null;
29222
29792
  if (fromSource) {
29223
29793
  let found = false;
@@ -29243,14 +29813,14 @@ function executeUpdate(env0, stmt) {
29243
29813
  const finalRow = fired.row;
29244
29814
  computeGeneratedColumns(env, table, finalRow);
29245
29815
  table.rowXmins.set(finalRow, env.ctx.rowVersionXid());
29246
- rows[ri] = finalRow;
29816
+ table.replaceRow(ri, finalRow);
29247
29817
  try {
29248
29818
  checkNotNull(env, table, finalRow);
29249
29819
  checkChecks(env, table, finalRow);
29250
29820
  checkUnique(env, table, finalRow, ri);
29251
29821
  checkForeignKeys(env, table, finalRow);
29252
29822
  } catch (err) {
29253
- rows[ri] = oldRow;
29823
+ table.replaceRow(ri, oldRow);
29254
29824
  throw err;
29255
29825
  }
29256
29826
  indexUpdateRow(env, table, ri, oldRow, finalRow);
@@ -29268,12 +29838,29 @@ function executeUpdate(env0, stmt) {
29268
29838
  }
29269
29839
  return commandResult("UPDATE", updateCount);
29270
29840
  }
29841
+ function isPureUpdateValue(expr) {
29842
+ switch (expr.type) {
29843
+ case "param":
29844
+ case "number_lit":
29845
+ case "string_lit":
29846
+ case "bool_lit":
29847
+ case "null_lit":
29848
+ case "colref":
29849
+ return true;
29850
+ case "binop":
29851
+ return isPureUpdateValue(expr.left) && isPureUpdateValue(expr.right);
29852
+ case "unop":
29853
+ return isPureUpdateValue(expr.operand);
29854
+ default:
29855
+ return false;
29856
+ }
29857
+ }
29271
29858
  function executeDelete(env0, stmt) {
29272
29859
  const env = applyWith(env0, stmt.with);
29273
29860
  const table = requireTargetTable(env, stmt.table, "delete from");
29274
29861
  const label = stmt.alias ?? table.name;
29275
29862
  fireStatementTriggers(env, table, "before", "delete");
29276
- const rows = table.mutableRows();
29863
+ const rows = table.writeRows();
29277
29864
  const usingSource = stmt.using.length > 0 ? buildFrom(env, stmt.using) : null;
29278
29865
  const targetCols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label }));
29279
29866
  const toDelete = [];
@@ -29303,6 +29890,7 @@ function executeDelete(env0, stmt) {
29303
29890
  if (skipped.has(ri)) continue;
29304
29891
  const row = rows[ri];
29305
29892
  handleReferencedDelete(env, table, row, 0);
29893
+ table.recordDurableDelete(row);
29306
29894
  rows.splice(ri, 1);
29307
29895
  deletedRows.unshift(row);
29308
29896
  }
@@ -29349,13 +29937,14 @@ function handleReferencedDelete(env, table, row, depth) {
29349
29937
  const idxs = referencingRowIdxs(ref, key);
29350
29938
  if (idxs.length === 0) continue;
29351
29939
  const action = con.onDelete ?? "no_action";
29352
- const child = env.ctx.state.ensureWritableTable(ref.table);
29353
- const childRows = child.mutableRows();
29940
+ const child = env.ctx.state.ensureWritableTableForDml(ref.table);
29941
+ const childRows = child.writeRows();
29354
29942
  switch (action) {
29355
29943
  case "cascade": {
29356
29944
  for (let k = idxs.length - 1; k >= 0; k--) {
29357
29945
  const childRow = childRows[idxs[k]];
29358
29946
  handleReferencedDelete(env, child, childRow, depth + 1);
29947
+ child.recordDurableDelete(childRow);
29359
29948
  childRows.splice(idxs[k], 1);
29360
29949
  }
29361
29950
  break;
@@ -29367,7 +29956,7 @@ function handleReferencedDelete(env, table, row, depth) {
29367
29956
  newRow[child.columnIndex(c)] = null;
29368
29957
  }
29369
29958
  child.rowXmins.set(newRow, env.ctx.rowVersionXid());
29370
- childRows[i] = newRow;
29959
+ child.replaceRow(i, newRow);
29371
29960
  checkNotNull(env, child, newRow);
29372
29961
  checkChecks(env, child, newRow);
29373
29962
  }
@@ -29381,7 +29970,7 @@ function handleReferencedDelete(env, table, row, depth) {
29381
29970
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
29382
29971
  }
29383
29972
  child.rowXmins.set(newRow, env.ctx.rowVersionXid());
29384
- childRows[i] = newRow;
29973
+ child.replaceRow(i, newRow);
29385
29974
  checkNotNull(env, child, newRow);
29386
29975
  checkChecks(env, child, newRow);
29387
29976
  checkForeignKeys(env, child, newRow);
@@ -29407,8 +29996,8 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
29407
29996
  const idxs = referencingRowIdxs(ref, oldKey);
29408
29997
  if (idxs.length === 0) continue;
29409
29998
  const action = con.onUpdate ?? "no_action";
29410
- const child = env.ctx.state.ensureWritableTable(ref.table);
29411
- const childRows = child.mutableRows();
29999
+ const child = env.ctx.state.ensureWritableTableForDml(ref.table);
30000
+ const childRows = child.writeRows();
29412
30001
  switch (action) {
29413
30002
  case "cascade": {
29414
30003
  for (const i of idxs) {
@@ -29419,7 +30008,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
29419
30008
  newRow[localIdx] = newRows[r][refIdx] ?? null;
29420
30009
  }
29421
30010
  child.rowXmins.set(newRow, env.ctx.rowVersionXid());
29422
- childRows[i] = newRow;
30011
+ child.replaceRow(i, newRow);
29423
30012
  checkChecks(env, child, newRow);
29424
30013
  }
29425
30014
  break;
@@ -29429,7 +30018,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
29429
30018
  const newRow = childRows[i].slice();
29430
30019
  for (const c of con.columns) newRow[child.columnIndex(c)] = null;
29431
30020
  child.rowXmins.set(newRow, env.ctx.rowVersionXid());
29432
- childRows[i] = newRow;
30021
+ child.replaceRow(i, newRow);
29433
30022
  checkNotNull(env, child, newRow);
29434
30023
  }
29435
30024
  break;
@@ -29442,7 +30031,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
29442
30031
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
29443
30032
  }
29444
30033
  child.rowXmins.set(newRow, env.ctx.rowVersionXid());
29445
- childRows[i] = newRow;
30034
+ child.replaceRow(i, newRow);
29446
30035
  checkForeignKeys(env, child, newRow);
29447
30036
  }
29448
30037
  break;
@@ -29965,6 +30554,8 @@ function openSnapshot(snapshot, options2 = {}) {
29965
30554
  now = () => new Date(ms);
29966
30555
  }
29967
30556
  const state = snapshot.state.cloneShallow();
30557
+ for (const schema of state.schemas.values())
30558
+ for (const [name2, table] of schema.tables) if (table.durableChanges) schema.tables.set(name2, table.untrackedFork());
29968
30559
  state.prng = prng;
29969
30560
  state.clock = now;
29970
30561
  return createAdoptedDatabase({
@@ -34650,6 +35241,24 @@ var Statement = class _Statement {
34650
35241
  this.database = database;
34651
35242
  this.sql = sql;
34652
35243
  this.statements = statements;
35244
+ const observer = database.durabilityObserver;
35245
+ if (observer) {
35246
+ const execute = this.execute;
35247
+ this.execute = (params) => {
35248
+ observer.assertWritable();
35249
+ if (params.some((value) => value instanceof Uint8Array)) observer.exposed();
35250
+ try {
35251
+ const result = execute.call(this, params);
35252
+ if (result.columns.some(
35253
+ (column, index) => column.type === "bytea" && result.rows.some((row) => row[index] !== null && row[index] !== void 0)
35254
+ ))
35255
+ observer.exposed();
35256
+ return result;
35257
+ } finally {
35258
+ observer.changed();
35259
+ }
35260
+ };
35261
+ }
34653
35262
  }
34654
35263
  database;
34655
35264
  statements;
@@ -34682,7 +35291,7 @@ var Statement = class _Statement {
34682
35291
  */
34683
35292
  textResult(...params) {
34684
35293
  const res = this.execute(params);
34685
- const ctx = new EngineCtx(this.database.state);
35294
+ const ctx = new EngineCtx(this.database.engineState);
34686
35295
  return {
34687
35296
  columns: res.columns.map((c) => c.name),
34688
35297
  columnTypes: res.columns.map((c) => c.type === UNKNOWN ? "text" : c.type),
@@ -34719,7 +35328,7 @@ var Statement = class _Statement {
34719
35328
  const refused = this.database.transactions.inTransaction ? refusedInTransactionBlock(stmt) : null;
34720
35329
  if (refused) throw pgError("misuse", `${refused} cannot run inside a transaction block`, "25001");
34721
35330
  const env = {
34722
- ctx: new EngineCtx(this.database.state),
35331
+ ctx: new EngineCtx(this.database.engineState),
34723
35332
  params: typed,
34724
35333
  ctes: /* @__PURE__ */ new Map(),
34725
35334
  outer: null
@@ -34729,12 +35338,13 @@ var Statement = class _Statement {
34729
35338
  return last;
34730
35339
  }
34731
35340
  toRows(res) {
34732
- const ctx = new EngineCtx(this.database.state);
35341
+ const ctx = new EngineCtx(this.database.engineState);
34733
35342
  return res.rows.map((row) => {
34734
35343
  const obj = {};
34735
35344
  for (let i = 0; i < res.columns.length; i++) {
34736
35345
  const c = res.columns[i];
34737
- obj[c.name] = datumToJs(c.type, row[i] ?? null, ctx, this.database.int8Mode);
35346
+ const value = datumToJs(c.type, row[i] ?? null, ctx, this.database.int8Mode);
35347
+ obj[c.name] = value;
34738
35348
  }
34739
35349
  return obj;
34740
35350
  });
@@ -34752,6 +35362,10 @@ function project(point) {
34752
35362
  var Database = class {
34753
35363
  /** @internal Engine catalog, tables, session settings. */
34754
35364
  state;
35365
+ /** @internal Engine-only access; buffered mode observes public state exposure. */
35366
+ engineState;
35367
+ /** @internal Installed only by buffered durability. */
35368
+ durabilityObserver;
34755
35369
  /** Seed used to construct the PRNG. Ignored when {@link randomMode} is `"os"`. */
34756
35370
  seed;
34757
35371
  /** Entropy mode for `random()` / `gen_random_uuid()`. */
@@ -34781,10 +35395,10 @@ var Database = class {
34781
35395
  this.int8Mode = options2.int8Mode;
34782
35396
  this.prng = options2.prng;
34783
35397
  this.now = options2.now;
34784
- this.state = options2.state;
34785
- this.state.prng = this.prng;
34786
- this.state.clock = () => this.now();
34787
- this.transactions = txManagerFor(this.state);
35398
+ this.engineState = options2.state;
35399
+ this.engineState.prng = this.prng;
35400
+ this.engineState.clock = () => this.now();
35401
+ this.transactions = txManagerFor(this.engineState);
34788
35402
  } else {
34789
35403
  this.seed = options2.seed ?? DEFAULT_DATABASE_SEED;
34790
35404
  this.randomMode = options2.random ?? "deterministic";
@@ -34792,9 +35406,10 @@ var Database = class {
34792
35406
  this.int8Mode = options2.int8 ?? "bigint";
34793
35407
  this.prng = this.randomMode === "os" ? new OsEntropy() : new Prng(this.seed);
34794
35408
  this.now = resolveClock(options2.now);
34795
- this.state = new DatabaseState(this.prng, () => this.now());
34796
- this.transactions = txManagerFor(this.state);
35409
+ this.engineState = new DatabaseState(this.prng, () => this.now());
35410
+ this.transactions = txManagerFor(this.engineState);
34797
35411
  }
35412
+ this.state = this.engineState;
34798
35413
  this.timeline = new Timeline({
34799
35414
  now: () => this.now().getTime(),
34800
35415
  ...options2.maxCheckpoints !== void 0 ? { maxCheckpoints: options2.maxCheckpoints } : {}
@@ -34821,14 +35436,15 @@ var Database = class {
34821
35436
  * a live in-memory snapshot.
34822
35437
  */
34823
35438
  registerFunction(spec) {
35439
+ this.durabilityObserver?.assertWritable();
34824
35440
  this.assertOpen();
34825
35441
  const parts = spec.name.split(".").map((p) => p.trim()).filter((p) => p.length > 0);
34826
35442
  if (parts.length === 0) throw pgError("syntax", "function name is required", "42601");
34827
- const schemaName = (parts.length >= 2 ? parts[0] : this.state.currentSchema()).toLowerCase();
35443
+ const schemaName = (parts.length >= 2 ? parts[0] : this.engineState.currentSchema()).toLowerCase();
34828
35444
  const name2 = parts[parts.length - 1].toLowerCase();
34829
- const functions = schemaName === "pg_catalog" ? this.state.systemFunctions : this.state.getSchema(schemaName).functions;
34830
- const argTypes = spec.args.map((a) => resolveTypeName(this.state, parseTypeName(a)).column.id);
34831
- const returns = resolveTypeName(this.state, parseTypeName(spec.returns)).column.id;
35445
+ const functions = schemaName === "pg_catalog" ? this.engineState.systemFunctions : this.engineState.getSchema(schemaName).functions;
35446
+ const argTypes = spec.args.map((a) => resolveTypeName(this.engineState, parseTypeName(a)).column.id);
35447
+ const returns = resolveTypeName(this.engineState, parseTypeName(spec.returns)).column.id;
34832
35448
  const fn = {
34833
35449
  name: name2,
34834
35450
  schema: schemaName,
@@ -34842,7 +35458,7 @@ var Database = class {
34842
35458
  body: null,
34843
35459
  rawBody: null,
34844
35460
  strict: spec.strict ?? true,
34845
- oid: this.state.nextOid(),
35461
+ oid: this.engineState.nextOid(),
34846
35462
  jsImpl: spec.fn
34847
35463
  };
34848
35464
  const existing = functions.get(name2) ?? [];
@@ -34852,6 +35468,7 @@ var Database = class {
34852
35468
  if (sameSig !== -1) existing[sameSig] = fn;
34853
35469
  else existing.push(fn);
34854
35470
  functions.set(name2, existing);
35471
+ this.durabilityObserver?.exposed();
34855
35472
  }
34856
35473
  /** Execute a single-statement query and return all rows keyed by column name. */
34857
35474
  query(sql, params = [], options2 = {}) {
@@ -34878,6 +35495,7 @@ var Database = class {
34878
35495
  */
34879
35496
  transaction(fn) {
34880
35497
  this.assertOpen();
35498
+ this.durabilityObserver?.assertWritable();
34881
35499
  this.apiTransactionDepth++;
34882
35500
  try {
34883
35501
  if (!this.transactions.inTransaction) {
@@ -34904,6 +35522,7 @@ var Database = class {
34904
35522
  }
34905
35523
  } finally {
34906
35524
  this.apiTransactionDepth--;
35525
+ this.durabilityObserver?.changed();
34907
35526
  }
34908
35527
  }
34909
35528
  /**
@@ -34998,7 +35617,7 @@ var Database = class {
34998
35617
  */
34999
35618
  fault(faults) {
35000
35619
  this.assertOpen();
35001
- Object.assign(this.state.faults, faults);
35620
+ Object.assign(this.engineState.faults, faults);
35002
35621
  }
35003
35622
  /** Close the database. Further SQL throws. Idempotent. */
35004
35623
  close() {
@@ -35008,6 +35627,7 @@ var Database = class {
35008
35627
  }
35009
35628
  if (this.transactions.inTransaction) this.transactions.rollback();
35010
35629
  this.closed = true;
35630
+ this.durabilityObserver?.closed?.();
35011
35631
  }
35012
35632
  /**
35013
35633
  * Execute `COPY table [(cols)] FROM STDIN` with the given text/csv payload
@@ -35026,13 +35646,18 @@ var Database = class {
35026
35646
  if (statements.length !== 1 || !stmt || stmt.type !== "copy" || stmt.direction !== "from") {
35027
35647
  throw pgError("misuse", "copyFrom() requires a single COPY ... FROM STDIN statement", "XX000");
35028
35648
  }
35029
- const env = { ctx: new EngineCtx(this.state), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
35030
- return executeCopyFromData(env, stmt, data).rowCount;
35649
+ this.durabilityObserver?.assertWritable();
35650
+ try {
35651
+ const env = { ctx: new EngineCtx(this.engineState), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
35652
+ return executeCopyFromData(env, stmt, data).rowCount;
35653
+ } finally {
35654
+ this.durabilityObserver?.changed();
35655
+ }
35031
35656
  }
35032
35657
  /** Rows affected by the most recent INSERT / UPDATE / DELETE. */
35033
35658
  get changes() {
35034
35659
  this.assertOpen();
35035
- return this.state.changes;
35660
+ return this.engineState.changes;
35036
35661
  }
35037
35662
  /** @internal */
35038
35663
  assertOpen() {
@@ -35044,7 +35669,7 @@ var Database = class {
35044
35669
  }
35045
35670
  captureLive() {
35046
35671
  return captureSnapshot(
35047
- this.state,
35672
+ this.engineState,
35048
35673
  this.prng,
35049
35674
  this.now,
35050
35675
  this.seed,
@@ -35054,7 +35679,8 @@ var Database = class {
35054
35679
  );
35055
35680
  }
35056
35681
  install(snapshot) {
35057
- this.state.restoreFrom(snapshot.state.cloneShallow());
35682
+ this.durabilityObserver?.exposed();
35683
+ this.engineState.restoreFrom(snapshot.state.cloneShallow());
35058
35684
  this.prng.setState(snapshot.prngState);
35059
35685
  if (!this.systemClock) this.now = fixedClock(new Date(snapshot.nowMs));
35060
35686
  }
@@ -36250,6 +36876,13 @@ var Writer = class {
36250
36876
  this.view.setBigInt64(this.len, value, true);
36251
36877
  this.len += 8;
36252
36878
  }
36879
+ /** Finite integer Number, encoded identically to i64(BigInt(value)) without allocation. */
36880
+ i64Number(value) {
36881
+ this.ensure(8);
36882
+ this.view.setUint32(this.len, value >>> 0, true);
36883
+ this.view.setUint32(this.len + 4, Math.floor(value / 4294967296) >>> 0, true);
36884
+ this.len += 8;
36885
+ }
36253
36886
  f64(value) {
36254
36887
  this.ensure(8);
36255
36888
  this.view.setFloat64(this.len, value, true);
@@ -36260,6 +36893,13 @@ var Writer = class {
36260
36893
  this.buf.set(value, this.len);
36261
36894
  this.len += value.length;
36262
36895
  }
36896
+ /** Reserve one contiguous region. Fill it before any subsequent Writer call can grow the buffer. */
36897
+ block(byteLength) {
36898
+ this.ensure(byteLength);
36899
+ const block = new DataView(this.buf.buffer, this.len, byteLength);
36900
+ this.len += byteLength;
36901
+ return block;
36902
+ }
36263
36903
  /** Length-prefixed UTF-8. */
36264
36904
  text(value) {
36265
36905
  const encoded = utf8Encode(value);
@@ -36272,7 +36912,7 @@ var Writer = class {
36272
36912
  }
36273
36913
  finish() {
36274
36914
  if (this.len === this.buf.length) return this.buf;
36275
- return this.buf.subarray(0, this.len).slice();
36915
+ return this.buf.slice(0, this.len);
36276
36916
  }
36277
36917
  fail() {
36278
36918
  throw new PostgresError("snapshot_format", "invalid or truncated postgres-mem snapshot", "XX000");
@@ -36489,15 +37129,18 @@ function writeInternTable(w, strings) {
36489
37129
  writeVarintU32(w, strings.length);
36490
37130
  if (strings.length === 0) return;
36491
37131
  const offsets = [];
37132
+ const encoded = [];
36492
37133
  let total = 0;
36493
37134
  for (const s of strings) {
36494
37135
  offsets.push(total);
36495
- total += utf8Encode(s).length;
37136
+ const bytes = utf8Encode(s);
37137
+ encoded.push(bytes);
37138
+ total += bytes.length;
36496
37139
  }
36497
37140
  writeVarintU32(w, total);
36498
37141
  const base = w.position + offsets.length * 4;
36499
37142
  for (const off of offsets) w.u32(base + off);
36500
- for (const s of strings) w.textBytes(s);
37143
+ for (const bytes of encoded) w.raw(bytes);
36501
37144
  }
36502
37145
  function readInternTable(r) {
36503
37146
  const count = readVarintU32(r);
@@ -36522,7 +37165,10 @@ var VERSION = 3;
36522
37165
  function encodeDatabaseState(state, runtime) {
36523
37166
  const pool = new InternPool();
36524
37167
  const schemas = [...state.schemas.values()].sort((a, b) => compareNames(a.name, b.name));
37168
+ const internValues = /* @__PURE__ */ new Map();
36525
37169
  for (const schema of schemas) {
37170
+ const values = [];
37171
+ internValues.set(schema, values);
36526
37172
  pool.count(schema.name);
36527
37173
  for (const table of sortedValues(schema.tables)) {
36528
37174
  pool.count(table.name);
@@ -36533,8 +37179,13 @@ function encodeDatabaseState(state, runtime) {
36533
37179
  pool.count(column.domain ?? "");
36534
37180
  if (column.identity) pool.count(column.identity.sequence);
36535
37181
  }
36536
- for (const row of table.allRows()) {
36537
- for (const d of row) if (typeof d === "string") pool.count(d);
37182
+ for (const row of table.serializationRows()) {
37183
+ for (const d of row) {
37184
+ if (typeof d === "string") {
37185
+ pool.count(d);
37186
+ values.push(d);
37187
+ } else if (d !== null && typeof d === "object" && !(d instanceof Uint8Array)) values.push(d);
37188
+ }
36538
37189
  }
36539
37190
  }
36540
37191
  for (const view of sortedValues(schema.views)) {
@@ -36542,7 +37193,12 @@ function encodeDatabaseState(state, runtime) {
36542
37193
  pool.count(view.schema);
36543
37194
  if (view.matRows) {
36544
37195
  for (const row of view.matRows) {
36545
- for (const d of row) if (typeof d === "string") pool.count(d);
37196
+ for (const d of row) {
37197
+ if (typeof d === "string") {
37198
+ pool.count(d);
37199
+ values.push(d);
37200
+ } else if (d !== null && typeof d === "object" && !(d instanceof Uint8Array)) values.push(d);
37201
+ }
36546
37202
  }
36547
37203
  }
36548
37204
  }
@@ -36575,7 +37231,7 @@ function encodeDatabaseState(state, runtime) {
36575
37231
  }
36576
37232
  }
36577
37233
  pool.finalize();
36578
- forceAllEncodeIntern(pool, state, schemas);
37234
+ forceAllEncodeIntern(pool, state, schemas, internValues);
36579
37235
  const internId = (s) => pool.id(s);
36580
37236
  const forceId = (s) => {
36581
37237
  const id = pool.id(s);
@@ -36604,7 +37260,7 @@ function encodeDatabaseState(state, runtime) {
36604
37260
  writeBjv(
36605
37261
  w,
36606
37262
  {
36607
- xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
37263
+ xmins: table.serializationRows().map((row) => table.rowXmins.get(row) ?? 2),
36608
37264
  name: table.name,
36609
37265
  schema: table.schema,
36610
37266
  columns: table.columns,
@@ -36617,7 +37273,7 @@ function encodeDatabaseState(state, runtime) {
36617
37273
  },
36618
37274
  forceId
36619
37275
  );
36620
- const rows = table.allRows();
37276
+ const rows = table.serializationRows();
36621
37277
  writeVarintU32(w, rows.length);
36622
37278
  for (let c = 0; c < table.columns.length; c++) writePackedColumn(w, rows, c, internId, forceId);
36623
37279
  }
@@ -36943,44 +37599,57 @@ function writePackedColumn(w, rows, col, internId, forceId) {
36943
37599
  }
36944
37600
  if (pack === PACK_FLOAT) {
36945
37601
  w.align4();
37602
+ const block = w.block((n - nulls) * 8);
37603
+ let offset = 0;
36946
37604
  for (let i = 0; i < n; i++) {
36947
37605
  if (bits[i >> 3] & 1 << (i & 7)) continue;
36948
- w.f64(rows[i][col]);
37606
+ block.setFloat64(offset, rows[i][col], true);
37607
+ offset += 8;
36949
37608
  }
36950
37609
  return;
36951
37610
  }
36952
37611
  if (pack === PACK_INT) {
36953
37612
  w.align4();
37613
+ const block = w.block((n - nulls) * 8);
37614
+ let offset = 0;
36954
37615
  for (let i = 0; i < n; i++) {
36955
37616
  if (bits[i >> 3] & 1 << (i & 7)) continue;
36956
37617
  const v = rows[i][col];
36957
- w.i64(typeof v === "bigint" ? v : BigInt(v));
37618
+ if (typeof v === "bigint") block.setBigInt64(offset, v, true);
37619
+ else {
37620
+ block.setUint32(offset, v >>> 0, true);
37621
+ block.setUint32(offset + 4, Math.floor(v / 4294967296) >>> 0, true);
37622
+ }
37623
+ offset += 8;
36958
37624
  }
36959
37625
  return;
36960
37626
  }
36961
37627
  if (pack === PACK_TEXT_INTERN) {
36962
37628
  w.align4();
37629
+ const block = w.block((n - nulls) * 4);
37630
+ let offset = 0;
36963
37631
  for (let i = 0; i < n; i++) {
36964
37632
  if (bits[i >> 3] & 1 << (i & 7)) continue;
36965
- w.u32(internId(rows[i][col]));
37633
+ block.setUint32(offset, internId(rows[i][col]), true);
37634
+ offset += 4;
36966
37635
  }
36967
37636
  return;
36968
37637
  }
36969
37638
  if (pack === PACK_TEXT_INLINE) {
36970
37639
  const offsets = [];
37640
+ const encoded = [];
36971
37641
  let blobLen = 0;
36972
37642
  for (let i = 0; i < n; i++) {
36973
37643
  if (bits[i >> 3] & 1 << (i & 7)) continue;
36974
37644
  offsets.push(blobLen);
36975
- blobLen += utf8Encode(rows[i][col]).length;
37645
+ const bytes = utf8Encode(rows[i][col]);
37646
+ encoded.push(bytes);
37647
+ blobLen += bytes.length;
36976
37648
  }
36977
37649
  writeVarintU32(w, offsets.length);
36978
37650
  for (const off of offsets) writeVarintU32(w, off);
36979
37651
  writeVarintU32(w, blobLen);
36980
- for (let i = 0; i < n; i++) {
36981
- if (bits[i >> 3] & 1 << (i & 7)) continue;
36982
- w.textBytes(rows[i][col]);
36983
- }
37652
+ for (const bytes of encoded) w.raw(bytes);
36984
37653
  return;
36985
37654
  }
36986
37655
  if (pack === PACK_BLOB) {
@@ -37180,7 +37849,7 @@ function compareNames(a, b) {
37180
37849
  function sortedValues(map) {
37181
37850
  return [...map.values()].sort((a, b) => compareNames(a.name, b.name));
37182
37851
  }
37183
- function forceAllEncodeIntern(pool, state, schemas) {
37852
+ function forceAllEncodeIntern(pool, state, schemas, internValues) {
37184
37853
  forceSchemaIntern(pool, state, schemas);
37185
37854
  for (const [k, v] of state.settings) {
37186
37855
  pool.forceId(k);
@@ -37192,18 +37861,7 @@ function forceAllEncodeIntern(pool, state, schemas) {
37192
37861
  }
37193
37862
  for (const schema of schemas) {
37194
37863
  pool.forceId(schema.name);
37195
- for (const table of sortedValues(schema.tables)) {
37196
- for (const row of table.allRows()) {
37197
- for (const d of row) forceDatumIntern(pool, d);
37198
- }
37199
- }
37200
- for (const view of sortedValues(schema.views)) {
37201
- if (view.matRows) {
37202
- for (const row of view.matRows) {
37203
- for (const d of row) forceDatumIntern(pool, d);
37204
- }
37205
- }
37206
- }
37864
+ for (const value of internValues.get(schema) ?? []) forceDatumIntern(pool, value);
37207
37865
  }
37208
37866
  }
37209
37867
  function forceDatumIntern(pool, value) {
@@ -37248,7 +37906,8 @@ function forceSchemaIntern(pool, state, schemas) {
37248
37906
  pool.forceId(table.name);
37249
37907
  pool.forceId(table.schema);
37250
37908
  forceBjvStrings(pool, {
37251
- xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
37909
+ // Only strings are interned here. Traversing every numeric xmin cannot add an id.
37910
+ xmins: [],
37252
37911
  name: table.name,
37253
37912
  schema: table.schema,
37254
37913
  columns: table.columns,