@crvouga/mockingbird-service-postgres 1.3.1 → 1.5.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/wire/cli.js CHANGED
@@ -3,6 +3,167 @@
3
3
  // src/wire/index.ts
4
4
  import { createServer } from "node:net";
5
5
 
6
+ // ../../core/dist/timeline.js
7
+ var BRANCH_PATTERN = /^[A-Za-z0-9_.-]{1,64}$/;
8
+ var Timeline = class {
9
+ maxCheckpoints;
10
+ now;
11
+ makeId;
12
+ nodes = /* @__PURE__ */ new Map();
13
+ heads = /* @__PURE__ */ new Map();
14
+ /** Unreferenced nodes in the exact order they became collectible. */
15
+ evictable = /* @__PURE__ */ new Set();
16
+ /** Branch heads plus explicit retainers. Absent means zero. */
17
+ references = /* @__PURE__ */ new Map();
18
+ explicitPins = /* @__PURE__ */ new Map();
19
+ sequence = 0;
20
+ constructor(options2 = {}) {
21
+ const max = options2.maxCheckpoints ?? 1e3;
22
+ if (!Number.isSafeInteger(max) || max < 1)
23
+ throw new RangeError("maxCheckpoints must be a positive integer");
24
+ this.maxCheckpoints = max;
25
+ this.now = options2.now ?? (() => this.sequence);
26
+ this.makeId = options2.id ?? ((sequence) => `cp_${sequence.toString(36).padStart(8, "0")}`);
27
+ }
28
+ /** Capture a new immutable value and move `branch` to it. */
29
+ commit(value, options2 = {}) {
30
+ const branch = options2.branch ?? "main";
31
+ this.assertBranch(branch);
32
+ const parent = options2.parent === void 0 ? this.heads.get(branch) ?? null : options2.parent;
33
+ if (parent !== null && !this.nodes.has(parent))
34
+ throw new RangeError(`no checkpoint ${parent}`);
35
+ const id = this.makeId(++this.sequence);
36
+ if (this.nodes.has(id))
37
+ throw new RangeError(`duplicate checkpoint id ${id}`);
38
+ const checkpoint = Object.freeze({ id, branch, parent, at: this.now(), value });
39
+ this.nodes.set(id, checkpoint);
40
+ this.moveHead(branch, id);
41
+ this.collect(this.maxCheckpoints);
42
+ return checkpoint;
43
+ }
44
+ /** Create a branch pointer without copying its checkpoint value. */
45
+ fork(branch, options2 = {}) {
46
+ this.assertBranch(branch);
47
+ if (this.heads.has(branch))
48
+ throw new RangeError(`branch already exists: ${branch}`);
49
+ const from = options2.from ?? this.heads.get("main");
50
+ if (from === void 0)
51
+ return void 0;
52
+ const checkpoint = this.get(from);
53
+ this.moveHead(branch, checkpoint.id);
54
+ return checkpoint;
55
+ }
56
+ /** Move a branch pointer to an existing checkpoint. */
57
+ checkout(branch, id) {
58
+ this.assertBranch(branch);
59
+ const checkpoint = this.get(id);
60
+ this.moveHead(branch, checkpoint.id);
61
+ return checkpoint;
62
+ }
63
+ get(id) {
64
+ const checkpoint = this.nodes.get(id);
65
+ if (!checkpoint)
66
+ throw new RangeError(`no checkpoint ${id}`);
67
+ return checkpoint;
68
+ }
69
+ head(branch = "main") {
70
+ const id = this.heads.get(branch);
71
+ return id === void 0 ? void 0 : this.get(id);
72
+ }
73
+ hasBranch(branch) {
74
+ return this.heads.has(branch);
75
+ }
76
+ branches() {
77
+ return Object.freeze(Object.fromEntries([...this.heads].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)));
78
+ }
79
+ checkpoints() {
80
+ return [...this.nodes.values()];
81
+ }
82
+ /** Number of retained checkpoints without allocating an array. */
83
+ get size() {
84
+ return this.nodes.size;
85
+ }
86
+ /** Pin a checkpoint independently of branch heads (used by compatibility snapshot handles). */
87
+ retain(id) {
88
+ const checkpoint = this.get(id);
89
+ this.explicitPins.set(id, (this.explicitPins.get(id) ?? 0) + 1);
90
+ this.addReference(id);
91
+ return checkpoint;
92
+ }
93
+ /** Release one explicit pin. Branch heads remain pinned until moved or deleted. */
94
+ release(id) {
95
+ if (!this.nodes.has(id))
96
+ return false;
97
+ const pins = this.explicitPins.get(id) ?? 0;
98
+ if (pins === 0)
99
+ return false;
100
+ if (pins === 1)
101
+ this.explicitPins.delete(id);
102
+ else
103
+ this.explicitPins.set(id, pins - 1);
104
+ this.removeReference(id);
105
+ this.collect(this.maxCheckpoints);
106
+ return true;
107
+ }
108
+ deleteBranch(branch) {
109
+ if (branch === "main")
110
+ throw new RangeError("cannot delete main branch");
111
+ const previous = this.heads.get(branch);
112
+ const deleted = this.heads.delete(branch);
113
+ if (previous !== void 0)
114
+ this.removeReference(previous);
115
+ this.collect(this.maxCheckpoints);
116
+ return deleted;
117
+ }
118
+ /**
119
+ * Deterministically discard oldest unpinned checkpoints. Collection is O(number removed):
120
+ * commits never scan pinned nodes or the retained history. Parents are metadata rather than a
121
+ * storage dependency, so a retained node remains usable after pruning.
122
+ */
123
+ gc(max = this.maxCheckpoints) {
124
+ if (!Number.isSafeInteger(max) || max < 1)
125
+ throw new RangeError("max must be a positive integer");
126
+ const removed = [];
127
+ this.collect(max, removed);
128
+ return removed;
129
+ }
130
+ collect(max, removed) {
131
+ while (this.nodes.size > max && this.evictable.size > 0) {
132
+ const id = this.evictable.values().next().value;
133
+ this.evictable.delete(id);
134
+ this.nodes.delete(id);
135
+ removed?.push(id);
136
+ }
137
+ }
138
+ moveHead(branch, id) {
139
+ const previous = this.heads.get(branch);
140
+ if (previous === id)
141
+ return;
142
+ if (previous !== void 0)
143
+ this.removeReference(previous);
144
+ this.heads.set(branch, id);
145
+ this.addReference(id);
146
+ }
147
+ addReference(id) {
148
+ this.references.set(id, (this.references.get(id) ?? 0) + 1);
149
+ this.evictable.delete(id);
150
+ }
151
+ removeReference(id) {
152
+ const next = (this.references.get(id) ?? 0) - 1;
153
+ if (next > 0)
154
+ this.references.set(id, next);
155
+ else {
156
+ this.references.delete(id);
157
+ if (this.nodes.has(id))
158
+ this.evictable.add(id);
159
+ }
160
+ }
161
+ assertBranch(branch) {
162
+ if (!BRANCH_PATTERN.test(branch))
163
+ throw new RangeError(`branch must match ${BRANCH_PATTERN}`);
164
+ }
165
+ };
166
+
6
167
  // src/errors/error.ts
7
168
  var CATEGORY_TO_SQLSTATE = {
8
169
  syntax: "42601",
@@ -4201,7 +4362,13 @@ var RowScope = class {
4201
4362
  }
4202
4363
  };
4203
4364
  function childEnv(env, outer) {
4204
- return { ctx: env.ctx, params: env.params, ctes: env.ctes, outer };
4365
+ return {
4366
+ ctx: env.ctx,
4367
+ params: env.params,
4368
+ ctes: env.ctes,
4369
+ outer,
4370
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
4371
+ };
4205
4372
  }
