@crvouga/mockingbird-service-postgres 3.6.0 → 3.8.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/server.js CHANGED
@@ -2803,6 +2803,12 @@ var invalidName = () => {
2803
2803
  throw pgError("syntax", "invalid name syntax", "42602");
2804
2804
  };
2805
2805
  function parseNamespaceInput(text) {
2806
+ const parsed = parseRelationInput(text);
2807
+ if ("oid" in parsed) return parsed;
2808
+ if (parsed.parts.length !== 1) invalidName();
2809
+ return { name: parsed.parts[0] };
2810
+ }
2811
+ function parseRelationInput(text) {
2806
2812
  if (text === "-") return { oid: 0 };
2807
2813
  if (/^\d+$/.test(text)) return { oid: parseOidText(text) };
2808
2814
  const names = [];
@@ -2838,8 +2844,8 @@ function parseNamespaceInput(text) {
2838
2844
  skipSpace();
2839
2845
  if (at === text.length) invalidName();
2840
2846
  }
2841
- if (names.length !== 1) invalidName();
2842
- return { name: names[0] };
2847
+ if (names.length === 0 || names.length > 3) invalidName();
2848
+ return { parts: names };
2843
2849
  }
2844
2850
  function namespaceText(oid, name) {
2845
2851
  if (oid === 0) return "-";
@@ -2912,6 +2918,7 @@ var TYPE_ALIASES = {
2912
2918
  regtype: "regtype",
2913
2919
  regproc: "regproc",
2914
2920
  regnamespace: "regnamespace",
2921
+ xid: "xid",
2915
2922
  oid: "oid",
2916
2923
  void: "void",
2917
2924
  record: "record",
@@ -2988,6 +2995,7 @@ var TYPE_OIDS = {
2988
2995
  regproc: 24,
2989
2996
  text: 25,
2990
2997
  oid: 26,
2998
+ xid: 28,
2991
2999
  json: 114,
2992
3000
  float4: 700,
2993
3001
  float8: 701,
@@ -3307,6 +3315,7 @@ function recordText(rec, ctx) {
3307
3315
  return `(${parts.join(",")})`;
3308
3316
  }
3309
3317
  function datumText(t, v, ctx) {
3318
+ if (t === "regclass") return v === 0 ? "-" : ctx.relationName?.(v) ?? String(v);
3310
3319
  if (t === "regnamespace") return namespaceText(v, ctx.namespaceName?.(v));
3311
3320
  if (v === null) throw pgError("internal", "datumText called with null");
3312
3321
  if (isArrayType(t)) return arrayText(v, ctx);
@@ -3317,6 +3326,7 @@ function datumText(t, v, ctx) {
3317
3326
  case "int2":
3318
3327
  case "int4":
3319
3328
  case "oid":
3329
+ case "xid":
3320
3330
  return String(v);
3321
3331
  case "int8":
3322
3332
  return String(v);
@@ -3381,6 +3391,12 @@ function datumText(t, v, ctx) {
3381
3391
  }
3382
3392
  var UTC_INPUT = { zoneOffsetForNaive: () => 0 };
3383
3393
  function datumFromText(t, text, ctx) {
3394
+ if (t === "regclass") {
3395
+ const parsed = parseRelationInput(text);
3396
+ if ("oid" in parsed) return parsed.oid;
3397
+ if (!ctx.relationOid) throw unsupported("regclass input without a catalog");
3398
+ return ctx.relationOid(parsed.parts);
3399
+ }
3384
3400
  if (t === "regnamespace") {
3385
3401
  const parsed = parseNamespaceInput(text);
3386
3402
  if ("oid" in parsed) return parsed.oid;
@@ -3402,6 +3418,7 @@ function datumFromText(t, text, ctx) {
3402
3418
  case "int8":
3403
3419
  return parseIntegerText(text, t);
3404
3420
  case "oid":
3421
+ case "xid":
3405
3422
  return parseOidText(text);
3406
3423
  case "float4":
3407
3424
  return Math.fround(parseFloatText(text, "float4"));
@@ -3558,6 +3575,8 @@ var TableData = class _TableData {
3558
3575
  schema;
3559
3576
  columns;
3560
3577
  rows;
3578
+ rowXmins = /* @__PURE__ */ new WeakMap();
3579
+ slabXmins = null;
3561
3580
  /** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
3562
3581
  slab = null;
3563
3582
  constraints;
@@ -3600,6 +3619,11 @@ var TableData = class _TableData {
3600
3619
  materializeSlab() {
3601
3620
  if (!this.slab) return;
3602
3621
  this.rows = this.slab.materialize();
3622
+ if (this.slabXmins)
3623
+ this.rows.forEach((row, index) => {
3624
+ this.rowXmins.set(row, this.slabXmins[index] ?? 2);
3625
+ });
3626
+ this.slabXmins = null;
3603
3627
  this.slab = null;
3604
3628
  this.indexStores = null;
3605
3629
  }
@@ -3633,6 +3657,10 @@ var TableData = class _TableData {
3633
3657
  } else {
3634
3658
  t.rows = this.rows.map((r) => r.slice());
3635
3659
  }
3660
+ t.rows.forEach((row, index) => {
3661
+ const xmin = this.slabXmins?.[index] ?? this.rowXmins.get(this.rows[index]);
3662
+ if (xmin !== void 0) t.rowXmins.set(row, xmin);
3663
+ });
3636
3664
  t.unlogged = this.unlogged;
3637
3665
  t.constraints = this.constraints.map((c) => ({ ...c }));
3638
3666
  t.triggers = this.triggers.map((tr) => ({ ...tr }));
@@ -3718,6 +3746,14 @@ var DatabaseState = class _DatabaseState {
3718
3746
  clock;
3719
3747
  changes = 0;
3720
3748
  oidCounter = 16384;
3749
+ /** Local monotonic xid allocator; 2 denotes a row from a legacy snapshot without metadata. */
3750
+ xidCounter = 3;
3751
+ transactionXid = null;
3752
+ allocateXid() {
3753
+ if (this.xidCounter > 4294967295)
3754
+ throw pgError("program_limit_exceeded", "transaction ID space exhausted; xid wraparound is not modeled", "54000");
3755
+ return this.xidCounter++;
3756
+ }
3721
3757
  inTransaction = false;
3722
3758
  /** Transaction-only events: included in rollback clones, never in exported snapshots. */
3723
3759
  pendingTriggers = [];
@@ -3931,6 +3967,8 @@ var DatabaseState = class _DatabaseState {
3931
3967
  s.sequenceCurrval = new Map(this.sequenceCurrval);
3932
3968
  s.tableStats = new Map(this.tableStats);
3933
3969
  s.oidCounter = this.oidCounter;
3970
+ s.xidCounter = this.xidCounter;
3971
+ s.transactionXid = this.transactionXid;
3934
3972
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
3935
3973
  return s;
3936
3974
  }
@@ -3950,6 +3988,8 @@ var DatabaseState = class _DatabaseState {
3950
3988
  s.sequenceCurrval = new Map(this.sequenceCurrval);
3951
3989
  s.tableStats = new Map(this.tableStats);
3952
3990
  s.oidCounter = this.oidCounter;
3991
+ s.xidCounter = this.xidCounter;
3992
+ s.transactionXid = this.transactionXid;
3953
3993
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
3954
3994
  return s;
3955
3995
  }
@@ -4025,6 +4065,8 @@ var DatabaseState = class _DatabaseState {
4025
4065
  this.sequenceCurrval = other.sequenceCurrval;
4026
4066
  this.tableStats = other.tableStats;
4027
4067
  this.oidCounter = other.oidCounter;
4068
+ this.xidCounter = Math.max(this.xidCounter, other.xidCounter);
4069
+ this.transactionXid = other.transactionXid;
4028
4070
  }
4029
4071
  /** @internal Snapshot codec access to the oid allocator. */
4030
4072
  snapshotOidCounter() {
@@ -4104,6 +4146,11 @@ function validateZone(zone) {
4104
4146
  // src/expressions/context.ts
4105
4147
  var EngineCtx = class {
4106
4148
  state;
4149
+ writeXid = null;
4150
+ rowVersionXid() {
4151
+ if (this.state.inTransaction) return this.state.transactionXid ??= this.state.allocateXid();
4152
+ return this.writeXid ??= this.state.allocateXid();
4153
+ }
4107
4154
  /** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
4108
4155
  txNow;
4109
4156
  /** statement timestamp */
@@ -4118,6 +4165,23 @@ var EngineCtx = class {
4118
4165
  timezone() {
4119
4166
  return this.state.getSetting("timezone") ?? "UTC";
4120
4167
  }
4168
+ relationOid(parts) {
4169
+ const target = this.state.resolveRelationSchema(parts);
4170
+ const schema = target ? this.state.schemas.get(target.schema) : void 0;
4171
+ const relation = target ? schema?.sequences.get(target.name) ?? schema?.tables.get(target.name) ?? schema?.views.get(target.name) : void 0;
4172
+ if (!relation) throw pgError("undefined_table", `relation "${parts.join(".")}" does not exist`, "42P01");
4173
+ return relation.oid;
4174
+ }
4175
+ relationName(oid) {
4176
+ for (const schema of this.state.schemas.values()) {
4177
+ for (const relation of [...schema.tables.values(), ...schema.sequences.values(), ...schema.views.values()]) {
4178
+ if (relation.oid !== oid) continue;
4179
+ const visible = this.state.resolveRelationSchema([relation.name])?.schema === schema.name;
4180
+ return (visible ? [relation.name] : [schema.name, relation.name]).map(quoteIdentifier).join(".");
4181
+ }
4182
+ }
4183
+ return null;
4184
+ }
4121
4185
  namespaceOid(name) {
4122
4186
  const oid = builtinNamespaceOid(name) ?? this.state.schemas.get(name)?.oid;
4123
4187
  if (oid === void 0) throw pgError("undefined_object", `schema "${name}" does not exist`, "3F000");
@@ -4418,7 +4482,7 @@ function castTo(env, value, target, opts = {}) {
4418
4482
  return tv(target, makeArray(toElem, items, arr.dims.slice(), arr.lbs.slice()));
4419
4483
  }
4420
4484
  if (from === "oid" && target === "regnamespace") return tv(target, v);
4421
- if (from === "regnamespace" && (target === "oid" || target === "int4" || target === "int8")) {
4485
+ if ((from === "regnamespace" || from === "regclass") && (target === "oid" || target === "int4" || target === "int8")) {
4422
4486
  return tv(target, target === "int8" ? BigInt(v) : v);
4423
4487
  }
4424
4488
  if ((from === "int4" || from === "int8" || from === "int2") && (target === "oid" || target === "regnamespace")) {
@@ -5119,6 +5183,8 @@ function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
5119
5183
  case "int2":
5120
5184
  case "int4":
5121
5185
  case "oid":
5186
+ case "regclass":
5187
+ case "xid":
5122
5188
  case "regnamespace":
5123
5189
  case "date":
5124
5190
  return expectNumber(a, t) - expectNumber(b, t);
@@ -5238,6 +5304,8 @@ function datumKey(t, v) {
5238
5304
  case "int2":
5239
5305
  case "int4":
5240
5306
  case "oid":
5307
+ case "regclass":
5308
+ case "xid":
5241
5309
  case "date":
5242
5310
  return `i${v}`;
5243
5311
  case "float4":
@@ -8146,7 +8214,7 @@ function setDatabaseCatalogContext(state, context) {
8146
8214
  var PG_VERSION_TEXT = "PostgreSQL 18.3 (postgres-mem) on TypeScript, in-memory engine";
8147
8215
  function findSequenceForCall(ctx, name) {
8148
8216
  const parts = parseQualifiedName(name);
8149
- const seq = ctx.state.findSequence(parts);
8217
+ const seq = /^\d+$/.test(name) ? [...ctx.state.schemas.values()].flatMap((schema) => [...schema.sequences.values()]).find((sequence) => sequence.oid === Number(name)) : ctx.state.findSequence(parts);
8150
8218
  if (!seq) {
8151
8219
  throw pgError("undefined_table", `relation "${name}" does not exist`, "42P01");
8152
8220
  }
@@ -8370,14 +8438,16 @@ function getMiscFunctions() {
8370
8438
  "pg_get_serial_sequence",
8371
8439
  strict("text", (ctx, args) => {
8372
8440
  const tableName2 = argText(ctx, args[0]);
8373
- const column = argText(ctx, args[1]).toLowerCase();
8441
+ const column = argText(ctx, args[1]);
8374
8442
  const table = ctx.state.findTable(parseQualifiedName(tableName2));
8375
8443
  if (!table) throw pgError("undefined_table", `relation "${tableName2}" does not exist`, "42P01");
8376
8444
  const col = table.columns.find((c) => c.name === column);
8377
8445
  if (!col)
8378
8446
  throw pgError("undefined_column", `column "${column}" of relation "${table.name}" does not exist`, "42703");
8379
- if (!col.identity) return tv("text", null);
8380
- return tv("text", col.identity.sequence.split(".").map(quoteIdent).join("."));
8447
+ const seq = [...ctx.state.schemas.get(table.schema)?.sequences.values() ?? []].find(
8448
+ (candidate) => candidate.ownedBy?.table === table.name && candidate.ownedBy.column === column
8449
+ );
8450
+ return tv("text", seq ? [seq.schema, seq.name].map(quoteIdent).join(".") : null);
8381
8451
  })
8382
8452
  );
8383
8453
  m.set("format_type", (ctx, args) => {
@@ -9895,7 +9965,7 @@ function evalTrgmWordSimilar(ctx, left, right) {
9895
9965
  const score = wordSimilarity(a.v, b.v);
9896
9966
  return tv("bool", score >= WORD_SIMILARITY_THRESHOLD);
9897
9967
  }
9898
- function assertGinTrgmIndex(state, table, stmt) {
9968
+ function assertGinTrgmIndex(state, table, stmt, expressionType) {
9899
9969
  const trgmCols = stmt.columns.filter((col2) => isGinTrgmOpclass(col2.opclass));
9900
9970
  if (trgmCols.length === 0) return;
9901
9971
  if (trgmCols.length !== stmt.columns.length || stmt.columns.length !== 1) {
@@ -9915,11 +9985,7 @@ function assertGinTrgmIndex(state, table, stmt) {
9915
9985
  if (stmt.unique) {
9916
9986
  throw pgError("feature_not_supported", `access method "gin" does not support unique indexes`, "0A000");
9917
9987
  }
9918
- if (col.expr.type !== "colref" || col.expr.parts.length !== 1) {
9919
- throw unsupported("expression gin_trgm_ops");
9920
- }
9921
- const index = table.columnIndex(col.expr.parts[0]);
9922
- const typeId = table.columns[index].type.id;
9988
+ const typeId = col.expr.type === "colref" && col.expr.parts.length === 1 ? table.columns[table.columnIndex(col.expr.parts[0])].type.id : expressionType(col.expr);
9923
9989
  if (!GIN_TRGM_TYPES.has(typeId)) {
9924
9990
  throw pgError(
9925
9991
  "datatype_mismatch",
@@ -13321,7 +13387,7 @@ var RowScope = class {
13321
13387
  let count2 = 0;
13322
13388
  for (let i = 0; i < this.columns.length; i++) {
13323
13389
  const c = this.columns[i];
13324
- if (c.name === name2 && !c.hidden) {
13390
+ if (c.name === name2 && (!c.hidden || c.system)) {
13325
13391
  count2++;
13326
13392
  if (count2 > 1) {
13327
13393
  throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
@@ -13359,7 +13425,7 @@ var RowScope = class {
13359
13425
  const names = [];
13360
13426
  for (let i = 0; i < this.columns.length; i++) {
13361
13427
  const c = this.columns[i];
13362
- if (c.table === rangeVar) {
13428
+ if (c.table === rangeVar && !c.system) {
13363
13429
  types.push(c.type);
13364
13430
  values.push(this.row[i] ?? null);
13365
13431
  names.push(c.name);
@@ -13557,6 +13623,17 @@ function tableScope(table, row) {
13557
13623
  const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
13558
13624
  return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
13559
13625
  }
13626
+ function expressionTypeOf(env, table, expr) {
13627
+ const scope = makeEvalScope(
13628
+ env,
13629
+ tableScope(
13630
+ table,
13631
+ table.columns.map(() => null)
13632
+ )
13633
+ );
13634
+ const v = evalExpr(env.ctx, scope, expr);
13635
+ return v.t === "unknown" ? "text" : v.t;
13636
+ }
13560
13637
  function checkNotNull(env, table, row) {
13561
13638
  void env;
13562
13639
  for (let i = 0; i < table.columns.length; i++) {
@@ -13802,7 +13879,7 @@ function tryIndexedFromItem(env, item, where) {
13802
13879
  if (!table) return null;
13803
13880
  const alias = item.alias ?? item.name[item.name.length - 1];
13804
13881
  table.materializeSlab();
13805
- return tryIndexedTableRows(env, table, alias, where);
13882
+ return tryIndexedTableRows(env, table, alias, where)?.map((row) => [...row, table.rowXmins.get(row) ?? 2]) ?? null;
13806
13883
  }
13807
13884
  function joinKeyFromRow(row, colIdxs, srcTypes, unifiedTypes, ctx) {
13808
13885
  const parts = [];
@@ -16292,6 +16369,7 @@ var Parser = class {
16292
16369
  let sqlBody = null;
16293
16370
  let volatility = null;
16294
16371
  let strict2 = false;
16372
+ const settings = {};
16295
16373
  for (; ; ) {
16296
16374
  if (this.eatKw("language")) {
16297
16375
  language = this.peek().type === "string" ? this.next().value : this.ident(true);
@@ -16349,8 +16427,23 @@ var Parser = class {
16349
16427
  continue;
16350
16428
  }
16351
16429
  if (this.eatKw("set")) {
16352
- this.ident(true);
16353
- if (this.eatOp("=") || this.eatKw("to")) this.next();
16430
+ const key = this.ident(true).toLowerCase();
16431
+ if (this.eatKw("from")) {
16432
+ this.expectKw("current");
16433
+ settings[key] = "__from_current__";
16434
+ } else {
16435
+ if (!this.eatOp("=")) this.expectKw("to");
16436
+ const values = [];
16437
+ do {
16438
+ const value = this.next();
16439
+ if (!["string", "ident", "quoted_ident", "number"].includes(value.type))
16440
+ this.errorAt(value, "expected setting value");
16441
+ values.push(
16442
+ key === "search_path" && /[^a-z0-9_]/.test(value.value) ? `"${value.value.replaceAll('"', '""')}"` : value.value
16443
+ );
16444
+ } while (this.eatPunct(","));
16445
+ settings[key] = values.join(", ");
16446
+ }
16354
16447
  continue;
16355
16448
  }
16356
16449
  if (this.eatKw("window")) throw unsupported("window functions via CREATE FUNCTION");
@@ -16430,7 +16523,8 @@ var Parser = class {
16430
16523
  body,
16431
16524
  sqlBody,
16432
16525
  volatility,
16433
- strict: strict2
16526
+ strict: strict2,
16527
+ settings
16434
16528
  };
16435
16529
  }
16436
16530
  parseCreateTrigger(orReplace, constraint) {
@@ -16462,7 +16556,6 @@ var Parser = class {
16462
16556
  } while (this.eatKw("or"));
16463
16557
  this.expectKw("on");
16464
16558
  const table = this.qualifiedName();
16465
- if (this.eatKw("referencing")) throw unsupported("trigger transition tables");
16466
16559
  let deferrable = false;
16467
16560
  let initiallyDeferred = false;
16468
16561
  if (this.eatKw("not")) this.expectKw("deferrable");
@@ -16475,6 +16568,23 @@ var Parser = class {
16475
16568
  this.errorAt(this.peek(), "only constraint triggers can be deferred");
16476
16569
  if (initiallyDeferred && !deferrable)
16477
16570
  this.errorAt(this.peek(), "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
16571
+ const transitions = [];
16572
+ if (!constraint && this.eatKw("referencing")) {
16573
+ do {
16574
+ const isNew = this.eatKw("new");
16575
+ if (!isNew) this.expectKw("old");
16576
+ if (this.eatKw("row")) {
16577
+ throw pgError(
16578
+ "feature_not_supported",
16579
+ "ROW variable naming in the REFERENCING clause is not supported",
16580
+ "0A000"
16581
+ );
16582
+ }
16583
+ this.expectKw("table");
16584
+ this.eatKw("as");
16585
+ transitions.push({ isNew, name: this.ident() });
16586
+ } while (this.atKw("new") || this.atKw("old"));
16587
+ }
16478
16588
  let forEachRow = false;
16479
16589
  if (this.eatKw("for")) {
16480
16590
  this.eatKw("each");
@@ -16512,7 +16622,8 @@ var Parser = class {
16512
16622
  forEachRow,
16513
16623
  when,
16514
16624
  funcName,
16515
- funcArgs
16625
+ funcArgs,
16626
+ ...transitions.length > 0 ? { transitions } : {}
16516
16627
  };
16517
16628
  }
16518
16629
  // --- ALTER --------------------------------------------------------------------
@@ -16539,8 +16650,8 @@ var Parser = class {
16539
16650
  type: "alter_sequence",
16540
16651
  name,
16541
16652
  ifExists,
16542
- options: { ownedBy: void 0 },
16543
- ...{ renameTo: to }
16653
+ options: {},
16654
+ renameTo: to
16544
16655
  };
16545
16656
  }
16546
16657
  if (this.atKw("set") && (this.atKw("logged", 1) || this.atKw("unlogged", 1))) {
@@ -19116,7 +19227,20 @@ function runFunctionBody(env, fn, args) {
19116
19227
  }
19117
19228
  return last;
19118
19229
  }
19230
+ function withFunctionSettings(env, fn, run) {
19231
+ const state = env.ctx.state;
19232
+ const saved = new Map(state.localSettings);
19233
+ for (const [name, value] of Object.entries(fn.settings ?? {})) state.localSettings.set(name, value);
19234
+ try {
19235
+ return run();
19236
+ } finally {
19237
+ state.localSettings = saved;
19238
+ }
19239
+ }
19119
19240
  function callSqlFunctionScalar(env, fn, args) {
19241
+ return withFunctionSettings(env, fn, () => callSqlFunctionScalarBody(env, fn, args));
19242
+ }
19243
+ function callSqlFunctionScalarBody(env, fn, args) {
19120
19244
  const retT = fn.returns ?? "text";
19121
19245
  if (fn.language === "plpgsql") {
19122
19246
  return callPlpgsqlScalar(env, fn, args);
@@ -19146,6 +19270,9 @@ function callSqlFunctionScalar(env, fn, args) {
19146
19270
  return castTo(env.ctx, tv(rawT, raw), retT, {});
19147
19271
  }
19148
19272
  function callSqlFunctionSet(env, fn, args) {
19273
+ return withFunctionSettings(env, fn, () => callSqlFunctionSetBody(env, fn, args));
19274
+ }
19275
+ function callSqlFunctionSetBody(env, fn, args) {
19149
19276
  if (fn.language === "plpgsql") {
19150
19277
  return callPlpgsqlSet(env, fn, args);
19151
19278
  }
@@ -19300,15 +19427,17 @@ function executeRecursiveCte(env, cte, query) {
19300
19427
  return rel3;
19301
19428
  }
19302
19429
  function renameWithAliases(rel3, label, colAliases, what) {
19303
- if (colAliases && colAliases.length > rel3.columns.length) {
19430
+ const visibleWidth = rel3.columns.filter((column) => !column.system).length;
19431
+ if (colAliases && colAliases.length > visibleWidth) {
19304
19432
  throw pgError(
19305
19433
  "invalid_column_reference",
19306
- `table "${what}" has ${rel3.columns.length} columns available but ${colAliases.length} columns specified`,
19434
+ `table "${what}" has ${visibleWidth} columns available but ${colAliases.length} columns specified`,
19307
19435
  "42P10"
19308
19436
  );
19309
19437
  }
19310
19438
  const columns = rel3.columns.map((c, i) => ({
19311
- name: colAliases?.[i] ?? c.name,
19439
+ ...c,
19440
+ name: c.system ? c.name : colAliases?.[i] ?? c.name,
19312
19441
  type: c.type === UNKNOWN ? "text" : c.type,
19313
19442
  table: label
19314
19443
  }));
@@ -19329,8 +19458,11 @@ function materializeItem(env, item, scope) {
19329
19458
  if (table) {
19330
19459
  table.materializeSlab();
19331
19460
  const rel3 = {
19332
- columns: table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
19333
- rows: table.rows
19461
+ columns: [
19462
+ ...table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
19463
+ { name: "xmin", type: "xid", table: label, hidden: true, system: true }
19464
+ ],
19465
+ rows: table.rows.map((row) => [...row, table.rowXmins.get(row) ?? 2])
19334
19466
  };
19335
19467
  return { rel: renameWithAliases(rel3, label, item.colAliases, label), rangeVars: /* @__PURE__ */ new Set([label]) };
19336
19468
  }
@@ -19960,7 +20092,7 @@ function resolveColIdx(columns, parts) {
19960
20092
  let found = -1;
19961
20093
  for (let i = 0; i < columns.length; i++) {
19962
20094
  const c = columns[i];
19963
- if (!c.hidden && c.name === name2) {
20095
+ if ((!c.hidden || c.system) && c.name === name2) {
19964
20096
  if (found !== -1) return null;
19965
20097
  found = i;
19966
20098
  }
@@ -20544,7 +20676,7 @@ function expandTargets(core, columns) {
20544
20676
  let any = false;
20545
20677
  for (let i = 0; i < columns.length; i++) {
20546
20678
  const c = columns[i];
20547
- if (c.table === label) {
20679
+ if (c.table === label && !c.system) {
20548
20680
  any = true;
20549
20681
  items.push({ name: c.name, kind: "col", colIdx: i, expr: null, hidden: false });
20550
20682
  }
@@ -21037,6 +21169,29 @@ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
21037
21169
  }
21038
21170
  return { row };
21039
21171
  }
21172
+ function transitionRelation(table, name, rows) {
21173
+ return {
21174
+ columns: table.columns.map((c) => ({ name: c.name, type: c.type.id, table: name })),
21175
+ rows
21176
+ };
21177
+ }
21178
+ function fireStatementTriggers(env, table, timing, event, transitions) {
21179
+ const fired = table.triggers.filter((t) => !t.forEachRow && t.timing === timing && matches(t, event)).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
21180
+ for (const t of fired) {
21181
+ if (!executor) throw unsupported(`trigger "${t.name}" execution`);
21182
+ const ctes = /* @__PURE__ */ new Map();
21183
+ if (t.oldTable !== void 0)
21184
+ ctes.set(t.oldTable, transitionRelation(table, t.oldTable, transitions?.oldRows ?? []));
21185
+ if (t.newTable !== void 0)
21186
+ ctes.set(t.newTable, transitionRelation(table, t.newTable, transitions?.newRows ?? []));
21187
+ const changes = env.ctx.state.changes;
21188
+ try {
21189
+ executor({ ctx: env.ctx, params: null, ctes, outer: null }, table, t, event, null, null);
21190
+ } finally {
21191
+ env.ctx.state.changes = changes;
21192
+ }
21193
+ }
21194
+ }
21040
21195
  var keyOf = (schema, name) => JSON.stringify([schema, name]);
21041
21196
  function flushConstraintTriggers(state, all = false) {
21042
21197
  const env = { ctx: new EngineCtx(state), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
@@ -21149,6 +21304,7 @@ var TransactionManager = class {
21149
21304
  this.base = null;
21150
21305
  this.savepoints = [];
21151
21306
  this.state.inTransaction = false;
21307
+ this.state.transactionXid = null;
21152
21308
  this.state.localSettings.clear();
21153
21309
  this.state.pendingTriggers = [];
21154
21310
  this.state.constraintModes.clear();
@@ -21161,6 +21317,7 @@ var TransactionManager = class {
21161
21317
  this.base = null;
21162
21318
  this.savepoints = [];
21163
21319
  this.state.inTransaction = false;
21320
+ this.state.transactionXid = null;
21164
21321
  this.state.localSettings.clear();
21165
21322
  this.state.pendingTriggers = [];
21166
21323
  this.state.constraintModes.clear();
@@ -21195,6 +21352,7 @@ var TransactionManager = class {
21195
21352
  this.base = null;
21196
21353
  this.savepoints = [];
21197
21354
  this.state.inTransaction = false;
21355
+ this.state.transactionXid = null;
21198
21356
  this.freezeDepth = 0;
21199
21357
  }
21200
21358
  };
@@ -21398,6 +21556,7 @@ function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, whe
21398
21556
  const updated = existing.slice();
21399
21557
  applyUpdateSets(env, table, sets, scope, updated);
21400
21558
  computeGeneratedColumns(env, table, updated);
21559
+ table.rowXmins.set(updated, env.ctx.rowVersionXid());
21401
21560
  rows[existingIdx] = updated;
21402
21561
  indexUpdateRow(env, table, existingIdx, existing, updated);
21403
21562
  checkNotNull(env, table, updated);
@@ -21416,7 +21575,13 @@ function executeInsert(env0, stmt) {
21416
21575
  const sourceRows = insertSourceRows(env, stmt, colIdxs);
21417
21576
  const insertedRows = [];
21418
21577
  let insertedCount = 0;
21578
+ const addedRows = [];
21579
+ const conflictOldRows = [];
21580
+ const conflictNewRows = [];
21581
+ const updatesOnConflict = stmt.onConflict !== null && stmt.onConflict.action !== "nothing";
21419
21582
  return withStatementRollback(env, () => {
21583
+ fireStatementTriggers(env, table, "before", "insert");
21584
+ if (updatesOnConflict) fireStatementTriggers(env, table, "before", "update");
21420
21585
  for (const srcRow of sourceRows) {
21421
21586
  const row = table.columns.map(() => null);
21422
21587
  const provided = /* @__PURE__ */ new Set();
@@ -21462,6 +21627,7 @@ function executeInsert(env0, stmt) {
21462
21627
  }
21463
21628
  if (conflictIdx !== null && conflictWhereOk) {
21464
21629
  if (stmt.onConflict.action === "nothing") continue;
21630
+ const replaced = rows[conflictIdx];
21465
21631
  const did = applyOnConflictUpdate(
21466
21632
  env,
21467
21633
  table,
@@ -21474,6 +21640,8 @@ function executeInsert(env0, stmt) {
21474
21640
  if (did) {
21475
21641
  insertedCount++;
21476
21642
  insertedRows.push(rows[conflictIdx]);
21643
+ conflictOldRows.push(replaced);
21644
+ conflictNewRows.push(rows[conflictIdx]);
21477
21645
  fireRowTriggers(env, table, "after", "update", null, rows[conflictIdx]);
21478
21646
  }
21479
21647
  continue;
@@ -21483,12 +21651,18 @@ function executeInsert(env0, stmt) {
21483
21651
  checkChecks(env, table, newRow);
21484
21652
  checkUnique(env, table, newRow, rows.length);
21485
21653
  checkForeignKeys(env, table, newRow);
21654
+ table.rowXmins.set(newRow, env.ctx.rowVersionXid());
21486
21655
  rows.push(newRow);
21487
21656
  indexInsertRow(env, table, rows.length - 1, newRow);
21488
21657
  insertedCount++;
21489
21658
  insertedRows.push(newRow);
21659
+ addedRows.push(newRow);
21490
21660
  fireRowTriggers(env, table, "after", "insert", null, newRow);
21491
21661
  }
21662
+ fireStatementTriggers(env, table, "after", "insert", { oldRows: [], newRows: addedRows });
21663
+ if (updatesOnConflict) {
21664
+ fireStatementTriggers(env, table, "after", "update", { oldRows: conflictOldRows, newRows: conflictNewRows });
21665
+ }
21492
21666
  env.ctx.state.changes = insertedCount;
21493
21667
  if (stmt.returning) {
21494
21668
  const res = evalReturning(env, table, label, stmt.returning, insertedRows, "INSERT");
@@ -21569,10 +21743,12 @@ function executeUpdate(env0, stmt) {
21569
21743
  const env = applyWith(env0, stmt.with);
21570
21744
  const table = requireTargetTable(env, stmt.table, "update");
21571
21745
  const label = stmt.alias ?? table.name;
21746
+ fireStatementTriggers(env, table, "before", "update");
21572
21747
  const fromSource = stmt.from.length > 0 ? buildFrom(env, stmt.from) : null;
21573
21748
  const rows = table.mutableRows();
21574
21749
  const targetCols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label }));
21575
21750
  const updatedRows = [];
21751
+ const replacedRows = [];
21576
21752
  let updateCount = 0;
21577
21753
  for (let ri = 0; ri < rows.length; ri++) {
21578
21754
  const oldRow = rows[ri];
@@ -21600,6 +21776,7 @@ function executeUpdate(env0, stmt) {
21600
21776
  if (fired.row === null) continue;
21601
21777
  const finalRow = fired.row;
21602
21778
  computeGeneratedColumns(env, table, finalRow);
21779
+ table.rowXmins.set(finalRow, env.ctx.rowVersionXid());
21603
21780
  rows[ri] = finalRow;
21604
21781
  try {
21605
21782
  checkNotNull(env, table, finalRow);
@@ -21614,8 +21791,10 @@ function executeUpdate(env0, stmt) {
21614
21791
  handleReferencedUpdate(env, table, [oldRow], [finalRow]);
21615
21792
  updateCount++;
21616
21793
  updatedRows.push(finalRow);
21794
+ replacedRows.push(oldRow);
21617
21795
  fireRowTriggers(env, table, "after", "update", oldRow, finalRow);
21618
21796
  }
21797
+ fireStatementTriggers(env, table, "after", "update", { oldRows: replacedRows, newRows: updatedRows });
21619
21798
  env.ctx.state.changes = updateCount;
21620
21799
  if (stmt.returning) {
21621
21800
  const res = evalReturning(env, table, label, stmt.returning, updatedRows, "UPDATE");
@@ -21627,6 +21806,7 @@ function executeDelete(env0, stmt) {
21627
21806
  const env = applyWith(env0, stmt.with);
21628
21807
  const table = requireTargetTable(env, stmt.table, "delete from");
21629
21808
  const label = stmt.alias ?? table.name;
21809
+ fireStatementTriggers(env, table, "before", "delete");
21630
21810
  const rows = table.mutableRows();
21631
21811
  const usingSource = stmt.using.length > 0 ? buildFrom(env, stmt.using) : null;
21632
21812
  const targetCols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label }));
@@ -21664,6 +21844,7 @@ function executeDelete(env0, stmt) {
21664
21844
  fireRowTriggers(env, table, "after", "delete", row, null);
21665
21845
  }
21666
21846
  if (deletedRows.length > 0) rebuildTableIndexes(env, table);
21847
+ fireStatementTriggers(env, table, "after", "delete", { oldRows: deletedRows, newRows: [] });
21667
21848
  env.ctx.state.changes = deletedRows.length;
21668
21849
  if (stmt.returning) {
21669
21850
  const res = evalReturning(env, table, label, stmt.returning, deletedRows, "DELETE");
@@ -21719,6 +21900,7 @@ function handleReferencedDelete(env, table, row, depth) {
21719
21900
  for (const c of con.columns) {
21720
21901
  newRow[child.columnIndex(c)] = null;
21721
21902
  }
21903
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21722
21904
  childRows[i] = newRow;
21723
21905
  checkNotNull(env, child, newRow);
21724
21906
  checkChecks(env, child, newRow);
@@ -21732,6 +21914,7 @@ function handleReferencedDelete(env, table, row, depth) {
21732
21914
  const ci = child.columnIndex(c);
21733
21915
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
21734
21916
  }
21917
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21735
21918
  childRows[i] = newRow;
21736
21919
  checkNotNull(env, child, newRow);
21737
21920
  checkChecks(env, child, newRow);
@@ -21769,6 +21952,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21769
21952
  const refIdx = table.columnIndex(con.refColumns[c]);
21770
21953
  newRow[localIdx] = newRows[r][refIdx] ?? null;
21771
21954
  }
21955
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21772
21956
  childRows[i] = newRow;
21773
21957
  checkChecks(env, child, newRow);
21774
21958
  }
@@ -21778,6 +21962,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21778
21962
  for (const i of idxs) {
21779
21963
  const newRow = childRows[i].slice();
21780
21964
  for (const c of con.columns) newRow[child.columnIndex(c)] = null;
21965
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21781
21966
  childRows[i] = newRow;
21782
21967
  checkNotNull(env, child, newRow);
21783
21968
  }
@@ -21790,6 +21975,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21790
21975
  const ci = child.columnIndex(c);
21791
21976
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
21792
21977
  }
21978
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21793
21979
  childRows[i] = newRow;
21794
21980
  checkForeignKeys(env, child, newRow);
21795
21981
  }
@@ -23801,7 +23987,7 @@ function pgTrigger(ctx) {
23801
23987
  let oid = 4e4;
23802
23988
  for (const t of allTables(ctx.state)) {
23803
23989
  for (const tr of t.triggers) {
23804
- rows.push([oid++, tr.name, t.oid, !tr.forEachRow]);
23990
+ rows.push([oid++, tr.name, t.oid, !tr.forEachRow, tr.oldTable ?? null, tr.newTable ?? null]);
23805
23991
  }
23806
23992
  }
23807
23993
  return rel2(
@@ -23809,7 +23995,9 @@ function pgTrigger(ctx) {
23809
23995
  ["oid", "oid"],
23810
23996
  ["tgname", "name"],
23811
23997
  ["tgrelid", "oid"],
23812
- ["tgisinternal", "bool"]
23998
+ ["tgisinternal", "bool"],
23999
+ ["tgoldtable", "name"],
24000
+ ["tgnewtable", "name"]
23813
24001
  ],
23814
24002
  rows,
23815
24003
  "pg_trigger"
@@ -24837,13 +25025,63 @@ function executeCreateSequence(env, stmt) {
24837
25025
  schema.sequences.set(name, seq);
24838
25026
  return commandResult("CREATE SEQUENCE", 0);
24839
25027
  }
25028
+ function renameSequenceReferences(env, seq, newName) {
25029
+ const state = env.ctx.state;
25030
+ const matches2 = (value) => {
25031
+ try {
25032
+ const input = parseRelationInput(value);
25033
+ if ("oid" in input) return input.oid === seq.oid;
25034
+ return state.findSequence(input.parts)?.oid === seq.oid;
25035
+ } catch {
25036
+ return false;
25037
+ }
25038
+ };
25039
+ const rewrite = (value) => {
25040
+ if (Array.isArray(value)) return value.map(rewrite);
25041
+ if (value === null || typeof value !== "object") return value;
25042
+ const node = value;
25043
+ const updated = Object.fromEntries(Object.entries(node).map(([key, child]) => [key, rewrite(child)]));
25044
+ const rewriteLiteral = (literal2) => {
25045
+ if (literal2 && typeof literal2 === "object" && "type" in literal2 && literal2.type === "string_lit" && "value" in literal2 && typeof literal2.value === "string" && matches2(literal2.value)) {
25046
+ return { ...literal2, value: [seq.schema, newName].map(quoteIdent).join(".") };
25047
+ }
25048
+ return literal2;
25049
+ };
25050
+ if (node.type === "func" && Array.isArray(node.name) && ["nextval", "currval", "setval"].includes(String(node.name.at(-1))) && Array.isArray(updated.args))
25051
+ updated.args[0] = rewriteLiteral(updated.args[0]);
25052
+ 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")
25053
+ updated.expr = rewriteLiteral(updated.expr);
25054
+ return updated;
25055
+ };
25056
+ for (const schema of state.schemas.values()) {
25057
+ for (const table of [...schema.tables.values()]) {
25058
+ const writable = state.ensureWritableTable(table);
25059
+ for (const column of writable.columns) {
25060
+ if (column.defaultExpr) column.defaultExpr = rewrite(column.defaultExpr);
25061
+ if (column.identity?.sequence === `${seq.schema}.${seq.name}`)
25062
+ column.identity = { ...column.identity, sequence: `${seq.schema}.${newName}` };
25063
+ }
25064
+ }
25065
+ }
25066
+ }
24840
25067
  function executeAlterSequence(env, stmt) {
24841
25068
  const state = env.ctx.state;
24842
- const seq = state.findSequence(stmt.name);
24843
- if (!seq) {
25069
+ const foundSequence = state.findSequence(stmt.name);
25070
+ if (!foundSequence) {
24844
25071
  if (stmt.ifExists) return commandResult("ALTER SEQUENCE", 0);
24845
25072
  throw pgError("undefined_table", `relation "${stmt.name.join(".")}" does not exist`, "42P01");
24846
25073
  }
25074
+ const seq = state.ensureWritableSequence(foundSequence);
25075
+ if (stmt.renameTo) {
25076
+ const schema = state.getSchema(seq.schema);
25077
+ if (schema.hasRelation(stmt.renameTo))
25078
+ throw pgError("duplicate_table", `relation "${stmt.renameTo}" already exists`, "42P07");
25079
+ renameSequenceReferences(env, seq, stmt.renameTo);
25080
+ schema.sequences.delete(seq.name);
25081
+ seq.name = stmt.renameTo;
25082
+ schema.sequences.set(seq.name, seq);
25083
+ return commandResult("ALTER SEQUENCE", 0);
25084
+ }
24847
25085
  const o = stmt.options;
24848
25086
  if (o.logged !== void 0) {
24849
25087
  setSequenceLogged(state, seq, o.logged);
@@ -24901,7 +25139,7 @@ function buildColumn(env, schema, tableName2, def, out, taken) {
24901
25139
  col.defaultExpr = {
24902
25140
  type: "func",
24903
25141
  name: ["nextval"],
24904
- args: [{ type: "string_lit", value: `${schema.name}.${seqName}` }]
25142
+ args: [{ type: "string_lit", value: [schema.name, seqName].map(quoteIdent).join(".") }]
24905
25143
  };
24906
25144
  }
24907
25145
  for (const c of def.constraints) {
@@ -25154,7 +25392,11 @@ function executeCreateTableAs(env, stmt) {
25154
25392
  const table = new TableData(schema.name, name, columns, state.nextOid(), stmt.temp);
25155
25393
  table.unlogged = stmt.unlogged === true;
25156
25394
  if (stmt.withData) {
25157
- for (const row of rel3.rows) table.mutableRows().push(row.slice());
25395
+ for (const row of rel3.rows) {
25396
+ const stored = row.slice();
25397
+ table.rowXmins.set(stored, env.ctx.rowVersionXid());
25398
+ table.mutableRows().push(stored);
25399
+ }
25158
25400
  }
25159
25401
  schema.tables.set(name, table);
25160
25402
  const count = stmt.withData ? table.rowCount() : 0;
@@ -25182,7 +25424,7 @@ function executeCreateIndex(env, stmt) {
25182
25424
  }
25183
25425
  }
25184
25426
  }
25185
- assertGinTrgmIndex(state, table, stmt);
25427
+ assertGinTrgmIndex(state, table, stmt, (expr) => expressionTypeOf(env, table, expr));
25186
25428
  const method = stmt.using ?? "btree";
25187
25429
  if (!ACCESS_METHODS.has(method) || method === "heap") {
25188
25430
  throw pgError("undefined_object", `access method "${method}" does not exist`, "42704");
@@ -25423,6 +25665,12 @@ function executeCreateFunction(env, stmt) {
25423
25665
  language: lang,
25424
25666
  body,
25425
25667
  rawBody: stmt.body,
25668
+ settings: Object.fromEntries(
25669
+ Object.entries(stmt.settings ?? {}).map(([key, value]) => [
25670
+ key,
25671
+ value === "__from_current__" ? state.getSetting(key) ?? "" : value
25672
+ ])
25673
+ ),
25426
25674
  strict: stmt.strict,
25427
25675
  oid: state.nextOid()
25428
25676
  };
@@ -25431,6 +25679,50 @@ function executeCreateFunction(env, stmt) {
25431
25679
  schema.functions.set(name, existing);
25432
25680
  return commandResult("CREATE FUNCTION", 0);
25433
25681
  }
25682
+ function validateTransitionTables(stmt) {
25683
+ const transitions = stmt.transitions ?? [];
25684
+ if (transitions.length === 0) return {};
25685
+ const invalid = (message2) => pgError("invalid_table_definition", message2, "42P17");
25686
+ const unsupportedClause = (message2) => pgError("feature_not_supported", message2, "0A000");
25687
+ if (stmt.timing !== "after") throw invalid("transition table name can only be specified for an AFTER trigger");
25688
+ if (stmt.events.some((e) => e.event === "truncate")) {
25689
+ throw unsupportedClause("TRUNCATE triggers with transition tables are not supported");
25690
+ }
25691
+ if (stmt.events.some((e) => e.columns !== null)) {
25692
+ throw unsupportedClause("transition tables cannot be specified for triggers with column lists");
25693
+ }
25694
+ if (stmt.events.length > 1) {
25695
+ throw unsupportedClause("transition tables cannot be specified for triggers with more than one event");
25696
+ }
25697
+ const event = stmt.events[0].event;
25698
+ let oldTable;
25699
+ let newTable;
25700
+ for (const transition of transitions) {
25701
+ if (transition.isNew) {
25702
+ if (event !== "insert" && event !== "update") {
25703
+ throw invalid("NEW TABLE can only be specified for an INSERT or UPDATE trigger");
25704
+ }
25705
+ if (newTable !== void 0) throw invalid("NEW TABLE cannot be specified multiple times");
25706
+ newTable = transition.name;
25707
+ } else {
25708
+ if (event !== "delete" && event !== "update") {
25709
+ throw invalid("OLD TABLE can only be specified for a DELETE or UPDATE trigger");
25710
+ }
25711
+ if (oldTable !== void 0) throw invalid("OLD TABLE cannot be specified multiple times");
25712
+ oldTable = transition.name;
25713
+ }
25714
+ }
25715
+ if (oldTable !== void 0 && oldTable === newTable) {
25716
+ throw invalid("OLD TABLE name and NEW TABLE name cannot be the same");
25717
+ }
25718
+ if (stmt.forEachRow) {
25719
+ throw pgError("unsupported", "transition tables on FOR EACH ROW triggers are not supported", "0A000");
25720
+ }
25721
+ return {
25722
+ ...oldTable !== void 0 ? { oldTable } : {},
25723
+ ...newTable !== void 0 ? { newTable } : {}
25724
+ };
25725
+ }
25434
25726
  function executeCreateTrigger(env, stmt) {
25435
25727
  if (stmt.constraint && (stmt.timing !== "after" || !stmt.forEachRow))
25436
25728
  throw pgError("syntax", "constraint triggers must be AFTER ROW triggers", "42601");
@@ -25440,6 +25732,7 @@ function executeCreateTrigger(env, stmt) {
25440
25732
  throw pgError("undefined_table", `relation "${stmt.table.join(".")}" does not exist`, "42P01");
25441
25733
  }
25442
25734
  const table = state.ensureWritableTable(found);
25735
+ const transitionTables = validateTransitionTables(stmt);
25443
25736
  const fnSchema = stmt.funcName.length >= 2 ? stmt.funcName[stmt.funcName.length - 2] : null;
25444
25737
  const fnName = stmt.funcName[stmt.funcName.length - 1];
25445
25738
  const fns = state.findFunctions(stmt.funcName);
@@ -25458,6 +25751,7 @@ function executeCreateTrigger(env, stmt) {
25458
25751
  timing: stmt.timing,
25459
25752
  events: stmt.events,
25460
25753
  forEachRow: stmt.forEachRow,
25754
+ ...transitionTables,
25461
25755
  when: stmt.when,
25462
25756
  funcSchema: fnSchema ?? fns[0].schema,
25463
25757
  funcName: fnName,
@@ -25607,6 +25901,7 @@ function executeAlterTable(env, stmt) {
25607
25901
  }
25608
25902
  const next = row.slice();
25609
25903
  next[idx] = nv;
25904
+ table.rowXmins.set(next, table.rowXmins.get(rows[i]) ?? 2);
25610
25905
  rows[i] = next;
25611
25906
  }
25612
25907
  col.type = resolved.column;
@@ -25708,6 +26003,11 @@ function executeAlterTable(env, stmt) {
25708
26003
  );
25709
26004
  }
25710
26005
  table.columns[idx].name = action.to;
26006
+ for (const seq of [...schema.sequences.values()]) {
26007
+ if (seq.ownedBy?.table === table.name && seq.ownedBy.column === action.from) {
26008
+ state.ensureWritableSequence(seq).ownedBy = { table: table.name, column: action.to };
26009
+ }
26010
+ }
25711
26011
  for (const con of table.constraints) {
25712
26012
  if (con.kind === "primary_key" || con.kind === "unique" || con.kind === "foreign_key") {
25713
26013
  con.columns = con.columns.map((c) => c === action.from ? action.to : c);
@@ -25744,6 +26044,11 @@ function executeAlterTable(env, stmt) {
25744
26044
  throw pgError("duplicate_table", `relation "${action.to}" already exists`, "42P07");
25745
26045
  }
25746
26046
  const oldName = table.name;
26047
+ for (const seq of [...schema.sequences.values()]) {
26048
+ if (seq.ownedBy?.table === oldName) {
26049
+ state.ensureWritableSequence(seq).ownedBy = { ...seq.ownedBy, table: action.to };
26050
+ }
26051
+ }
25747
26052
  schema.tables.delete(table.name);
25748
26053
  table.name = action.to;
25749
26054
  schema.tables.set(action.to, table);
@@ -27617,6 +27922,7 @@ function encodeDatabaseState(state, runtime) {
27617
27922
  writeBjv(
27618
27923
  w,
27619
27924
  {
27925
+ xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
27620
27926
  name: table.name,
27621
27927
  schema: table.schema,
27622
27928
  columns: table.columns,
@@ -27714,8 +28020,14 @@ function decodeInner(snapshot, prng, clock) {
27714
28020
  table.constraints = meta.constraints;
27715
28021
  table.triggers = meta.triggers;
27716
28022
  table.unlogged = meta.unlogged === true;
28023
+ table.slabXmins = meta.xmins ?? null;
28024
+ state.xidCounter = Math.max(
28025
+ state.xidCounter,
28026
+ (meta.xmins ?? []).reduce((max, xid) => Math.max(max, xid + 1), 3)
28027
+ );
27717
28028
  if (meta.stats) state.tableStats.set(table.oid, meta.stats);
27718
28029
  const rowCount = readVarintU32(r);
28030
+ if (meta.xmins && meta.xmins.length !== rowCount) throw snapshotError();
27719
28031
  const slabColumns = [];
27720
28032
  for (let c = 0; c < meta.columns.length; c++)
27721
28033
  slabColumns.push(readPackedColumn(r, rowCount, intern, meta.columns[c].type.id));
@@ -28159,6 +28471,8 @@ function validateTableMetaBjv(value) {
28159
28471
  if (!isRecord(value) || typeof value.name !== "string" || typeof value.schema !== "string") throw snapshotError();
28160
28472
  if (!Array.isArray(value.columns)) throw snapshotError();
28161
28473
  for (const col of value.columns) validateColumnMeta(col);
28474
+ if (value.xmins !== void 0 && (!Array.isArray(value.xmins) || value.xmins.some((xid) => !Number.isInteger(xid) || xid < 2 || xid > 4294967295)))
28475
+ throw snapshotError();
28162
28476
  }
28163
28477
  function validateViewMetaBjv(value) {
28164
28478
  if (!isRecord(value) || typeof value.name !== "string" || typeof value.schema !== "string") throw snapshotError();
@@ -28252,6 +28566,7 @@ function forceSchemaIntern(pool, state, schemas) {
28252
28566
  pool.forceId(table.name);
28253
28567
  pool.forceId(table.schema);
28254
28568
  forceBjvStrings(pool, {
28569
+ xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
28255
28570
  name: table.name,
28256
28571
  schema: table.schema,
28257
28572
  columns: table.columns,
@@ -29882,7 +30197,7 @@ var Connection = class {
29882
30197
  if (stmt?.type !== "transaction") throw pgError2("syntax", "invalid transaction command", "42601");
29883
30198
  switch (stmt.action) {
29884
30199
  case "begin":
29885
- this.transaction ??= { statements: [], savepoints: [] };
30200
+ this.transaction ??= { statements: [], savepoints: [], xid: this.database.state.allocateXid() };
29886
30201
  return command("BEGIN");
29887
30202
  case "commit": {
29888
30203
  const transaction = this.transaction;
@@ -29891,6 +30206,7 @@ var Connection = class {
29891
30206
  this.inSession(
29892
30207
  this.database,
29893
30208
  () => this.database.transaction(() => {
30209
+ this.database.state.transactionXid = transaction.xid;
29894
30210
  for (const logged of transaction.statements) this.replay(this.database, logged);
29895
30211
  })
29896
30212
  );
@@ -29941,6 +30257,7 @@ var Connection = class {
29941
30257
  workspace.state.settings = new Map(this.settings);
29942
30258
  workspace.state.settingDefaults = this.settingDefaults;
29943
30259
  workspace.transactions.begin();
30260
+ workspace.state.transactionXid = this.transaction?.xid ?? null;
29944
30261
  for (const logged of this.transaction?.statements ?? []) {
29945
30262
  this.replay(workspace, logged);
29946
30263
  }