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