@crvouga/mockingbird-service-postgres 3.5.0 → 3.6.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/CHANGELOG.md +6 -0
- package/COMPATIBILITY.md +3 -0
- package/compat/sections/trg.ts +2 -0
- package/dist/admin.js +924 -735
- package/dist/admin.js.map +4 -4
- package/dist/ast/nodes.d.ts +9 -1
- package/dist/executor/triggers-scope.d.ts +4 -0
- package/dist/executor/triggers.d.ts +4 -0
- package/dist/index.js +924 -735
- package/dist/index.js.map +4 -4
- package/dist/server.js +941 -735
- package/dist/server.js.map +4 -4
- package/dist/storage/database-state.d.ts +13 -0
- package/dist/storage/guc.d.ts +2 -0
- package/dist/storage/indexable-relation.d.ts +3 -0
- package/dist/unstable.js +16938 -16749
- package/dist/unstable.js.map +4 -4
- package/dist/wire/cli.js +942 -736
- package/dist/wire/cli.js.map +4 -4
- package/dist/wire/index.js +942 -736
- package/dist/wire/index.js.map +4 -4
- package/package.json +1 -1
package/dist/wire/cli.js
CHANGED
|
@@ -3702,7 +3702,7 @@ async function preflightFleet(config, options2) {
|
|
|
3702
3702
|
break;
|
|
3703
3703
|
}
|
|
3704
3704
|
}
|
|
3705
|
-
targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.
|
|
3705
|
+
targets.set(name2, { ...target, packageVersion: packageVersion ?? "3.6.0" });
|
|
3706
3706
|
} catch (error) {
|
|
3707
3707
|
throw new Error(`service ${name2}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
3708
3708
|
}
|
|
@@ -5539,6 +5539,13 @@ function isPostgresError(err) {
|
|
|
5539
5539
|
return typeof sqlState === "string" && /^[0-9A-Z]{5}$/.test(sqlState);
|
|
5540
5540
|
}
|
|
5541
5541
|
|
|
5542
|
+
// src/storage/guc.ts
|
|
5543
|
+
function validateStorageSetting(name2, value) {
|
|
5544
|
+
if (name2 === "default_table_access_method" && value !== "heap" || name2 === "default_tablespace" && value !== "" && value !== "pg_default") {
|
|
5545
|
+
throw pgError("invalid_parameter_value", `invalid value for parameter "${name2}": "${value}"`, "22023");
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
|
|
5542
5549
|
// src/runtime/prng.ts
|
|
5543
5550
|
var Prng = class _Prng {
|
|
5544
5551
|
state;
|
|
@@ -8994,6 +9001,9 @@ var DatabaseState = class _DatabaseState {
|
|
|
8994
9001
|
changes = 0;
|
|
8995
9002
|
oidCounter = 16384;
|
|
8996
9003
|
inTransaction = false;
|
|
9004
|
+
/** Transaction-only events: included in rollback clones, never in exported snapshots. */
|
|
9005
|
+
pendingTriggers = [];
|
|
9006
|
+
constraintModes = /* @__PURE__ */ new Map();
|
|
8997
9007
|
/** most recent sequence touched by nextval/setval, for lastval() */
|
|
8998
9008
|
lastSequence = null;
|
|
8999
9009
|
/** Session currval per sequence; absent entry means currval is undefined. */
|
|
@@ -9036,6 +9046,8 @@ var DatabaseState = class _DatabaseState {
|
|
|
9036
9046
|
this.settings.set("row_security", "on");
|
|
9037
9047
|
this.settings.set("array_nulls", "on");
|
|
9038
9048
|
this.settings.set("backslash_quote", "safe_encoding");
|
|
9049
|
+
this.settings.set("default_tablespace", "");
|
|
9050
|
+
this.settings.set("default_table_access_method", "heap");
|
|
9039
9051
|
}
|
|
9040
9052
|
nextOid() {
|
|
9041
9053
|
return this.oidCounter++;
|
|
@@ -9195,6 +9207,8 @@ var DatabaseState = class _DatabaseState {
|
|
|
9195
9207
|
s.prepared = new Map(this.prepared);
|
|
9196
9208
|
s.changes = this.changes;
|
|
9197
9209
|
s.inTransaction = this.inTransaction;
|
|
9210
|
+
s.pendingTriggers = this.pendingTriggers.slice();
|
|
9211
|
+
s.constraintModes = new Map(this.constraintModes);
|
|
9198
9212
|
s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
|
|
9199
9213
|
s.sequenceCurrval = new Map(this.sequenceCurrval);
|
|
9200
9214
|
s.tableStats = new Map(this.tableStats);
|
|
@@ -9212,6 +9226,8 @@ var DatabaseState = class _DatabaseState {
|
|
|
9212
9226
|
s.prepared = new Map(this.prepared);
|
|
9213
9227
|
s.changes = this.changes;
|
|
9214
9228
|
s.inTransaction = this.inTransaction;
|
|
9229
|
+
s.pendingTriggers = this.pendingTriggers.slice();
|
|
9230
|
+
s.constraintModes = new Map(this.constraintModes);
|
|
9215
9231
|
s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
|
|
9216
9232
|
s.sequenceCurrval = new Map(this.sequenceCurrval);
|
|
9217
9233
|
s.tableStats = new Map(this.tableStats);
|
|
@@ -9284,6 +9300,8 @@ var DatabaseState = class _DatabaseState {
|
|
|
9284
9300
|
this.settings = other.settings;
|
|
9285
9301
|
this.localSettings = other.localSettings;
|
|
9286
9302
|
this.prepared = other.prepared;
|
|
9303
|
+
this.pendingTriggers = other.pendingTriggers.slice();
|
|
9304
|
+
this.constraintModes = new Map(other.constraintModes);
|
|
9287
9305
|
this.changes = other.changes;
|
|
9288
9306
|
this.lastSequence = other.lastSequence;
|
|
9289
9307
|
this.sequenceCurrval = other.sequenceCurrval;
|
|
@@ -9300,90 +9318,192 @@ var DatabaseState = class _DatabaseState {
|
|
|
9300
9318
|
}
|
|
9301
9319
|
};
|
|
9302
9320
|
|
|
9303
|
-
// src/
|
|
9304
|
-
var
|
|
9305
|
-
|
|
9306
|
-
|
|
9321
|
+
// src/types/timezone.ts
|
|
9322
|
+
var intlCache = /* @__PURE__ */ new Map();
|
|
9323
|
+
function intlFor(zone) {
|
|
9324
|
+
const cached = intlCache.get(zone);
|
|
9325
|
+
if (cached) return cached;
|
|
9326
|
+
try {
|
|
9327
|
+
const fmt = new Intl.DateTimeFormat("en-US", {
|
|
9328
|
+
timeZone: zone,
|
|
9329
|
+
timeZoneName: "longOffset",
|
|
9330
|
+
year: "numeric"
|
|
9331
|
+
});
|
|
9332
|
+
intlCache.set(zone, fmt);
|
|
9333
|
+
return fmt;
|
|
9334
|
+
} catch {
|
|
9335
|
+
return null;
|
|
9336
|
+
}
|
|
9337
|
+
}
|
|
9338
|
+
function parseFixedOffset(zone) {
|
|
9339
|
+
const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
|
|
9340
|
+
if (!m) return null;
|
|
9341
|
+
const sign = m[1] === "-" ? -1 : 1;
|
|
9342
|
+
return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
|
|
9343
|
+
}
|
|
9344
|
+
function parsePosixOffset(zone) {
|
|
9345
|
+
const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
|
|
9346
|
+
if (!m) return null;
|
|
9347
|
+
const sign = m[1] === "-" ? 1 : -1;
|
|
9348
|
+
return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
|
|
9349
|
+
}
|
|
9350
|
+
function pgMicrosToUnixMs(utcMicros) {
|
|
9351
|
+
return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
|
|
9352
|
+
}
|
|
9353
|
+
function zoneOffsetAtUtc(zone, utcMicros) {
|
|
9354
|
+
const z = zone.trim();
|
|
9355
|
+
const lower = z.toLowerCase();
|
|
9356
|
+
if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
|
|
9357
|
+
const posix = parsePosixOffset(z);
|
|
9358
|
+
if (posix !== null) return posix;
|
|
9359
|
+
const fixed = parseFixedOffset(z);
|
|
9360
|
+
if (fixed !== null) return fixed;
|
|
9361
|
+
const fmt = intlFor(z);
|
|
9362
|
+
if (fmt) {
|
|
9363
|
+
const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
|
|
9364
|
+
const parts = fmt.formatToParts(new Date(ms));
|
|
9365
|
+
const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
|
|
9366
|
+
const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
|
|
9367
|
+
if (!m) return 0;
|
|
9368
|
+
const sign = m[1] === "-" ? -1 : 1;
|
|
9369
|
+
return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
|
|
9307
9370
|
}
|
|
9371
|
+
throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
|
|
9372
|
+
}
|
|
9373
|
+
function clampDateMs(ms) {
|
|
9374
|
+
const MAX = 864e13;
|
|
9375
|
+
return Math.max(-MAX, Math.min(MAX, ms));
|
|
9376
|
+
}
|
|
9377
|
+
function zoneOffsetForNaive(zone, naiveMicros) {
|
|
9378
|
+
const first = zoneOffsetAtUtc(zone, naiveMicros);
|
|
9379
|
+
const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
|
|
9380
|
+
return second;
|
|
9381
|
+
}
|
|
9382
|
+
function validateZone(zone) {
|
|
9383
|
+
zoneOffsetAtUtc(zone, 0n);
|
|
9384
|
+
}
|
|
9385
|
+
|
|
9386
|
+
// src/expressions/context.ts
|
|
9387
|
+
var EngineCtx = class {
|
|
9308
9388
|
state;
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9389
|
+
/** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
|
|
9390
|
+
txNow;
|
|
9391
|
+
/** statement timestamp */
|
|
9392
|
+
stmtNow;
|
|
9393
|
+
constructor(state, txNow) {
|
|
9394
|
+
this.state = state;
|
|
9395
|
+
const nowMs = state.clock().getTime();
|
|
9396
|
+
const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
|
|
9397
|
+
this.txNow = txNow ?? nowMicros;
|
|
9398
|
+
this.stmtNow = nowMicros;
|
|
9314
9399
|
}
|
|
9315
|
-
|
|
9316
|
-
this.state.
|
|
9317
|
-
this.freezeDepth++;
|
|
9318
|
-
return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
|
|
9400
|
+
timezone() {
|
|
9401
|
+
return this.state.getSetting("timezone") ?? "UTC";
|
|
9319
9402
|
}
|
|
9320
|
-
|
|
9321
|
-
this.state.
|
|
9322
|
-
|
|
9403
|
+
namespaceOid(name2) {
|
|
9404
|
+
const oid = builtinNamespaceOid(name2) ?? this.state.schemas.get(name2)?.oid;
|
|
9405
|
+
if (oid === void 0) throw pgError("undefined_object", `schema "${name2}" does not exist`, "3F000");
|
|
9406
|
+
return oid;
|
|
9323
9407
|
}
|
|
9324
|
-
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9408
|
+
namespaceName(oid) {
|
|
9409
|
+
const builtin = builtinNamespaceName(oid);
|
|
9410
|
+
if (builtin !== void 0) return builtin;
|
|
9411
|
+
for (const schema of this.state.schemas.values()) {
|
|
9412
|
+
if (schema.oid === oid) return schema.name;
|
|
9328
9413
|
}
|
|
9414
|
+
return null;
|
|
9329
9415
|
}
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
return;
|
|
9333
|
-
}
|
|
9334
|
-
this.base = this.takeSnapshot();
|
|
9335
|
-
this.state.inTransaction = true;
|
|
9336
|
-
assert(this.freezeDepth === 1, "BEGIN freeze depth");
|
|
9416
|
+
zoneOffsetAt(utcMicros) {
|
|
9417
|
+
return zoneOffsetAtUtc(this.timezone(), utcMicros);
|
|
9337
9418
|
}
|
|
9338
|
-
|
|
9339
|
-
this.
|
|
9340
|
-
this.savepoints = [];
|
|
9341
|
-
this.state.inTransaction = false;
|
|
9342
|
-
this.state.localSettings.clear();
|
|
9343
|
-
while (this.freezeDepth > 0) this.thawOnce();
|
|
9419
|
+
zoneOffsetForNaive(naiveMicros) {
|
|
9420
|
+
return zoneOffsetForNaive(this.timezone(), naiveMicros);
|
|
9344
9421
|
}
|
|
9345
|
-
|
|
9346
|
-
if (
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
this.base = null;
|
|
9350
|
-
this.savepoints = [];
|
|
9351
|
-
this.state.inTransaction = false;
|
|
9352
|
-
this.state.localSettings.clear();
|
|
9353
|
-
while (this.freezeDepth > 0) this.thawOnce();
|
|
9422
|
+
enumLabels(enumType) {
|
|
9423
|
+
if (!isEnumType(enumType)) return null;
|
|
9424
|
+
const e = this.state.findEnumByKey(enumType.slice(5));
|
|
9425
|
+
return e?.labels ?? null;
|
|
9354
9426
|
}
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
}
|
|
9359
|
-
this.savepoints.push({ name: name2, snap: this.takeSnapshot() });
|
|
9427
|
+
enumHasLabel(enumType, label) {
|
|
9428
|
+
const labels = this.enumLabels(enumType);
|
|
9429
|
+
return labels === null ? true : labels.includes(label);
|
|
9360
9430
|
}
|
|
9361
|
-
|
|
9362
|
-
const
|
|
9363
|
-
|
|
9431
|
+
enumOrder(enumType, label) {
|
|
9432
|
+
const labels = this.enumLabels(enumType);
|
|
9433
|
+
if (!labels) return 0;
|
|
9434
|
+
const idx = labels.indexOf(label);
|
|
9435
|
+
return idx === -1 ? labels.length : idx;
|
|
9364
9436
|
}
|
|
9365
|
-
|
|
9366
|
-
const
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
this.savepoints.splice(idx + 1);
|
|
9437
|
+
requireEnum(enumType) {
|
|
9438
|
+
const labels = this.enumLabels(enumType);
|
|
9439
|
+
if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
|
|
9440
|
+
return labels;
|
|
9370
9441
|
}
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9442
|
+
};
|
|
9443
|
+
|
|
9444
|
+
// src/api/bind.ts
|
|
9445
|
+
var INT4_MIN2 = -2147483648;
|
|
9446
|
+
var INT4_MAX2 = 2147483647;
|
|
9447
|
+
function bindValueToTyped(value, index) {
|
|
9448
|
+
if (value === null || value === void 0) return tv(UNKNOWN, null);
|
|
9449
|
+
switch (typeof value) {
|
|
9450
|
+
case "boolean":
|
|
9451
|
+
return tv("bool", value);
|
|
9452
|
+
case "number":
|
|
9453
|
+
if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
|
|
9454
|
+
return tv("int4", value);
|
|
9455
|
+
}
|
|
9456
|
+
if (Number.isInteger(value) && Number.isSafeInteger(value)) {
|
|
9457
|
+
return tv("int8", BigInt(value));
|
|
9458
|
+
}
|
|
9459
|
+
return tv("float8", value);
|
|
9460
|
+
case "bigint":
|
|
9461
|
+
if (value < -9223372036854775808n || value > 9223372036854775807n) {
|
|
9462
|
+
throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
|
|
9463
|
+
}
|
|
9464
|
+
return tv("int8", value);
|
|
9465
|
+
case "string":
|
|
9466
|
+
return tv(UNKNOWN, value);
|
|
9467
|
+
case "object": {
|
|
9468
|
+
if (value instanceof Uint8Array) return tv("bytea", value);
|
|
9469
|
+
if (value instanceof Date) {
|
|
9470
|
+
const ms = value.getTime();
|
|
9471
|
+
if (Number.isNaN(ms)) {
|
|
9472
|
+
throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
|
|
9473
|
+
}
|
|
9474
|
+
return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
|
|
9475
|
+
}
|
|
9476
|
+
break;
|
|
9377
9477
|
}
|
|
9378
|
-
|
|
9478
|
+
default:
|
|
9479
|
+
break;
|
|
9379
9480
|
}
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9481
|
+
throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
|
|
9482
|
+
}
|
|
9483
|
+
function datumToJs(t, v, ctx, int8 = "bigint") {
|
|
9484
|
+
if (v === null) return null;
|
|
9485
|
+
switch (t) {
|
|
9486
|
+
case "bool":
|
|
9487
|
+
return v;
|
|
9488
|
+
case "int2":
|
|
9489
|
+
case "int4":
|
|
9490
|
+
case "oid":
|
|
9491
|
+
return typeof v === "bigint" ? Number(v) : v;
|
|
9492
|
+
case "int8": {
|
|
9493
|
+
const n = typeof v === "bigint" ? v : BigInt(v);
|
|
9494
|
+
if (int8 === "string") return n.toString();
|
|
9495
|
+
if (int8 === "number") return Number(n);
|
|
9496
|
+
return n;
|
|
9497
|
+
}
|
|
9498
|
+
case "float4":
|
|
9499
|
+
case "float8":
|
|
9500
|
+
return v;
|
|
9501
|
+
case "bytea":
|
|
9502
|
+
return v;
|
|
9503
|
+
default:
|
|
9504
|
+
return datumText(t === UNKNOWN ? "text" : t, v, ctx);
|
|
9385
9505
|
}
|
|
9386
|
-
}
|
|
9506
|
+
}
|
|
9387
9507
|
|
|
9388
9508
|
// src/types/cast.ts
|
|
9389
9509
|
var UTC_CAST_ENV = {
|
|
@@ -9861,259 +9981,6 @@ function unifyTypes(a, b) {
|
|
|
9861
9981
|
return null;
|
|
9862
9982
|
}
|
|
9863
9983
|
|
|
9864
|
-
// src/types/resolve.ts
|
|
9865
|
-
var SERIALS = {
|
|
9866
|
-
smallserial: "int2",
|
|
9867
|
-
serial2: "int2",
|
|
9868
|
-
serial: "int4",
|
|
9869
|
-
serial4: "int4",
|
|
9870
|
-
bigserial: "int8",
|
|
9871
|
-
serial8: "int8"
|
|
9872
|
-
};
|
|
9873
|
-
function modOf(t, mods) {
|
|
9874
|
-
if (mods.length === 0) return null;
|
|
9875
|
-
if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
|
|
9876
|
-
return { a: mods[0] };
|
|
9877
|
-
}
|
|
9878
|
-
function resolveTypeName(state, tn) {
|
|
9879
|
-
const joined = tn.parts.join(".");
|
|
9880
|
-
const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
|
|
9881
|
-
if (bare !== null) {
|
|
9882
|
-
const serial = SERIALS[bare];
|
|
9883
|
-
if (serial !== void 0 && tn.arrayDims === 0) {
|
|
9884
|
-
return { column: { id: serial, mod: null }, domain: null, serial };
|
|
9885
|
-
}
|
|
9886
|
-
const builtin = normalizeTypeName(bare);
|
|
9887
|
-
if (builtin !== null) {
|
|
9888
|
-
const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
|
|
9889
|
-
return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
|
|
9890
|
-
}
|
|
9891
|
-
}
|
|
9892
|
-
const enumData = state.findEnum(tn.parts);
|
|
9893
|
-
if (enumData) {
|
|
9894
|
-
const elem = `enum:${enumData.schema}.${enumData.name}`;
|
|
9895
|
-
const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
|
|
9896
|
-
return { column: { id, mod: null }, domain: null, serial: null };
|
|
9897
|
-
}
|
|
9898
|
-
const domainData = state.findDomain(tn.parts);
|
|
9899
|
-
if (domainData) {
|
|
9900
|
-
if (tn.arrayDims > 0) {
|
|
9901
|
-
const id = arrayTypeOf(domainData.baseType.id);
|
|
9902
|
-
return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
|
|
9903
|
-
}
|
|
9904
|
-
return {
|
|
9905
|
-
column: domainData.baseType,
|
|
9906
|
-
domain: `${domainData.schema}.${domainData.name}`,
|
|
9907
|
-
serial: null
|
|
9908
|
-
};
|
|
9909
|
-
}
|
|
9910
|
-
throw pgError("undefined_object", `type "${joined}" does not exist`);
|
|
9911
|
-
}
|
|
9912
|
-
|
|
9913
|
-
// src/executor/relation.ts
|
|
9914
|
-
var RowScope = class {
|
|
9915
|
-
constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
|
|
9916
|
-
this.columns = columns;
|
|
9917
|
-
this.row = row;
|
|
9918
|
-
this.parent = parent;
|
|
9919
|
-
this.rangeVars = rangeVars;
|
|
9920
|
-
}
|
|
9921
|
-
columns;
|
|
9922
|
-
row;
|
|
9923
|
-
parent;
|
|
9924
|
-
rangeVars;
|
|
9925
|
-
/** Resolve a (possibly qualified) column reference. undefined = not found. */
|
|
9926
|
-
lookup(parts) {
|
|
9927
|
-
if (parts.length === 1) {
|
|
9928
|
-
const name3 = parts[0];
|
|
9929
|
-
let found2;
|
|
9930
|
-
let count2 = 0;
|
|
9931
|
-
for (let i = 0; i < this.columns.length; i++) {
|
|
9932
|
-
const c = this.columns[i];
|
|
9933
|
-
if (c.name === name3 && !c.hidden) {
|
|
9934
|
-
count2++;
|
|
9935
|
-
if (count2 > 1) {
|
|
9936
|
-
throw pgError("ambiguous_column", `column reference "${name3}" is ambiguous`);
|
|
9937
|
-
}
|
|
9938
|
-
found2 = tv(c.type, this.row[i] ?? null);
|
|
9939
|
-
}
|
|
9940
|
-
}
|
|
9941
|
-
if (found2 !== void 0) return found2;
|
|
9942
|
-
if (this.rangeVars.has(name3)) {
|
|
9943
|
-
return this.wholeRow(name3);
|
|
9944
|
-
}
|
|
9945
|
-
return this.parent?.lookup(parts);
|
|
9946
|
-
}
|
|
9947
|
-
const table = parts[parts.length - 2];
|
|
9948
|
-
const name2 = parts[parts.length - 1];
|
|
9949
|
-
let found;
|
|
9950
|
-
let count = 0;
|
|
9951
|
-
for (let i = 0; i < this.columns.length; i++) {
|
|
9952
|
-
const c = this.columns[i];
|
|
9953
|
-
if (c.table === table && c.name === name2) {
|
|
9954
|
-
count++;
|
|
9955
|
-
if (count > 1) {
|
|
9956
|
-
throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
|
|
9957
|
-
}
|
|
9958
|
-
found = tv(c.type, this.row[i] ?? null);
|
|
9959
|
-
}
|
|
9960
|
-
}
|
|
9961
|
-
if (found !== void 0) return found;
|
|
9962
|
-
return this.parent?.lookup(parts);
|
|
9963
|
-
}
|
|
9964
|
-
/** Build a record value from all columns belonging to a range variable. */
|
|
9965
|
-
wholeRow(rangeVar) {
|
|
9966
|
-
const types = [];
|
|
9967
|
-
const values = [];
|
|
9968
|
-
const names = [];
|
|
9969
|
-
for (let i = 0; i < this.columns.length; i++) {
|
|
9970
|
-
const c = this.columns[i];
|
|
9971
|
-
if (c.table === rangeVar) {
|
|
9972
|
-
types.push(c.type);
|
|
9973
|
-
values.push(this.row[i] ?? null);
|
|
9974
|
-
names.push(c.name);
|
|
9975
|
-
}
|
|
9976
|
-
}
|
|
9977
|
-
if (types.length === 0) return void 0;
|
|
9978
|
-
return tv("record", { kind: "pgrecord", types, values, names });
|
|
9979
|
-
}
|
|
9980
|
-
hasRangeVar(name2) {
|
|
9981
|
-
if (this.rangeVars.has(name2)) return true;
|
|
9982
|
-
return this.parent?.hasRangeVar(name2) ?? false;
|
|
9983
|
-
}
|
|
9984
|
-
};
|
|
9985
|
-
function childEnv(env, outer) {
|
|
9986
|
-
return {
|
|
9987
|
-
ctx: env.ctx,
|
|
9988
|
-
params: env.params,
|
|
9989
|
-
ctes: env.ctes,
|
|
9990
|
-
outer,
|
|
9991
|
-
allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
|
|
9992
|
-
};
|
|
9993
|
-
}
|
|
9994
|
-
function relationResult(rel3, command2) {
|
|
9995
|
-
const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
|
|
9996
|
-
return {
|
|
9997
|
-
columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
|
|
9998
|
-
rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
|
|
9999
|
-
command: command2,
|
|
10000
|
-
rowCount: rel3.rows.length
|
|
10001
|
-
};
|
|
10002
|
-
}
|
|
10003
|
-
function commandResult(command2, rowCount) {
|
|
10004
|
-
return { columns: [], rows: [], command: command2, rowCount };
|
|
10005
|
-
}
|
|
10006
|
-
function inferColumnName(e) {
|
|
10007
|
-
switch (e.type) {
|
|
10008
|
-
case "colref":
|
|
10009
|
-
return e.parts[e.parts.length - 1];
|
|
10010
|
-
case "func":
|
|
10011
|
-
return e.name[e.name.length - 1];
|
|
10012
|
-
case "cast": {
|
|
10013
|
-
const inner = inferColumnName(e.expr);
|
|
10014
|
-
if (inner !== "?column?") return inner;
|
|
10015
|
-
return e.target.parts[e.target.parts.length - 1];
|
|
10016
|
-
}
|
|
10017
|
-
case "collate":
|
|
10018
|
-
return inferColumnName(e.expr);
|
|
10019
|
-
case "case":
|
|
10020
|
-
return "case";
|
|
10021
|
-
case "array_ctor":
|
|
10022
|
-
case "array_query":
|
|
10023
|
-
return "array";
|
|
10024
|
-
case "row":
|
|
10025
|
-
return "row";
|
|
10026
|
-
case "subquery_expr":
|
|
10027
|
-
return e.kind === "exists" ? "exists" : "?column?";
|
|
10028
|
-
case "bool_lit":
|
|
10029
|
-
return "bool";
|
|
10030
|
-
case "extract":
|
|
10031
|
-
return "extract";
|
|
10032
|
-
case "position":
|
|
10033
|
-
return "position";
|
|
10034
|
-
case "substring_sql":
|
|
10035
|
-
return "substring";
|
|
10036
|
-
case "overlay":
|
|
10037
|
-
return "overlay";
|
|
10038
|
-
case "trim":
|
|
10039
|
-
return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
|
|
10040
|
-
case "field_select":
|
|
10041
|
-
return e.field === "*" ? "?column?" : e.field;
|
|
10042
|
-
case "at_time_zone":
|
|
10043
|
-
return "timezone";
|
|
10044
|
-
case "grouping_func":
|
|
10045
|
-
return "grouping";
|
|
10046
|
-
case "subscript":
|
|
10047
|
-
return inferColumnName(e.base);
|
|
10048
|
-
default:
|
|
10049
|
-
return "?column?";
|
|
10050
|
-
}
|
|
10051
|
-
}
|
|
10052
|
-
|
|
10053
|
-
// src/api/bind.ts
|
|
10054
|
-
var INT4_MIN2 = -2147483648;
|
|
10055
|
-
var INT4_MAX2 = 2147483647;
|
|
10056
|
-
function bindValueToTyped(value, index) {
|
|
10057
|
-
if (value === null || value === void 0) return tv(UNKNOWN, null);
|
|
10058
|
-
switch (typeof value) {
|
|
10059
|
-
case "boolean":
|
|
10060
|
-
return tv("bool", value);
|
|
10061
|
-
case "number":
|
|
10062
|
-
if (Number.isInteger(value) && value >= INT4_MIN2 && value <= INT4_MAX2) {
|
|
10063
|
-
return tv("int4", value);
|
|
10064
|
-
}
|
|
10065
|
-
if (Number.isInteger(value) && Number.isSafeInteger(value)) {
|
|
10066
|
-
return tv("int8", BigInt(value));
|
|
10067
|
-
}
|
|
10068
|
-
return tv("float8", value);
|
|
10069
|
-
case "bigint":
|
|
10070
|
-
if (value < -9223372036854775808n || value > 9223372036854775807n) {
|
|
10071
|
-
throw pgError("numeric_value_out_of_range", `bigint parameter $${index + 1} out of int8 range`, "22003");
|
|
10072
|
-
}
|
|
10073
|
-
return tv("int8", value);
|
|
10074
|
-
case "string":
|
|
10075
|
-
return tv(UNKNOWN, value);
|
|
10076
|
-
case "object": {
|
|
10077
|
-
if (value instanceof Uint8Array) return tv("bytea", value);
|
|
10078
|
-
if (value instanceof Date) {
|
|
10079
|
-
const ms = value.getTime();
|
|
10080
|
-
if (Number.isNaN(ms)) {
|
|
10081
|
-
throw pgError("invalid_datetime", `invalid Date parameter $${index + 1}`, "22008");
|
|
10082
|
-
}
|
|
10083
|
-
return tv("timestamptz", BigInt(Math.round(ms)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG);
|
|
10084
|
-
}
|
|
10085
|
-
break;
|
|
10086
|
-
}
|
|
10087
|
-
default:
|
|
10088
|
-
break;
|
|
10089
|
-
}
|
|
10090
|
-
throw pgError("misuse", `unsupported parameter type for $${index + 1}: ${typeof value}`, "XX000");
|
|
10091
|
-
}
|
|
10092
|
-
function datumToJs(t, v, ctx, int8 = "bigint") {
|
|
10093
|
-
if (v === null) return null;
|
|
10094
|
-
switch (t) {
|
|
10095
|
-
case "bool":
|
|
10096
|
-
return v;
|
|
10097
|
-
case "int2":
|
|
10098
|
-
case "int4":
|
|
10099
|
-
case "oid":
|
|
10100
|
-
return typeof v === "bigint" ? Number(v) : v;
|
|
10101
|
-
case "int8": {
|
|
10102
|
-
const n = typeof v === "bigint" ? v : BigInt(v);
|
|
10103
|
-
if (int8 === "string") return n.toString();
|
|
10104
|
-
if (int8 === "number") return Number(n);
|
|
10105
|
-
return n;
|
|
10106
|
-
}
|
|
10107
|
-
case "float4":
|
|
10108
|
-
case "float8":
|
|
10109
|
-
return v;
|
|
10110
|
-
case "bytea":
|
|
10111
|
-
return v;
|
|
10112
|
-
default:
|
|
10113
|
-
return datumText(t === UNKNOWN ? "text" : t, v, ctx);
|
|
10114
|
-
}
|
|
10115
|
-
}
|
|
10116
|
-
|
|
10117
9984
|
// src/functions/datetime-fns.ts
|
|
10118
9985
|
function extractDatePart(ctx, field0, src0, asNumeric) {
|
|
10119
9986
|
const field = field0.toLowerCase();
|
|
@@ -11028,71 +10895,6 @@ function getArrayFunctions() {
|
|
|
11028
10895
|
return m;
|
|
11029
10896
|
}
|
|
11030
10897
|
|
|
11031
|
-
// src/types/timezone.ts
|
|
11032
|
-
var intlCache = /* @__PURE__ */ new Map();
|
|
11033
|
-
function intlFor(zone) {
|
|
11034
|
-
const cached = intlCache.get(zone);
|
|
11035
|
-
if (cached) return cached;
|
|
11036
|
-
try {
|
|
11037
|
-
const fmt = new Intl.DateTimeFormat("en-US", {
|
|
11038
|
-
timeZone: zone,
|
|
11039
|
-
timeZoneName: "longOffset",
|
|
11040
|
-
year: "numeric"
|
|
11041
|
-
});
|
|
11042
|
-
intlCache.set(zone, fmt);
|
|
11043
|
-
return fmt;
|
|
11044
|
-
} catch {
|
|
11045
|
-
return null;
|
|
11046
|
-
}
|
|
11047
|
-
}
|
|
11048
|
-
function parseFixedOffset(zone) {
|
|
11049
|
-
const m = /^([+-]?)(\d{1,2})(?::(\d{2}))?(?::(\d{2}))?$/.exec(zone.trim());
|
|
11050
|
-
if (!m) return null;
|
|
11051
|
-
const sign = m[1] === "-" ? -1 : 1;
|
|
11052
|
-
return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60 + Number(m[4] ?? 0));
|
|
11053
|
-
}
|
|
11054
|
-
function parsePosixOffset(zone) {
|
|
11055
|
-
const m = /^(?:utc|gmt)([+-])(\d{1,2})(?::(\d{2}))?$/i.exec(zone.trim());
|
|
11056
|
-
if (!m) return null;
|
|
11057
|
-
const sign = m[1] === "-" ? 1 : -1;
|
|
11058
|
-
return sign * (Number(m[2]) * 3600 + Number(m[3] ?? 0) * 60);
|
|
11059
|
-
}
|
|
11060
|
-
function pgMicrosToUnixMs(utcMicros) {
|
|
11061
|
-
return Number((utcMicros - UNIX_EPOCH_MICROS_FROM_PG) / 1000n);
|
|
11062
|
-
}
|
|
11063
|
-
function zoneOffsetAtUtc(zone, utcMicros) {
|
|
11064
|
-
const z = zone.trim();
|
|
11065
|
-
const lower = z.toLowerCase();
|
|
11066
|
-
if (lower === "utc" || lower === "gmt" || lower === "z" || lower === "zulu" || lower === "universal") return 0;
|
|
11067
|
-
const posix = parsePosixOffset(z);
|
|
11068
|
-
if (posix !== null) return posix;
|
|
11069
|
-
const fixed = parseFixedOffset(z);
|
|
11070
|
-
if (fixed !== null) return fixed;
|
|
11071
|
-
const fmt = intlFor(z);
|
|
11072
|
-
if (fmt) {
|
|
11073
|
-
const ms = clampDateMs(pgMicrosToUnixMs(utcMicros));
|
|
11074
|
-
const parts = fmt.formatToParts(new Date(ms));
|
|
11075
|
-
const tzName = parts.find((p) => p.type === "timeZoneName")?.value ?? "GMT";
|
|
11076
|
-
const m = /GMT([+-])(\d{2}):(\d{2})(?::(\d{2}))?/.exec(tzName);
|
|
11077
|
-
if (!m) return 0;
|
|
11078
|
-
const sign = m[1] === "-" ? -1 : 1;
|
|
11079
|
-
return sign * (Number(m[2]) * 3600 + Number(m[3]) * 60 + Number(m[4] ?? 0));
|
|
11080
|
-
}
|
|
11081
|
-
throw pgError("invalid_parameter_value", `time zone "${zone}" not recognized`);
|
|
11082
|
-
}
|
|
11083
|
-
function clampDateMs(ms) {
|
|
11084
|
-
const MAX = 864e13;
|
|
11085
|
-
return Math.max(-MAX, Math.min(MAX, ms));
|
|
11086
|
-
}
|
|
11087
|
-
function zoneOffsetForNaive(zone, naiveMicros) {
|
|
11088
|
-
const first = zoneOffsetAtUtc(zone, naiveMicros);
|
|
11089
|
-
const second = zoneOffsetAtUtc(zone, naiveMicros - BigInt(first) * 1000000n);
|
|
11090
|
-
return second;
|
|
11091
|
-
}
|
|
11092
|
-
function validateZone(zone) {
|
|
11093
|
-
zoneOffsetAtUtc(zone, 0n);
|
|
11094
|
-
}
|
|
11095
|
-
|
|
11096
10898
|
// src/functions/datetime-registry.ts
|
|
11097
10899
|
function getDatetimeFunctions() {
|
|
11098
10900
|
const m = /* @__PURE__ */ new Map();
|
|
@@ -12692,6 +12494,28 @@ function exactDegTan(x) {
|
|
|
12692
12494
|
return Math.tan(x * Math.PI / 180);
|
|
12693
12495
|
}
|
|
12694
12496
|
|
|
12497
|
+
// src/storage/indexable-relation.ts
|
|
12498
|
+
function materializedTable(view) {
|
|
12499
|
+
const table = new TableData(
|
|
12500
|
+
view.schema,
|
|
12501
|
+
view.name,
|
|
12502
|
+
(view.matColumns ?? []).map((c) => ({
|
|
12503
|
+
name: c.name,
|
|
12504
|
+
type: { id: c.type, mod: null },
|
|
12505
|
+
notNull: false,
|
|
12506
|
+
defaultExpr: null,
|
|
12507
|
+
identity: null,
|
|
12508
|
+
generated: null,
|
|
12509
|
+
collate: null,
|
|
12510
|
+
domain: null
|
|
12511
|
+
})),
|
|
12512
|
+
view.oid,
|
|
12513
|
+
view.temp
|
|
12514
|
+
);
|
|
12515
|
+
table.rows = view.matRows ?? [];
|
|
12516
|
+
return table;
|
|
12517
|
+
}
|
|
12518
|
+
|
|
12695
12519
|
// src/schema/index-catalog.ts
|
|
12696
12520
|
var isKeyConstraint = (constraint) => constraint.kind === "primary_key" || constraint.kind === "unique";
|
|
12697
12521
|
var ACCESS_METHODS = /* @__PURE__ */ new Map([
|
|
@@ -12720,6 +12544,8 @@ function syncIndexCatalog(state) {
|
|
|
12720
12544
|
const tables = /* @__PURE__ */ new Map();
|
|
12721
12545
|
for (const schema of state.schemas.values()) {
|
|
12722
12546
|
for (const table of schema.tables.values()) tables.set(table.oid, { schema, table });
|
|
12547
|
+
for (const view of schema.views.values())
|
|
12548
|
+
if (view.materialized) tables.set(view.oid, { schema, table: materializedTable(view) });
|
|
12723
12549
|
}
|
|
12724
12550
|
const backing = /* @__PURE__ */ new Map();
|
|
12725
12551
|
for (const { table } of tables.values()) {
|
|
@@ -12917,6 +12743,55 @@ function deparseExpr(e) {
|
|
|
12917
12743
|
}
|
|
12918
12744
|
}
|
|
12919
12745
|
|
|
12746
|
+
// src/types/resolve.ts
|
|
12747
|
+
var SERIALS = {
|
|
12748
|
+
smallserial: "int2",
|
|
12749
|
+
serial2: "int2",
|
|
12750
|
+
serial: "int4",
|
|
12751
|
+
serial4: "int4",
|
|
12752
|
+
bigserial: "int8",
|
|
12753
|
+
serial8: "int8"
|
|
12754
|
+
};
|
|
12755
|
+
function modOf(t, mods) {
|
|
12756
|
+
if (mods.length === 0) return null;
|
|
12757
|
+
if (t === "numeric") return { a: mods[0], b: mods[1] ?? 0 };
|
|
12758
|
+
return { a: mods[0] };
|
|
12759
|
+
}
|
|
12760
|
+
function resolveTypeName(state, tn) {
|
|
12761
|
+
const joined = tn.parts.join(".");
|
|
12762
|
+
const bare = tn.parts.length === 1 ? tn.parts[0] : tn.parts.length === 2 && tn.parts[0] === "pg_catalog" ? tn.parts[1] : null;
|
|
12763
|
+
if (bare !== null) {
|
|
12764
|
+
const serial = SERIALS[bare];
|
|
12765
|
+
if (serial !== void 0 && tn.arrayDims === 0) {
|
|
12766
|
+
return { column: { id: serial, mod: null }, domain: null, serial };
|
|
12767
|
+
}
|
|
12768
|
+
const builtin = normalizeTypeName(bare);
|
|
12769
|
+
if (builtin !== null) {
|
|
12770
|
+
const id = tn.arrayDims > 0 ? arrayTypeOf(builtin) : builtin;
|
|
12771
|
+
return { column: { id, mod: modOf(builtin, tn.mods) }, domain: null, serial: null };
|
|
12772
|
+
}
|
|
12773
|
+
}
|
|
12774
|
+
const enumData = state.findEnum(tn.parts);
|
|
12775
|
+
if (enumData) {
|
|
12776
|
+
const elem = `enum:${enumData.schema}.${enumData.name}`;
|
|
12777
|
+
const id = tn.arrayDims > 0 ? arrayTypeOf(elem) : elem;
|
|
12778
|
+
return { column: { id, mod: null }, domain: null, serial: null };
|
|
12779
|
+
}
|
|
12780
|
+
const domainData = state.findDomain(tn.parts);
|
|
12781
|
+
if (domainData) {
|
|
12782
|
+
if (tn.arrayDims > 0) {
|
|
12783
|
+
const id = arrayTypeOf(domainData.baseType.id);
|
|
12784
|
+
return { column: { id, mod: domainData.baseType.mod }, domain: null, serial: null };
|
|
12785
|
+
}
|
|
12786
|
+
return {
|
|
12787
|
+
column: domainData.baseType,
|
|
12788
|
+
domain: `${domainData.schema}.${domainData.name}`,
|
|
12789
|
+
serial: null
|
|
12790
|
+
};
|
|
12791
|
+
}
|
|
12792
|
+
throw pgError("undefined_object", `type "${joined}" does not exist`);
|
|
12793
|
+
}
|
|
12794
|
+
|
|
12920
12795
|
// src/sql/ruleutils.ts
|
|
12921
12796
|
var BOOL = "bool";
|
|
12922
12797
|
var TEXT = "text";
|
|
@@ -13714,7 +13589,11 @@ function getMiscFunctions() {
|
|
|
13714
13589
|
}
|
|
13715
13590
|
const name2 = argText(ctx, args2[0]).toLowerCase();
|
|
13716
13591
|
const value = args2[1].v === null ? "" : argText(ctx, args2[1]);
|
|
13717
|
-
ctx.state.settings.
|
|
13592
|
+
if (!ctx.state.settings.has(name2) && !name2.includes("."))
|
|
13593
|
+
throw pgError("undefined_object", `unrecognized configuration parameter "${name2}"`, "42704");
|
|
13594
|
+
validateStorageSetting(name2, value);
|
|
13595
|
+
const local = args2[2]?.v === true;
|
|
13596
|
+
if (!local || ctx.state.inTransaction) (local ? ctx.state.localSettings : ctx.state.settings).set(name2, value);
|
|
13718
13597
|
return tv("text", value);
|
|
13719
13598
|
});
|
|
13720
13599
|
m.set(
|
|
@@ -13780,10 +13659,7 @@ function getMiscFunctions() {
|
|
|
13780
13659
|
if (!col)
|
|
13781
13660
|
throw pgError("undefined_column", `column "${column}" of relation "${table.name}" does not exist`, "42703");
|
|
13782
13661
|
if (!col.identity) return tv("text", null);
|
|
13783
|
-
return tv(
|
|
13784
|
-
"text",
|
|
13785
|
-
col.identity.sequence.split(".").map(quoteIdent).join(".")
|
|
13786
|
-
);
|
|
13662
|
+
return tv("text", col.identity.sequence.split(".").map(quoteIdent).join("."));
|
|
13787
13663
|
})
|
|
13788
13664
|
);
|
|
13789
13665
|
m.set("format_type", (ctx, args2) => {
|
|
@@ -18707,6 +18583,146 @@ function isSrfName(name2) {
|
|
|
18707
18583
|
return SRFS.has(name2);
|
|
18708
18584
|
}
|
|
18709
18585
|
|
|
18586
|
+
// src/executor/relation.ts
|
|
18587
|
+
var RowScope = class {
|
|
18588
|
+
constructor(columns, row, parent = null, rangeVars = /* @__PURE__ */ new Set()) {
|
|
18589
|
+
this.columns = columns;
|
|
18590
|
+
this.row = row;
|
|
18591
|
+
this.parent = parent;
|
|
18592
|
+
this.rangeVars = rangeVars;
|
|
18593
|
+
}
|
|
18594
|
+
columns;
|
|
18595
|
+
row;
|
|
18596
|
+
parent;
|
|
18597
|
+
rangeVars;
|
|
18598
|
+
/** Resolve a (possibly qualified) column reference. undefined = not found. */
|
|
18599
|
+
lookup(parts) {
|
|
18600
|
+
if (parts.length === 1) {
|
|
18601
|
+
const name3 = parts[0];
|
|
18602
|
+
let found2;
|
|
18603
|
+
let count2 = 0;
|
|
18604
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
18605
|
+
const c = this.columns[i];
|
|
18606
|
+
if (c.name === name3 && !c.hidden) {
|
|
18607
|
+
count2++;
|
|
18608
|
+
if (count2 > 1) {
|
|
18609
|
+
throw pgError("ambiguous_column", `column reference "${name3}" is ambiguous`);
|
|
18610
|
+
}
|
|
18611
|
+
found2 = tv(c.type, this.row[i] ?? null);
|
|
18612
|
+
}
|
|
18613
|
+
}
|
|
18614
|
+
if (found2 !== void 0) return found2;
|
|
18615
|
+
if (this.rangeVars.has(name3)) {
|
|
18616
|
+
return this.wholeRow(name3);
|
|
18617
|
+
}
|
|
18618
|
+
return this.parent?.lookup(parts);
|
|
18619
|
+
}
|
|
18620
|
+
const table = parts[parts.length - 2];
|
|
18621
|
+
const name2 = parts[parts.length - 1];
|
|
18622
|
+
let found;
|
|
18623
|
+
let count = 0;
|
|
18624
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
18625
|
+
const c = this.columns[i];
|
|
18626
|
+
if (c.table === table && c.name === name2) {
|
|
18627
|
+
count++;
|
|
18628
|
+
if (count > 1) {
|
|
18629
|
+
throw pgError("ambiguous_column", `column reference "${name2}" is ambiguous`);
|
|
18630
|
+
}
|
|
18631
|
+
found = tv(c.type, this.row[i] ?? null);
|
|
18632
|
+
}
|
|
18633
|
+
}
|
|
18634
|
+
if (found !== void 0) return found;
|
|
18635
|
+
return this.parent?.lookup(parts);
|
|
18636
|
+
}
|
|
18637
|
+
/** Build a record value from all columns belonging to a range variable. */
|
|
18638
|
+
wholeRow(rangeVar) {
|
|
18639
|
+
const types = [];
|
|
18640
|
+
const values = [];
|
|
18641
|
+
const names = [];
|
|
18642
|
+
for (let i = 0; i < this.columns.length; i++) {
|
|
18643
|
+
const c = this.columns[i];
|
|
18644
|
+
if (c.table === rangeVar) {
|
|
18645
|
+
types.push(c.type);
|
|
18646
|
+
values.push(this.row[i] ?? null);
|
|
18647
|
+
names.push(c.name);
|
|
18648
|
+
}
|
|
18649
|
+
}
|
|
18650
|
+
if (types.length === 0) return void 0;
|
|
18651
|
+
return tv("record", { kind: "pgrecord", types, values, names });
|
|
18652
|
+
}
|
|
18653
|
+
hasRangeVar(name2) {
|
|
18654
|
+
if (this.rangeVars.has(name2)) return true;
|
|
18655
|
+
return this.parent?.hasRangeVar(name2) ?? false;
|
|
18656
|
+
}
|
|
18657
|
+
};
|
|
18658
|
+
function childEnv(env, outer) {
|
|
18659
|
+
return {
|
|
18660
|
+
ctx: env.ctx,
|
|
18661
|
+
params: env.params,
|
|
18662
|
+
ctes: env.ctes,
|
|
18663
|
+
outer,
|
|
18664
|
+
allowUnpopulatedMatviews: env.allowUnpopulatedMatviews
|
|
18665
|
+
};
|
|
18666
|
+
}
|
|
18667
|
+
function relationResult(rel3, command2) {
|
|
18668
|
+
const visible = rel3.columns.map((c, i) => ({ i, c })).filter(({ c }) => !c.hidden);
|
|
18669
|
+
return {
|
|
18670
|
+
columns: visible.map(({ c }) => ({ name: c.name, type: c.type })),
|
|
18671
|
+
rows: rel3.rows.map((r) => visible.map(({ i }) => r[i] ?? null)),
|
|
18672
|
+
command: command2,
|
|
18673
|
+
rowCount: rel3.rows.length
|
|
18674
|
+
};
|
|
18675
|
+
}
|
|
18676
|
+
function commandResult(command2, rowCount) {
|
|
18677
|
+
return { columns: [], rows: [], command: command2, rowCount };
|
|
18678
|
+
}
|
|
18679
|
+
function inferColumnName(e) {
|
|
18680
|
+
switch (e.type) {
|
|
18681
|
+
case "colref":
|
|
18682
|
+
return e.parts[e.parts.length - 1];
|
|
18683
|
+
case "func":
|
|
18684
|
+
return e.name[e.name.length - 1];
|
|
18685
|
+
case "cast": {
|
|
18686
|
+
const inner = inferColumnName(e.expr);
|
|
18687
|
+
if (inner !== "?column?") return inner;
|
|
18688
|
+
return e.target.parts[e.target.parts.length - 1];
|
|
18689
|
+
}
|
|
18690
|
+
case "collate":
|
|
18691
|
+
return inferColumnName(e.expr);
|
|
18692
|
+
case "case":
|
|
18693
|
+
return "case";
|
|
18694
|
+
case "array_ctor":
|
|
18695
|
+
case "array_query":
|
|
18696
|
+
return "array";
|
|
18697
|
+
case "row":
|
|
18698
|
+
return "row";
|
|
18699
|
+
case "subquery_expr":
|
|
18700
|
+
return e.kind === "exists" ? "exists" : "?column?";
|
|
18701
|
+
case "bool_lit":
|
|
18702
|
+
return "bool";
|
|
18703
|
+
case "extract":
|
|
18704
|
+
return "extract";
|
|
18705
|
+
case "position":
|
|
18706
|
+
return "position";
|
|
18707
|
+
case "substring_sql":
|
|
18708
|
+
return "substring";
|
|
18709
|
+
case "overlay":
|
|
18710
|
+
return "overlay";
|
|
18711
|
+
case "trim":
|
|
18712
|
+
return e.side === "leading" ? "ltrim" : e.side === "trailing" ? "rtrim" : "btrim";
|
|
18713
|
+
case "field_select":
|
|
18714
|
+
return e.field === "*" ? "?column?" : e.field;
|
|
18715
|
+
case "at_time_zone":
|
|
18716
|
+
return "timezone";
|
|
18717
|
+
case "grouping_func":
|
|
18718
|
+
return "grouping";
|
|
18719
|
+
case "subscript":
|
|
18720
|
+
return inferColumnName(e.base);
|
|
18721
|
+
default:
|
|
18722
|
+
return "?column?";
|
|
18723
|
+
}
|
|
18724
|
+
}
|
|
18725
|
+
|
|
18710
18726
|
// src/indexes/index.ts
|
|
18711
18727
|
var IndexStore = class _IndexStore {
|
|
18712
18728
|
name;
|
|
@@ -18769,53 +18785,228 @@ function ensureIndexStores(env, table) {
|
|
|
18769
18785
|
const key = uniqueKeyOf(env, table, spec, table.rowAt(i));
|
|
18770
18786
|
if (key !== null) store.insert(key, i);
|
|
18771
18787
|
}
|
|
18772
|
-
stores.set(spec.name, store);
|
|
18773
|
-
}
|
|
18774
|
-
const schema = env.ctx.state.schemas.get(table.schema);
|
|
18775
|
-
if (schema) {
|
|
18776
|
-
for (const idx of schema.indexes.values()) {
|
|
18777
|
-
if (idx.table !== table.name || idx.unique) continue;
|
|
18778
|
-
stores.set(idx.name, new IndexStore(idx.name, false));
|
|
18788
|
+
stores.set(spec.name, store);
|
|
18789
|
+
}
|
|
18790
|
+
const schema = env.ctx.state.schemas.get(table.schema);
|
|
18791
|
+
if (schema) {
|
|
18792
|
+
for (const idx of schema.indexes.values()) {
|
|
18793
|
+
if (idx.table !== table.name || idx.unique) continue;
|
|
18794
|
+
stores.set(idx.name, new IndexStore(idx.name, false));
|
|
18795
|
+
}
|
|
18796
|
+
}
|
|
18797
|
+
table.indexStores = stores;
|
|
18798
|
+
return stores;
|
|
18799
|
+
}
|
|
18800
|
+
function indexStoreFor(env, table, spec) {
|
|
18801
|
+
const stores = ensureIndexStores(env, table);
|
|
18802
|
+
let store = stores.get(spec.name);
|
|
18803
|
+
if (!store) {
|
|
18804
|
+
store = new IndexStore(spec.name, true);
|
|
18805
|
+
for (let i = 0; i < table.rowCount(); i++) {
|
|
18806
|
+
const key = uniqueKeyOf(env, table, spec, table.rowAt(i));
|
|
18807
|
+
if (key !== null) store.insert(key, i);
|
|
18808
|
+
}
|
|
18809
|
+
stores.set(spec.name, store);
|
|
18810
|
+
}
|
|
18811
|
+
return store;
|
|
18812
|
+
}
|
|
18813
|
+
function indexInsertRow(env, table, rowIdx, row) {
|
|
18814
|
+
for (const spec of uniqueSpecsFor(env, table)) {
|
|
18815
|
+
const key = uniqueKeyOf(env, table, spec, row);
|
|
18816
|
+
if (key === null) continue;
|
|
18817
|
+
indexStoreFor(env, table, spec).insert(key, rowIdx);
|
|
18818
|
+
}
|
|
18819
|
+
}
|
|
18820
|
+
function indexRemoveRow(env, table, rowIdx, row) {
|
|
18821
|
+
if (!table.indexStores) return;
|
|
18822
|
+
for (const spec of uniqueSpecsFor(env, table)) {
|
|
18823
|
+
const key = uniqueKeyOf(env, table, spec, row);
|
|
18824
|
+
if (key === null) continue;
|
|
18825
|
+
table.indexStores.get(spec.name)?.remove(key, rowIdx);
|
|
18826
|
+
}
|
|
18827
|
+
}
|
|
18828
|
+
function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
|
|
18829
|
+
indexRemoveRow(env, table, rowIdx, oldRow);
|
|
18830
|
+
indexInsertRow(env, table, rowIdx, newRow);
|
|
18831
|
+
}
|
|
18832
|
+
function rebuildTableIndexes(env, table) {
|
|
18833
|
+
table.indexStores = null;
|
|
18834
|
+
ensureIndexStores(env, table);
|
|
18835
|
+
}
|
|
18836
|
+
|
|
18837
|
+
// src/constraints/enforce.ts
|
|
18838
|
+
function tableScope(table, row) {
|
|
18839
|
+
const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
|
|
18840
|
+
return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
|
|
18841
|
+
}
|
|
18842
|
+
function checkNotNull(env, table, row) {
|
|
18843
|
+
void env;
|
|
18844
|
+
for (let i = 0; i < table.columns.length; i++) {
|
|
18845
|
+
const c = table.columns[i];
|
|
18846
|
+
if (c.notNull && (row[i] ?? null) === null) {
|
|
18847
|
+
throw pgError(
|
|
18848
|
+
"not_null_violation",
|
|
18849
|
+
`null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
|
|
18850
|
+
"23502"
|
|
18851
|
+
);
|
|
18852
|
+
}
|
|
18853
|
+
}
|
|
18854
|
+
}
|
|
18855
|
+
function checkChecks(env, table, row) {
|
|
18856
|
+
for (const con of table.constraints) {
|
|
18857
|
+
if (con.kind !== "check") continue;
|
|
18858
|
+
const scope = makeEvalScope(env, tableScope(table, row));
|
|
18859
|
+
const v = evalExpr(env.ctx, scope, con.expr);
|
|
18860
|
+
if (v.v === null) continue;
|
|
18861
|
+
const b = castTo(env.ctx, v, "bool", {});
|
|
18862
|
+
if (b.v !== true) {
|
|
18863
|
+
throw pgError(
|
|
18864
|
+
"check_violation",
|
|
18865
|
+
`new row for relation "${table.name}" violates check constraint "${con.name}"`,
|
|
18866
|
+
"23514"
|
|
18867
|
+
);
|
|
18868
|
+
}
|
|
18869
|
+
}
|
|
18870
|
+
}
|
|
18871
|
+
function uniqueSpecsFor(env, table) {
|
|
18872
|
+
const specs = [];
|
|
18873
|
+
for (const con of table.constraints) {
|
|
18874
|
+
if (con.kind !== "primary_key" && con.kind !== "unique") continue;
|
|
18875
|
+
specs.push({
|
|
18876
|
+
name: con.name,
|
|
18877
|
+
keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
|
|
18878
|
+
columnNames: con.columns,
|
|
18879
|
+
nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
|
|
18880
|
+
where: null,
|
|
18881
|
+
isPrimary: con.kind === "primary_key"
|
|
18882
|
+
});
|
|
18883
|
+
}
|
|
18884
|
+
const schema = env.ctx.state.schemas.get(table.schema);
|
|
18885
|
+
if (schema) {
|
|
18886
|
+
for (const idx of schema.indexes.values()) {
|
|
18887
|
+
if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
|
|
18888
|
+
specs.push(uniqueSpecOfIndex(table, idx));
|
|
18889
|
+
}
|
|
18890
|
+
}
|
|
18891
|
+
return specs;
|
|
18892
|
+
}
|
|
18893
|
+
function uniqueSpecOfIndex(table, idx) {
|
|
18894
|
+
return {
|
|
18895
|
+
name: idx.name,
|
|
18896
|
+
keys: idx.columns.map((c) => ({
|
|
18897
|
+
colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
|
|
18898
|
+
expr: c.expr
|
|
18899
|
+
})),
|
|
18900
|
+
columnNames: idx.columns.map((c) => c.column ?? "expr"),
|
|
18901
|
+
nullsNotDistinct: idx.nullsNotDistinct,
|
|
18902
|
+
where: idx.where,
|
|
18903
|
+
isPrimary: false
|
|
18904
|
+
};
|
|
18905
|
+
}
|
|
18906
|
+
function uniqueKeyOf(env, table, spec, row) {
|
|
18907
|
+
if (spec.where) {
|
|
18908
|
+
const scope = makeEvalScope(env, tableScope(table, row));
|
|
18909
|
+
const v = evalExpr(env.ctx, scope, spec.where);
|
|
18910
|
+
if (v.v !== true) return null;
|
|
18911
|
+
}
|
|
18912
|
+
const parts = [];
|
|
18913
|
+
let hasNull = false;
|
|
18914
|
+
for (const k of spec.keys) {
|
|
18915
|
+
let value;
|
|
18916
|
+
let type;
|
|
18917
|
+
if (k.expr) {
|
|
18918
|
+
const scope = makeEvalScope(env, tableScope(table, row));
|
|
18919
|
+
const v = evalExpr(env.ctx, scope, k.expr);
|
|
18920
|
+
value = v.v;
|
|
18921
|
+
type = v.t === "unknown" ? "text" : v.t;
|
|
18922
|
+
} else {
|
|
18923
|
+
value = row[k.colIdx] ?? null;
|
|
18924
|
+
type = table.columns[k.colIdx].type.id;
|
|
18925
|
+
}
|
|
18926
|
+
if (value === null) {
|
|
18927
|
+
hasNull = true;
|
|
18928
|
+
parts.push("\0N");
|
|
18929
|
+
} else {
|
|
18930
|
+
parts.push(datumKey(type, value));
|
|
18931
|
+
}
|
|
18932
|
+
}
|
|
18933
|
+
if (hasNull && !spec.nullsNotDistinct) return null;
|
|
18934
|
+
return parts.join("");
|
|
18935
|
+
}
|
|
18936
|
+
function checkUnique(env, table, row, selfIdx) {
|
|
18937
|
+
for (const spec of uniqueSpecsFor(env, table)) {
|
|
18938
|
+
const key = uniqueKeyOf(env, table, spec, row);
|
|
18939
|
+
if (key === null) continue;
|
|
18940
|
+
indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
|
|
18941
|
+
}
|
|
18942
|
+
}
|
|
18943
|
+
function findConflict(env, table, spec, row) {
|
|
18944
|
+
const key = uniqueKeyOf(env, table, spec, row);
|
|
18945
|
+
if (key === null) return null;
|
|
18946
|
+
const hits = indexStoreFor(env, table, spec).lookup(key);
|
|
18947
|
+
return hits.length > 0 ? hits[0] : null;
|
|
18948
|
+
}
|
|
18949
|
+
function checkForeignKeys(env, table, row) {
|
|
18950
|
+
const state = env.ctx.state;
|
|
18951
|
+
for (const con of table.constraints) {
|
|
18952
|
+
if (con.kind !== "foreign_key") continue;
|
|
18953
|
+
const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
|
|
18954
|
+
const nulls = values.filter((v) => v === null).length;
|
|
18955
|
+
if (con.match === "simple" && nulls > 0) continue;
|
|
18956
|
+
if (con.match === "full") {
|
|
18957
|
+
if (nulls === values.length) continue;
|
|
18958
|
+
if (nulls > 0) {
|
|
18959
|
+
throw pgError(
|
|
18960
|
+
"constraint_foreign_key",
|
|
18961
|
+
`insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
|
|
18962
|
+
"23503"
|
|
18963
|
+
);
|
|
18964
|
+
}
|
|
18965
|
+
}
|
|
18966
|
+
const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
|
|
18967
|
+
if (!refTable) {
|
|
18968
|
+
throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
|
|
18969
|
+
}
|
|
18970
|
+
const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
|
|
18971
|
+
const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
|
|
18972
|
+
const wanted = values.map((v, i) => {
|
|
18973
|
+
const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
|
|
18974
|
+
const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
|
|
18975
|
+
return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
|
|
18976
|
+
}).join("");
|
|
18977
|
+
let found = false;
|
|
18978
|
+
for (let i = 0; i < refTable.rowCount(); i++) {
|
|
18979
|
+
const r = refTable.rowAt(i);
|
|
18980
|
+
const key = refIdxs.map((ri, j) => {
|
|
18981
|
+
const v = r[ri] ?? null;
|
|
18982
|
+
return v === null ? "\0N" : datumKey(keyTypes[j], v);
|
|
18983
|
+
}).join("");
|
|
18984
|
+
if (key === wanted) {
|
|
18985
|
+
found = true;
|
|
18986
|
+
break;
|
|
18987
|
+
}
|
|
18988
|
+
}
|
|
18989
|
+
if (!found) {
|
|
18990
|
+
throw pgError(
|
|
18991
|
+
"constraint_foreign_key",
|
|
18992
|
+
`insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
|
|
18993
|
+
"23503"
|
|
18994
|
+
);
|
|
18779
18995
|
}
|
|
18780
18996
|
}
|
|
18781
|
-
table.indexStores = stores;
|
|
18782
|
-
return stores;
|
|
18783
18997
|
}
|
|
18784
|
-
function
|
|
18785
|
-
const
|
|
18786
|
-
|
|
18787
|
-
|
|
18788
|
-
|
|
18789
|
-
|
|
18790
|
-
|
|
18791
|
-
|
|
18998
|
+
function referencingConstraints(env, table) {
|
|
18999
|
+
const out = [];
|
|
19000
|
+
for (const schema of env.ctx.state.schemas.values()) {
|
|
19001
|
+
for (const t of schema.tables.values()) {
|
|
19002
|
+
for (const con of t.constraints) {
|
|
19003
|
+
if (con.kind === "foreign_key" && con.refSchema === table.schema && con.refTable === table.name) {
|
|
19004
|
+
out.push({ table: t, constraint: con });
|
|
19005
|
+
}
|
|
19006
|
+
}
|
|
18792
19007
|
}
|
|
18793
|
-
stores.set(spec.name, store);
|
|
18794
|
-
}
|
|
18795
|
-
return store;
|
|
18796
|
-
}
|
|
18797
|
-
function indexInsertRow(env, table, rowIdx, row) {
|
|
18798
|
-
for (const spec of uniqueSpecsFor(env, table)) {
|
|
18799
|
-
const key = uniqueKeyOf(env, table, spec, row);
|
|
18800
|
-
if (key === null) continue;
|
|
18801
|
-
indexStoreFor(env, table, spec).insert(key, rowIdx);
|
|
18802
|
-
}
|
|
18803
|
-
}
|
|
18804
|
-
function indexRemoveRow(env, table, rowIdx, row) {
|
|
18805
|
-
if (!table.indexStores) return;
|
|
18806
|
-
for (const spec of uniqueSpecsFor(env, table)) {
|
|
18807
|
-
const key = uniqueKeyOf(env, table, spec, row);
|
|
18808
|
-
if (key === null) continue;
|
|
18809
|
-
table.indexStores.get(spec.name)?.remove(key, rowIdx);
|
|
18810
19008
|
}
|
|
18811
|
-
|
|
18812
|
-
function indexUpdateRow(env, table, rowIdx, oldRow, newRow) {
|
|
18813
|
-
indexRemoveRow(env, table, rowIdx, oldRow);
|
|
18814
|
-
indexInsertRow(env, table, rowIdx, newRow);
|
|
18815
|
-
}
|
|
18816
|
-
function rebuildTableIndexes(env, table) {
|
|
18817
|
-
table.indexStores = null;
|
|
18818
|
-
ensureIndexStores(env, table);
|
|
19009
|
+
return out;
|
|
18819
19010
|
}
|
|
18820
19011
|
|
|
18821
19012
|
// src/planner/access.ts
|
|
@@ -20701,10 +20892,9 @@ var Parser = class {
|
|
|
20701
20892
|
return this.parseCreateFunction(orReplace);
|
|
20702
20893
|
}
|
|
20703
20894
|
if (this.atKw("trigger") || this.atKw("constraint") && this.atKw("trigger", 1)) {
|
|
20704
|
-
|
|
20705
|
-
}
|
|
20895
|
+
const constraint = this.eatKw("constraint");
|
|
20706
20896
|
this.expectKw("trigger");
|
|
20707
|
-
return this.parseCreateTrigger(orReplace);
|
|
20897
|
+
return this.parseCreateTrigger(orReplace, constraint);
|
|
20708
20898
|
}
|
|
20709
20899
|
if (this.atKw("extension")) {
|
|
20710
20900
|
this.pos++;
|
|
@@ -21525,7 +21715,7 @@ var Parser = class {
|
|
|
21525
21715
|
strict: strict2
|
|
21526
21716
|
};
|
|
21527
21717
|
}
|
|
21528
|
-
parseCreateTrigger(orReplace) {
|
|
21718
|
+
parseCreateTrigger(orReplace, constraint) {
|
|
21529
21719
|
const name2 = this.ident();
|
|
21530
21720
|
let timing;
|
|
21531
21721
|
if (this.eatKw("before")) timing = "before";
|
|
@@ -21555,9 +21745,18 @@ var Parser = class {
|
|
|
21555
21745
|
this.expectKw("on");
|
|
21556
21746
|
const table = this.qualifiedName();
|
|
21557
21747
|
if (this.eatKw("referencing")) throw unsupported("trigger transition tables");
|
|
21558
|
-
|
|
21559
|
-
|
|
21560
|
-
|
|
21748
|
+
let deferrable = false;
|
|
21749
|
+
let initiallyDeferred = false;
|
|
21750
|
+
if (this.eatKw("not")) this.expectKw("deferrable");
|
|
21751
|
+
else if (this.eatKw("deferrable")) deferrable = true;
|
|
21752
|
+
if (this.eatKw("initially")) {
|
|
21753
|
+
if (this.eatKw("deferred")) initiallyDeferred = true;
|
|
21754
|
+
else this.expectKw("immediate");
|
|
21755
|
+
}
|
|
21756
|
+
if ((deferrable || initiallyDeferred) && !constraint)
|
|
21757
|
+
this.errorAt(this.peek(), "only constraint triggers can be deferred");
|
|
21758
|
+
if (initiallyDeferred && !deferrable)
|
|
21759
|
+
this.errorAt(this.peek(), "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
|
|
21561
21760
|
let forEachRow = false;
|
|
21562
21761
|
if (this.eatKw("for")) {
|
|
21563
21762
|
this.eatKw("each");
|
|
@@ -21582,7 +21781,21 @@ var Parser = class {
|
|
|
21582
21781
|
} while (this.eatPunct(","));
|
|
21583
21782
|
}
|
|
21584
21783
|
this.expectPunct(")");
|
|
21585
|
-
return {
|
|
21784
|
+
return {
|
|
21785
|
+
type: "create_trigger",
|
|
21786
|
+
constraint,
|
|
21787
|
+
deferrable,
|
|
21788
|
+
initiallyDeferred,
|
|
21789
|
+
orReplace,
|
|
21790
|
+
name: name2,
|
|
21791
|
+
timing,
|
|
21792
|
+
events,
|
|
21793
|
+
table,
|
|
21794
|
+
forEachRow,
|
|
21795
|
+
when,
|
|
21796
|
+
funcName,
|
|
21797
|
+
funcArgs
|
|
21798
|
+
};
|
|
21586
21799
|
}
|
|
21587
21800
|
// --- ALTER --------------------------------------------------------------------
|
|
21588
21801
|
parseAlter() {
|
|
@@ -21927,9 +22140,15 @@ var Parser = class {
|
|
|
21927
22140
|
this.skipToStatementEnd();
|
|
21928
22141
|
return { type: "no_op", what: "SET TRANSACTION" };
|
|
21929
22142
|
}
|
|
21930
|
-
if (this.
|
|
21931
|
-
this.
|
|
21932
|
-
|
|
22143
|
+
if (this.eatKw("constraints")) {
|
|
22144
|
+
const names = this.eatKw("all") ? null : [];
|
|
22145
|
+
if (names)
|
|
22146
|
+
do {
|
|
22147
|
+
names.push(this.qualifiedName());
|
|
22148
|
+
} while (this.eatPunct(","));
|
|
22149
|
+
const deferred = this.eatKw("deferred");
|
|
22150
|
+
if (!deferred) this.expectKw("immediate");
|
|
22151
|
+
return { type: "set_constraints", names, deferred };
|
|
21933
22152
|
}
|
|
21934
22153
|
if (this.atKw("role") || this.atKw("session", 0) && this.atKw("authorization", 1)) {
|
|
21935
22154
|
this.skipToStatementEnd();
|
|
@@ -24304,12 +24523,12 @@ function executeRecursiveCte(env, cte, query) {
|
|
|
24304
24523
|
table: null
|
|
24305
24524
|
}));
|
|
24306
24525
|
const seen = /* @__PURE__ */ new Set();
|
|
24307
|
-
const
|
|
24526
|
+
const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(columns[i].type, v)).join("");
|
|
24308
24527
|
let result = [];
|
|
24309
24528
|
let working = [];
|
|
24310
24529
|
for (const row of base.rows) {
|
|
24311
24530
|
if (!body.all) {
|
|
24312
|
-
const k =
|
|
24531
|
+
const k = keyOf2(row);
|
|
24313
24532
|
if (seen.has(k)) continue;
|
|
24314
24533
|
seen.add(k);
|
|
24315
24534
|
}
|
|
@@ -24342,7 +24561,7 @@ function executeRecursiveCte(env, cte, query) {
|
|
|
24342
24561
|
return castTo(env.ctx, tv(srcT === UNKNOWN ? "text" : srcT, v), columns[i].type, {}).v;
|
|
24343
24562
|
});
|
|
24344
24563
|
if (!body.all) {
|
|
24345
|
-
const k =
|
|
24564
|
+
const k = keyOf2(row);
|
|
24346
24565
|
if (seen.has(k)) continue;
|
|
24347
24566
|
seen.add(k);
|
|
24348
24567
|
}
|
|
@@ -25522,7 +25741,7 @@ function setOpRelation(env, op) {
|
|
|
25522
25741
|
);
|
|
25523
25742
|
const lrows = normalize2(left);
|
|
25524
25743
|
const rrows = normalize2(right);
|
|
25525
|
-
const
|
|
25744
|
+
const keyOf2 = (row) => row.map((v, i) => v === null ? "\0N" : datumKey(types[i], v)).join("");
|
|
25526
25745
|
let rows;
|
|
25527
25746
|
switch (op.op) {
|
|
25528
25747
|
case "union": {
|
|
@@ -25530,7 +25749,7 @@ function setOpRelation(env, op) {
|
|
|
25530
25749
|
if (!op.all) {
|
|
25531
25750
|
const seen = /* @__PURE__ */ new Set();
|
|
25532
25751
|
rows = rows.filter((r) => {
|
|
25533
|
-
const k =
|
|
25752
|
+
const k = keyOf2(r);
|
|
25534
25753
|
if (seen.has(k)) return false;
|
|
25535
25754
|
seen.add(k);
|
|
25536
25755
|
return true;
|
|
@@ -25541,13 +25760,13 @@ function setOpRelation(env, op) {
|
|
|
25541
25760
|
case "intersect": {
|
|
25542
25761
|
const rightCounts = /* @__PURE__ */ new Map();
|
|
25543
25762
|
for (const r of rrows) {
|
|
25544
|
-
const k =
|
|
25763
|
+
const k = keyOf2(r);
|
|
25545
25764
|
rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
|
|
25546
25765
|
}
|
|
25547
25766
|
rows = [];
|
|
25548
25767
|
const emitted = /* @__PURE__ */ new Set();
|
|
25549
25768
|
for (const r of lrows) {
|
|
25550
|
-
const k =
|
|
25769
|
+
const k = keyOf2(r);
|
|
25551
25770
|
const avail = rightCounts.get(k) ?? 0;
|
|
25552
25771
|
if (avail <= 0) continue;
|
|
25553
25772
|
if (op.all) {
|
|
@@ -25563,13 +25782,13 @@ function setOpRelation(env, op) {
|
|
|
25563
25782
|
case "except": {
|
|
25564
25783
|
const rightCounts = /* @__PURE__ */ new Map();
|
|
25565
25784
|
for (const r of rrows) {
|
|
25566
|
-
const k =
|
|
25785
|
+
const k = keyOf2(r);
|
|
25567
25786
|
rightCounts.set(k, (rightCounts.get(k) ?? 0) + 1);
|
|
25568
25787
|
}
|
|
25569
25788
|
rows = [];
|
|
25570
25789
|
const emitted = /* @__PURE__ */ new Set();
|
|
25571
25790
|
for (const r of lrows) {
|
|
25572
|
-
const k =
|
|
25791
|
+
const k = keyOf2(r);
|
|
25573
25792
|
if (op.all) {
|
|
25574
25793
|
const avail = rightCounts.get(k) ?? 0;
|
|
25575
25794
|
if (avail > 0) {
|
|
@@ -26023,201 +26242,48 @@ function executeCore(env0, core, orderBy, opts) {
|
|
|
26023
26242
|
}
|
|
26024
26243
|
rel3 = stripHidden(rel3);
|
|
26025
26244
|
return rel3;
|
|
26026
|
-
}
|
|
26027
|
-
function executeSelectStmt(env0, stmt) {
|
|
26028
|
-
const env = applyWith(env0, stmt.with);
|
|
26029
|
-
let rel3;
|
|
26030
|
-
if (stmt.body.type === "select_core") {
|
|
26031
|
-
rel3 = executeCore(env, stmt.body, stmt.orderBy, { hasLimit: stmt.limit !== null });
|
|
26032
|
-
} else {
|
|
26033
|
-
rel3 = executeBody(env, stmt.body);
|
|
26034
|
-
const specs = outputOrderSpecs(env, rel3, stmt.orderBy);
|
|
26035
|
-
if (specs.length > 0) sortRows(env, rel3, specs);
|
|
26036
|
-
rel3 = stripHidden(rel3);
|
|
26037
|
-
}
|
|
26038
|
-
if (stmt.limitWithTies) {
|
|
26039
|
-
if (stmt.orderBy.length === 0) {
|
|
26040
|
-
throw pgError("syntax", "WITH TIES cannot be specified without ORDER BY clause", "42601");
|
|
26041
|
-
}
|
|
26042
|
-
const tieSpecs = outputOrderSpecs(env, rel3, stmt.orderBy);
|
|
26043
|
-
return stripHidden(applyLimitOffset(env, rel3, stmt.limit, stmt.offset, tieSpecs));
|
|
26044
|
-
}
|
|
26045
|
-
return applyLimitOffset(env, rel3, stmt.limit, stmt.offset);
|
|
26046
|
-
}
|
|
26047
|
-
|
|
26048
|
-
// src/constraints/enforce.ts
|
|
26049
|
-
function tableScope(table, row) {
|
|
26050
|
-
const cols = table.columns.map((c) => ({ name: c.name, type: c.type.id, table: table.name }));
|
|
26051
|
-
return new RowScope(cols, row, null, /* @__PURE__ */ new Set([table.name]));
|
|
26052
|
-
}
|
|
26053
|
-
function checkNotNull(env, table, row) {
|
|
26054
|
-
void env;
|
|
26055
|
-
for (let i = 0; i < table.columns.length; i++) {
|
|
26056
|
-
const c = table.columns[i];
|
|
26057
|
-
if (c.notNull && (row[i] ?? null) === null) {
|
|
26058
|
-
throw pgError(
|
|
26059
|
-
"not_null_violation",
|
|
26060
|
-
`null value in column "${c.name}" of relation "${table.name}" violates not-null constraint`,
|
|
26061
|
-
"23502"
|
|
26062
|
-
);
|
|
26063
|
-
}
|
|
26064
|
-
}
|
|
26065
|
-
}
|
|
26066
|
-
function checkChecks(env, table, row) {
|
|
26067
|
-
for (const con of table.constraints) {
|
|
26068
|
-
if (con.kind !== "check") continue;
|
|
26069
|
-
const scope = makeEvalScope(env, tableScope(table, row));
|
|
26070
|
-
const v = evalExpr(env.ctx, scope, con.expr);
|
|
26071
|
-
if (v.v === null) continue;
|
|
26072
|
-
const b = castTo(env.ctx, v, "bool", {});
|
|
26073
|
-
if (b.v !== true) {
|
|
26074
|
-
throw pgError(
|
|
26075
|
-
"check_violation",
|
|
26076
|
-
`new row for relation "${table.name}" violates check constraint "${con.name}"`,
|
|
26077
|
-
"23514"
|
|
26078
|
-
);
|
|
26079
|
-
}
|
|
26080
|
-
}
|
|
26081
|
-
}
|
|
26082
|
-
function uniqueSpecsFor(env, table) {
|
|
26083
|
-
const specs = [];
|
|
26084
|
-
for (const con of table.constraints) {
|
|
26085
|
-
if (con.kind !== "primary_key" && con.kind !== "unique") continue;
|
|
26086
|
-
specs.push({
|
|
26087
|
-
name: con.name,
|
|
26088
|
-
keys: con.columns.map((c) => ({ colIdx: table.columnIndex(c), expr: null })),
|
|
26089
|
-
columnNames: con.columns,
|
|
26090
|
-
nullsNotDistinct: con.kind === "unique" ? con.nullsNotDistinct : false,
|
|
26091
|
-
where: null,
|
|
26092
|
-
isPrimary: con.kind === "primary_key"
|
|
26093
|
-
});
|
|
26094
|
-
}
|
|
26095
|
-
const schema = env.ctx.state.schemas.get(table.schema);
|
|
26096
|
-
if (schema) {
|
|
26097
|
-
for (const idx of schema.indexes.values()) {
|
|
26098
|
-
if (idx.table !== table.name || !idx.unique || idx.isConstraint || idx.valid === false) continue;
|
|
26099
|
-
specs.push(uniqueSpecOfIndex(table, idx));
|
|
26100
|
-
}
|
|
26101
|
-
}
|
|
26102
|
-
return specs;
|
|
26103
|
-
}
|
|
26104
|
-
function uniqueSpecOfIndex(table, idx) {
|
|
26105
|
-
return {
|
|
26106
|
-
name: idx.name,
|
|
26107
|
-
keys: idx.columns.map((c) => ({
|
|
26108
|
-
colIdx: c.column !== null ? table.columnIndex(c.column) : -1,
|
|
26109
|
-
expr: c.expr
|
|
26110
|
-
})),
|
|
26111
|
-
columnNames: idx.columns.map((c) => c.column ?? "expr"),
|
|
26112
|
-
nullsNotDistinct: idx.nullsNotDistinct,
|
|
26113
|
-
where: idx.where,
|
|
26114
|
-
isPrimary: false
|
|
26115
|
-
};
|
|
26116
|
-
}
|
|
26117
|
-
function uniqueKeyOf(env, table, spec, row) {
|
|
26118
|
-
if (spec.where) {
|
|
26119
|
-
const scope = makeEvalScope(env, tableScope(table, row));
|
|
26120
|
-
const v = evalExpr(env.ctx, scope, spec.where);
|
|
26121
|
-
if (v.v !== true) return null;
|
|
26122
|
-
}
|
|
26123
|
-
const parts = [];
|
|
26124
|
-
let hasNull = false;
|
|
26125
|
-
for (const k of spec.keys) {
|
|
26126
|
-
let value;
|
|
26127
|
-
let type;
|
|
26128
|
-
if (k.expr) {
|
|
26129
|
-
const scope = makeEvalScope(env, tableScope(table, row));
|
|
26130
|
-
const v = evalExpr(env.ctx, scope, k.expr);
|
|
26131
|
-
value = v.v;
|
|
26132
|
-
type = v.t === "unknown" ? "text" : v.t;
|
|
26133
|
-
} else {
|
|
26134
|
-
value = row[k.colIdx] ?? null;
|
|
26135
|
-
type = table.columns[k.colIdx].type.id;
|
|
26136
|
-
}
|
|
26137
|
-
if (value === null) {
|
|
26138
|
-
hasNull = true;
|
|
26139
|
-
parts.push("\0N");
|
|
26140
|
-
} else {
|
|
26141
|
-
parts.push(datumKey(type, value));
|
|
26142
|
-
}
|
|
26143
|
-
}
|
|
26144
|
-
if (hasNull && !spec.nullsNotDistinct) return null;
|
|
26145
|
-
return parts.join("");
|
|
26146
|
-
}
|
|
26147
|
-
function checkUnique(env, table, row, selfIdx) {
|
|
26148
|
-
for (const spec of uniqueSpecsFor(env, table)) {
|
|
26149
|
-
const key = uniqueKeyOf(env, table, spec, row);
|
|
26150
|
-
if (key === null) continue;
|
|
26151
|
-
indexStoreFor(env, table, spec).checkUnique(key, selfIdx);
|
|
26152
|
-
}
|
|
26153
|
-
}
|
|
26154
|
-
function findConflict(env, table, spec, row) {
|
|
26155
|
-
const key = uniqueKeyOf(env, table, spec, row);
|
|
26156
|
-
if (key === null) return null;
|
|
26157
|
-
const hits = indexStoreFor(env, table, spec).lookup(key);
|
|
26158
|
-
return hits.length > 0 ? hits[0] : null;
|
|
26159
|
-
}
|
|
26160
|
-
function checkForeignKeys(env, table, row) {
|
|
26161
|
-
const state = env.ctx.state;
|
|
26162
|
-
for (const con of table.constraints) {
|
|
26163
|
-
if (con.kind !== "foreign_key") continue;
|
|
26164
|
-
const values = con.columns.map((c) => row[table.columnIndex(c)] ?? null);
|
|
26165
|
-
const nulls = values.filter((v) => v === null).length;
|
|
26166
|
-
if (con.match === "simple" && nulls > 0) continue;
|
|
26167
|
-
if (con.match === "full") {
|
|
26168
|
-
if (nulls === values.length) continue;
|
|
26169
|
-
if (nulls > 0) {
|
|
26170
|
-
throw pgError(
|
|
26171
|
-
"constraint_foreign_key",
|
|
26172
|
-
`insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
|
|
26173
|
-
"23503"
|
|
26174
|
-
);
|
|
26175
|
-
}
|
|
26176
|
-
}
|
|
26177
|
-
const refTable = state.schemas.get(con.refSchema)?.tables.get(con.refTable);
|
|
26178
|
-
if (!refTable) {
|
|
26179
|
-
throw pgError("undefined_table", `relation "${con.refSchema}.${con.refTable}" does not exist`, "42P01");
|
|
26180
|
-
}
|
|
26181
|
-
const refIdxs = con.refColumns.map((c) => refTable.columnIndex(c));
|
|
26182
|
-
const keyTypes = con.refColumns.map((_c, i) => refTable.columns[refIdxs[i]].type.id);
|
|
26183
|
-
const wanted = values.map((v, i) => {
|
|
26184
|
-
const localT = table.columns[table.columnIndex(con.columns[i])].type.id;
|
|
26185
|
-
const cast = castTo(env.ctx, tv(localT, v), keyTypes[i], {});
|
|
26186
|
-
return cast.v === null ? "\0N" : datumKey(keyTypes[i], cast.v);
|
|
26187
|
-
}).join("");
|
|
26188
|
-
let found = false;
|
|
26189
|
-
for (let i = 0; i < refTable.rowCount(); i++) {
|
|
26190
|
-
const r = refTable.rowAt(i);
|
|
26191
|
-
const key = refIdxs.map((ri, j) => {
|
|
26192
|
-
const v = r[ri] ?? null;
|
|
26193
|
-
return v === null ? "\0N" : datumKey(keyTypes[j], v);
|
|
26194
|
-
}).join("");
|
|
26195
|
-
if (key === wanted) {
|
|
26196
|
-
found = true;
|
|
26197
|
-
break;
|
|
26198
|
-
}
|
|
26199
|
-
}
|
|
26200
|
-
if (!found) {
|
|
26201
|
-
throw pgError(
|
|
26202
|
-
"constraint_foreign_key",
|
|
26203
|
-
`insert or update on table "${table.name}" violates foreign key constraint "${con.name}"`,
|
|
26204
|
-
"23503"
|
|
26205
|
-
);
|
|
26245
|
+
}
|
|
26246
|
+
function executeSelectStmt(env0, stmt) {
|
|
26247
|
+
const env = applyWith(env0, stmt.with);
|
|
26248
|
+
let rel3;
|
|
26249
|
+
if (stmt.body.type === "select_core") {
|
|
26250
|
+
rel3 = executeCore(env, stmt.body, stmt.orderBy, { hasLimit: stmt.limit !== null });
|
|
26251
|
+
} else {
|
|
26252
|
+
rel3 = executeBody(env, stmt.body);
|
|
26253
|
+
const specs = outputOrderSpecs(env, rel3, stmt.orderBy);
|
|
26254
|
+
if (specs.length > 0) sortRows(env, rel3, specs);
|
|
26255
|
+
rel3 = stripHidden(rel3);
|
|
26256
|
+
}
|
|
26257
|
+
if (stmt.limitWithTies) {
|
|
26258
|
+
if (stmt.orderBy.length === 0) {
|
|
26259
|
+
throw pgError("syntax", "WITH TIES cannot be specified without ORDER BY clause", "42601");
|
|
26206
26260
|
}
|
|
26261
|
+
const tieSpecs = outputOrderSpecs(env, rel3, stmt.orderBy);
|
|
26262
|
+
return stripHidden(applyLimitOffset(env, rel3, stmt.limit, stmt.offset, tieSpecs));
|
|
26207
26263
|
}
|
|
26264
|
+
return applyLimitOffset(env, rel3, stmt.limit, stmt.offset);
|
|
26208
26265
|
}
|
|
26209
|
-
|
|
26210
|
-
|
|
26211
|
-
|
|
26212
|
-
|
|
26213
|
-
|
|
26214
|
-
|
|
26215
|
-
|
|
26216
|
-
|
|
26217
|
-
|
|
26266
|
+
|
|
26267
|
+
// src/executor/triggers-scope.ts
|
|
26268
|
+
function triggerScope(table, newRow, oldRow) {
|
|
26269
|
+
const cols = [];
|
|
26270
|
+
const row = [];
|
|
26271
|
+
const rangeVars = /* @__PURE__ */ new Set();
|
|
26272
|
+
if (newRow) {
|
|
26273
|
+
rangeVars.add("new");
|
|
26274
|
+
for (let i = 0; i < table.columns.length; i++) {
|
|
26275
|
+
cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
|
|
26276
|
+
row.push(newRow[i] ?? null);
|
|
26218
26277
|
}
|
|
26219
26278
|
}
|
|
26220
|
-
|
|
26279
|
+
if (oldRow) {
|
|
26280
|
+
rangeVars.add("old");
|
|
26281
|
+
for (let i = 0; i < table.columns.length; i++) {
|
|
26282
|
+
cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
|
|
26283
|
+
row.push(oldRow[i] ?? null);
|
|
26284
|
+
}
|
|
26285
|
+
}
|
|
26286
|
+
return new RowScope(cols, row, null, rangeVars);
|
|
26221
26287
|
}
|
|
26222
26288
|
|
|
26223
26289
|
// src/executor/triggers.ts
|
|
@@ -26233,6 +26299,18 @@ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
|
|
|
26233
26299
|
for (const t of table.triggers) {
|
|
26234
26300
|
if (t.timing !== timing || !matches(t, event) || !t.forEachRow) continue;
|
|
26235
26301
|
if (!executor) throw unsupported(`trigger "${t.name}" execution`);
|
|
26302
|
+
if (t.constraint && timing === "after") {
|
|
26303
|
+
if (t.when && !evalPredicate(env, triggerScope(table, newRow, oldRow), t.when)) continue;
|
|
26304
|
+
env.ctx.state.pendingTriggers.push({
|
|
26305
|
+
schema: table.schema,
|
|
26306
|
+
table: table.name,
|
|
26307
|
+
trigger: t.name,
|
|
26308
|
+
event,
|
|
26309
|
+
oldRow: oldRow?.slice() ?? null,
|
|
26310
|
+
newRow: newRow?.slice() ?? null
|
|
26311
|
+
});
|
|
26312
|
+
continue;
|
|
26313
|
+
}
|
|
26236
26314
|
const result = executor(env, table, t, event, oldRow, timing === "before" ? row : newRow);
|
|
26237
26315
|
if (timing === "before") {
|
|
26238
26316
|
if (result === null) return { row: null };
|
|
@@ -26241,6 +26319,167 @@ function fireRowTriggers(env, table, timing, event, oldRow, newRow) {
|
|
|
26241
26319
|
}
|
|
26242
26320
|
return { row };
|
|
26243
26321
|
}
|
|
26322
|
+
var keyOf = (schema, name2) => JSON.stringify([schema, name2]);
|
|
26323
|
+
function flushConstraintTriggers(state, all = false) {
|
|
26324
|
+
const env = { ctx: new EngineCtx(state), params: null, ctes: /* @__PURE__ */ new Map(), outer: null };
|
|
26325
|
+
for (let i = 0; i < state.pendingTriggers.length; ) {
|
|
26326
|
+
const pending2 = state.pendingTriggers[i];
|
|
26327
|
+
const table = state.schemas.get(pending2.schema)?.tables.get(pending2.table);
|
|
26328
|
+
const trigger = table?.triggers.find((t) => t.name === pending2.trigger);
|
|
26329
|
+
if (!table || !trigger) {
|
|
26330
|
+
state.pendingTriggers.splice(i, 1);
|
|
26331
|
+
continue;
|
|
26332
|
+
}
|
|
26333
|
+
const deferred = trigger.deferrable && (state.constraintModes.get(keyOf(table.schema, trigger.name)) ?? trigger.initiallyDeferred);
|
|
26334
|
+
if (!all && state.inTransaction && deferred) {
|
|
26335
|
+
i++;
|
|
26336
|
+
continue;
|
|
26337
|
+
}
|
|
26338
|
+
if (!executor) throw unsupported(`trigger "${trigger.name}" execution`);
|
|
26339
|
+
state.pendingTriggers.splice(i, 1);
|
|
26340
|
+
const changes = state.changes;
|
|
26341
|
+
try {
|
|
26342
|
+
executor(env, table, { ...trigger, when: null }, pending2.event, pending2.oldRow, pending2.newRow);
|
|
26343
|
+
} catch (error) {
|
|
26344
|
+
state.pendingTriggers.splice(i, 0, pending2);
|
|
26345
|
+
throw error;
|
|
26346
|
+
} finally {
|
|
26347
|
+
state.changes = changes;
|
|
26348
|
+
}
|
|
26349
|
+
}
|
|
26350
|
+
}
|
|
26351
|
+
function setConstraints(state, stmt) {
|
|
26352
|
+
if (!state.inTransaction) return;
|
|
26353
|
+
const matches2 = [];
|
|
26354
|
+
if (stmt.names) {
|
|
26355
|
+
for (const name2 of stmt.names) {
|
|
26356
|
+
const schemas = name2.length > 1 ? [name2[name2.length - 2]] : state.effectiveSearchPath();
|
|
26357
|
+
let found = false;
|
|
26358
|
+
for (const schema of schemas) {
|
|
26359
|
+
const items = [...state.schemas.get(schema)?.tables.values() ?? []].flatMap(
|
|
26360
|
+
(table) => table.triggers.filter((t) => t.constraint && t.name === name2[name2.length - 1])
|
|
26361
|
+
);
|
|
26362
|
+
if (items.length) {
|
|
26363
|
+
for (const trigger of items) matches2.push({ schema, trigger });
|
|
26364
|
+
found = true;
|
|
26365
|
+
break;
|
|
26366
|
+
}
|
|
26367
|
+
}
|
|
26368
|
+
if (!found) throw pgError("undefined_object", `constraint "${name2.join(".")}" does not exist`, "42704");
|
|
26369
|
+
}
|
|
26370
|
+
} else {
|
|
26371
|
+
for (const schema of state.schemas.values())
|
|
26372
|
+
for (const table of schema.tables.values())
|
|
26373
|
+
for (const trigger of table.triggers)
|
|
26374
|
+
if (trigger.constraint && trigger.deferrable) matches2.push({ schema: schema.name, trigger });
|
|
26375
|
+
}
|
|
26376
|
+
for (const { trigger } of matches2)
|
|
26377
|
+
if (stmt.deferred && !trigger.deferrable)
|
|
26378
|
+
throw pgError("misuse", `constraint "${trigger.name}" is not deferrable`, "55000");
|
|
26379
|
+
const previous = new Map(state.constraintModes);
|
|
26380
|
+
for (const { schema, trigger } of matches2) state.constraintModes.set(keyOf(schema, trigger.name), stmt.deferred);
|
|
26381
|
+
try {
|
|
26382
|
+
if (!stmt.deferred) flushConstraintTriggers(state);
|
|
26383
|
+
} catch (error) {
|
|
26384
|
+
state.constraintModes = previous;
|
|
26385
|
+
throw error;
|
|
26386
|
+
}
|
|
26387
|
+
}
|
|
26388
|
+
|
|
26389
|
+
// src/transactions/manager.ts
|
|
26390
|
+
var TransactionManager = class {
|
|
26391
|
+
constructor(state) {
|
|
26392
|
+
this.state = state;
|
|
26393
|
+
}
|
|
26394
|
+
state;
|
|
26395
|
+
base = null;
|
|
26396
|
+
savepoints = [];
|
|
26397
|
+
freezeDepth = 0;
|
|
26398
|
+
get inTransaction() {
|
|
26399
|
+
return this.base !== null;
|
|
26400
|
+
}
|
|
26401
|
+
takeSnapshot() {
|
|
26402
|
+
this.state.freezeShared();
|
|
26403
|
+
this.freezeDepth++;
|
|
26404
|
+
return { state: this.state.cloneShallow(), prngState: this.state.prng.getState() };
|
|
26405
|
+
}
|
|
26406
|
+
restore(snap) {
|
|
26407
|
+
this.state.restoreFrom(snap.state);
|
|
26408
|
+
this.state.prng.setState(snap.prngState);
|
|
26409
|
+
}
|
|
26410
|
+
thawOnce() {
|
|
26411
|
+
if (this.freezeDepth > 0) {
|
|
26412
|
+
this.state.thawShared();
|
|
26413
|
+
this.freezeDepth--;
|
|
26414
|
+
}
|
|
26415
|
+
}
|
|
26416
|
+
begin() {
|
|
26417
|
+
if (this.base !== null) {
|
|
26418
|
+
return;
|
|
26419
|
+
}
|
|
26420
|
+
this.base = this.takeSnapshot();
|
|
26421
|
+
this.state.inTransaction = true;
|
|
26422
|
+
assert(this.freezeDepth === 1, "BEGIN freeze depth");
|
|
26423
|
+
}
|
|
26424
|
+
commit() {
|
|
26425
|
+
try {
|
|
26426
|
+
flushConstraintTriggers(this.state, true);
|
|
26427
|
+
} catch (error) {
|
|
26428
|
+
this.rollback();
|
|
26429
|
+
throw error;
|
|
26430
|
+
}
|
|
26431
|
+
this.base = null;
|
|
26432
|
+
this.savepoints = [];
|
|
26433
|
+
this.state.inTransaction = false;
|
|
26434
|
+
this.state.localSettings.clear();
|
|
26435
|
+
this.state.pendingTriggers = [];
|
|
26436
|
+
this.state.constraintModes.clear();
|
|
26437
|
+
while (this.freezeDepth > 0) this.thawOnce();
|
|
26438
|
+
}
|
|
26439
|
+
rollback() {
|
|
26440
|
+
if (this.base !== null) {
|
|
26441
|
+
this.restore(this.base);
|
|
26442
|
+
}
|
|
26443
|
+
this.base = null;
|
|
26444
|
+
this.savepoints = [];
|
|
26445
|
+
this.state.inTransaction = false;
|
|
26446
|
+
this.state.localSettings.clear();
|
|
26447
|
+
this.state.pendingTriggers = [];
|
|
26448
|
+
this.state.constraintModes.clear();
|
|
26449
|
+
while (this.freezeDepth > 0) this.thawOnce();
|
|
26450
|
+
}
|
|
26451
|
+
savepoint(name2) {
|
|
26452
|
+
if (this.base === null) {
|
|
26453
|
+
throw pgError("transaction_state", "SAVEPOINT can only be used in transaction blocks", "25P01");
|
|
26454
|
+
}
|
|
26455
|
+
this.savepoints.push({ name: name2, snap: this.takeSnapshot() });
|
|
26456
|
+
}
|
|
26457
|
+
releaseSavepoint(name2) {
|
|
26458
|
+
const idx = this.findSavepoint(name2);
|
|
26459
|
+
this.savepoints.splice(idx);
|
|
26460
|
+
}
|
|
26461
|
+
rollbackToSavepoint(name2) {
|
|
26462
|
+
const idx = this.findSavepoint(name2);
|
|
26463
|
+
const sp = this.savepoints[idx];
|
|
26464
|
+
this.restore(sp.snap);
|
|
26465
|
+
this.savepoints.splice(idx + 1);
|
|
26466
|
+
}
|
|
26467
|
+
findSavepoint(name2) {
|
|
26468
|
+
if (this.base === null) {
|
|
26469
|
+
throw pgError("transaction_state", `SAVEPOINT can only be used in transaction blocks`, "25P01");
|
|
26470
|
+
}
|
|
26471
|
+
for (let i = this.savepoints.length - 1; i >= 0; i--) {
|
|
26472
|
+
if (this.savepoints[i].name === name2) return i;
|
|
26473
|
+
}
|
|
26474
|
+
throw pgError("invalid_savepoint_specification", `savepoint "${name2}" does not exist`, "3B001");
|
|
26475
|
+
}
|
|
26476
|
+
reset() {
|
|
26477
|
+
this.base = null;
|
|
26478
|
+
this.savepoints = [];
|
|
26479
|
+
this.state.inTransaction = false;
|
|
26480
|
+
this.freezeDepth = 0;
|
|
26481
|
+
}
|
|
26482
|
+
};
|
|
26244
26483
|
|
|
26245
26484
|
// src/executor/dml.ts
|
|
26246
26485
|
function withStatementRollback(env, fn) {
|
|
@@ -26930,6 +27169,7 @@ function executeSet(env, stmt) {
|
|
|
26930
27169
|
else target.delete(name2);
|
|
26931
27170
|
return commandResult("SET", 0);
|
|
26932
27171
|
}
|
|
27172
|
+
validateStorageSetting(name2, stmt.value);
|
|
26933
27173
|
target.set(name2, stmt.value);
|
|
26934
27174
|
return commandResult("SET", 0);
|
|
26935
27175
|
}
|
|
@@ -27235,64 +27475,6 @@ function executeCopyFromData(env, stmt, data) {
|
|
|
27235
27475
|
};
|
|
27236
27476
|
}
|
|
27237
27477
|
|
|
27238
|
-
// src/expressions/context.ts
|
|
27239
|
-
var EngineCtx = class {
|
|
27240
|
-
state;
|
|
27241
|
-
/** transaction timestamp (now(), current_timestamp) — UTC micros since PG epoch */
|
|
27242
|
-
txNow;
|
|
27243
|
-
/** statement timestamp */
|
|
27244
|
-
stmtNow;
|
|
27245
|
-
constructor(state, txNow) {
|
|
27246
|
-
this.state = state;
|
|
27247
|
-
const nowMs = state.clock().getTime();
|
|
27248
|
-
const nowMicros = BigInt(Math.round(nowMs)) * 1000n + UNIX_EPOCH_MICROS_FROM_PG;
|
|
27249
|
-
this.txNow = txNow ?? nowMicros;
|
|
27250
|
-
this.stmtNow = nowMicros;
|
|
27251
|
-
}
|
|
27252
|
-
timezone() {
|
|
27253
|
-
return this.state.getSetting("timezone") ?? "UTC";
|
|
27254
|
-
}
|
|
27255
|
-
namespaceOid(name2) {
|
|
27256
|
-
const oid = builtinNamespaceOid(name2) ?? this.state.schemas.get(name2)?.oid;
|
|
27257
|
-
if (oid === void 0) throw pgError("undefined_object", `schema "${name2}" does not exist`, "3F000");
|
|
27258
|
-
return oid;
|
|
27259
|
-
}
|
|
27260
|
-
namespaceName(oid) {
|
|
27261
|
-
const builtin = builtinNamespaceName(oid);
|
|
27262
|
-
if (builtin !== void 0) return builtin;
|
|
27263
|
-
for (const schema of this.state.schemas.values()) {
|
|
27264
|
-
if (schema.oid === oid) return schema.name;
|
|
27265
|
-
}
|
|
27266
|
-
return null;
|
|
27267
|
-
}
|
|
27268
|
-
zoneOffsetAt(utcMicros) {
|
|
27269
|
-
return zoneOffsetAtUtc(this.timezone(), utcMicros);
|
|
27270
|
-
}
|
|
27271
|
-
zoneOffsetForNaive(naiveMicros) {
|
|
27272
|
-
return zoneOffsetForNaive(this.timezone(), naiveMicros);
|
|
27273
|
-
}
|
|
27274
|
-
enumLabels(enumType) {
|
|
27275
|
-
if (!isEnumType(enumType)) return null;
|
|
27276
|
-
const e = this.state.findEnumByKey(enumType.slice(5));
|
|
27277
|
-
return e?.labels ?? null;
|
|
27278
|
-
}
|
|
27279
|
-
enumHasLabel(enumType, label) {
|
|
27280
|
-
const labels = this.enumLabels(enumType);
|
|
27281
|
-
return labels === null ? true : labels.includes(label);
|
|
27282
|
-
}
|
|
27283
|
-
enumOrder(enumType, label) {
|
|
27284
|
-
const labels = this.enumLabels(enumType);
|
|
27285
|
-
if (!labels) return 0;
|
|
27286
|
-
const idx = labels.indexOf(label);
|
|
27287
|
-
return idx === -1 ? labels.length : idx;
|
|
27288
|
-
}
|
|
27289
|
-
requireEnum(enumType) {
|
|
27290
|
-
const labels = this.enumLabels(enumType);
|
|
27291
|
-
if (!labels) throw pgError("undefined_object", `type "${enumType.slice(5)}" does not exist`);
|
|
27292
|
-
return labels;
|
|
27293
|
-
}
|
|
27294
|
-
};
|
|
27295
|
-
|
|
27296
27478
|
// src/runtime/clock.ts
|
|
27297
27479
|
var DEFAULT_NOW = /* @__PURE__ */ new Date("2000-01-01T00:00:00.000Z");
|
|
27298
27480
|
function fixedClock(instant = DEFAULT_NOW) {
|
|
@@ -28260,7 +28442,7 @@ function pgClass(ctx) {
|
|
|
28260
28442
|
v.materialized ? "m" : "v",
|
|
28261
28443
|
v.columns?.length ?? 0,
|
|
28262
28444
|
v.matRows?.length ?? 0,
|
|
28263
|
-
|
|
28445
|
+
v.materialized && [...schemaData.indexes.values()].some((i) => i.tableOid === v.oid),
|
|
28264
28446
|
!v.materialized || v.matRows !== null,
|
|
28265
28447
|
relPersistence(v)
|
|
28266
28448
|
);
|
|
@@ -28526,7 +28708,7 @@ function pgIndex(ctx) {
|
|
|
28526
28708
|
const valid = i.valid !== false;
|
|
28527
28709
|
rows.push([
|
|
28528
28710
|
i.oid ?? 0,
|
|
28529
|
-
table?.oid ?? 0,
|
|
28711
|
+
table?.oid ?? i.tableOid ?? 0,
|
|
28530
28712
|
indexAttributeCount(i),
|
|
28531
28713
|
i.columns.length,
|
|
28532
28714
|
i.unique,
|
|
@@ -28698,7 +28880,7 @@ function pgStatUserIndexes(ctx) {
|
|
|
28698
28880
|
for (const index of schema.indexes.values()) {
|
|
28699
28881
|
const table = schema.tables.get(index.table);
|
|
28700
28882
|
rows.push([
|
|
28701
|
-
table?.oid ?? 0,
|
|
28883
|
+
table?.oid ?? index.tableOid ?? 0,
|
|
28702
28884
|
index.oid ?? 0,
|
|
28703
28885
|
schema.name,
|
|
28704
28886
|
index.table,
|
|
@@ -29293,26 +29475,6 @@ function runTriggerBody(env, table, stmts, vars) {
|
|
|
29293
29475
|
}
|
|
29294
29476
|
}
|
|
29295
29477
|
}
|
|
29296
|
-
function triggerScope(table, newRow, oldRow) {
|
|
29297
|
-
const cols = [];
|
|
29298
|
-
const row = [];
|
|
29299
|
-
const rangeVars = /* @__PURE__ */ new Set();
|
|
29300
|
-
if (newRow) {
|
|
29301
|
-
rangeVars.add("new");
|
|
29302
|
-
for (let i = 0; i < table.columns.length; i++) {
|
|
29303
|
-
cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "new" });
|
|
29304
|
-
row.push(newRow[i] ?? null);
|
|
29305
|
-
}
|
|
29306
|
-
}
|
|
29307
|
-
if (oldRow) {
|
|
29308
|
-
rangeVars.add("old");
|
|
29309
|
-
for (let i = 0; i < table.columns.length; i++) {
|
|
29310
|
-
cols.push({ name: table.columns[i].name, type: table.columns[i].type.id, table: "old" });
|
|
29311
|
-
row.push(oldRow[i] ?? null);
|
|
29312
|
-
}
|
|
29313
|
-
}
|
|
29314
|
-
return new RowScope(cols, row, null, rangeVars);
|
|
29315
|
-
}
|
|
29316
29478
|
function executeTrigger(env, table, trigger, _event, oldRow, newRow) {
|
|
29317
29479
|
const state = env.ctx.state;
|
|
29318
29480
|
if (trigger.when !== null && !evalPredicate(env, triggerScope(table, newRow, oldRow), trigger.when)) {
|
|
@@ -30282,7 +30444,8 @@ function executeCreateTableAs(env, stmt) {
|
|
|
30282
30444
|
}
|
|
30283
30445
|
function executeCreateIndex(env, stmt) {
|
|
30284
30446
|
const state = env.ctx.state;
|
|
30285
|
-
const
|
|
30447
|
+
const view = state.findView(stmt.table);
|
|
30448
|
+
const table = state.findTable(stmt.table) ?? (view?.materialized ? materializedTable(view) : void 0);
|
|
30286
30449
|
if (!table) {
|
|
30287
30450
|
throw pgError("undefined_table", `relation "${stmt.table.join(".")}" does not exist`, "42P01");
|
|
30288
30451
|
}
|
|
@@ -30394,13 +30557,22 @@ function executeRefreshMatView(env, stmt) {
|
|
|
30394
30557
|
if (!found?.materialized) {
|
|
30395
30558
|
throw pgError("undefined_table", `materialized view "${stmt.name.join(".")}" does not exist`, "42P01");
|
|
30396
30559
|
}
|
|
30560
|
+
const rel3 = executeSelectStmt(matviewQueryEnv(env, !stmt.withData), found.query);
|
|
30561
|
+
const next = {
|
|
30562
|
+
...found,
|
|
30563
|
+
matColumns: rel3.columns.map((c, i) => ({
|
|
30564
|
+
name: found.columns?.[i] ?? c.name,
|
|
30565
|
+
type: c.type === UNKNOWN ? "text" : c.type
|
|
30566
|
+
})),
|
|
30567
|
+
matRows: stmt.withData ? rel3.rows : null
|
|
30568
|
+
};
|
|
30569
|
+
const table = materializedTable(next);
|
|
30570
|
+
for (const index of env.ctx.state.getSchema(found.schema).indexes.values()) {
|
|
30571
|
+
if (index.tableOid === found.oid && index.valid !== false) assertUniqueIndexBuildable(env, table, index);
|
|
30572
|
+
}
|
|
30397
30573
|
const view = env.ctx.state.ensureWritableView(found);
|
|
30398
|
-
|
|
30399
|
-
view.
|
|
30400
|
-
name: view.columns?.[i] ?? c.name,
|
|
30401
|
-
type: c.type === UNKNOWN ? "text" : c.type
|
|
30402
|
-
}));
|
|
30403
|
-
view.matRows = stmt.withData ? rel3.rows : null;
|
|
30574
|
+
view.matColumns = next.matColumns;
|
|
30575
|
+
view.matRows = next.matRows;
|
|
30404
30576
|
return commandResult("REFRESH MATERIALIZED VIEW", 0);
|
|
30405
30577
|
}
|
|
30406
30578
|
function executeCreateSchema(env, stmt) {
|
|
@@ -30542,6 +30714,8 @@ function executeCreateFunction(env, stmt) {
|
|
|
30542
30714
|
return commandResult("CREATE FUNCTION", 0);
|
|
30543
30715
|
}
|
|
30544
30716
|
function executeCreateTrigger(env, stmt) {
|
|
30717
|
+
if (stmt.constraint && (stmt.timing !== "after" || !stmt.forEachRow))
|
|
30718
|
+
throw pgError("syntax", "constraint triggers must be AFTER ROW triggers", "42601");
|
|
30545
30719
|
const state = env.ctx.state;
|
|
30546
30720
|
const found = state.findTable(stmt.table);
|
|
30547
30721
|
if (!found) {
|
|
@@ -30560,6 +30734,9 @@ function executeCreateTrigger(env, stmt) {
|
|
|
30560
30734
|
}
|
|
30561
30735
|
const meta = {
|
|
30562
30736
|
name: stmt.name,
|
|
30737
|
+
constraint: stmt.constraint,
|
|
30738
|
+
deferrable: stmt.deferrable,
|
|
30739
|
+
initiallyDeferred: stmt.initiallyDeferred,
|
|
30563
30740
|
timing: stmt.timing,
|
|
30564
30741
|
events: stmt.events,
|
|
30565
30742
|
forEachRow: stmt.forEachRow,
|
|
@@ -31328,7 +31505,16 @@ function alterTableIsSelfContained(stmt) {
|
|
|
31328
31505
|
return stmt.actions.length === 1 && action !== void 0 && SELF_CONTAINED_ALTER_ACTIONS.has(action.kind);
|
|
31329
31506
|
}
|
|
31330
31507
|
function executeStatement(env, stmt) {
|
|
31331
|
-
if (!RESHAPES_TABLES.has(stmt.type))
|
|
31508
|
+
if (!RESHAPES_TABLES.has(stmt.type)) {
|
|
31509
|
+
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))) {
|
|
31510
|
+
return withStatementRollback(env, () => {
|
|
31511
|
+
const result = dispatchStatement(env, stmt);
|
|
31512
|
+
flushConstraintTriggers(env.ctx.state);
|
|
31513
|
+
return result;
|
|
31514
|
+
});
|
|
31515
|
+
}
|
|
31516
|
+
return dispatchStatement(env, stmt);
|
|
31517
|
+
}
|
|
31332
31518
|
try {
|
|
31333
31519
|
return dispatchStatement(env, stmt);
|
|
31334
31520
|
} finally {
|
|
@@ -31387,6 +31573,9 @@ function dispatchStatement(env, stmt) {
|
|
|
31387
31573
|
return executeRefreshMatView(env, stmt);
|
|
31388
31574
|
case "transaction":
|
|
31389
31575
|
return executeTransaction(env, stmt);
|
|
31576
|
+
case "set_constraints":
|
|
31577
|
+
setConstraints(env.ctx.state, stmt);
|
|
31578
|
+
return commandResult("SET CONSTRAINTS", 0);
|
|
31390
31579
|
case "set":
|
|
31391
31580
|
return executeSet(env, stmt);
|
|
31392
31581
|
case "show":
|
|
@@ -33825,11 +34014,13 @@ var ScramServer = class {
|
|
|
33825
34014
|
var splitStatements = (script) => {
|
|
33826
34015
|
const out = [];
|
|
33827
34016
|
let start3 = 0;
|
|
34017
|
+
let hasSql = false;
|
|
33828
34018
|
let i = 0;
|
|
33829
34019
|
const n = script.length;
|
|
33830
34020
|
const push = (end) => {
|
|
33831
34021
|
const text = script.slice(start3, end).trim();
|
|
33832
|
-
if (
|
|
34022
|
+
if (hasSql) out.push(text);
|
|
34023
|
+
hasSql = false;
|
|
33833
34024
|
};
|
|
33834
34025
|
while (i < n) {
|
|
33835
34026
|
const c = script[i];
|
|
@@ -33851,9 +34042,11 @@ var splitStatements = (script) => {
|
|
|
33851
34042
|
i += 2;
|
|
33852
34043
|
} else i++;
|
|
33853
34044
|
}
|
|
34045
|
+
if (depth > 0) hasSql = true;
|
|
33854
34046
|
continue;
|
|
33855
34047
|
}
|
|
33856
34048
|
if (c === "'" || c === '"') {
|
|
34049
|
+
hasSql = true;
|
|
33857
34050
|
const escaped = c === "'" && /[eE]/.test(script[i - 1] ?? "") && !/[\w$]/.test(script[i - 2] ?? "");
|
|
33858
34051
|
i++;
|
|
33859
34052
|
while (i < n) {
|
|
@@ -33876,6 +34069,7 @@ var splitStatements = (script) => {
|
|
|
33876
34069
|
if (c === "$") {
|
|
33877
34070
|
const m = /^\$([A-Za-z_][A-Za-z0-9_]*)?\$/.exec(script.slice(i, i + 64));
|
|
33878
34071
|
if (m) {
|
|
34072
|
+
hasSql = true;
|
|
33879
34073
|
const tag = m[0];
|
|
33880
34074
|
const end = script.indexOf(tag, i + tag.length);
|
|
33881
34075
|
i = end === -1 ? n : end + tag.length;
|
|
@@ -33886,6 +34080,7 @@ var splitStatements = (script) => {
|
|
|
33886
34080
|
push(i);
|
|
33887
34081
|
start3 = i + 1;
|
|
33888
34082
|
}
|
|
34083
|
+
if (c !== ";" && !/\s/.test(c)) hasSql = true;
|
|
33889
34084
|
i++;
|
|
33890
34085
|
}
|
|
33891
34086
|
push(n);
|
|
@@ -34318,7 +34513,16 @@ var binaryValue = (type, text) => {
|
|
|
34318
34513
|
}
|
|
34319
34514
|
};
|
|
34320
34515
|
var binaryEncodable = (type) => TEXT_TYPES2.has(type) || ["bool", "int2", "int4", "oid", "int8", "float4", "float8", "bytea", "uuid"].includes(type);
|
|
34321
|
-
var
|
|
34516
|
+
var setsSessionConfig = (node) => {
|
|
34517
|
+
if (Array.isArray(node)) return node.some(setsSessionConfig);
|
|
34518
|
+
if (typeof node !== "object" || node === null) return false;
|
|
34519
|
+
const call = node;
|
|
34520
|
+
if (call.type === "func" && call.name?.at(-1) === "set_config") return true;
|
|
34521
|
+
return Object.values(node).some(setsSessionConfig);
|
|
34522
|
+
};
|
|
34523
|
+
var mutatesDatabase = (sql) => parse(sql).some(
|
|
34524
|
+
(stmt) => !["select", "show", "explain", "transaction", "no_op"].includes(stmt.type) || stmt.type === "select" && setsSessionConfig(stmt)
|
|
34525
|
+
);
|
|
34322
34526
|
var NEVER_WRITES = /* @__PURE__ */ new Set(["show", "set", "reset", "transaction", "no_op", "prepare", "deallocate"]);
|
|
34323
34527
|
var WRITE_NODES = /* @__PURE__ */ new Set(["insert", "update", "delete"]);
|
|
34324
34528
|
var containsWrite = (db, node) => {
|
|
@@ -34943,6 +35147,7 @@ var Connection = class {
|
|
|
34943
35147
|
}
|
|
34944
35148
|
return outcome;
|
|
34945
35149
|
} finally {
|
|
35150
|
+
workspace?.transactions.rollback();
|
|
34946
35151
|
workspace?.close();
|
|
34947
35152
|
}
|
|
34948
35153
|
}
|
|
@@ -35017,8 +35222,9 @@ var Connection = class {
|
|
|
35017
35222
|
});
|
|
35018
35223
|
workspace.state.settings = new Map(this.settings);
|
|
35019
35224
|
workspace.state.settingDefaults = this.settingDefaults;
|
|
35225
|
+
workspace.transactions.begin();
|
|
35020
35226
|
for (const logged of this.transaction?.statements ?? []) {
|
|
35021
|
-
|
|
35227
|
+
this.replay(workspace, logged);
|
|
35022
35228
|
}
|
|
35023
35229
|
return workspace;
|
|
35024
35230
|
}
|