@crvouga/postgres-mem 1.1.0 → 1.1.2
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/AGENTS.md +1 -1
- package/README.md +3 -2
- package/compat/divergences.json +0 -7
- package/compat/sections/par.ts +1 -8
- package/compat/unsupported-register.json +0 -1
- package/dist/executor/plpgsql.d.ts +3 -0
- package/dist/executor/select.d.ts +4 -2
- package/dist/expressions/eval.d.ts +4 -0
- package/dist/index.js +616 -118
- package/dist/index.js.map +3 -3
- package/dist/sql/deparse.d.ts +3 -0
- package/dist/storage/database-state.d.ts +2 -0
- package/dist/types/jsonb.d.ts +3 -1
- package/dist/types/range.d.ts +17 -0
- package/dist/unstable.js +524 -116
- package/dist/unstable.js.map +3 -3
- package/package.json +5 -3
package/dist/unstable.js
CHANGED
|
@@ -1441,11 +1441,12 @@ function jsonbCompare(a, b) {
|
|
|
1441
1441
|
return assertNever(a);
|
|
1442
1442
|
}
|
|
1443
1443
|
}
|
|
1444
|
-
function jsonbContains(a, b) {
|
|
1444
|
+
function jsonbContains(a, b, opts) {
|
|
1445
|
+
const allowScalarInArray = opts?.allowScalarInArray ?? true;
|
|
1445
1446
|
if (a.j === "obj" && b.j === "obj") {
|
|
1446
1447
|
for (const [k, bv] of b.v) {
|
|
1447
1448
|
const av = a.v.get(k);
|
|
1448
|
-
if (av === void 0 || !jsonbContains(av, bv)) return false;
|
|
1449
|
+
if (av === void 0 || !jsonbContains(av, bv, { allowScalarInArray: false })) return false;
|
|
1449
1450
|
}
|
|
1450
1451
|
return true;
|
|
1451
1452
|
}
|
|
@@ -1453,7 +1454,7 @@ function jsonbContains(a, b) {
|
|
|
1453
1454
|
for (const bv of b.v) {
|
|
1454
1455
|
let found = false;
|
|
1455
1456
|
for (const av of a.v) {
|
|
1456
|
-
if (jsonbContains(av, bv)) {
|
|
1457
|
+
if (jsonbContains(av, bv, opts)) {
|
|
1457
1458
|
found = true;
|
|
1458
1459
|
break;
|
|
1459
1460
|
}
|
|
@@ -1462,7 +1463,7 @@ function jsonbContains(a, b) {
|
|
|
1462
1463
|
}
|
|
1463
1464
|
return true;
|
|
1464
1465
|
}
|
|
1465
|
-
if (a.j === "arr" && b.j !== "arr" && b.j !== "obj") {
|
|
1466
|
+
if (allowScalarInArray && a.j === "arr" && b.j !== "arr" && b.j !== "obj") {
|
|
1466
1467
|
for (const av of a.v) {
|
|
1467
1468
|
if (av.j === b.j && jsonbEquals(av, b)) return true;
|
|
1468
1469
|
}
|
|
@@ -3413,6 +3414,14 @@ function unifyTypes(a, b) {
|
|
|
3413
3414
|
|
|
3414
3415
|
// src/types/compare.ts
|
|
3415
3416
|
var DEFAULT_COMPARE_CTX = {};
|
|
3417
|
+
function expectNumber(a, t) {
|
|
3418
|
+
if (typeof a !== "number") throw pgError("internal", `invalid ${t} datum for comparison`, "XX000");
|
|
3419
|
+
return a;
|
|
3420
|
+
}
|
|
3421
|
+
function expectBigint(a, t) {
|
|
3422
|
+
if (typeof a !== "bigint") throw pgError("internal", `invalid ${t} datum for comparison`, "XX000");
|
|
3423
|
+
return a;
|
|
3424
|
+
}
|
|
3416
3425
|
function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
|
|
3417
3426
|
if (a === null || b === null) throw pgError("internal", "datumCompare called with null");
|
|
3418
3427
|
if (isArrayType(t)) return arrayCompare(t, a, b, ctx);
|
|
@@ -3427,7 +3436,7 @@ function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
|
|
|
3427
3436
|
case "int4":
|
|
3428
3437
|
case "oid":
|
|
3429
3438
|
case "date":
|
|
3430
|
-
return a - b;
|
|
3439
|
+
return expectNumber(a, t) - expectNumber(b, t);
|
|
3431
3440
|
case "float4":
|
|
3432
3441
|
case "float8": {
|
|
3433
3442
|
const fa = a;
|
|
@@ -3442,8 +3451,8 @@ function datumCompare(t, a, b, ctx = DEFAULT_COMPARE_CTX) {
|
|
|
3442
3451
|
case "timestamp":
|
|
3443
3452
|
case "timestamptz":
|
|
3444
3453
|
case "time": {
|
|
3445
|
-
const ba = a;
|
|
3446
|
-
const bb = b;
|
|
3454
|
+
const ba = expectBigint(a, t);
|
|
3455
|
+
const bb = expectBigint(b, t);
|
|
3447
3456
|
return ba < bb ? -1 : ba > bb ? 1 : 0;
|
|
3448
3457
|
}
|
|
3449
3458
|
case "numeric":
|
|
@@ -3758,6 +3767,7 @@ function getJsonFunctions() {
|
|
|
3758
3767
|
});
|
|
3759
3768
|
m.set("json_typeof", typeofFn);
|
|
3760
3769
|
m.set("jsonb_typeof", typeofFn);
|
|
3770
|
+
const jsonpathArg = (ctx, arg) => arg.t === "jsonpath" ? arg.v : argText(ctx, arg);
|
|
3761
3771
|
m.set("jsonb_path_query_first", (ctx, args) => {
|
|
3762
3772
|
if (args.length < 2) {
|
|
3763
3773
|
throw pgError(
|
|
@@ -3768,11 +3778,22 @@ function getJsonFunctions() {
|
|
|
3768
3778
|
}
|
|
3769
3779
|
if (args[0].v === null || args[1].v === null) return tv("jsonb", null);
|
|
3770
3780
|
const doc = jsonArg(ctx, args[0]);
|
|
3771
|
-
const
|
|
3772
|
-
const found = jsonpathQueryFirst(doc, path);
|
|
3781
|
+
const found = jsonpathQueryFirst(doc, jsonpathArg(ctx, args[1]));
|
|
3773
3782
|
if (found === null) return tv("jsonb", null);
|
|
3774
3783
|
return outJsonb(found);
|
|
3775
3784
|
});
|
|
3785
|
+
m.set("jsonb_path_exists", (ctx, args) => {
|
|
3786
|
+
if (args.length < 2) {
|
|
3787
|
+
throw pgError(
|
|
3788
|
+
"undefined_function",
|
|
3789
|
+
`function jsonb_path_exists(${args.map((a) => a.t).join(", ")}) does not exist`,
|
|
3790
|
+
"42883"
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3793
|
+
if (args[0].v === null || args[1].v === null) return tv("bool", null);
|
|
3794
|
+
const doc = jsonArg(ctx, args[0]);
|
|
3795
|
+
return tv("bool", jsonpathQueryFirst(doc, jsonpathArg(ctx, args[1])) !== null);
|
|
3796
|
+
});
|
|
3776
3797
|
m.set(
|
|
3777
3798
|
"json_array_length",
|
|
3778
3799
|
strict("int4", (ctx, args) => {
|
|
@@ -6538,6 +6559,18 @@ function parseQualifiedName(name) {
|
|
|
6538
6559
|
parts.push(current);
|
|
6539
6560
|
return parts.map((p) => p.trim()).filter((p) => p.length > 0);
|
|
6540
6561
|
}
|
|
6562
|
+
function sequenceSessionKey(seq) {
|
|
6563
|
+
return `${seq.schema}\0${seq.name}`;
|
|
6564
|
+
}
|
|
6565
|
+
function markSessionCurrval(ctx, seq, value) {
|
|
6566
|
+
ctx.state.sequenceCurrval.set(sequenceSessionKey(seq), value);
|
|
6567
|
+
}
|
|
6568
|
+
function sessionCurrvalDefined(ctx, seq) {
|
|
6569
|
+
return ctx.state.sequenceCurrval.has(sequenceSessionKey(seq));
|
|
6570
|
+
}
|
|
6571
|
+
function readSessionCurrval(ctx, seq) {
|
|
6572
|
+
return ctx.state.sequenceCurrval.get(sequenceSessionKey(seq));
|
|
6573
|
+
}
|
|
6541
6574
|
function sequenceNextval(ctx, seq) {
|
|
6542
6575
|
seq = ctx.state.ensureWritableSequence(seq);
|
|
6543
6576
|
let next;
|
|
@@ -6567,6 +6600,7 @@ function sequenceNextval(ctx, seq) {
|
|
|
6567
6600
|
}
|
|
6568
6601
|
seq.lastValue = next;
|
|
6569
6602
|
seq.isCalled = true;
|
|
6603
|
+
markSessionCurrval(ctx, seq, next);
|
|
6570
6604
|
ctx.state.lastSequence = { schema: seq.schema, name: seq.name };
|
|
6571
6605
|
return next;
|
|
6572
6606
|
}
|
|
@@ -6642,14 +6676,14 @@ function getMiscFunctions() {
|
|
|
6642
6676
|
"currval",
|
|
6643
6677
|
strict("int8", (ctx, args) => {
|
|
6644
6678
|
const seq = findSequenceForCall(ctx, argText(ctx, args[0]));
|
|
6645
|
-
if (!seq
|
|
6679
|
+
if (!sessionCurrvalDefined(ctx, seq)) {
|
|
6646
6680
|
throw pgError(
|
|
6647
6681
|
"object_not_in_prerequisite_state",
|
|
6648
6682
|
`currval of sequence "${seq.name}" is not yet defined in this session`,
|
|
6649
6683
|
"55000"
|
|
6650
6684
|
);
|
|
6651
6685
|
}
|
|
6652
|
-
return tv("int8", seq
|
|
6686
|
+
return tv("int8", readSessionCurrval(ctx, seq));
|
|
6653
6687
|
})
|
|
6654
6688
|
);
|
|
6655
6689
|
m.set("lastval", (ctx) => {
|
|
@@ -6658,10 +6692,10 @@ function getMiscFunctions() {
|
|
|
6658
6692
|
throw pgError("object_not_in_prerequisite_state", "lastval is not yet defined in this session", "55000");
|
|
6659
6693
|
}
|
|
6660
6694
|
const seq = ctx.state.findSequence([last.schema, last.name]);
|
|
6661
|
-
if (!seq
|
|
6695
|
+
if (!seq || !sessionCurrvalDefined(ctx, seq)) {
|
|
6662
6696
|
throw pgError("object_not_in_prerequisite_state", "lastval is not yet defined in this session", "55000");
|
|
6663
6697
|
}
|
|
6664
|
-
return tv("int8", seq
|
|
6698
|
+
return tv("int8", readSessionCurrval(ctx, seq));
|
|
6665
6699
|
});
|
|
6666
6700
|
m.set(
|
|
6667
6701
|
"setval",
|
|
@@ -6678,6 +6712,7 @@ function getMiscFunctions() {
|
|
|
6678
6712
|
}
|
|
6679
6713
|
seq.lastValue = value;
|
|
6680
6714
|
seq.isCalled = isCalled;
|
|
6715
|
+
if (isCalled) markSessionCurrval(ctx, seq, value);
|
|
6681
6716
|
ctx.state.lastSequence = { schema: seq.schema, name: seq.name };
|
|
6682
6717
|
return tv("int8", value);
|
|
6683
6718
|
})
|
|
@@ -12693,7 +12728,10 @@ var Parser = class {
|
|
|
12693
12728
|
this.pos++;
|
|
12694
12729
|
const operand = this.parseUnary();
|
|
12695
12730
|
if (operand.type === "number_lit") {
|
|
12696
|
-
|
|
12731
|
+
if (t.value === "+") return operand;
|
|
12732
|
+
const raw = operand.raw;
|
|
12733
|
+
if (raw.startsWith("-")) return { type: "number_lit", raw: raw.slice(1) };
|
|
12734
|
+
return { type: "number_lit", raw: `-${raw}` };
|
|
12697
12735
|
}
|
|
12698
12736
|
return { type: "unop", op: t.value, operand };
|
|
12699
12737
|
}
|
|
@@ -14392,16 +14430,31 @@ function evalUnary(ctx, op, operand) {
|
|
|
14392
14430
|
switch (op) {
|
|
14393
14431
|
case "-": {
|
|
14394
14432
|
if (t === "unknown") throw pgError("ambiguous_function", "operator is not unique: - unknown");
|
|
14395
|
-
if (v === null) return tv(t, null);
|
|
14396
14433
|
if (t === "int2" || t === "int4") {
|
|
14434
|
+
if (v === null) return tv(t, null);
|
|
14397
14435
|
const neg = -v;
|
|
14398
14436
|
return tv(t, t === "int2" ? checkInt2(neg) : checkInt4(neg));
|
|
14399
14437
|
}
|
|
14400
|
-
if (t === "int8")
|
|
14401
|
-
|
|
14402
|
-
|
|
14403
|
-
|
|
14404
|
-
if (t === "
|
|
14438
|
+
if (t === "int8") {
|
|
14439
|
+
if (v === null) return tv(t, null);
|
|
14440
|
+
return tv(t, checkInt8(-v));
|
|
14441
|
+
}
|
|
14442
|
+
if (t === "float4" || t === "float8") {
|
|
14443
|
+
if (v === null) return tv(t, null);
|
|
14444
|
+
return tv(t, -v);
|
|
14445
|
+
}
|
|
14446
|
+
if (t === "numeric") {
|
|
14447
|
+
if (v === null) return tv(t, null);
|
|
14448
|
+
return tv(t, numericNeg(v));
|
|
14449
|
+
}
|
|
14450
|
+
if (t === "interval") {
|
|
14451
|
+
if (v === null) return tv(t, null);
|
|
14452
|
+
return tv(t, intervalNeg(v));
|
|
14453
|
+
}
|
|
14454
|
+
if (t === "money") {
|
|
14455
|
+
if (v === null) return tv(t, null);
|
|
14456
|
+
return tv(t, -v);
|
|
14457
|
+
}
|
|
14405
14458
|
throw pgError("undefined_function", `operator does not exist: - ${typeDisplayName(t)}`);
|
|
14406
14459
|
}
|
|
14407
14460
|
case "+": {
|
|
@@ -14649,21 +14702,39 @@ function boolArg(ctx, kind, v) {
|
|
|
14649
14702
|
}
|
|
14650
14703
|
return toBool(ctx, v);
|
|
14651
14704
|
}
|
|
14652
|
-
function
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
|
|
14705
|
+
function evalAsPredicate(ctx, kind, v) {
|
|
14706
|
+
return boolArg(ctx, kind, v) === true;
|
|
14707
|
+
}
|
|
14708
|
+
function checkBoolExprType(ctx, scope, e, kind) {
|
|
14709
|
+
if (e.type === "binop" && e.op === "and") {
|
|
14710
|
+
boolArg(ctx, "AND", evalExpr(ctx, scope, e.left));
|
|
14711
|
+
boolArg(ctx, "AND", evalExpr(ctx, scope, e.right));
|
|
14712
|
+
return;
|
|
14713
|
+
}
|
|
14714
|
+
if (e.type === "binop" && e.op === "or") {
|
|
14715
|
+
boolArg(ctx, "OR", evalExpr(ctx, scope, e.left));
|
|
14716
|
+
boolArg(ctx, "OR", evalExpr(ctx, scope, e.right));
|
|
14717
|
+
return;
|
|
14718
|
+
}
|
|
14719
|
+
if (e.type === "unop" && e.op === "not") {
|
|
14720
|
+
boolArg(ctx, "NOT", evalExpr(ctx, scope, e.operand));
|
|
14721
|
+
return;
|
|
14722
|
+
}
|
|
14723
|
+
if (e.type === "cast") {
|
|
14724
|
+
checkBoolExprType(ctx, scope, e.expr, kind);
|
|
14725
|
+
return;
|
|
14726
|
+
}
|
|
14727
|
+
if (e.type === "case") {
|
|
14728
|
+
validateSearchedCaseTree(ctx, scope, e);
|
|
14729
|
+
return;
|
|
14730
|
+
}
|
|
14731
|
+
const v = evalExpr(ctx, scope, e);
|
|
14732
|
+
if (v.t !== "bool" && v.t !== "unknown") {
|
|
14733
|
+
throw pgError("datatype_mismatch", `argument of ${kind} must be type boolean, not type ${typeDisplayName(v.t)}`);
|
|
14663
14734
|
}
|
|
14664
14735
|
}
|
|
14665
14736
|
function checkSkippedBoolArg(ctx, scope, kind, e) {
|
|
14666
|
-
|
|
14737
|
+
boolArg(ctx, kind, evalExpr(ctx, scope, e));
|
|
14667
14738
|
}
|
|
14668
14739
|
function evalBinaryNode(ctx, scope, op, leftE, rightE) {
|
|
14669
14740
|
if (op === "and") {
|
|
@@ -14766,7 +14837,55 @@ function applyDomainChecks(ctx, domainKey, value) {
|
|
|
14766
14837
|
}
|
|
14767
14838
|
}
|
|
14768
14839
|
}
|
|
14840
|
+
function validateSearchedCaseTree(ctx, scope, e) {
|
|
14841
|
+
if (e.operand !== null) return;
|
|
14842
|
+
for (const { when, then } of e.whens) {
|
|
14843
|
+
boolArg(ctx, "CASE/WHEN", evalExpr(ctx, scope, when));
|
|
14844
|
+
validateCaseSubExpr(ctx, scope, then);
|
|
14845
|
+
}
|
|
14846
|
+
if (e.elseExpr !== null) validateCaseSubExpr(ctx, scope, e.elseExpr);
|
|
14847
|
+
}
|
|
14848
|
+
function validateCaseSubExpr(ctx, scope, e) {
|
|
14849
|
+
switch (e.type) {
|
|
14850
|
+
case "case":
|
|
14851
|
+
validateSearchedCaseTree(ctx, scope, e);
|
|
14852
|
+
return;
|
|
14853
|
+
case "binop":
|
|
14854
|
+
if (e.op === "and") {
|
|
14855
|
+
boolArg(ctx, "AND", evalExpr(ctx, scope, e.left));
|
|
14856
|
+
boolArg(ctx, "AND", evalExpr(ctx, scope, e.right));
|
|
14857
|
+
} else if (e.op === "or") {
|
|
14858
|
+
boolArg(ctx, "OR", evalExpr(ctx, scope, e.left));
|
|
14859
|
+
boolArg(ctx, "OR", evalExpr(ctx, scope, e.right));
|
|
14860
|
+
}
|
|
14861
|
+
validateCaseSubExpr(ctx, scope, e.left);
|
|
14862
|
+
validateCaseSubExpr(ctx, scope, e.right);
|
|
14863
|
+
return;
|
|
14864
|
+
case "unop":
|
|
14865
|
+
if (e.op === "not") {
|
|
14866
|
+
boolArg(ctx, "NOT", evalExpr(ctx, scope, e.operand));
|
|
14867
|
+
}
|
|
14868
|
+
validateCaseSubExpr(ctx, scope, e.operand);
|
|
14869
|
+
return;
|
|
14870
|
+
case "cast":
|
|
14871
|
+
case "collate":
|
|
14872
|
+
validateCaseSubExpr(ctx, scope, e.expr);
|
|
14873
|
+
return;
|
|
14874
|
+
case "func":
|
|
14875
|
+
for (const arg of e.args) validateCaseSubExpr(ctx, scope, arg);
|
|
14876
|
+
return;
|
|
14877
|
+
case "row":
|
|
14878
|
+
for (const item of e.items) validateCaseSubExpr(ctx, scope, item);
|
|
14879
|
+
return;
|
|
14880
|
+
case "array_ctor":
|
|
14881
|
+
for (const item of e.items) validateCaseSubExpr(ctx, scope, item);
|
|
14882
|
+
return;
|
|
14883
|
+
default:
|
|
14884
|
+
return;
|
|
14885
|
+
}
|
|
14886
|
+
}
|
|
14769
14887
|
function evalCase(ctx, scope, e) {
|
|
14888
|
+
validateSearchedCaseTree(ctx, scope, e);
|
|
14770
14889
|
let chosen = null;
|
|
14771
14890
|
if (e.operand !== null) {
|
|
14772
14891
|
const operand = evalExpr(ctx, scope, e.operand);
|
|
@@ -14780,7 +14899,8 @@ function evalCase(ctx, scope, e) {
|
|
|
14780
14899
|
}
|
|
14781
14900
|
} else {
|
|
14782
14901
|
for (const { when, then } of e.whens) {
|
|
14783
|
-
|
|
14902
|
+
const w = evalExpr(ctx, scope, when);
|
|
14903
|
+
if (boolArg(ctx, "CASE/WHEN", w) === true) {
|
|
14784
14904
|
chosen = then;
|
|
14785
14905
|
break;
|
|
14786
14906
|
}
|
|
@@ -16117,7 +16237,14 @@ function makeEvalScope(env, scope, extras) {
|
|
|
16117
16237
|
return { type: t === UNKNOWN ? "text" : t, values: rel2.rows.map((r) => r[0] ?? null) };
|
|
16118
16238
|
},
|
|
16119
16239
|
aggValue(node) {
|
|
16120
|
-
|
|
16240
|
+
const map = extras?.aggMap;
|
|
16241
|
+
if (!map) return void 0;
|
|
16242
|
+
const direct = map.get(node);
|
|
16243
|
+
if (direct !== void 0) return direct;
|
|
16244
|
+
for (const [call, value] of map) {
|
|
16245
|
+
if (exprEq(call, node)) return value;
|
|
16246
|
+
}
|
|
16247
|
+
return void 0;
|
|
16121
16248
|
},
|
|
16122
16249
|
windowValue(node) {
|
|
16123
16250
|
if (!node.over) return void 0;
|
|
@@ -16138,11 +16265,9 @@ function makeEvalScope(env, scope, extras) {
|
|
|
16138
16265
|
function evalScalar(env, scope, e, extras) {
|
|
16139
16266
|
return evalExpr(env.ctx, makeEvalScope(env, scope, extras), e);
|
|
16140
16267
|
}
|
|
16141
|
-
function evalPredicate(env, scope, e, extras) {
|
|
16268
|
+
function evalPredicate(env, scope, e, extras, kind = "WHERE") {
|
|
16142
16269
|
const v = evalScalar(env, scope, e, extras);
|
|
16143
|
-
|
|
16144
|
-
const b = castTo(env.ctx, v, "bool", {});
|
|
16145
|
-
return b.v === true;
|
|
16270
|
+
return evalAsPredicate(env.ctx, kind, v);
|
|
16146
16271
|
}
|
|
16147
16272
|
function resolveUserFunctionForArgs(env, name, args) {
|
|
16148
16273
|
const candidates = env.ctx.state.findFunctions(name);
|
|
@@ -16768,7 +16893,7 @@ function combineJoin(env, kind, left, right, on, using, usingAlias, rangeVars, e
|
|
|
16768
16893
|
for (let i = 0; i < left.columns.length; i++) row.push(lrow[i] ?? null);
|
|
16769
16894
|
for (let i = 0; i < right.columns.length; i++) row.push(rrow[i] ?? null);
|
|
16770
16895
|
const jscope = new RowScope(columns, row, env.outer, rangeVars);
|
|
16771
|
-
return evalPredicate(env, jscope, on);
|
|
16896
|
+
return evalPredicate(env, jscope, on, void 0, "ON");
|
|
16772
16897
|
};
|
|
16773
16898
|
const useHashJoin = kind !== "cross" && hashLeftIdxs.length > 0;
|
|
16774
16899
|
if (useHashJoin) {
|
|
@@ -16883,6 +17008,11 @@ function buildFrom(env, items, where = null) {
|
|
|
16883
17008
|
}
|
|
16884
17009
|
return acc;
|
|
16885
17010
|
}
|
|
17011
|
+
function exprHasAggregateCall(e) {
|
|
17012
|
+
const collector = { aggs: [], windows: [], groupings: [] };
|
|
17013
|
+
collectCalls(e, collector);
|
|
17014
|
+
return collector.aggs.length > 0;
|
|
17015
|
+
}
|
|
16886
17016
|
function collectCalls(e, out) {
|
|
16887
17017
|
if (!e || typeof e !== "object") return;
|
|
16888
17018
|
if (e.type === "subquery_expr") return;
|
|
@@ -17024,7 +17154,192 @@ function groupDefMatches(def, e, columns) {
|
|
|
17024
17154
|
}
|
|
17025
17155
|
return exprEq(def.expr, e);
|
|
17026
17156
|
}
|
|
17027
|
-
function
|
|
17157
|
+
function groupingErrorForColref(parts, columns) {
|
|
17158
|
+
const idx = resolveColIdx(columns, parts);
|
|
17159
|
+
let label;
|
|
17160
|
+
if (idx !== null) {
|
|
17161
|
+
const c = columns[idx];
|
|
17162
|
+
label = c.table ? `${c.table}.${c.name}` : c.name;
|
|
17163
|
+
} else {
|
|
17164
|
+
label = parts.join(".");
|
|
17165
|
+
}
|
|
17166
|
+
throw pgError(
|
|
17167
|
+
"grouping_error",
|
|
17168
|
+
`column "${label}" must appear in the GROUP BY clause or be used in an aggregate function`,
|
|
17169
|
+
"42803"
|
|
17170
|
+
);
|
|
17171
|
+
}
|
|
17172
|
+
function isGroupingExpr(e, groupDefs, columns) {
|
|
17173
|
+
return groupDefs.some((d) => groupDefMatches(d, e, columns));
|
|
17174
|
+
}
|
|
17175
|
+
function validateGroupedExpr(e, groupDefs, columns, inAgg) {
|
|
17176
|
+
if (!e || typeof e !== "object") return;
|
|
17177
|
+
if (e.type === "subquery_expr") return;
|
|
17178
|
+
if (!inAgg && isGroupingExpr(e, groupDefs, columns)) return;
|
|
17179
|
+
switch (e.type) {
|
|
17180
|
+
case "null_lit":
|
|
17181
|
+
case "string_lit":
|
|
17182
|
+
case "number_lit":
|
|
17183
|
+
case "bool_lit":
|
|
17184
|
+
case "bitstring_lit":
|
|
17185
|
+
case "param":
|
|
17186
|
+
case "default_expr":
|
|
17187
|
+
return;
|
|
17188
|
+
case "colref":
|
|
17189
|
+
if (!inAgg) {
|
|
17190
|
+
if (resolveColIdx(columns, e.parts) === null) return;
|
|
17191
|
+
groupingErrorForColref(e.parts, columns);
|
|
17192
|
+
}
|
|
17193
|
+
return;
|
|
17194
|
+
case "grouping_func":
|
|
17195
|
+
for (const a of e.args) validateGroupedExpr(a, groupDefs, columns, inAgg);
|
|
17196
|
+
return;
|
|
17197
|
+
case "func": {
|
|
17198
|
+
const name = e.name[e.name.length - 1];
|
|
17199
|
+
if (e.over) {
|
|
17200
|
+
for (const a of e.args) validateGroupedExpr(a, groupDefs, columns, false);
|
|
17201
|
+
if (e.filter) validateGroupedExpr(e.filter, groupDefs, columns, false);
|
|
17202
|
+
for (const p of e.over.partitionBy ?? []) validateGroupedExpr(p, groupDefs, columns, false);
|
|
17203
|
+
for (const ob of e.over.orderBy ?? []) validateGroupedExpr(ob.expr, groupDefs, columns, false);
|
|
17204
|
+
return;
|
|
17205
|
+
}
|
|
17206
|
+
if (isAggregateName(name)) {
|
|
17207
|
+
for (const a of e.args) validateGroupedExpr(a, groupDefs, columns, true);
|
|
17208
|
+
if (e.filter) validateGroupedExpr(e.filter, groupDefs, columns, true);
|
|
17209
|
+
for (const ob of e.orderBy ?? []) validateGroupedExpr(ob.expr, groupDefs, columns, true);
|
|
17210
|
+
return;
|
|
17211
|
+
}
|
|
17212
|
+
for (const a of e.args) validateGroupedExpr(a, groupDefs, columns, inAgg);
|
|
17213
|
+
if (e.filter) validateGroupedExpr(e.filter, groupDefs, columns, inAgg);
|
|
17214
|
+
for (const ob of e.orderBy ?? []) validateGroupedExpr(ob.expr, groupDefs, columns, inAgg);
|
|
17215
|
+
return;
|
|
17216
|
+
}
|
|
17217
|
+
case "binop":
|
|
17218
|
+
validateGroupedExpr(e.left, groupDefs, columns, inAgg);
|
|
17219
|
+
validateGroupedExpr(e.right, groupDefs, columns, inAgg);
|
|
17220
|
+
return;
|
|
17221
|
+
case "unop":
|
|
17222
|
+
validateGroupedExpr(e.operand, groupDefs, columns, inAgg);
|
|
17223
|
+
return;
|
|
17224
|
+
case "cast":
|
|
17225
|
+
validateGroupedExpr(e.expr, groupDefs, columns, inAgg);
|
|
17226
|
+
return;
|
|
17227
|
+
case "collate":
|
|
17228
|
+
validateGroupedExpr(e.expr, groupDefs, columns, inAgg);
|
|
17229
|
+
return;
|
|
17230
|
+
case "case": {
|
|
17231
|
+
if (e.operand) validateGroupedExpr(e.operand, groupDefs, columns, inAgg);
|
|
17232
|
+
for (const w of e.whens) {
|
|
17233
|
+
validateGroupedExpr(w.when, groupDefs, columns, inAgg);
|
|
17234
|
+
validateGroupedExpr(w.then, groupDefs, columns, inAgg);
|
|
17235
|
+
}
|
|
17236
|
+
if (e.elseExpr) validateGroupedExpr(e.elseExpr, groupDefs, columns, inAgg);
|
|
17237
|
+
return;
|
|
17238
|
+
}
|
|
17239
|
+
case "in_expr":
|
|
17240
|
+
validateGroupedExpr(e.left, groupDefs, columns, inAgg);
|
|
17241
|
+
if (e.list) {
|
|
17242
|
+
for (const r of e.list) validateGroupedExpr(r, groupDefs, columns, inAgg);
|
|
17243
|
+
}
|
|
17244
|
+
return;
|
|
17245
|
+
case "between":
|
|
17246
|
+
validateGroupedExpr(e.left, groupDefs, columns, inAgg);
|
|
17247
|
+
validateGroupedExpr(e.low, groupDefs, columns, inAgg);
|
|
17248
|
+
validateGroupedExpr(e.high, groupDefs, columns, inAgg);
|
|
17249
|
+
return;
|
|
17250
|
+
case "is_null":
|
|
17251
|
+
case "bool_test":
|
|
17252
|
+
validateGroupedExpr(e.expr, groupDefs, columns, inAgg);
|
|
17253
|
+
return;
|
|
17254
|
+
case "is_distinct":
|
|
17255
|
+
validateGroupedExpr(e.left, groupDefs, columns, inAgg);
|
|
17256
|
+
validateGroupedExpr(e.right, groupDefs, columns, inAgg);
|
|
17257
|
+
return;
|
|
17258
|
+
case "row":
|
|
17259
|
+
for (const el of e.items) validateGroupedExpr(el, groupDefs, columns, inAgg);
|
|
17260
|
+
return;
|
|
17261
|
+
case "array_ctor":
|
|
17262
|
+
for (const el of e.items) validateGroupedExpr(el, groupDefs, columns, inAgg);
|
|
17263
|
+
return;
|
|
17264
|
+
case "array_query":
|
|
17265
|
+
return;
|
|
17266
|
+
case "subscript":
|
|
17267
|
+
validateGroupedExpr(e.base, groupDefs, columns, inAgg);
|
|
17268
|
+
for (const idx of e.indexes) {
|
|
17269
|
+
if (idx.lower) validateGroupedExpr(idx.lower, groupDefs, columns, inAgg);
|
|
17270
|
+
if (idx.upper) validateGroupedExpr(idx.upper, groupDefs, columns, inAgg);
|
|
17271
|
+
}
|
|
17272
|
+
return;
|
|
17273
|
+
case "field_select":
|
|
17274
|
+
validateGroupedExpr(e.base, groupDefs, columns, inAgg);
|
|
17275
|
+
return;
|
|
17276
|
+
case "at_time_zone":
|
|
17277
|
+
validateGroupedExpr(e.expr, groupDefs, columns, inAgg);
|
|
17278
|
+
validateGroupedExpr(e.zone, groupDefs, columns, inAgg);
|
|
17279
|
+
return;
|
|
17280
|
+
case "like":
|
|
17281
|
+
validateGroupedExpr(e.left, groupDefs, columns, inAgg);
|
|
17282
|
+
validateGroupedExpr(e.pattern, groupDefs, columns, inAgg);
|
|
17283
|
+
if (e.escape) validateGroupedExpr(e.escape, groupDefs, columns, inAgg);
|
|
17284
|
+
return;
|
|
17285
|
+
case "position":
|
|
17286
|
+
validateGroupedExpr(e.needle, groupDefs, columns, inAgg);
|
|
17287
|
+
validateGroupedExpr(e.haystack, groupDefs, columns, inAgg);
|
|
17288
|
+
return;
|
|
17289
|
+
case "substring_sql":
|
|
17290
|
+
validateGroupedExpr(e.source, groupDefs, columns, inAgg);
|
|
17291
|
+
if (e.from) validateGroupedExpr(e.from, groupDefs, columns, inAgg);
|
|
17292
|
+
if (e.forLen) validateGroupedExpr(e.forLen, groupDefs, columns, inAgg);
|
|
17293
|
+
if (e.similar) validateGroupedExpr(e.similar, groupDefs, columns, inAgg);
|
|
17294
|
+
if (e.escape) validateGroupedExpr(e.escape, groupDefs, columns, inAgg);
|
|
17295
|
+
return;
|
|
17296
|
+
case "overlay":
|
|
17297
|
+
validateGroupedExpr(e.source, groupDefs, columns, inAgg);
|
|
17298
|
+
validateGroupedExpr(e.placing, groupDefs, columns, inAgg);
|
|
17299
|
+
validateGroupedExpr(e.from, groupDefs, columns, inAgg);
|
|
17300
|
+
if (e.forLen) validateGroupedExpr(e.forLen, groupDefs, columns, inAgg);
|
|
17301
|
+
return;
|
|
17302
|
+
case "trim":
|
|
17303
|
+
validateGroupedExpr(e.source, groupDefs, columns, inAgg);
|
|
17304
|
+
if (e.chars) validateGroupedExpr(e.chars, groupDefs, columns, inAgg);
|
|
17305
|
+
return;
|
|
17306
|
+
case "extract":
|
|
17307
|
+
validateGroupedExpr(e.source, groupDefs, columns, inAgg);
|
|
17308
|
+
return;
|
|
17309
|
+
default:
|
|
17310
|
+
return;
|
|
17311
|
+
}
|
|
17312
|
+
}
|
|
17313
|
+
function validateGroupedTargets(targets, groupDefs, columns) {
|
|
17314
|
+
for (const t of targets) {
|
|
17315
|
+
if (t.expr.type === "star") {
|
|
17316
|
+
if (t.expr.table) {
|
|
17317
|
+
const label = t.expr.table[t.expr.table.length - 1];
|
|
17318
|
+
for (const c of columns) {
|
|
17319
|
+
if (c.table === label) {
|
|
17320
|
+
const parts = c.table ? [c.table, c.name] : [c.name];
|
|
17321
|
+
validateGroupedExpr({ type: "colref", parts }, groupDefs, columns, false);
|
|
17322
|
+
}
|
|
17323
|
+
}
|
|
17324
|
+
} else {
|
|
17325
|
+
for (const c of columns) {
|
|
17326
|
+
if (!c.hidden) {
|
|
17327
|
+
const parts = c.table ? [c.table, c.name] : [c.name];
|
|
17328
|
+
validateGroupedExpr({ type: "colref", parts }, groupDefs, columns, false);
|
|
17329
|
+
}
|
|
17330
|
+
}
|
|
17331
|
+
}
|
|
17332
|
+
continue;
|
|
17333
|
+
}
|
|
17334
|
+
validateGroupedExpr(t.expr, groupDefs, columns, false);
|
|
17335
|
+
}
|
|
17336
|
+
}
|
|
17337
|
+
function validateGroupedQuery(core, groupDefs, columns, orderBy = []) {
|
|
17338
|
+
validateGroupedTargets(core.targets, groupDefs, columns);
|
|
17339
|
+
if (core.having) validateGroupedExpr(core.having, groupDefs, columns, false);
|
|
17340
|
+
for (const ob of orderBy) validateGroupedExpr(ob.expr, groupDefs, columns, false);
|
|
17341
|
+
}
|
|
17342
|
+
function computeAggregate(env, call, rows, probeScope) {
|
|
17028
17343
|
const ctx = env.ctx;
|
|
17029
17344
|
const name = call.name[call.name.length - 1];
|
|
17030
17345
|
const orderedSet = isOrderedSetAggregate(name);
|
|
@@ -17111,6 +17426,17 @@ function computeAggregate(env, call, rows) {
|
|
|
17111
17426
|
}
|
|
17112
17427
|
argTypes.push(t);
|
|
17113
17428
|
}
|
|
17429
|
+
if (effective.length === 0 && probeScope !== null && argCount > 0) {
|
|
17430
|
+
const scope = makeEvalScope(env, probeScope);
|
|
17431
|
+
for (let i = 0; i < argCount; i++) {
|
|
17432
|
+
if (argTypes[i] !== UNKNOWN) continue;
|
|
17433
|
+
if (call.star) continue;
|
|
17434
|
+
const expr = orderedSet && i >= call.args.length ? orderBy[0].expr : call.args[i] ?? orderBy[0].expr;
|
|
17435
|
+
if (!expr) continue;
|
|
17436
|
+
const v = evalExpr(ctx, scope, expr);
|
|
17437
|
+
argTypes[i] = v.t === UNKNOWN ? "text" : v.t;
|
|
17438
|
+
}
|
|
17439
|
+
}
|
|
17114
17440
|
const acc = createAggregate(ctx, name, argTypes);
|
|
17115
17441
|
for (const t of effective) acc.step(t.args);
|
|
17116
17442
|
return acc.result();
|
|
@@ -17415,7 +17741,16 @@ function expandTargets(core, columns) {
|
|
|
17415
17741
|
}
|
|
17416
17742
|
return items;
|
|
17417
17743
|
}
|
|
17418
|
-
function
|
|
17744
|
+
function checkPredicateType(env, columns, rangeVars, e, kind, extras) {
|
|
17745
|
+
const probe = new RowScope(
|
|
17746
|
+
columns,
|
|
17747
|
+
columns.map(() => null),
|
|
17748
|
+
env.outer,
|
|
17749
|
+
rangeVars
|
|
17750
|
+
);
|
|
17751
|
+
checkBoolExprType(env.ctx, makeEvalScope(env, probe, extras), e, kind);
|
|
17752
|
+
}
|
|
17753
|
+
function executeCore(env0, core, orderBy, opts) {
|
|
17419
17754
|
const env = env0;
|
|
17420
17755
|
const ctx = env.ctx;
|
|
17421
17756
|
const source = buildFrom(env, core.from, core.where);
|
|
@@ -17424,6 +17759,7 @@ function executeCore(env0, core, orderBy) {
|
|
|
17424
17759
|
const rowScope = (row) => new RowScope(srcCols, row, env.outer, rangeVars);
|
|
17425
17760
|
let srcRows = source.rel.rows;
|
|
17426
17761
|
if (core.where) {
|
|
17762
|
+
checkPredicateType(env, srcCols, rangeVars, core.where, "WHERE");
|
|
17427
17763
|
if (core.from.length === 1) {
|
|
17428
17764
|
const indexed = tryIndexedFromItem(env, core.from[0], core.where);
|
|
17429
17765
|
if (indexed !== null) {
|
|
@@ -17513,7 +17849,7 @@ function executeCore(env0, core, orderBy) {
|
|
|
17513
17849
|
const aggMap = /* @__PURE__ */ new Map();
|
|
17514
17850
|
const groupScopes = rows.map((r) => rowScope(r));
|
|
17515
17851
|
for (const agg of collector.aggs) {
|
|
17516
|
-
aggMap.set(agg, computeAggregate(env, agg, groupScopes));
|
|
17852
|
+
aggMap.set(agg, computeAggregate(env, agg, groupScopes, repScope));
|
|
17517
17853
|
}
|
|
17518
17854
|
ctxs.push({
|
|
17519
17855
|
scope: repScope,
|
|
@@ -17554,9 +17890,19 @@ function executeCore(env0, core, orderBy) {
|
|
|
17554
17890
|
return tv("int4", mask);
|
|
17555
17891
|
} : void 0
|
|
17556
17892
|
});
|
|
17893
|
+
if (core.having) {
|
|
17894
|
+
if (ctxs.length > 0) {
|
|
17895
|
+
checkPredicateType(env, srcCols, rangeVars, core.having, "HAVING", extrasFor(ctxs[0]));
|
|
17896
|
+
} else if (!exprHasAggregateCall(core.having)) {
|
|
17897
|
+
checkPredicateType(env, srcCols, rangeVars, core.having, "HAVING");
|
|
17898
|
+
}
|
|
17899
|
+
}
|
|
17900
|
+
if (grouped) {
|
|
17901
|
+
validateGroupedQuery(core, groupDefs, srcCols, orderBy);
|
|
17902
|
+
}
|
|
17557
17903
|
if (core.having) {
|
|
17558
17904
|
const having = core.having;
|
|
17559
|
-
ctxs = ctxs.filter((rc) => evalPredicate(env, rc.scope, having, extrasFor(rc)));
|
|
17905
|
+
ctxs = ctxs.filter((rc) => evalPredicate(env, rc.scope, having, extrasFor(rc), "HAVING"));
|
|
17560
17906
|
}
|
|
17561
17907
|
const windowMaps = /* @__PURE__ */ new Map();
|
|
17562
17908
|
if (collector.windows.length > 0) {
|
|
@@ -17601,6 +17947,14 @@ function executeCore(env0, core, orderBy) {
|
|
|
17601
17947
|
sortSpecs.push(spec);
|
|
17602
17948
|
orderExprs.push({ item, spec });
|
|
17603
17949
|
}
|
|
17950
|
+
if (core.distinct && !core.distinct.on && sortSpecs.length > 0 && !opts?.hasLimit) {
|
|
17951
|
+
const used = new Set(sortSpecs.map((s) => s.colIdx));
|
|
17952
|
+
for (let i = 0; i < visibleCount; i++) {
|
|
17953
|
+
if (projItems[i].hidden || used.has(i)) continue;
|
|
17954
|
+
sortSpecs.push({ colIdx: i, dir: "asc", nullsFirst: false });
|
|
17955
|
+
used.add(i);
|
|
17956
|
+
}
|
|
17957
|
+
}
|
|
17604
17958
|
const distinctOnIdx = [];
|
|
17605
17959
|
if (core.distinct?.on) {
|
|
17606
17960
|
for (const e of core.distinct.on) {
|
|
@@ -17784,7 +18138,7 @@ function executeSelectStmt(env0, stmt) {
|
|
|
17784
18138
|
const env = applyWith(env0, stmt.with);
|
|
17785
18139
|
let rel2;
|
|
17786
18140
|
if (stmt.body.type === "select_core") {
|
|
17787
|
-
rel2 = executeCore(env, stmt.body, stmt.orderBy);
|
|
18141
|
+
rel2 = executeCore(env, stmt.body, stmt.orderBy, { hasLimit: stmt.limit !== null });
|
|
17788
18142
|
} else {
|
|
17789
18143
|
rel2 = executeBody(env, stmt.body);
|
|
17790
18144
|
const specs = outputOrderSpecs(env, rel2, stmt.orderBy);
|
|
@@ -18002,6 +18356,9 @@ var PlParser = class {
|
|
|
18002
18356
|
this.expectSemi();
|
|
18003
18357
|
return { kind: "for", targets, query, body };
|
|
18004
18358
|
}
|
|
18359
|
+
if (this.atKw("update") || this.atKw("insert") || this.atKw("delete")) {
|
|
18360
|
+
return { kind: "sql", text: this.parseSqlTextUntilSemi() };
|
|
18361
|
+
}
|
|
18005
18362
|
const target = [];
|
|
18006
18363
|
const first = this.next();
|
|
18007
18364
|
if (first.type !== "ident" && first.type !== "quoted_ident") {
|
|
@@ -18019,6 +18376,22 @@ var PlParser = class {
|
|
|
18019
18376
|
}
|
|
18020
18377
|
return { kind: "assign", target, expr: this.parseExprUntilSemi() };
|
|
18021
18378
|
}
|
|
18379
|
+
parseSqlTextUntilSemi() {
|
|
18380
|
+
const start = this.peek().pos;
|
|
18381
|
+
let depth = 0;
|
|
18382
|
+
for (; ; ) {
|
|
18383
|
+
const t = this.peek();
|
|
18384
|
+
if (t.type === "eof") throw unsupported("plpgsql: unterminated statement");
|
|
18385
|
+
if (t.type === "punct" && t.value === "(") depth++;
|
|
18386
|
+
if (t.type === "punct" && t.value === ")") depth--;
|
|
18387
|
+
if (t.type === "punct" && t.value === ";" && depth === 0) {
|
|
18388
|
+
const text = this.src.slice(start, t.pos).trim();
|
|
18389
|
+
this.pos++;
|
|
18390
|
+
return text;
|
|
18391
|
+
}
|
|
18392
|
+
this.pos++;
|
|
18393
|
+
}
|
|
18394
|
+
}
|
|
18022
18395
|
parseExprUntilSemi() {
|
|
18023
18396
|
const start = this.peek().pos;
|
|
18024
18397
|
let depth = 0;
|
|
@@ -18236,6 +18609,12 @@ function runStmt(env, stmt, vars, emit, tableNames) {
|
|
|
18236
18609
|
}
|
|
18237
18610
|
return;
|
|
18238
18611
|
}
|
|
18612
|
+
case "sql": {
|
|
18613
|
+
const stmts = parse(stmt.text);
|
|
18614
|
+
if (stmts.length !== 1) throw unsupported(`plpgsql SQL statement: ${stmt.text}`);
|
|
18615
|
+
runStatement(env, stmts[0]);
|
|
18616
|
+
return;
|
|
18617
|
+
}
|
|
18239
18618
|
}
|
|
18240
18619
|
}
|
|
18241
18620
|
function bindArgs(env, fn, args) {
|
|
@@ -18416,6 +18795,12 @@ function runTriggerBody(env, table, stmts, vars) {
|
|
|
18416
18795
|
}
|
|
18417
18796
|
break;
|
|
18418
18797
|
}
|
|
18798
|
+
case "sql": {
|
|
18799
|
+
const stmts2 = parse(stmt.text);
|
|
18800
|
+
if (stmts2.length !== 1) throw unsupported(`trigger body SQL: ${stmt.text}`);
|
|
18801
|
+
runStatement(env, stmts2[0]);
|
|
18802
|
+
break;
|
|
18803
|
+
}
|
|
18419
18804
|
default:
|
|
18420
18805
|
throw unsupported(`trigger body: ${stmt.kind}`);
|
|
18421
18806
|
}
|
|
@@ -18666,6 +19051,8 @@ var DatabaseState = class _DatabaseState {
|
|
|
18666
19051
|
inTransaction = false;
|
|
18667
19052
|
/** most recent sequence touched by nextval/setval, for lastval() */
|
|
18668
19053
|
lastSequence = null;
|
|
19054
|
+
/** Session currval per sequence; absent entry means currval is undefined. */
|
|
19055
|
+
sequenceCurrval = /* @__PURE__ */ new Map();
|
|
18669
19056
|
constructor(prng, clock) {
|
|
18670
19057
|
this.prng = prng;
|
|
18671
19058
|
this.clock = clock;
|
|
@@ -18854,6 +19241,7 @@ var DatabaseState = class _DatabaseState {
|
|
|
18854
19241
|
s.changes = this.changes;
|
|
18855
19242
|
s.inTransaction = this.inTransaction;
|
|
18856
19243
|
s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
|
|
19244
|
+
s.sequenceCurrval = new Map(this.sequenceCurrval);
|
|
18857
19245
|
s.oidCounter = this.oidCounter;
|
|
18858
19246
|
return s;
|
|
18859
19247
|
}
|
|
@@ -18868,6 +19256,7 @@ var DatabaseState = class _DatabaseState {
|
|
|
18868
19256
|
s.changes = this.changes;
|
|
18869
19257
|
s.inTransaction = this.inTransaction;
|
|
18870
19258
|
s.lastSequence = this.lastSequence ? { ...this.lastSequence } : null;
|
|
19259
|
+
s.sequenceCurrval = new Map(this.sequenceCurrval);
|
|
18871
19260
|
s.oidCounter = this.oidCounter;
|
|
18872
19261
|
return s;
|
|
18873
19262
|
}
|
|
@@ -18938,6 +19327,7 @@ var DatabaseState = class _DatabaseState {
|
|
|
18938
19327
|
this.prepared = other.prepared;
|
|
18939
19328
|
this.changes = other.changes;
|
|
18940
19329
|
this.lastSequence = other.lastSequence;
|
|
19330
|
+
this.sequenceCurrval = other.sequenceCurrval;
|
|
18941
19331
|
this.oidCounter = other.oidCounter;
|
|
18942
19332
|
}
|
|
18943
19333
|
/** @internal Snapshot codec access to the oid allocator. */
|
|
@@ -20279,6 +20669,22 @@ function executeTruncate(env, stmt) {
|
|
|
20279
20669
|
}
|
|
20280
20670
|
|
|
20281
20671
|
// src/executor/dml.ts
|
|
20672
|
+
function withStatementRollback(env, fn) {
|
|
20673
|
+
if (env.ctx.state.inTransaction) return fn();
|
|
20674
|
+
const state = env.ctx.state;
|
|
20675
|
+
state.freezeShared();
|
|
20676
|
+
const snap = state.cloneShallow();
|
|
20677
|
+
const prngSnap = state.prng.getState();
|
|
20678
|
+
try {
|
|
20679
|
+
return fn();
|
|
20680
|
+
} catch (e) {
|
|
20681
|
+
state.restoreFrom(snap);
|
|
20682
|
+
state.prng.setState(prngSnap);
|
|
20683
|
+
throw e;
|
|
20684
|
+
} finally {
|
|
20685
|
+
state.thawShared();
|
|
20686
|
+
}
|
|
20687
|
+
}
|
|
20282
20688
|
function requireTargetTable(env, parts, verb) {
|
|
20283
20689
|
const state = env.ctx.state;
|
|
20284
20690
|
const table = state.findTable(parts);
|
|
@@ -20479,84 +20885,86 @@ function executeInsert(env0, stmt) {
|
|
|
20479
20885
|
const sourceRows = insertSourceRows(env, stmt, colIdxs);
|
|
20480
20886
|
const insertedRows = [];
|
|
20481
20887
|
let insertedCount = 0;
|
|
20482
|
-
|
|
20483
|
-
const
|
|
20484
|
-
|
|
20485
|
-
|
|
20486
|
-
|
|
20487
|
-
|
|
20488
|
-
|
|
20489
|
-
|
|
20490
|
-
|
|
20888
|
+
return withStatementRollback(env, () => {
|
|
20889
|
+
for (const srcRow of sourceRows) {
|
|
20890
|
+
const row = table.columns.map(() => null);
|
|
20891
|
+
const provided = /* @__PURE__ */ new Set();
|
|
20892
|
+
for (let k = 0; k < srcRow.length; k++) {
|
|
20893
|
+
const ci = colIdxs[k];
|
|
20894
|
+
const col = table.columns[ci];
|
|
20895
|
+
const cell = srcRow[k];
|
|
20896
|
+
if (cell === DEFAULT_MARKER) {
|
|
20897
|
+
row[ci] = columnDefault(env, table, col);
|
|
20898
|
+
provided.add(ci);
|
|
20899
|
+
continue;
|
|
20900
|
+
}
|
|
20901
|
+
if (col.identity?.always && stmt.overriding !== "system") {
|
|
20902
|
+
throw pgError("generated_always", `cannot insert a non-DEFAULT value into column "${col.name}"`, "428C9");
|
|
20903
|
+
}
|
|
20904
|
+
row[ci] = coerceToColumn(env, cell, col);
|
|
20491
20905
|
provided.add(ci);
|
|
20492
|
-
continue;
|
|
20493
|
-
}
|
|
20494
|
-
if (col.identity?.always && stmt.overriding !== "system") {
|
|
20495
|
-
throw pgError("generated_always", `cannot insert a non-DEFAULT value into column "${col.name}"`, "428C9");
|
|
20496
20906
|
}
|
|
20497
|
-
|
|
20498
|
-
|
|
20499
|
-
|
|
20500
|
-
|
|
20501
|
-
|
|
20502
|
-
|
|
20503
|
-
|
|
20504
|
-
|
|
20505
|
-
|
|
20506
|
-
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
|
|
20512
|
-
|
|
20513
|
-
|
|
20514
|
-
|
|
20515
|
-
|
|
20516
|
-
const
|
|
20517
|
-
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
conflictIdx = idx;
|
|
20522
|
-
break;
|
|
20907
|
+
for (let i = 0; i < table.columns.length; i++) {
|
|
20908
|
+
if (provided.has(i)) continue;
|
|
20909
|
+
const col = table.columns[i];
|
|
20910
|
+
if (col.generated) continue;
|
|
20911
|
+
row[i] = columnDefault(env, table, col);
|
|
20912
|
+
}
|
|
20913
|
+
const fired = fireRowTriggers(env, table, "before", "insert", null, row);
|
|
20914
|
+
if (fired.row === null) continue;
|
|
20915
|
+
const newRow = fired.row;
|
|
20916
|
+
computeGeneratedColumns(env, table, newRow);
|
|
20917
|
+
if (stmt.onConflict) {
|
|
20918
|
+
const arbiters = resolveArbiters(env, table, stmt.onConflict);
|
|
20919
|
+
let conflictIdx = null;
|
|
20920
|
+
let conflictWhereOk = true;
|
|
20921
|
+
for (const a of arbiters) {
|
|
20922
|
+
if ("columns" in (stmt.onConflict.target ?? {}) && stmt.onConflict.target && "columns" in stmt.onConflict.target && stmt.onConflict.target.where) {
|
|
20923
|
+
const scope = tableRowScope(env, table, label, newRow);
|
|
20924
|
+
conflictWhereOk = evalPredicate(env, scope, stmt.onConflict.target.where);
|
|
20925
|
+
}
|
|
20926
|
+
const idx = findConflict(env, table, a.spec, newRow);
|
|
20927
|
+
if (idx !== null) {
|
|
20928
|
+
conflictIdx = idx;
|
|
20929
|
+
break;
|
|
20930
|
+
}
|
|
20523
20931
|
}
|
|
20524
|
-
|
|
20525
|
-
|
|
20526
|
-
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
20532
|
-
|
|
20533
|
-
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20932
|
+
if (conflictIdx !== null && conflictWhereOk) {
|
|
20933
|
+
if (stmt.onConflict.action === "nothing") continue;
|
|
20934
|
+
const did = applyOnConflictUpdate(
|
|
20935
|
+
env,
|
|
20936
|
+
table,
|
|
20937
|
+
label,
|
|
20938
|
+
conflictIdx,
|
|
20939
|
+
newRow,
|
|
20940
|
+
stmt.onConflict.action.sets,
|
|
20941
|
+
stmt.onConflict.action.where
|
|
20942
|
+
);
|
|
20943
|
+
if (did) {
|
|
20944
|
+
insertedCount++;
|
|
20945
|
+
insertedRows.push(rows[conflictIdx]);
|
|
20946
|
+
fireRowTriggers(env, table, "after", "update", null, rows[conflictIdx]);
|
|
20947
|
+
}
|
|
20948
|
+
continue;
|
|
20540
20949
|
}
|
|
20541
|
-
continue;
|
|
20542
20950
|
}
|
|
20951
|
+
checkNotNull(env, table, newRow);
|
|
20952
|
+
checkChecks(env, table, newRow);
|
|
20953
|
+
checkUnique(env, table, newRow, rows.length);
|
|
20954
|
+
checkForeignKeys(env, table, newRow);
|
|
20955
|
+
rows.push(newRow);
|
|
20956
|
+
indexInsertRow(env, table, rows.length - 1, newRow);
|
|
20957
|
+
insertedCount++;
|
|
20958
|
+
insertedRows.push(newRow);
|
|
20959
|
+
fireRowTriggers(env, table, "after", "insert", null, newRow);
|
|
20543
20960
|
}
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
insertedRows.push(newRow);
|
|
20552
|
-
fireRowTriggers(env, table, "after", "insert", null, newRow);
|
|
20553
|
-
}
|
|
20554
|
-
env.ctx.state.changes = insertedCount;
|
|
20555
|
-
if (stmt.returning) {
|
|
20556
|
-
const res = evalReturning(env, table, label, stmt.returning, insertedRows, "INSERT");
|
|
20557
|
-
return { ...res, rowCount: insertedCount };
|
|
20558
|
-
}
|
|
20559
|
-
return commandResult("INSERT", insertedCount);
|
|
20961
|
+
env.ctx.state.changes = insertedCount;
|
|
20962
|
+
if (stmt.returning) {
|
|
20963
|
+
const res = evalReturning(env, table, label, stmt.returning, insertedRows, "INSERT");
|
|
20964
|
+
return { ...res, rowCount: insertedCount };
|
|
20965
|
+
}
|
|
20966
|
+
return commandResult("INSERT", insertedCount);
|
|
20967
|
+
});
|
|
20560
20968
|
}
|
|
20561
20969
|
function applyUpdateSets(env, table, sets, scope, row) {
|
|
20562
20970
|
for (const set of sets) {
|