4206
4373
  function relationResult(rel2, command2) {
4207
4374
  const visible = rel2.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
@@ -8541,6 +8708,234 @@ function callScalarFunction(ctx, name, args2) {
8541
8708
  return fn(ctx, args2);
8542
8709
  }
8543
8710
 
8711
+ // src/functions/pgtrgm.ts
8712
+ var PGTRGM_BODY = "pg_trgm";
8713
+ var WORD_SIMILARITY_THRESHOLD = Math.fround(0.6);
8714
+ var GIN_TRGM_TYPES = /* @__PURE__ */ new Set(["text", "varchar"]);
8715
+ var WORD_CHAR = /[\p{L}\p{N}]+/gu;
8716
+ function pgTrgmSchema(state) {
8717
+ for (const schema of state.schemas.values()) {
8718
+ for (const fns of schema.functions.values()) {
8719
+ if (fns.some((fn) => fn.language === "internal" && fn.rawBody === PGTRGM_BODY)) return schema.name;
8720
+ }
8721
+ }
8722
+ return null;
8723
+ }
8724
+ function pgTrgmInstalled(state) {
8725
+ return pgTrgmSchema(state) !== null;
8726
+ }
8727
+ function installPgTrgm(state, schemaName) {
8728
+ const schema = state.getSchema(schemaName);
8729
+ const existing = schema.functions.get("similarity") ?? [];
8730
+ const fn = {
8731
+ name: "similarity",
8732
+ schema: schema.name,
8733
+ argNames: [null, null],
8734
+ argTypes: ["text", "text"],
8735
+ argDefaults: [null, null],
8736
+ returns: "float4",
8737
+ returnsSet: false,
8738
+ returnsTable: null,
8739
+ language: "internal",
8740
+ body: null,
8741
+ rawBody: PGTRGM_BODY,
8742
+ strict: true,
8743
+ oid: state.nextOid()
8744
+ };
8745
+ existing.push(fn);
8746
+ schema.functions.set("similarity", existing);
8747
+ }
8748
+ function uninstallPgTrgm(state) {
8749
+ let removed = false;
8750
+ for (const schema of state.schemas.values()) {
8751
+ for (const [name, fns] of [...schema.functions.entries()]) {
8752
+ const keep = fns.filter((fn) => fn.language !== "internal" || fn.rawBody !== PGTRGM_BODY);
8753
+ if (keep.length === fns.length) continue;
8754
+ removed = true;
8755
+ if (keep.length === 0) schema.functions.delete(name);
8756
+ else schema.functions.set(name, keep);
8757
+ }
8758
+ }
8759
+ return removed;
8760
+ }
8761
+ function evalPgTrgmFunction(ctx, fn, args2) {
8762
+ const ret = fn.returns ?? "float4";
8763
+ if (fn.strict && args2.some((arg) => arg.v === null)) return tv(ret, null);
8764
+ if (fn.name !== "similarity" || args2.length !== 2) {
8765
+ throw pgError("undefined_function", `function ${fn.schema}.${fn.name} is not implemented`, "42883");
8766
+ }
8767
+ const left = castTo(ctx, args2[0], "text");
8768
+ const right = castTo(ctx, args2[1], "text");
8769
+ if (left.v === null || right.v === null) return tv("float4", null);
8770
+ return tv("float4", trigramSimilarity(left.v, right.v));
8771
+ }
8772
+ function evalTrgmWordSimilar(ctx, left, right) {
8773
+ const missing = () => {
8774
+ throw pgError(
8775
+ "undefined_function",
8776
+ `operator does not exist: ${typeDisplayName(left.t)} <% ${typeDisplayName(right.t)}`
8777
+ );
8778
+ };
8779
+ if (!pgTrgmInstalled(ctx.state)) missing();
8780
+ if (!canImplicitCast(left.t, "text") || !canImplicitCast(right.t, "text")) missing();
8781
+ const a = castTo(ctx, left, "text");
8782
+ const b = castTo(ctx, right, "text");
8783
+ if (a.v === null || b.v === null) return tv("bool", null);
8784
+ const score = wordSimilarity(a.v, b.v);
8785
+ return tv("bool", score >= WORD_SIMILARITY_THRESHOLD);
8786
+ }
8787
+ function assertGinTrgmIndex(state, table, stmt) {
8788
+ const trgmCols = stmt.columns.filter((col2) => isGinTrgmOpclass(col2.opclass));
8789
+ if (trgmCols.length === 0) return;
8790
+ if (trgmCols.length !== stmt.columns.length || stmt.columns.length !== 1) {
8791
+ throw unsupported("multicolumn gin_trgm_ops");
8792
+ }
8793
+ const method = stmt.using ?? "btree";
8794
+ const col = trgmCols[0];
8795
+ const opclass = col.opclass;
8796
+ const label = opclass.join(".");
8797
+ if (method !== "gin" || !opclassVisible(state, opclass)) {
8798
+ throw pgError(
8799
+ "undefined_object",
8800
+ `operator class "${label}" does not exist for access method "${method}"`,
8801
+ "42704"
8802
+ );
8803
+ }
8804
+ if (stmt.unique) {
8805
+ throw pgError("feature_not_supported", `access method "gin" does not support unique indexes`, "0A000");
8806
+ }
8807
+ if (col.expr.type !== "colref" || col.expr.parts.length !== 1) {
8808
+ throw unsupported("expression gin_trgm_ops");
8809
+ }
8810
+ const index = table.columnIndex(col.expr.parts[0]);
8811
+ const typeId = table.columns[index].type.id;
8812
+ if (!GIN_TRGM_TYPES.has(typeId)) {
8813
+ throw pgError(
8814
+ "datatype_mismatch",
8815
+ `operator class "${label}" does not accept data type ${typeDisplayName(typeId)}`,
8816
+ "42804"
8817
+ );
8818
+ }
8819
+ }
8820
+ function isGinTrgmOpclass(opclass) {
8821
+ return opclass !== null && opclass[opclass.length - 1] === "gin_trgm_ops";
8822
+ }
8823
+ function opclassVisible(state, opclass) {
8824
+ const schema = pgTrgmSchema(state);
8825
+ if (schema === null || opclass[opclass.length - 1] !== "gin_trgm_ops") return false;
8826
+ if (opclass.length === 1) return state.effectiveSearchPath().includes(schema);
8827
+ if (opclass.length === 2) return opclass[0] === schema;
8828
+ return false;
8829
+ }
8830
+ function trigramSimilarity(left, right) {
8831
+ const a = uniqueSorted(orderedTrigrams(left));
8832
+ const b = uniqueSorted(orderedTrigrams(right));
8833
+ if (a.length === 0 || b.length === 0) return 0;
8834
+ let i = 0;
8835
+ let j = 0;
8836
+ let count = 0;
8837
+ while (i < a.length && j < b.length) {
8838
+ const cmp = a[i] < b[j] ? -1 : a[i] > b[j] ? 1 : 0;
8839
+ if (cmp < 0) i++;
8840
+ else if (cmp > 0) j++;
8841
+ else {
8842
+ count++;
8843
+ i++;
8844
+ j++;
8845
+ }
8846
+ }
8847
+ return calcSml(count, a.length, b.length);
8848
+ }
8849
+ function wordSimilarity(pattern, haystack) {
8850
+ const trg1 = orderedTrigrams(pattern);
8851
+ const trg2 = orderedTrigrams(haystack);
8852
+ const len1 = trg1.length;
8853
+ const len2 = trg2.length;
8854
+ if (len1 === 0 || len2 === 0) return 0;
8855
+ const positional = [];
8856
+ for (let i = 0; i < len1; i++) positional.push({ trg: trg1[i], index: -1 });
8857
+ for (let i = 0; i < len2; i++) positional.push({ trg: trg2[i], index: i });
8858
+ positional.sort((x, y) => x.trg < y.trg ? -1 : x.trg > y.trg ? 1 : x.index - y.index);
8859
+ const len = len1 + len2;
8860
+ const trg2indexes = new Array(len2);
8861
+ const found = new Array(len).fill(false);
8862
+ let ulen1 = 0;
8863
+ let group = 0;
8864
+ for (let i = 0; i < len; i++) {
8865
+ if (i > 0 && positional[i - 1].trg !== positional[i].trg) {
8866
+ if (found[group]) ulen1++;
8867
+ group++;
8868
+ }
8869
+ const index = positional[i].index;
8870
+ if (index >= 0) trg2indexes[index] = group;
8871
+ else found[group] = true;
8872
+ }
8873
+ if (found[group]) ulen1++;
8874
+ return iterateWordSimilarity(trg2indexes, found, ulen1, len2);
8875
+ }
8876
+ function orderedTrigrams(input) {
8877
+ const out = [];
8878
+ for (const match of input.matchAll(WORD_CHAR)) {
8879
+ const padded = ` ${match[0].toLowerCase()} `;
8880
+ for (let i = 0; i + 3 <= padded.length; i++) out.push(padded.slice(i, i + 3));
8881
+ }
8882
+ return out;
8883
+ }
8884
+ function uniqueSorted(trigrams) {
8885
+ return [...new Set(trigrams)].sort();
8886
+ }
8887
+ function calcSml(count, len1, len2) {
8888
+ const denom = len1 + len2 - count;
8889
+ if (denom <= 0) return 0;
8890
+ return Math.fround(count / denom);
8891
+ }
8892
+ function iterateWordSimilarity(trg2indexes, found, ulen1, len2) {
8893
+ const lastpos = new Array(found.length).fill(-1);
8894
+ let ulen2 = 0;
8895
+ let count = 0;
8896
+ let lower = -1;
8897
+ let smlrMax = 0;
8898
+ for (let i = 0; i < len2; i++) {
8899
+ const trgindex = trg2indexes[i];
8900
+ if (lower >= 0 || found[trgindex]) {
8901
+ if (lastpos[trgindex] < 0) {
8902
+ ulen2++;
8903
+ if (found[trgindex]) count++;
8904
+ }
8905
+ lastpos[trgindex] = i;
8906
+ }
8907
+ if (!found[trgindex]) continue;
8908
+ if (lower === -1) {
8909
+ lower = i;
8910
+ ulen2 = 1;
8911
+ }
8912
+ let smlrCur = calcSml(count, ulen1, ulen2);
8913
+ let tmpCount = count;
8914
+ let tmpUlen2 = ulen2;
8915
+ const prevLower = lower;
8916
+ for (let tmpLower = lower; tmpLower <= i; tmpLower++) {
8917
+ const smlrTmp = calcSml(tmpCount, ulen1, tmpUlen2);
8918
+ if (smlrTmp > smlrCur) {
8919
+ smlrCur = smlrTmp;
8920
+ ulen2 = tmpUlen2;
8921
+ lower = tmpLower;
8922
+ count = tmpCount;
8923
+ }
8924
+ const tmpTrgindex = trg2indexes[tmpLower];
8925
+ if (lastpos[tmpTrgindex] === tmpLower) {
8926
+ tmpUlen2--;
8927
+ if (found[tmpTrgindex]) tmpCount--;
8928
+ }
8929
+ }
8930
+ if (smlrCur > smlrMax) smlrMax = smlrCur;
8931
+ for (let tmpLower = prevLower; tmpLower < lower; tmpLower++) {
8932
+ const tmpTrgindex = trg2indexes[tmpLower];
8933
+ if (lastpos[tmpTrgindex] === tmpLower) lastpos[tmpTrgindex] = -1;
8934
+ }
8935
+ }
8936
+ return smlrMax;
8937
+ }
8938
+
8544
8939
  // src/expressions/operators.ts
8545
8940
  var NUM_LADDER = ["int2", "int4", "int8", "numeric", "float4", "float8"];
8546
8941
  function opNotExist(op, l, r) {
@@ -8684,6 +9079,8 @@ function evalBinary(ctx, op, l0, r0) {
8684
9079
  return evalJsonbDeletePath(ctx, l, r);
8685
9080
  case "@@":
8686
9081
  return evalTextSearchMatch(ctx, l, r);
9082
+ case "<%":
9083
+ return evalTrgmWordSimilar(ctx, l, r);
8687
9084
  default:
8688
9085
  opNotExist(op, l.t, r.t);
8689
9086
  }
@@ -10904,6 +11301,634 @@ function unifyAggType(a, b) {
10904
11301
  return unifyTypes(a, b) ?? a;
10905
11302
  }
10906
11303
 
11304
+ // src/functions/pgcrypto.ts
11305
+ var PGCRYPTO_BODY = "pgcrypto";
11306
+ var utf82 = new TextEncoder();
11307
+ var MD5_S = [
11308
+ 7,
11309
+ 12,
11310
+ 17,
11311
+ 22,
11312
+ 7,
11313
+ 12,
11314
+ 17,
11315
+ 22,
11316
+ 7,
11317
+ 12,
11318
+ 17,
11319
+ 22,
11320
+ 7,
11321
+ 12,
11322
+ 17,
11323
+ 22,
11324
+ 5,
11325
+ 9,
11326
+ 14,
11327
+ 20,
11328
+ 5,
11329
+ 9,
11330
+ 14,
11331
+ 20,
11332
+ 5,
11333
+ 9,
11334
+ 14,
11335
+ 20,
11336
+ 5,
11337
+ 9,
11338
+ 14,
11339
+ 20,
11340
+ 4,
11341
+ 11,
11342
+ 16,
11343
+ 23,
11344
+ 4,
11345
+ 11,
11346
+ 16,
11347
+ 23,
11348
+ 4,
11349
+ 11,
11350
+ 16,
11351
+ 23,
11352
+ 4,
11353
+ 11,
11354
+ 16,
11355
+ 23,
11356
+ 6,
11357
+ 10,
11358
+ 15,
11359
+ 21,
11360
+ 6,
11361
+ 10,
11362
+ 15,
11363
+ 21,
11364
+ 6,
11365
+ 10,
11366
+ 15,
11367
+ 21,
11368
+ 6,
11369
+ 10,
11370
+ 15,
11371
+ 21
11372
+ ];
11373
+ var MD5_K = new Uint32Array([
11374
+ 3614090360,
11375
+ 3905402710,
11376
+ 606105819,
11377
+ 3250441966,
11378
+ 4118548399,
11379
+ 1200080426,
11380
+ 2821735955,
11381
+ 4249261313,
11382
+ 1770035416,
11383
+ 2336552879,
11384
+ 4294925233,
11385
+ 2304563134,
11386
+ 1804603682,
11387
+ 4254626195,
11388
+ 2792965006,
11389
+ 1236535329,
11390
+ 4129170786,
11391
+ 3225465664,
11392
+ 643717713,
11393
+ 3921069994,
11394
+ 3593408605,
11395
+ 38016083,
11396
+ 3634488961,
11397
+ 3889429448,
11398
+ 568446438,
11399
+ 3275163606,
11400
+ 4107603335,
11401
+ 1163531501,
11402
+ 2850285829,
11403
+ 4243563512,
11404
+ 1735328473,
11405
+ 2368359562,
11406
+ 4294588738,
11407
+ 2272392833,
11408
+ 1839030562,
11409
+ 4259657740,
11410
+ 2763975236,
11411
+ 1272893353,
11412
+ 4139469664,
11413
+ 3200236656,
11414
+ 681279174,
11415
+ 3936430074,
11416
+ 3572445317,
11417
+ 76029189,
11418
+ 3654602809,
11419
+ 3873151461,
11420
+ 530742520,
11421
+ 3299628645,
11422
+ 4096336452,
11423
+ 1126891415,
11424
+ 2878612391,
11425
+ 4237533241,
11426
+ 1700485571,
11427
+ 2399980690,
11428
+ 4293915773,
11429
+ 2240044497,
11430
+ 1873313359,
11431
+ 4264355552,
11432
+ 2734768916,
11433
+ 1309151649,
11434
+ 4149444226,
11435
+ 3174756917,
11436
+ 718787259,
11437
+ 3951481745
11438
+ ]);
11439
+ var SHA256_K = new Uint32Array([
11440
+ 1116352408,
11441
+ 1899447441,
11442
+ 3049323471,
11443
+ 3921009573,
11444
+ 961987163,
11445
+ 1508970993,
11446
+ 2453635748,
11447
+ 2870763221,
11448
+ 3624381080,
11449
+ 310598401,
11450
+ 607225278,
11451
+ 1426881987,
11452
+ 1925078388,
11453
+ 2162078206,
11454
+ 2614888103,
11455
+ 3248222580,
11456
+ 3835390401,
11457
+ 4022224774,
11458
+ 264347078,
11459
+ 604807628,
11460
+ 770255983,
11461
+ 1249150122,
11462
+ 1555081692,
11463
+ 1996064986,
11464
+ 2554220882,
11465
+ 2821834349,
11466
+ 2952996808,
11467
+ 3210313671,
11468
+ 3336571891,
11469
+ 3584528711,
11470
+ 113926993,
11471
+ 338241895,
11472
+ 666307205,
11473
+ 773529912,
11474
+ 1294757372,
11475
+ 1396182291,
11476
+ 1695183700,
11477
+ 1986661051,
11478
+ 2177026350,
11479
+ 2456956037,
11480
+ 2730485921,
11481
+ 2820302411,
11482
+ 3259730800,
11483
+ 3345764771,
11484
+ 3516065817,
11485
+ 3600352804,
11486
+ 4094571909,
11487
+ 275423344,
11488
+ 430227734,
11489
+ 506948616,
11490
+ 659060556,
11491
+ 883997877,
11492
+ 958139571,
11493
+ 1322822218,
11494
+ 1537002063,
11495
+ 1747873779,
11496
+ 1955562222,
11497
+ 2024104815,
11498
+ 2227730452,
11499
+ 2361852424,
11500
+ 2428436474,
11501
+ 2756734187,
11502
+ 3204031479,
11503
+ 3329325298
11504
+ ]);
11505
+ var SHA512_K = [
11506
+ 0x428a2f98d728ae22n,
11507
+ 0x7137449123ef65cdn,
11508
+ 0xb5c0fbcfec4d3b2fn,
11509
+ 0xe9b5dba58189dbbcn,
11510
+ 0x3956c25bf348b538n,
11511
+ 0x59f111f1b605d019n,
11512
+ 0x923f82a4af194f9bn,
11513
+ 0xab1c5ed5da6d8118n,
11514
+ 0xd807aa98a3030242n,
11515
+ 0x12835b0145706fben,
11516
+ 0x243185be4ee4b28cn,
11517
+ 0x550c7dc3d5ffb4e2n,
11518
+ 0x72be5d74f27b896fn,
11519
+ 0x80deb1fe3b1696b1n,
11520
+ 0x9bdc06a725c71235n,
11521
+ 0xc19bf174cf692694n,
11522
+ 0xe49b69c19ef14ad2n,
11523
+ 0xefbe4786384f25e3n,
11524
+ 0x0fc19dc68b8cd5b5n,
11525
+ 0x240ca1cc77ac9c65n,
11526
+ 0x2de92c6f592b0275n,
11527
+ 0x4a7484aa6ea6e483n,
11528
+ 0x5cb0a9dcbd41fbd4n,
11529
+ 0x76f988da831153b5n,
11530
+ 0x983e5152ee66dfabn,
11531
+ 0xa831c66d2db43210n,
11532
+ 0xb00327c898fb213fn,
11533
+ 0xbf597fc7beef0ee4n,
11534
+ 0xc6e00bf33da88fc2n,
11535
+ 0xd5a79147930aa725n,
11536
+ 0x06ca6351e003826fn,
11537
+ 0x142929670a0e6e70n,
11538
+ 0x27b70a8546d22ffcn,
11539
+ 0x2e1b21385c26c926n,
11540
+ 0x4d2c6dfc5ac42aedn,
11541
+ 0x53380d139d95b3dfn,
11542
+ 0x650a73548baf63den,
11543
+ 0x766a0abb3c77b2a8n,
11544
+ 0x81c2c92e47edaee6n,
11545
+ 0x92722c851482353bn,
11546
+ 0xa2bfe8a14cf10364n,
11547
+ 0xa81a664bbc423001n,
11548
+ 0xc24b8b70d0f89791n,
11549
+ 0xc76c51a30654be30n,
11550
+ 0xd192e819d6ef5218n,
11551
+ 0xd69906245565a910n,
11552
+ 0xf40e35855771202an,
11553
+ 0x106aa07032bbd1b8n,
11554
+ 0x19a4c116b8d2d0c8n,
11555
+ 0x1e376c085141ab53n,
11556
+ 0x2748774cdf8eeb99n,
11557
+ 0x34b0bcb5e19b48a8n,
11558
+ 0x391c0cb3c5c95a63n,
11559
+ 0x4ed8aa4ae3418acbn,
11560
+ 0x5b9cca4f7763e373n,
11561
+ 0x682e6ff3d6b2b8a3n,
11562
+ 0x748f82ee5defb2fcn,
11563
+ 0x78a5636f43172f60n,
11564
+ 0x84c87814a1f0ab72n,
11565
+ 0x8cc702081a6439ecn,
11566
+ 0x90befffa23631e28n,
11567
+ 0xa4506cebde82bde9n,
11568
+ 0xbef9a3f7b2c67915n,
11569
+ 0xc67178f2e372532bn,
11570
+ 0xca273eceea26619cn,
11571
+ 0xd186b8c721c0c207n,
11572
+ 0xeada7dd6cde0eb1en,
11573
+ 0xf57d4f7fee6ed178n,
11574
+ 0x06f067aa72176fban,
11575
+ 0x0a637dc5a2c898a6n,
11576
+ 0x113f9804bef90daen,
11577
+ 0x1b710b35131c471bn,
11578
+ 0x28db77f523047d84n,
11579
+ 0x32caab7b40c72493n,
11580
+ 0x3c9ebe0a15c9bebcn,
11581
+ 0x431d67c49c100d4cn,
11582
+ 0x4cc5d4becb3e42b6n,
11583
+ 0x597f299cfc657e2an,
11584
+ 0x5fcb6fab3ad6faecn,
11585
+ 0x6c44198c4a475817n
11586
+ ];
11587
+ var MASK64 = (1n << 64n) - 1n;
11588
+ function rotl32(x, n) {
11589
+ return (x << n | x >>> 32 - n) >>> 0;
11590
+ }
11591
+ function rotr32(x, n) {
11592
+ return (x >>> n | x << 32 - n) >>> 0;
11593
+ }
11594
+ function rotr64(x, n) {
11595
+ return (x >> n | x << 64n - n) & MASK64;
11596
+ }
11597
+ function padBe(data, block, lengthBytes) {
11598
+ const bitLen = BigInt(data.length) * 8n;
11599
+ let len = data.length + 1 + lengthBytes;
11600
+ const rem = len % block;
11601
+ if (rem !== 0) len += block - rem;
11602
+ const out = new Uint8Array(len);
11603
+ out.set(data);
11604
+ out[data.length] = 128;
11605
+ const view = new DataView(out.buffer);
11606
+ view.setUint32(out.length - 8, Number(bitLen >> 32n & 0xffffffffn), false);
11607
+ view.setUint32(out.length - 4, Number(bitLen & 0xffffffffn), false);
11608
+ return out;
11609
+ }
11610
+ function padMd5(data) {
11611
+ const bitLen = BigInt(data.length) * 8n;
11612
+ let len = data.length + 1 + 8;
11613
+ const rem = len % 64;
11614
+ if (rem !== 0) len += 64 - rem;
11615
+ const out = new Uint8Array(len);
11616
+ out.set(data);
11617
+ out[data.length] = 128;
11618
+ const view = new DataView(out.buffer);
11619
+ view.setUint32(out.length - 8, Number(bitLen & 0xffffffffn), true);
11620
+ view.setUint32(out.length - 4, Number(bitLen >> 32n & 0xffffffffn), true);
11621
+ return out;
11622
+ }
11623
+ function md5(data) {
11624
+ const bytes = padMd5(data);
11625
+ const view = new DataView(bytes.buffer);
11626
+ let a0 = 1732584193;
11627
+ let b0 = 4023233417;
11628
+ let c0 = 2562383102;
11629
+ let d0 = 271733878;
11630
+ const m = new Uint32Array(16);
11631
+ for (let off = 0; off < bytes.length; off += 64) {
11632
+ for (let i = 0; i < 16; i++) m[i] = view.getUint32(off + i * 4, true);
11633
+ let a = a0;
11634
+ let b = b0;
11635
+ let c = c0;
11636
+ let d = d0;
11637
+ for (let i = 0; i < 64; i++) {
11638
+ let f;
11639
+ let g;
11640
+ if (i < 16) {
11641
+ f = b & c | ~b & d;
11642
+ g = i;
11643
+ } else if (i < 32) {
11644
+ f = d & b | ~d & c;
11645
+ g = (5 * i + 1) % 16;
11646
+ } else if (i < 48) {
11647
+ f = b ^ c ^ d;
11648
+ g = (3 * i + 5) % 16;
11649
+ } else {
11650
+ f = c ^ (b | ~d);
11651
+ g = 7 * i % 16;
11652
+ }
11653
+ const sum = f + a + MD5_K[i] + m[g] >>> 0;
11654
+ a = d;
11655
+ d = c;
11656
+ c = b;
11657
+ b = b + rotl32(sum, MD5_S[i]) >>> 0;
11658
+ }
11659
+ a0 = a0 + a >>> 0;
11660
+ b0 = b0 + b >>> 0;
11661
+ c0 = c0 + c >>> 0;
11662
+ d0 = d0 + d >>> 0;
11663
+ }
11664
+ const out = new Uint8Array(16);
11665
+ const ov = new DataView(out.buffer);
11666
+ ov.setUint32(0, a0, true);
11667
+ ov.setUint32(4, b0, true);
11668
+ ov.setUint32(8, c0, true);
11669
+ ov.setUint32(12, d0, true);
11670
+ return out;
11671
+ }
11672
+ function sha1(data) {
11673
+ const bytes = padBe(data, 64, 8);
11674
+ const view = new DataView(bytes.buffer);
11675
+ let h0 = 1732584193;
11676
+ let h1 = 4023233417;
11677
+ let h2 = 2562383102;
11678
+ let h3 = 271733878;
11679
+ let h4 = 3285377520;
11680
+ const w = new Uint32Array(80);
11681
+ for (let off = 0; off < bytes.length; off += 64) {
11682
+ for (let t = 0; t < 16; t++) w[t] = view.getUint32(off + t * 4, false);
11683
+ for (let t = 16; t < 80; t++) w[t] = rotl32(w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16], 1);
11684
+ let a = h0;
11685
+ let b = h1;
11686
+ let c = h2;
11687
+ let d = h3;
11688
+ let e = h4;
11689
+ for (let t = 0; t < 80; t++) {
11690
+ let f;
11691
+ let k;
11692
+ if (t < 20) {
11693
+ f = b & c | ~b & d;
11694
+ k = 1518500249;
11695
+ } else if (t < 40) {
11696
+ f = b ^ c ^ d;
11697
+ k = 1859775393;
11698
+ } else if (t < 60) {
11699
+ f = b & c | b & d | c & d;
11700
+ k = 2400959708;
11701
+ } else {
11702
+ f = b ^ c ^ d;
11703
+ k = 3395469782;
11704
+ }
11705
+ const temp = rotl32(a, 5) + f + e + k + w[t] >>> 0;
11706
+ e = d;
11707
+ d = c;
11708
+ c = rotl32(b, 30);
11709
+ b = a;
11710
+ a = temp;
11711
+ }
11712
+ h0 = h0 + a >>> 0;
11713
+ h1 = h1 + b >>> 0;
11714
+ h2 = h2 + c >>> 0;
11715
+ h3 = h3 + d >>> 0;
11716
+ h4 = h4 + e >>> 0;
11717
+ }
11718
+ const out = new Uint8Array(20);
11719
+ const ov = new DataView(out.buffer);
11720
+ ov.setUint32(0, h0, false);
11721
+ ov.setUint32(4, h1, false);
11722
+ ov.setUint32(8, h2, false);
11723
+ ov.setUint32(12, h3, false);
11724
+ ov.setUint32(16, h4, false);
11725
+ return out;
11726
+ }
11727
+ function sha256(data, sha224) {
11728
+ const bytes = padBe(data, 64, 8);
11729
+ const view = new DataView(bytes.buffer);
11730
+ let h0 = sha224 ? 3238371032 : 1779033703;
11731
+ let h1 = sha224 ? 914150663 : 3144134277;
11732
+ let h2 = sha224 ? 812702999 : 1013904242;
11733
+ let h3 = sha224 ? 4144912697 : 2773480762;
11734
+ let h4 = sha224 ? 4290775857 : 1359893119;
11735
+ let h5 = sha224 ? 1750603025 : 2600822924;
11736
+ let h6 = sha224 ? 1694076839 : 528734635;
11737
+ let h7 = sha224 ? 3204075428 : 1541459225;
11738
+ const w = new Uint32Array(64);
11739
+ for (let off = 0; off < bytes.length; off += 64) {
11740
+ for (let t = 0; t < 16; t++) w[t] = view.getUint32(off + t * 4, false);
11741
+ for (let t = 16; t < 64; t++) {
11742
+ const x15 = w[t - 15];
11743
+ const x2 = w[t - 2];
11744
+ const s0 = rotr32(x15, 7) ^ rotr32(x15, 18) ^ x15 >>> 3;
11745
+ const s1 = rotr32(x2, 17) ^ rotr32(x2, 19) ^ x2 >>> 10;
11746
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1 >>> 0;
11747
+ }
11748
+ let a = h0;
11749
+ let b = h1;
11750
+ let c = h2;
11751
+ let d = h3;
11752
+ let e = h4;
11753
+ let f = h5;
11754
+ let g = h6;
11755
+ let h = h7;
11756
+ for (let t = 0; t < 64; t++) {
11757
+ const s1 = rotr32(e, 6) ^ rotr32(e, 11) ^ rotr32(e, 25);
11758
+ const ch = e & f ^ ~e & g;
11759
+ const t1 = h + s1 + ch + SHA256_K[t] + w[t] >>> 0;
11760
+ const s0 = rotr32(a, 2) ^ rotr32(a, 13) ^ rotr32(a, 22);
11761
+ const maj = a & b ^ a & c ^ b & c;
11762
+ const t2 = s0 + maj >>> 0;
11763
+ h = g;
11764
+ g = f;
11765
+ f = e;
11766
+ e = d + t1 >>> 0;
11767
+ d = c;
11768
+ c = b;
11769
+ b = a;
11770
+ a = t1 + t2 >>> 0;
11771
+ }
11772
+ h0 = h0 + a >>> 0;
11773
+ h1 = h1 + b >>> 0;
11774
+ h2 = h2 + c >>> 0;
11775
+ h3 = h3 + d >>> 0;
11776
+ h4 = h4 + e >>> 0;
11777
+ h5 = h5 + f >>> 0;
11778
+ h6 = h6 + g >>> 0;
11779
+ h7 = h7 + h >>> 0;
11780
+ }
11781
+ const words = sha224 ? 7 : 8;
11782
+ const out = new Uint8Array(words * 4);
11783
+ const ov = new DataView(out.buffer);
11784
+ const hs = [h0, h1, h2, h3, h4, h5, h6, h7];
11785
+ for (let i = 0; i < words; i++) ov.setUint32(i * 4, hs[i], false);
11786
+ return out;
11787
+ }
11788
+ function readUint64BE(view, offset) {
11789
+ return BigInt(view.getUint32(offset, false)) << 32n | BigInt(view.getUint32(offset + 4, false));
11790
+ }
11791
+ function sha512(data, sha384) {
11792
+ const bytes = padBe(data, 128, 16);
11793
+ const view = new DataView(bytes.buffer);
11794
+ let h0 = sha384 ? 0xcbbb9d5dc1059ed8n : 0x6a09e667f3bcc908n;
11795
+ let h1 = sha384 ? 0x629a292a367cd507n : 0xbb67ae8584caa73bn;
11796
+ let h2 = sha384 ? 0x9159015a3070dd17n : 0x3c6ef372fe94f82bn;
11797
+ let h3 = sha384 ? 0x152fecd8f70e5939n : 0xa54ff53a5f1d36f1n;
11798
+ let h4 = sha384 ? 0x67332667ffc00b31n : 0x510e527fade682d1n;
11799
+ let h5 = sha384 ? 0x8eb44a8768581511n : 0x9b05688c2b3e6c1fn;
11800
+ let h6 = sha384 ? 0xdb0c2e0d64f98fa7n : 0x1f83d9abfb41bd6bn;
11801
+ let h7 = sha384 ? 0x47b5481dbefa4fa4n : 0x5be0cd19137e2179n;
11802
+ const w = new Array(80);
11803
+ for (let off = 0; off < bytes.length; off += 128) {
11804
+ for (let t = 0; t < 16; t++) w[t] = readUint64BE(view, off + t * 8);
11805
+ for (let t = 16; t < 80; t++) {
11806
+ const x15 = w[t - 15];
11807
+ const x2 = w[t - 2];
11808
+ const s0 = rotr64(x15, 1n) ^ rotr64(x15, 8n) ^ x15 >> 7n;
11809
+ const s1 = rotr64(x2, 19n) ^ rotr64(x2, 61n) ^ x2 >> 6n;
11810
+ w[t] = w[t - 16] + s0 + w[t - 7] + s1 & MASK64;
11811
+ }
11812
+ let a = h0;
11813
+ let b = h1;
11814
+ let c = h2;
11815
+ let d = h3;
11816
+ let e = h4;
11817
+ let f = h5;
11818
+ let g = h6;
11819
+ let h = h7;
11820
+ for (let t = 0; t < 80; t++) {
11821
+ const s1 = rotr64(e, 14n) ^ rotr64(e, 18n) ^ rotr64(e, 41n);
11822
+ const ch = e & f ^ ~e & g & MASK64;
11823
+ const t1 = h + s1 + ch + SHA512_K[t] + w[t] & MASK64;
11824
+ const s0 = rotr64(a, 28n) ^ rotr64(a, 34n) ^ rotr64(a, 39n);
11825
+ const maj = a & b ^ a & c ^ b & c;
11826
+ const t2 = s0 + maj & MASK64;
11827
+ h = g;
11828
+ g = f;
11829
+ f = e;
11830
+ e = d + t1 & MASK64;
11831
+ d = c;
11832
+ c = b;
11833
+ b = a;
11834
+ a = t1 + t2 & MASK64;
11835
+ }
11836
+ h0 = h0 + a & MASK64;
11837
+ h1 = h1 + b & MASK64;
11838
+ h2 = h2 + c & MASK64;
11839
+ h3 = h3 + d & MASK64;
11840
+ h4 = h4 + e & MASK64;
11841
+ h5 = h5 + f & MASK64;
11842
+ h6 = h6 + g & MASK64;
11843
+ h7 = h7 + h & MASK64;
11844
+ }
11845
+ const words = sha384 ? 6 : 8;
11846
+ const out = new Uint8Array(words * 8);
11847
+ const ov = new DataView(out.buffer);
11848
+ const hs = [h0, h1, h2, h3, h4, h5, h6, h7];
11849
+ for (let i = 0; i < words; i++) {
11850
+ const word = hs[i];
11851
+ ov.setUint32(i * 8, Number(word >> 32n & 0xffffffffn), false);
11852
+ ov.setUint32(i * 8 + 4, Number(word & 0xffffffffn), false);
11853
+ }
11854
+ return out;
11855
+ }
11856
+ function digestBytes(data, algorithm) {
11857
+ switch (algorithm.toLowerCase().replaceAll("-", "")) {
11858
+ case "md5":
11859
+ return md5(data);
11860
+ case "sha1":
11861
+ return sha1(data);
11862
+ case "sha224":
11863
+ return sha256(data, true);
11864
+ case "sha256":
11865
+ return sha256(data, false);
11866
+ case "sha384":
11867
+ return sha512(data, true);
11868
+ case "sha512":
11869
+ return sha512(data, false);
11870
+ default:
11871
+ throw pgError("invalid_parameter_value", `Cannot use "${algorithm}": No such hash algorithm`, "22023");
11872
+ }
11873
+ }
11874
+ function pgcryptoInstalled(state) {
11875
+ for (const schema of state.schemas.values()) {
11876
+ for (const fns of schema.functions.values()) {
11877
+ if (fns.some((fn) => fn.language === "internal" && fn.rawBody === PGCRYPTO_BODY)) return true;
11878
+ }
11879
+ }
11880
+ return false;
11881
+ }
11882
+ function installPgcrypto(state, schemaName) {
11883
+ const schema = state.getSchema(schemaName);
11884
+ const existing = schema.functions.get("digest") ?? [];
11885
+ const arg0Types = ["text", "bytea"];
11886
+ for (const arg0 of arg0Types) {
11887
+ const fn = {
11888
+ name: "digest",
11889
+ schema: schema.name,
11890
+ argNames: [null, null],
11891
+ argTypes: [arg0, "text"],
11892
+ argDefaults: [null, null],
11893
+ returns: "bytea",
11894
+ returnsSet: false,
11895
+ returnsTable: null,
11896
+ language: "internal",
11897
+ body: null,
11898
+ rawBody: PGCRYPTO_BODY,
11899
+ strict: true,
11900
+ oid: state.nextOid()
11901
+ };
11902
+ existing.push(fn);
11903
+ }
11904
+ schema.functions.set("digest", existing);
11905
+ }
11906
+ function uninstallPgcrypto(state) {
11907
+ let removed = false;
11908
+ for (const schema of state.schemas.values()) {
11909
+ for (const [name, fns] of [...schema.functions.entries()]) {
11910
+ const keep = fns.filter((fn) => fn.language !== "internal" || fn.rawBody !== PGCRYPTO_BODY);
11911
+ if (keep.length === fns.length) continue;
11912
+ removed = true;
11913
+ if (keep.length === 0) schema.functions.delete(name);
11914
+ else schema.functions.set(name, keep);
11915
+ }
11916
+ }
11917
+ return removed;
11918
+ }
11919
+ function evalPgcryptoFunction(ctx, fn, args2) {
11920
+ const ret = fn.returns ?? "bytea";
11921
+ if (fn.strict && args2.some((arg) => arg.v === null)) return tv(ret, null);
11922
+ if (fn.name !== "digest" || args2.length !== 2) {
11923
+ throw pgError("undefined_function", `function ${fn.schema}.${fn.name} is not implemented`, "42883");
11924
+ }
11925
+ const data = castTo(ctx, args2[0], fn.argTypes[0] ?? "bytea", {});
11926
+ const algorithm = castTo(ctx, args2[1], "text", {});
11927
+ if (data.v === null || algorithm.v === null) return tv("bytea", null);
11928
+ const bytes = fn.argTypes[0] === "bytea" ? data.v : utf82.encode(data.v);
11929
+ return tv("bytea", digestBytes(bytes, algorithm.v));
11930
+ }
11931
+
10907
11932
  // src/functions/srf.ts
10908
11933
  function jsonInput(ctx, a) {
10909
11934
  void ctx;
@@ -13097,10 +14122,32 @@ var Parser = class {
13097
14122
  }
13098
14123
  if (this.atKw("extension")) {
13099
14124
  this.pos++;
13100
- this.parseIfNotExists();
14125
+ const ifNotExists = this.parseIfNotExists();
13101
14126
  const name = this.ident(true);
13102
- while (!this.atPunct(";") && this.peek().type !== "eof") this.pos++;
13103
- throw unsupported(`extension "${name}"`);
14127
+ let schema = null;
14128
+ let version = null;
14129
+ let cascade = false;
14130
+ this.eatKw("with");
14131
+ while (!this.atPunct(";") && this.peek().type !== "eof") {
14132
+ if (this.eatKw("schema")) {
14133
+ schema = this.ident(true);
14134
+ continue;
14135
+ }
14136
+ if (this.eatKw("version")) {
14137
+ const token = this.next();
14138
+ if (token.type !== "string" && token.type !== "ident" && token.type !== "quoted_ident") {
14139
+ this.errorAt(token, "expected extension version");
14140
+ }
14141
+ version = token.value;
14142
+ continue;
14143
+ }
14144
+ if (this.eatKw("cascade")) {
14145
+ cascade = true;
14146
+ continue;
14147
+ }
14148
+ throw unsupported("CREATE EXTENSION option");
14149
+ }
14150
+ return { type: "create_extension", name, ifNotExists, schema, version, cascade };
13104
14151
  }
13105
14152
  if (this.atKw("database")) throw unsupported("CREATE DATABASE");
13106
14153
  if (this.atKw("role") || this.atKw("user") || this.atKw("group")) throw unsupported("roles");
@@ -13577,7 +14624,11 @@ var Parser = class {
13577
14624
  let opclass = null;
13578
14625
  const t = this.peek();
13579
14626
  if (t.type === "ident" && !RESERVED.has(t.value) && !["asc", "desc", "nulls", "with", "where", "include"].includes(t.value)) {
13580
- opclass = this.ident();
14627
+ opclass = [this.ident()];
14628
+ while (this.atPunct(".")) {
14629
+ this.pos++;
14630
+ opclass.push(this.ident(true));
14631
+ }
13581
14632
  }
13582
14633
  let dir = null;
13583
14634
  if (this.eatKw("asc")) dir = "asc";
@@ -15813,7 +16864,13 @@ function runStmt(env, stmt, vars, emit, tableNames) {
15813
16864
  return;
15814
16865
  }
15815
16866
  case "for": {
15816
- const forEnv = { ctx: env.ctx, params: env.params, ctes: env.ctes, outer: vars.scope() };
16867
+ const forEnv = {
16868
+ ctx: env.ctx,
16869
+ params: env.params,
16870
+ ctes: env.ctes,
16871
+ outer: vars.scope(),
16872
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
16873
+ };
15817
16874
  const rel2 = executeSelectStmt(forEnv, stmt.query);
15818
16875
  for (const row of rel2.rows) {
15819
16876
  for (let i = 0; i < stmt.targets.length; i++) {
@@ -15855,7 +16912,13 @@ function initVars(env, fn, bound, program) {
15855
16912
  if (fn.returnsTable) {
15856
16913
  for (const c of fn.returnsTable) vars.declare(c.name, c.type, null);
15857
16914
  }
15858
- const seed = () => ({ ctx: env.ctx, params: bound, ctes: /* @__PURE__ */ new Map(), outer: vars.scope() });
16915
+ const seed = () => ({
16916
+ ctx: env.ctx,
16917
+ params: bound,
16918
+ ctes: /* @__PURE__ */ new Map(),
16919
+ outer: vars.scope(),
16920
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
16921
+ });
15859
16922
  for (const d of program.decls) {
15860
16923
  const id = resolveTypeName(env.ctx.state, d.typeName).column.id;
15861
16924
  let val = null;
@@ -15868,7 +16931,13 @@ function initVars(env, fn, bound, program) {
15868
16931
  return vars;
15869
16932
  }
15870
16933
  function plpgsqlEnv(env, bound, vars) {
15871
- return { ctx: env.ctx, params: bound, ctes: /* @__PURE__ */ new Map(), outer: vars.scope() };
16934
+ return {
16935
+ ctx: env.ctx,
16936
+ params: bound,
16937
+ ctes: /* @__PURE__ */ new Map(),
16938
+ outer: vars.scope(),
16939
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
16940
+ };
15872
16941
  }
15873
16942
  function callPlpgsqlScalar(env, fn, args2) {
15874
16943
  const retT = fn.returns ?? "text";
@@ -16467,7 +17536,13 @@ function functionEnv(env, fn, args2) {
16467
17536
  bound.push(castTo(env.ctx, evalScalar(env, null, dflt), fn.argTypes[i], {}));
16468
17537
  }
16469
17538
  }
16470
- const fnEnv = { ctx: env.ctx, params: bound, ctes: /* @__PURE__ */ new Map(), outer: null };
17539
+ const fnEnv = {
17540
+ ctx: env.ctx,
17541
+ params: bound,
17542
+ ctes: /* @__PURE__ */ new Map(),
17543
+ outer: null,
17544
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
17545
+ };
16471
17546
  const namedCols = fn.argNames.map((n, i) => ({ n, i })).filter((x) => x.n !== null);
16472
17547
  if (namedCols.length > 0) {
16473
17548
  const cols = namedCols.map(({ n, i }) => ({ name: n, type: fn.argTypes[i] ?? "text", table: null }));
@@ -16493,6 +17568,10 @@ function callSqlFunctionScalar(env, fn, args2) {
16493
17568
  if (fn.language === "plpgsql") {
16494
17569
  return callPlpgsqlScalar(env, fn, args2);
16495
17570
  }
17571
+ if (fn.language === "internal") {
17572
+ if (fn.rawBody === "pg_trgm") return evalPgTrgmFunction(env.ctx, fn, args2);
17573
+ return evalPgcryptoFunction(env.ctx, fn, args2);
17574
+ }
16496
17575
  if (fn.language === "js") {
16497
17576
  if (!fn.jsImpl) {
16498
17577
  throw pgError("undefined_function", `JavaScript function ${fn.name} is not registered`, "42883");
@@ -16569,7 +17648,13 @@ function applyWith(env, w) {
16569
17648
  if (!w) return env;
16570
17649
  const ctes = new Map(env.ctes);
16571
17650
  for (const cte of w.ctes) {
16572
- const scopedEnv = { ctx: env.ctx, params: env.params, ctes, outer: env.outer };
17651
+ const scopedEnv = {
17652
+ ctx: env.ctx,
17653
+ params: env.params,
17654
+ ctes,
17655
+ outer: env.outer,
17656
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
17657
+ };
16573
17658
  let rel2;
16574
17659
  if (w.recursive && cte.query.type === "select" && cte.query.body.type === "setop" && cte.query.body.op === "union" && referencesRelation(cte.query.body.right, cte.name)) {
16575
17660
  rel2 = executeRecursiveCte(scopedEnv, cte, cte.query);
@@ -16584,7 +17669,13 @@ function applyWith(env, w) {
16584
17669
  }
16585
17670
  ctes.set(cte.name, applyCteColumnNames(rel2, cte));
16586
17671
  }
16587
- return { ctx: env.ctx, params: env.params, ctes, outer: env.outer };
17672
+ return {
17673
+ ctx: env.ctx,
17674
+ params: env.params,
17675
+ ctes,
17676
+ outer: env.outer,
17677
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
17678
+ };
16588
17679
  }
16589
17680
  var MAX_RECURSION_ITERATIONS = 2e5;
16590
17681
  var MAX_RECURSION_ROWS = 5e6;
@@ -16616,7 +17707,13 @@ function executeRecursiveCte(env, cte, query) {
16616
17707
  }
16617
17708
  const iterCtes = new Map(env.ctes);
16618
17709
  iterCtes.set(cte.name, { columns, rows: working });
16619
- const iterEnv = { ctx: env.ctx, params: env.params, ctes: iterCtes, outer: env.outer };
17710
+ const iterEnv = {
17711
+ ctx: env.ctx,
17712
+ params: env.params,
17713
+ ctes: iterCtes,
17714
+ outer: env.outer,
17715
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
17716
+ };
16620
17717
  const step = executeBody(iterEnv, body.right);
16621
17718
  if (step.columns.length !== columns.length) {
16622
17719
  throw pgError("syntax", "each UNION query must have the same number of columns", "42601");
@@ -16688,7 +17785,7 @@ function materializeItem(env, item, scope) {
16688
17785
  if (view) {
16689
17786
  let rel2;
16690
17787
  if (view.materialized) {
16691
- if (view.matRows === null || view.matColumns === null) {
17788
+ if (view.matColumns === null || view.matRows === null && !env.allowUnpopulatedMatviews) {
16692
17789
  throw pgError(
16693
17790
  "object_not_in_prerequisite_state",
16694
17791
  `materialized view "${view.name}" has not been populated`,
@@ -16697,10 +17794,16 @@ function materializeItem(env, item, scope) {
16697
17794
  }
16698
17795
  rel2 = {
16699
17796
  columns: view.matColumns.map((c) => ({ name: c.name, type: c.type, table: label })),
16700
- rows: view.matRows
17797
+ rows: view.matRows ?? []
16701
17798
  };
16702
17799
  } else {
16703
- const viewEnv = { ctx: env.ctx, params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
17800
+ const viewEnv = {
17801
+ ctx: env.ctx,
17802
+ params: null,
17803
+ ctes: /* @__PURE__ */ new Map(),
17804
+ outer: null,
17805
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
17806
+ };
16704
17807
  rel2 = executeSelectStmt(viewEnv, view.query);
16705
17808
  rel2 = {
16706
17809
  columns: rel2.columns.map((c, i) => ({
@@ -17793,7 +18896,7 @@ function setOpRelation(env, op) {
17793
18896
  return t === UNKNOWN ? "text" : t;
17794
18897
  });
17795
18898
  const columns = left.columns.map((c, i) => ({ name: c.name, type: types[i], table: null }));
17796
- const normalize = (rel2) => rel2.rows.map(
18899
+ const normalize2 = (rel2) => rel2.rows.map(
17797
18900
  (row) => row.map((v, i) => {
17798
18901
  if (v === null) return null;
17799
18902
  const srcT = rel2.columns[i].type;
@@ -17801,8 +18904,8 @@ function setOpRelation(env, op) {
17801
18904
  return castTo(ctx, tv(srcT === UNKNOWN ? "text" : srcT, v), types[i], {}).v;
17802
18905
  })
17803
18906
  );
17804
- const lrows = normalize(left);
17805
- const rrows = normalize(right);
18907
+ const lrows = normalize2(left);
18908
+ const rrows = normalize2(right);
17806
18909
  const keyOf = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
17807
18910
  let rows;
17808
18911
  switch (op.op) {
@@ -18835,7 +19938,13 @@ function applyUpdateSets(env, table, sets, scope, row) {
18835
19938
  });
18836
19939
  if (typeof set.value === "object" && "kind" in set.value && set.value.kind === "row_subquery") {
18837
19940
  const rel2 = executeSelectStmt(
18838
- { ctx: env.ctx, params: env.params, ctes: env.ctes, outer: scope },
19941
+ {
19942
+ ctx: env.ctx,
19943
+ params: env.params,
19944
+ ctes: env.ctes,
19945
+ outer: scope,
19946
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
19947
+ },
18839
19948
  set.value.query
18840
19949
  );
18841
19950
  if (rel2.rows.length > 1) {
@@ -20618,6 +21727,9 @@ function executeTrigger(env, table, trigger, _event, oldRow, newRow) {
20618
21727
  setTriggerExecutor(executeTrigger);
20619
21728
 
20620
21729
  // src/executor/ddl.ts
21730
+ function matviewQueryEnv(env, allowUnpopulatedMatviews) {
21731
+ return { ctx: env.ctx, params: null, ctes: /* @__PURE__ */ new Map(), outer: null, allowUnpopulatedMatviews };
21732
+ }
20621
21733
  function targetSchema(env, parts) {
20622
21734
  const state = env.ctx.state;
20623
21735
  if (parts.length >= 2) {
@@ -21021,6 +22133,7 @@ function executeCreateIndex(env, stmt) {
21021
22133
  }
21022
22134
  }
21023
22135
  }
22136
+ assertGinTrgmIndex(state, table, stmt);
21024
22137
  schema.indexes.set(name, {
21025
22138
  name,
21026
22139
  schema: schema.name,
@@ -21065,7 +22178,7 @@ function executeCreateView(env, stmt) {
21065
22178
  let matRows = null;
21066
22179
  let matColumns = null;
21067
22180
  if (stmt.materialized) {
21068
- const rel2 = executeSelectStmt({ ctx: env.ctx, params: null, ctes: /* @__PURE__ */ new Map(), outer: null }, stmt.query);
22181
+ const rel2 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), stmt.query);
21069
22182
  matColumns = rel2.columns.map((c, i) => ({
21070
22183
  name: stmt.columns?.[i] ?? c.name,
21071
22184
  type: c.type === UNKNOWN ? "text" : c.type
@@ -21091,7 +22204,7 @@ function executeRefreshMatView(env, stmt) {
21091
22204
  throw pgError("undefined_table", `materialized view "${stmt.name.join(".")}" does not exist`, "42P01");
21092
22205
  }
21093
22206
  const view = env.ctx.state.ensureWritableView(found);
21094
- const rel2 = executeSelectStmt({ ctx: env.ctx, params: null, ctes: /* @__PURE__ */ new Map(), outer: null }, view.query);
22207
+ const rel2 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), view.query);
21095
22208
  view.matColumns = rel2.columns.map((c, i) => ({
21096
22209
  name: view.columns?.[i] ?? c.name,
21097
22210
  type: c.type === UNKNOWN ? "text" : c.type
@@ -21099,6 +22212,32 @@ function executeRefreshMatView(env, stmt) {
21099
22212
  view.matRows = stmt.withData ? rel2.rows : null;
21100
22213
  return commandResult("REFRESH MATERIALIZED VIEW", 0);
21101
22214
  }
22215
+ function executeCreateExtension(env, stmt) {
22216
+ const state = env.ctx.state;
22217
+ const schemaName = stmt.schema ?? state.currentSchema();
22218
+ const install = () => {
22219
+ if (stmt.name === "pgcrypto") {
22220
+ if (pgcryptoInstalled(state)) return "exists";
22221
+ installPgcrypto(state, state.getSchema(schemaName).name);
22222
+ return "installed";
22223
+ }
22224
+ if (stmt.name === "pg_trgm") {
22225
+ if (pgTrgmInstalled(state)) return "exists";
22226
+ installPgTrgm(state, state.getSchema(schemaName).name);
22227
+ return "installed";
22228
+ }
22229
+ return "unsupported";
22230
+ };
22231
+ const outcome = install();
22232
+ if (outcome === "unsupported") {
22233
+ throw pgError("feature_not_supported", `extension "${stmt.name}" is not available`, "0A000");
22234
+ }
22235
+ if (outcome === "exists") {
22236
+ if (stmt.ifNotExists) return commandResult("CREATE EXTENSION", 0);
22237
+ throw pgError("duplicate_object", `extension "${stmt.name}" already exists`, "42710");
22238
+ }
22239
+ return commandResult("CREATE EXTENSION", 0);
22240
+ }
21102
22241
  function executeCreateSchema(env, stmt) {
21103
22242
  const state = env.ctx.state;
21104
22243
  if (state.schemas.has(stmt.name)) {
@@ -21887,8 +23026,19 @@ function executeDrop(env, stmt) {
21887
23026
  table.triggers.splice(idx, 1);
21888
23027
  break;
21889
23028
  }
21890
- case "extension":
21891
- break;
23029
+ case "extension": {
23030
+ const ext = parts[parts.length - 1];
23031
+ if (ext === "pgcrypto" && pgcryptoInstalled(state)) {
23032
+ uninstallPgcrypto(state);
23033
+ break;
23034
+ }
23035
+ if (ext === "pg_trgm" && pgTrgmInstalled(state)) {
23036
+ uninstallPgTrgm(state);
23037
+ break;
23038
+ }
23039
+ if (stmt.ifExists) break;
23040
+ throw pgError("undefined_object", `extension "${ext}" does not exist`, "42704");
23041
+ }
21892
23042
  }
21893
23043
  }
21894
23044
  const label = stmt.kind === "materialized_view" ? "MATERIALIZED VIEW" : stmt.kind.toUpperCase();
@@ -21970,6 +23120,8 @@ function executeStatement(env, stmt) {
21970
23120
  return executeAlterSequence(env, stmt);
21971
23121
  case "create_schema":
21972
23122
  return executeCreateSchema(env, stmt);
23123
+ case "create_extension":
23124
+ return executeCreateExtension(env, stmt);
21973
23125
  case "create_enum":
21974
23126
  return executeCreateEnum(env, stmt);
21975
23127
  case "alter_enum":
@@ -22125,6 +23277,9 @@ var ADOPT = /* @__PURE__ */ Symbol("postgres-mem.adopt");
22125
23277
  function isAdopted(value) {
22126
23278
  return ADOPT in value;
22127
23279
  }
23280
+ function project(point) {
23281
+ return { id: point.id, branch: point.branch, parent: point.parent, at: point.at };
23282
+ }
22128
23283
  var Database = class {
22129
23284
  /** @internal Engine catalog, tables, session settings. */
22130
23285
  state;
@@ -22145,6 +23300,10 @@ var Database = class {
22145
23300
  closed = false;
22146
23301
  transactionSequence = 0;
22147
23302
  apiTransactionDepth = 0;
23303
+ /** @internal Shared checkpoint DAG. Omitted from published declarations. */
23304
+ timeline;
23305
+ historyBranch = "main";
23306
+ originId = "";
22148
23307
  constructor(options2 = {}) {
22149
23308
  if (isAdopted(options2)) {
22150
23309
  this.seed = options2.seed;
@@ -22157,16 +23316,23 @@ var Database = class {
22157
23316
  this.state.prng = this.prng;
22158
23317
  this.state.clock = () => this.now();
22159
23318
  this.transactions = txManagerFor(this.state);
22160
- return;
23319
+ } else {
23320
+ this.seed = options2.seed ?? DEFAULT_DATABASE_SEED;
23321
+ this.randomMode = options2.random ?? "deterministic";
23322
+ this.systemClock = options2.now === "system";
23323
+ this.int8Mode = options2.int8 ?? "bigint";
23324
+ this.prng = this.randomMode === "os" ? new OsEntropy() : new Prng(this.seed);
23325
+ this.now = resolveClock(options2.now);
23326
+ this.state = new DatabaseState(this.prng, () => this.now());
23327
+ this.transactions = txManagerFor(this.state);
22161
23328
  }
22162
- this.seed = options2.seed ?? DEFAULT_DATABASE_SEED;
22163
- this.randomMode = options2.random ?? "deterministic";
22164
- this.systemClock = options2.now === "system";
22165
- this.int8Mode = options2.int8 ?? "bigint";
22166
- this.prng = this.randomMode === "os" ? new OsEntropy() : new Prng(this.seed);
22167
- this.now = resolveClock(options2.now);
22168
- this.state = new DatabaseState(this.prng, () => this.now());
22169
- this.transactions = txManagerFor(this.state);
23329
+ this.timeline = new Timeline({
23330
+ now: () => this.now().getTime(),
23331
+ ...options2.maxCheckpoints !== void 0 ? { maxCheckpoints: options2.maxCheckpoints } : {}
23332
+ });
23333
+ const origin = this.timeline.commit(this.captureLive());
23334
+ this.originId = origin.id;
23335
+ this.timeline.retain(origin.id);
22170
23336
  }
22171
23337
  /**
22172
23338
  * Execute SQL for its side effects. Multiple semicolon-separated statements
@@ -22221,7 +23387,15 @@ var Database = class {
22221
23387
  /** Execute a single-statement query and return all rows keyed by column name. */
22222
23388
  query(sql, params = [], options2 = {}) {
22223
23389
  this.assertOpen();
22224
- if (options2.at) return options2.at.open().query(sql, params);
23390
+ const at = options2.at;
23391
+ if (typeof at === "string") {
23392
+ try {
23393
+ return this.timeline.get(at).value.open().query(sql, params);
23394
+ } catch (error) {
23395
+ this.historyError(error);
23396
+ }
23397
+ }
23398
+ if (at) return at.open().query(sql, params);
22225
23399
  return this.prepareSingle(sql).all(...params);
22226
23400
  }
22227
23401
  /** Compile a single SQL statement into a reusable {@link Statement}. */
@@ -22269,23 +23443,77 @@ var Database = class {
22269
23443
  * {@link Snapshot.open} for a copy-on-write fork.
22270
23444
  */
22271
23445
  snapshot() {
23446
+ const point = this.record(this.historyBranch);
23447
+ return this.timeline.get(point.id).value;
23448
+ }
23449
+ /** Alias for {@link snapshot}, naming the value as a timeline checkpoint. */
23450
+ checkpoint() {
23451
+ return this.snapshot();
23452
+ }
23453
+ /**
23454
+ * Commit the live state onto `branch` (default: the branch this database follows).
23455
+ * Does not switch the live database. Illegal inside a transaction.
23456
+ */
23457
+ record(branch = this.historyBranch) {
22272
23458
  this.assertOpen();
22273
23459
  if (this.transactions.inTransaction) {
22274
23460
  throw pgError("transaction_state", "cannot snapshot during a transaction", "25P01");
22275
23461
  }
22276
- return captureSnapshot(
22277
- this.state,
22278
- this.prng,
22279
- this.now,
22280
- this.seed,
22281
- this.randomMode,
22282
- this.systemClock,
22283
- this.int8Mode
22284
- );
23462
+ try {
23463
+ return project(this.timeline.commit(this.captureLive(), { branch }));
23464
+ } catch (error) {
23465
+ this.historyError(error);
23466
+ }
22285
23467
  }
22286
- /** Alias for {@link snapshot}, naming the value as a timeline checkpoint. */
22287
- checkpoint() {
22288
- return this.snapshot();
23468
+ /** Point `name` at a checkpoint without copying rows or switching the live database. */
23469
+ fork(name, at) {
23470
+ this.assertOpen();
23471
+ try {
23472
+ const point = this.timeline.fork(name, at !== void 0 ? { from: at } : {});
23473
+ if (!point) throw pgError("misuse", "no checkpoint to fork from", "XX000");
23474
+ return project(point);
23475
+ } catch (error) {
23476
+ if (error instanceof PostgresError) throw error;
23477
+ this.historyError(error);
23478
+ }
23479
+ }
23480
+ /** Move `branch` to `id` and install that checkpoint as the live database. */
23481
+ checkout(id, branch = this.historyBranch) {
23482
+ this.assertOpen();
23483
+ if (this.transactions.inTransaction) {
23484
+ throw pgError("transaction_state", "cannot checkout during a transaction", "25P01");
23485
+ }
23486
+ try {
23487
+ const point = this.timeline.checkout(branch, id);
23488
+ this.historyBranch = branch;
23489
+ this.install(point.value);
23490
+ return project(point);
23491
+ } catch (error) {
23492
+ this.historyError(error);
23493
+ }
23494
+ }
23495
+ /** Return the live database to the origin checkpoint on `main`. */
23496
+ reset() {
23497
+ return this.checkout(this.originId, "main");
23498
+ }
23499
+ /** Checkpoint ids and branch heads. Values stay inside the timeline. */
23500
+ get history() {
23501
+ const timeline = this.timeline;
23502
+ return {
23503
+ get size() {
23504
+ return timeline.size;
23505
+ },
23506
+ head(branch) {
23507
+ const point = timeline.head(branch);
23508
+ return point ? project(point) : void 0;
23509
+ },
23510
+ branches() {
23511
+ return timeline.branches();
23512
+ },
23513
+ checkpoints() {
23514
+ return timeline.checkpoints().map(project);
23515
+ }
23516
+ };
22289
23517
  }
22290
23518
  /** Open a copy-on-write branch from `at`, or from the current state when omitted. */
22291
23519
  branch(at = this.snapshot()) {
@@ -22330,6 +23558,26 @@ var Database = class {
22330
23558
  assertOpen() {
22331
23559
  if (this.closed) throw pgError("misuse", "Database is closed", "XX000");
22332
23560
  }
23561
+ historyError(error) {
23562
+ const message2 = error instanceof Error ? error.message : String(error);
23563
+ throw pgError("misuse", message2, "XX000");
23564
+ }
23565
+ captureLive() {
23566
+ return captureSnapshot(
23567
+ this.state,
23568
+ this.prng,
23569
+ this.now,
23570
+ this.seed,
23571
+ this.randomMode,
23572
+ this.systemClock,
23573
+ this.int8Mode
23574
+ );
23575
+ }
23576
+ install(snapshot) {
23577
+ this.state.restoreFrom(snapshot.state.cloneShallow());
23578
+ this.prng.setState(snapshot.prngState);
23579
+ if (!this.systemClock) this.now = fixedClock(new Date(snapshot.nowMs));
23580
+ }
22333
23581
  prepareSingle(sql) {
22334
23582
  const statements = parse(sql);
22335
23583
  if (statements.length === 0) {
@@ -22789,7 +24037,7 @@ var FrameParser = class {
22789
24037
  return { kind: "typed", type, body };
22790
24038
  }
22791
24039
  };
22792
- var utf82 = {
24040
+ var utf83 = {
22793
24041
  encode: (s) => encoder2.encode(s),
22794
24042
  decode: (b) => decoder.decode(b)
22795
24043
  };
@@ -23010,13 +24258,13 @@ var binaryValue = (type, text) => {
23010
24258
  return out;
23011
24259
  }
23012
24260
  default:
23013
- return TEXT_TYPES2.has(type) ? utf82.encode(text) : null;
24261
+ return TEXT_TYPES2.has(type) ? utf83.encode(text) : null;
23014
24262
  }
23015
24263
  };
23016
24264
  var binaryEncodable = (type) => TEXT_TYPES2.has(type) || ["bool", "int2", "int4", "oid", "int8", "float4", "float8", "bytea", "uuid"].includes(type);
23017
24265
  var decodeParam = (oid, format, bytes) => {
23018
24266
  if (bytes === null) return null;
23019
- if (format === 0) return utf82.decode(bytes);
24267
+ if (format === 0) return utf83.decode(bytes);
23020
24268
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
23021
24269
  switch (oid) {
23022
24270
  case 16:
@@ -23052,7 +24300,7 @@ var decodeParam = (oid, format, bytes) => {
23052
24300
  case 1042:
23053
24301
  case 1043:
23054
24302
  case 3802:
23055
- return utf82.decode(bytes);
24303
+ return utf83.decode(bytes);
23056
24304
  default:
23057
24305
  throw pgError2("internal", `binary parameter format is not supported for type oid ${oid}`, "0A000");
23058
24306
  }
@@ -23219,6 +24467,11 @@ var Connection = class {
23219
24467
  return;
23220
24468
  }
23221
24469
  this.user = parameters.user ?? "postgres";
24470
+ const requested = parameters.database && parameters.database.length > 0 ? parameters.database : this.user;
24471
+ if (this.options.database !== void 0 && requested !== this.options.database) {
24472
+ this.fatal("3D000", `database "${requested}" does not exist`);
24473
+ return;
24474
+ }
23222
24475
  if (this.options.password !== void 0) {
23223
24476
  this.scram = new ScramServer(this.options.password);
23224
24477
  this.write(backend.authenticationSASL(["SCRAM-SHA-256"]));
@@ -23234,7 +24487,7 @@ var Connection = class {
23234
24487
  if (!this.scramStarted) {
23235
24488
  const mechanism = body.cstring();
23236
24489
  const length = body.i32();
23237
- const clientFirst = utf82.decode(body.take(length));
24490
+ const clientFirst = utf83.decode(body.take(length));
23238
24491
  const serverFirst = mechanism === "SCRAM-SHA-256" ? this.scram.first(clientFirst) : null;
23239
24492
  if (serverFirst === null) {
23240
24493
  this.fatal("28000", `SASL authentication with ${mechanism} is not supported or malformed`);
@@ -23244,7 +24497,7 @@ var Connection = class {
23244
24497
  this.write(backend.authenticationSASLContinue(serverFirst));
23245
24498
  return;
23246
24499
  }
23247
- const serverFinal = this.scram.final(utf82.decode(body.rest()));
24500
+ const serverFinal = this.scram.final(utf83.decode(body.rest()));
23248
24501
  if (serverFinal === null) {
23249
24502
  this.fatal("28P01", `password authentication failed for user "${this.user}"`);
23250
24503
  return;
@@ -23492,7 +24745,7 @@ var Connection = class {
23492
24745
  row.map((value, c) => {
23493
24746
  if (value === null) return null;
23494
24747
  const type = result.columnTypes[c];
23495
- return formats[c] === 1 ? binaryValue(type, value) ?? utf82.encode(value) : utf82.encode(value);
24748
+ return formats[c] === 1 ? binaryValue(type, value) ?? utf83.encode(value) : utf83.encode(value);
23496
24749
  })
23497
24750
  )
23498
24751
  );
@@ -23660,13 +24913,53 @@ var ConnectionDropped = class extends Error {
23660
24913
  };
23661
24914
 
23662
24915
  // src/wire/index.ts
24916
+ var parseUri = (raw) => {
24917
+ let url;
24918
+ try {
24919
+ url = new URL(raw);
24920
+ } catch {
24921
+ throw new Error(`invalid postgres URI: ${raw}`);
24922
+ }
24923
+ if (url.protocol !== "postgres:" && url.protocol !== "postgresql:") {
24924
+ throw new Error(`unsupported postgres URI protocol ${url.protocol}`);
24925
+ }
24926
+ const databaseName = decodeURIComponent(url.pathname.replace(/^\//, ""));
24927
+ const password = url.password === "" ? void 0 : decodeURIComponent(url.password);
24928
+ const user = decodeURIComponent(url.username || "postgres");
24929
+ const port = url.port === "" ? 5432 : Number(url.port);
24930
+ if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`invalid postgres URI port: ${url.port}`);
24931
+ return {
24932
+ host: url.hostname || "127.0.0.1",
24933
+ port,
24934
+ user,
24935
+ ...password !== void 0 ? { password } : {},
24936
+ ...databaseName !== "" ? { databaseName } : {}
24937
+ };
24938
+ };
24939
+ var normalize = (input) => {
24940
+ if (typeof input === "string") return parseUri(input);
24941
+ if (input.url === void 0) return input;
24942
+ const parsed = parseUri(input.url);
24943
+ return {
24944
+ ...parsed,
24945
+ ...input,
24946
+ host: input.host ?? parsed.host,
24947
+ port: input.port ?? parsed.port,
24948
+ password: input.password ?? parsed.password,
24949
+ databaseName: input.databaseName ?? parsed.databaseName,
24950
+ user: input.user ?? parsed.user,
24951
+ parameters: input.parameters ?? parsed.parameters
24952
+ };
24953
+ };
23663
24954
  var isSnapshot = (value) => typeof value === "object" && value !== null && "open" in value && typeof value.open === "function";
23664
- var serve = (options2 = {}) => {
24955
+ var serve = (input = {}) => {
24956
+ const options2 = normalize(input);
23665
24957
  const database = isSnapshot(options2.database) ? options2.database.open() : options2.database ?? new Database();
23666
24958
  const cluster = new Cluster(database);
23667
24959
  const faults = {};
23668
24960
  const connections = /* @__PURE__ */ new Set();
23669
24961
  const host = options2.host ?? "127.0.0.1";
24962
+ const user = options2.user || "postgres";
23670
24963
  const server2 = createServer((socket) => {
23671
24964
  socket.setNoDelay(true);
23672
24965
  const connection = new Connection(socket, cluster, {
@@ -23674,6 +24967,7 @@ var serve = (options2 = {}) => {
23674
24967
  serverVersion: options2.serverVersion ?? "18.3",
23675
24968
  parameters: options2.parameters ?? {},
23676
24969
  faults,
24970
+ ...options2.databaseName !== void 0 ? { database: options2.databaseName } : {},
23677
24971
  ...options2.onLog ? { onLog: options2.onLog } : {}
23678
24972
  });
23679
24973
  connections.add(connection);
@@ -23685,9 +24979,12 @@ var serve = (options2 = {}) => {
23685
24979
  server2.removeListener("error", reject);
23686
24980
  const address = server2.address();
23687
24981
  const port = typeof address === "object" && address !== null ? address.port : 0;
24982
+ const name = options2.databaseName ?? "postgres";
24983
+ const auth = options2.password ? `${encodeURIComponent(user)}:${encodeURIComponent(options2.password)}@` : `${encodeURIComponent(user)}@`;
23688
24984
  resolve({
23689
24985
  port,
23690
24986
  host,
24987
+ connectionString: `postgres://${auth}${host}:${port}/${encodeURIComponent(name)}`,
23691
24988
  database,
23692
24989
  server: server2,
23693
24990
  get connections() {
@@ -23712,7 +25009,7 @@ var serve = (options2 = {}) => {
23712
25009
  };
23713
25010
 
23714
25011
  // src/wire/cli.ts
23715
- var usage = `mockingbird-postgres serve [--port <n>] [--host <h>] [--password <p>] [--server-version <v>] [--log]`;
25012
+ var usage = `mockingbird-postgres serve [postgres://URI] [--port <n>] [--host <h>] [--password <p>] [--server-version <v>] [--log]`;
23716
25013
  var args = process.argv.slice(2);
23717
25014
  if (args[0] !== "serve") {
23718
25015
  console.error(usage);
@@ -23722,6 +25019,10 @@ var options = {};
23722
25019
  var log = false;
23723
25020
  for (let i = 1; i < args.length; i++) {
23724
25021
  const flag = args[i];
25022
+ if (flag !== void 0 && (flag.startsWith("postgres://") || flag.startsWith("postgresql://"))) {
25023
+ options.url = flag;
25024
+ continue;
25025
+ }
23725
25026
  const value = args[i + 1];
23726
25027
  const need = () => {
23727
25028
  if (value === void 0) {
@@ -23759,8 +25060,7 @@ if (log) {
23759
25060
  );
23760
25061
  }
23761
25062
  var server = await serve(options);
23762
- var auth = options.password ? `postgres:${options.password}@` : "postgres@";
23763
- console.log(`mockingbird-postgres listening on postgres://${auth}${server.host}:${server.port}/postgres`);
25063
+ console.log(`mockingbird-postgres listening on ${server.connectionString}`);
23764
25064
  var stop = async () => {
23765
25065
  await server.close();
23766
25066
  process.exit(0);