@crvouga/mockingbird-service-postgres 3.5.0 → 3.7.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/admin.js CHANGED
@@ -2505,6 +2505,13 @@ function isPostgresError(err) {
2505
2505
  return typeof sqlState === "string" && /^[0-9A-Z]{5}$/.test(sqlState);
2506
2506
  }
2507
2507
 
2508
+ // src/storage/guc.ts
2509
+ function validateStorageSetting(name, value) {
2510
+ if (name === "default_table_access_method" && value !== "heap" || name === "default_tablespace" && value !== "" && value !== "pg_default") {
2511
+ throw pgError("invalid_parameter_value", `invalid value for parameter "${name}": "${value}"`, "22023");
2512
+ }
2513
+ }
2514
+
2508
2515
  // src/runtime/prng.ts
2509
2516
  var Prng = class _Prng {
2510
2517
  state;
@@ -5044,6 +5051,12 @@ var invalidName = () => {
5044
5051
  throw pgError("syntax", "invalid name syntax", "42602");
5045
5052
  };
5046
5053
  function parseNamespaceInput(text) {
5054
+ const parsed = parseRelationInput(text);
5055
+ if ("oid" in parsed) return parsed;
5056
+ if (parsed.parts.length !== 1) invalidName();
5057
+ return { name: parsed.parts[0] };
5058
+ }
5059
+ function parseRelationInput(text) {
5047
5060
  if (text === "-") return { oid: 0 };
5048
5061
  if (/^\d+$/.test(text)) return { oid: parseOidText(text) };
5049
5062
  const names = [];
@@ -5079,8 +5092,8 @@ function parseNamespaceInput(text) {
5079
5092
  skipSpace();
5080
5093
  if (at === text.length) invalidName();
5081
5094
  }
5082
- if (names.length !== 1) invalidName();
5083
- return { name: names[0] };
5095
+ if (names.length === 0 || names.length > 3) invalidName();
5096
+ return { parts: names };
5084
5097
  }
5085
5098
  function namespaceText(oid, name) {
5086
5099
  if (oid === 0) return "-";
@@ -5153,6 +5166,7 @@ var TYPE_ALIASES = {
5153
5166
  regtype: "regtype",
5154
5167
  regproc: "regproc",
5155
5168
  regnamespace: "regnamespace",
5169
+ xid: "xid",
5156
5170
  oid: "oid",
5157
5171
  void: "void",
5158
5172
  record: "record",
@@ -5229,6 +5243,7 @@ var TYPE_OIDS = {
5229
5243
  regproc: 24,
5230
5244
  text: 25,
5231
5245
  oid: 26,
5246
+ xid: 28,
5232
5247
  json: 114,
5233
5248
  float4: 700,
5234
5249
  float8: 701,
@@ -5547,6 +5562,7 @@ function recordText(rec, ctx) {
5547
5562
  return `(${parts.join(",")})`;
5548
5563
  }
5549
5564
  function datumText(t, v, ctx) {
5565
+ if (t === "regclass") return v === 0 ? "-" : ctx.relationName?.(v) ?? String(v);
5550
5566
  if (t === "regnamespace") return namespaceText(v, ctx.namespaceName?.(v));
5551
5567
  if (v === null) throw pgError("internal", "datumText called with null");
5552
5568
  if (isArrayType(t)) return arrayText(v, ctx);
@@ -5557,6 +5573,7 @@ function datumText(t, v, ctx) {
5557
5573
  case "int2":
5558
5574
  case "int4":
5559
5575
  case "oid":
5576
+ case "xid":
5560
5577
  return String(v);
5561
5578
  case "int8":
5562
5579
  return String(v);
@@ -5621,6 +5638,12 @@ function datumText(t, v, ctx) {
5621
5638
  }
5622
5639
  var UTC_INPUT = { zoneOffsetForNaive: () => 0 };
5623
5640
  function datumFromText(t, text, ctx) {
5641
+ if (t === "regclass") {
5642
+ const parsed = parseRelationInput(text);
5643
+ if ("oid" in parsed) return parsed.oid;
5644
+ if (!ctx.relationOid) throw unsupported("regclass input without a catalog");
5645
+ return ctx.relationOid(parsed.parts);
5646
+ }
5624
5647
  if (t === "regnamespace") {
5625
5648
  const parsed = parseNamespaceInput(text);
5626
5649
  if ("oid" in parsed) return parsed.oid;
@@ -5642,6 +5665,7 @@ function datumFromText(t, text, ctx) {
5642
5665
  case "int8":
5643
5666
  return parseIntegerText(text, t);
5644
5667
  case "oid":
5668
+ case "xid":
5645
5669
  return parseOidText(text);
5646
5670
  case "float4":
5647
5671
  return Math.fround(parseFloatText(text, "float4"));
@@ -5798,6 +5822,8 @@ var TableData = class _TableData {
5798
5822
  schema;
5799
5823
  columns;
5800
5824
  rows;
5825
+ rowXmins = /* @__PURE__ */ new WeakMap();
5826
+ slabXmins = null;
5801
5827
  /** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
5802
5828
  slab = null;
5803
5829
  constraints;
@@ -5840,6 +5866,11 @@ var TableData = class _TableData {
5840
5866
  materializeSlab() {
5841
5867
  if (!this.slab) return;
5842
5868
  this.rows = this.slab.materialize();
5869
+ if (this.slabXmins)
5870
+ this.rows.forEach((row, index) => {
5871
+ this.rowXmins.set(row, this.slabXmins[index] ?? 2);
5872
+ });
5873
+ this.slabXmins = null;
5843
5874
  this.slab = null;
5844
5875
  this.indexStores = null;
5845
5876
  }
@@ -5873,6 +5904,10 @@ var TableData = class _TableData {
5873
5904
  } else {
5874
5905
  t.rows = this.rows.map((r) => r.slice());
5875
5906
  }
5907
+ t.rows.forEach((row, index) => {
5908
+ const xmin = this.slabXmins?.[index] ?? this.rowXmins.get(this.rows[index]);
5909
+ if (xmin !== void 0) t.rowXmins.set(row, xmin);
5910
+ });
5876
5911
  t.unlogged = this.unlogged;
5877
5912
  t.constraints = this.constraints.map((c) => ({ ...c }));
5878
5913
  t.triggers = this.triggers.map((tr) => ({ ...tr }));
@@ -5958,7 +5993,18 @@ var DatabaseState = class _DatabaseState {
5958
5993
  clock;
5959
5994
  changes = 0;
5960
5995
  oidCounter = 16384;
5996
+ /** Local monotonic xid allocator; 2 denotes a row from a legacy snapshot without metadata. */
5997
+ xidCounter = 3;
5998
+ transactionXid = null;
5999
+ allocateXid() {
6000
+ if (this.xidCounter > 4294967295)
6001
+ throw pgError("program_limit_exceeded", "transaction ID space exhausted; xid wraparound is not modeled", "54000");
6002
+ return this.xidCounter++;
6003
+ }
5961
6004
  inTransaction = false;
6005
+ /** Transaction-only events: included in rollback clones, never in exported snapshots. */
6006
+ pendingTriggers = [];
6007
+ constraintModes = /* @__PURE__ */ new Map();
5962
6008
  /** most recent sequence touched by nextval/setval, for lastval() */
5963
6009
  lastSequence = null;
5964
6010
  /** Session currval per sequence; absent entry means currval is undefined. */
@@ -6001,6 +6047,8 @@ var DatabaseState = class _DatabaseState {
6001
6047
  this.settings.set("row_security", "on");
6002
6048
  this.settings.set("array_nulls", "on");
6003
6049
  this.settings.set("backslash_quote", "safe_encoding");
6050
+ this.settings.set("default_tablespace", "");
6051
+ this.settings.set("default_table_access_method", "heap");
6004
6052
  }
6005
6053
  nextOid() {
6006
6054
  return this.oidCounter++;
@@ -6160,10 +6208,14 @@ var DatabaseState = class _DatabaseState {
6160
6208
  s.prepared = new Map(this.prepared);
6161
6209
  s.changes = this.changes;
6162
6210
  s.inTransaction = this.inTransaction;
6211
+ s.pendingTriggers = this.pendingTriggers.slice();
6212
+ s.constraintModes = new Map(this.constraintModes);
6163
6213
  s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
6164
6214
  s.sequenceCurrval = new Map(this.sequenceCurrval);
6165
6215
  s.tableStats = new Map(this.tableStats);
6166
6216
  s.oidCounter = this.oidCounter;
6217
+ s.xidCounter = this.xidCounter;
6218
+ s.transactionXid = this.transactionXid;
6167
6219
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
6168
6220
  return s;
6169
6221
  }
@@ -6177,10 +6229,14 @@ var DatabaseState = class _DatabaseState {
6177
6229
  s.prepared = new Map(this.prepared);
6178
6230
  s.changes = this.changes;
6179
6231
  s.inTransaction = this.inTransaction;
6232
+ s.pendingTriggers = this.pendingTriggers.slice();
6233
+ s.constraintModes = new Map(this.constraintModes);
6180
6234
  s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
6181
6235
  s.sequenceCurrval = new Map(this.sequenceCurrval);
6182
6236
  s.tableStats = new Map(this.tableStats);
6183
6237
  s.oidCounter = this.oidCounter;
6238
+ s.xidCounter = this.xidCounter;
6239
+ s.transactionXid = this.transactionXid;
6184
6240
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
6185
6241
  return s;
6186
6242
  }
@@ -6249,11 +6305,15 @@ var DatabaseState = class _DatabaseState {
6249
6305
  this.settings = other.settings;
6250
6306
  this.localSettings = other.localSettings;
6251
6307
  this.prepared = other.prepared;
6308
+ this.pendingTriggers = other.pendingTriggers.slice();
6309
+ this.constraintModes = new Map(other.constraintModes);
6252
6310
  this.changes = other.changes;
6253
6311
  this.lastSequence = other.lastSequence;
6254
6312
  this.sequenceCurrval = other.sequenceCurrval;
6255
6313
  this.tableStats = other.tableStats;
6256
6314
  this.oidCounter = other.oidCounter;
6315
+ this.xidCounter = Math.max(this.xidCounter, other.xidCounter);
6316
+ this.transactionXid = other.transactionXid;
6257
6317
  }
6258
6318
  /** @internal Snapshot codec access to the oid allocator. */
6259
6319
  snapshotOidCounter() {
@@ -6265,91 +6325,212 @@ var DatabaseState = class _DatabaseState {
6265
6325
  }
6266
6326
  };
6267
6327
 
6268
- // src/transactions/manager.ts
6269
- var TransactionManager = class {
6270
- constructor(state) {
6271
- this.state = state;
6328
+ // src/types/timezone.ts
6329
+ var intlCache = /* @__PURE__ */ new Map();
6330
+ function intlFor(zone) {
6331
+ const cached = intlCache.get(zone);
6332
+ if (cached) return cached;
6333
+ try {
6334
+ const fmt = new Intl.DateTimeFormat("en-US", {
6335
+ timeZone: zone,
6336
+ timeZoneName: "longOffset",
6337
+ year: "numeric"
6338
+ });
6339
+ intlCache.set(zone, fmt);
6340
+ return fmt;
6341
+ } catch {
6342
+ return null;
6343
+ }
6344
+ }
6345
+ function parseFixedOffset(zone) {
6346
+ const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
6347
+ if (!m) return null;
6348
+ const sign = m[1] === "-" ? -1 : 1;
6349
+ return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
6350
+ }
6351
+ function parsePosixOffset(zone) {
6352
+ const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
6353
+ if (!m) return null;
6354
+ const sign = m[1] === "-" ? 1 : -1;
6355
+ return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
6356
+ }
6357
+ function pgMicrosToUnixMs(utcMicros) {
6358
+ return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
6359
+ }
6360
+ function zoneOffsetAtUtc(zone, utcMicros) {
6361
+ const z = zone.trim();
6362
+ const lower = z.toLowerCase();
6363
+ if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
6364
+ const posix = parsePosixOffset(z);
6365
+ if (posix !== null) return posix;
6366
+ const fixed = parseFixedOffset(z);
6367
+ if (fixed !== null) return fixed;
6368
+ const fmt = intlFor(z);
6369
+ if (fmt) {
6370
+ const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
6371
+ const parts = fmt.formatToParts(new Date(ms));
6372
+ const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
6373
+ const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
6374
+ if (!m) return 0;
6375
+ const sign = m[1] === "-" ? -1 : 1;
6376
+ return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
6272
6377
  }
6378
+ throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
6379
+ }
6380
+ function clampDateMs(ms) {
6381
+ const MAX = 864e13;
6382
+ return Math.max(-MAX, Math.min(MAX, ms));
6383
+ }
6384
+ function zoneOffsetForNaive(zone, naiveMicros) {
6385
+ const first = zoneOffsetAtUtc(zone, naiveMicros);
6386
+ const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
6387
+ return second;
6388
+ }
6389
+
6390
+ // src/expressions/context.ts
6391
+ var EngineCtx = class {
6273
6392
  state;
6274
- base = null;
6275
- savepoints = [];
6276
- freezeDepth = 0;
6277
- get inTransaction() {
6278
- return this.base !== null;
6393
+ writeXid = null;
6394
+ rowVersionXid() {
6395
+ if (this.state.inTransaction) return this.state.transactionXid ??= this.state.allocateXid();
6396
+ return this.writeXid ??= this.state.allocateXid();
6279
6397
  }
6280
- takeSnapshot() {
6281
- this.state.freezeShared();
6282
- this.freezeDepth++;
6283
- return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
6398
+ /** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
6399
+ txNow;
6400
+ /** statement timestamp */
6401
+ stmtNow;
6402
+ constructor(state, txNow) {
6403
+ this.state = state;
6404
+ const nowMs = state.clock().getTime();
6405
+ const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
6406
+ this.txNow = txNow ?? nowMicros;
6407
+ this.stmtNow = nowMicros;
6284
6408
  }
6285
- restore(snap) {
6286
- this.state.restoreFrom(snap.state);
6287
- this.state.prng.setState(snap.prngState);
6409
+ timezone() {
6410
+ return this.state.getSetting("timezone") ?? "UTC";
6288
6411
  }
6289
- thawOnce() {
6290
- if (this.freezeDepth > 0) {
6291
- this.state.thawShared();
6292
- this.freezeDepth--;
6293
- }
6412
+ relationOid(parts) {
6413
+ const target = this.state.resolveRelationSchema(parts);
6414
+ const schema = target ? this.state.schemas.get(target.schema) : void 0;
6415
+ const relation = target ? schema?.sequences.get(target.name) ?? schema?.tables.get(target.name) ?? schema?.views.get(target.name) : void 0;
6416
+ if (!relation) throw pgError("undefined_table", `relation "${parts.join(".")}" does not exist`, "42P01");
6417
+ return relation.oid;
6294
6418
  }
6295
- begin() {
6296
- if (this.base !== null) {
6297
- return;
6419
+ relationName(oid) {
6420
+ for (const schema of this.state.schemas.values()) {
6421
+ for (const relation of [...schema.tables.values(), ...schema.sequences.values(), ...schema.views.values()]) {
6422
+ if (relation.oid !== oid) continue;
6423
+ const visible = this.state.resolveRelationSchema([relation.name])?.schema === schema.name;
6424
+ return (visible ? [relation.name] : [schema.name, relation.name]).map(quoteIdentifier).join(".");
6425
+ }
6298
6426
  }
6299
- this.base = this.takeSnapshot();
6300
- this.state.inTransaction = true;
6301
- assert(this.freezeDepth === 1, "BEGIN freeze depth");
6427
+ return null;
6302
6428
  }
6303
- commit() {
6304
- this.base = null;
6305
- this.savepoints = [];
6306
- this.state.inTransaction = false;
6307
- this.state.localSettings.clear();
6308
- while (this.freezeDepth > 0) this.thawOnce();
6429
+ namespaceOid(name) {
6430
+ const oid = builtinNamespaceOid(name) ?? this.state.schemas.get(name)?.oid;
6431
+ if (oid === void 0) throw pgError("undefined_object", `schema "${name}" does not exist`, "3F000");
6432
+ return oid;
6309
6433
  }
6310
- rollback() {
6311
- if (this.base !== null) {
6312
- this.restore(this.base);
6434
+ namespaceName(oid) {
6435
+ const builtin = builtinNamespaceName(oid);
6436
+ if (builtin !== void 0) return builtin;
6437
+ for (const schema of this.state.schemas.values()) {
6438
+ if (schema.oid === oid) return schema.name;
6313
6439
  }
6314
- this.base = null;
6315
- this.savepoints = [];
6316
- this.state.inTransaction = false;
6317
- this.state.localSettings.clear();
6318
- while (this.freezeDepth > 0) this.thawOnce();
6440
+ return null;
6319
6441
  }
6320
- savepoint(name) {
6321
- if (this.base === null) {
6322
- throw pgError("transaction_state", "SAVEPOINT can only be used in transaction blocks", "25P01");
6323
- }
6324
- this.savepoints.push({ name, snap: this.takeSnapshot() });
6442
+ zoneOffsetAt(utcMicros) {
6443
+ return zoneOffsetAtUtc(this.timezone(), utcMicros);
6325
6444
  }
6326
- releaseSavepoint(name) {
6327
- const idx = this.findSavepoint(name);
6328
- this.savepoints.splice(idx);
6445
+ zoneOffsetForNaive(naiveMicros) {
6446
+ return zoneOffsetForNaive(this.timezone(), naiveMicros);
6329
6447
  }
6330
- rollbackToSavepoint(name) {
6331
- const idx = this.findSavepoint(name);
6332
- const sp = this.savepoints[idx];
6333
- this.restore(sp.snap);
6334
- this.savepoints.splice(idx + 1);
6448
+ enumLabels(enumType) {
6449
+ if (!isEnumType(enumType)) return null;
6450
+ const e = this.state.findEnumByKey(enumType.slice(5));
6451
+ return e?.labels ?? null;
6335
6452
  }
6336
- findSavepoint(name) {
6337
- if (this.base === null) {
6338
- throw pgError("transaction_state", `SAVEPOINT can only be used in transaction blocks`, "25P01");
6339
- }
6340
- for (let i = this.savepoints.length - 1; i >= 0; i--) {
6341
- if (this.savepoints[i].name === name) return i;
6342
- }
6343
- throw pgError("invalid_savepoint_specification", `savepoint "${name}" does not exist`, "3B001");
6453
+ enumHasLabel(enumType, label) {
6454
+ const labels = this.enumLabels(enumType);
6455
+ return labels === null ? true : labels.includes(label);
6344
6456
  }
6345
- reset() {
6346
- this.base = null;
6347
- this.savepoints = [];
6348
- this.state.inTransaction = false;
6349
- this.freezeDepth = 0;
6457
+ enumOrder(enumType, label) {
6458
+ const labels = this.enumLabels(enumType);
6459
+ if (!labels) return 0;
6460
+ const idx = labels.indexOf(label);
6461
+ return idx === -1 ? labels.length : idx;
6462
+ }
6463
+ requireEnum(enumType) {
6464
+ const labels = this.enumLabels(enumType);
6465
+ if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
6466
+ return labels;
6350
6467
  }
6351
6468
  };
6352
6469
 
6470
+ // src/api/bind.ts
6471
+ var INT4_MIN2 = -2147483648;
6472
+ var INT4_MAX2 = 2147483647;
6473
+ function bindValueToTyped(value, index) {
6474
+ if (value === null || value === void 0) return tv(UNKNOWN, null);
6475
+ switch (typeof value) {
6476
+ case "boolean":
6477
+ return tv("bool", value);
6478
+ case "number":
6479
+ if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
6480
+ return tv("int4", value);
6481
+ }
6482
+ if (Number.isInteger(value) && Number.isSafeInteger(value)) {
6483
+ return tv("int8", BigInt(value));
6484
+ }
6485
+ return tv("float8", value);
6486
+ case "bigint":
6487
+ if (value < -9223372036854775808n || value > 9223372036854775807n) {
6488
+ throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
6489
+ }
6490
+ return tv("int8", value);
6491
+ case "string":
6492
+ return tv(UNKNOWN, value);
6493
+ case "object": {
6494
+ if (value instanceof Uint8Array) return tv("bytea", value);
6495
+ if (value instanceof Date) {
6496
+ const ms = value.getTime();
6497
+ if (Number.isNaN(ms)) {
6498
+ throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
6499
+ }
6500
+ return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
6501
+ }
6502
+ break;
6503
+ }
6504
+ default:
6505
+ break;
6506
+ }
6507
+ throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
6508
+ }
6509
+ function datumToJs(t, v, ctx, int8 = "bigint") {
6510
+ if (v === null) return null;
6511
+ switch (t) {
6512
+ case "bool":
6513
+ return v;
6514
+ case "int2":
6515
+ case "int4":
6516
+ case "oid":
6517
+ return typeof v === "bigint" ? Number(v) : v;
6518
+ case "int8": {
6519
+ const n = typeof v === "bigint" ? v : BigInt(v);
6520
+ if (int8 === "string") return n.toString();
6521
+ if (int8 === "number") return Number(n);
6522
+ return n;
6523
+ }
6524
+ case "float4":
6525
+ case "float8":
6526
+ return v;
6527
+ case "bytea":
6528
+ return v;
6529
+ default:
6530
+ return datumText(t === UNKNOWN ? "text" : t, v, ctx);
6531
+ }
6532
+ }
6533
+
6353
6534
  // src/types/cast.ts
6354
6535
  var UTC_CAST_ENV = {
6355
6536
  zoneOffsetAt: () => 0,
@@ -6545,7 +6726,7 @@ function castTo(env, value, target, opts = {}) {
6545
6726
  return tv(target, makeArray(toElem, items, arr.dims.slice(), arr.lbs.slice()));
6546
6727
  }
6547
6728
  if (from === "oid" && target === "regnamespace") return tv(target, v);
6548
- if (from === "regnamespace" && (target === "oid" || target === "int4" || target === "int8")) {
6729
+ if ((from === "regnamespace" || from === "regclass") && (target === "oid" || target === "int4" || target === "int8")) {
6549
6730
  return tv(target, target === "int8" ? BigInt(v) : v);
6550
6731
  }
6551
6732
  if ((from === "int4" || from === "int8" || from === "int2") && (target === "oid" || target === "regnamespace")) {
@@ -6826,259 +7007,6 @@ function unifyTypes(a, b) {
6826
7007
  return null;
6827
7008
  }
6828
7009
 
6829
- // src/types/resolve.ts
6830
- var SERIALS = {
6831
- smallserial: "int2",
6832
- serial2: "int2",
6833
- serial: "int4",
6834
- serial4: "int4",
6835
- bigserial: "int8",
6836
- serial8: "int8"
6837
- };
6838
- function modOf(t, mods) {
6839
- if (mods.length === 0) return null;
6840
- if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
6841
- return { a: mods[0] };
6842
- }
6843
- function resolveTypeName(state, tn) {
6844
- const joined = tn.parts.join(".");
6845
- const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
6846
- if (bare !== null) {
6847
- const serial = SERIALS[bare];
6848
- if (serial !== void 0 && tn.arrayDims === 0) {
6849
- return { column: { id: serial, mod: null }, domain: null, serial };
6850
- }
6851
- const builtin = normalizeTypeName(bare);
6852
- if (builtin !== null) {
6853
- const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
6854
- return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
6855
- }
6856
- }
6857
- const enumData = state.findEnum(tn.parts);
6858
- if (enumData) {
6859
- const elem = `enum:${enumData.schema}.${enumData.name}`;
6860
- const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
6861
- return { column: { id, mod: null }, domain: null, serial: null };
6862
- }
6863
- const domainData = state.findDomain(tn.parts);
6864
- if (domainData) {
6865
- if (tn.arrayDims > 0) {
6866
- const id = arrayTypeOf(domainData.baseType.id);
6867
- return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
6868
- }
6869
- return {
6870
- column: domainData.baseType,
6871
- domain: `${domainData.schema}.${domainData.name}`,
6872
- serial: null
6873
- };
6874
- }
6875
- throw pgError("undefined_object", `type "${joined}" does not exist`);
6876
- }
6877
-
6878
- // src/executor/relation.ts
6879
- var RowScope = class {
6880
- constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
6881
- this.columns = columns;
6882
- this.row = row;
6883
- this.parent = parent;
6884
- this.rangeVars = rangeVars;
6885
- }
6886
- columns;
6887
- row;
6888
- parent;
6889
- rangeVars;
6890
- /** Resolve a (possibly qualified) column reference. undefined = not found. */
6891
- lookup(parts) {
6892
- if (parts.length === 1) {
6893
- const name2 = parts[0];
6894
- let found2;
6895
- let count3 = 0;
6896
- for (let i = 0; i < this.columns.length; i++) {
6897
- const c = this.columns[i];
6898
- if (c.name === name2 && !c.hidden) {
6899
- count3++;
6900
- if (count3 > 1) {
6901
- throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
6902
- }
6903
- found2 = tv(c.type, this.row[i] ?? null);
6904
- }
6905
- }
6906
- if (found2 !== void 0) return found2;
6907
- if (this.rangeVars.has(name2)) {
6908
- return this.wholeRow(name2);
6909
- }
6910
- return this.parent?.lookup(parts);
6911
- }
6912
- const table = parts[parts.length - 2];
6913
- const name = parts[parts.length - 1];
6914
- let found;
6915
- let count2 = 0;
6916
- for (let i = 0; i < this.columns.length; i++) {
6917
- const c = this.columns[i];
6918
- if (c.table === table && c.name === name) {
6919
- count2++;
6920
- if (count2 > 1) {
6921
- throw pgError("ambiguous_column", `column reference "${name}" is ambiguous`);
6922
- }
6923
- found = tv(c.type, this.row[i] ?? null);
6924
- }
6925
- }
6926
- if (found !== void 0) return found;
6927
- return this.parent?.lookup(parts);
6928
- }
6929
- /** Build a record value from all columns belonging to a range variable. */
6930
- wholeRow(rangeVar) {
6931
- const types = [];
6932
- const values = [];
6933
- const names = [];
6934
- for (let i = 0; i < this.columns.length; i++) {
6935
- const c = this.columns[i];
6936
- if (c.table === rangeVar) {
6937
- types.push(c.type);
6938
- values.push(this.row[i] ?? null);
6939
- names.push(c.name);
6940
- }
6941
- }
6942
- if (types.length === 0) return void 0;
6943
- return tv("record", { kind: "pgrecord", types, values, names });
6944
- }
6945
- hasRangeVar(name) {
6946
- if (this.rangeVars.has(name)) return true;
6947
- return this.parent?.hasRangeVar(name) ?? false;
6948
- }
6949
- };
6950
- function childEnv(env, outer) {
6951
- return {
6952
- ctx: env.ctx,
6953
- params: env.params,
6954
- ctes: env.ctes,
6955
- outer,
6956
- allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
6957
- };
6958
- }
6959
- function relationResult(rel3, command) {
6960
- const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
6961
- return {
6962
- columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
6963
- rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
6964
- command,
6965
- rowCount: rel3.rows.length
6966
- };
6967
- }
6968
- function commandResult(command, rowCount) {
6969
- return { columns: [], rows: [], command, rowCount };
6970
- }
6971
- function inferColumnName(e) {
6972
- switch (e.type) {
6973
- case "colref":
6974
- return e.parts[e.parts.length - 1];
6975
- case "func":
6976
- return e.name[e.name.length - 1];
6977
- case "cast": {
6978
- const inner = inferColumnName(e.expr);
6979
- if (inner !== "?column?") return inner;
6980
- return e.target.parts[e.target.parts.length - 1];
6981
- }
6982
- case "collate":
6983
- return inferColumnName(e.expr);
6984
- case "case":
6985
- return "case";
6986
- case "array_ctor":
6987
- case "array_query":
6988
- return "array";
6989
- case "row":
6990
- return "row";
6991
- case "subquery_expr":
6992
- return e.kind === "exists" ? "exists" : "?column?";
6993
- case "bool_lit":
6994
- return "bool";
6995
- case "extract":
6996
- return "extract";
6997
- case "position":
6998
- return "position";
6999
- case "substring_sql":
7000
- return "substring";
7001
- case "overlay":
7002
- return "overlay";
7003
- case "trim":
7004
- return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
7005
- case "field_select":
7006
- return e.field === "*" ? "?column?" : e.field;
7007
- case "at_time_zone":
7008
- return "timezone";
7009
- case "grouping_func":
7010
- return "grouping";
7011
- case "subscript":
7012
- return inferColumnName(e.base);
7013
- default:
7014
- return "?column?";
7015
- }
7016
- }
7017
-
7018
- // src/api/bind.ts
7019
- var INT4_MIN2 = -2147483648;
7020
- var INT4_MAX2 = 2147483647;
7021
- function bindValueToTyped(value, index) {
7022
- if (value === null || value === void 0) return tv(UNKNOWN, null);
7023
- switch (typeof value) {
7024
- case "boolean":
7025
- return tv("bool", value);
7026
- case "number":
7027
- if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
7028
- return tv("int4", value);
7029
- }
7030
- if (Number.isInteger(value) && Number.isSafeInteger(value)) {
7031
- return tv("int8", BigInt(value));
7032
- }
7033
- return tv("float8", value);
7034
- case "bigint":
7035
- if (value < -9223372036854775808n || value > 9223372036854775807n) {
7036
- throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
7037
- }
7038
- return tv("int8", value);
7039
- case "string":
7040
- return tv(UNKNOWN, value);
7041
- case "object": {
7042
- if (value instanceof Uint8Array) return tv("bytea", value);
7043
- if (value instanceof Date) {
7044
- const ms = value.getTime();
7045
- if (Number.isNaN(ms)) {
7046
- throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
7047
- }
7048
- return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
7049
- }
7050
- break;
7051
- }
7052
- default:
7053
- break;
7054
- }
7055
- throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
7056
- }
7057
- function datumToJs(t, v, ctx, int8 = "bigint") {
7058
- if (v === null) return null;
7059
- switch (t) {
7060
- case "bool":
7061
- return v;
7062
- case "int2":
7063
- case "int4":
7064
- case "oid":
7065
- return typeof v === "bigint" ? Number(v) : v;
7066
- case "int8": {
7067
- const n = typeof v === "bigint" ? v : BigInt(v);
7068
- if (int8 === "string") return n.toString();
7069
- if (int8 === "number") return Number(n);
7070
- return n;
7071
- }
7072
- case "float4":
7073
- case "float8":
7074
- return v;
7075
- case "bytea":
7076
- return v;
7077
- default:
7078
- return datumText(t === UNKNOWN ? "text" : t, v, ctx);
7079
- }
7080
- }
7081
-
7082
7010
  // src/functions/datetime-fns.ts
7083
7011
  function extractDatePart(ctx, field0, src0, asNumeric) {
7084
7012
  const field = field0.toLowerCase();
@@ -7499,6 +7427,8 @@ function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
7499
7427
  case "int2":
7500
7428
  case "int4":
7501
7429
  case "oid":
7430
+ case "regclass":
7431
+ case "xid":
7502
7432
  case "regnamespace":
7503
7433
  case "date":
7504
7434
  return expectNumber(a, t) - expectNumber(b, t);
@@ -7618,6 +7548,8 @@ function datumKey(t, v) {
7618
7548
  case "int2":
7619
7549
  case "int4":
7620
7550
  case "oid":
7551
+ case "regclass":
7552
+ case "xid":
7621
7553
  case "date":
7622
7554
  return `i${v}`;
7623
7555
  case "float4":
@@ -7993,68 +7925,6 @@ function getArrayFunctions() {
7993
7925
  return m;
7994
7926
  }
7995
7927
 
7996
- // src/types/timezone.ts
7997
- var intlCache = /* @__PURE__ */ new Map();
7998
- function intlFor(zone) {
7999
- const cached = intlCache.get(zone);
8000
- if (cached) return cached;
8001
- try {
8002
- const fmt = new Intl.DateTimeFormat("en-US", {
8003
- timeZone: zone,
8004
- timeZoneName: "longOffset",
8005
- year: "numeric"
8006
- });
8007
- intlCache.set(zone, fmt);
8008
- return fmt;
8009
- } catch {
8010
- return null;
8011
- }
8012
- }
8013
- function parseFixedOffset(zone) {
8014
- const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
8015
- if (!m) return null;
8016
- const sign = m[1] === "-" ? -1 : 1;
8017
- return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
8018
- }
8019
- function parsePosixOffset(zone) {
8020
- const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
8021
- if (!m) return null;
8022
- const sign = m[1] === "-" ? 1 : -1;
8023
- return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
8024
- }
8025
- function pgMicrosToUnixMs(utcMicros) {
8026
- return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
8027
- }
8028
- function zoneOffsetAtUtc(zone, utcMicros) {
8029
- const z = zone.trim();
8030
- const lower = z.toLowerCase();
8031
- if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
8032
- const posix = parsePosixOffset(z);
8033
- if (posix !== null) return posix;
8034
- const fixed = parseFixedOffset(z);
8035
- if (fixed !== null) return fixed;
8036
- const fmt = intlFor(z);
8037
- if (fmt) {
8038
- const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
8039
- const parts = fmt.formatToParts(new Date(ms));
8040
- const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
8041
- const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
8042
- if (!m) return 0;
8043
- const sign = m[1] === "-" ? -1 : 1;
8044
- return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
8045
- }
8046
- throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
8047
- }
8048
- function clampDateMs(ms) {
8049
- const MAX = 864e13;
8050
- return Math.max(-MAX, Math.min(MAX, ms));
8051
- }
8052
- function zoneOffsetForNaive(zone, naiveMicros) {
8053
- const first = zoneOffsetAtUtc(zone, naiveMicros);
8054
- const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
8055
- return second;
8056
- }
8057
-
8058
7928
  // src/functions/datetime-registry.ts
8059
7929
  function getDatetimeFunctions() {
8060
7930
  const m = /* @__PURE__ */ new Map();
@@ -9654,6 +9524,28 @@ function exactDegTan(x) {
9654
9524
  return Math.tan(x * Math.PI / 180);
9655
9525
  }
9656
9526
 
9527
+ // src/storage/indexable-relation.ts
9528
+ function materializedTable(view) {
9529
+ const table = new TableData(
9530
+ view.schema,
9531
+ view.name,
9532
+ (view.matColumns ?? []).map((c) => ({
9533
+ name: c.name,
9534
+ type: { id: c.type, mod: null },
9535
+ notNull: false,
9536
+ defaultExpr: null,
9537
+ identity: null,
9538
+ generated: null,
9539
+ collate: null,
9540
+ domain: null
9541
+ })),
9542
+ view.oid,
9543
+ view.temp
9544
+ );
9545
+ table.rows = view.matRows ?? [];
9546
+ return table;
9547
+ }
9548
+
9657
9549
  // src/schema/index-catalog.ts
9658
9550
  var isKeyConstraint = (constraint) => constraint.kind === "primary_key" || constraint.kind === "unique";
9659
9551
  var ACCESS_METHODS = /* @__PURE__ */ new Map([
@@ -9682,6 +9574,8 @@ function syncIndexCatalog(state) {
9682
9574
  const tables = /* @__PURE__ */ new Map();
9683
9575
  for (const schema of state.schemas.values()) {
9684
9576
  for (const table of schema.tables.values()) tables.set(table.oid, { schema, table });
9577
+ for (const view of schema.views.values())
9578
+ if (view.materialized) tables.set(view.oid, { schema, table: materializedTable(view) });
9685
9579
  }
9686
9580
  const backing = /* @__PURE__ */ new Map();
9687
9581
  for (const { table } of tables.values()) {
@@ -9879,6 +9773,55 @@ function deparseExpr(e) {
9879
9773
  }
9880
9774
  }
9881
9775
 
9776
+ // src/types/resolve.ts
9777
+ var SERIALS = {
9778
+ smallserial: "int2",
9779
+ serial2: "int2",
9780
+ serial: "int4",
9781
+ serial4: "int4",
9782
+ bigserial: "int8",
9783
+ serial8: "int8"
9784
+ };
9785
+ function modOf(t, mods) {
9786
+ if (mods.length === 0) return null;
9787
+ if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
9788
+ return { a: mods[0] };
9789
+ }
9790
+ function resolveTypeName(state, tn) {
9791
+ const joined = tn.parts.join(".");
9792
+ const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
9793
+ if (bare !== null) {
9794
+ const serial = SERIALS[bare];
9795
+ if (serial !== void 0 && tn.arrayDims === 0) {
9796
+ return { column: { id: serial, mod: null }, domain: null, serial };
9797
+ }
9798
+ const builtin = normalizeTypeName(bare);
9799
+ if (builtin !== null) {
9800
+ const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
9801
+ return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
9802
+ }
9803
+ }
9804
+ const enumData = state.findEnum(tn.parts);
9805
+ if (enumData) {
9806
+ const elem = `enum:${enumData.schema}.${enumData.name}`;
9807
+ const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
9808
+ return { column: { id, mod: null }, domain: null, serial: null };
9809
+ }
9810
+ const domainData = state.findDomain(tn.parts);
9811
+ if (domainData) {
9812
+ if (tn.arrayDims > 0) {
9813
+ const id = arrayTypeOf(domainData.baseType.id);
9814
+ return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
9815
+ }
9816
+ return {
9817
+ column: domainData.baseType,
9818
+ domain: `${domainData.schema}.${domainData.name}`,
9819
+ serial: null
9820
+ };
9821
+ }
9822
+ throw pgError("undefined_object", `type "${joined}" does not exist`);
9823
+ }
9824
+
9882
9825
  // src/sql/ruleutils.ts
9883
9826
  var BOOL = "bool";
9884
9827
  var TEXT = "text";
@@ -10512,7 +10455,7 @@ function databaseCatalogContext(state) {
10512
10455
  var PG_VERSION_TEXT = "PostgreSQL 18.3 (postgres-mem) on TypeScript, in-memory engine";
10513
10456
  function findSequenceForCall(ctx, name) {
10514
10457
  const parts = parseQualifiedName(name);
10515
- const seq = ctx.state.findSequence(parts);
10458
+ const seq = /^\d+$/.test(name) ? [...ctx.state.schemas.values()].flatMap((schema) => [...schema.sequences.values()]).find((sequence) => sequence.oid === Number(name)) : ctx.state.findSequence(parts);
10516
10459
  if (!seq) {
10517
10460
  throw pgError("undefined_table", `relation "${name}" does not exist`, "42P01");
10518
10461
  }
@@ -10673,7 +10616,11 @@ function getMiscFunctions() {
10673
10616
  }
10674
10617
  const name = argText(ctx, args[0]).toLowerCase();
10675
10618
  const value = args[1].v === null ? "" : argText(ctx, args[1]);
10676
- ctx.state.settings.set(name, value);
10619
+ if (!ctx.state.settings.has(name) && !name.includes("."))
10620
+ throw pgError("undefined_object", `unrecognized configuration parameter "${name}"`, "42704");
10621
+ validateStorageSetting(name, value);
10622
+ const local = args[2]?.v === true;
10623
+ if (!local || ctx.state.inTransaction) (local ? ctx.state.localSettings : ctx.state.settings).set(name, value);
10677
10624
  return tv("text", value);
10678
10625
  });
10679
10626
  m.set(
@@ -10732,17 +10679,16 @@ function getMiscFunctions() {
10732
10679
  "pg_get_serial_sequence",
10733
10680
  strict("text", (ctx, args) => {
10734
10681
  const tableName2 = argText(ctx, args[0]);
10735
- const column = argText(ctx, args[1]).toLowerCase();
10682
+ const column = argText(ctx, args[1]);
10736
10683
  const table = ctx.state.findTable(parseQualifiedName(tableName2));
10737
10684
  if (!table) throw pgError("undefined_table", `relation "${tableName2}" does not exist`, "42P01");
10738
10685
  const col = table.columns.find((c) => c.name === column);
10739
10686
  if (!col)
10740
10687
  throw pgError("undefined_column", `column "${column}" of relation "${table.name}" does not exist`, "42703");
10741
- if (!col.identity) return tv("text", null);
10742
- return tv(
10743
- "text",
10744
- col.identity.sequence.split(".").map(quoteIdent).join(".")
10688
+ const seq = [...ctx.state.schemas.get(table.schema)?.sequences.values() ?? []].find(
10689
+ (candidate) => candidate.ownedBy?.table === table.name && candidate.ownedBy.column === column
10745
10690
  );
10691
+ return tv("text", seq ? [seq.schema, seq.name].map(quoteIdent).join(".") : null);
10746
10692
  })
10747
10693
  );
10748
10694
  m.set("format_type", (ctx, args) => {
@@ -15666,6 +15612,146 @@ function isSrfName(name) {
15666
15612
  return SRFS.has(name);
15667
15613
  }
15668
15614
 
15615
+ // src/executor/relation.ts
15616
+ var RowScope = class {
15617
+ constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
15618
+ this.columns = columns;
15619
+ this.row = row;
15620
+ this.parent = parent;
15621
+ this.rangeVars = rangeVars;
15622
+ }
15623
+ columns;
15624
+ row;
15625
+ parent;
15626
+ rangeVars;
15627
+ /** Resolve a (possibly qualified) column reference. undefined = not found. */
15628
+ lookup(parts) {
15629
+ if (parts.length === 1) {
15630
+ const name2 = parts[0];
15631
+ let found2;
15632
+ let count3 = 0;
15633
+ for (let i = 0; i < this.columns.length; i++) {
15634
+ const c = this.columns[i];
15635
+ if (c.name === name2 && (!c.hidden || c.system)) {
15636
+ count3++;
15637
+ if (count3 > 1) {
15638
+ throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
15639
+ }
15640
+ found2 = tv(c.type, this.row[i] ?? null);
15641
+ }
15642
+ }
15643
+ if (found2 !== void 0) return found2;
15644
+ if (this.rangeVars.has(name2)) {
15645
+ return this.wholeRow(name2);
15646
+ }
15647
+ return this.parent?.lookup(parts);
15648
+ }
15649
+ const table = parts[parts.length - 2];
15650
+ const name = parts[parts.length - 1];
15651
+ let found;
15652
+ let count2 = 0;
15653
+ for (let i = 0; i < this.columns.length; i++) {
15654
+ const c = this.columns[i];
15655
+ if (c.table === table && c.name === name) {
15656
+ count2++;
15657
+ if (count2 > 1) {
15658
+ throw pgError("ambiguous_column", `column reference "${name}" is ambiguous`);
15659
+ }
15660
+ found = tv(c.type, this.row[i] ?? null);
15661
+ }
15662
+ }
15663
+ if (found !== void 0) return found;
15664
+ return this.parent?.lookup(parts);
15665
+ }
15666
+ /** Build a record value from all columns belonging to a range variable. */
15667
+ wholeRow(rangeVar) {
15668
+ const types = [];
15669
+ const values = [];
15670
+ const names = [];
15671
+ for (let i = 0; i < this.columns.length; i++) {
15672
+ const c = this.columns[i];
15673
+ if (c.table === rangeVar && !c.system) {
15674
+ types.push(c.type);
15675
+ values.push(this.row[i] ?? null);
15676
+ names.push(c.name);
15677
+ }
15678
+ }
15679
+ if (types.length === 0) return void 0;
15680
+ return tv("record", { kind: "pgrecord", types, values, names });
15681
+ }
15682
+ hasRangeVar(name) {
15683
+ if (this.rangeVars.has(name)) return true;
15684
+ return this.parent?.hasRangeVar(name) ?? false;
15685
+ }
15686
+ };
15687
+ function childEnv(env, outer) {
15688
+ return {
15689
+ ctx: env.ctx,
15690
+ params: env.params,
15691
+ ctes: env.ctes,
15692
+ outer,
15693
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
15694
+ };
15695
+ }
15696
+ function relationResult(rel3, command) {
15697
+ const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
15698
+ return {
15699
+ columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
15700
+ rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
15701
+ command,
15702
+ rowCount: rel3.rows.length
15703
+ };
15704
+ }
15705
+ function commandResult(command, rowCount) {
15706
+ return { columns: [], rows: [], command, rowCount };
15707
+ }
15708
+ function inferColumnName(e) {
15709
+ switch (e.type) {
15710
+ case "colref":
15711
+ return e.parts[e.parts.length - 1];
15712
+ case "func":
15713
+ return e.name[e.name.length - 1];
15714
+ case "cast": {
15715
+ const inner = inferColumnName(e.expr);
15716
+ if (inner !== "?column?") return inner;
15717
+ return e.target.parts[e.target.parts.length - 1];
15718
+ }
15719
+ case "collate":
15720
+ return inferColumnName(e.expr);
15721
+ case "case":
15722
+ return "case";
15723
+ case "array_ctor":
15724
+ case "array_query":
15725
+ return "array";
15726
+ case "row":
15727
+ return "row";
15728
+ case "subquery_expr":
15729
+ return e.kind === "exists" ? "exists" : "?column?";
15730
+ case "bool_lit":
15731
+ return "bool";
15732
+ case "extract":
15733
+ return "extract";
15734
+ case "position":
15735
+ return "position";
15736
+ case "substring_sql":
15737
+ return "substring";
15738
+ case "overlay":
15739
+ return "overlay";
15740
+ case "trim":
15741
+ return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
15742
+ case "field_select":
15743
+ return e.field === "*" ? "?column?" : e.field;
15744
+ case "at_time_zone":
15745
+ return "timezone";
15746
+ case "grouping_func":
15747
+ return "grouping";
15748
+ case "subscript":
15749
+ return inferColumnName(e.base);
15750
+ default:
15751
+ return "?column?";
15752
+ }
15753
+ }
15754
+
15669
15755
  // src/indexes/index.ts
15670
15756
  var IndexStore = class _IndexStore {
15671
15757
  name;
@@ -15728,53 +15814,228 @@ function ensureIndexStores(env, table) {
15728
15814
  const key = uniqueKeyOf(env, table, spec, table.rowAt(i));
15729
15815
  if (key !== null) store.insert(key, i);
15730
15816
  }
15731
- stores.set(spec.name, store);
15732
- }
15733
- const schema = env.ctx.state.schemas.get(table.schema);
15734
- if (schema) {
15735
- for (const idx of schema.indexes.values()) {
15736
- if (idx.table !== table.name || idx.unique) continue;
15737
- stores.set(idx.name, new IndexStore(idx.name, false));
15817
+ stores.set(spec.name, store);
15818
+ }
15819
+ const schema = env.ctx.state.schemas.get(table.schema);
15820
+ if (schema) {
15821
+ for (const idx of schema.indexes.values()) {
15822
+ if (idx.table !== table.name || idx.unique) continue;
15823
+ stores.set(idx.name, new IndexStore(idx.name, false));
15824
+ }
15825
+ }
15826
+ table.indexStores = stores;
15827
+ return stores;
15828
+ }
15829
+ function indexStoreFor(env, table, spec) {
15830
+ const stores = ensureIndexStores(env, table);
15831
+ let store = stores.get(spec.name);
15832
+ if (!store) {
15833
+ store = new IndexStore(spec.name, true);
15834
+ for (let i = 0; i < table.rowCount(); i++) {
15835
+ const key = uniqueKeyOf(env, table, spec, table.rowAt(i));
15836
+ if (key !== null) store.insert(key, i);
15837
+ }
15838
+ stores.set(spec.name, store);
15839
+ }
15840
+ return store;
15841
+ }
15842
+ function indexInsertRow(env, table, rowIdx, row) {
15843
+ for (const spec of uniqueSpecsFor(env, table)) {
15844
+ const key = uniqueKeyOf(env, table, spec, row);
15845
+ if (key === null) continue;
15846
+ indexStoreFor(env, table, spec).insert(key, rowIdx);
15847
+ }
15848
+ }
15849
+ function indexRemoveRow(env, table, rowIdx, row) {
15850
+ if (!table.indexStores) return;
15851
+ for (const spec of uniqueSpecsFor(env, table)) {
15852
+ const key = uniqueKeyOf(env, table, spec, row);
15853
+ if (key === null) continue;
15854
+ table.indexStores.get(spec.name)?.remove(key, rowIdx);
15855
+ }
15856
+ }
15857
+ function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
15858
+ indexRemoveRow(env, table, rowIdx, oldRow);
15859
+ indexInsertRow(env, table, rowIdx, newRow);
15860
+ }
15861
+ function rebuildTableIndexes(env, table) {
15862
+ table.indexStores = null;
15863
+ ensureIndexStores(env, table);
15864
+ }
15865
+
15866
+ // src/constraints/enforce.ts
15867
+ function tableScope(table, row) {
15868
+ const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
15869
+ return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
15870
+ }
15871
+ function checkNotNull(env, table, row) {
15872
+ void env;
15873
+ for (let i = 0; i < table.columns.length; i++) {
15874
+ const c = table.columns[i];
15875
+ if (c.notNull && (row[i] ?? null) === null) {
15876
+ throw pgError(
15877
+ "not_null_violation",
15878
+ `null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
15879
+ "23502"
15880
+ );
15881
+ }
15882
+ }
15883
+ }
15884
+ function checkChecks(env, table, row) {
15885
+ for (const con of table.constraints) {
15886
+ if (con.kind !== "check") continue;
15887
+ const scope = makeEvalScope(env, tableScope(table, row));
15888
+ const v = evalExpr(env.ctx, scope, con.expr);
15889
+ if (v.v === null) continue;
15890
+ const b = castTo(env.ctx, v, "bool", {});
15891
+ if (b.v !== true) {
15892
+ throw pgError(
15893
+ "check_violation",
15894
+ `new row for relation "${table.name}" violates check constraint "${con.name}"`,
15895
+ "23514"
15896
+ );
15897
+ }
15898
+ }
15899
+ }
15900
+ function uniqueSpecsFor(env, table) {
15901
+ const specs = [];
15902
+ for (const con of table.constraints) {
15903
+ if (con.kind !== "primary_key" && con.kind !== "unique") continue;
15904
+ specs.push({
15905
+ name: con.name,
15906
+ keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
15907
+ columnNames: con.columns,
15908
+ nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
15909
+ where: null,
15910
+ isPrimary: con.kind === "primary_key"
15911
+ });
15912
+ }
15913
+ const schema = env.ctx.state.schemas.get(table.schema);
15914
+ if (schema) {
15915
+ for (const idx of schema.indexes.values()) {
15916
+ if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
15917
+ specs.push(uniqueSpecOfIndex(table, idx));
15918
+ }
15919
+ }
15920
+ return specs;
15921
+ }
15922
+ function uniqueSpecOfIndex(table, idx) {
15923
+ return {
15924
+ name: idx.name,
15925
+ keys: idx.columns.map((c) => ({
15926
+ colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
15927
+ expr: c.expr
15928
+ })),
15929
+ columnNames: idx.columns.map((c) => c.column ?? "expr"),
15930
+ nullsNotDistinct: idx.nullsNotDistinct,
15931
+ where: idx.where,
15932
+ isPrimary: false
15933
+ };
15934
+ }
15935
+ function uniqueKeyOf(env, table, spec, row) {
15936
+ if (spec.where) {
15937
+ const scope = makeEvalScope(env, tableScope(table, row));
15938
+ const v = evalExpr(env.ctx, scope, spec.where);
15939
+ if (v.v !== true) return null;
15940
+ }
15941
+ const parts = [];
15942
+ let hasNull = false;
15943
+ for (const k of spec.keys) {
15944
+ let value;
15945
+ let type;
15946
+ if (k.expr) {
15947
+ const scope = makeEvalScope(env, tableScope(table, row));
15948
+ const v = evalExpr(env.ctx, scope, k.expr);
15949
+ value = v.v;
15950
+ type = v.t === "unknown" ? "text" : v.t;
15951
+ } else {
15952
+ value = row[k.colIdx] ?? null;
15953
+ type = table.columns[k.colIdx].type.id;
15954
+ }
15955
+ if (value === null) {
15956
+ hasNull = true;
15957
+ parts.push("\0N");
15958
+ } else {
15959
+ parts.push(datumKey(type, value));
15960
+ }
15961
+ }
15962
+ if (hasNull && !spec.nullsNotDistinct) return null;
15963
+ return parts.join("");
15964
+ }
15965
+ function checkUnique(env, table, row, selfIdx) {
15966
+ for (const spec of uniqueSpecsFor(env, table)) {
15967
+ const key = uniqueKeyOf(env, table, spec, row);
15968
+ if (key === null) continue;
15969
+ indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
15970
+ }
15971
+ }
15972
+ function findConflict(env, table, spec, row) {
15973
+ const key = uniqueKeyOf(env, table, spec, row);
15974
+ if (key === null) return null;
15975
+ const hits = indexStoreFor(env, table, spec).lookup(key);
15976
+ return hits.length > 0 ? hits[0] : null;
15977
+ }
15978
+ function checkForeignKeys(env, table, row) {
15979
+ const state = env.ctx.state;
15980
+ for (const con of table.constraints) {
15981
+ if (con.kind !== "foreign_key") continue;
15982
+ const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
15983
+ const nulls = values.filter((v) => v === null).length;
15984
+ if (con.match === "simple" && nulls > 0) continue;
15985
+ if (con.match === "full") {
15986
+ if (nulls === values.length) continue;
15987
+ if (nulls > 0) {
15988
+ throw pgError(
15989
+ "constraint_foreign_key",
15990
+ `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
15991
+ "23503"
15992
+ );
15993
+ }
15994
+ }
15995
+ const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
15996
+ if (!refTable) {
15997
+ throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
15998
+ }
15999
+ const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
16000
+ const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
16001
+ const wanted = values.map((v, i) => {
16002
+ const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
16003
+ const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
16004
+ return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
16005
+ }).join("");
16006
+ let found = false;
16007
+ for (let i = 0; i < refTable.rowCount(); i++) {
16008
+ const r = refTable.rowAt(i);
16009
+ const key = refIdxs.map((ri, j) => {
16010
+ const v = r[ri] ?? null;
16011
+ return v === null ? "\0N" : datumKey(keyTypes[j], v);
16012
+ }).join("");
16013
+ if (key === wanted) {
16014
+ found = true;
16015
+ break;
16016
+ }
16017
+ }
16018
+ if (!found) {
16019
+ throw pgError(
16020
+ "constraint_foreign_key",
16021
+ `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
16022
+ "23503"
16023
+ );
15738
16024
  }
15739
16025
  }
15740
- table.indexStores = stores;
15741
- return stores;
15742
16026
  }
15743
- function indexStoreFor(env, table, spec) {
15744
- const stores = ensureIndexStores(env, table);
15745
- let store = stores.get(spec.name);
15746
- if (!store) {
15747
- store = new IndexStore(spec.name, true);
15748
- for (let i = 0; i < table.rowCount(); i++) {
15749
- const key = uniqueKeyOf(env, table, spec, table.rowAt(i));
15750
- if (key !== null) store.insert(key, i);
16027
+ function referencingConstraints(env, table) {
16028
+ const out = [];
16029
+ for (const schema of env.ctx.state.schemas.values()) {
16030
+ for (const t of schema.tables.values()) {
16031
+ for (const con of t.constraints) {
16032
+ if (con.kind === "foreign_key" && con.refSchema === table.schema && con.refTable === table.name) {
16033
+ out.push({ table: t, constraint: con });
16034
+ }
16035
+ }
15751
16036
  }
15752
- stores.set(spec.name, store);
15753
- }
15754
- return store;
15755
- }
15756
- function indexInsertRow(env, table, rowIdx, row) {
15757
- for (const spec of uniqueSpecsFor(env, table)) {
15758
- const key = uniqueKeyOf(env, table, spec, row);
15759
- if (key === null) continue;
15760
- indexStoreFor(env, table, spec).insert(key, rowIdx);
15761
- }
15762
- }
15763
- function indexRemoveRow(env, table, rowIdx, row) {
15764
- if (!table.indexStores) return;
15765
- for (const spec of uniqueSpecsFor(env, table)) {
15766
- const key = uniqueKeyOf(env, table, spec, row);
15767
- if (key === null) continue;
15768
- table.indexStores.get(spec.name)?.remove(key, rowIdx);
15769
16037
  }
15770
- }
15771
- function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
15772
- indexRemoveRow(env, table, rowIdx, oldRow);
15773
- indexInsertRow(env, table, rowIdx, newRow);
15774
- }
15775
- function rebuildTableIndexes(env, table) {
15776
- table.indexStores = null;
15777
- ensureIndexStores(env, table);
16038
+ return out;
15778
16039
  }
15779
16040
 
15780
16041
  // src/planner/access.ts
@@ -15852,7 +16113,7 @@ function tryIndexedFromItem(env, item, where) {
15852
16113
  if (!table) return null;
15853
16114
  const alias = item.alias ?? item.name[item.name.length - 1];
15854
16115
  table.materializeSlab();
15855
- return tryIndexedTableRows(env, table, alias, where);
16116
+ return tryIndexedTableRows(env, table, alias, where)?.map((row) => [...row, table.rowXmins.get(row) ?? 2]) ?? null;
15856
16117
  }
15857
16118
  function joinKeyFromRow(row, colIdxs, srcTypes, unifiedTypes, ctx) {
15858
16119
  const parts = [];
@@ -17660,10 +17921,9 @@ var Parser = class {
17660
17921
  return this.parseCreateFunction(orReplace);
17661
17922
  }
17662
17923
  if (this.atKw("trigger") || this.atKw("constraint") && this.atKw("trigger", 1)) {
17663
- if (this.eatKw("constraint")) {
17664
- }
17924
+ const constraint = this.eatKw("constraint");
17665
17925
  this.expectKw("trigger");
17666
- return this.parseCreateTrigger(orReplace);
17926
+ return this.parseCreateTrigger(orReplace, constraint);
17667
17927
  }
17668
17928
  if (this.atKw("extension")) {
17669
17929
  this.pos++;
@@ -18343,6 +18603,7 @@ var Parser = class {
18343
18603
  let sqlBody = null;
18344
18604
  let volatility = null;
18345
18605
  let strict2 = false;
18606
+ const settings = {};
18346
18607
  for (; ; ) {
18347
18608
  if (this.eatKw("language")) {
18348
18609
  language = this.peek().type === "string" ? this.next().value : this.ident(true);
@@ -18400,8 +18661,23 @@ var Parser = class {
18400
18661
  continue;
18401
18662
  }
18402
18663
  if (this.eatKw("set")) {
18403
- this.ident(true);
18404
- if (this.eatOp("=") || this.eatKw("to")) this.next();
18664
+ const key = this.ident(true).toLowerCase();
18665
+ if (this.eatKw("from")) {
18666
+ this.expectKw("current");
18667
+ settings[key] = "__from_current__";
18668
+ } else {
18669
+ if (!this.eatOp("=")) this.expectKw("to");
18670
+ const values = [];
18671
+ do {
18672
+ const value = this.next();
18673
+ if (!["string", "ident", "quoted_ident", "number"].includes(value.type))
18674
+ this.errorAt(value, "expected setting value");
18675
+ values.push(
18676
+ key === "search_path" && /[^a-z0-9_]/.test(value.value) ? `"${value.value.replaceAll('"', '""')}"` : value.value
18677
+ );
18678
+ } while (this.eatPunct(","));
18679
+ settings[key] = values.join(", ");
18680
+ }
18405
18681
  continue;
18406
18682
  }
18407
18683
  if (this.eatKw("window")) throw unsupported("window functions via CREATE FUNCTION");
@@ -18481,10 +18757,11 @@ var Parser = class {
18481
18757
  body,
18482
18758
  sqlBody,
18483
18759
  volatility,
18484
- strict: strict2
18760
+ strict: strict2,
18761
+ settings
18485
18762
  };
18486
18763
  }
18487
- parseCreateTrigger(orReplace) {
18764
+ parseCreateTrigger(orReplace, constraint) {
18488
18765
  const name = this.ident();
18489
18766
  let timing;
18490
18767
  if (this.eatKw("before")) timing = "before";
@@ -18514,9 +18791,18 @@ var Parser = class {
18514
18791
  this.expectKw("on");
18515
18792
  const table = this.qualifiedName();
18516
18793
  if (this.eatKw("referencing")) throw unsupported("trigger transition tables");
18517
- while (this.atKw("not") || this.atKw("deferrable") || this.atKw("initially")) {
18518
- this.pos++;
18519
- }
18794
+ let deferrable = false;
18795
+ let initiallyDeferred = false;
18796
+ if (this.eatKw("not")) this.expectKw("deferrable");
18797
+ else if (this.eatKw("deferrable")) deferrable = true;
18798
+ if (this.eatKw("initially")) {
18799
+ if (this.eatKw("deferred")) initiallyDeferred = true;
18800
+ else this.expectKw("immediate");
18801
+ }
18802
+ if ((deferrable || initiallyDeferred) && !constraint)
18803
+ this.errorAt(this.peek(), "only constraint triggers can be deferred");
18804
+ if (initiallyDeferred && !deferrable)
18805
+ this.errorAt(this.peek(), "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
18520
18806
  let forEachRow = false;
18521
18807
  if (this.eatKw("for")) {
18522
18808
  this.eatKw("each");
@@ -18541,7 +18827,21 @@ var Parser = class {
18541
18827
  } while (this.eatPunct(","));
18542
18828
  }
18543
18829
  this.expectPunct(")");
18544
- return { type: "create_trigger", orReplace, name, timing, events, table, forEachRow, when, funcName, funcArgs };
18830
+ return {
18831
+ type: "create_trigger",
18832
+ constraint,
18833
+ deferrable,
18834
+ initiallyDeferred,
18835
+ orReplace,
18836
+ name,
18837
+ timing,
18838
+ events,
18839
+ table,
18840
+ forEachRow,
18841
+ when,
18842
+ funcName,
18843
+ funcArgs
18844
+ };
18545
18845
  }
18546
18846
  // --- ALTER --------------------------------------------------------------------
18547
18847
  parseAlter() {
@@ -18567,8 +18867,8 @@ var Parser = class {
18567
18867
  type: "alter_sequence",
18568
18868
  name,
18569
18869
  ifExists,
18570
- options: { ownedBy: void 0 },
18571
- ...{ renameTo: to }
18870
+ options: {},
18871
+ renameTo: to
18572
18872
  };
18573
18873
  }
18574
18874
  if (this.atKw("set") && (this.atKw("logged", 1) || this.atKw("unlogged", 1))) {
@@ -18886,9 +19186,15 @@ var Parser = class {
18886
19186
  this.skipToStatementEnd();
18887
19187
  return { type: "no_op", what: "SET TRANSACTION" };
18888
19188
  }
18889
- if (this.atKw("constraints")) {
18890
- this.skipToStatementEnd();
18891
- return { type: "no_op", what: "SET CONSTRAINTS" };
19189
+ if (this.eatKw("constraints")) {
19190
+ const names = this.eatKw("all") ? null : [];
19191
+ if (names)
19192
+ do {
19193
+ names.push(this.qualifiedName());
19194
+ } while (this.eatPunct(","));
19195
+ const deferred = this.eatKw("deferred");
19196
+ if (!deferred) this.expectKw("immediate");
19197
+ return { type: "set_constraints", names, deferred };
18892
19198
  }
18893
19199
  if (this.atKw("role") || this.atKw("session", 0) && this.atKw("authorization", 1)) {
18894
19200
  this.skipToStatementEnd();
@@ -21138,7 +21444,20 @@ function runFunctionBody(env, fn, args) {
21138
21444
  }
21139
21445
  return last;
21140
21446
  }
21447
+ function withFunctionSettings(env, fn, run) {
21448
+ const state = env.ctx.state;
21449
+ const saved = new Map(state.localSettings);
21450
+ for (const [name, value] of Object.entries(fn.settings ?? {})) state.localSettings.set(name, value);
21451
+ try {
21452
+ return run();
21453
+ } finally {
21454
+ state.localSettings = saved;
21455
+ }
21456
+ }
21141
21457
  function callSqlFunctionScalar(env, fn, args) {
21458
+ return withFunctionSettings(env, fn, () => callSqlFunctionScalarBody(env, fn, args));
21459
+ }
21460
+ function callSqlFunctionScalarBody(env, fn, args) {
21142
21461
  const retT = fn.returns ?? "text";
21143
21462
  if (fn.language === "plpgsql") {
21144
21463
  return callPlpgsqlScalar(env, fn, args);
@@ -21168,6 +21487,9 @@ function callSqlFunctionScalar(env, fn, args) {
21168
21487
  return castTo(env.ctx, tv(rawT, raw), retT, {});
21169
21488
  }
21170
21489
  function callSqlFunctionSet(env, fn, args) {
21490
+ return withFunctionSettings(env, fn, () => callSqlFunctionSetBody(env, fn, args));
21491
+ }
21492
+ function callSqlFunctionSetBody(env, fn, args) {
21171
21493
  if (fn.language === "plpgsql") {
21172
21494
  return callPlpgsqlSet(env, fn, args);
21173
21495
  }
@@ -21263,12 +21585,12 @@ function executeRecursiveCte(env, cte, query) {
21263
21585
  table: null
21264
21586
  }));
21265
21587
  const seen = /* @__PURE__ */ new Set();
21266
- const keyOf = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(columns[i].type, v)).join("");
21588
+ const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(columns[i].type, v)).join("");
21267
21589
  let result = [];
21268
21590
  let working = [];
21269
21591
  for (const row of base.rows) {
21270
21592
  if (!body.all) {
21271
- const k = keyOf(row);
21593
+ const k = keyOf2(row);
21272
21594
  if (seen.has(k)) continue;
21273
21595
  seen.add(k);
21274
21596
  }
@@ -21301,7 +21623,7 @@ function executeRecursiveCte(env, cte, query) {
21301
21623
  return castTo(env.ctx, tv(srcT === UNKNOWN ? "text" : srcT, v), columns[i].type, {}).v;
21302
21624
  });
21303
21625
  if (!body.all) {
21304
- const k = keyOf(row);
21626
+ const k = keyOf2(row);
21305
21627
  if (seen.has(k)) continue;
21306
21628
  seen.add(k);
21307
21629
  }
@@ -21322,15 +21644,17 @@ function executeRecursiveCte(env, cte, query) {
21322
21644
  return rel3;
21323
21645
  }
21324
21646
  function renameWithAliases(rel3, label, colAliases, what) {
21325
- if (colAliases && colAliases.length > rel3.columns.length) {
21647
+ const visibleWidth = rel3.columns.filter((column) => !column.system).length;
21648
+ if (colAliases && colAliases.length > visibleWidth) {
21326
21649
  throw pgError(
21327
21650
  "invalid_column_reference",
21328
- `table "${what}" has ${rel3.columns.length} columns available but ${colAliases.length} columns specified`,
21651
+ `table "${what}" has ${visibleWidth} columns available but ${colAliases.length} columns specified`,
21329
21652
  "42P10"
21330
21653
  );
21331
21654
  }
21332
21655
  const columns = rel3.columns.map((c, i) => ({
21333
- name: colAliases?.[i] ?? c.name,
21656
+ ...c,
21657
+ name: c.system ? c.name : colAliases?.[i] ?? c.name,
21334
21658
  type: c.type === UNKNOWN ? "text" : c.type,
21335
21659
  table: label
21336
21660
  }));
@@ -21351,8 +21675,11 @@ function materializeItem(env, item, scope) {
21351
21675
  if (table) {
21352
21676
  table.materializeSlab();
21353
21677
  const rel3 = {
21354
- columns: table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
21355
- rows: table.rows
21678
+ columns: [
21679
+ ...table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
21680
+ { name: "xmin", type: "xid", table: label, hidden: true, system: true }
21681
+ ],
21682
+ rows: table.rows.map((row) => [...row, table.rowXmins.get(row) ?? 2])
21356
21683
  };
21357
21684
  return { rel: renameWithAliases(rel3, label, item.colAliases, label), rangeVars: /* @__PURE__ */ new Set([label]) };
21358
21685
  }
@@ -21982,7 +22309,7 @@ function resolveColIdx(columns, parts) {
21982
22309
  let found = -1;
21983
22310
  for (let i = 0; i < columns.length; i++) {
21984
22311
  const c = columns[i];
21985
- if (!c.hidden && c.name === name2) {
22312
+ if ((!c.hidden || c.system) && c.name === name2) {
21986
22313
  if (found !== -1) return null;
21987
22314
  found = i;
21988
22315
  }
@@ -22481,7 +22808,7 @@ function setOpRelation(env, op) {
22481
22808
  );
22482
22809
  const lrows = normalize(left);
22483
22810
  const rrows = normalize(right);
22484
- const keyOf = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
22811
+ const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
22485
22812
  let rows;
22486
22813
  switch (op.op) {
22487
22814
  case "union": {
@@ -22489,7 +22816,7 @@ function setOpRelation(env, op) {
22489
22816
  if (!op.all) {
22490
22817
  const seen = /* @__PURE__ */ new Set();
22491
22818
  rows = rows.filter((r) => {
22492
- const k = keyOf(r);
22819
+ const k = keyOf2(r);
22493
22820
  if (seen.has(k)) return false;
22494
22821
  seen.add(k);
22495
22822
  return true;
@@ -22500,13 +22827,13 @@ function setOpRelation(env, op) {
22500
22827
  case "intersect": {
22501
22828
  const rightCounts = /* @__PURE__ */ new Map();
22502
22829
  for (const r of rrows) {
22503
- const k = keyOf(r);
22830
+ const k = keyOf2(r);
22504
22831
  rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
22505
22832
  }
22506
22833
  rows = [];
22507
22834
  const emitted = /* @__PURE__ */ new Set();
22508
22835
  for (const r of lrows) {
22509
- const k = keyOf(r);
22836
+ const k = keyOf2(r);
22510
22837
  const avail = rightCounts.get(k) ?? 0;
22511
22838
  if (avail <= 0) continue;
22512
22839
  if (op.all) {
@@ -22522,13 +22849,13 @@ function setOpRelation(env, op) {
22522
22849
  case "except": {
22523
22850
  const rightCounts = /* @__PURE__ */ new Map();
22524
22851
  for (const r of rrows) {
22525
- const k = keyOf(r);
22852
+ const k = keyOf2(r);
22526
22853
  rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
22527
22854
  }
22528
22855
  rows = [];
22529
22856
  const emitted = /* @__PURE__ */ new Set();
22530
22857
  for (const r of lrows) {
22531
- const k = keyOf(r);
22858
+ const k = keyOf2(r);
22532
22859
  if (op.all) {
22533
22860
  const avail = rightCounts.get(k) ?? 0;
22534
22861
  if (avail > 0) {
@@ -22566,7 +22893,7 @@ function expandTargets(core, columns) {
22566
22893
  let any = false;
22567
22894
  for (let i = 0; i < columns.length; i++) {
22568
22895
  const c = columns[i];
22569
- if (c.table === label) {
22896
+ if (c.table === label && !c.system) {
22570
22897
  any = true;
22571
22898
  items.push({ name: c.name, kind: "col", colIdx: i, expr: null, hidden: false });
22572
22899
  }
@@ -22998,185 +23325,32 @@ function executeSelectStmt(env0, stmt) {
22998
23325
  if (stmt.orderBy.length === 0) {
22999
23326
  throw pgError("syntax", "WITH TIES cannot be specified without ORDER BY clause", "42601");
23000
23327
  }
23001
- const tieSpecs = outputOrderSpecs(env, rel3, stmt.orderBy);
23002
- return stripHidden(applyLimitOffset(env, rel3, stmt.limit, stmt.offset, tieSpecs));
23003
- }
23004
- return applyLimitOffset(env, rel3, stmt.limit, stmt.offset);
23005
- }
23006
-
23007
- // src/constraints/enforce.ts
23008
- function tableScope(table, row) {
23009
- const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
23010
- return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
23011
- }
23012
- function checkNotNull(env, table, row) {
23013
- void env;
23014
- for (let i = 0; i < table.columns.length; i++) {
23015
- const c = table.columns[i];
23016
- if (c.notNull && (row[i] ?? null) === null) {
23017
- throw pgError(
23018
- "not_null_violation",
23019
- `null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
23020
- "23502"
23021
- );
23022
- }
23023
- }
23024
- }
23025
- function checkChecks(env, table, row) {
23026
- for (const con of table.constraints) {
23027
- if (con.kind !== "check") continue;
23028
- const scope = makeEvalScope(env, tableScope(table, row));
23029
- const v = evalExpr(env.ctx, scope, con.expr);
23030
- if (v.v === null) continue;
23031
- const b = castTo(env.ctx, v, "bool", {});
23032
- if (b.v !== true) {
23033
- throw pgError(
23034
- "check_violation",
23035
- `new row for relation "${table.name}" violates check constraint "${con.name}"`,
23036
- "23514"
23037
- );
23038
- }
23039
- }
23040
- }
23041
- function uniqueSpecsFor(env, table) {
23042
- const specs = [];
23043
- for (const con of table.constraints) {
23044
- if (con.kind !== "primary_key" && con.kind !== "unique") continue;
23045
- specs.push({
23046
- name: con.name,
23047
- keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
23048
- columnNames: con.columns,
23049
- nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
23050
- where: null,
23051
- isPrimary: con.kind === "primary_key"
23052
- });
23053
- }
23054
- const schema = env.ctx.state.schemas.get(table.schema);
23055
- if (schema) {
23056
- for (const idx of schema.indexes.values()) {
23057
- if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
23058
- specs.push(uniqueSpecOfIndex(table, idx));
23059
- }
23060
- }
23061
- return specs;
23062
- }
23063
- function uniqueSpecOfIndex(table, idx) {
23064
- return {
23065
- name: idx.name,
23066
- keys: idx.columns.map((c) => ({
23067
- colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
23068
- expr: c.expr
23069
- })),
23070
- columnNames: idx.columns.map((c) => c.column ?? "expr"),
23071
- nullsNotDistinct: idx.nullsNotDistinct,
23072
- where: idx.where,
23073
- isPrimary: false
23074
- };
23075
- }
23076
- function uniqueKeyOf(env, table, spec, row) {
23077
- if (spec.where) {
23078
- const scope = makeEvalScope(env, tableScope(table, row));
23079
- const v = evalExpr(env.ctx, scope, spec.where);
23080
- if (v.v !== true) return null;
23081
- }
23082
- const parts = [];
23083
- let hasNull = false;
23084
- for (const k of spec.keys) {
23085
- let value;
23086
- let type;
23087
- if (k.expr) {
23088
- const scope = makeEvalScope(env, tableScope(table, row));
23089
- const v = evalExpr(env.ctx, scope, k.expr);
23090
- value = v.v;
23091
- type = v.t === "unknown" ? "text" : v.t;
23092
- } else {
23093
- value = row[k.colIdx] ?? null;
23094
- type = table.columns[k.colIdx].type.id;
23095
- }
23096
- if (value === null) {
23097
- hasNull = true;
23098
- parts.push("\0N");
23099
- } else {
23100
- parts.push(datumKey(type, value));
23101
- }
23102
- }
23103
- if (hasNull && !spec.nullsNotDistinct) return null;
23104
- return parts.join("");
23105
- }
23106
- function checkUnique(env, table, row, selfIdx) {
23107
- for (const spec of uniqueSpecsFor(env, table)) {
23108
- const key = uniqueKeyOf(env, table, spec, row);
23109
- if (key === null) continue;
23110
- indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
23111
- }
23112
- }
23113
- function findConflict(env, table, spec, row) {
23114
- const key = uniqueKeyOf(env, table, spec, row);
23115
- if (key === null) return null;
23116
- const hits = indexStoreFor(env, table, spec).lookup(key);
23117
- return hits.length > 0 ? hits[0] : null;
23118
- }
23119
- function checkForeignKeys(env, table, row) {
23120
- const state = env.ctx.state;
23121
- for (const con of table.constraints) {
23122
- if (con.kind !== "foreign_key") continue;
23123
- const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
23124
- const nulls = values.filter((v) => v === null).length;
23125
- if (con.match === "simple" && nulls > 0) continue;
23126
- if (con.match === "full") {
23127
- if (nulls === values.length) continue;
23128
- if (nulls > 0) {
23129
- throw pgError(
23130
- "constraint_foreign_key",
23131
- `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
23132
- "23503"
23133
- );
23134
- }
23135
- }
23136
- const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
23137
- if (!refTable) {
23138
- throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
23139
- }
23140
- const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
23141
- const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
23142
- const wanted = values.map((v, i) => {
23143
- const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
23144
- const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
23145
- return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
23146
- }).join("");
23147
- let found = false;
23148
- for (let i = 0; i < refTable.rowCount(); i++) {
23149
- const r = refTable.rowAt(i);
23150
- const key = refIdxs.map((ri, j) => {
23151
- const v = r[ri] ?? null;
23152
- return v === null ? "\0N" : datumKey(keyTypes[j], v);
23153
- }).join("");
23154
- if (key === wanted) {
23155
- found = true;
23156
- break;
23157
- }
23158
- }
23159
- if (!found) {
23160
- throw pgError(
23161
- "constraint_foreign_key",
23162
- `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
23163
- "23503"
23164
- );
23165
- }
23328
+ const tieSpecs = outputOrderSpecs(env, rel3, stmt.orderBy);
23329
+ return stripHidden(applyLimitOffset(env, rel3, stmt.limit, stmt.offset, tieSpecs));
23166
23330
  }
23331
+ return applyLimitOffset(env, rel3, stmt.limit, stmt.offset);
23167
23332
  }
23168
- function referencingConstraints(env, table) {
23169
- const out = [];
23170
- for (const schema of env.ctx.state.schemas.values()) {
23171
- for (const t of schema.tables.values()) {
23172
- for (const con of t.constraints) {
23173
- if (con.kind === "foreign_key" && con.refSchema === table.schema && con.refTable === table.name) {
23174
- out.push({ table: t, constraint: con });
23175
- }
23176
- }
23333
+
23334
+ // src/executor/triggers-scope.ts
23335
+ function triggerScope(table, newRow, oldRow) {
23336
+ const cols = [];
23337
+ const row = [];
23338
+ const rangeVars = /* @__PURE__ */ new Set();
23339
+ if (newRow) {
23340
+ rangeVars.add("new");
23341
+ for (let i = 0; i < table.columns.length; i++) {
23342
+ cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
23343
+ row.push(newRow[i] ?? null);
23177
23344
  }
23178
23345
  }
23179
- return out;
23346
+ if (oldRow) {
23347
+ rangeVars.add("old");
23348
+ for (let i = 0; i < table.columns.length; i++) {
23349
+ cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
23350
+ row.push(oldRow[i] ?? null);
23351
+ }
23352
+ }
23353
+ return new RowScope(cols, row, null, rangeVars);
23180
23354
  }
23181
23355
 
23182
23356
  // src/executor/triggers.ts
@@ -23192,6 +23366,18 @@ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
23192
23366
  for (const t of table.triggers) {
23193
23367
  if (t.timing !== timing || !matches2(t, event) || !t.forEachRow) continue;
23194
23368
  if (!executor) throw unsupported(`trigger "${t.name}" execution`);
23369
+ if (t.constraint && timing === "after") {
23370
+ if (t.when && !evalPredicate(env, triggerScope(table, newRow, oldRow), t.when)) continue;
23371
+ env.ctx.state.pendingTriggers.push({
23372
+ schema: table.schema,
23373
+ table: table.name,
23374
+ trigger: t.name,
23375
+ event,
23376
+ oldRow: oldRow?.slice() ?? null,
23377
+ newRow: newRow?.slice() ?? null
23378
+ });
23379
+ continue;
23380
+ }
23195
23381
  const result = executor(env, table, t, event, oldRow, timing === "before" ? row : newRow);
23196
23382
  if (timing === "before") {
23197
23383
  if (result === null) return { row: null };
@@ -23200,6 +23386,170 @@ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
23200
23386
  }
23201
23387
  return { row };
23202
23388
  }
23389
+ var keyOf = (schema, name) => JSON.stringify([schema, name]);
23390
+ function flushConstraintTriggers(state, all = false) {
23391
+ const env = { ctx: new EngineCtx(state), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
23392
+ for (let i = 0; i < state.pendingTriggers.length; ) {
23393
+ const pending = state.pendingTriggers[i];
23394
+ const table = state.schemas.get(pending.schema)?.tables.get(pending.table);
23395
+ const trigger = table?.triggers.find((t) => t.name === pending.trigger);
23396
+ if (!table || !trigger) {
23397
+ state.pendingTriggers.splice(i, 1);
23398
+ continue;
23399
+ }
23400
+ const deferred = trigger.deferrable && (state.constraintModes.get(keyOf(table.schema, trigger.name)) ?? trigger.initiallyDeferred);
23401
+ if (!all && state.inTransaction && deferred) {
23402
+ i++;
23403
+ continue;
23404
+ }
23405
+ if (!executor) throw unsupported(`trigger "${trigger.name}" execution`);
23406
+ state.pendingTriggers.splice(i, 1);
23407
+ const changes = state.changes;
23408
+ try {
23409
+ executor(env, table, { ...trigger, when: null }, pending.event, pending.oldRow, pending.newRow);
23410
+ } catch (error) {
23411
+ state.pendingTriggers.splice(i, 0, pending);
23412
+ throw error;
23413
+ } finally {
23414
+ state.changes = changes;
23415
+ }
23416
+ }
23417
+ }
23418
+ function setConstraints(state, stmt) {
23419
+ if (!state.inTransaction) return;
23420
+ const matches3 = [];
23421
+ if (stmt.names) {
23422
+ for (const name of stmt.names) {
23423
+ const schemas = name.length > 1 ? [name[name.length - 2]] : state.effectiveSearchPath();
23424
+ let found = false;
23425
+ for (const schema of schemas) {
23426
+ const items = [...state.schemas.get(schema)?.tables.values() ?? []].flatMap(
23427
+ (table) => table.triggers.filter((t) => t.constraint && t.name === name[name.length - 1])
23428
+ );
23429
+ if (items.length) {
23430
+ for (const trigger of items) matches3.push({ schema, trigger });
23431
+ found = true;
23432
+ break;
23433
+ }
23434
+ }
23435
+ if (!found) throw pgError("undefined_object", `constraint "${name.join(".")}" does not exist`, "42704");
23436
+ }
23437
+ } else {
23438
+ for (const schema of state.schemas.values())
23439
+ for (const table of schema.tables.values())
23440
+ for (const trigger of table.triggers)
23441
+ if (trigger.constraint && trigger.deferrable) matches3.push({ schema: schema.name, trigger });
23442
+ }
23443
+ for (const { trigger } of matches3)
23444
+ if (stmt.deferred && !trigger.deferrable)
23445
+ throw pgError("misuse", `constraint "${trigger.name}" is not deferrable`, "55000");
23446
+ const previous = new Map(state.constraintModes);
23447
+ for (const { schema, trigger } of matches3) state.constraintModes.set(keyOf(schema, trigger.name), stmt.deferred);
23448
+ try {
23449
+ if (!stmt.deferred) flushConstraintTriggers(state);
23450
+ } catch (error) {
23451
+ state.constraintModes = previous;
23452
+ throw error;
23453
+ }
23454
+ }
23455
+
23456
+ // src/transactions/manager.ts
23457
+ var TransactionManager = class {
23458
+ constructor(state) {
23459
+ this.state = state;
23460
+ }
23461
+ state;
23462
+ base = null;
23463
+ savepoints = [];
23464
+ freezeDepth = 0;
23465
+ get inTransaction() {
23466
+ return this.base !== null;
23467
+ }
23468
+ takeSnapshot() {
23469
+ this.state.freezeShared();
23470
+ this.freezeDepth++;
23471
+ return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
23472
+ }
23473
+ restore(snap) {
23474
+ this.state.restoreFrom(snap.state);
23475
+ this.state.prng.setState(snap.prngState);
23476
+ }
23477
+ thawOnce() {
23478
+ if (this.freezeDepth > 0) {
23479
+ this.state.thawShared();
23480
+ this.freezeDepth--;
23481
+ }
23482
+ }
23483
+ begin() {
23484
+ if (this.base !== null) {
23485
+ return;
23486
+ }
23487
+ this.base = this.takeSnapshot();
23488
+ this.state.inTransaction = true;
23489
+ assert(this.freezeDepth === 1, "BEGIN freeze depth");
23490
+ }
23491
+ commit() {
23492
+ try {
23493
+ flushConstraintTriggers(this.state, true);
23494
+ } catch (error) {
23495
+ this.rollback();
23496
+ throw error;
23497
+ }
23498
+ this.base = null;
23499
+ this.savepoints = [];
23500
+ this.state.inTransaction = false;
23501
+ this.state.transactionXid = null;
23502
+ this.state.localSettings.clear();
23503
+ this.state.pendingTriggers = [];
23504
+ this.state.constraintModes.clear();
23505
+ while (this.freezeDepth > 0) this.thawOnce();
23506
+ }
23507
+ rollback() {
23508
+ if (this.base !== null) {
23509
+ this.restore(this.base);
23510
+ }
23511
+ this.base = null;
23512
+ this.savepoints = [];
23513
+ this.state.inTransaction = false;
23514
+ this.state.transactionXid = null;
23515
+ this.state.localSettings.clear();
23516
+ this.state.pendingTriggers = [];
23517
+ this.state.constraintModes.clear();
23518
+ while (this.freezeDepth > 0) this.thawOnce();
23519
+ }
23520
+ savepoint(name) {
23521
+ if (this.base === null) {
23522
+ throw pgError("transaction_state", "SAVEPOINT can only be used in transaction blocks", "25P01");
23523
+ }
23524
+ this.savepoints.push({ name, snap: this.takeSnapshot() });
23525
+ }
23526
+ releaseSavepoint(name) {
23527
+ const idx = this.findSavepoint(name);
23528
+ this.savepoints.splice(idx);
23529
+ }
23530
+ rollbackToSavepoint(name) {
23531
+ const idx = this.findSavepoint(name);
23532
+ const sp = this.savepoints[idx];
23533
+ this.restore(sp.snap);
23534
+ this.savepoints.splice(idx + 1);
23535
+ }
23536
+ findSavepoint(name) {
23537
+ if (this.base === null) {
23538
+ throw pgError("transaction_state", `SAVEPOINT can only be used in transaction blocks`, "25P01");
23539
+ }
23540
+ for (let i = this.savepoints.length - 1; i >= 0; i--) {
23541
+ if (this.savepoints[i].name === name) return i;
23542
+ }
23543
+ throw pgError("invalid_savepoint_specification", `savepoint "${name}" does not exist`, "3B001");
23544
+ }
23545
+ reset() {
23546
+ this.base = null;
23547
+ this.savepoints = [];
23548
+ this.state.inTransaction = false;
23549
+ this.state.transactionXid = null;
23550
+ this.freezeDepth = 0;
23551
+ }
23552
+ };
23203
23553
 
23204
23554
  // src/executor/dml.ts
23205
23555
  function withStatementRollback(env, fn) {
@@ -23400,6 +23750,7 @@ function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, whe
23400
23750
  const updated = existing.slice();
23401
23751
  applyUpdateSets(env, table, sets, scope, updated);
23402
23752
  computeGeneratedColumns(env, table, updated);
23753
+ table.rowXmins.set(updated, env.ctx.rowVersionXid());
23403
23754
  rows[existingIdx] = updated;
23404
23755
  indexUpdateRow(env, table, existingIdx, existing, updated);
23405
23756
  checkNotNull(env, table, updated);
@@ -23485,6 +23836,7 @@ function executeInsert(env0, stmt) {
23485
23836
  checkChecks(env, table, newRow);
23486
23837
  checkUnique(env, table, newRow, rows.length);
23487
23838
  checkForeignKeys(env, table, newRow);
23839
+ table.rowXmins.set(newRow, env.ctx.rowVersionXid());
23488
23840
  rows.push(newRow);
23489
23841
  indexInsertRow(env, table, rows.length - 1, newRow);
23490
23842
  insertedCount++;
@@ -23602,6 +23954,7 @@ function executeUpdate(env0, stmt) {
23602
23954
  if (fired.row === null) continue;
23603
23955
  const finalRow = fired.row;
23604
23956
  computeGeneratedColumns(env, table, finalRow);
23957
+ table.rowXmins.set(finalRow, env.ctx.rowVersionXid());
23605
23958
  rows[ri] = finalRow;
23606
23959
  try {
23607
23960
  checkNotNull(env, table, finalRow);
@@ -23721,6 +24074,7 @@ function handleReferencedDelete(env, table, row, depth) {
23721
24074
  for (const c of con.columns) {
23722
24075
  newRow[child.columnIndex(c)] = null;
23723
24076
  }
24077
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
23724
24078
  childRows[i] = newRow;
23725
24079
  checkNotNull(env, child, newRow);
23726
24080
  checkChecks(env, child, newRow);
@@ -23734,6 +24088,7 @@ function handleReferencedDelete(env, table, row, depth) {
23734
24088
  const ci = child.columnIndex(c);
23735
24089
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
23736
24090
  }
24091
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
23737
24092
  childRows[i] = newRow;
23738
24093
  checkNotNull(env, child, newRow);
23739
24094
  checkChecks(env, child, newRow);
@@ -23771,6 +24126,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
23771
24126
  const refIdx = table.columnIndex(con.refColumns[c]);
23772
24127
  newRow[localIdx] = newRows[r][refIdx] ?? null;
23773
24128
  }
24129
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
23774
24130
  childRows[i] = newRow;
23775
24131
  checkChecks(env, child, newRow);
23776
24132
  }
@@ -23780,6 +24136,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
23780
24136
  for (const i of idxs) {
23781
24137
  const newRow = childRows[i].slice();
23782
24138
  for (const c of con.columns) newRow[child.columnIndex(c)] = null;
24139
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
23783
24140
  childRows[i] = newRow;
23784
24141
  checkNotNull(env, child, newRow);
23785
24142
  }
@@ -23792,6 +24149,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
23792
24149
  const ci = child.columnIndex(c);
23793
24150
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
23794
24151
  }
24152
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
23795
24153
  childRows[i] = newRow;
23796
24154
  checkForeignKeys(env, child, newRow);
23797
24155
  }
@@ -23889,6 +24247,7 @@ function executeSet(env, stmt) {
23889
24247
  else target.delete(name);
23890
24248
  return commandResult("SET", 0);
23891
24249
  }
24250
+ validateStorageSetting(name, stmt.value);
23892
24251
  target.set(name, stmt.value);
23893
24252
  return commandResult("SET", 0);
23894
24253
  }
@@ -24194,64 +24553,6 @@ function executeCopyFromData(env, stmt, data) {
24194
24553
  };
24195
24554
  }
24196
24555
 
24197
- // src/expressions/context.ts
24198
- var EngineCtx = class {
24199
- state;
24200
- /** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
24201
- txNow;
24202
- /** statement timestamp */
24203
- stmtNow;
24204
- constructor(state, txNow) {
24205
- this.state = state;
24206
- const nowMs = state.clock().getTime();
24207
- const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
24208
- this.txNow = txNow ?? nowMicros;
24209
- this.stmtNow = nowMicros;
24210
- }
24211
- timezone() {
24212
- return this.state.getSetting("timezone") ?? "UTC";
24213
- }
24214
- namespaceOid(name) {
24215
- const oid = builtinNamespaceOid(name) ?? this.state.schemas.get(name)?.oid;
24216
- if (oid === void 0) throw pgError("undefined_object", `schema "${name}" does not exist`, "3F000");
24217
- return oid;
24218
- }
24219
- namespaceName(oid) {
24220
- const builtin = builtinNamespaceName(oid);
24221
- if (builtin !== void 0) return builtin;
24222
- for (const schema of this.state.schemas.values()) {
24223
- if (schema.oid === oid) return schema.name;
24224
- }
24225
- return null;
24226
- }
24227
- zoneOffsetAt(utcMicros) {
24228
- return zoneOffsetAtUtc(this.timezone(), utcMicros);
24229
- }
24230
- zoneOffsetForNaive(naiveMicros) {
24231
- return zoneOffsetForNaive(this.timezone(), naiveMicros);
24232
- }
24233
- enumLabels(enumType) {
24234
- if (!isEnumType(enumType)) return null;
24235
- const e = this.state.findEnumByKey(enumType.slice(5));
24236
- return e?.labels ?? null;
24237
- }
24238
- enumHasLabel(enumType, label) {
24239
- const labels = this.enumLabels(enumType);
24240
- return labels === null ? true : labels.includes(label);
24241
- }
24242
- enumOrder(enumType, label) {
24243
- const labels = this.enumLabels(enumType);
24244
- if (!labels) return 0;
24245
- const idx = labels.indexOf(label);
24246
- return idx === -1 ? labels.length : idx;
24247
- }
24248
- requireEnum(enumType) {
24249
- const labels = this.enumLabels(enumType);
24250
- if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
24251
- return labels;
24252
- }
24253
- };
24254
-
24255
24556
  // src/runtime/clock.ts
24256
24557
  var DEFAULT_NOW = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
24257
24558
  function fixedClock(instant = DEFAULT_NOW) {
@@ -25219,7 +25520,7 @@ function pgClass(ctx) {
25219
25520
  v.materialized ? "m" : "v",
25220
25521
  v.columns?.length ?? 0,
25221
25522
  v.matRows?.length ?? 0,
25222
- false,
25523
+ v.materialized && [...schemaData.indexes.values()].some((i) => i.tableOid === v.oid),
25223
25524
  !v.materialized || v.matRows !== null,
25224
25525
  relPersistence(v)
25225
25526
  );
@@ -25485,7 +25786,7 @@ function pgIndex(ctx) {
25485
25786
  const valid = i.valid !== false;
25486
25787
  rows.push([
25487
25788
  i.oid ?? 0,
25488
- table?.oid ?? 0,
25789
+ table?.oid ?? i.tableOid ?? 0,
25489
25790
  indexAttributeCount(i),
25490
25791
  i.columns.length,
25491
25792
  i.unique,
@@ -25657,7 +25958,7 @@ function pgStatUserIndexes(ctx) {
25657
25958
  for (const index of schema.indexes.values()) {
25658
25959
  const table = schema.tables.get(index.table);
25659
25960
  rows.push([
25660
- table?.oid ?? 0,
25961
+ table?.oid ?? index.tableOid ?? 0,
25661
25962
  index.oid ?? 0,
25662
25963
  schema.name,
25663
25964
  index.table,
@@ -26252,26 +26553,6 @@ function runTriggerBody(env, table, stmts, vars) {
26252
26553
  }
26253
26554
  }
26254
26555
  }
26255
- function triggerScope(table, newRow, oldRow) {
26256
- const cols = [];
26257
- const row = [];
26258
- const rangeVars = /* @__PURE__ */ new Set();
26259
- if (newRow) {
26260
- rangeVars.add("new");
26261
- for (let i = 0; i < table.columns.length; i++) {
26262
- cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
26263
- row.push(newRow[i] ?? null);
26264
- }
26265
- }
26266
- if (oldRow) {
26267
- rangeVars.add("old");
26268
- for (let i = 0; i < table.columns.length; i++) {
26269
- cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
26270
- row.push(oldRow[i] ?? null);
26271
- }
26272
- }
26273
- return new RowScope(cols, row, null, rangeVars);
26274
- }
26275
26556
  function executeTrigger(env, table, trigger, _event, oldRow, newRow) {
26276
26557
  const state = env.ctx.state;
26277
26558
  if (trigger.when !== null && !evalPredicate(env, triggerScope(table, newRow, oldRow), trigger.when)) {
@@ -26913,13 +27194,63 @@ function executeCreateSequence(env, stmt) {
26913
27194
  schema.sequences.set(name, seq);
26914
27195
  return commandResult("CREATE SEQUENCE", 0);
26915
27196
  }
27197
+ function renameSequenceReferences(env, seq, newName) {
27198
+ const state = env.ctx.state;
27199
+ const matches3 = (value) => {
27200
+ try {
27201
+ const input = parseRelationInput(value);
27202
+ if ("oid" in input) return input.oid === seq.oid;
27203
+ return state.findSequence(input.parts)?.oid === seq.oid;
27204
+ } catch {
27205
+ return false;
27206
+ }
27207
+ };
27208
+ const rewrite = (value) => {
27209
+ if (Array.isArray(value)) return value.map(rewrite);
27210
+ if (value === null || typeof value !== "object") return value;
27211
+ const node = value;
27212
+ const updated = Object.fromEntries(Object.entries(node).map(([key, child]) => [key, rewrite(child)]));
27213
+ const rewriteLiteral = (literal2) => {
27214
+ if (literal2 && typeof literal2 === "object" && "type" in literal2 && literal2.type === "string_lit" && "value" in literal2 && typeof literal2.value === "string" && matches3(literal2.value)) {
27215
+ return { ...literal2, value: [seq.schema, newName].map(quoteIdent).join(".") };
27216
+ }
27217
+ return literal2;
27218
+ };
27219
+ if (node.type === "func" && Array.isArray(node.name) && ["nextval", "currval", "setval"].includes(String(node.name.at(-1))) && Array.isArray(updated.args))
27220
+ updated.args[0] = rewriteLiteral(updated.args[0]);
27221
+ if (node.type === "cast" && node.target && typeof node.target === "object" && "parts" in node.target && Array.isArray(node.target.parts) && node.target.parts.at(-1) === "regclass")
27222
+ updated.expr = rewriteLiteral(updated.expr);
27223
+ return updated;
27224
+ };
27225
+ for (const schema of state.schemas.values()) {
27226
+ for (const table of [...schema.tables.values()]) {
27227
+ const writable = state.ensureWritableTable(table);
27228
+ for (const column of writable.columns) {
27229
+ if (column.defaultExpr) column.defaultExpr = rewrite(column.defaultExpr);
27230
+ if (column.identity?.sequence === `${seq.schema}.${seq.name}`)
27231
+ column.identity = { ...column.identity, sequence: `${seq.schema}.${newName}` };
27232
+ }
27233
+ }
27234
+ }
27235
+ }
26916
27236
  function executeAlterSequence(env, stmt) {
26917
27237
  const state = env.ctx.state;
26918
- const seq = state.findSequence(stmt.name);
26919
- if (!seq) {
27238
+ const foundSequence = state.findSequence(stmt.name);
27239
+ if (!foundSequence) {
26920
27240
  if (stmt.ifExists) return commandResult("ALTER SEQUENCE", 0);
26921
27241
  throw pgError("undefined_table", `relation "${stmt.name.join(".")}" does not exist`, "42P01");
26922
27242
  }
27243
+ const seq = state.ensureWritableSequence(foundSequence);
27244
+ if (stmt.renameTo) {
27245
+ const schema = state.getSchema(seq.schema);
27246
+ if (schema.hasRelation(stmt.renameTo))
27247
+ throw pgError("duplicate_table", `relation "${stmt.renameTo}" already exists`, "42P07");
27248
+ renameSequenceReferences(env, seq, stmt.renameTo);
27249
+ schema.sequences.delete(seq.name);
27250
+ seq.name = stmt.renameTo;
27251
+ schema.sequences.set(seq.name, seq);
27252
+ return commandResult("ALTER SEQUENCE", 0);
27253
+ }
26923
27254
  const o = stmt.options;
26924
27255
  if (o.logged !== void 0) {
26925
27256
  setSequenceLogged(state, seq, o.logged);
@@ -26977,7 +27308,7 @@ function buildColumn(env, schema, tableName2, def, out, taken) {
26977
27308
  col.defaultExpr = {
26978
27309
  type: "func",
26979
27310
  name: ["nextval"],
26980
- args: [{ type: "string_lit", value: `${schema.name}.${seqName}` }]
27311
+ args: [{ type: "string_lit", value: [schema.name, seqName].map(quoteIdent).join(".") }]
26981
27312
  };
26982
27313
  }
26983
27314
  for (const c of def.constraints) {
@@ -27230,7 +27561,11 @@ function executeCreateTableAs(env, stmt) {
27230
27561
  const table = new TableData(schema.name, name, columns, state.nextOid(), stmt.temp);
27231
27562
  table.unlogged = stmt.unlogged === true;
27232
27563
  if (stmt.withData) {
27233
- for (const row of rel3.rows) table.mutableRows().push(row.slice());
27564
+ for (const row of rel3.rows) {
27565
+ const stored = row.slice();
27566
+ table.rowXmins.set(stored, env.ctx.rowVersionXid());
27567
+ table.mutableRows().push(stored);
27568
+ }
27234
27569
  }
27235
27570
  schema.tables.set(name, table);
27236
27571
  const count2 = stmt.withData ? table.rowCount() : 0;
@@ -27238,7 +27573,8 @@ function executeCreateTableAs(env, stmt) {
27238
27573
  }
27239
27574
  function executeCreateIndex(env, stmt) {
27240
27575
  const state = env.ctx.state;
27241
- const table = state.findTable(stmt.table);
27576
+ const view = state.findView(stmt.table);
27577
+ const table = state.findTable(stmt.table) ?? (view?.materialized ? materializedTable(view) : void 0);
27242
27578
  if (!table) {
27243
27579
  throw pgError("undefined_table", `relation "${stmt.table.join(".")}" does not exist`, "42P01");
27244
27580
  }
@@ -27350,13 +27686,22 @@ function executeRefreshMatView(env, stmt) {
27350
27686
  if (!found?.materialized) {
27351
27687
  throw pgError("undefined_table", `materialized view "${stmt.name.join(".")}" does not exist`, "42P01");
27352
27688
  }
27689
+ const rel3 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), found.query);
27690
+ const next = {
27691
+ ...found,
27692
+ matColumns: rel3.columns.map((c, i) => ({
27693
+ name: found.columns?.[i] ?? c.name,
27694
+ type: c.type === UNKNOWN ? "text" : c.type
27695
+ })),
27696
+ matRows: stmt.withData ? rel3.rows : null
27697
+ };
27698
+ const table = materializedTable(next);
27699
+ for (const index of env.ctx.state.getSchema(found.schema).indexes.values()) {
27700
+ if (index.tableOid === found.oid && index.valid !== false) assertUniqueIndexBuildable(env, table, index);
27701
+ }
27353
27702
  const view = env.ctx.state.ensureWritableView(found);
27354
- const rel3 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), view.query);
27355
- view.matColumns = rel3.columns.map((c, i) => ({
27356
- name: view.columns?.[i] ?? c.name,
27357
- type: c.type === UNKNOWN ? "text" : c.type
27358
- }));
27359
- view.matRows = stmt.withData ? rel3.rows : null;
27703
+ view.matColumns = next.matColumns;
27704
+ view.matRows = next.matRows;
27360
27705
  return commandResult("REFRESH MATERIALIZED VIEW", 0);
27361
27706
  }
27362
27707
  function executeCreateSchema(env, stmt) {
@@ -27489,6 +27834,12 @@ function executeCreateFunction(env, stmt) {
27489
27834
  language: lang,
27490
27835
  body,
27491
27836
  rawBody: stmt.body,
27837
+ settings: Object.fromEntries(
27838
+ Object.entries(stmt.settings ?? {}).map(([key, value]) => [
27839
+ key,
27840
+ value === "__from_current__" ? state.getSetting(key) ?? "" : value
27841
+ ])
27842
+ ),
27492
27843
  strict: stmt.strict,
27493
27844
  oid: state.nextOid()
27494
27845
  };
@@ -27498,6 +27849,8 @@ function executeCreateFunction(env, stmt) {
27498
27849
  return commandResult("CREATE FUNCTION", 0);
27499
27850
  }
27500
27851
  function executeCreateTrigger(env, stmt) {
27852
+ if (stmt.constraint && (stmt.timing !== "after" || !stmt.forEachRow))
27853
+ throw pgError("syntax", "constraint triggers must be AFTER ROW triggers", "42601");
27501
27854
  const state = env.ctx.state;
27502
27855
  const found = state.findTable(stmt.table);
27503
27856
  if (!found) {
@@ -27516,6 +27869,9 @@ function executeCreateTrigger(env, stmt) {
27516
27869
  }
27517
27870
  const meta = {
27518
27871
  name: stmt.name,
27872
+ constraint: stmt.constraint,
27873
+ deferrable: stmt.deferrable,
27874
+ initiallyDeferred: stmt.initiallyDeferred,
27519
27875
  timing: stmt.timing,
27520
27876
  events: stmt.events,
27521
27877
  forEachRow: stmt.forEachRow,
@@ -27668,6 +28024,7 @@ function executeAlterTable(env, stmt) {
27668
28024
  }
27669
28025
  const next = row.slice();
27670
28026
  next[idx] = nv;
28027
+ table.rowXmins.set(next, table.rowXmins.get(rows[i]) ?? 2);
27671
28028
  rows[i] = next;
27672
28029
  }
27673
28030
  col.type = resolved.column;
@@ -27769,6 +28126,11 @@ function executeAlterTable(env, stmt) {
27769
28126
  );
27770
28127
  }
27771
28128
  table.columns[idx].name = action.to;
28129
+ for (const seq of [...schema.sequences.values()]) {
28130
+ if (seq.ownedBy?.table === table.name && seq.ownedBy.column === action.from) {
28131
+ state.ensureWritableSequence(seq).ownedBy = { table: table.name, column: action.to };
28132
+ }
28133
+ }
27772
28134
  for (const con of table.constraints) {
27773
28135
  if (con.kind === "primary_key" || con.kind === "unique" || con.kind === "foreign_key") {
27774
28136
  con.columns = con.columns.map((c) => c === action.from ? action.to : c);
@@ -27805,6 +28167,11 @@ function executeAlterTable(env, stmt) {
27805
28167
  throw pgError("duplicate_table", `relation "${action.to}" already exists`, "42P07");
27806
28168
  }
27807
28169
  const oldName = table.name;
28170
+ for (const seq of [...schema.sequences.values()]) {
28171
+ if (seq.ownedBy?.table === oldName) {
28172
+ state.ensureWritableSequence(seq).ownedBy = { ...seq.ownedBy, table: action.to };
28173
+ }
28174
+ }
27808
28175
  schema.tables.delete(table.name);
27809
28176
  table.name = action.to;
27810
28177
  schema.tables.set(action.to, table);
@@ -28284,7 +28651,16 @@ function alterTableIsSelfContained(stmt) {
28284
28651
  return stmt.actions.length === 1 && action !== void 0 && SELF_CONTAINED_ALTER_ACTIONS.has(action.kind);
28285
28652
  }
28286
28653
  function executeStatement(env, stmt) {
28287
- if (!RESHAPES_TABLES.has(stmt.type)) return dispatchStatement(env, stmt);
28654
+ if (!RESHAPES_TABLES.has(stmt.type)) {
28655
+ if ((stmt.type === "insert" || stmt.type === "update" || stmt.type === "delete") && (env.ctx.state.pendingTriggers.length > 0 || env.ctx.state.findTable(stmt.table)?.triggers.some((t) => t.constraint))) {
28656
+ return withStatementRollback(env, () => {
28657
+ const result = dispatchStatement(env, stmt);
28658
+ flushConstraintTriggers(env.ctx.state);
28659
+ return result;
28660
+ });
28661
+ }
28662
+ return dispatchStatement(env, stmt);
28663
+ }
28288
28664
  try {
28289
28665
  return dispatchStatement(env, stmt);
28290
28666
  } finally {
@@ -28343,6 +28719,9 @@ function dispatchStatement(env, stmt) {
28343
28719
  return executeRefreshMatView(env, stmt);
28344
28720
  case "transaction":
28345
28721
  return executeTransaction(env, stmt);
28722
+ case "set_constraints":
28723
+ setConstraints(env.ctx.state, stmt);
28724
+ return commandResult("SET CONSTRAINTS", 0);
28346
28725
  case "set":
28347
28726
  return executeSet(env, stmt);
28348
28727
  case "show":