@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/index.js CHANGED
@@ -254,6 +254,13 @@ function isPostgresError(err) {
254
254
  return typeof sqlState === "string" && /^[0-9A-Z]{5}$/.test(sqlState);
255
255
  }
256
256
 
257
+ // src/storage/guc.ts
258
+ function validateStorageSetting(name, value) {
259
+ if (name === "default_table_access_method" && value !== "heap" || name === "default_tablespace" && value !== "" && value !== "pg_default") {
260
+ throw pgError("invalid_parameter_value", `invalid value for parameter "${name}": "${value}"`, "22023");
261
+ }
262
+ }
263
+
257
264
  // src/runtime/prng.ts
258
265
  var Prng = class _Prng {
259
266
  state;
@@ -2793,6 +2800,12 @@ var invalidName = () => {
2793
2800
  throw pgError("syntax", "invalid name syntax", "42602");
2794
2801
  };
2795
2802
  function parseNamespaceInput(text) {
2803
+ const parsed = parseRelationInput(text);
2804
+ if ("oid" in parsed) return parsed;
2805
+ if (parsed.parts.length !== 1) invalidName();
2806
+ return { name: parsed.parts[0] };
2807
+ }
2808
+ function parseRelationInput(text) {
2796
2809
  if (text === "-") return { oid: 0 };
2797
2810
  if (/^\d+$/.test(text)) return { oid: parseOidText(text) };
2798
2811
  const names = [];
@@ -2828,8 +2841,8 @@ function parseNamespaceInput(text) {
2828
2841
  skipSpace();
2829
2842
  if (at === text.length) invalidName();
2830
2843
  }
2831
- if (names.length !== 1) invalidName();
2832
- return { name: names[0] };
2844
+ if (names.length === 0 || names.length > 3) invalidName();
2845
+ return { parts: names };
2833
2846
  }
2834
2847
  function namespaceText(oid, name) {
2835
2848
  if (oid === 0) return "-";
@@ -2902,6 +2915,7 @@ var TYPE_ALIASES = {
2902
2915
  regtype: "regtype",
2903
2916
  regproc: "regproc",
2904
2917
  regnamespace: "regnamespace",
2918
+ xid: "xid",
2905
2919
  oid: "oid",
2906
2920
  void: "void",
2907
2921
  record: "record",
@@ -2978,6 +2992,7 @@ var TYPE_OIDS = {
2978
2992
  regproc: 24,
2979
2993
  text: 25,
2980
2994
  oid: 26,
2995
+ xid: 28,
2981
2996
  json: 114,
2982
2997
  float4: 700,
2983
2998
  float8: 701,
@@ -3296,6 +3311,7 @@ function recordText(rec, ctx) {
3296
3311
  return `(${parts.join(",")})`;
3297
3312
  }
3298
3313
  function datumText(t, v, ctx) {
3314
+ if (t === "regclass") return v === 0 ? "-" : ctx.relationName?.(v) ?? String(v);
3299
3315
  if (t === "regnamespace") return namespaceText(v, ctx.namespaceName?.(v));
3300
3316
  if (v === null) throw pgError("internal", "datumText called with null");
3301
3317
  if (isArrayType(t)) return arrayText(v, ctx);
@@ -3306,6 +3322,7 @@ function datumText(t, v, ctx) {
3306
3322
  case "int2":
3307
3323
  case "int4":
3308
3324
  case "oid":
3325
+ case "xid":
3309
3326
  return String(v);
3310
3327
  case "int8":
3311
3328
  return String(v);
@@ -3370,6 +3387,12 @@ function datumText(t, v, ctx) {
3370
3387
  }
3371
3388
  var UTC_INPUT = { zoneOffsetForNaive: () => 0 };
3372
3389
  function datumFromText(t, text, ctx) {
3390
+ if (t === "regclass") {
3391
+ const parsed = parseRelationInput(text);
3392
+ if ("oid" in parsed) return parsed.oid;
3393
+ if (!ctx.relationOid) throw unsupported("regclass input without a catalog");
3394
+ return ctx.relationOid(parsed.parts);
3395
+ }
3373
3396
  if (t === "regnamespace") {
3374
3397
  const parsed = parseNamespaceInput(text);
3375
3398
  if ("oid" in parsed) return parsed.oid;
@@ -3391,6 +3414,7 @@ function datumFromText(t, text, ctx) {
3391
3414
  case "int8":
3392
3415
  return parseIntegerText(text, t);
3393
3416
  case "oid":
3417
+ case "xid":
3394
3418
  return parseOidText(text);
3395
3419
  case "float4":
3396
3420
  return Math.fround(parseFloatText(text, "float4"));
@@ -3547,6 +3571,8 @@ var TableData = class _TableData {
3547
3571
  schema;
3548
3572
  columns;
3549
3573
  rows;
3574
+ rowXmins = /* @__PURE__ */ new WeakMap();
3575
+ slabXmins = null;
3550
3576
  /** Frozen columnar storage after snapshot hydrate; `rows` stays empty until materialized. */
3551
3577
  slab = null;
3552
3578
  constraints;
@@ -3589,6 +3615,11 @@ var TableData = class _TableData {
3589
3615
  materializeSlab() {
3590
3616
  if (!this.slab) return;
3591
3617
  this.rows = this.slab.materialize();
3618
+ if (this.slabXmins)
3619
+ this.rows.forEach((row, index) => {
3620
+ this.rowXmins.set(row, this.slabXmins[index] ?? 2);
3621
+ });
3622
+ this.slabXmins = null;
3592
3623
  this.slab = null;
3593
3624
  this.indexStores = null;
3594
3625
  }
@@ -3622,6 +3653,10 @@ var TableData = class _TableData {
3622
3653
  } else {
3623
3654
  t.rows = this.rows.map((r) => r.slice());
3624
3655
  }
3656
+ t.rows.forEach((row, index) => {
3657
+ const xmin = this.slabXmins?.[index] ?? this.rowXmins.get(this.rows[index]);
3658
+ if (xmin !== void 0) t.rowXmins.set(row, xmin);
3659
+ });
3625
3660
  t.unlogged = this.unlogged;
3626
3661
  t.constraints = this.constraints.map((c) => ({ ...c }));
3627
3662
  t.triggers = this.triggers.map((tr) => ({ ...tr }));
@@ -3707,7 +3742,18 @@ var DatabaseState = class _DatabaseState {
3707
3742
  clock;
3708
3743
  changes = 0;
3709
3744
  oidCounter = 16384;
3745
+ /** Local monotonic xid allocator; 2 denotes a row from a legacy snapshot without metadata. */
3746
+ xidCounter = 3;
3747
+ transactionXid = null;
3748
+ allocateXid() {
3749
+ if (this.xidCounter > 4294967295)
3750
+ throw pgError("program_limit_exceeded", "transaction ID space exhausted; xid wraparound is not modeled", "54000");
3751
+ return this.xidCounter++;
3752
+ }
3710
3753
  inTransaction = false;
3754
+ /** Transaction-only events: included in rollback clones, never in exported snapshots. */
3755
+ pendingTriggers = [];
3756
+ constraintModes = /* @__PURE__ */ new Map();
3711
3757
  /** most recent sequence touched by nextval/setval, for lastval() */
3712
3758
  lastSequence = null;
3713
3759
  /** Session currval per sequence; absent entry means currval is undefined. */
@@ -3750,6 +3796,8 @@ var DatabaseState = class _DatabaseState {
3750
3796
  this.settings.set("row_security", "on");
3751
3797
  this.settings.set("array_nulls", "on");
3752
3798
  this.settings.set("backslash_quote", "safe_encoding");
3799
+ this.settings.set("default_tablespace", "");
3800
+ this.settings.set("default_table_access_method", "heap");
3753
3801
  }
3754
3802
  nextOid() {
3755
3803
  return this.oidCounter++;
@@ -3909,10 +3957,14 @@ var DatabaseState = class _DatabaseState {
3909
3957
  s.prepared = new Map(this.prepared);
3910
3958
  s.changes = this.changes;
3911
3959
  s.inTransaction = this.inTransaction;
3960
+ s.pendingTriggers = this.pendingTriggers.slice();
3961
+ s.constraintModes = new Map(this.constraintModes);
3912
3962
  s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
3913
3963
  s.sequenceCurrval = new Map(this.sequenceCurrval);
3914
3964
  s.tableStats = new Map(this.tableStats);
3915
3965
  s.oidCounter = this.oidCounter;
3966
+ s.xidCounter = this.xidCounter;
3967
+ s.transactionXid = this.transactionXid;
3916
3968
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
3917
3969
  return s;
3918
3970
  }
@@ -3926,10 +3978,14 @@ var DatabaseState = class _DatabaseState {
3926
3978
  s.prepared = new Map(this.prepared);
3927
3979
  s.changes = this.changes;
3928
3980
  s.inTransaction = this.inTransaction;
3981
+ s.pendingTriggers = this.pendingTriggers.slice();
3982
+ s.constraintModes = new Map(this.constraintModes);
3929
3983
  s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
3930
3984
  s.sequenceCurrval = new Map(this.sequenceCurrval);
3931
3985
  s.tableStats = new Map(this.tableStats);
3932
3986
  s.oidCounter = this.oidCounter;
3987
+ s.xidCounter = this.xidCounter;
3988
+ s.transactionXid = this.transactionXid;
3933
3989
  for (const [name, overloads] of this.systemFunctions) s.systemFunctions.set(name, overloads.slice());
3934
3990
  return s;
3935
3991
  }
@@ -3998,11 +4054,15 @@ var DatabaseState = class _DatabaseState {
3998
4054
  this.settings = other.settings;
3999
4055
  this.localSettings = other.localSettings;
4000
4056
  this.prepared = other.prepared;
4057
+ this.pendingTriggers = other.pendingTriggers.slice();
4058
+ this.constraintModes = new Map(other.constraintModes);
4001
4059
  this.changes = other.changes;
4002
4060
  this.lastSequence = other.lastSequence;
4003
4061
  this.sequenceCurrval = other.sequenceCurrval;
4004
4062
  this.tableStats = other.tableStats;
4005
4063
  this.oidCounter = other.oidCounter;
4064
+ this.xidCounter = Math.max(this.xidCounter, other.xidCounter);
4065
+ this.transactionXid = other.transactionXid;
4006
4066
  }
4007
4067
  /** @internal Snapshot codec access to the oid allocator. */
4008
4068
  snapshotOidCounter() {
@@ -4014,91 +4074,212 @@ var DatabaseState = class _DatabaseState {
4014
4074
  }
4015
4075
  };
4016
4076
 
4017
- // src/transactions/manager.ts
4018
- var TransactionManager = class {
4019
- constructor(state) {
4020
- this.state = state;
4077
+ // src/types/timezone.ts
4078
+ var intlCache = /* @__PURE__ */ new Map();
4079
+ function intlFor(zone) {
4080
+ const cached = intlCache.get(zone);
4081
+ if (cached) return cached;
4082
+ try {
4083
+ const fmt = new Intl.DateTimeFormat("en-US", {
4084
+ timeZone: zone,
4085
+ timeZoneName: "longOffset",
4086
+ year: "numeric"
4087
+ });
4088
+ intlCache.set(zone, fmt);
4089
+ return fmt;
4090
+ } catch {
4091
+ return null;
4092
+ }
4093
+ }
4094
+ function parseFixedOffset(zone) {
4095
+ const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
4096
+ if (!m) return null;
4097
+ const sign = m[1] === "-" ? -1 : 1;
4098
+ return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
4099
+ }
4100
+ function parsePosixOffset(zone) {
4101
+ const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
4102
+ if (!m) return null;
4103
+ const sign = m[1] === "-" ? 1 : -1;
4104
+ return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
4105
+ }
4106
+ function pgMicrosToUnixMs(utcMicros) {
4107
+ return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
4108
+ }
4109
+ function zoneOffsetAtUtc(zone, utcMicros) {
4110
+ const z = zone.trim();
4111
+ const lower = z.toLowerCase();
4112
+ if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
4113
+ const posix = parsePosixOffset(z);
4114
+ if (posix !== null) return posix;
4115
+ const fixed = parseFixedOffset(z);
4116
+ if (fixed !== null) return fixed;
4117
+ const fmt = intlFor(z);
4118
+ if (fmt) {
4119
+ const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
4120
+ const parts = fmt.formatToParts(new Date(ms));
4121
+ const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
4122
+ const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
4123
+ if (!m) return 0;
4124
+ const sign = m[1] === "-" ? -1 : 1;
4125
+ return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
4021
4126
  }
4127
+ throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
4128
+ }
4129
+ function clampDateMs(ms) {
4130
+ const MAX = 864e13;
4131
+ return Math.max(-MAX, Math.min(MAX, ms));
4132
+ }
4133
+ function zoneOffsetForNaive(zone, naiveMicros) {
4134
+ const first = zoneOffsetAtUtc(zone, naiveMicros);
4135
+ const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
4136
+ return second;
4137
+ }
4138
+
4139
+ // src/expressions/context.ts
4140
+ var EngineCtx = class {
4022
4141
  state;
4023
- base = null;
4024
- savepoints = [];
4025
- freezeDepth = 0;
4026
- get inTransaction() {
4027
- return this.base !== null;
4142
+ writeXid = null;
4143
+ rowVersionXid() {
4144
+ if (this.state.inTransaction) return this.state.transactionXid ??= this.state.allocateXid();
4145
+ return this.writeXid ??= this.state.allocateXid();
4028
4146
  }
4029
- takeSnapshot() {
4030
- this.state.freezeShared();
4031
- this.freezeDepth++;
4032
- return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
4147
+ /** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
4148
+ txNow;
4149
+ /** statement timestamp */
4150
+ stmtNow;
4151
+ constructor(state, txNow) {
4152
+ this.state = state;
4153
+ const nowMs = state.clock().getTime();
4154
+ const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
4155
+ this.txNow = txNow ?? nowMicros;
4156
+ this.stmtNow = nowMicros;
4033
4157
  }
4034
- restore(snap) {
4035
- this.state.restoreFrom(snap.state);
4036
- this.state.prng.setState(snap.prngState);
4158
+ timezone() {
4159
+ return this.state.getSetting("timezone") ?? "UTC";
4037
4160
  }
4038
- thawOnce() {
4039
- if (this.freezeDepth > 0) {
4040
- this.state.thawShared();
4041
- this.freezeDepth--;
4042
- }
4161
+ relationOid(parts) {
4162
+ const target = this.state.resolveRelationSchema(parts);
4163
+ const schema = target ? this.state.schemas.get(target.schema) : void 0;
4164
+ const relation = target ? schema?.sequences.get(target.name) ?? schema?.tables.get(target.name) ?? schema?.views.get(target.name) : void 0;
4165
+ if (!relation) throw pgError("undefined_table", `relation "${parts.join(".")}" does not exist`, "42P01");
4166
+ return relation.oid;
4043
4167
  }
4044
- begin() {
4045
- if (this.base !== null) {
4046
- return;
4168
+ relationName(oid) {
4169
+ for (const schema of this.state.schemas.values()) {
4170
+ for (const relation of [...schema.tables.values(), ...schema.sequences.values(), ...schema.views.values()]) {
4171
+ if (relation.oid !== oid) continue;
4172
+ const visible = this.state.resolveRelationSchema([relation.name])?.schema === schema.name;
4173
+ return (visible ? [relation.name] : [schema.name, relation.name]).map(quoteIdentifier).join(".");
4174
+ }
4047
4175
  }
4048
- this.base = this.takeSnapshot();
4049
- this.state.inTransaction = true;
4050
- assert(this.freezeDepth === 1, "BEGIN freeze depth");
4176
+ return null;
4051
4177
  }
4052
- commit() {
4053
- this.base = null;
4054
- this.savepoints = [];
4055
- this.state.inTransaction = false;
4056
- this.state.localSettings.clear();
4057
- while (this.freezeDepth > 0) this.thawOnce();
4178
+ namespaceOid(name) {
4179
+ const oid = builtinNamespaceOid(name) ?? this.state.schemas.get(name)?.oid;
4180
+ if (oid === void 0) throw pgError("undefined_object", `schema "${name}" does not exist`, "3F000");
4181
+ return oid;
4058
4182
  }
4059
- rollback() {
4060
- if (this.base !== null) {
4061
- this.restore(this.base);
4183
+ namespaceName(oid) {
4184
+ const builtin = builtinNamespaceName(oid);
4185
+ if (builtin !== void 0) return builtin;
4186
+ for (const schema of this.state.schemas.values()) {
4187
+ if (schema.oid === oid) return schema.name;
4062
4188
  }
4063
- this.base = null;
4064
- this.savepoints = [];
4065
- this.state.inTransaction = false;
4066
- this.state.localSettings.clear();
4067
- while (this.freezeDepth > 0) this.thawOnce();
4189
+ return null;
4068
4190
  }
4069
- savepoint(name) {
4070
- if (this.base === null) {
4071
- throw pgError("transaction_state", "SAVEPOINT can only be used in transaction blocks", "25P01");
4072
- }
4073
- this.savepoints.push({ name, snap: this.takeSnapshot() });
4191
+ zoneOffsetAt(utcMicros) {
4192
+ return zoneOffsetAtUtc(this.timezone(), utcMicros);
4074
4193
  }
4075
- releaseSavepoint(name) {
4076
- const idx = this.findSavepoint(name);
4077
- this.savepoints.splice(idx);
4194
+ zoneOffsetForNaive(naiveMicros) {
4195
+ return zoneOffsetForNaive(this.timezone(), naiveMicros);
4078
4196
  }
4079
- rollbackToSavepoint(name) {
4080
- const idx = this.findSavepoint(name);
4081
- const sp = this.savepoints[idx];
4082
- this.restore(sp.snap);
4083
- this.savepoints.splice(idx + 1);
4197
+ enumLabels(enumType) {
4198
+ if (!isEnumType(enumType)) return null;
4199
+ const e = this.state.findEnumByKey(enumType.slice(5));
4200
+ return e?.labels ?? null;
4084
4201
  }
4085
- findSavepoint(name) {
4086
- if (this.base === null) {
4087
- throw pgError("transaction_state", `SAVEPOINT can only be used in transaction blocks`, "25P01");
4088
- }
4089
- for (let i = this.savepoints.length - 1; i >= 0; i--) {
4090
- if (this.savepoints[i].name === name) return i;
4091
- }
4092
- throw pgError("invalid_savepoint_specification", `savepoint "${name}" does not exist`, "3B001");
4202
+ enumHasLabel(enumType, label) {
4203
+ const labels = this.enumLabels(enumType);
4204
+ return labels === null ? true : labels.includes(label);
4093
4205
  }
4094
- reset() {
4095
- this.base = null;
4096
- this.savepoints = [];
4097
- this.state.inTransaction = false;
4098
- this.freezeDepth = 0;
4206
+ enumOrder(enumType, label) {
4207
+ const labels = this.enumLabels(enumType);
4208
+ if (!labels) return 0;
4209
+ const idx = labels.indexOf(label);
4210
+ return idx === -1 ? labels.length : idx;
4211
+ }
4212
+ requireEnum(enumType) {
4213
+ const labels = this.enumLabels(enumType);
4214
+ if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
4215
+ return labels;
4099
4216
  }
4100
4217
  };
4101
4218
 
4219
+ // src/api/bind.ts
4220
+ var INT4_MIN2 = -2147483648;
4221
+ var INT4_MAX2 = 2147483647;
4222
+ function bindValueToTyped(value, index) {
4223
+ if (value === null || value === void 0) return tv(UNKNOWN, null);
4224
+ switch (typeof value) {
4225
+ case "boolean":
4226
+ return tv("bool", value);
4227
+ case "number":
4228
+ if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
4229
+ return tv("int4", value);
4230
+ }
4231
+ if (Number.isInteger(value) && Number.isSafeInteger(value)) {
4232
+ return tv("int8", BigInt(value));
4233
+ }
4234
+ return tv("float8", value);
4235
+ case "bigint":
4236
+ if (value < -9223372036854775808n || value > 9223372036854775807n) {
4237
+ throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
4238
+ }
4239
+ return tv("int8", value);
4240
+ case "string":
4241
+ return tv(UNKNOWN, value);
4242
+ case "object": {
4243
+ if (value instanceof Uint8Array) return tv("bytea", value);
4244
+ if (value instanceof Date) {
4245
+ const ms = value.getTime();
4246
+ if (Number.isNaN(ms)) {
4247
+ throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
4248
+ }
4249
+ return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
4250
+ }
4251
+ break;
4252
+ }
4253
+ default:
4254
+ break;
4255
+ }
4256
+ throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
4257
+ }
4258
+ function datumToJs(t, v, ctx, int8 = "bigint") {
4259
+ if (v === null) return null;
4260
+ switch (t) {
4261
+ case "bool":
4262
+ return v;
4263
+ case "int2":
4264
+ case "int4":
4265
+ case "oid":
4266
+ return typeof v === "bigint" ? Number(v) : v;
4267
+ case "int8": {
4268
+ const n = typeof v === "bigint" ? v : BigInt(v);
4269
+ if (int8 === "string") return n.toString();
4270
+ if (int8 === "number") return Number(n);
4271
+ return n;
4272
+ }
4273
+ case "float4":
4274
+ case "float8":
4275
+ return v;
4276
+ case "bytea":
4277
+ return v;
4278
+ default:
4279
+ return datumText(t === UNKNOWN ? "text" : t, v, ctx);
4280
+ }
4281
+ }
4282
+
4102
4283
  // src/types/cast.ts
4103
4284
  var UTC_CAST_ENV = {
4104
4285
  zoneOffsetAt: () => 0,
@@ -4294,7 +4475,7 @@ function castTo(env, value, target, opts = {}) {
4294
4475
  return tv(target, makeArray(toElem, items, arr.dims.slice(), arr.lbs.slice()));
4295
4476
  }
4296
4477
  if (from === "oid" && target === "regnamespace") return tv(target, v);
4297
- if (from === "regnamespace" && (target === "oid" || target === "int4" || target === "int8")) {
4478
+ if ((from === "regnamespace" || from === "regclass") && (target === "oid" || target === "int4" || target === "int8")) {
4298
4479
  return tv(target, target === "int8" ? BigInt(v) : v);
4299
4480
  }
4300
4481
  if ((from === "int4" || from === "int8" || from === "int2") && (target === "oid" || target === "regnamespace")) {
@@ -4575,259 +4756,6 @@ function unifyTypes(a, b) {
4575
4756
  return null;
4576
4757
  }
4577
4758
 
4578
- // src/types/resolve.ts
4579
- var SERIALS = {
4580
- smallserial: "int2",
4581
- serial2: "int2",
4582
- serial: "int4",
4583
- serial4: "int4",
4584
- bigserial: "int8",
4585
- serial8: "int8"
4586
- };
4587
- function modOf(t, mods) {
4588
- if (mods.length === 0) return null;
4589
- if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
4590
- return { a: mods[0] };
4591
- }
4592
- function resolveTypeName(state, tn) {
4593
- const joined = tn.parts.join(".");
4594
- const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
4595
- if (bare !== null) {
4596
- const serial = SERIALS[bare];
4597
- if (serial !== void 0 && tn.arrayDims === 0) {
4598
- return { column: { id: serial, mod: null }, domain: null, serial };
4599
- }
4600
- const builtin = normalizeTypeName(bare);
4601
- if (builtin !== null) {
4602
- const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
4603
- return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
4604
- }
4605
- }
4606
- const enumData = state.findEnum(tn.parts);
4607
- if (enumData) {
4608
- const elem = `enum:${enumData.schema}.${enumData.name}`;
4609
- const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
4610
- return { column: { id, mod: null }, domain: null, serial: null };
4611
- }
4612
- const domainData = state.findDomain(tn.parts);
4613
- if (domainData) {
4614
- if (tn.arrayDims > 0) {
4615
- const id = arrayTypeOf(domainData.baseType.id);
4616
- return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
4617
- }
4618
- return {
4619
- column: domainData.baseType,
4620
- domain: `${domainData.schema}.${domainData.name}`,
4621
- serial: null
4622
- };
4623
- }
4624
- throw pgError("undefined_object", `type "${joined}" does not exist`);
4625
- }
4626
-
4627
- // src/executor/relation.ts
4628
- var RowScope = class {
4629
- constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
4630
- this.columns = columns;
4631
- this.row = row;
4632
- this.parent = parent;
4633
- this.rangeVars = rangeVars;
4634
- }
4635
- columns;
4636
- row;
4637
- parent;
4638
- rangeVars;
4639
- /** Resolve a (possibly qualified) column reference. undefined = not found. */
4640
- lookup(parts) {
4641
- if (parts.length === 1) {
4642
- const name2 = parts[0];
4643
- let found2;
4644
- let count2 = 0;
4645
- for (let i = 0; i < this.columns.length; i++) {
4646
- const c = this.columns[i];
4647
- if (c.name === name2 && !c.hidden) {
4648
- count2++;
4649
- if (count2 > 1) {
4650
- throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
4651
- }
4652
- found2 = tv(c.type, this.row[i] ?? null);
4653
- }
4654
- }
4655
- if (found2 !== void 0) return found2;
4656
- if (this.rangeVars.has(name2)) {
4657
- return this.wholeRow(name2);
4658
- }
4659
- return this.parent?.lookup(parts);
4660
- }
4661
- const table = parts[parts.length - 2];
4662
- const name = parts[parts.length - 1];
4663
- let found;
4664
- let count = 0;
4665
- for (let i = 0; i < this.columns.length; i++) {
4666
- const c = this.columns[i];
4667
- if (c.table === table && c.name === name) {
4668
- count++;
4669
- if (count > 1) {
4670
- throw pgError("ambiguous_column", `column reference "${name}" is ambiguous`);
4671
- }
4672
- found = tv(c.type, this.row[i] ?? null);
4673
- }
4674
- }
4675
- if (found !== void 0) return found;
4676
- return this.parent?.lookup(parts);
4677
- }
4678
- /** Build a record value from all columns belonging to a range variable. */
4679
- wholeRow(rangeVar) {
4680
- const types = [];
4681
- const values = [];
4682
- const names = [];
4683
- for (let i = 0; i < this.columns.length; i++) {
4684
- const c = this.columns[i];
4685
- if (c.table === rangeVar) {
4686
- types.push(c.type);
4687
- values.push(this.row[i] ?? null);
4688
- names.push(c.name);
4689
- }
4690
- }
4691
- if (types.length === 0) return void 0;
4692
- return tv("record", { kind: "pgrecord", types, values, names });
4693
- }
4694
- hasRangeVar(name) {
4695
- if (this.rangeVars.has(name)) return true;
4696
- return this.parent?.hasRangeVar(name) ?? false;
4697
- }
4698
- };
4699
- function childEnv(env, outer) {
4700
- return {
4701
- ctx: env.ctx,
4702
- params: env.params,
4703
- ctes: env.ctes,
4704
- outer,
4705
- allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
4706
- };
4707
- }
4708
- function relationResult(rel3, command) {
4709
- const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
4710
- return {
4711
- columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
4712
- rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
4713
- command,
4714
- rowCount: rel3.rows.length
4715
- };
4716
- }
4717
- function commandResult(command, rowCount) {
4718
- return { columns: [], rows: [], command, rowCount };
4719
- }
4720
- function inferColumnName(e) {
4721
- switch (e.type) {
4722
- case "colref":
4723
- return e.parts[e.parts.length - 1];
4724
- case "func":
4725
- return e.name[e.name.length - 1];
4726
- case "cast": {
4727
- const inner = inferColumnName(e.expr);
4728
- if (inner !== "?column?") return inner;
4729
- return e.target.parts[e.target.parts.length - 1];
4730
- }
4731
- case "collate":
4732
- return inferColumnName(e.expr);
4733
- case "case":
4734
- return "case";
4735
- case "array_ctor":
4736
- case "array_query":
4737
- return "array";
4738
- case "row":
4739
- return "row";
4740
- case "subquery_expr":
4741
- return e.kind === "exists" ? "exists" : "?column?";
4742
- case "bool_lit":
4743
- return "bool";
4744
- case "extract":
4745
- return "extract";
4746
- case "position":
4747
- return "position";
4748
- case "substring_sql":
4749
- return "substring";
4750
- case "overlay":
4751
- return "overlay";
4752
- case "trim":
4753
- return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
4754
- case "field_select":
4755
- return e.field === "*" ? "?column?" : e.field;
4756
- case "at_time_zone":
4757
- return "timezone";
4758
- case "grouping_func":
4759
- return "grouping";
4760
- case "subscript":
4761
- return inferColumnName(e.base);
4762
- default:
4763
- return "?column?";
4764
- }
4765
- }
4766
-
4767
- // src/api/bind.ts
4768
- var INT4_MIN2 = -2147483648;
4769
- var INT4_MAX2 = 2147483647;
4770
- function bindValueToTyped(value, index) {
4771
- if (value === null || value === void 0) return tv(UNKNOWN, null);
4772
- switch (typeof value) {
4773
- case "boolean":
4774
- return tv("bool", value);
4775
- case "number":
4776
- if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
4777
- return tv("int4", value);
4778
- }
4779
- if (Number.isInteger(value) && Number.isSafeInteger(value)) {
4780
- return tv("int8", BigInt(value));
4781
- }
4782
- return tv("float8", value);
4783
- case "bigint":
4784
- if (value < -9223372036854775808n || value > 9223372036854775807n) {
4785
- throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
4786
- }
4787
- return tv("int8", value);
4788
- case "string":
4789
- return tv(UNKNOWN, value);
4790
- case "object": {
4791
- if (value instanceof Uint8Array) return tv("bytea", value);
4792
- if (value instanceof Date) {
4793
- const ms = value.getTime();
4794
- if (Number.isNaN(ms)) {
4795
- throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
4796
- }
4797
- return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
4798
- }
4799
- break;
4800
- }
4801
- default:
4802
- break;
4803
- }
4804
- throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
4805
- }
4806
- function datumToJs(t, v, ctx, int8 = "bigint") {
4807
- if (v === null) return null;
4808
- switch (t) {
4809
- case "bool":
4810
- return v;
4811
- case "int2":
4812
- case "int4":
4813
- case "oid":
4814
- return typeof v === "bigint" ? Number(v) : v;
4815
- case "int8": {
4816
- const n = typeof v === "bigint" ? v : BigInt(v);
4817
- if (int8 === "string") return n.toString();
4818
- if (int8 === "number") return Number(n);
4819
- return n;
4820
- }
4821
- case "float4":
4822
- case "float8":
4823
- return v;
4824
- case "bytea":
4825
- return v;
4826
- default:
4827
- return datumText(t === UNKNOWN ? "text" : t, v, ctx);
4828
- }
4829
- }
4830
-
4831
4759
  // src/functions/datetime-fns.ts
4832
4760
  function extractDatePart(ctx, field0, src0, asNumeric) {
4833
4761
  const field = field0.toLowerCase();
@@ -5248,6 +5176,8 @@ function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
5248
5176
  case "int2":
5249
5177
  case "int4":
5250
5178
  case "oid":
5179
+ case "regclass":
5180
+ case "xid":
5251
5181
  case "regnamespace":
5252
5182
  case "date":
5253
5183
  return expectNumber(a, t) - expectNumber(b, t);
@@ -5367,6 +5297,8 @@ function datumKey(t, v) {
5367
5297
  case "int2":
5368
5298
  case "int4":
5369
5299
  case "oid":
5300
+ case "regclass":
5301
+ case "xid":
5370
5302
  case "date":
5371
5303
  return `i${v}`;
5372
5304
  case "float4":
@@ -5742,68 +5674,6 @@ function getArrayFunctions() {
5742
5674
  return m;
5743
5675
  }
5744
5676
 
5745
- // src/types/timezone.ts
5746
- var intlCache = /* @__PURE__ */ new Map();
5747
- function intlFor(zone) {
5748
- const cached = intlCache.get(zone);
5749
- if (cached) return cached;
5750
- try {
5751
- const fmt = new Intl.DateTimeFormat("en-US", {
5752
- timeZone: zone,
5753
- timeZoneName: "longOffset",
5754
- year: "numeric"
5755
- });
5756
- intlCache.set(zone, fmt);
5757
- return fmt;
5758
- } catch {
5759
- return null;
5760
- }
5761
- }
5762
- function parseFixedOffset(zone) {
5763
- const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
5764
- if (!m) return null;
5765
- const sign = m[1] === "-" ? -1 : 1;
5766
- return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
5767
- }
5768
- function parsePosixOffset(zone) {
5769
- const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
5770
- if (!m) return null;
5771
- const sign = m[1] === "-" ? 1 : -1;
5772
- return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
5773
- }
5774
- function pgMicrosToUnixMs(utcMicros) {
5775
- return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
5776
- }
5777
- function zoneOffsetAtUtc(zone, utcMicros) {
5778
- const z = zone.trim();
5779
- const lower = z.toLowerCase();
5780
- if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
5781
- const posix = parsePosixOffset(z);
5782
- if (posix !== null) return posix;
5783
- const fixed = parseFixedOffset(z);
5784
- if (fixed !== null) return fixed;
5785
- const fmt = intlFor(z);
5786
- if (fmt) {
5787
- const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
5788
- const parts = fmt.formatToParts(new Date(ms));
5789
- const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
5790
- const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
5791
- if (!m) return 0;
5792
- const sign = m[1] === "-" ? -1 : 1;
5793
- return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
5794
- }
5795
- throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
5796
- }
5797
- function clampDateMs(ms) {
5798
- const MAX = 864e13;
5799
- return Math.max(-MAX, Math.min(MAX, ms));
5800
- }
5801
- function zoneOffsetForNaive(zone, naiveMicros) {
5802
- const first = zoneOffsetAtUtc(zone, naiveMicros);
5803
- const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
5804
- return second;
5805
- }
5806
-
5807
5677
  // src/functions/datetime-registry.ts
5808
5678
  function getDatetimeFunctions() {
5809
5679
  const m = /* @__PURE__ */ new Map();
@@ -7403,6 +7273,28 @@ function exactDegTan(x) {
7403
7273
  return Math.tan(x * Math.PI / 180);
7404
7274
  }
7405
7275
 
7276
+ // src/storage/indexable-relation.ts
7277
+ function materializedTable(view) {
7278
+ const table = new TableData(
7279
+ view.schema,
7280
+ view.name,
7281
+ (view.matColumns ?? []).map((c) => ({
7282
+ name: c.name,
7283
+ type: { id: c.type, mod: null },
7284
+ notNull: false,
7285
+ defaultExpr: null,
7286
+ identity: null,
7287
+ generated: null,
7288
+ collate: null,
7289
+ domain: null
7290
+ })),
7291
+ view.oid,
7292
+ view.temp
7293
+ );
7294
+ table.rows = view.matRows ?? [];
7295
+ return table;
7296
+ }
7297
+
7406
7298
  // src/schema/index-catalog.ts
7407
7299
  var isKeyConstraint = (constraint) => constraint.kind === "primary_key" || constraint.kind === "unique";
7408
7300
  var ACCESS_METHODS = /* @__PURE__ */ new Map([
@@ -7431,6 +7323,8 @@ function syncIndexCatalog(state) {
7431
7323
  const tables = /* @__PURE__ */ new Map();
7432
7324
  for (const schema of state.schemas.values()) {
7433
7325
  for (const table of schema.tables.values()) tables.set(table.oid, { schema, table });
7326
+ for (const view of schema.views.values())
7327
+ if (view.materialized) tables.set(view.oid, { schema, table: materializedTable(view) });
7434
7328
  }
7435
7329
  const backing = /* @__PURE__ */ new Map();
7436
7330
  for (const { table } of tables.values()) {
@@ -7628,6 +7522,55 @@ function deparseExpr(e) {
7628
7522
  }
7629
7523
  }
7630
7524
 
7525
+ // src/types/resolve.ts
7526
+ var SERIALS = {
7527
+ smallserial: "int2",
7528
+ serial2: "int2",
7529
+ serial: "int4",
7530
+ serial4: "int4",
7531
+ bigserial: "int8",
7532
+ serial8: "int8"
7533
+ };
7534
+ function modOf(t, mods) {
7535
+ if (mods.length === 0) return null;
7536
+ if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
7537
+ return { a: mods[0] };
7538
+ }
7539
+ function resolveTypeName(state, tn) {
7540
+ const joined = tn.parts.join(".");
7541
+ const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
7542
+ if (bare !== null) {
7543
+ const serial = SERIALS[bare];
7544
+ if (serial !== void 0 && tn.arrayDims === 0) {
7545
+ return { column: { id: serial, mod: null }, domain: null, serial };
7546
+ }
7547
+ const builtin = normalizeTypeName(bare);
7548
+ if (builtin !== null) {
7549
+ const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
7550
+ return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
7551
+ }
7552
+ }
7553
+ const enumData = state.findEnum(tn.parts);
7554
+ if (enumData) {
7555
+ const elem = `enum:${enumData.schema}.${enumData.name}`;
7556
+ const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
7557
+ return { column: { id, mod: null }, domain: null, serial: null };
7558
+ }
7559
+ const domainData = state.findDomain(tn.parts);
7560
+ if (domainData) {
7561
+ if (tn.arrayDims > 0) {
7562
+ const id = arrayTypeOf(domainData.baseType.id);
7563
+ return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
7564
+ }
7565
+ return {
7566
+ column: domainData.baseType,
7567
+ domain: `${domainData.schema}.${domainData.name}`,
7568
+ serial: null
7569
+ };
7570
+ }
7571
+ throw pgError("undefined_object", `type "${joined}" does not exist`);
7572
+ }
7573
+
7631
7574
  // src/sql/ruleutils.ts
7632
7575
  var BOOL = "bool";
7633
7576
  var TEXT = "text";
@@ -8261,7 +8204,7 @@ function databaseCatalogContext(state) {
8261
8204
  var PG_VERSION_TEXT = "PostgreSQL 18.3 (postgres-mem) on TypeScript, in-memory engine";
8262
8205
  function findSequenceForCall(ctx, name) {
8263
8206
  const parts = parseQualifiedName(name);
8264
- const seq = ctx.state.findSequence(parts);
8207
+ const seq = /^\d+$/.test(name) ? [...ctx.state.schemas.values()].flatMap((schema) => [...schema.sequences.values()]).find((sequence) => sequence.oid === Number(name)) : ctx.state.findSequence(parts);
8265
8208
  if (!seq) {
8266
8209
  throw pgError("undefined_table", `relation "${name}" does not exist`, "42P01");
8267
8210
  }
@@ -8422,7 +8365,11 @@ function getMiscFunctions() {
8422
8365
  }
8423
8366
  const name = argText(ctx, args[0]).toLowerCase();
8424
8367
  const value = args[1].v === null ? "" : argText(ctx, args[1]);
8425
- ctx.state.settings.set(name, value);
8368
+ if (!ctx.state.settings.has(name) && !name.includes("."))
8369
+ throw pgError("undefined_object", `unrecognized configuration parameter "${name}"`, "42704");
8370
+ validateStorageSetting(name, value);
8371
+ const local = args[2]?.v === true;
8372
+ if (!local || ctx.state.inTransaction) (local ? ctx.state.localSettings : ctx.state.settings).set(name, value);
8426
8373
  return tv("text", value);
8427
8374
  });
8428
8375
  m.set(
@@ -8481,17 +8428,16 @@ function getMiscFunctions() {
8481
8428
  "pg_get_serial_sequence",
8482
8429
  strict("text", (ctx, args) => {
8483
8430
  const tableName2 = argText(ctx, args[0]);
8484
- const column = argText(ctx, args[1]).toLowerCase();
8431
+ const column = argText(ctx, args[1]);
8485
8432
  const table = ctx.state.findTable(parseQualifiedName(tableName2));
8486
8433
  if (!table) throw pgError("undefined_table", `relation "${tableName2}" does not exist`, "42P01");
8487
8434
  const col = table.columns.find((c) => c.name === column);
8488
8435
  if (!col)
8489
8436
  throw pgError("undefined_column", `column "${column}" of relation "${table.name}" does not exist`, "42703");
8490
- if (!col.identity) return tv("text", null);
8491
- return tv(
8492
- "text",
8493
- col.identity.sequence.split(".").map(quoteIdent).join(".")
8437
+ const seq = [...ctx.state.schemas.get(table.schema)?.sequences.values() ?? []].find(
8438
+ (candidate) => candidate.ownedBy?.table === table.name && candidate.ownedBy.column === column
8494
8439
  );
8440
+ return tv("text", seq ? [seq.schema, seq.name].map(quoteIdent).join(".") : null);
8495
8441
  })
8496
8442
  );
8497
8443
  m.set("format_type", (ctx, args) => {
@@ -13415,6 +13361,146 @@ function isSrfName(name) {
13415
13361
  return SRFS.has(name);
13416
13362
  }
13417
13363
 
13364
+ // src/executor/relation.ts
13365
+ var RowScope = class {
13366
+ constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
13367
+ this.columns = columns;
13368
+ this.row = row;
13369
+ this.parent = parent;
13370
+ this.rangeVars = rangeVars;
13371
+ }
13372
+ columns;
13373
+ row;
13374
+ parent;
13375
+ rangeVars;
13376
+ /** Resolve a (possibly qualified) column reference. undefined = not found. */
13377
+ lookup(parts) {
13378
+ if (parts.length === 1) {
13379
+ const name2 = parts[0];
13380
+ let found2;
13381
+ let count2 = 0;
13382
+ for (let i = 0; i < this.columns.length; i++) {
13383
+ const c = this.columns[i];
13384
+ if (c.name === name2 && (!c.hidden || c.system)) {
13385
+ count2++;
13386
+ if (count2 > 1) {
13387
+ throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
13388
+ }
13389
+ found2 = tv(c.type, this.row[i] ?? null);
13390
+ }
13391
+ }
13392
+ if (found2 !== void 0) return found2;
13393
+ if (this.rangeVars.has(name2)) {
13394
+ return this.wholeRow(name2);
13395
+ }
13396
+ return this.parent?.lookup(parts);
13397
+ }
13398
+ const table = parts[parts.length - 2];
13399
+ const name = parts[parts.length - 1];
13400
+ let found;
13401
+ let count = 0;
13402
+ for (let i = 0; i < this.columns.length; i++) {
13403
+ const c = this.columns[i];
13404
+ if (c.table === table && c.name === name) {
13405
+ count++;
13406
+ if (count > 1) {
13407
+ throw pgError("ambiguous_column", `column reference "${name}" is ambiguous`);
13408
+ }
13409
+ found = tv(c.type, this.row[i] ?? null);
13410
+ }
13411
+ }
13412
+ if (found !== void 0) return found;
13413
+ return this.parent?.lookup(parts);
13414
+ }
13415
+ /** Build a record value from all columns belonging to a range variable. */
13416
+ wholeRow(rangeVar) {
13417
+ const types = [];
13418
+ const values = [];
13419
+ const names = [];
13420
+ for (let i = 0; i < this.columns.length; i++) {
13421
+ const c = this.columns[i];
13422
+ if (c.table === rangeVar && !c.system) {
13423
+ types.push(c.type);
13424
+ values.push(this.row[i] ?? null);
13425
+ names.push(c.name);
13426
+ }
13427
+ }
13428
+ if (types.length === 0) return void 0;
13429
+ return tv("record", { kind: "pgrecord", types, values, names });
13430
+ }
13431
+ hasRangeVar(name) {
13432
+ if (this.rangeVars.has(name)) return true;
13433
+ return this.parent?.hasRangeVar(name) ?? false;
13434
+ }
13435
+ };
13436
+ function childEnv(env, outer) {
13437
+ return {
13438
+ ctx: env.ctx,
13439
+ params: env.params,
13440
+ ctes: env.ctes,
13441
+ outer,
13442
+ allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
13443
+ };
13444
+ }
13445
+ function relationResult(rel3, command) {
13446
+ const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
13447
+ return {
13448
+ columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
13449
+ rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
13450
+ command,
13451
+ rowCount: rel3.rows.length
13452
+ };
13453
+ }
13454
+ function commandResult(command, rowCount) {
13455
+ return { columns: [], rows: [], command, rowCount };
13456
+ }
13457
+ function inferColumnName(e) {
13458
+ switch (e.type) {
13459
+ case "colref":
13460
+ return e.parts[e.parts.length - 1];
13461
+ case "func":
13462
+ return e.name[e.name.length - 1];
13463
+ case "cast": {
13464
+ const inner = inferColumnName(e.expr);
13465
+ if (inner !== "?column?") return inner;
13466
+ return e.target.parts[e.target.parts.length - 1];
13467
+ }
13468
+ case "collate":
13469
+ return inferColumnName(e.expr);
13470
+ case "case":
13471
+ return "case";
13472
+ case "array_ctor":
13473
+ case "array_query":
13474
+ return "array";
13475
+ case "row":
13476
+ return "row";
13477
+ case "subquery_expr":
13478
+ return e.kind === "exists" ? "exists" : "?column?";
13479
+ case "bool_lit":
13480
+ return "bool";
13481
+ case "extract":
13482
+ return "extract";
13483
+ case "position":
13484
+ return "position";
13485
+ case "substring_sql":
13486
+ return "substring";
13487
+ case "overlay":
13488
+ return "overlay";
13489
+ case "trim":
13490
+ return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
13491
+ case "field_select":
13492
+ return e.field === "*" ? "?column?" : e.field;
13493
+ case "at_time_zone":
13494
+ return "timezone";
13495
+ case "grouping_func":
13496
+ return "grouping";
13497
+ case "subscript":
13498
+ return inferColumnName(e.base);
13499
+ default:
13500
+ return "?column?";
13501
+ }
13502
+ }
13503
+
13418
13504
  // src/indexes/index.ts
13419
13505
  var IndexStore = class _IndexStore {
13420
13506
  name;
@@ -13517,13 +13603,188 @@ function indexRemoveRow(env, table, rowIdx, row) {
13517
13603
  table.indexStores.get(spec.name)?.remove(key, rowIdx);
13518
13604
  }
13519
13605
  }
13520
- function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
13521
- indexRemoveRow(env, table, rowIdx, oldRow);
13522
- indexInsertRow(env, table, rowIdx, newRow);
13523
- }
13524
- function rebuildTableIndexes(env, table) {
13525
- table.indexStores = null;
13526
- ensureIndexStores(env, table);
13606
+ function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
13607
+ indexRemoveRow(env, table, rowIdx, oldRow);
13608
+ indexInsertRow(env, table, rowIdx, newRow);
13609
+ }
13610
+ function rebuildTableIndexes(env, table) {
13611
+ table.indexStores = null;
13612
+ ensureIndexStores(env, table);
13613
+ }
13614
+
13615
+ // src/constraints/enforce.ts
13616
+ function tableScope(table, row) {
13617
+ const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
13618
+ return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
13619
+ }
13620
+ function checkNotNull(env, table, row) {
13621
+ void env;
13622
+ for (let i = 0; i < table.columns.length; i++) {
13623
+ const c = table.columns[i];
13624
+ if (c.notNull && (row[i] ?? null) === null) {
13625
+ throw pgError(
13626
+ "not_null_violation",
13627
+ `null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
13628
+ "23502"
13629
+ );
13630
+ }
13631
+ }
13632
+ }
13633
+ function checkChecks(env, table, row) {
13634
+ for (const con of table.constraints) {
13635
+ if (con.kind !== "check") continue;
13636
+ const scope = makeEvalScope(env, tableScope(table, row));
13637
+ const v = evalExpr(env.ctx, scope, con.expr);
13638
+ if (v.v === null) continue;
13639
+ const b = castTo(env.ctx, v, "bool", {});
13640
+ if (b.v !== true) {
13641
+ throw pgError(
13642
+ "check_violation",
13643
+ `new row for relation "${table.name}" violates check constraint "${con.name}"`,
13644
+ "23514"
13645
+ );
13646
+ }
13647
+ }
13648
+ }
13649
+ function uniqueSpecsFor(env, table) {
13650
+ const specs = [];
13651
+ for (const con of table.constraints) {
13652
+ if (con.kind !== "primary_key" && con.kind !== "unique") continue;
13653
+ specs.push({
13654
+ name: con.name,
13655
+ keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
13656
+ columnNames: con.columns,
13657
+ nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
13658
+ where: null,
13659
+ isPrimary: con.kind === "primary_key"
13660
+ });
13661
+ }
13662
+ const schema = env.ctx.state.schemas.get(table.schema);
13663
+ if (schema) {
13664
+ for (const idx of schema.indexes.values()) {
13665
+ if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
13666
+ specs.push(uniqueSpecOfIndex(table, idx));
13667
+ }
13668
+ }
13669
+ return specs;
13670
+ }
13671
+ function uniqueSpecOfIndex(table, idx) {
13672
+ return {
13673
+ name: idx.name,
13674
+ keys: idx.columns.map((c) => ({
13675
+ colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
13676
+ expr: c.expr
13677
+ })),
13678
+ columnNames: idx.columns.map((c) => c.column ?? "expr"),
13679
+ nullsNotDistinct: idx.nullsNotDistinct,
13680
+ where: idx.where,
13681
+ isPrimary: false
13682
+ };
13683
+ }
13684
+ function uniqueKeyOf(env, table, spec, row) {
13685
+ if (spec.where) {
13686
+ const scope = makeEvalScope(env, tableScope(table, row));
13687
+ const v = evalExpr(env.ctx, scope, spec.where);
13688
+ if (v.v !== true) return null;
13689
+ }
13690
+ const parts = [];
13691
+ let hasNull = false;
13692
+ for (const k of spec.keys) {
13693
+ let value;
13694
+ let type;
13695
+ if (k.expr) {
13696
+ const scope = makeEvalScope(env, tableScope(table, row));
13697
+ const v = evalExpr(env.ctx, scope, k.expr);
13698
+ value = v.v;
13699
+ type = v.t === "unknown" ? "text" : v.t;
13700
+ } else {
13701
+ value = row[k.colIdx] ?? null;
13702
+ type = table.columns[k.colIdx].type.id;
13703
+ }
13704
+ if (value === null) {
13705
+ hasNull = true;
13706
+ parts.push("\0N");
13707
+ } else {
13708
+ parts.push(datumKey(type, value));
13709
+ }
13710
+ }
13711
+ if (hasNull && !spec.nullsNotDistinct) return null;
13712
+ return parts.join("");
13713
+ }
13714
+ function checkUnique(env, table, row, selfIdx) {
13715
+ for (const spec of uniqueSpecsFor(env, table)) {
13716
+ const key = uniqueKeyOf(env, table, spec, row);
13717
+ if (key === null) continue;
13718
+ indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
13719
+ }
13720
+ }
13721
+ function findConflict(env, table, spec, row) {
13722
+ const key = uniqueKeyOf(env, table, spec, row);
13723
+ if (key === null) return null;
13724
+ const hits = indexStoreFor(env, table, spec).lookup(key);
13725
+ return hits.length > 0 ? hits[0] : null;
13726
+ }
13727
+ function checkForeignKeys(env, table, row) {
13728
+ const state = env.ctx.state;
13729
+ for (const con of table.constraints) {
13730
+ if (con.kind !== "foreign_key") continue;
13731
+ const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
13732
+ const nulls = values.filter((v) => v === null).length;
13733
+ if (con.match === "simple" && nulls > 0) continue;
13734
+ if (con.match === "full") {
13735
+ if (nulls === values.length) continue;
13736
+ if (nulls > 0) {
13737
+ throw pgError(
13738
+ "constraint_foreign_key",
13739
+ `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
13740
+ "23503"
13741
+ );
13742
+ }
13743
+ }
13744
+ const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
13745
+ if (!refTable) {
13746
+ throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
13747
+ }
13748
+ const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
13749
+ const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
13750
+ const wanted = values.map((v, i) => {
13751
+ const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
13752
+ const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
13753
+ return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
13754
+ }).join("");
13755
+ let found = false;
13756
+ for (let i = 0; i < refTable.rowCount(); i++) {
13757
+ const r = refTable.rowAt(i);
13758
+ const key = refIdxs.map((ri, j) => {
13759
+ const v = r[ri] ?? null;
13760
+ return v === null ? "\0N" : datumKey(keyTypes[j], v);
13761
+ }).join("");
13762
+ if (key === wanted) {
13763
+ found = true;
13764
+ break;
13765
+ }
13766
+ }
13767
+ if (!found) {
13768
+ throw pgError(
13769
+ "constraint_foreign_key",
13770
+ `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
13771
+ "23503"
13772
+ );
13773
+ }
13774
+ }
13775
+ }
13776
+ function referencingConstraints(env, table) {
13777
+ const out = [];
13778
+ for (const schema of env.ctx.state.schemas.values()) {
13779
+ for (const t of schema.tables.values()) {
13780
+ for (const con of t.constraints) {
13781
+ if (con.kind === "foreign_key" && con.refSchema === table.schema && con.refTable === table.name) {
13782
+ out.push({ table: t, constraint: con });
13783
+ }
13784
+ }
13785
+ }
13786
+ }
13787
+ return out;
13527
13788
  }
13528
13789
 
13529
13790
  // src/planner/access.ts
@@ -13601,7 +13862,7 @@ function tryIndexedFromItem(env, item, where) {
13601
13862
  if (!table) return null;
13602
13863
  const alias = item.alias ?? item.name[item.name.length - 1];
13603
13864
  table.materializeSlab();
13604
- return tryIndexedTableRows(env, table, alias, where);
13865
+ return tryIndexedTableRows(env, table, alias, where)?.map((row) => [...row, table.rowXmins.get(row) ?? 2]) ?? null;
13605
13866
  }
13606
13867
  function joinKeyFromRow(row, colIdxs, srcTypes, unifiedTypes, ctx) {
13607
13868
  const parts = [];
@@ -15409,10 +15670,9 @@ var Parser = class {
15409
15670
  return this.parseCreateFunction(orReplace);
15410
15671
  }
15411
15672
  if (this.atKw("trigger") || this.atKw("constraint") && this.atKw("trigger", 1)) {
15412
- if (this.eatKw("constraint")) {
15413
- }
15673
+ const constraint = this.eatKw("constraint");
15414
15674
  this.expectKw("trigger");
15415
- return this.parseCreateTrigger(orReplace);
15675
+ return this.parseCreateTrigger(orReplace, constraint);
15416
15676
  }
15417
15677
  if (this.atKw("extension")) {
15418
15678
  this.pos++;
@@ -16092,6 +16352,7 @@ var Parser = class {
16092
16352
  let sqlBody = null;
16093
16353
  let volatility = null;
16094
16354
  let strict2 = false;
16355
+ const settings = {};
16095
16356
  for (; ; ) {
16096
16357
  if (this.eatKw("language")) {
16097
16358
  language = this.peek().type === "string" ? this.next().value : this.ident(true);
@@ -16149,8 +16410,23 @@ var Parser = class {
16149
16410
  continue;
16150
16411
  }
16151
16412
  if (this.eatKw("set")) {
16152
- this.ident(true);
16153
- if (this.eatOp("=") || this.eatKw("to")) this.next();
16413
+ const key = this.ident(true).toLowerCase();
16414
+ if (this.eatKw("from")) {
16415
+ this.expectKw("current");
16416
+ settings[key] = "__from_current__";
16417
+ } else {
16418
+ if (!this.eatOp("=")) this.expectKw("to");
16419
+ const values = [];
16420
+ do {
16421
+ const value = this.next();
16422
+ if (!["string", "ident", "quoted_ident", "number"].includes(value.type))
16423
+ this.errorAt(value, "expected setting value");
16424
+ values.push(
16425
+ key === "search_path" && /[^a-z0-9_]/.test(value.value) ? `"${value.value.replaceAll('"', '""')}"` : value.value
16426
+ );
16427
+ } while (this.eatPunct(","));
16428
+ settings[key] = values.join(", ");
16429
+ }
16154
16430
  continue;
16155
16431
  }
16156
16432
  if (this.eatKw("window")) throw unsupported("window functions via CREATE FUNCTION");
@@ -16230,10 +16506,11 @@ var Parser = class {
16230
16506
  body,
16231
16507
  sqlBody,
16232
16508
  volatility,
16233
- strict: strict2
16509
+ strict: strict2,
16510
+ settings
16234
16511
  };
16235
16512
  }
16236
- parseCreateTrigger(orReplace) {
16513
+ parseCreateTrigger(orReplace, constraint) {
16237
16514
  const name = this.ident();
16238
16515
  let timing;
16239
16516
  if (this.eatKw("before")) timing = "before";
@@ -16263,9 +16540,18 @@ var Parser = class {
16263
16540
  this.expectKw("on");
16264
16541
  const table = this.qualifiedName();
16265
16542
  if (this.eatKw("referencing")) throw unsupported("trigger transition tables");
16266
- while (this.atKw("not") || this.atKw("deferrable") || this.atKw("initially")) {
16267
- this.pos++;
16268
- }
16543
+ let deferrable = false;
16544
+ let initiallyDeferred = false;
16545
+ if (this.eatKw("not")) this.expectKw("deferrable");
16546
+ else if (this.eatKw("deferrable")) deferrable = true;
16547
+ if (this.eatKw("initially")) {
16548
+ if (this.eatKw("deferred")) initiallyDeferred = true;
16549
+ else this.expectKw("immediate");
16550
+ }
16551
+ if ((deferrable || initiallyDeferred) && !constraint)
16552
+ this.errorAt(this.peek(), "only constraint triggers can be deferred");
16553
+ if (initiallyDeferred && !deferrable)
16554
+ this.errorAt(this.peek(), "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
16269
16555
  let forEachRow = false;
16270
16556
  if (this.eatKw("for")) {
16271
16557
  this.eatKw("each");
@@ -16290,7 +16576,21 @@ var Parser = class {
16290
16576
  } while (this.eatPunct(","));
16291
16577
  }
16292
16578
  this.expectPunct(")");
16293
- return { type: "create_trigger", orReplace, name, timing, events, table, forEachRow, when, funcName, funcArgs };
16579
+ return {
16580
+ type: "create_trigger",
16581
+ constraint,
16582
+ deferrable,
16583
+ initiallyDeferred,
16584
+ orReplace,
16585
+ name,
16586
+ timing,
16587
+ events,
16588
+ table,
16589
+ forEachRow,
16590
+ when,
16591
+ funcName,
16592
+ funcArgs
16593
+ };
16294
16594
  }
16295
16595
  // --- ALTER --------------------------------------------------------------------
16296
16596
  parseAlter() {
@@ -16316,8 +16616,8 @@ var Parser = class {
16316
16616
  type: "alter_sequence",
16317
16617
  name,
16318
16618
  ifExists,
16319
- options: { ownedBy: void 0 },
16320
- ...{ renameTo: to }
16619
+ options: {},
16620
+ renameTo: to
16321
16621
  };
16322
16622
  }
16323
16623
  if (this.atKw("set") && (this.atKw("logged", 1) || this.atKw("unlogged", 1))) {
@@ -16635,9 +16935,15 @@ var Parser = class {
16635
16935
  this.skipToStatementEnd();
16636
16936
  return { type: "no_op", what: "SET TRANSACTION" };
16637
16937
  }
16638
- if (this.atKw("constraints")) {
16639
- this.skipToStatementEnd();
16640
- return { type: "no_op", what: "SET CONSTRAINTS" };
16938
+ if (this.eatKw("constraints")) {
16939
+ const names = this.eatKw("all") ? null : [];
16940
+ if (names)
16941
+ do {
16942
+ names.push(this.qualifiedName());
16943
+ } while (this.eatPunct(","));
16944
+ const deferred = this.eatKw("deferred");
16945
+ if (!deferred) this.expectKw("immediate");
16946
+ return { type: "set_constraints", names, deferred };
16641
16947
  }
16642
16948
  if (this.atKw("role") || this.atKw("session", 0) && this.atKw("authorization", 1)) {
16643
16949
  this.skipToStatementEnd();
@@ -18887,7 +19193,20 @@ function runFunctionBody(env, fn, args) {
18887
19193
  }
18888
19194
  return last;
18889
19195
  }
19196
+ function withFunctionSettings(env, fn, run) {
19197
+ const state = env.ctx.state;
19198
+ const saved = new Map(state.localSettings);
19199
+ for (const [name, value] of Object.entries(fn.settings ?? {})) state.localSettings.set(name, value);
19200
+ try {
19201
+ return run();
19202
+ } finally {
19203
+ state.localSettings = saved;
19204
+ }
19205
+ }
18890
19206
  function callSqlFunctionScalar(env, fn, args) {
19207
+ return withFunctionSettings(env, fn, () => callSqlFunctionScalarBody(env, fn, args));
19208
+ }
19209
+ function callSqlFunctionScalarBody(env, fn, args) {
18891
19210
  const retT = fn.returns ?? "text";
18892
19211
  if (fn.language === "plpgsql") {
18893
19212
  return callPlpgsqlScalar(env, fn, args);
@@ -18917,6 +19236,9 @@ function callSqlFunctionScalar(env, fn, args) {
18917
19236
  return castTo(env.ctx, tv(rawT, raw), retT, {});
18918
19237
  }
18919
19238
  function callSqlFunctionSet(env, fn, args) {
19239
+ return withFunctionSettings(env, fn, () => callSqlFunctionSetBody(env, fn, args));
19240
+ }
19241
+ function callSqlFunctionSetBody(env, fn, args) {
18920
19242
  if (fn.language === "plpgsql") {
18921
19243
  return callPlpgsqlSet(env, fn, args);
18922
19244
  }
@@ -19012,12 +19334,12 @@ function executeRecursiveCte(env, cte, query) {
19012
19334
  table: null
19013
19335
  }));
19014
19336
  const seen = /* @__PURE__ */ new Set();
19015
- const keyOf = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(columns[i].type, v)).join("");
19337
+ const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(columns[i].type, v)).join("");
19016
19338
  let result = [];
19017
19339
  let working = [];
19018
19340
  for (const row of base.rows) {
19019
19341
  if (!body.all) {
19020
- const k = keyOf(row);
19342
+ const k = keyOf2(row);
19021
19343
  if (seen.has(k)) continue;
19022
19344
  seen.add(k);
19023
19345
  }
@@ -19050,7 +19372,7 @@ function executeRecursiveCte(env, cte, query) {
19050
19372
  return castTo(env.ctx, tv(srcT === UNKNOWN ? "text" : srcT, v), columns[i].type, {}).v;
19051
19373
  });
19052
19374
  if (!body.all) {
19053
- const k = keyOf(row);
19375
+ const k = keyOf2(row);
19054
19376
  if (seen.has(k)) continue;
19055
19377
  seen.add(k);
19056
19378
  }
@@ -19071,15 +19393,17 @@ function executeRecursiveCte(env, cte, query) {
19071
19393
  return rel3;
19072
19394
  }
19073
19395
  function renameWithAliases(rel3, label, colAliases, what) {
19074
- if (colAliases && colAliases.length > rel3.columns.length) {
19396
+ const visibleWidth = rel3.columns.filter((column) => !column.system).length;
19397
+ if (colAliases && colAliases.length > visibleWidth) {
19075
19398
  throw pgError(
19076
19399
  "invalid_column_reference",
19077
- `table "${what}" has ${rel3.columns.length} columns available but ${colAliases.length} columns specified`,
19400
+ `table "${what}" has ${visibleWidth} columns available but ${colAliases.length} columns specified`,
19078
19401
  "42P10"
19079
19402
  );
19080
19403
  }
19081
19404
  const columns = rel3.columns.map((c, i) => ({
19082
- name: colAliases?.[i] ?? c.name,
19405
+ ...c,
19406
+ name: c.system ? c.name : colAliases?.[i] ?? c.name,
19083
19407
  type: c.type === UNKNOWN ? "text" : c.type,
19084
19408
  table: label
19085
19409
  }));
@@ -19100,8 +19424,11 @@ function materializeItem(env, item, scope) {
19100
19424
  if (table) {
19101
19425
  table.materializeSlab();
19102
19426
  const rel3 = {
19103
- columns: table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
19104
- rows: table.rows
19427
+ columns: [
19428
+ ...table.columns.map((c) => ({ name: c.name, type: c.type.id, table: label })),
19429
+ { name: "xmin", type: "xid", table: label, hidden: true, system: true }
19430
+ ],
19431
+ rows: table.rows.map((row) => [...row, table.rowXmins.get(row) ?? 2])
19105
19432
  };
19106
19433
  return { rel: renameWithAliases(rel3, label, item.colAliases, label), rangeVars: /* @__PURE__ */ new Set([label]) };
19107
19434
  }
@@ -19731,7 +20058,7 @@ function resolveColIdx(columns, parts) {
19731
20058
  let found = -1;
19732
20059
  for (let i = 0; i < columns.length; i++) {
19733
20060
  const c = columns[i];
19734
- if (!c.hidden && c.name === name2) {
20061
+ if ((!c.hidden || c.system) && c.name === name2) {
19735
20062
  if (found !== -1) return null;
19736
20063
  found = i;
19737
20064
  }
@@ -20230,7 +20557,7 @@ function setOpRelation(env, op) {
20230
20557
  );
20231
20558
  const lrows = normalize(left);
20232
20559
  const rrows = normalize(right);
20233
- const keyOf = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
20560
+ const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
20234
20561
  let rows;
20235
20562
  switch (op.op) {
20236
20563
  case "union": {
@@ -20238,7 +20565,7 @@ function setOpRelation(env, op) {
20238
20565
  if (!op.all) {
20239
20566
  const seen = /* @__PURE__ */ new Set();
20240
20567
  rows = rows.filter((r) => {
20241
- const k = keyOf(r);
20568
+ const k = keyOf2(r);
20242
20569
  if (seen.has(k)) return false;
20243
20570
  seen.add(k);
20244
20571
  return true;
@@ -20249,13 +20576,13 @@ function setOpRelation(env, op) {
20249
20576
  case "intersect": {
20250
20577
  const rightCounts = /* @__PURE__ */ new Map();
20251
20578
  for (const r of rrows) {
20252
- const k = keyOf(r);
20579
+ const k = keyOf2(r);
20253
20580
  rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
20254
20581
  }
20255
20582
  rows = [];
20256
20583
  const emitted = /* @__PURE__ */ new Set();
20257
20584
  for (const r of lrows) {
20258
- const k = keyOf(r);
20585
+ const k = keyOf2(r);
20259
20586
  const avail = rightCounts.get(k) ?? 0;
20260
20587
  if (avail <= 0) continue;
20261
20588
  if (op.all) {
@@ -20271,13 +20598,13 @@ function setOpRelation(env, op) {
20271
20598
  case "except": {
20272
20599
  const rightCounts = /* @__PURE__ */ new Map();
20273
20600
  for (const r of rrows) {
20274
- const k = keyOf(r);
20601
+ const k = keyOf2(r);
20275
20602
  rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
20276
20603
  }
20277
20604
  rows = [];
20278
20605
  const emitted = /* @__PURE__ */ new Set();
20279
20606
  for (const r of lrows) {
20280
- const k = keyOf(r);
20607
+ const k = keyOf2(r);
20281
20608
  if (op.all) {
20282
20609
  const avail = rightCounts.get(k) ?? 0;
20283
20610
  if (avail > 0) {
@@ -20315,7 +20642,7 @@ function expandTargets(core, columns) {
20315
20642
  let any = false;
20316
20643
  for (let i = 0; i < columns.length; i++) {
20317
20644
  const c = columns[i];
20318
- if (c.table === label) {
20645
+ if (c.table === label && !c.system) {
20319
20646
  any = true;
20320
20647
  items.push({ name: c.name, kind: "col", colIdx: i, expr: null, hidden: false });
20321
20648
  }
@@ -20753,202 +21080,225 @@ function executeSelectStmt(env0, stmt) {
20753
21080
  return applyLimitOffset(env, rel3, stmt.limit, stmt.offset);
20754
21081
  }
20755
21082
 
20756
- // src/constraints/enforce.ts
20757
- function tableScope(table, row) {
20758
- const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
20759
- return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
20760
- }
20761
- function checkNotNull(env, table, row) {
20762
- void env;
20763
- for (let i = 0; i < table.columns.length; i++) {
20764
- const c = table.columns[i];
20765
- if (c.notNull && (row[i] ?? null) === null) {
20766
- throw pgError(
20767
- "not_null_violation",
20768
- `null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
20769
- "23502"
20770
- );
21083
+ // src/executor/triggers-scope.ts
21084
+ function triggerScope(table, newRow, oldRow) {
21085
+ const cols = [];
21086
+ const row = [];
21087
+ const rangeVars = /* @__PURE__ */ new Set();
21088
+ if (newRow) {
21089
+ rangeVars.add("new");
21090
+ for (let i = 0; i < table.columns.length; i++) {
21091
+ cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
21092
+ row.push(newRow[i] ?? null);
20771
21093
  }
20772
21094
  }
20773
- }
20774
- function checkChecks(env, table, row) {
20775
- for (const con of table.constraints) {
20776
- if (con.kind !== "check") continue;
20777
- const scope = makeEvalScope(env, tableScope(table, row));
20778
- const v = evalExpr(env.ctx, scope, con.expr);
20779
- if (v.v === null) continue;
20780
- const b = castTo(env.ctx, v, "bool", {});
20781
- if (b.v !== true) {
20782
- throw pgError(
20783
- "check_violation",
20784
- `new row for relation "${table.name}" violates check constraint "${con.name}"`,
20785
- "23514"
20786
- );
21095
+ if (oldRow) {
21096
+ rangeVars.add("old");
21097
+ for (let i = 0; i < table.columns.length; i++) {
21098
+ cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
21099
+ row.push(oldRow[i] ?? null);
20787
21100
  }
20788
21101
  }
21102
+ return new RowScope(cols, row, null, rangeVars);
20789
21103
  }
20790
- function uniqueSpecsFor(env, table) {
20791
- const specs = [];
20792
- for (const con of table.constraints) {
20793
- if (con.kind !== "primary_key" && con.kind !== "unique") continue;
20794
- specs.push({
20795
- name: con.name,
20796
- keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
20797
- columnNames: con.columns,
20798
- nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
20799
- where: null,
20800
- isPrimary: con.kind === "primary_key"
20801
- });
20802
- }
20803
- const schema = env.ctx.state.schemas.get(table.schema);
20804
- if (schema) {
20805
- for (const idx of schema.indexes.values()) {
20806
- if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
20807
- specs.push(uniqueSpecOfIndex(table, idx));
20808
- }
20809
- }
20810
- return specs;
21104
+
21105
+ // src/executor/triggers.ts
21106
+ function matches(t, event) {
21107
+ return t.events.some((e) => e.event === event);
20811
21108
  }
20812
- function uniqueSpecOfIndex(table, idx) {
20813
- return {
20814
- name: idx.name,
20815
- keys: idx.columns.map((c) => ({
20816
- colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
20817
- expr: c.expr
20818
- })),
20819
- columnNames: idx.columns.map((c) => c.column ?? "expr"),
20820
- nullsNotDistinct: idx.nullsNotDistinct,
20821
- where: idx.where,
20822
- isPrimary: false
20823
- };
21109
+ var executor = null;
21110
+ function setTriggerExecutor(e) {
21111
+ executor = e;
20824
21112
  }
20825
- function uniqueKeyOf(env, table, spec, row) {
20826
- if (spec.where) {
20827
- const scope = makeEvalScope(env, tableScope(table, row));
20828
- const v = evalExpr(env.ctx, scope, spec.where);
20829
- if (v.v !== true) return null;
20830
- }
20831
- const parts = [];
20832
- let hasNull = false;
20833
- for (const k of spec.keys) {
20834
- let value;
20835
- let type;
20836
- if (k.expr) {
20837
- const scope = makeEvalScope(env, tableScope(table, row));
20838
- const v = evalExpr(env.ctx, scope, k.expr);
20839
- value = v.v;
20840
- type = v.t === "unknown" ? "text" : v.t;
20841
- } else {
20842
- value = row[k.colIdx] ?? null;
20843
- type = table.columns[k.colIdx].type.id;
21113
+ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
21114
+ let row = newRow ?? oldRow;
21115
+ for (const t of table.triggers) {
21116
+ if (t.timing !== timing || !matches(t, event) || !t.forEachRow) continue;
21117
+ if (!executor) throw unsupported(`trigger "${t.name}" execution`);
21118
+ if (t.constraint && timing === "after") {
21119
+ if (t.when && !evalPredicate(env, triggerScope(table, newRow, oldRow), t.when)) continue;
21120
+ env.ctx.state.pendingTriggers.push({
21121
+ schema: table.schema,
21122
+ table: table.name,
21123
+ trigger: t.name,
21124
+ event,
21125
+ oldRow: oldRow?.slice() ?? null,
21126
+ newRow: newRow?.slice() ?? null
21127
+ });
21128
+ continue;
20844
21129
  }
20845
- if (value === null) {
20846
- hasNull = true;
20847
- parts.push("\0N");
20848
- } else {
20849
- parts.push(datumKey(type, value));
21130
+ const result = executor(env, table, t, event, oldRow, timing === "before" ? row : newRow);
21131
+ if (timing === "before") {
21132
+ if (result === null) return { row: null };
21133
+ row = result;
20850
21134
  }
20851
21135
  }
20852
- if (hasNull && !spec.nullsNotDistinct) return null;
20853
- return parts.join("");
21136
+ return { row };
20854
21137
  }
20855
- function checkUnique(env, table, row, selfIdx) {
20856
- for (const spec of uniqueSpecsFor(env, table)) {
20857
- const key = uniqueKeyOf(env, table, spec, row);
20858
- if (key === null) continue;
20859
- indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
21138
+ var keyOf = (schema, name) => JSON.stringify([schema, name]);
21139
+ function flushConstraintTriggers(state, all = false) {
21140
+ const env = { ctx: new EngineCtx(state), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
21141
+ for (let i = 0; i < state.pendingTriggers.length; ) {
21142
+ const pending = state.pendingTriggers[i];
21143
+ const table = state.schemas.get(pending.schema)?.tables.get(pending.table);
21144
+ const trigger = table?.triggers.find((t) => t.name === pending.trigger);
21145
+ if (!table || !trigger) {
21146
+ state.pendingTriggers.splice(i, 1);
21147
+ continue;
21148
+ }
21149
+ const deferred = trigger.deferrable && (state.constraintModes.get(keyOf(table.schema, trigger.name)) ?? trigger.initiallyDeferred);
21150
+ if (!all && state.inTransaction && deferred) {
21151
+ i++;
21152
+ continue;
21153
+ }
21154
+ if (!executor) throw unsupported(`trigger "${trigger.name}" execution`);
21155
+ state.pendingTriggers.splice(i, 1);
21156
+ const changes = state.changes;
21157
+ try {
21158
+ executor(env, table, { ...trigger, when: null }, pending.event, pending.oldRow, pending.newRow);
21159
+ } catch (error) {
21160
+ state.pendingTriggers.splice(i, 0, pending);
21161
+ throw error;
21162
+ } finally {
21163
+ state.changes = changes;
21164
+ }
20860
21165
  }
20861
21166
  }
20862
- function findConflict(env, table, spec, row) {
20863
- const key = uniqueKeyOf(env, table, spec, row);
20864
- if (key === null) return null;
20865
- const hits = indexStoreFor(env, table, spec).lookup(key);
20866
- return hits.length > 0 ? hits[0] : null;
20867
- }
20868
- function checkForeignKeys(env, table, row) {
20869
- const state = env.ctx.state;
20870
- for (const con of table.constraints) {
20871
- if (con.kind !== "foreign_key") continue;
20872
- const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
20873
- const nulls = values.filter((v) => v === null).length;
20874
- if (con.match === "simple" && nulls > 0) continue;
20875
- if (con.match === "full") {
20876
- if (nulls === values.length) continue;
20877
- if (nulls > 0) {
20878
- throw pgError(
20879
- "constraint_foreign_key",
20880
- `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
20881
- "23503"
21167
+ function setConstraints(state, stmt) {
21168
+ if (!state.inTransaction) return;
21169
+ const matches2 = [];
21170
+ if (stmt.names) {
21171
+ for (const name of stmt.names) {
21172
+ const schemas = name.length > 1 ? [name[name.length - 2]] : state.effectiveSearchPath();
21173
+ let found = false;
21174
+ for (const schema of schemas) {
21175
+ const items = [...state.schemas.get(schema)?.tables.values() ?? []].flatMap(
21176
+ (table) => table.triggers.filter((t) => t.constraint && t.name === name[name.length - 1])
20882
21177
  );
21178
+ if (items.length) {
21179
+ for (const trigger of items) matches2.push({ schema, trigger });
21180
+ found = true;
21181
+ break;
21182
+ }
20883
21183
  }
21184
+ if (!found) throw pgError("undefined_object", `constraint "${name.join(".")}" does not exist`, "42704");
20884
21185
  }
20885
- const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
20886
- if (!refTable) {
20887
- throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
20888
- }
20889
- const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
20890
- const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
20891
- const wanted = values.map((v, i) => {
20892
- const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
20893
- const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
20894
- return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
20895
- }).join("");
20896
- let found = false;
20897
- for (let i = 0; i < refTable.rowCount(); i++) {
20898
- const r = refTable.rowAt(i);
20899
- const key = refIdxs.map((ri, j) => {
20900
- const v = r[ri] ?? null;
20901
- return v === null ? "\0N" : datumKey(keyTypes[j], v);
20902
- }).join("");
20903
- if (key === wanted) {
20904
- found = true;
20905
- break;
20906
- }
21186
+ } else {
21187
+ for (const schema of state.schemas.values())
21188
+ for (const table of schema.tables.values())
21189
+ for (const trigger of table.triggers)
21190
+ if (trigger.constraint && trigger.deferrable) matches2.push({ schema: schema.name, trigger });
21191
+ }
21192
+ for (const { trigger } of matches2)
21193
+ if (stmt.deferred && !trigger.deferrable)
21194
+ throw pgError("misuse", `constraint "${trigger.name}" is not deferrable`, "55000");
21195
+ const previous = new Map(state.constraintModes);
21196
+ for (const { schema, trigger } of matches2) state.constraintModes.set(keyOf(schema, trigger.name), stmt.deferred);
21197
+ try {
21198
+ if (!stmt.deferred) flushConstraintTriggers(state);
21199
+ } catch (error) {
21200
+ state.constraintModes = previous;
21201
+ throw error;
21202
+ }
21203
+ }
21204
+
21205
+ // src/transactions/manager.ts
21206
+ var TransactionManager = class {
21207
+ constructor(state) {
21208
+ this.state = state;
21209
+ }
21210
+ state;
21211
+ base = null;
21212
+ savepoints = [];
21213
+ freezeDepth = 0;
21214
+ get inTransaction() {
21215
+ return this.base !== null;
21216
+ }
21217
+ takeSnapshot() {
21218
+ this.state.freezeShared();
21219
+ this.freezeDepth++;
21220
+ return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
21221
+ }
21222
+ restore(snap) {
21223
+ this.state.restoreFrom(snap.state);
21224
+ this.state.prng.setState(snap.prngState);
21225
+ }
21226
+ thawOnce() {
21227
+ if (this.freezeDepth > 0) {
21228
+ this.state.thawShared();
21229
+ this.freezeDepth--;
20907
21230
  }
20908
- if (!found) {
20909
- throw pgError(
20910
- "constraint_foreign_key",
20911
- `insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
20912
- "23503"
20913
- );
21231
+ }
21232
+ begin() {
21233
+ if (this.base !== null) {
21234
+ return;
20914
21235
  }
21236
+ this.base = this.takeSnapshot();
21237
+ this.state.inTransaction = true;
21238
+ assert(this.freezeDepth === 1, "BEGIN freeze depth");
20915
21239
  }
20916
- }
20917
- function referencingConstraints(env, table) {
20918
- const out = [];
20919
- for (const schema of env.ctx.state.schemas.values()) {
20920
- for (const t of schema.tables.values()) {
20921
- for (const con of t.constraints) {
20922
- if (con.kind === "foreign_key" && con.refSchema === table.schema && con.refTable === table.name) {
20923
- out.push({ table: t, constraint: con });
20924
- }
20925
- }
21240
+ commit() {
21241
+ try {
21242
+ flushConstraintTriggers(this.state, true);
21243
+ } catch (error) {
21244
+ this.rollback();
21245
+ throw error;
20926
21246
  }
21247
+ this.base = null;
21248
+ this.savepoints = [];
21249
+ this.state.inTransaction = false;
21250
+ this.state.transactionXid = null;
21251
+ this.state.localSettings.clear();
21252
+ this.state.pendingTriggers = [];
21253
+ this.state.constraintModes.clear();
21254
+ while (this.freezeDepth > 0) this.thawOnce();
20927
21255
  }
20928
- return out;
20929
- }
20930
-
20931
- // src/executor/triggers.ts
20932
- function matches(t, event) {
20933
- return t.events.some((e) => e.event === event);
20934
- }
20935
- var executor = null;
20936
- function setTriggerExecutor(e) {
20937
- executor = e;
20938
- }
20939
- function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
20940
- let row = newRow ?? oldRow;
20941
- for (const t of table.triggers) {
20942
- if (t.timing !== timing || !matches(t, event) || !t.forEachRow) continue;
20943
- if (!executor) throw unsupported(`trigger "${t.name}" execution`);
20944
- const result = executor(env, table, t, event, oldRow, timing === "before" ? row : newRow);
20945
- if (timing === "before") {
20946
- if (result === null) return { row: null };
20947
- row = result;
21256
+ rollback() {
21257
+ if (this.base !== null) {
21258
+ this.restore(this.base);
21259
+ }
21260
+ this.base = null;
21261
+ this.savepoints = [];
21262
+ this.state.inTransaction = false;
21263
+ this.state.transactionXid = null;
21264
+ this.state.localSettings.clear();
21265
+ this.state.pendingTriggers = [];
21266
+ this.state.constraintModes.clear();
21267
+ while (this.freezeDepth > 0) this.thawOnce();
21268
+ }
21269
+ savepoint(name) {
21270
+ if (this.base === null) {
21271
+ throw pgError("transaction_state", "SAVEPOINT can only be used in transaction blocks", "25P01");
20948
21272
  }
21273
+ this.savepoints.push({ name, snap: this.takeSnapshot() });
20949
21274
  }
20950
- return { row };
20951
- }
21275
+ releaseSavepoint(name) {
21276
+ const idx = this.findSavepoint(name);
21277
+ this.savepoints.splice(idx);
21278
+ }
21279
+ rollbackToSavepoint(name) {
21280
+ const idx = this.findSavepoint(name);
21281
+ const sp = this.savepoints[idx];
21282
+ this.restore(sp.snap);
21283
+ this.savepoints.splice(idx + 1);
21284
+ }
21285
+ findSavepoint(name) {
21286
+ if (this.base === null) {
21287
+ throw pgError("transaction_state", `SAVEPOINT can only be used in transaction blocks`, "25P01");
21288
+ }
21289
+ for (let i = this.savepoints.length - 1; i >= 0; i--) {
21290
+ if (this.savepoints[i].name === name) return i;
21291
+ }
21292
+ throw pgError("invalid_savepoint_specification", `savepoint "${name}" does not exist`, "3B001");
21293
+ }
21294
+ reset() {
21295
+ this.base = null;
21296
+ this.savepoints = [];
21297
+ this.state.inTransaction = false;
21298
+ this.state.transactionXid = null;
21299
+ this.freezeDepth = 0;
21300
+ }
21301
+ };
20952
21302
 
20953
21303
  // src/executor/dml.ts
20954
21304
  function withStatementRollback(env, fn) {
@@ -21149,6 +21499,7 @@ function applyOnConflictUpdate(env, table, label, existingIdx, newRow, sets, whe
21149
21499
  const updated = existing.slice();
21150
21500
  applyUpdateSets(env, table, sets, scope, updated);
21151
21501
  computeGeneratedColumns(env, table, updated);
21502
+ table.rowXmins.set(updated, env.ctx.rowVersionXid());
21152
21503
  rows[existingIdx] = updated;
21153
21504
  indexUpdateRow(env, table, existingIdx, existing, updated);
21154
21505
  checkNotNull(env, table, updated);
@@ -21234,6 +21585,7 @@ function executeInsert(env0, stmt) {
21234
21585
  checkChecks(env, table, newRow);
21235
21586
  checkUnique(env, table, newRow, rows.length);
21236
21587
  checkForeignKeys(env, table, newRow);
21588
+ table.rowXmins.set(newRow, env.ctx.rowVersionXid());
21237
21589
  rows.push(newRow);
21238
21590
  indexInsertRow(env, table, rows.length - 1, newRow);
21239
21591
  insertedCount++;
@@ -21351,6 +21703,7 @@ function executeUpdate(env0, stmt) {
21351
21703
  if (fired.row === null) continue;
21352
21704
  const finalRow = fired.row;
21353
21705
  computeGeneratedColumns(env, table, finalRow);
21706
+ table.rowXmins.set(finalRow, env.ctx.rowVersionXid());
21354
21707
  rows[ri] = finalRow;
21355
21708
  try {
21356
21709
  checkNotNull(env, table, finalRow);
@@ -21470,6 +21823,7 @@ function handleReferencedDelete(env, table, row, depth) {
21470
21823
  for (const c of con.columns) {
21471
21824
  newRow[child.columnIndex(c)] = null;
21472
21825
  }
21826
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21473
21827
  childRows[i] = newRow;
21474
21828
  checkNotNull(env, child, newRow);
21475
21829
  checkChecks(env, child, newRow);
@@ -21483,6 +21837,7 @@ function handleReferencedDelete(env, table, row, depth) {
21483
21837
  const ci = child.columnIndex(c);
21484
21838
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
21485
21839
  }
21840
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21486
21841
  childRows[i] = newRow;
21487
21842
  checkNotNull(env, child, newRow);
21488
21843
  checkChecks(env, child, newRow);
@@ -21520,6 +21875,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21520
21875
  const refIdx = table.columnIndex(con.refColumns[c]);
21521
21876
  newRow[localIdx] = newRows[r][refIdx] ?? null;
21522
21877
  }
21878
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21523
21879
  childRows[i] = newRow;
21524
21880
  checkChecks(env, child, newRow);
21525
21881
  }
@@ -21529,6 +21885,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21529
21885
  for (const i of idxs) {
21530
21886
  const newRow = childRows[i].slice();
21531
21887
  for (const c of con.columns) newRow[child.columnIndex(c)] = null;
21888
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21532
21889
  childRows[i] = newRow;
21533
21890
  checkNotNull(env, child, newRow);
21534
21891
  }
@@ -21541,6 +21898,7 @@ function handleReferencedUpdate(env, table, oldRows, newRows) {
21541
21898
  const ci = child.columnIndex(c);
21542
21899
  newRow[ci] = columnDefault(env, child, child.columns[ci]);
21543
21900
  }
21901
+ child.rowXmins.set(newRow, env.ctx.rowVersionXid());
21544
21902
  childRows[i] = newRow;
21545
21903
  checkForeignKeys(env, child, newRow);
21546
21904
  }
@@ -21638,6 +21996,7 @@ function executeSet(env, stmt) {
21638
21996
  else target.delete(name);
21639
21997
  return commandResult("SET", 0);
21640
21998
  }
21999
+ validateStorageSetting(name, stmt.value);
21641
22000
  target.set(name, stmt.value);
21642
22001
  return commandResult("SET", 0);
21643
22002
  }
@@ -21943,64 +22302,6 @@ function executeCopyFromData(env, stmt, data) {
21943
22302
  };
21944
22303
  }
21945
22304
 
21946
- // src/expressions/context.ts
21947
- var EngineCtx = class {
21948
- state;
21949
- /** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
21950
- txNow;
21951
- /** statement timestamp */
21952
- stmtNow;
21953
- constructor(state, txNow) {
21954
- this.state = state;
21955
- const nowMs = state.clock().getTime();
21956
- const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
21957
- this.txNow = txNow ?? nowMicros;
21958
- this.stmtNow = nowMicros;
21959
- }
21960
- timezone() {
21961
- return this.state.getSetting("timezone") ?? "UTC";
21962
- }
21963
- namespaceOid(name) {
21964
- const oid = builtinNamespaceOid(name) ?? this.state.schemas.get(name)?.oid;
21965
- if (oid === void 0) throw pgError("undefined_object", `schema "${name}" does not exist`, "3F000");
21966
- return oid;
21967
- }
21968
- namespaceName(oid) {
21969
- const builtin = builtinNamespaceName(oid);
21970
- if (builtin !== void 0) return builtin;
21971
- for (const schema of this.state.schemas.values()) {
21972
- if (schema.oid === oid) return schema.name;
21973
- }
21974
- return null;
21975
- }
21976
- zoneOffsetAt(utcMicros) {
21977
- return zoneOffsetAtUtc(this.timezone(), utcMicros);
21978
- }
21979
- zoneOffsetForNaive(naiveMicros) {
21980
- return zoneOffsetForNaive(this.timezone(), naiveMicros);
21981
- }
21982
- enumLabels(enumType) {
21983
- if (!isEnumType(enumType)) return null;
21984
- const e = this.state.findEnumByKey(enumType.slice(5));
21985
- return e?.labels ?? null;
21986
- }
21987
- enumHasLabel(enumType, label) {
21988
- const labels = this.enumLabels(enumType);
21989
- return labels === null ? true : labels.includes(label);
21990
- }
21991
- enumOrder(enumType, label) {
21992
- const labels = this.enumLabels(enumType);
21993
- if (!labels) return 0;
21994
- const idx = labels.indexOf(label);
21995
- return idx === -1 ? labels.length : idx;
21996
- }
21997
- requireEnum(enumType) {
21998
- const labels = this.enumLabels(enumType);
21999
- if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
22000
- return labels;
22001
- }
22002
- };
22003
-
22004
22305
  // src/runtime/clock.ts
22005
22306
  var DEFAULT_NOW = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
22006
22307
  function fixedClock(instant = DEFAULT_NOW) {
@@ -22968,7 +23269,7 @@ function pgClass(ctx) {
22968
23269
  v.materialized ? "m" : "v",
22969
23270
  v.columns?.length ?? 0,
22970
23271
  v.matRows?.length ?? 0,
22971
- false,
23272
+ v.materialized && [...schemaData.indexes.values()].some((i) => i.tableOid === v.oid),
22972
23273
  !v.materialized || v.matRows !== null,
22973
23274
  relPersistence(v)
22974
23275
  );
@@ -23234,7 +23535,7 @@ function pgIndex(ctx) {
23234
23535
  const valid = i.valid !== false;
23235
23536
  rows.push([
23236
23537
  i.oid ?? 0,
23237
- table?.oid ?? 0,
23538
+ table?.oid ?? i.tableOid ?? 0,
23238
23539
  indexAttributeCount(i),
23239
23540
  i.columns.length,
23240
23541
  i.unique,
@@ -23406,7 +23707,7 @@ function pgStatUserIndexes(ctx) {
23406
23707
  for (const index of schema.indexes.values()) {
23407
23708
  const table = schema.tables.get(index.table);
23408
23709
  rows.push([
23409
- table?.oid ?? 0,
23710
+ table?.oid ?? index.tableOid ?? 0,
23410
23711
  index.oid ?? 0,
23411
23712
  schema.name,
23412
23713
  index.table,
@@ -24001,26 +24302,6 @@ function runTriggerBody(env, table, stmts, vars) {
24001
24302
  }
24002
24303
  }
24003
24304
  }
24004
- function triggerScope(table, newRow, oldRow) {
24005
- const cols = [];
24006
- const row = [];
24007
- const rangeVars = /* @__PURE__ */ new Set();
24008
- if (newRow) {
24009
- rangeVars.add("new");
24010
- for (let i = 0; i < table.columns.length; i++) {
24011
- cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
24012
- row.push(newRow[i] ?? null);
24013
- }
24014
- }
24015
- if (oldRow) {
24016
- rangeVars.add("old");
24017
- for (let i = 0; i < table.columns.length; i++) {
24018
- cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
24019
- row.push(oldRow[i] ?? null);
24020
- }
24021
- }
24022
- return new RowScope(cols, row, null, rangeVars);
24023
- }
24024
24305
  function executeTrigger(env, table, trigger, _event, oldRow, newRow) {
24025
24306
  const state = env.ctx.state;
24026
24307
  if (trigger.when !== null && !evalPredicate(env, triggerScope(table, newRow, oldRow), trigger.when)) {
@@ -24662,13 +24943,63 @@ function executeCreateSequence(env, stmt) {
24662
24943
  schema.sequences.set(name, seq);
24663
24944
  return commandResult("CREATE SEQUENCE", 0);
24664
24945
  }
24946
+ function renameSequenceReferences(env, seq, newName) {
24947
+ const state = env.ctx.state;
24948
+ const matches2 = (value) => {
24949
+ try {
24950
+ const input = parseRelationInput(value);
24951
+ if ("oid" in input) return input.oid === seq.oid;
24952
+ return state.findSequence(input.parts)?.oid === seq.oid;
24953
+ } catch {
24954
+ return false;
24955
+ }
24956
+ };
24957
+ const rewrite = (value) => {
24958
+ if (Array.isArray(value)) return value.map(rewrite);
24959
+ if (value === null || typeof value !== "object") return value;
24960
+ const node = value;
24961
+ const updated = Object.fromEntries(Object.entries(node).map(([key, child]) => [key, rewrite(child)]));
24962
+ const rewriteLiteral = (literal2) => {
24963
+ if (literal2 && typeof literal2 === "object" && "type" in literal2 && literal2.type === "string_lit" && "value" in literal2 && typeof literal2.value === "string" && matches2(literal2.value)) {
24964
+ return { ...literal2, value: [seq.schema, newName].map(quoteIdent).join(".") };
24965
+ }
24966
+ return literal2;
24967
+ };
24968
+ if (node.type === "func" && Array.isArray(node.name) && ["nextval", "currval", "setval"].includes(String(node.name.at(-1))) && Array.isArray(updated.args))
24969
+ updated.args[0] = rewriteLiteral(updated.args[0]);
24970
+ 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")
24971
+ updated.expr = rewriteLiteral(updated.expr);
24972
+ return updated;
24973
+ };
24974
+ for (const schema of state.schemas.values()) {
24975
+ for (const table of [...schema.tables.values()]) {
24976
+ const writable = state.ensureWritableTable(table);
24977
+ for (const column of writable.columns) {
24978
+ if (column.defaultExpr) column.defaultExpr = rewrite(column.defaultExpr);
24979
+ if (column.identity?.sequence === `${seq.schema}.${seq.name}`)
24980
+ column.identity = { ...column.identity, sequence: `${seq.schema}.${newName}` };
24981
+ }
24982
+ }
24983
+ }
24984
+ }
24665
24985
  function executeAlterSequence(env, stmt) {
24666
24986
  const state = env.ctx.state;
24667
- const seq = state.findSequence(stmt.name);
24668
- if (!seq) {
24987
+ const foundSequence = state.findSequence(stmt.name);
24988
+ if (!foundSequence) {
24669
24989
  if (stmt.ifExists) return commandResult("ALTER SEQUENCE", 0);
24670
24990
  throw pgError("undefined_table", `relation "${stmt.name.join(".")}" does not exist`, "42P01");
24671
24991
  }
24992
+ const seq = state.ensureWritableSequence(foundSequence);
24993
+ if (stmt.renameTo) {
24994
+ const schema = state.getSchema(seq.schema);
24995
+ if (schema.hasRelation(stmt.renameTo))
24996
+ throw pgError("duplicate_table", `relation "${stmt.renameTo}" already exists`, "42P07");
24997
+ renameSequenceReferences(env, seq, stmt.renameTo);
24998
+ schema.sequences.delete(seq.name);
24999
+ seq.name = stmt.renameTo;
25000
+ schema.sequences.set(seq.name, seq);
25001
+ return commandResult("ALTER SEQUENCE", 0);
25002
+ }
24672
25003
  const o = stmt.options;
24673
25004
  if (o.logged !== void 0) {
24674
25005
  setSequenceLogged(state, seq, o.logged);
@@ -24726,7 +25057,7 @@ function buildColumn(env, schema, tableName2, def, out, taken) {
24726
25057
  col.defaultExpr = {
24727
25058
  type: "func",
24728
25059
  name: ["nextval"],
24729
- args: [{ type: "string_lit", value: `${schema.name}.${seqName}` }]
25060
+ args: [{ type: "string_lit", value: [schema.name, seqName].map(quoteIdent).join(".") }]
24730
25061
  };
24731
25062
  }
24732
25063
  for (const c of def.constraints) {
@@ -24979,7 +25310,11 @@ function executeCreateTableAs(env, stmt) {
24979
25310
  const table = new TableData(schema.name, name, columns, state.nextOid(), stmt.temp);
24980
25311
  table.unlogged = stmt.unlogged === true;
24981
25312
  if (stmt.withData) {
24982
- for (const row of rel3.rows) table.mutableRows().push(row.slice());
25313
+ for (const row of rel3.rows) {
25314
+ const stored = row.slice();
25315
+ table.rowXmins.set(stored, env.ctx.rowVersionXid());
25316
+ table.mutableRows().push(stored);
25317
+ }
24983
25318
  }
24984
25319
  schema.tables.set(name, table);
24985
25320
  const count = stmt.withData ? table.rowCount() : 0;
@@ -24987,7 +25322,8 @@ function executeCreateTableAs(env, stmt) {
24987
25322
  }
24988
25323
  function executeCreateIndex(env, stmt) {
24989
25324
  const state = env.ctx.state;
24990
- const table = state.findTable(stmt.table);
25325
+ const view = state.findView(stmt.table);
25326
+ const table = state.findTable(stmt.table) ?? (view?.materialized ? materializedTable(view) : void 0);
24991
25327
  if (!table) {
24992
25328
  throw pgError("undefined_table", `relation "${stmt.table.join(".")}" does not exist`, "42P01");
24993
25329
  }
@@ -25099,13 +25435,22 @@ function executeRefreshMatView(env, stmt) {
25099
25435
  if (!found?.materialized) {
25100
25436
  throw pgError("undefined_table", `materialized view "${stmt.name.join(".")}" does not exist`, "42P01");
25101
25437
  }
25438
+ const rel3 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), found.query);
25439
+ const next = {
25440
+ ...found,
25441
+ matColumns: rel3.columns.map((c, i) => ({
25442
+ name: found.columns?.[i] ?? c.name,
25443
+ type: c.type === UNKNOWN ? "text" : c.type
25444
+ })),
25445
+ matRows: stmt.withData ? rel3.rows : null
25446
+ };
25447
+ const table = materializedTable(next);
25448
+ for (const index of env.ctx.state.getSchema(found.schema).indexes.values()) {
25449
+ if (index.tableOid === found.oid && index.valid !== false) assertUniqueIndexBuildable(env, table, index);
25450
+ }
25102
25451
  const view = env.ctx.state.ensureWritableView(found);
25103
- const rel3 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), view.query);
25104
- view.matColumns = rel3.columns.map((c, i) => ({
25105
- name: view.columns?.[i] ?? c.name,
25106
- type: c.type === UNKNOWN ? "text" : c.type
25107
- }));
25108
- view.matRows = stmt.withData ? rel3.rows : null;
25452
+ view.matColumns = next.matColumns;
25453
+ view.matRows = next.matRows;
25109
25454
  return commandResult("REFRESH MATERIALIZED VIEW", 0);
25110
25455
  }
25111
25456
  function executeCreateSchema(env, stmt) {
@@ -25238,6 +25583,12 @@ function executeCreateFunction(env, stmt) {
25238
25583
  language: lang,
25239
25584
  body,
25240
25585
  rawBody: stmt.body,
25586
+ settings: Object.fromEntries(
25587
+ Object.entries(stmt.settings ?? {}).map(([key, value]) => [
25588
+ key,
25589
+ value === "__from_current__" ? state.getSetting(key) ?? "" : value
25590
+ ])
25591
+ ),
25241
25592
  strict: stmt.strict,
25242
25593
  oid: state.nextOid()
25243
25594
  };
@@ -25247,6 +25598,8 @@ function executeCreateFunction(env, stmt) {
25247
25598
  return commandResult("CREATE FUNCTION", 0);
25248
25599
  }
25249
25600
  function executeCreateTrigger(env, stmt) {
25601
+ if (stmt.constraint && (stmt.timing !== "after" || !stmt.forEachRow))
25602
+ throw pgError("syntax", "constraint triggers must be AFTER ROW triggers", "42601");
25250
25603
  const state = env.ctx.state;
25251
25604
  const found = state.findTable(stmt.table);
25252
25605
  if (!found) {
@@ -25265,6 +25618,9 @@ function executeCreateTrigger(env, stmt) {
25265
25618
  }
25266
25619
  const meta = {
25267
25620
  name: stmt.name,
25621
+ constraint: stmt.constraint,
25622
+ deferrable: stmt.deferrable,
25623
+ initiallyDeferred: stmt.initiallyDeferred,
25268
25624
  timing: stmt.timing,
25269
25625
  events: stmt.events,
25270
25626
  forEachRow: stmt.forEachRow,
@@ -25417,6 +25773,7 @@ function executeAlterTable(env, stmt) {
25417
25773
  }
25418
25774
  const next = row.slice();
25419
25775
  next[idx] = nv;
25776
+ table.rowXmins.set(next, table.rowXmins.get(rows[i]) ?? 2);
25420
25777
  rows[i] = next;
25421
25778
  }
25422
25779
  col.type = resolved.column;
@@ -25518,6 +25875,11 @@ function executeAlterTable(env, stmt) {
25518
25875
  );
25519
25876
  }
25520
25877
  table.columns[idx].name = action.to;
25878
+ for (const seq of [...schema.sequences.values()]) {
25879
+ if (seq.ownedBy?.table === table.name && seq.ownedBy.column === action.from) {
25880
+ state.ensureWritableSequence(seq).ownedBy = { table: table.name, column: action.to };
25881
+ }
25882
+ }
25521
25883
  for (const con of table.constraints) {
25522
25884
  if (con.kind === "primary_key" || con.kind === "unique" || con.kind === "foreign_key") {
25523
25885
  con.columns = con.columns.map((c) => c === action.from ? action.to : c);
@@ -25554,6 +25916,11 @@ function executeAlterTable(env, stmt) {
25554
25916
  throw pgError("duplicate_table", `relation "${action.to}" already exists`, "42P07");
25555
25917
  }
25556
25918
  const oldName = table.name;
25919
+ for (const seq of [...schema.sequences.values()]) {
25920
+ if (seq.ownedBy?.table === oldName) {
25921
+ state.ensureWritableSequence(seq).ownedBy = { ...seq.ownedBy, table: action.to };
25922
+ }
25923
+ }
25557
25924
  schema.tables.delete(table.name);
25558
25925
  table.name = action.to;
25559
25926
  schema.tables.set(action.to, table);
@@ -26033,7 +26400,16 @@ function alterTableIsSelfContained(stmt) {
26033
26400
  return stmt.actions.length === 1 && action !== void 0 && SELF_CONTAINED_ALTER_ACTIONS.has(action.kind);
26034
26401
  }
26035
26402
  function executeStatement(env, stmt) {
26036
- if (!RESHAPES_TABLES.has(stmt.type)) return dispatchStatement(env, stmt);
26403
+ if (!RESHAPES_TABLES.has(stmt.type)) {
26404
+ 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))) {
26405
+ return withStatementRollback(env, () => {
26406
+ const result = dispatchStatement(env, stmt);
26407
+ flushConstraintTriggers(env.ctx.state);
26408
+ return result;
26409
+ });
26410
+ }
26411
+ return dispatchStatement(env, stmt);
26412
+ }
26037
26413
  try {
26038
26414
  return dispatchStatement(env, stmt);
26039
26415
  } finally {
@@ -26092,6 +26468,9 @@ function dispatchStatement(env, stmt) {
26092
26468
  return executeRefreshMatView(env, stmt);
26093
26469
  case "transaction":
26094
26470
  return executeTransaction(env, stmt);
26471
+ case "set_constraints":
26472
+ setConstraints(env.ctx.state, stmt);
26473
+ return commandResult("SET CONSTRAINTS", 0);
26095
26474
  case "set":
26096
26475
  return executeSet(env, stmt);
26097
26476
  case "show":
@@ -27131,6 +27510,7 @@ function encodeDatabaseState(state, runtime) {
27131
27510
  writeBjv(
27132
27511
  w,
27133
27512
  {
27513
+ xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
27134
27514
  name: table.name,
27135
27515
  schema: table.schema,
27136
27516
  columns: table.columns,
@@ -27228,8 +27608,14 @@ function decodeInner(snapshot, prng, clock) {
27228
27608
  table.constraints = meta.constraints;
27229
27609
  table.triggers = meta.triggers;
27230
27610
  table.unlogged = meta.unlogged === true;
27611
+ table.slabXmins = meta.xmins ?? null;
27612
+ state.xidCounter = Math.max(
27613
+ state.xidCounter,
27614
+ (meta.xmins ?? []).reduce((max, xid) => Math.max(max, xid + 1), 3)
27615
+ );
27231
27616
  if (meta.stats) state.tableStats.set(table.oid, meta.stats);
27232
27617
  const rowCount = readVarintU32(r);
27618
+ if (meta.xmins && meta.xmins.length !== rowCount) throw snapshotError();
27233
27619
  const slabColumns = [];
27234
27620
  for (let c = 0; c < meta.columns.length; c++)
27235
27621
  slabColumns.push(readPackedColumn(r, rowCount, intern, meta.columns[c].type.id));
@@ -27673,6 +28059,8 @@ function validateTableMetaBjv(value) {
27673
28059
  if (!isRecord(value) || typeof value.name !== "string" || typeof value.schema !== "string") throw snapshotError();
27674
28060
  if (!Array.isArray(value.columns)) throw snapshotError();
27675
28061
  for (const col of value.columns) validateColumnMeta(col);
28062
+ if (value.xmins !== void 0 && (!Array.isArray(value.xmins) || value.xmins.some((xid) => !Number.isInteger(xid) || xid < 2 || xid > 4294967295)))
28063
+ throw snapshotError();
27676
28064
  }
27677
28065
  function validateViewMetaBjv(value) {
27678
28066
  if (!isRecord(value) || typeof value.name !== "string" || typeof value.schema !== "string") throw snapshotError();
@@ -27766,6 +28154,7 @@ function forceSchemaIntern(pool, state, schemas) {
27766
28154
  pool.forceId(table.name);
27767
28155
  pool.forceId(table.schema);
27768
28156
  forceBjvStrings(pool, {
28157
+ xmins: table.allRows().map((row) => table.rowXmins.get(row) ?? 2),
27769
28158
  name: table.name,
27770
28159
  schema: table.schema,
27771
28160
  columns: table.columns,
@@ -27843,10 +28232,188 @@ function forceBjvStrings(pool, value) {
27843
28232
  }
27844
28233
  }
27845
28234
  registerCodec({ encodeDatabaseState, decodeDatabaseState });
28235
+
28236
+ // src/api/schema-report.ts
28237
+ var bounded = (value, fallback2, max) => {
28238
+ if (value === void 0) return fallback2;
28239
+ if (!Number.isSafeInteger(value) || value < 1 || value > max)
28240
+ throw new RangeError(`limit must be an integer between 1 and ${max}`);
28241
+ return value;
28242
+ };
28243
+ function analyzeSchema(sql, options = {}) {
28244
+ const inputLimit = bounded(options.maxInputBytes, 1024 * 1024, 4 * 1024 * 1024);
28245
+ const statementLimit = bounded(options.maxStatements, 1e3, 1e4);
28246
+ const diagnosticLimit = bounded(options.maxDiagnostics, 100, 1e3);
28247
+ const report = {
28248
+ engine: "mockingbird-postgres",
28249
+ version: true ? "3.7.0" : "source-tree",
28250
+ statements: 0,
28251
+ accepted: 0,
28252
+ compatible: null,
28253
+ truncated: false,
28254
+ diagnostics: []
28255
+ };
28256
+ const add = (diagnostic) => {
28257
+ if (report.diagnostics.length >= diagnosticLimit) {
28258
+ report.truncated = true;
28259
+ return false;
28260
+ }
28261
+ report.diagnostics.push({
28262
+ ...diagnostic,
28263
+ ...diagnostic.object ? { object: diagnostic.object.slice(0, 200) } : {}
28264
+ });
28265
+ if (diagnostic.category !== "unknown") report.compatible = false;
28266
+ return true;
28267
+ };
28268
+ const location = (offset) => {
28269
+ const prefix = sql.slice(0, offset);
28270
+ return { offset, line: prefix.split("\n").length, column: offset - prefix.lastIndexOf("\n") };
28271
+ };
28272
+ if (sql.length > inputLimit || new TextEncoder().encode(sql).length > inputLimit) {
28273
+ add({
28274
+ statement: 0,
28275
+ ...location(0),
28276
+ sqlstate: null,
28277
+ category: "limit",
28278
+ message: `Input exceeds ${inputLimit} bytes`
28279
+ });
28280
+ report.truncated = true;
28281
+ return report;
28282
+ }
28283
+ let tokens;
28284
+ try {
28285
+ tokens = tokenize(sql);
28286
+ } catch (error) {
28287
+ add({
28288
+ statement: 1,
28289
+ ...location(0),
28290
+ sqlstate: isPostgresError(error) ? error.code : null,
28291
+ category: "syntax",
28292
+ message: error instanceof Error ? error.message.slice(0, 500) : "Cannot tokenize input"
28293
+ });
28294
+ return report;
28295
+ }
28296
+ const db = new Database();
28297
+ const failed = /* @__PURE__ */ new Map();
28298
+ let start = 0;
28299
+ let tokenStart = 0;
28300
+ let atomicDepth = 0;
28301
+ const run = (end, tokenEnd) => {
28302
+ const statementTokens = tokens.slice(tokenStart, tokenEnd);
28303
+ tokenStart = tokenEnd + 1;
28304
+ const offset = statementTokens[0]?.pos;
28305
+ const statementSql = sql.slice(start, end);
28306
+ start = end + 1;
28307
+ if (offset === void 0) return;
28308
+ if (report.statements >= statementLimit) {
28309
+ report.truncated = true;
28310
+ add({
28311
+ statement: report.statements + 1,
28312
+ ...location(offset),
28313
+ sqlstate: null,
28314
+ category: "limit",
28315
+ message: `Statement limit ${statementLimit} reached`
28316
+ });
28317
+ return;
28318
+ }
28319
+ report.statements++;
28320
+ let object;
28321
+ const candidate = statementTokens.findIndex(
28322
+ (token) => ["table", "view", "function", "sequence", "schema", "type", "index"].includes(token.value)
28323
+ );
28324
+ if (candidate >= 0) {
28325
+ const name = statementTokens[candidate + 1];
28326
+ if (name?.type === "ident" || name?.type === "quoted_ident") object = name.value;
28327
+ }
28328
+ try {
28329
+ const ast = parse(statementSql);
28330
+ const statement = ast[0];
28331
+ if (statement && "name" in statement && Array.isArray(statement.name)) object = statement.name.join(".");
28332
+ if (statement && !/^(create_|alter_|comment|grant|revoke|set|reset)/.test(statement.type)) {
28333
+ add({
28334
+ statement: report.statements,
28335
+ ...location(offset),
28336
+ object,
28337
+ sqlstate: null,
28338
+ category: "unknown",
28339
+ message: "Only schema statements are analyzed; data, queries and dynamic commands are unknown"
28340
+ });
28341
+ return;
28342
+ }
28343
+ const references = statementTokens.flatMap((token, index) => {
28344
+ if (!["from", "join", "references"].includes(token.value)) return [];
28345
+ const parts = [];
28346
+ for (let at = index + 1; at < statementTokens.length; at += 2) {
28347
+ const part = statementTokens[at];
28348
+ if (!part || part.type !== "ident" && part.type !== "quoted_ident") break;
28349
+ parts.push(part.value);
28350
+ if (statementTokens[at + 1]?.value !== ".") break;
28351
+ }
28352
+ return parts.length ? [parts.join(".")] : [];
28353
+ });
28354
+ const missing = [...failed].find(
28355
+ ([name]) => references.some(
28356
+ (reference) => reference === name || !reference.includes(".") && reference === name.split(".").at(-1) || !name.includes(".") && name === reference.split(".").at(-1)
28357
+ )
28358
+ );
28359
+ if (missing) {
28360
+ add({
28361
+ statement: report.statements,
28362
+ ...location(offset),
28363
+ object,
28364
+ sqlstate: "42P01",
28365
+ category: "prerequisite",
28366
+ message: `Prerequisite ${missing[0]} was not created`,
28367
+ prerequisiteStatement: missing[1]
28368
+ });
28369
+ if (object) failed.set(object, report.statements);
28370
+ return;
28371
+ }
28372
+ db.exec(statementSql);
28373
+ report.accepted++;
28374
+ add({
28375
+ statement: report.statements,
28376
+ ...location(offset),
28377
+ object,
28378
+ sqlstate: null,
28379
+ category: "unknown",
28380
+ message: "Accepted by the ephemeral engine; semantics, function bodies and dynamic SQL require oracle verification"
28381
+ });
28382
+ } catch (error) {
28383
+ const code = isPostgresError(error) ? error.code : null;
28384
+ const message = error instanceof Error ? error.message.slice(0, 500) : "Schema analysis failed";
28385
+ const prerequisite = code?.startsWith("42") ? [...failed].find(([name]) => message.includes(`"${name}"`) || message.includes(`"${name.split(".").at(-1)}"`)) : void 0;
28386
+ add({
28387
+ statement: report.statements,
28388
+ ...location(offset),
28389
+ object,
28390
+ sqlstate: code,
28391
+ category: prerequisite ? "prerequisite" : code === "0A000" ? "unsupported" : code?.startsWith("426") ? "syntax" : "execution",
28392
+ message,
28393
+ ...prerequisite ? { prerequisiteStatement: prerequisite[1] } : {}
28394
+ });
28395
+ if (object) failed.set(object, report.statements);
28396
+ }
28397
+ };
28398
+ try {
28399
+ for (let index = 0; index < tokens.length; index++) {
28400
+ const token = tokens[index];
28401
+ if (token.value === "begin" && tokens[index + 1]?.value === "atomic") atomicDepth++;
28402
+ if (token.value === "end" && atomicDepth > 0) atomicDepth--;
28403
+ if (token.type === "punct" && token.value === ";" && atomicDepth === 0 || token.type === "eof")
28404
+ run(token.pos, index);
28405
+ if (report.truncated) break;
28406
+ }
28407
+ } finally {
28408
+ db.close();
28409
+ }
28410
+ return report;
28411
+ }
27846
28412
  export {
27847
28413
  Database,
27848
28414
  PostgresError,
27849
28415
  Snapshot,
27850
- Statement
28416
+ Statement,
28417
+ analyzeSchema
27851
28418
  };
27852
28419
  //# sourceMappingURL=index.js.map