@dbsp/adapter-pgsql 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +42 -1
- package/dist/index.js +1281 -819
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1355,7 +1355,9 @@ function compileExpressionIntent(intent, ctx, state) {
|
|
|
1355
1355
|
}
|
|
1356
1356
|
case "relationColumn": {
|
|
1357
1357
|
const rc = intent;
|
|
1358
|
-
const
|
|
1358
|
+
const relationSegments = rc.relation.split(".");
|
|
1359
|
+
const leaf = relationSegments[relationSegments.length - 1] ?? rc.relation;
|
|
1360
|
+
const alias = state.aliases.get(rc.relation) ?? state.aliases.get(leaf) ?? leaf;
|
|
1359
1361
|
return columnRef(rc.column, alias, void 0, ctx.naming);
|
|
1360
1362
|
}
|
|
1361
1363
|
case "case": {
|
|
@@ -2814,8 +2816,9 @@ var init_param_intent = __esm({
|
|
|
2814
2816
|
import { isFieldRef, isParamIntent as isParamIntent3 } from "@dbsp/types";
|
|
2815
2817
|
function buildColumnRef(column, ctx) {
|
|
2816
2818
|
if (column.includes(".")) {
|
|
2817
|
-
const dotIndex = column.
|
|
2818
|
-
const
|
|
2819
|
+
const dotIndex = column.lastIndexOf(".");
|
|
2820
|
+
const relation = column.substring(0, dotIndex);
|
|
2821
|
+
const table = ctx.aliases?.get(relation) ?? relation;
|
|
2819
2822
|
const col = column.substring(dotIndex + 1);
|
|
2820
2823
|
return columnRef(col, table, void 0, ctx.naming);
|
|
2821
2824
|
}
|
|
@@ -3648,6 +3651,27 @@ var init_range = __esm({
|
|
|
3648
3651
|
}
|
|
3649
3652
|
});
|
|
3650
3653
|
|
|
3654
|
+
// src/binding-registry.ts
|
|
3655
|
+
function emittedBindName(name, naming) {
|
|
3656
|
+
return naming.toDatabase(name);
|
|
3657
|
+
}
|
|
3658
|
+
function hasBindingName(bindingNames, name, naming) {
|
|
3659
|
+
return bindingNames?.has(emittedBindName(name, naming)) ?? false;
|
|
3660
|
+
}
|
|
3661
|
+
function schemaForFromName(schemaName, fromName, bindingNames, naming) {
|
|
3662
|
+
return hasBindingName(bindingNames, fromName, naming) ? void 0 : schemaName;
|
|
3663
|
+
}
|
|
3664
|
+
function withBindingName(bindingNames, name, naming) {
|
|
3665
|
+
const next = new Set(bindingNames ?? []);
|
|
3666
|
+
next.add(emittedBindName(name, naming));
|
|
3667
|
+
return next;
|
|
3668
|
+
}
|
|
3669
|
+
var init_binding_registry = __esm({
|
|
3670
|
+
"src/binding-registry.ts"() {
|
|
3671
|
+
"use strict";
|
|
3672
|
+
}
|
|
3673
|
+
});
|
|
3674
|
+
|
|
3651
3675
|
// src/compile-where.ts
|
|
3652
3676
|
function toHandlerContext(ctx) {
|
|
3653
3677
|
return {
|
|
@@ -3656,11 +3680,12 @@ function toHandlerContext(ctx) {
|
|
|
3656
3680
|
currentAlias: ctx.currentAlias ?? ctx.rootTable,
|
|
3657
3681
|
maxRecursiveDepth: 100,
|
|
3658
3682
|
...ctx.schemaName !== void 0 && { schema: ctx.schemaName },
|
|
3683
|
+
...ctx.bindingNames !== void 0 && { bindingNames: ctx.bindingNames },
|
|
3659
3684
|
...ctx.model !== void 0 && { model: ctx.model },
|
|
3660
3685
|
...ctx.outerTable !== void 0 && { outerAlias: ctx.outerTable }
|
|
3661
3686
|
};
|
|
3662
3687
|
}
|
|
3663
|
-
function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, schemaName, use = "rawExists") {
|
|
3688
|
+
function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, schemaName, use = "rawExists", bindingNames) {
|
|
3664
3689
|
assertNoUnsupportedSubqueryModifiers(intent, use);
|
|
3665
3690
|
if (intent.where && containsOuterRef(intent.where)) {
|
|
3666
3691
|
throw new Error(
|
|
@@ -3705,9 +3730,14 @@ function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, s
|
|
|
3705
3730
|
}
|
|
3706
3731
|
const stmt = {
|
|
3707
3732
|
targetList,
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3733
|
+
fromClause: [
|
|
3734
|
+
rangeVar(
|
|
3735
|
+
targetTable,
|
|
3736
|
+
innerAlias,
|
|
3737
|
+
schemaForFromName(schemaName, targetTable, bindingNames, naming),
|
|
3738
|
+
naming
|
|
3739
|
+
)
|
|
3740
|
+
]
|
|
3711
3741
|
};
|
|
3712
3742
|
let paramCount = 0;
|
|
3713
3743
|
let innerParameters = [];
|
|
@@ -3721,6 +3751,7 @@ function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, s
|
|
|
3721
3751
|
aliases: /* @__PURE__ */ new Map(),
|
|
3722
3752
|
paramState: innerState,
|
|
3723
3753
|
naming,
|
|
3754
|
+
...bindingNames !== void 0 && { bindingNames },
|
|
3724
3755
|
compileSubquery: (_nestedIntent, _nestedOffset) => {
|
|
3725
3756
|
throw new Error(
|
|
3726
3757
|
"buildSubqueryFromIntent: nested subquery not supported"
|
|
@@ -4098,6 +4129,7 @@ var init_compile_where = __esm({
|
|
|
4098
4129
|
init_custom();
|
|
4099
4130
|
init_handlers();
|
|
4100
4131
|
init_assert_field();
|
|
4132
|
+
init_binding_registry();
|
|
4101
4133
|
init_types();
|
|
4102
4134
|
init_utils();
|
|
4103
4135
|
init_intent_to_decisions();
|
|
@@ -4142,7 +4174,8 @@ var init_raw_exists = __esm({
|
|
|
4142
4174
|
state.paramIndex,
|
|
4143
4175
|
ctx.naming,
|
|
4144
4176
|
ctx.schema,
|
|
4145
|
-
"rawExists"
|
|
4177
|
+
"rawExists",
|
|
4178
|
+
ctx.bindingNames
|
|
4146
4179
|
);
|
|
4147
4180
|
if (innerParams) {
|
|
4148
4181
|
for (const p of innerParams) {
|
|
@@ -4378,7 +4411,19 @@ function buildPredicateSubquerySelect(use, sourceIntent, decision, ctx, state, d
|
|
|
4378
4411
|
}
|
|
4379
4412
|
const stmt = {
|
|
4380
4413
|
targetList: [{ ResTarget: { val: targetVal } }],
|
|
4381
|
-
fromClause: [
|
|
4414
|
+
fromClause: [
|
|
4415
|
+
rangeVar(
|
|
4416
|
+
targetTable,
|
|
4417
|
+
targetAlias,
|
|
4418
|
+
schemaForFromName(
|
|
4419
|
+
ctx.schema,
|
|
4420
|
+
targetTable,
|
|
4421
|
+
ctx.bindingNames,
|
|
4422
|
+
ctx.naming
|
|
4423
|
+
),
|
|
4424
|
+
ctx.naming
|
|
4425
|
+
)
|
|
4426
|
+
],
|
|
4382
4427
|
...whereClause && { whereClause }
|
|
4383
4428
|
};
|
|
4384
4429
|
if (decision.orderBy && decision.orderBy.length > 0) {
|
|
@@ -4415,6 +4460,7 @@ var init_subquery_emission = __esm({
|
|
|
4415
4460
|
"src/subquery-emission.ts"() {
|
|
4416
4461
|
"use strict";
|
|
4417
4462
|
init_ast_helpers();
|
|
4463
|
+
init_binding_registry();
|
|
4418
4464
|
init_intent_to_decisions();
|
|
4419
4465
|
init_param_intent();
|
|
4420
4466
|
}
|
|
@@ -6685,7 +6731,7 @@ var init_relation = __esm({
|
|
|
6685
6731
|
if (relation.includes(".")) {
|
|
6686
6732
|
const segments = relation.split(".");
|
|
6687
6733
|
const leaf = segments[segments.length - 1];
|
|
6688
|
-
alias = state.aliases.get(
|
|
6734
|
+
alias = state.aliases.get(relation) ?? state.aliases.get(leaf) ?? leaf;
|
|
6689
6735
|
} else {
|
|
6690
6736
|
alias = state.aliases.get(relation) ?? relation;
|
|
6691
6737
|
}
|
|
@@ -7047,6 +7093,7 @@ import {
|
|
|
7047
7093
|
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
7048
7094
|
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST
|
|
7049
7095
|
} from "@dbsp/types";
|
|
7096
|
+
import { getNqlBindingRefName, isNqlBindingRef } from "@dbsp/types/internal";
|
|
7050
7097
|
|
|
7051
7098
|
// src/pgsql-deparser.ts
|
|
7052
7099
|
function deparse(node) {
|
|
@@ -8333,6 +8380,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8333
8380
|
defaultPk;
|
|
8334
8381
|
deriveFk;
|
|
8335
8382
|
model;
|
|
8383
|
+
bindingNames;
|
|
8336
8384
|
/** Mutable state shared with extracted condition/value compilation functions */
|
|
8337
8385
|
state = {
|
|
8338
8386
|
parameters: [],
|
|
@@ -8357,6 +8405,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8357
8405
|
joinAliasMap = /* @__PURE__ */ new Map();
|
|
8358
8406
|
/**
|
|
8359
8407
|
* Tracks all join aliases in use for the current query.
|
|
8408
|
+
* Entries are stored in emitted database-alias space, after naming.toDatabase().
|
|
8360
8409
|
* Ensures no two JOINs share the same alias (DOUBLE-ALIAS prevention).
|
|
8361
8410
|
*/
|
|
8362
8411
|
usedJoinAliases = /* @__PURE__ */ new Set();
|
|
@@ -8366,16 +8415,19 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8366
8415
|
this.defaultPk = options.defaultPkColumnName ?? DEFAULT_PK_COLUMN;
|
|
8367
8416
|
this.deriveFk = options.deriveFkColumnName ?? defaultFkDerivation;
|
|
8368
8417
|
this.model = options.model ?? void 0;
|
|
8418
|
+
this.bindingNames = options.bindingNames;
|
|
8369
8419
|
}
|
|
8370
8420
|
/** Build immutable context for handler-based WHERE compilation */
|
|
8371
8421
|
handlerCtx() {
|
|
8372
8422
|
return {
|
|
8373
8423
|
naming: this.naming,
|
|
8374
8424
|
rootTable: this.currentRootTable,
|
|
8425
|
+
aliases: this.resolvedJoinAliases(),
|
|
8375
8426
|
maxRecursiveDepth: 100,
|
|
8376
8427
|
defaultPkColumnName: this.defaultPk,
|
|
8377
8428
|
deriveFkColumnName: this.deriveFk,
|
|
8378
8429
|
...this.schema != null && { schema: this.schema },
|
|
8430
|
+
...this.bindingNames != null && { bindingNames: this.bindingNames },
|
|
8379
8431
|
...this.model != null && { model: this.model }
|
|
8380
8432
|
};
|
|
8381
8433
|
}
|
|
@@ -8386,6 +8438,24 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8386
8438
|
}
|
|
8387
8439
|
return alias;
|
|
8388
8440
|
}
|
|
8441
|
+
emittedJoinAlias(alias) {
|
|
8442
|
+
const dbAlias = this.naming.toDatabase(alias);
|
|
8443
|
+
validateIdentifier(dbAlias, "alias");
|
|
8444
|
+
return dbAlias;
|
|
8445
|
+
}
|
|
8446
|
+
resolvedJoinAliases() {
|
|
8447
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
8448
|
+
for (const [relationPath, entry] of this.joinAliasMap) {
|
|
8449
|
+
const isLegacyPath = relationPath.startsWith("__legacy__:");
|
|
8450
|
+
if (!isLegacyPath) {
|
|
8451
|
+
aliases.set(relationPath, entry.alias);
|
|
8452
|
+
}
|
|
8453
|
+
if (entry.relationName && (isLegacyPath || relationPath === entry.relationName)) {
|
|
8454
|
+
aliases.set(entry.relationName, entry.alias);
|
|
8455
|
+
}
|
|
8456
|
+
}
|
|
8457
|
+
return aliases;
|
|
8458
|
+
}
|
|
8389
8459
|
/**
|
|
8390
8460
|
* Dispatch a PlanDecision through the unified WHERE handler system.
|
|
8391
8461
|
* Bridges PlanCompiler's state to handler types, calls dispatcher, syncs back.
|
|
@@ -8567,12 +8637,13 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8567
8637
|
const candidateAlias = handlerDecision.relation ?? handlerDecision.targetTable ?? handlerDecision.relationName;
|
|
8568
8638
|
if (candidateAlias) {
|
|
8569
8639
|
let alias = candidateAlias;
|
|
8640
|
+
let emittedAlias = this.emittedJoinAlias(alias);
|
|
8570
8641
|
let counter = 1;
|
|
8571
|
-
while (this.usedJoinAliases.has(
|
|
8642
|
+
while (this.usedJoinAliases.has(emittedAlias)) {
|
|
8572
8643
|
alias = `${candidateAlias}_${counter++}`;
|
|
8644
|
+
emittedAlias = this.emittedJoinAlias(alias);
|
|
8573
8645
|
}
|
|
8574
|
-
|
|
8575
|
-
this.usedJoinAliases.add(alias);
|
|
8646
|
+
this.usedJoinAliases.add(emittedAlias);
|
|
8576
8647
|
finalJoinAlias = alias;
|
|
8577
8648
|
if (alias !== candidateAlias) {
|
|
8578
8649
|
handlerDecision.relation = alias;
|
|
@@ -8585,7 +8656,10 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8585
8656
|
this.joinAliasMap.set(relationIdentityPath, {
|
|
8586
8657
|
alias: finalJoinAlias,
|
|
8587
8658
|
joinType: requestedJoinType,
|
|
8588
|
-
...decision.targetTable && { targetTable: decision.targetTable }
|
|
8659
|
+
...decision.targetTable && { targetTable: decision.targetTable },
|
|
8660
|
+
...(decision.relationName ?? decision.relation) && {
|
|
8661
|
+
relationName: decision.relationName ?? decision.relation
|
|
8662
|
+
}
|
|
8589
8663
|
});
|
|
8590
8664
|
}
|
|
8591
8665
|
const out = {};
|
|
@@ -8658,10 +8732,12 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8658
8732
|
naming: this.naming,
|
|
8659
8733
|
rootTable: plan.rootTable,
|
|
8660
8734
|
currentAlias: currentAlias ?? plan.rootTable,
|
|
8735
|
+
aliases: this.resolvedJoinAliases(),
|
|
8661
8736
|
maxRecursiveDepth: 100,
|
|
8662
8737
|
defaultPkColumnName: this.defaultPk,
|
|
8663
8738
|
deriveFkColumnName: this.deriveFk,
|
|
8664
8739
|
...plan.schema ?? this.schema ? { schema: plan.schema ?? this.schema } : {},
|
|
8740
|
+
...this.bindingNames != null && { bindingNames: this.bindingNames },
|
|
8665
8741
|
...this.model != null && { model: this.model },
|
|
8666
8742
|
compileSubquery: (query, paramOffset) => this.compileExpressionSubquery(query, paramOffset),
|
|
8667
8743
|
compileNqlSelectExpression: (value, handlerCtx, state) => this.compileNqlFunctionArg(value, handlerCtx, state)
|
|
@@ -8673,7 +8749,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8673
8749
|
parameters: this.state.parameters,
|
|
8674
8750
|
paramIndex: this.state.paramIndex,
|
|
8675
8751
|
ctes: /* @__PURE__ */ new Map(),
|
|
8676
|
-
aliases:
|
|
8752
|
+
aliases: this.resolvedJoinAliases(),
|
|
8677
8753
|
joins: []
|
|
8678
8754
|
};
|
|
8679
8755
|
}
|
|
@@ -8684,7 +8760,10 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8684
8760
|
schema: this.schema
|
|
8685
8761
|
},
|
|
8686
8762
|
defaultPkColumnName: this.defaultPk,
|
|
8687
|
-
deriveFkColumnName: this.deriveFk
|
|
8763
|
+
deriveFkColumnName: this.deriveFk,
|
|
8764
|
+
...this.bindingNames !== void 0 && {
|
|
8765
|
+
bindingNames: this.bindingNames
|
|
8766
|
+
}
|
|
8688
8767
|
});
|
|
8689
8768
|
const innerPlan = {
|
|
8690
8769
|
rootTable: query.from,
|
|
@@ -8703,14 +8782,14 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8703
8782
|
return funcCall(functionName, argNodes);
|
|
8704
8783
|
}
|
|
8705
8784
|
compileNqlFunctionArg(arg, ctx, state) {
|
|
8785
|
+
if (isNqlBindingRef(arg)) {
|
|
8786
|
+
return buildColumnRef(getNqlBindingRefName(arg), ctx);
|
|
8787
|
+
}
|
|
8706
8788
|
if (typeof arg === "string") {
|
|
8707
8789
|
return buildColumnRef(arg, ctx);
|
|
8708
8790
|
}
|
|
8709
8791
|
if (typeof arg === "object" && arg !== null) {
|
|
8710
8792
|
const record = arg;
|
|
8711
|
-
if (typeof record.$ref === "string") {
|
|
8712
|
-
return buildColumnRef(record.$ref, ctx);
|
|
8713
|
-
}
|
|
8714
8793
|
if (typeof record.kind !== "string") {
|
|
8715
8794
|
const legacyKind = typeof record.$op === "string" ? `$op:${record.$op}` : typeof record.$fn === "string" ? `$fn:${record.$fn}` : "object";
|
|
8716
8795
|
throw new UnhandledNqlSelectExpressionKindError(legacyKind);
|
|
@@ -9131,11 +9210,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9131
9210
|
* Compile an includeStrategy decision and register its results.
|
|
9132
9211
|
* Pushes targets onto targetList, raw joins / CTEs onto instance collections.
|
|
9133
9212
|
*/
|
|
9134
|
-
|
|
9135
|
-
const includeResult = this.compileIncludeViaHandler(decision, plan);
|
|
9136
|
-
if (includeResult.targets) {
|
|
9137
|
-
targetList.push(...includeResult.targets);
|
|
9138
|
-
}
|
|
9213
|
+
registerIncludeCompilationResult(includeResult) {
|
|
9139
9214
|
if (includeResult.rawJoin) {
|
|
9140
9215
|
this.rawJoins.push(includeResult.rawJoin);
|
|
9141
9216
|
}
|
|
@@ -9146,6 +9221,27 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9146
9221
|
this.pendingCtes.push(includeResult.cte);
|
|
9147
9222
|
}
|
|
9148
9223
|
}
|
|
9224
|
+
compileIncludeDecision(decision, plan, targetList, precompiled) {
|
|
9225
|
+
const includeResult = precompiled ?? this.compileIncludeViaHandler(decision, plan);
|
|
9226
|
+
if (includeResult.targets) {
|
|
9227
|
+
targetList.push(...includeResult.targets);
|
|
9228
|
+
}
|
|
9229
|
+
if (!precompiled) {
|
|
9230
|
+
this.registerIncludeCompilationResult(includeResult);
|
|
9231
|
+
}
|
|
9232
|
+
}
|
|
9233
|
+
compileJoinIncludeAllocationPass(decisions, plan) {
|
|
9234
|
+
const includeResults = /* @__PURE__ */ new Map();
|
|
9235
|
+
for (const decision of decisions) {
|
|
9236
|
+
if (decision.type !== "includeStrategy" || decision.choice !== "join") {
|
|
9237
|
+
continue;
|
|
9238
|
+
}
|
|
9239
|
+
const includeResult = this.compileIncludeViaHandler(decision, plan);
|
|
9240
|
+
includeResults.set(decision, includeResult);
|
|
9241
|
+
this.registerIncludeCompilationResult(includeResult);
|
|
9242
|
+
}
|
|
9243
|
+
return includeResults;
|
|
9244
|
+
}
|
|
9149
9245
|
/**
|
|
9150
9246
|
* Fold a WHERE-family decision into an existing where expression.
|
|
9151
9247
|
* Returns the updated (or new) where node.
|
|
@@ -9279,6 +9375,14 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9279
9375
|
}
|
|
9280
9376
|
return where;
|
|
9281
9377
|
}
|
|
9378
|
+
reserveManualJoinAliases(decisions) {
|
|
9379
|
+
for (const decision of decisions) {
|
|
9380
|
+
if (decision.type !== "join") continue;
|
|
9381
|
+
const alias = decision.alias ?? decision.targetTable;
|
|
9382
|
+
if (!alias) continue;
|
|
9383
|
+
this.usedJoinAliases.add(this.emittedJoinAlias(alias));
|
|
9384
|
+
}
|
|
9385
|
+
}
|
|
9282
9386
|
/**
|
|
9283
9387
|
* Apply a single join decision to the FROM clause in-place.
|
|
9284
9388
|
* Chains multiple joins by wrapping from[0] as the left-arg each time.
|
|
@@ -9337,22 +9441,35 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9337
9441
|
}
|
|
9338
9442
|
return void 0;
|
|
9339
9443
|
}
|
|
9444
|
+
/**
|
|
9445
|
+
* Compile a column reference that may use dotted 'relation.column' notation.
|
|
9446
|
+
*/
|
|
9447
|
+
compileRelationAwareColumnRef(column, table) {
|
|
9448
|
+
const dot = column.lastIndexOf(".");
|
|
9449
|
+
if (dot !== -1) {
|
|
9450
|
+
const relation = column.slice(0, dot);
|
|
9451
|
+
const alias = this.resolvedJoinAliases().get(relation) ?? relation;
|
|
9452
|
+
return columnRef(column.slice(dot + 1), alias, void 0, this.naming);
|
|
9453
|
+
}
|
|
9454
|
+
return columnRef(column, table, void 0, this.naming);
|
|
9455
|
+
}
|
|
9340
9456
|
/**
|
|
9341
9457
|
* Compile a single groupBy decision into a ColumnRef AST node.
|
|
9342
9458
|
* Supports dotted 'relation.column' notation for joined tables.
|
|
9343
9459
|
*/
|
|
9344
9460
|
compileGroupByDecision(decision) {
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9461
|
+
return this.compileRelationAwareColumnRef(
|
|
9462
|
+
decision.column,
|
|
9463
|
+
decision.table
|
|
9464
|
+
);
|
|
9465
|
+
}
|
|
9466
|
+
/**
|
|
9467
|
+
* Compile a DISTINCT ON column into a ColumnRef AST node.
|
|
9468
|
+
* Mirrors GROUP BY relation-alias resolution while preserving unqualified
|
|
9469
|
+
* DISTINCT ON columns as unqualified references.
|
|
9470
|
+
*/
|
|
9471
|
+
compileDistinctOnColumn(column) {
|
|
9472
|
+
return this.compileRelationAwareColumnRef(column, void 0);
|
|
9356
9473
|
}
|
|
9357
9474
|
/**
|
|
9358
9475
|
* Assemble the final SelectStmt from all accumulated clause nodes.
|
|
@@ -9400,10 +9517,17 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9400
9517
|
plan.decisions,
|
|
9401
9518
|
plan.rootTable
|
|
9402
9519
|
);
|
|
9520
|
+
this.reserveManualJoinAliases(decisions);
|
|
9521
|
+
const includeJoinResults = this.compileJoinIncludeAllocationPass(
|
|
9522
|
+
decisions,
|
|
9523
|
+
plan
|
|
9524
|
+
);
|
|
9525
|
+
this.state.aliases = this.resolvedJoinAliases();
|
|
9403
9526
|
const targetList = [];
|
|
9404
9527
|
const from = this.compileFromClause(plan);
|
|
9405
9528
|
let where;
|
|
9406
9529
|
const orderBy = [];
|
|
9530
|
+
const orderByDecisions = [];
|
|
9407
9531
|
const groupBy = [];
|
|
9408
9532
|
let having;
|
|
9409
9533
|
let limit;
|
|
@@ -9423,7 +9547,12 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9423
9547
|
this.compileSelectTarget(decision, plan, targetList);
|
|
9424
9548
|
break;
|
|
9425
9549
|
case "includeStrategy":
|
|
9426
|
-
this.compileIncludeDecision(
|
|
9550
|
+
this.compileIncludeDecision(
|
|
9551
|
+
decision,
|
|
9552
|
+
plan,
|
|
9553
|
+
targetList,
|
|
9554
|
+
includeJoinResults.get(decision)
|
|
9555
|
+
);
|
|
9427
9556
|
where = this.compileIncludeWhereConditions(decision, where);
|
|
9428
9557
|
break;
|
|
9429
9558
|
case "where":
|
|
@@ -9436,8 +9565,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9436
9565
|
this.compileJoinDecision(decision, plan, from);
|
|
9437
9566
|
break;
|
|
9438
9567
|
case "orderBy": {
|
|
9439
|
-
|
|
9440
|
-
if (obNode) orderBy.push(obNode);
|
|
9568
|
+
orderByDecisions.push(decision);
|
|
9441
9569
|
break;
|
|
9442
9570
|
}
|
|
9443
9571
|
case "groupBy":
|
|
@@ -9478,12 +9606,16 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
9478
9606
|
case "distinctOn":
|
|
9479
9607
|
if (decision.columns && decision.columns.length > 0) {
|
|
9480
9608
|
distinct = decision.columns.map(
|
|
9481
|
-
(col) =>
|
|
9609
|
+
(col) => this.compileDistinctOnColumn(col)
|
|
9482
9610
|
);
|
|
9483
9611
|
}
|
|
9484
9612
|
break;
|
|
9485
9613
|
}
|
|
9486
9614
|
}
|
|
9615
|
+
for (const decision of orderByDecisions) {
|
|
9616
|
+
const obNode = this.compileOrderByDecision(decision, plan);
|
|
9617
|
+
if (obNode) orderBy.push(obNode);
|
|
9618
|
+
}
|
|
9487
9619
|
this.flushPendingJoins(from, plan);
|
|
9488
9620
|
return this.buildSelectStmt(
|
|
9489
9621
|
targetList,
|
|
@@ -13074,6 +13206,7 @@ function matchGlob(pattern, value) {
|
|
|
13074
13206
|
|
|
13075
13207
|
// src/mutations/mutation-compiler.ts
|
|
13076
13208
|
init_ast_helpers();
|
|
13209
|
+
init_binding_registry();
|
|
13077
13210
|
init_compiler_utils();
|
|
13078
13211
|
init_handlers();
|
|
13079
13212
|
init_param_intent();
|
|
@@ -13299,12 +13432,18 @@ function compileInsertFrom(config, ctx, state) {
|
|
|
13299
13432
|
const _dbTargetTable = naming.toDatabase(config.targetTable);
|
|
13300
13433
|
const dbSourceTable = naming.toDatabase(config.sourceTable);
|
|
13301
13434
|
const sourceAlias = config.sourceTable;
|
|
13435
|
+
const sourceSchema = schemaForFromName(
|
|
13436
|
+
ctx.schema,
|
|
13437
|
+
config.sourceTable,
|
|
13438
|
+
ctx.bindingNames,
|
|
13439
|
+
naming
|
|
13440
|
+
);
|
|
13302
13441
|
const dbColumns = config.columns?.map((c) => naming.toDatabase(c));
|
|
13303
13442
|
let targetList;
|
|
13304
13443
|
if (config.columns && config.columns.length > 0) {
|
|
13305
13444
|
targetList = config.columns.map(
|
|
13306
13445
|
(col) => resTarget(
|
|
13307
|
-
columnRef(col, sourceAlias,
|
|
13446
|
+
columnRef(col, sourceAlias, sourceSchema, naming),
|
|
13308
13447
|
naming.toDatabase(col)
|
|
13309
13448
|
)
|
|
13310
13449
|
);
|
|
@@ -13344,8 +13483,8 @@ function compileInsertFrom(config, ctx, state) {
|
|
|
13344
13483
|
inh: true,
|
|
13345
13484
|
relpersistence: "p"
|
|
13346
13485
|
};
|
|
13347
|
-
if (
|
|
13348
|
-
sourceRelation.schemaname = naming.toDatabase(
|
|
13486
|
+
if (sourceSchema) {
|
|
13487
|
+
sourceRelation.schemaname = naming.toDatabase(sourceSchema);
|
|
13349
13488
|
}
|
|
13350
13489
|
const selectQuery = {
|
|
13351
13490
|
SelectStmt: {
|
|
@@ -13374,12 +13513,18 @@ function compileUpsertFrom(config, ctx, state) {
|
|
|
13374
13513
|
const naming = ctx.naming;
|
|
13375
13514
|
const dbSourceTable = naming.toDatabase(config.sourceTable);
|
|
13376
13515
|
const sourceAlias = config.sourceTable;
|
|
13516
|
+
const sourceSchema = schemaForFromName(
|
|
13517
|
+
ctx.schema,
|
|
13518
|
+
config.sourceTable,
|
|
13519
|
+
ctx.bindingNames,
|
|
13520
|
+
naming
|
|
13521
|
+
);
|
|
13377
13522
|
const dbColumns = config.columns?.map((c) => naming.toDatabase(c));
|
|
13378
13523
|
let targetList;
|
|
13379
13524
|
if (config.columns && config.columns.length > 0) {
|
|
13380
13525
|
targetList = config.columns.map(
|
|
13381
13526
|
(col) => resTarget(
|
|
13382
|
-
columnRef(col, sourceAlias,
|
|
13527
|
+
columnRef(col, sourceAlias, sourceSchema, naming),
|
|
13383
13528
|
naming.toDatabase(col)
|
|
13384
13529
|
)
|
|
13385
13530
|
);
|
|
@@ -13419,8 +13564,8 @@ function compileUpsertFrom(config, ctx, state) {
|
|
|
13419
13564
|
inh: true,
|
|
13420
13565
|
relpersistence: "p"
|
|
13421
13566
|
};
|
|
13422
|
-
if (
|
|
13423
|
-
sourceRelation.schemaname = naming.toDatabase(
|
|
13567
|
+
if (sourceSchema) {
|
|
13568
|
+
sourceRelation.schemaname = naming.toDatabase(sourceSchema);
|
|
13424
13569
|
}
|
|
13425
13570
|
const selectQuery = {
|
|
13426
13571
|
SelectStmt: {
|
|
@@ -13565,6 +13710,28 @@ init_compiler_utils();
|
|
|
13565
13710
|
init_handlers();
|
|
13566
13711
|
init_param_intent();
|
|
13567
13712
|
init_param_ref();
|
|
13713
|
+
function buildWhereClause(conditions, ctx, state) {
|
|
13714
|
+
if (!conditions || conditions.length === 0) return void 0;
|
|
13715
|
+
const dispatch = createWhereDispatcher();
|
|
13716
|
+
if (conditions.length === 1) {
|
|
13717
|
+
return dispatch(conditions[0], ctx, state);
|
|
13718
|
+
}
|
|
13719
|
+
const nodes = conditions.map((condition) => dispatch(condition, ctx, state));
|
|
13720
|
+
return {
|
|
13721
|
+
BoolExpr: { boolop: "AND_EXPR", args: nodes }
|
|
13722
|
+
};
|
|
13723
|
+
}
|
|
13724
|
+
function buildActionWhereClause(config, ctx, state) {
|
|
13725
|
+
if (config.actionWhereIntent) {
|
|
13726
|
+
if (!config.compileActionWhere) {
|
|
13727
|
+
throw new Error(
|
|
13728
|
+
"Upsert actionWhereIntent requires compileActionWhere callback"
|
|
13729
|
+
);
|
|
13730
|
+
}
|
|
13731
|
+
return config.compileActionWhere(config.actionWhereIntent, state);
|
|
13732
|
+
}
|
|
13733
|
+
return buildWhereClause(config.actionWhere, ctx, state);
|
|
13734
|
+
}
|
|
13568
13735
|
function buildOnConflictClause(config, ctx, state) {
|
|
13569
13736
|
const naming = ctx.naming;
|
|
13570
13737
|
const action = config.conflictAction;
|
|
@@ -13578,18 +13745,12 @@ function buildOnConflictClause(config, ctx, state) {
|
|
|
13578
13745
|
}))
|
|
13579
13746
|
};
|
|
13580
13747
|
if (config.conflictTarget.where && config.conflictTarget.where.length > 0) {
|
|
13581
|
-
const
|
|
13582
|
-
|
|
13583
|
-
|
|
13584
|
-
|
|
13585
|
-
|
|
13586
|
-
|
|
13587
|
-
const nodes = conditions.map((c) => dispatch(c, ctx, state));
|
|
13588
|
-
whereClause = {
|
|
13589
|
-
BoolExpr: { boolop: "AND_EXPR", args: nodes }
|
|
13590
|
-
};
|
|
13591
|
-
}
|
|
13592
|
-
infer.whereClause = whereClause;
|
|
13748
|
+
const whereClause2 = buildWhereClause(
|
|
13749
|
+
config.conflictTarget.where,
|
|
13750
|
+
ctx,
|
|
13751
|
+
state
|
|
13752
|
+
);
|
|
13753
|
+
if (whereClause2) infer.whereClause = whereClause2;
|
|
13593
13754
|
}
|
|
13594
13755
|
} else if (config.conflictTarget.constraint) {
|
|
13595
13756
|
infer = {
|
|
@@ -13635,10 +13796,12 @@ function buildOnConflictClause(config, ctx, state) {
|
|
|
13635
13796
|
}
|
|
13636
13797
|
};
|
|
13637
13798
|
});
|
|
13799
|
+
const whereClause = buildActionWhereClause(config, ctx, state);
|
|
13638
13800
|
return {
|
|
13639
13801
|
action: "ONCONFLICT_UPDATE",
|
|
13640
13802
|
...infer && { infer },
|
|
13641
|
-
targetList
|
|
13803
|
+
targetList,
|
|
13804
|
+
...whereClause && { whereClause }
|
|
13642
13805
|
};
|
|
13643
13806
|
}
|
|
13644
13807
|
function compileUpsert(config, ctx, state) {
|
|
@@ -13776,7 +13939,8 @@ init_naming_plugin();
|
|
|
13776
13939
|
init_param_ref();
|
|
13777
13940
|
|
|
13778
13941
|
// src/pgsql-adapter.ts
|
|
13779
|
-
import { POSTGRESQL_CAPABILITIES, plan as
|
|
13942
|
+
import { POSTGRESQL_CAPABILITIES as POSTGRESQL_CAPABILITIES2, plan as planFn2 } from "@dbsp/core";
|
|
13943
|
+
import { getNqlBindingRefName as getNqlBindingRefName2, isNqlBindingRef as isNqlBindingRef2 } from "@dbsp/types/internal";
|
|
13780
13944
|
|
|
13781
13945
|
// src/adapter-compiler-includes.ts
|
|
13782
13946
|
init_ast_helpers();
|
|
@@ -13962,449 +14126,97 @@ function compileSubqueryIncludeManyToMany(info, parentIds, schemaName, state, de
|
|
|
13962
14126
|
}
|
|
13963
14127
|
|
|
13964
14128
|
// src/adapter-compiler-mutations.ts
|
|
14129
|
+
import {
|
|
14130
|
+
InvalidOperationError as InvalidOperationError3,
|
|
14131
|
+
isSqlRaw as isSqlRaw2,
|
|
14132
|
+
POSTGRESQL_CAPABILITIES,
|
|
14133
|
+
plan as planFn
|
|
14134
|
+
} from "@dbsp/core";
|
|
14135
|
+
|
|
14136
|
+
// src/adapter-compiler-select.ts
|
|
14137
|
+
init_assert_field();
|
|
14138
|
+
init_ast_helpers();
|
|
13965
14139
|
init_compile_where();
|
|
14140
|
+
import { countDistinctRelationPathsByName } from "@dbsp/core";
|
|
13966
14141
|
init_compiler_utils();
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
|
|
13976
|
-
|
|
13977
|
-
if (rel.type === "belongsTo") {
|
|
13978
|
-
const fk = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
|
|
13979
|
-
return {
|
|
13980
|
-
targetTable,
|
|
13981
|
-
...fk !== void 0 && { sourceColumn: fk },
|
|
13982
|
-
targetColumn: "id"
|
|
13983
|
-
};
|
|
13984
|
-
}
|
|
13985
|
-
return { targetTable };
|
|
13986
|
-
}
|
|
13987
|
-
function resolveExistsIntent(where, sourceTable, deps) {
|
|
14142
|
+
init_types();
|
|
14143
|
+
init_intent_to_decisions();
|
|
14144
|
+
init_param_ref();
|
|
14145
|
+
|
|
14146
|
+
// src/plan-decision-extractor.ts
|
|
14147
|
+
init_assert_field();
|
|
14148
|
+
init_intent_to_decisions();
|
|
14149
|
+
import { deriveRelationPathFromIntentPath } from "@dbsp/core";
|
|
14150
|
+
function findExistsIntents(where) {
|
|
14151
|
+
if (!where || typeof where !== "object") return [];
|
|
13988
14152
|
const w = where;
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
const conditions = w.conditions;
|
|
13992
|
-
if (!conditions) return where;
|
|
13993
|
-
const enriched = conditions.map(
|
|
13994
|
-
(c) => resolveExistsIntent(c, sourceTable, deps)
|
|
13995
|
-
);
|
|
13996
|
-
const changed = enriched.some((c, i) => c !== conditions[i]);
|
|
13997
|
-
return changed ? { ...w, conditions: enriched } : where;
|
|
13998
|
-
}
|
|
13999
|
-
if (kind === "not") {
|
|
14000
|
-
const condition = w.condition;
|
|
14001
|
-
if (!condition) return where;
|
|
14002
|
-
const enriched = resolveExistsIntent(condition, sourceTable, deps);
|
|
14003
|
-
return enriched !== condition ? { ...w, condition: enriched } : where;
|
|
14153
|
+
if (w.kind === "exists" || w.kind === "notExists" || w.kind === "relationFilter") {
|
|
14154
|
+
return [w];
|
|
14004
14155
|
}
|
|
14005
|
-
|
|
14006
|
-
|
|
14007
|
-
|
|
14008
|
-
|
|
14009
|
-
return {
|
|
14010
|
-
...w,
|
|
14011
|
-
targetTable: resolved.targetTable,
|
|
14012
|
-
...resolved.sourceColumn !== void 0 && {
|
|
14013
|
-
sourceColumn: resolved.sourceColumn
|
|
14014
|
-
},
|
|
14015
|
-
...resolved.targetColumn !== void 0 && {
|
|
14016
|
-
targetColumn: resolved.targetColumn
|
|
14156
|
+
const results = [];
|
|
14157
|
+
if (w.conditions && Array.isArray(w.conditions)) {
|
|
14158
|
+
for (const c of w.conditions) {
|
|
14159
|
+
results.push(...findExistsIntents(c));
|
|
14017
14160
|
}
|
|
14018
|
-
}
|
|
14161
|
+
}
|
|
14162
|
+
if (w.condition) {
|
|
14163
|
+
results.push(...findExistsIntents(w.condition));
|
|
14164
|
+
}
|
|
14165
|
+
return results;
|
|
14019
14166
|
}
|
|
14020
|
-
function
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14167
|
+
function resolveRelation(model, sourceTable, relationName) {
|
|
14168
|
+
const rel = model.getRelation(`${sourceTable}.${relationName}`);
|
|
14169
|
+
if (!rel) return void 0;
|
|
14170
|
+
const foreignKey = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
|
|
14171
|
+
const relationType = rel.type;
|
|
14172
|
+
return { target: rel.target, foreignKey, relationType };
|
|
14173
|
+
}
|
|
14174
|
+
function resolveIncludeAlias(context) {
|
|
14175
|
+
return context.relation ?? context.includeAlias;
|
|
14176
|
+
}
|
|
14177
|
+
function resolveIncludeByPath(includes, intentPath, relationName) {
|
|
14178
|
+
if (!includes) return void 0;
|
|
14179
|
+
if (intentPath) {
|
|
14180
|
+
const indexPattern = /include\[(\d+)\]/g;
|
|
14181
|
+
let current = includes;
|
|
14182
|
+
let resolved;
|
|
14183
|
+
let execResult = indexPattern.exec(intentPath);
|
|
14184
|
+
while (execResult !== null) {
|
|
14185
|
+
const idx = parseInt(execResult[1], 10);
|
|
14186
|
+
const item = current[idx];
|
|
14187
|
+
if (!item) break;
|
|
14188
|
+
resolved = item;
|
|
14189
|
+
current = item.include ?? [];
|
|
14190
|
+
execResult = indexPattern.exec(intentPath);
|
|
14030
14191
|
}
|
|
14192
|
+
if (resolved) return resolved;
|
|
14031
14193
|
}
|
|
14032
|
-
return
|
|
14194
|
+
return includes.find(
|
|
14195
|
+
(i) => i.relation === relationName || i.via === relationName
|
|
14196
|
+
);
|
|
14033
14197
|
}
|
|
14034
|
-
function
|
|
14035
|
-
const
|
|
14036
|
-
|
|
14037
|
-
|
|
14038
|
-
|
|
14039
|
-
|
|
14040
|
-
maxRecursiveDepth: 100
|
|
14041
|
-
};
|
|
14042
|
-
const state = createCompilerState();
|
|
14043
|
-
const firstRow = intent.values?.[0] ?? {};
|
|
14044
|
-
const columns = Object.keys(firstRow);
|
|
14045
|
-
const rows = intent.values ?? [];
|
|
14046
|
-
const values = rows.map((row) => columns.map((col) => row[col]));
|
|
14047
|
-
const columnTypes = getColumnTypes(intent.table, columns, deps);
|
|
14048
|
-
const config = {
|
|
14049
|
-
table: intent.table,
|
|
14050
|
-
columns,
|
|
14051
|
-
values,
|
|
14052
|
-
...intent.returning && { returning: [...intent.returning] },
|
|
14053
|
-
...columnTypes && { columnTypes }
|
|
14054
|
-
};
|
|
14055
|
-
const maxBatchSize = options?.maxBatchSize;
|
|
14056
|
-
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
14057
|
-
throw new InvalidOperationError3(
|
|
14058
|
-
"insert",
|
|
14059
|
-
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
14060
|
-
);
|
|
14198
|
+
function deriveForeignKey(context, deriveFk = defaultFkDerivation, defaultPk = DEFAULT_PK_COLUMN) {
|
|
14199
|
+
const fk = context.foreignKey ?? context.sourceFK;
|
|
14200
|
+
if (fk) return fk;
|
|
14201
|
+
if (!context.relationType) return void 0;
|
|
14202
|
+
if (context.relationType === "belongsTo") {
|
|
14203
|
+
return context.target ? deriveFk(context.target, defaultPk) : void 0;
|
|
14061
14204
|
}
|
|
14062
|
-
|
|
14063
|
-
|
|
14064
|
-
|
|
14065
|
-
const
|
|
14066
|
-
|
|
14067
|
-
|
|
14068
|
-
|
|
14205
|
+
return context.sourceTable ? deriveFk(context.sourceTable, defaultPk) : void 0;
|
|
14206
|
+
}
|
|
14207
|
+
function mapComparisonOperator(op3) {
|
|
14208
|
+
const map = {
|
|
14209
|
+
eq: "=",
|
|
14210
|
+
neq: "!=",
|
|
14211
|
+
gt: ">",
|
|
14212
|
+
gte: ">=",
|
|
14213
|
+
lt: "<",
|
|
14214
|
+
lte: "<=",
|
|
14215
|
+
like: "LIKE",
|
|
14216
|
+
ilike: "ILIKE",
|
|
14217
|
+
isDistinctFrom: "IS DISTINCT FROM"
|
|
14069
14218
|
};
|
|
14070
|
-
|
|
14071
|
-
function compileInsertFrom2(intent, _options, deps) {
|
|
14072
|
-
const schemaName = deps.schemaName;
|
|
14073
|
-
const ctx = {
|
|
14074
|
-
naming: deps.naming,
|
|
14075
|
-
rootTable: intent.source,
|
|
14076
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14077
|
-
maxRecursiveDepth: 100
|
|
14078
|
-
};
|
|
14079
|
-
const state = createCompilerState();
|
|
14080
|
-
const config = {
|
|
14081
|
-
targetTable: intent.table,
|
|
14082
|
-
sourceTable: intent.source,
|
|
14083
|
-
...intent.columns && { columns: [...intent.columns] },
|
|
14084
|
-
...intent.where && { where: [whereIntentAsDecision(intent.where)] },
|
|
14085
|
-
...intent.limit !== void 0 && { limit: intent.limit },
|
|
14086
|
-
...intent.returning && { returning: [...intent.returning] }
|
|
14087
|
-
};
|
|
14088
|
-
const ast = compileInsertFrom(config, ctx, state);
|
|
14089
|
-
const sql = deparseQuoted(ast);
|
|
14090
|
-
return {
|
|
14091
|
-
sql,
|
|
14092
|
-
parameters: state.parameters
|
|
14093
|
-
};
|
|
14094
|
-
}
|
|
14095
|
-
function compileUpdate2(intent, _options, deps) {
|
|
14096
|
-
const schemaName = deps.schemaName;
|
|
14097
|
-
const ctx = {
|
|
14098
|
-
naming: deps.naming,
|
|
14099
|
-
rootTable: intent.table,
|
|
14100
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14101
|
-
maxRecursiveDepth: 100
|
|
14102
|
-
};
|
|
14103
|
-
const state = createCompilerState();
|
|
14104
|
-
const setColumns = Object.keys(intent.set ?? {});
|
|
14105
|
-
const columnTypes = getColumnTypes(intent.table, setColumns, deps);
|
|
14106
|
-
const config = {
|
|
14107
|
-
table: intent.table,
|
|
14108
|
-
set: Object.entries(intent.set ?? {}).map(([column, value]) => ({
|
|
14109
|
-
column,
|
|
14110
|
-
value
|
|
14111
|
-
})),
|
|
14112
|
-
...intent.where && { where: [whereIntentAsDecision(intent.where)] },
|
|
14113
|
-
...intent.returning && { returning: [...intent.returning] },
|
|
14114
|
-
...columnTypes && { columnTypes }
|
|
14115
|
-
};
|
|
14116
|
-
const ast = compileUpdate(config, ctx, state);
|
|
14117
|
-
const sql = deparseQuoted(ast);
|
|
14118
|
-
return {
|
|
14119
|
-
sql,
|
|
14120
|
-
parameters: state.parameters
|
|
14121
|
-
};
|
|
14122
|
-
}
|
|
14123
|
-
function compileBatchUpdate(intent, _options, deps) {
|
|
14124
|
-
const schemaName = deps.schemaName;
|
|
14125
|
-
const ctx = {
|
|
14126
|
-
naming: deps.naming,
|
|
14127
|
-
rootTable: intent.table,
|
|
14128
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14129
|
-
maxRecursiveDepth: 100
|
|
14130
|
-
};
|
|
14131
|
-
const state = createCompilerState();
|
|
14132
|
-
if (intent.updates.length === 0) {
|
|
14133
|
-
throw new InvalidOperationError3(
|
|
14134
|
-
"update",
|
|
14135
|
-
"batchSet requires at least one row"
|
|
14136
|
-
);
|
|
14137
|
-
}
|
|
14138
|
-
const allColumns = Object.keys(intent.updates[0]);
|
|
14139
|
-
const matchColumns = [...intent.matchColumns];
|
|
14140
|
-
for (const mc of matchColumns) {
|
|
14141
|
-
if (!allColumns.includes(mc)) {
|
|
14142
|
-
throw new InvalidOperationError3(
|
|
14143
|
-
"update",
|
|
14144
|
-
`Match column "${mc}" not found in update data. Each row must include the match column(s).`
|
|
14145
|
-
);
|
|
14146
|
-
}
|
|
14147
|
-
}
|
|
14148
|
-
const values = intent.updates.map((row) => allColumns.map((col) => row[col]));
|
|
14149
|
-
validateBatchCardinality(allColumns, values);
|
|
14150
|
-
const columnArrays = transposeToColumnArrays(allColumns, values);
|
|
14151
|
-
const columnTypes = getColumnTypes(intent.table, allColumns, deps);
|
|
14152
|
-
const scalarSet = intent.scalarSet ? Object.entries(intent.scalarSet).map(([column, value]) => ({
|
|
14153
|
-
column,
|
|
14154
|
-
value
|
|
14155
|
-
})) : void 0;
|
|
14156
|
-
let whereGuard;
|
|
14157
|
-
if (intent.where) {
|
|
14158
|
-
const whereCtx = {
|
|
14159
|
-
rootTable: intent.table,
|
|
14160
|
-
aliases: /* @__PURE__ */ new Map(),
|
|
14161
|
-
paramState: state,
|
|
14162
|
-
naming: deps.naming,
|
|
14163
|
-
...schemaName !== void 0 && { schemaName },
|
|
14164
|
-
...deps.model !== void 0 && { model: deps.model },
|
|
14165
|
-
compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
|
|
14166
|
-
sqIntent,
|
|
14167
|
-
paramOffset,
|
|
14168
|
-
deps.naming,
|
|
14169
|
-
schemaName,
|
|
14170
|
-
"rawExists"
|
|
14171
|
-
)
|
|
14172
|
-
};
|
|
14173
|
-
whereGuard = compileWhereIntent(intent.where, whereCtx);
|
|
14174
|
-
}
|
|
14175
|
-
const config = {
|
|
14176
|
-
table: intent.table,
|
|
14177
|
-
matchColumns,
|
|
14178
|
-
allColumns,
|
|
14179
|
-
columnArrays,
|
|
14180
|
-
...scalarSet && { scalarSet },
|
|
14181
|
-
...intent.returning && { returning: [...intent.returning] },
|
|
14182
|
-
...columnTypes && { columnTypes },
|
|
14183
|
-
...whereGuard !== void 0 && { whereGuard }
|
|
14184
|
-
};
|
|
14185
|
-
const ast = compileUnnestUpdate(config, ctx, state);
|
|
14186
|
-
const sql = deparseQuoted(ast);
|
|
14187
|
-
return {
|
|
14188
|
-
sql,
|
|
14189
|
-
parameters: state.parameters
|
|
14190
|
-
};
|
|
14191
|
-
}
|
|
14192
|
-
function compileDelete2(intent, options, deps) {
|
|
14193
|
-
const schemaName = deps.schemaName;
|
|
14194
|
-
const resolvedModel = options?.model ?? deps.model;
|
|
14195
|
-
const ctx = {
|
|
14196
|
-
naming: deps.naming,
|
|
14197
|
-
rootTable: intent.table,
|
|
14198
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14199
|
-
maxRecursiveDepth: 100,
|
|
14200
|
-
...resolvedModel !== void 0 && { model: resolvedModel }
|
|
14201
|
-
};
|
|
14202
|
-
const state = createCompilerState();
|
|
14203
|
-
const resolvedWhere = intent.where ? resolveExistsIntent(intent.where, intent.table, deps) : void 0;
|
|
14204
|
-
const config = {
|
|
14205
|
-
table: intent.table,
|
|
14206
|
-
...resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] },
|
|
14207
|
-
...intent.returning && { returning: [...intent.returning] }
|
|
14208
|
-
};
|
|
14209
|
-
const ast = compileDelete(config, ctx, state);
|
|
14210
|
-
const sql = deparseQuoted(ast);
|
|
14211
|
-
return {
|
|
14212
|
-
sql,
|
|
14213
|
-
parameters: state.parameters
|
|
14214
|
-
};
|
|
14215
|
-
}
|
|
14216
|
-
function compileUpsert2(intent, options, deps) {
|
|
14217
|
-
const schemaName = deps.schemaName;
|
|
14218
|
-
const ctx = {
|
|
14219
|
-
naming: deps.naming,
|
|
14220
|
-
rootTable: intent.table,
|
|
14221
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14222
|
-
maxRecursiveDepth: 100
|
|
14223
|
-
};
|
|
14224
|
-
const state = createCompilerState();
|
|
14225
|
-
const firstRow = intent.values?.[0] ?? {};
|
|
14226
|
-
const rawExprs = {};
|
|
14227
|
-
const scalarSet = {};
|
|
14228
|
-
if (intent.action.type === "doUpdate" && intent.action.set) {
|
|
14229
|
-
for (const [key, val] of Object.entries(intent.action.set)) {
|
|
14230
|
-
if (isSqlRaw2(val)) {
|
|
14231
|
-
rawExprs[key] = val.sql;
|
|
14232
|
-
} else {
|
|
14233
|
-
scalarSet[key] = val;
|
|
14234
|
-
}
|
|
14235
|
-
}
|
|
14236
|
-
}
|
|
14237
|
-
const hasScalarSet = Object.keys(scalarSet).length > 0;
|
|
14238
|
-
const mergedFirstRow = hasScalarSet ? { ...firstRow, ...scalarSet } : firstRow;
|
|
14239
|
-
const columns = Object.keys(mergedFirstRow);
|
|
14240
|
-
const values = (intent.values ?? []).map((row) => {
|
|
14241
|
-
const mergedRow = hasScalarSet ? { ...row, ...scalarSet } : row;
|
|
14242
|
-
return columns.map((col) => mergedRow[col]);
|
|
14243
|
-
});
|
|
14244
|
-
const conflictTarget = {};
|
|
14245
|
-
if ("columns" in intent.onConflict) {
|
|
14246
|
-
conflictTarget.columns = [...intent.onConflict.columns];
|
|
14247
|
-
} else if ("constraint" in intent.onConflict) {
|
|
14248
|
-
conflictTarget.constraint = intent.onConflict.constraint;
|
|
14249
|
-
}
|
|
14250
|
-
const conflictAction = intent.action.type === "doNothing" ? "nothing" : "update";
|
|
14251
|
-
let updateColumns;
|
|
14252
|
-
if (intent.action.type === "doUpdate") {
|
|
14253
|
-
if (intent.action.set) {
|
|
14254
|
-
updateColumns = Object.keys(intent.action.set);
|
|
14255
|
-
} else {
|
|
14256
|
-
const conflictCols = "columns" in intent.onConflict ? intent.onConflict.columns : [];
|
|
14257
|
-
updateColumns = columns.filter((col) => !conflictCols.includes(col));
|
|
14258
|
-
}
|
|
14259
|
-
}
|
|
14260
|
-
const columnTypes = getColumnTypes(intent.table, columns, deps);
|
|
14261
|
-
const hasRawExprs = Object.keys(rawExprs).length > 0;
|
|
14262
|
-
const config = {
|
|
14263
|
-
table: intent.table,
|
|
14264
|
-
columns,
|
|
14265
|
-
values,
|
|
14266
|
-
conflictTarget,
|
|
14267
|
-
conflictAction,
|
|
14268
|
-
...updateColumns && { updateColumns },
|
|
14269
|
-
...intent.returning && { returning: [...intent.returning] },
|
|
14270
|
-
...columnTypes && { columnTypes },
|
|
14271
|
-
...hasRawExprs && { updateExpressions: rawExprs }
|
|
14272
|
-
};
|
|
14273
|
-
const maxBatchSize = options?.maxBatchSize;
|
|
14274
|
-
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
14275
|
-
throw new InvalidOperationError3(
|
|
14276
|
-
"upsert",
|
|
14277
|
-
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
14278
|
-
);
|
|
14279
|
-
}
|
|
14280
|
-
const batchThreshold = options?.batchThreshold ?? 50;
|
|
14281
|
-
const useUnnest = values.length > 0 && (batchThreshold === 0 || values.length > batchThreshold);
|
|
14282
|
-
const ast = useUnnest ? compileUnnestUpsert(config, ctx, state) : compileUpsert(config, ctx, state);
|
|
14283
|
-
const sql = deparseQuoted(ast);
|
|
14284
|
-
return {
|
|
14285
|
-
sql,
|
|
14286
|
-
parameters: state.parameters
|
|
14287
|
-
};
|
|
14288
|
-
}
|
|
14289
|
-
function compileUpsertFrom2(intent, options, deps) {
|
|
14290
|
-
const schemaName = deps.schemaName;
|
|
14291
|
-
const ctx = {
|
|
14292
|
-
naming: deps.naming,
|
|
14293
|
-
rootTable: intent.source,
|
|
14294
|
-
...schemaName !== void 0 && { schema: schemaName },
|
|
14295
|
-
maxRecursiveDepth: 100
|
|
14296
|
-
};
|
|
14297
|
-
const state = createCompilerState();
|
|
14298
|
-
let columns;
|
|
14299
|
-
if (intent.columns) {
|
|
14300
|
-
columns = [...intent.columns];
|
|
14301
|
-
} else if (options?.model) {
|
|
14302
|
-
const targetTable = options.model.getTable(intent.table);
|
|
14303
|
-
if (targetTable) {
|
|
14304
|
-
columns = targetTable.columns.map((c) => c.name);
|
|
14305
|
-
}
|
|
14306
|
-
}
|
|
14307
|
-
const config = {
|
|
14308
|
-
targetTable: intent.table,
|
|
14309
|
-
sourceTable: intent.source,
|
|
14310
|
-
conflictColumns: [...intent.conflictColumns],
|
|
14311
|
-
...columns && { columns },
|
|
14312
|
-
...intent.where && { where: [whereIntentAsDecision(intent.where)] },
|
|
14313
|
-
...intent.limit !== void 0 && { limit: intent.limit },
|
|
14314
|
-
...intent.returning && { returning: [...intent.returning] }
|
|
14315
|
-
};
|
|
14316
|
-
const ast = compileUpsertFrom(config, ctx, state);
|
|
14317
|
-
const sql = deparseQuoted(ast);
|
|
14318
|
-
return {
|
|
14319
|
-
sql,
|
|
14320
|
-
parameters: state.parameters
|
|
14321
|
-
};
|
|
14322
|
-
}
|
|
14323
|
-
|
|
14324
|
-
// src/adapter-compiler-select.ts
|
|
14325
|
-
init_assert_field();
|
|
14326
|
-
init_ast_helpers();
|
|
14327
|
-
init_compile_where();
|
|
14328
|
-
import { countDistinctRelationPathsByName } from "@dbsp/core";
|
|
14329
|
-
init_compiler_utils();
|
|
14330
|
-
init_types();
|
|
14331
|
-
init_intent_to_decisions();
|
|
14332
|
-
init_param_ref();
|
|
14333
|
-
|
|
14334
|
-
// src/plan-decision-extractor.ts
|
|
14335
|
-
init_assert_field();
|
|
14336
|
-
init_intent_to_decisions();
|
|
14337
|
-
import { deriveRelationPathFromIntentPath } from "@dbsp/core";
|
|
14338
|
-
function findExistsIntents(where) {
|
|
14339
|
-
if (!where || typeof where !== "object") return [];
|
|
14340
|
-
const w = where;
|
|
14341
|
-
if (w.kind === "exists" || w.kind === "notExists" || w.kind === "relationFilter") {
|
|
14342
|
-
return [w];
|
|
14343
|
-
}
|
|
14344
|
-
const results = [];
|
|
14345
|
-
if (w.conditions && Array.isArray(w.conditions)) {
|
|
14346
|
-
for (const c of w.conditions) {
|
|
14347
|
-
results.push(...findExistsIntents(c));
|
|
14348
|
-
}
|
|
14349
|
-
}
|
|
14350
|
-
if (w.condition) {
|
|
14351
|
-
results.push(...findExistsIntents(w.condition));
|
|
14352
|
-
}
|
|
14353
|
-
return results;
|
|
14354
|
-
}
|
|
14355
|
-
function resolveRelation(model, sourceTable, relationName) {
|
|
14356
|
-
const rel = model.getRelation(`${sourceTable}.${relationName}`);
|
|
14357
|
-
if (!rel) return void 0;
|
|
14358
|
-
const foreignKey = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
|
|
14359
|
-
const relationType = rel.type;
|
|
14360
|
-
return { target: rel.target, foreignKey, relationType };
|
|
14361
|
-
}
|
|
14362
|
-
function resolveIncludeAlias(context) {
|
|
14363
|
-
return context.relation ?? context.includeAlias;
|
|
14364
|
-
}
|
|
14365
|
-
function resolveIncludeByPath(includes, intentPath, relationName) {
|
|
14366
|
-
if (!includes) return void 0;
|
|
14367
|
-
if (intentPath) {
|
|
14368
|
-
const indexPattern = /include\[(\d+)\]/g;
|
|
14369
|
-
let current = includes;
|
|
14370
|
-
let resolved;
|
|
14371
|
-
let execResult = indexPattern.exec(intentPath);
|
|
14372
|
-
while (execResult !== null) {
|
|
14373
|
-
const idx = parseInt(execResult[1], 10);
|
|
14374
|
-
const item = current[idx];
|
|
14375
|
-
if (!item) break;
|
|
14376
|
-
resolved = item;
|
|
14377
|
-
current = item.include ?? [];
|
|
14378
|
-
execResult = indexPattern.exec(intentPath);
|
|
14379
|
-
}
|
|
14380
|
-
if (resolved) return resolved;
|
|
14381
|
-
}
|
|
14382
|
-
return includes.find(
|
|
14383
|
-
(i) => i.relation === relationName || i.via === relationName
|
|
14384
|
-
);
|
|
14385
|
-
}
|
|
14386
|
-
function deriveForeignKey(context, deriveFk = defaultFkDerivation, defaultPk = DEFAULT_PK_COLUMN) {
|
|
14387
|
-
const fk = context.foreignKey ?? context.sourceFK;
|
|
14388
|
-
if (fk) return fk;
|
|
14389
|
-
if (!context.relationType) return void 0;
|
|
14390
|
-
if (context.relationType === "belongsTo") {
|
|
14391
|
-
return context.target ? deriveFk(context.target, defaultPk) : void 0;
|
|
14392
|
-
}
|
|
14393
|
-
return context.sourceTable ? deriveFk(context.sourceTable, defaultPk) : void 0;
|
|
14394
|
-
}
|
|
14395
|
-
function mapComparisonOperator(op3) {
|
|
14396
|
-
const map = {
|
|
14397
|
-
eq: "=",
|
|
14398
|
-
neq: "!=",
|
|
14399
|
-
gt: ">",
|
|
14400
|
-
gte: ">=",
|
|
14401
|
-
lt: "<",
|
|
14402
|
-
lte: "<=",
|
|
14403
|
-
like: "LIKE",
|
|
14404
|
-
ilike: "ILIKE",
|
|
14405
|
-
isDistinctFrom: "IS DISTINCT FROM"
|
|
14406
|
-
};
|
|
14407
|
-
return map[op3] ?? "=";
|
|
14219
|
+
return map[op3] ?? "=";
|
|
14408
14220
|
}
|
|
14409
14221
|
function convertWhereToDecisions(where, table) {
|
|
14410
14222
|
if (!where || typeof where !== "object") return [];
|
|
@@ -15424,288 +15236,754 @@ function compileJoinIntents(joins, rootTable, schemaName, deps) {
|
|
|
15424
15236
|
});
|
|
15425
15237
|
}
|
|
15426
15238
|
}
|
|
15427
|
-
return results;
|
|
15239
|
+
return results;
|
|
15240
|
+
}
|
|
15241
|
+
function stripJoinColumnsForAggregation(decisions, intent) {
|
|
15242
|
+
const isAggregateOnly = intent.select && "type" in intent.select && intent.select.type === "aggregate" && !("fields" in intent.select && intent.select.fields);
|
|
15243
|
+
const isDistinct = intent.distinct === true;
|
|
15244
|
+
const hasGroupBy = intent.groupBy && intent.groupBy.length > 0;
|
|
15245
|
+
const hasExplicitColumns = intent.select && "type" in intent.select && intent.select.type === "expressions";
|
|
15246
|
+
if (isAggregateOnly || isDistinct || hasGroupBy || hasExplicitColumns) {
|
|
15247
|
+
for (const d of decisions) {
|
|
15248
|
+
if (d.type === "includeStrategy" && d.choice === "join") {
|
|
15249
|
+
d.columns = [];
|
|
15250
|
+
}
|
|
15251
|
+
}
|
|
15252
|
+
}
|
|
15253
|
+
}
|
|
15254
|
+
function buildRelationColumnsMap(decisions, includedRelations) {
|
|
15255
|
+
const map = /* @__PURE__ */ new Map();
|
|
15256
|
+
for (const d of decisions) {
|
|
15257
|
+
if (!(d.type === "selectRelationColumn" && d.relation && d.column))
|
|
15258
|
+
continue;
|
|
15259
|
+
const col = d.column;
|
|
15260
|
+
const alias = d.alias;
|
|
15261
|
+
const fullRelation = d.relation;
|
|
15262
|
+
const rootRelation = fullRelation.split(".")[0] ?? "";
|
|
15263
|
+
if (!includedRelations.has(rootRelation)) continue;
|
|
15264
|
+
const mapKey = fullRelation;
|
|
15265
|
+
if (col === "*") {
|
|
15266
|
+
map.set(mapKey, [{ col: "*" }]);
|
|
15267
|
+
continue;
|
|
15268
|
+
}
|
|
15269
|
+
const existing = map.get(mapKey);
|
|
15270
|
+
if (existing) {
|
|
15271
|
+
if (existing.length === 1 && existing[0]?.col === "*") continue;
|
|
15272
|
+
if (!existing.some((e) => e.col === col)) {
|
|
15273
|
+
existing.push({ col, ...alias !== void 0 && { alias } });
|
|
15274
|
+
}
|
|
15275
|
+
} else {
|
|
15276
|
+
map.set(mapKey, [{ col, ...alias !== void 0 && { alias } }]);
|
|
15277
|
+
}
|
|
15278
|
+
}
|
|
15279
|
+
return map;
|
|
15280
|
+
}
|
|
15281
|
+
function injectAndValidateRelationColumns(enrichedUnifiedDecisions, relationColumnsMap, model) {
|
|
15282
|
+
if (relationColumnsMap.size === 0) return;
|
|
15283
|
+
for (const d of enrichedUnifiedDecisions) {
|
|
15284
|
+
if (d.type === "includeStrategy" && d.relationName) {
|
|
15285
|
+
const mapKey = d.relationPath ?? d.relationName;
|
|
15286
|
+
const entries = mapKey ? relationColumnsMap.get(mapKey) : void 0;
|
|
15287
|
+
if (entries) {
|
|
15288
|
+
const mut = d;
|
|
15289
|
+
mut.columns = entries.map((e) => e.col);
|
|
15290
|
+
const aliasMap = {};
|
|
15291
|
+
for (const { col, alias } of entries) {
|
|
15292
|
+
if (alias) aliasMap[col] = alias;
|
|
15293
|
+
}
|
|
15294
|
+
if (Object.keys(aliasMap).length > 0) {
|
|
15295
|
+
mut.columnAliases = aliasMap;
|
|
15296
|
+
}
|
|
15297
|
+
}
|
|
15298
|
+
}
|
|
15299
|
+
}
|
|
15300
|
+
if (!model) return;
|
|
15301
|
+
for (const d of enrichedUnifiedDecisions) {
|
|
15302
|
+
if (d.type === "includeStrategy" && d.columns && d.targetTable && !(d.columns.length === 1 && d.columns[0] === "*")) {
|
|
15303
|
+
const targetTable = model.getTable(d.targetTable);
|
|
15304
|
+
if (targetTable) {
|
|
15305
|
+
const validColumnNames = new Set(
|
|
15306
|
+
targetTable.columns.map((c) => c.name)
|
|
15307
|
+
);
|
|
15308
|
+
const invalid = d.columns.filter(
|
|
15309
|
+
(c) => !validColumnNames.has(c)
|
|
15310
|
+
);
|
|
15311
|
+
if (invalid.length > 0) {
|
|
15312
|
+
throw new Error(
|
|
15313
|
+
`Unknown column(s) ${invalid.map((c) => `'${c}'`).join(", ")} in relation '${d.relationName}' (table '${d.targetTable}'). Available: ${[...validColumnNames].join(", ")}`
|
|
15314
|
+
);
|
|
15315
|
+
}
|
|
15316
|
+
}
|
|
15317
|
+
}
|
|
15318
|
+
}
|
|
15319
|
+
}
|
|
15320
|
+
function applyJoinHydrationPrefixes(decisions) {
|
|
15321
|
+
const usages = [];
|
|
15322
|
+
for (const d of decisions) {
|
|
15323
|
+
if (d.type !== "includeStrategy" || d.choice !== "join" || !d.relationName) {
|
|
15324
|
+
continue;
|
|
15325
|
+
}
|
|
15326
|
+
const relationName = d.relationName;
|
|
15327
|
+
const relationPath = d.relationPath ?? relationName;
|
|
15328
|
+
usages.push({ relationName, relationPath });
|
|
15329
|
+
}
|
|
15330
|
+
const pathCountsByRelation = countDistinctRelationPathsByName(usages);
|
|
15331
|
+
for (const d of decisions) {
|
|
15332
|
+
if (d.type !== "includeStrategy" || d.choice !== "join" || !d.relationName) {
|
|
15333
|
+
continue;
|
|
15334
|
+
}
|
|
15335
|
+
const relationName = d.relationName;
|
|
15336
|
+
const relationPath = d.relationPath ?? relationName;
|
|
15337
|
+
const usesFullPath = (pathCountsByRelation.get(relationName) ?? 0) > 1;
|
|
15338
|
+
d.hydrationPrefix = usesFullPath ? relationPath : relationName;
|
|
15339
|
+
}
|
|
15340
|
+
}
|
|
15341
|
+
function enrichRangeDecisions(allDecisions, model, rootTable) {
|
|
15342
|
+
if (!model) return;
|
|
15343
|
+
for (let i = 0; i < allDecisions.length; i++) {
|
|
15344
|
+
const d = allDecisions[i];
|
|
15345
|
+
if (d && d.type === "where" && (d.operator === "contains" || d.operator === "containedBy" || d.operator === "overlaps")) {
|
|
15346
|
+
const tableName = d.table || rootTable;
|
|
15347
|
+
const table = model.getTable(tableName);
|
|
15348
|
+
if (table) {
|
|
15349
|
+
const col = table.columns.find((c) => c.name === d.column);
|
|
15350
|
+
if (col?.type.endsWith("range")) {
|
|
15351
|
+
allDecisions[i] = { ...d, dataType: col.type };
|
|
15352
|
+
}
|
|
15353
|
+
}
|
|
15354
|
+
}
|
|
15355
|
+
}
|
|
15356
|
+
}
|
|
15357
|
+
function buildSimplifiedPlanReport(plan, allDecisions, schemaName) {
|
|
15358
|
+
const bvFromSource = plan.intent?.batchValuesSource;
|
|
15359
|
+
const batchValuesFromFields = bvFromSource ? (() => {
|
|
15360
|
+
const { rangeFunction, params } = buildBatchValuesRangeFn(
|
|
15361
|
+
bvFromSource,
|
|
15362
|
+
1
|
|
15363
|
+
);
|
|
15364
|
+
return {
|
|
15365
|
+
batchValuesFromNode: rangeFunction,
|
|
15366
|
+
batchValuesFromParams: params
|
|
15367
|
+
};
|
|
15368
|
+
})() : {};
|
|
15369
|
+
return {
|
|
15370
|
+
rootTable: plan.rootTable,
|
|
15371
|
+
decisions: allDecisions,
|
|
15372
|
+
...schemaName ? { schema: schemaName } : {},
|
|
15373
|
+
...plan.intent?.existsWrap ? { existsWrap: true } : {},
|
|
15374
|
+
...plan.intent?.lock ? { lock: plan.intent.lock } : {},
|
|
15375
|
+
...batchValuesFromFields
|
|
15376
|
+
};
|
|
15377
|
+
}
|
|
15378
|
+
function compileSelect(plan, options, deps) {
|
|
15379
|
+
const schemaName = deps.schemaName;
|
|
15380
|
+
const resolvedModelForCompiler = options?.model ?? deps.model;
|
|
15381
|
+
const compilerOptions = {
|
|
15382
|
+
naming: deps.naming,
|
|
15383
|
+
...schemaName && { schema: schemaName },
|
|
15384
|
+
defaultPkColumnName: deps.defaultPk,
|
|
15385
|
+
deriveFkColumnName: deps.deriveFk,
|
|
15386
|
+
...deps.bindingNames !== void 0 && {
|
|
15387
|
+
bindingNames: deps.bindingNames
|
|
15388
|
+
},
|
|
15389
|
+
...resolvedModelForCompiler != null && {
|
|
15390
|
+
model: resolvedModelForCompiler
|
|
15391
|
+
}
|
|
15392
|
+
};
|
|
15393
|
+
const execIntent = plan.executableIntent ?? plan.intent;
|
|
15394
|
+
const planForCompilation = plan.executableIntent !== void 0 ? { ...plan, intent: plan.executableIntent } : plan;
|
|
15395
|
+
let simplifiedPlan;
|
|
15396
|
+
if (execIntent) {
|
|
15397
|
+
let decisions = intentToDecisions(execIntent, plan.rootTable);
|
|
15398
|
+
const resolvedModel = options?.model ?? deps.model;
|
|
15399
|
+
if (resolvedModel) {
|
|
15400
|
+
decisions = convertDottedFieldsToExists(
|
|
15401
|
+
decisions,
|
|
15402
|
+
plan.rootTable,
|
|
15403
|
+
resolvedModel
|
|
15404
|
+
);
|
|
15405
|
+
}
|
|
15406
|
+
enrichExistsDecisionsInPlace(
|
|
15407
|
+
decisions,
|
|
15408
|
+
planForCompilation,
|
|
15409
|
+
options?.model ?? deps.model
|
|
15410
|
+
);
|
|
15411
|
+
const unifiedIncludeDecisions = extractAllIncludeDecisions(
|
|
15412
|
+
planForCompilation,
|
|
15413
|
+
deps.defaultPk,
|
|
15414
|
+
deps.deriveFk
|
|
15415
|
+
);
|
|
15416
|
+
const coveredByPlanner = new Set(
|
|
15417
|
+
unifiedIncludeDecisions.filter((d) => d.type === "includeStrategy").map((d) => d.relationName).filter(Boolean)
|
|
15418
|
+
);
|
|
15419
|
+
const synthesizedModel = options?.model ?? deps.model;
|
|
15420
|
+
const synthesizedJoins = synthesizedModel ? synthesizeMissingJoinDecisions(
|
|
15421
|
+
planForCompilation,
|
|
15422
|
+
coveredByPlanner,
|
|
15423
|
+
synthesizedModel,
|
|
15424
|
+
deps.defaultPk,
|
|
15425
|
+
deps.deriveFk
|
|
15426
|
+
) : [];
|
|
15427
|
+
const allUnifiedIncludeDecisions = synthesizedJoins.length > 0 ? [...unifiedIncludeDecisions, ...synthesizedJoins] : unifiedIncludeDecisions;
|
|
15428
|
+
const enrichedUnifiedDecisions = [
|
|
15429
|
+
...allUnifiedIncludeDecisions
|
|
15430
|
+
];
|
|
15431
|
+
stripJoinColumnsForAggregation(enrichedUnifiedDecisions, execIntent);
|
|
15432
|
+
applyJoinHydrationPrefixes(enrichedUnifiedDecisions);
|
|
15433
|
+
const includedRelations = new Set(
|
|
15434
|
+
enrichedUnifiedDecisions.filter((d) => d.type === "includeStrategy").map((d) => d.relationName).filter(Boolean)
|
|
15435
|
+
);
|
|
15436
|
+
if (includedRelations.size > 0) {
|
|
15437
|
+
const relationColumnsMap = buildRelationColumnsMap(
|
|
15438
|
+
decisions,
|
|
15439
|
+
includedRelations
|
|
15440
|
+
);
|
|
15441
|
+
injectAndValidateRelationColumns(
|
|
15442
|
+
enrichedUnifiedDecisions,
|
|
15443
|
+
relationColumnsMap,
|
|
15444
|
+
options?.model ?? deps.model
|
|
15445
|
+
);
|
|
15446
|
+
}
|
|
15447
|
+
const deduplicatedDecisions = includedRelations.size > 0 ? decisions.filter((d) => {
|
|
15448
|
+
if (d.type === "selectRelationColumn" && d.relation) {
|
|
15449
|
+
const rel = d.relation;
|
|
15450
|
+
const rootRelation = rel.split(".")[0] ?? rel;
|
|
15451
|
+
if (includedRelations.has(rootRelation)) {
|
|
15452
|
+
return false;
|
|
15453
|
+
}
|
|
15454
|
+
}
|
|
15455
|
+
return true;
|
|
15456
|
+
}) : decisions;
|
|
15457
|
+
const joinIntentDecisions = execIntent?.joins && execIntent.joins.length > 0 ? compileJoinIntents(
|
|
15458
|
+
execIntent.joins,
|
|
15459
|
+
plan.rootTable,
|
|
15460
|
+
schemaName,
|
|
15461
|
+
deps
|
|
15462
|
+
) : [];
|
|
15463
|
+
const allDecisions = [
|
|
15464
|
+
...deduplicatedDecisions,
|
|
15465
|
+
...enrichedUnifiedDecisions,
|
|
15466
|
+
...joinIntentDecisions
|
|
15467
|
+
];
|
|
15468
|
+
const rangeModel = options?.model ?? deps.model;
|
|
15469
|
+
enrichRangeDecisions(allDecisions, rangeModel, plan.rootTable);
|
|
15470
|
+
simplifiedPlan = buildSimplifiedPlanReport(
|
|
15471
|
+
planForCompilation,
|
|
15472
|
+
allDecisions,
|
|
15473
|
+
schemaName
|
|
15474
|
+
);
|
|
15475
|
+
} else {
|
|
15476
|
+
simplifiedPlan = {
|
|
15477
|
+
rootTable: plan.rootTable,
|
|
15478
|
+
decisions: bridgeLegacyDecisions(plan.decisions),
|
|
15479
|
+
...schemaName ? { schema: schemaName } : {}
|
|
15480
|
+
};
|
|
15481
|
+
}
|
|
15482
|
+
const result = compilePlan(simplifiedPlan, compilerOptions);
|
|
15483
|
+
return {
|
|
15484
|
+
sql: result.sql,
|
|
15485
|
+
parameters: result.parameters
|
|
15486
|
+
};
|
|
15428
15487
|
}
|
|
15429
|
-
function
|
|
15430
|
-
const
|
|
15431
|
-
const
|
|
15432
|
-
const
|
|
15433
|
-
|
|
15434
|
-
|
|
15435
|
-
|
|
15436
|
-
|
|
15437
|
-
|
|
15438
|
-
|
|
15488
|
+
function compileWithIncludes(plan, options, deps) {
|
|
15489
|
+
const main = compileSelect(plan, options, deps);
|
|
15490
|
+
const subqueryIncludes = [];
|
|
15491
|
+
for (const d of plan.decisions) {
|
|
15492
|
+
if (d.type !== "include-strategy" || d.choice !== "subquery") continue;
|
|
15493
|
+
const ctx = d.context;
|
|
15494
|
+
if (!ctx.target) continue;
|
|
15495
|
+
const relationName = ctx.includeAlias ?? ctx.relation;
|
|
15496
|
+
if (!relationName) continue;
|
|
15497
|
+
const rawFk = deriveForeignKey(ctx, deps.deriveFk, deps.defaultPk) ?? deps.defaultPk;
|
|
15498
|
+
const fk = Array.isArray(rawFk) ? rawFk[0] : rawFk;
|
|
15499
|
+
const isBelongsTo = ctx.relationType === "belongsTo";
|
|
15500
|
+
const sourceKey = isBelongsTo ? fk : "id";
|
|
15501
|
+
const targetFk = isBelongsTo ? "id" : fk;
|
|
15502
|
+
const includeIntent = plan.intent?.include?.find(
|
|
15503
|
+
(i) => i.relation === relationName || i.relation === ctx.includeAlias
|
|
15504
|
+
);
|
|
15505
|
+
const entry = {
|
|
15506
|
+
relationName,
|
|
15507
|
+
targetTable: ctx.target,
|
|
15508
|
+
foreignKey: targetFk,
|
|
15509
|
+
sourceKey,
|
|
15510
|
+
sourceTable: ctx.sourceTable ?? plan.rootTable
|
|
15511
|
+
};
|
|
15512
|
+
if (typeof ctx.relationType === "string") {
|
|
15513
|
+
entry.relationType = ctx.relationType;
|
|
15439
15514
|
}
|
|
15440
|
-
|
|
15441
|
-
|
|
15442
|
-
function buildRelationColumnsMap(decisions, includedRelations) {
|
|
15443
|
-
const map = /* @__PURE__ */ new Map();
|
|
15444
|
-
for (const d of decisions) {
|
|
15445
|
-
if (!(d.type === "selectRelationColumn" && d.relation && d.column))
|
|
15446
|
-
continue;
|
|
15447
|
-
const col = d.column;
|
|
15448
|
-
const alias = d.alias;
|
|
15449
|
-
const fullRelation = d.relation;
|
|
15450
|
-
const rootRelation = fullRelation.split(".")[0] ?? "";
|
|
15451
|
-
if (!includedRelations.has(rootRelation)) continue;
|
|
15452
|
-
const mapKey = fullRelation;
|
|
15453
|
-
if (col === "*") {
|
|
15454
|
-
map.set(mapKey, [{ col: "*" }]);
|
|
15455
|
-
continue;
|
|
15515
|
+
if (includeIntent?.select != null) {
|
|
15516
|
+
entry.select = includeIntent.select;
|
|
15456
15517
|
}
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
if (existing.length === 1 && existing[0]?.col === "*") continue;
|
|
15460
|
-
if (!existing.some((e) => e.col === col)) {
|
|
15461
|
-
existing.push({ col, ...alias !== void 0 && { alias } });
|
|
15462
|
-
}
|
|
15463
|
-
} else {
|
|
15464
|
-
map.set(mapKey, [{ col, ...alias !== void 0 && { alias } }]);
|
|
15518
|
+
if (includeIntent?.where != null) {
|
|
15519
|
+
entry.where = includeIntent.where;
|
|
15465
15520
|
}
|
|
15521
|
+
subqueryIncludes.push(entry);
|
|
15466
15522
|
}
|
|
15467
|
-
return
|
|
15523
|
+
return { main, subqueryIncludes };
|
|
15468
15524
|
}
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15525
|
+
|
|
15526
|
+
// src/adapter-compiler-mutations.ts
|
|
15527
|
+
init_binding_registry();
|
|
15528
|
+
init_compile_where();
|
|
15529
|
+
init_compiler_utils();
|
|
15530
|
+
init_handlers();
|
|
15531
|
+
function whereIntentAsDecision(where) {
|
|
15532
|
+
return where;
|
|
15533
|
+
}
|
|
15534
|
+
function renumberSqlParams(sql, offset) {
|
|
15535
|
+
if (offset === 0) return sql;
|
|
15536
|
+
return sql.replace(/\$(\d+)/g, (_match, num) => {
|
|
15537
|
+
return `$${Number.parseInt(num, 10) + offset}`;
|
|
15538
|
+
});
|
|
15539
|
+
}
|
|
15540
|
+
function compileSourceQueryCte(operation, sourceName, sourceQuery, options, deps) {
|
|
15541
|
+
const model = deps.model;
|
|
15542
|
+
if (model === void 0) {
|
|
15543
|
+
throw new Error(
|
|
15544
|
+
`${operation} with sourceQuery requires a model to emit the source CTE for '${sourceName}'.`
|
|
15545
|
+
);
|
|
15487
15546
|
}
|
|
15488
|
-
|
|
15489
|
-
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15547
|
+
const sourcePlan = planFn(sourceQuery, model, {
|
|
15548
|
+
dialectCapabilities: POSTGRESQL_CAPABILITIES
|
|
15549
|
+
});
|
|
15550
|
+
return compileSelect(sourcePlan, options, deps);
|
|
15551
|
+
}
|
|
15552
|
+
function prependSourceCte(sql, parameters, sourceName, sourceCte, naming) {
|
|
15553
|
+
if (sourceCte === void 0) {
|
|
15554
|
+
return { sql, parameters };
|
|
15555
|
+
}
|
|
15556
|
+
const cteParamCount = sourceCte.parameters.length;
|
|
15557
|
+
const sourceCteName = emittedBindName(sourceName, naming);
|
|
15558
|
+
return {
|
|
15559
|
+
sql: `WITH ${quoteIdent2(sourceCteName, "alias")} as (${sourceCte.sql}) ${renumberSqlParams(sql, cteParamCount)}`,
|
|
15560
|
+
parameters: [...sourceCte.parameters, ...parameters]
|
|
15561
|
+
};
|
|
15562
|
+
}
|
|
15563
|
+
function resolveExistsRelation(sourceTable, relation, model) {
|
|
15564
|
+
if (!model) return { targetTable: relation };
|
|
15565
|
+
const rel = model.getRelation(`${sourceTable}.${relation}`);
|
|
15566
|
+
if (!rel) return { targetTable: relation };
|
|
15567
|
+
const targetTable = rel.target;
|
|
15568
|
+
if (rel.type === "belongsTo") {
|
|
15569
|
+
const fk2 = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
|
|
15570
|
+
return {
|
|
15571
|
+
targetTable,
|
|
15572
|
+
...fk2 !== void 0 && { sourceColumn: fk2 },
|
|
15573
|
+
targetColumn: "id"
|
|
15574
|
+
};
|
|
15575
|
+
}
|
|
15576
|
+
const fk = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
|
|
15577
|
+
return {
|
|
15578
|
+
targetTable,
|
|
15579
|
+
sourceColumn: rel.sourceKey ?? "id",
|
|
15580
|
+
...fk !== void 0 && { targetColumn: fk }
|
|
15581
|
+
};
|
|
15582
|
+
}
|
|
15583
|
+
function resolveExistsIntent(where, sourceTable, deps) {
|
|
15584
|
+
const w = where;
|
|
15585
|
+
const kind = w.kind;
|
|
15586
|
+
if (kind === "and" || kind === "or") {
|
|
15587
|
+
const conditions = w.conditions;
|
|
15588
|
+
if (!conditions) return where;
|
|
15589
|
+
const enriched = conditions.map(
|
|
15590
|
+
(c) => resolveExistsIntent(c, sourceTable, deps)
|
|
15591
|
+
);
|
|
15592
|
+
const changed = enriched.some((c, i) => c !== conditions[i]);
|
|
15593
|
+
return changed ? { ...w, conditions: enriched } : where;
|
|
15594
|
+
}
|
|
15595
|
+
if (kind === "not") {
|
|
15596
|
+
const condition = w.condition;
|
|
15597
|
+
if (!condition) return where;
|
|
15598
|
+
const enriched = resolveExistsIntent(condition, sourceTable, deps);
|
|
15599
|
+
return enriched !== condition ? { ...w, condition: enriched } : where;
|
|
15600
|
+
}
|
|
15601
|
+
if (kind !== "exists" && kind !== "notExists") return where;
|
|
15602
|
+
const relation = w.relation;
|
|
15603
|
+
const resolved = resolveExistsRelation(sourceTable, relation, deps.model);
|
|
15604
|
+
if (resolved.targetTable === relation && !resolved.sourceColumn) return where;
|
|
15605
|
+
return {
|
|
15606
|
+
...w,
|
|
15607
|
+
targetTable: resolved.targetTable,
|
|
15608
|
+
...resolved.sourceColumn !== void 0 && {
|
|
15609
|
+
sourceColumn: resolved.sourceColumn
|
|
15610
|
+
},
|
|
15611
|
+
...resolved.targetColumn !== void 0 && {
|
|
15612
|
+
targetColumn: resolved.targetColumn
|
|
15613
|
+
}
|
|
15614
|
+
};
|
|
15615
|
+
}
|
|
15616
|
+
function getColumnTypes(tableName, columns, deps) {
|
|
15617
|
+
if (!deps.model) return void 0;
|
|
15618
|
+
const table = deps.model.getTable(tableName);
|
|
15619
|
+
if (!table) return void 0;
|
|
15620
|
+
let result;
|
|
15621
|
+
for (const col of columns) {
|
|
15622
|
+
const columnIR = table.columns.find((c) => c.name === col);
|
|
15623
|
+
if (columnIR) {
|
|
15624
|
+
result ??= {};
|
|
15625
|
+
result[col] = columnIR.originalDbType ?? columnIR.type;
|
|
15505
15626
|
}
|
|
15506
15627
|
}
|
|
15628
|
+
return result;
|
|
15629
|
+
}
|
|
15630
|
+
function compileUpsertActionWhere(where, table, state, deps, schemaName) {
|
|
15631
|
+
const whereCtx = {
|
|
15632
|
+
rootTable: table,
|
|
15633
|
+
aliases: /* @__PURE__ */ new Map(),
|
|
15634
|
+
paramState: state,
|
|
15635
|
+
naming: deps.naming,
|
|
15636
|
+
...schemaName !== void 0 && { schemaName },
|
|
15637
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15638
|
+
...deps.model !== void 0 && { model: deps.model },
|
|
15639
|
+
compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
|
|
15640
|
+
sqIntent,
|
|
15641
|
+
paramOffset,
|
|
15642
|
+
deps.naming,
|
|
15643
|
+
schemaName,
|
|
15644
|
+
"rawExists",
|
|
15645
|
+
deps.bindingNames
|
|
15646
|
+
)
|
|
15647
|
+
};
|
|
15648
|
+
return compileWhereIntent(where, whereCtx);
|
|
15649
|
+
}
|
|
15650
|
+
function compileInsert2(intent, options, deps) {
|
|
15651
|
+
const schemaName = deps.schemaName;
|
|
15652
|
+
const ctx = {
|
|
15653
|
+
naming: deps.naming,
|
|
15654
|
+
rootTable: intent.table,
|
|
15655
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15656
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15657
|
+
maxRecursiveDepth: 100
|
|
15658
|
+
};
|
|
15659
|
+
const state = createCompilerState();
|
|
15660
|
+
const firstRow = intent.values?.[0] ?? {};
|
|
15661
|
+
const columns = Object.keys(firstRow);
|
|
15662
|
+
const rows = intent.values ?? [];
|
|
15663
|
+
const values = rows.map((row) => columns.map((col) => row[col]));
|
|
15664
|
+
const columnTypes = getColumnTypes(intent.table, columns, deps);
|
|
15665
|
+
const config = {
|
|
15666
|
+
table: intent.table,
|
|
15667
|
+
columns,
|
|
15668
|
+
values,
|
|
15669
|
+
...intent.returning && { returning: [...intent.returning] },
|
|
15670
|
+
...columnTypes && { columnTypes }
|
|
15671
|
+
};
|
|
15672
|
+
const maxBatchSize = options?.maxBatchSize;
|
|
15673
|
+
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
15674
|
+
throw new InvalidOperationError3(
|
|
15675
|
+
"insert",
|
|
15676
|
+
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
15677
|
+
);
|
|
15678
|
+
}
|
|
15679
|
+
const batchThreshold = options?.batchThreshold ?? 50;
|
|
15680
|
+
const useUnnest = values.length > 0 && (batchThreshold === 0 || values.length > batchThreshold);
|
|
15681
|
+
const ast = useUnnest ? compileUnnestInsert(config, ctx, state) : compileInsert(config, ctx, state);
|
|
15682
|
+
const sql = deparseQuoted(ast);
|
|
15683
|
+
return {
|
|
15684
|
+
sql,
|
|
15685
|
+
parameters: state.parameters
|
|
15686
|
+
};
|
|
15687
|
+
}
|
|
15688
|
+
function compileInsertFrom2(intent, options, deps) {
|
|
15689
|
+
const schemaName = deps.schemaName;
|
|
15690
|
+
const sourceCte = intent.sourceQuery !== void 0 && !hasBindingName(deps.bindingNames, intent.source, deps.naming) ? compileSourceQueryCte(
|
|
15691
|
+
"compileInsertFrom",
|
|
15692
|
+
intent.source,
|
|
15693
|
+
intent.sourceQuery,
|
|
15694
|
+
options,
|
|
15695
|
+
deps
|
|
15696
|
+
) : void 0;
|
|
15697
|
+
const bindingNames = intent.sourceQuery !== void 0 ? withBindingName(deps.bindingNames, intent.source, deps.naming) : deps.bindingNames;
|
|
15698
|
+
const ctx = {
|
|
15699
|
+
naming: deps.naming,
|
|
15700
|
+
rootTable: intent.source,
|
|
15701
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15702
|
+
...bindingNames !== void 0 && { bindingNames },
|
|
15703
|
+
maxRecursiveDepth: 100
|
|
15704
|
+
};
|
|
15705
|
+
const state = createCompilerState();
|
|
15706
|
+
const config = {
|
|
15707
|
+
targetTable: intent.table,
|
|
15708
|
+
sourceTable: intent.source,
|
|
15709
|
+
...intent.columns && { columns: [...intent.columns] },
|
|
15710
|
+
...intent.where && { where: [whereIntentAsDecision(intent.where)] },
|
|
15711
|
+
...intent.limit !== void 0 && { limit: intent.limit },
|
|
15712
|
+
...intent.returning && { returning: [...intent.returning] }
|
|
15713
|
+
};
|
|
15714
|
+
const ast = compileInsertFrom(config, ctx, state);
|
|
15715
|
+
const sql = deparseQuoted(ast);
|
|
15716
|
+
return prependSourceCte(
|
|
15717
|
+
sql,
|
|
15718
|
+
state.parameters,
|
|
15719
|
+
intent.source,
|
|
15720
|
+
sourceCte,
|
|
15721
|
+
deps.naming
|
|
15722
|
+
);
|
|
15507
15723
|
}
|
|
15508
|
-
function
|
|
15509
|
-
const
|
|
15510
|
-
|
|
15511
|
-
|
|
15512
|
-
|
|
15513
|
-
|
|
15514
|
-
|
|
15515
|
-
|
|
15516
|
-
|
|
15724
|
+
function compileUpdate2(intent, options, deps) {
|
|
15725
|
+
const schemaName = deps.schemaName;
|
|
15726
|
+
const resolvedModel = options?.model ?? deps.model;
|
|
15727
|
+
const ctx = {
|
|
15728
|
+
naming: deps.naming,
|
|
15729
|
+
rootTable: intent.table,
|
|
15730
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15731
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15732
|
+
...resolvedModel !== void 0 && { model: resolvedModel },
|
|
15733
|
+
maxRecursiveDepth: 100
|
|
15734
|
+
};
|
|
15735
|
+
const state = createCompilerState();
|
|
15736
|
+
const setColumns = Object.keys(intent.set ?? {});
|
|
15737
|
+
const columnTypes = getColumnTypes(intent.table, setColumns, deps);
|
|
15738
|
+
const resolvedWhere = intent.where ? resolveExistsIntent(intent.where, intent.table, deps) : void 0;
|
|
15739
|
+
const config = {
|
|
15740
|
+
table: intent.table,
|
|
15741
|
+
set: Object.entries(intent.set ?? {}).map(([column, value]) => ({
|
|
15742
|
+
column,
|
|
15743
|
+
value
|
|
15744
|
+
})),
|
|
15745
|
+
...resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] },
|
|
15746
|
+
...intent.returning && { returning: [...intent.returning] },
|
|
15747
|
+
...columnTypes && { columnTypes }
|
|
15748
|
+
};
|
|
15749
|
+
const ast = compileUpdate(config, ctx, state);
|
|
15750
|
+
const sql = deparseQuoted(ast);
|
|
15751
|
+
return {
|
|
15752
|
+
sql,
|
|
15753
|
+
parameters: state.parameters
|
|
15754
|
+
};
|
|
15755
|
+
}
|
|
15756
|
+
function compileBatchUpdate(intent, _options, deps) {
|
|
15757
|
+
const schemaName = deps.schemaName;
|
|
15758
|
+
const ctx = {
|
|
15759
|
+
naming: deps.naming,
|
|
15760
|
+
rootTable: intent.table,
|
|
15761
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15762
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15763
|
+
maxRecursiveDepth: 100
|
|
15764
|
+
};
|
|
15765
|
+
const state = createCompilerState();
|
|
15766
|
+
if (intent.updates.length === 0) {
|
|
15767
|
+
throw new InvalidOperationError3(
|
|
15768
|
+
"update",
|
|
15769
|
+
"batchSet requires at least one row"
|
|
15770
|
+
);
|
|
15517
15771
|
}
|
|
15518
|
-
const
|
|
15519
|
-
|
|
15520
|
-
|
|
15521
|
-
|
|
15772
|
+
const allColumns = Object.keys(intent.updates[0]);
|
|
15773
|
+
const matchColumns = [...intent.matchColumns];
|
|
15774
|
+
for (const mc of matchColumns) {
|
|
15775
|
+
if (!allColumns.includes(mc)) {
|
|
15776
|
+
throw new InvalidOperationError3(
|
|
15777
|
+
"update",
|
|
15778
|
+
`Match column "${mc}" not found in update data. Each row must include the match column(s).`
|
|
15779
|
+
);
|
|
15522
15780
|
}
|
|
15523
|
-
const relationName = d.relationName;
|
|
15524
|
-
const relationPath = d.relationPath ?? relationName;
|
|
15525
|
-
const usesFullPath = (pathCountsByRelation.get(relationName) ?? 0) > 1;
|
|
15526
|
-
d.hydrationPrefix = usesFullPath ? relationPath : relationName;
|
|
15527
15781
|
}
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
|
|
15531
|
-
|
|
15532
|
-
|
|
15533
|
-
|
|
15534
|
-
|
|
15535
|
-
|
|
15536
|
-
|
|
15537
|
-
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15782
|
+
const values = intent.updates.map((row) => allColumns.map((col) => row[col]));
|
|
15783
|
+
validateBatchCardinality(allColumns, values);
|
|
15784
|
+
const columnArrays = transposeToColumnArrays(allColumns, values);
|
|
15785
|
+
const columnTypes = getColumnTypes(intent.table, allColumns, deps);
|
|
15786
|
+
const scalarSet = intent.scalarSet ? Object.entries(intent.scalarSet).map(([column, value]) => ({
|
|
15787
|
+
column,
|
|
15788
|
+
value
|
|
15789
|
+
})) : void 0;
|
|
15790
|
+
let whereGuard;
|
|
15791
|
+
if (intent.where) {
|
|
15792
|
+
const whereCtx = {
|
|
15793
|
+
rootTable: intent.table,
|
|
15794
|
+
aliases: /* @__PURE__ */ new Map(),
|
|
15795
|
+
paramState: state,
|
|
15796
|
+
naming: deps.naming,
|
|
15797
|
+
...schemaName !== void 0 && { schemaName },
|
|
15798
|
+
...deps.bindingNames !== void 0 && {
|
|
15799
|
+
bindingNames: deps.bindingNames
|
|
15800
|
+
},
|
|
15801
|
+
...deps.model !== void 0 && { model: deps.model },
|
|
15802
|
+
compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
|
|
15803
|
+
sqIntent,
|
|
15804
|
+
paramOffset,
|
|
15805
|
+
deps.naming,
|
|
15806
|
+
schemaName,
|
|
15807
|
+
"rawExists",
|
|
15808
|
+
deps.bindingNames
|
|
15809
|
+
)
|
|
15810
|
+
};
|
|
15811
|
+
whereGuard = compileWhereIntent(intent.where, whereCtx);
|
|
15543
15812
|
}
|
|
15813
|
+
const config = {
|
|
15814
|
+
table: intent.table,
|
|
15815
|
+
matchColumns,
|
|
15816
|
+
allColumns,
|
|
15817
|
+
columnArrays,
|
|
15818
|
+
...scalarSet && { scalarSet },
|
|
15819
|
+
...intent.returning && { returning: [...intent.returning] },
|
|
15820
|
+
...columnTypes && { columnTypes },
|
|
15821
|
+
...whereGuard !== void 0 && { whereGuard }
|
|
15822
|
+
};
|
|
15823
|
+
const ast = compileUnnestUpdate(config, ctx, state);
|
|
15824
|
+
const sql = deparseQuoted(ast);
|
|
15825
|
+
return {
|
|
15826
|
+
sql,
|
|
15827
|
+
parameters: state.parameters
|
|
15828
|
+
};
|
|
15544
15829
|
}
|
|
15545
|
-
function
|
|
15546
|
-
const
|
|
15547
|
-
const
|
|
15548
|
-
|
|
15549
|
-
|
|
15550
|
-
|
|
15551
|
-
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15555
|
-
|
|
15556
|
-
|
|
15830
|
+
function compileDelete2(intent, options, deps) {
|
|
15831
|
+
const schemaName = deps.schemaName;
|
|
15832
|
+
const resolvedModel = options?.model ?? deps.model;
|
|
15833
|
+
const ctx = {
|
|
15834
|
+
naming: deps.naming,
|
|
15835
|
+
rootTable: intent.table,
|
|
15836
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15837
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15838
|
+
maxRecursiveDepth: 100,
|
|
15839
|
+
...resolvedModel !== void 0 && { model: resolvedModel }
|
|
15840
|
+
};
|
|
15841
|
+
const state = createCompilerState();
|
|
15842
|
+
const resolvedWhere = intent.where ? resolveExistsIntent(intent.where, intent.table, deps) : void 0;
|
|
15843
|
+
const config = {
|
|
15844
|
+
table: intent.table,
|
|
15845
|
+
...resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] },
|
|
15846
|
+
...intent.returning && { returning: [...intent.returning] }
|
|
15847
|
+
};
|
|
15848
|
+
const ast = compileDelete(config, ctx, state);
|
|
15849
|
+
const sql = deparseQuoted(ast);
|
|
15557
15850
|
return {
|
|
15558
|
-
|
|
15559
|
-
|
|
15560
|
-
...schemaName ? { schema: schemaName } : {},
|
|
15561
|
-
...plan.intent?.existsWrap ? { existsWrap: true } : {},
|
|
15562
|
-
...plan.intent?.lock ? { lock: plan.intent.lock } : {},
|
|
15563
|
-
...batchValuesFromFields
|
|
15851
|
+
sql,
|
|
15852
|
+
parameters: state.parameters
|
|
15564
15853
|
};
|
|
15565
15854
|
}
|
|
15566
|
-
function
|
|
15855
|
+
function compileUpsert2(intent, options, deps) {
|
|
15567
15856
|
const schemaName = deps.schemaName;
|
|
15568
|
-
const
|
|
15569
|
-
const compilerOptions = {
|
|
15857
|
+
const ctx = {
|
|
15570
15858
|
naming: deps.naming,
|
|
15571
|
-
|
|
15572
|
-
|
|
15573
|
-
|
|
15574
|
-
...
|
|
15575
|
-
|
|
15576
|
-
}
|
|
15859
|
+
rootTable: intent.table,
|
|
15860
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15861
|
+
...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
|
|
15862
|
+
...deps.model !== void 0 && { model: deps.model },
|
|
15863
|
+
maxRecursiveDepth: 100
|
|
15577
15864
|
};
|
|
15578
|
-
const
|
|
15579
|
-
const
|
|
15580
|
-
|
|
15581
|
-
|
|
15582
|
-
|
|
15583
|
-
const
|
|
15584
|
-
|
|
15585
|
-
|
|
15586
|
-
|
|
15587
|
-
|
|
15588
|
-
|
|
15589
|
-
);
|
|
15865
|
+
const state = createCompilerState();
|
|
15866
|
+
const firstRow = intent.values?.[0] ?? {};
|
|
15867
|
+
const rawExprs = {};
|
|
15868
|
+
const scalarSet = {};
|
|
15869
|
+
if (intent.action.type === "doUpdate" && intent.action.set) {
|
|
15870
|
+
for (const [key, val] of Object.entries(intent.action.set)) {
|
|
15871
|
+
if (isSqlRaw2(val)) {
|
|
15872
|
+
rawExprs[key] = val.sql;
|
|
15873
|
+
} else {
|
|
15874
|
+
scalarSet[key] = val;
|
|
15875
|
+
}
|
|
15590
15876
|
}
|
|
15591
|
-
|
|
15592
|
-
|
|
15593
|
-
|
|
15594
|
-
|
|
15595
|
-
|
|
15596
|
-
const
|
|
15597
|
-
|
|
15598
|
-
|
|
15599
|
-
|
|
15600
|
-
|
|
15601
|
-
|
|
15602
|
-
|
|
15603
|
-
|
|
15604
|
-
|
|
15605
|
-
|
|
15606
|
-
|
|
15607
|
-
|
|
15608
|
-
|
|
15609
|
-
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
const enrichedUnifiedDecisions = [
|
|
15614
|
-
...allUnifiedIncludeDecisions
|
|
15615
|
-
];
|
|
15616
|
-
stripJoinColumnsForAggregation(enrichedUnifiedDecisions, execIntent);
|
|
15617
|
-
applyJoinHydrationPrefixes(enrichedUnifiedDecisions);
|
|
15618
|
-
const includedRelations = new Set(
|
|
15619
|
-
enrichedUnifiedDecisions.filter((d) => d.type === "includeStrategy").map((d) => d.relationName).filter(Boolean)
|
|
15620
|
-
);
|
|
15621
|
-
if (includedRelations.size > 0) {
|
|
15622
|
-
const relationColumnsMap = buildRelationColumnsMap(
|
|
15623
|
-
decisions,
|
|
15624
|
-
includedRelations
|
|
15625
|
-
);
|
|
15626
|
-
injectAndValidateRelationColumns(
|
|
15627
|
-
enrichedUnifiedDecisions,
|
|
15628
|
-
relationColumnsMap,
|
|
15629
|
-
options?.model ?? deps.model
|
|
15630
|
-
);
|
|
15877
|
+
}
|
|
15878
|
+
const hasScalarSet = Object.keys(scalarSet).length > 0;
|
|
15879
|
+
const mergedFirstRow = hasScalarSet ? { ...firstRow, ...scalarSet } : firstRow;
|
|
15880
|
+
const columns = Object.keys(mergedFirstRow);
|
|
15881
|
+
const values = (intent.values ?? []).map((row) => {
|
|
15882
|
+
const mergedRow = hasScalarSet ? { ...row, ...scalarSet } : row;
|
|
15883
|
+
return columns.map((col) => mergedRow[col]);
|
|
15884
|
+
});
|
|
15885
|
+
const conflictTarget = {};
|
|
15886
|
+
if ("columns" in intent.onConflict) {
|
|
15887
|
+
conflictTarget.columns = [...intent.onConflict.columns];
|
|
15888
|
+
} else if ("constraint" in intent.onConflict) {
|
|
15889
|
+
conflictTarget.constraint = intent.onConflict.constraint;
|
|
15890
|
+
}
|
|
15891
|
+
const conflictAction = intent.action.type === "doNothing" ? "nothing" : "update";
|
|
15892
|
+
let updateColumns;
|
|
15893
|
+
if (intent.action.type === "doUpdate") {
|
|
15894
|
+
if (intent.action.set) {
|
|
15895
|
+
updateColumns = Object.keys(intent.action.set);
|
|
15896
|
+
} else {
|
|
15897
|
+
const conflictCols = "columns" in intent.onConflict ? intent.onConflict.columns : [];
|
|
15898
|
+
updateColumns = columns.filter((col) => !conflictCols.includes(col));
|
|
15631
15899
|
}
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
|
|
15900
|
+
}
|
|
15901
|
+
const columnTypes = getColumnTypes(intent.table, columns, deps);
|
|
15902
|
+
const hasRawExprs = Object.keys(rawExprs).length > 0;
|
|
15903
|
+
const actionWhere = intent.action.type === "doUpdate" && intent.action.where ? intent.action.where : void 0;
|
|
15904
|
+
const resolvedActionWhere = actionWhere ? resolveExistsIntent(actionWhere, intent.table, deps) : void 0;
|
|
15905
|
+
const config = {
|
|
15906
|
+
table: intent.table,
|
|
15907
|
+
columns,
|
|
15908
|
+
values,
|
|
15909
|
+
conflictTarget,
|
|
15910
|
+
conflictAction,
|
|
15911
|
+
...updateColumns && { updateColumns },
|
|
15912
|
+
...intent.returning && { returning: [...intent.returning] },
|
|
15913
|
+
...columnTypes && { columnTypes },
|
|
15914
|
+
...hasRawExprs && { updateExpressions: rawExprs },
|
|
15915
|
+
...resolvedActionWhere && {
|
|
15916
|
+
actionWhereIntent: resolvedActionWhere,
|
|
15917
|
+
compileActionWhere: (where, paramState) => compileUpsertActionWhere(
|
|
15918
|
+
where,
|
|
15919
|
+
intent.table,
|
|
15920
|
+
paramState,
|
|
15921
|
+
deps,
|
|
15922
|
+
schemaName
|
|
15923
|
+
)
|
|
15924
|
+
}
|
|
15925
|
+
};
|
|
15926
|
+
const maxBatchSize = options?.maxBatchSize;
|
|
15927
|
+
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
15928
|
+
throw new InvalidOperationError3(
|
|
15929
|
+
"upsert",
|
|
15930
|
+
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
15659
15931
|
);
|
|
15660
|
-
} else {
|
|
15661
|
-
simplifiedPlan = {
|
|
15662
|
-
rootTable: plan.rootTable,
|
|
15663
|
-
decisions: bridgeLegacyDecisions(plan.decisions),
|
|
15664
|
-
...schemaName ? { schema: schemaName } : {}
|
|
15665
|
-
};
|
|
15666
15932
|
}
|
|
15667
|
-
const
|
|
15933
|
+
const batchThreshold = options?.batchThreshold ?? 50;
|
|
15934
|
+
const useUnnest = values.length > 0 && (batchThreshold === 0 || values.length > batchThreshold);
|
|
15935
|
+
const ast = useUnnest ? compileUnnestUpsert(config, ctx, state) : compileUpsert(config, ctx, state);
|
|
15936
|
+
const sql = deparseQuoted(ast);
|
|
15668
15937
|
return {
|
|
15669
|
-
sql
|
|
15670
|
-
parameters:
|
|
15938
|
+
sql,
|
|
15939
|
+
parameters: state.parameters
|
|
15671
15940
|
};
|
|
15672
15941
|
}
|
|
15673
|
-
function
|
|
15674
|
-
const
|
|
15675
|
-
const
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
|
|
15679
|
-
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
|
|
15683
|
-
|
|
15684
|
-
|
|
15685
|
-
|
|
15686
|
-
|
|
15687
|
-
|
|
15688
|
-
|
|
15689
|
-
|
|
15690
|
-
|
|
15691
|
-
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
|
|
15698
|
-
entry.relationType = ctx.relationType;
|
|
15699
|
-
}
|
|
15700
|
-
if (includeIntent?.select != null) {
|
|
15701
|
-
entry.select = includeIntent.select;
|
|
15702
|
-
}
|
|
15703
|
-
if (includeIntent?.where != null) {
|
|
15704
|
-
entry.where = includeIntent.where;
|
|
15942
|
+
function compileUpsertFrom2(intent, options, deps) {
|
|
15943
|
+
const schemaName = deps.schemaName;
|
|
15944
|
+
const sourceCte = intent.sourceQuery !== void 0 && !hasBindingName(deps.bindingNames, intent.source, deps.naming) ? compileSourceQueryCte(
|
|
15945
|
+
"compileUpsertFrom",
|
|
15946
|
+
intent.source,
|
|
15947
|
+
intent.sourceQuery,
|
|
15948
|
+
options,
|
|
15949
|
+
deps
|
|
15950
|
+
) : void 0;
|
|
15951
|
+
const bindingNames = intent.sourceQuery !== void 0 ? withBindingName(deps.bindingNames, intent.source, deps.naming) : deps.bindingNames;
|
|
15952
|
+
const ctx = {
|
|
15953
|
+
naming: deps.naming,
|
|
15954
|
+
rootTable: intent.source,
|
|
15955
|
+
...schemaName !== void 0 && { schema: schemaName },
|
|
15956
|
+
...bindingNames !== void 0 && { bindingNames },
|
|
15957
|
+
maxRecursiveDepth: 100
|
|
15958
|
+
};
|
|
15959
|
+
const state = createCompilerState();
|
|
15960
|
+
let columns;
|
|
15961
|
+
if (intent.columns) {
|
|
15962
|
+
columns = [...intent.columns];
|
|
15963
|
+
} else if (options?.model) {
|
|
15964
|
+
const targetTable = options.model.getTable(intent.table);
|
|
15965
|
+
if (targetTable) {
|
|
15966
|
+
columns = targetTable.columns.map((c) => c.name);
|
|
15705
15967
|
}
|
|
15706
|
-
subqueryIncludes.push(entry);
|
|
15707
15968
|
}
|
|
15708
|
-
|
|
15969
|
+
const config = {
|
|
15970
|
+
targetTable: intent.table,
|
|
15971
|
+
sourceTable: intent.source,
|
|
15972
|
+
conflictColumns: [...intent.conflictColumns],
|
|
15973
|
+
...columns && { columns },
|
|
15974
|
+
...intent.where && { where: [whereIntentAsDecision(intent.where)] },
|
|
15975
|
+
...intent.limit !== void 0 && { limit: intent.limit },
|
|
15976
|
+
...intent.returning && { returning: [...intent.returning] }
|
|
15977
|
+
};
|
|
15978
|
+
const ast = compileUpsertFrom(config, ctx, state);
|
|
15979
|
+
const sql = deparseQuoted(ast);
|
|
15980
|
+
return prependSourceCte(
|
|
15981
|
+
sql,
|
|
15982
|
+
state.parameters,
|
|
15983
|
+
intent.source,
|
|
15984
|
+
sourceCte,
|
|
15985
|
+
deps.naming
|
|
15986
|
+
);
|
|
15709
15987
|
}
|
|
15710
15988
|
|
|
15711
15989
|
// src/adapter-compiler-recursive.ts
|
|
@@ -16794,6 +17072,7 @@ function buildRecursiveAnchorWhere(where, tableAlias, deps, state) {
|
|
|
16794
17072
|
// src/pgsql-adapter.ts
|
|
16795
17073
|
init_assert_field();
|
|
16796
17074
|
init_ast_helpers();
|
|
17075
|
+
init_binding_registry();
|
|
16797
17076
|
|
|
16798
17077
|
// src/ddl/index-operations.ts
|
|
16799
17078
|
init_validate();
|
|
@@ -16960,9 +17239,9 @@ function compileLeafOrBranch(intent, compileFn) {
|
|
|
16960
17239
|
const result = compileFn(intent);
|
|
16961
17240
|
return { sql: result.sql, parameters: result.parameters };
|
|
16962
17241
|
}
|
|
16963
|
-
function createLeafCompileFn(adapter, model,
|
|
17242
|
+
function createLeafCompileFn(adapter, model, planFn3, options) {
|
|
16964
17243
|
return (query) => {
|
|
16965
|
-
const planReport =
|
|
17244
|
+
const planReport = planFn3(query, model, {
|
|
16966
17245
|
dialectCapabilities: adapter.dialectCapabilities
|
|
16967
17246
|
});
|
|
16968
17247
|
return adapter.compile(planReport, { ...options, model });
|
|
@@ -17084,7 +17363,7 @@ function mapFetchDirection(direction) {
|
|
|
17084
17363
|
|
|
17085
17364
|
// src/pgsql-adapter.ts
|
|
17086
17365
|
init_validate();
|
|
17087
|
-
function
|
|
17366
|
+
function renumberSqlParams2(sql, offset) {
|
|
17088
17367
|
if (offset === 0) return sql;
|
|
17089
17368
|
return sql.replace(/\$(\d+)/g, (_match, num) => {
|
|
17090
17369
|
return `$${Number.parseInt(num, 10) + offset}`;
|
|
@@ -17093,6 +17372,79 @@ function renumberSqlParams(sql, offset) {
|
|
|
17093
17372
|
function isCompiledNqlQuery(input) {
|
|
17094
17373
|
return !("intent" in input) && ("query" in input || "cteQuery" in input || "mutation" in input || "setOperation" in input || "bindings" in input || "mutationBindings" in input);
|
|
17095
17374
|
}
|
|
17375
|
+
function formatGuardPathSegment(key) {
|
|
17376
|
+
return /^[A-Za-z_$][\w$]*$/.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
17377
|
+
}
|
|
17378
|
+
function findNqlBindingRefMarker(value, path, seen = /* @__PURE__ */ new WeakSet()) {
|
|
17379
|
+
if (value === null || typeof value !== "object") {
|
|
17380
|
+
return void 0;
|
|
17381
|
+
}
|
|
17382
|
+
if (isNqlBindingRef2(value)) {
|
|
17383
|
+
return {
|
|
17384
|
+
ref: getNqlBindingRefName2(value),
|
|
17385
|
+
path
|
|
17386
|
+
};
|
|
17387
|
+
}
|
|
17388
|
+
if (seen.has(value)) {
|
|
17389
|
+
return void 0;
|
|
17390
|
+
}
|
|
17391
|
+
seen.add(value);
|
|
17392
|
+
if (Array.isArray(value)) {
|
|
17393
|
+
for (let i = 0; i < value.length; i++) {
|
|
17394
|
+
const found = findNqlBindingRefMarker(value[i], `${path}[${i}]`, seen);
|
|
17395
|
+
if (found) return found;
|
|
17396
|
+
}
|
|
17397
|
+
return void 0;
|
|
17398
|
+
}
|
|
17399
|
+
const record = value;
|
|
17400
|
+
for (const key of Object.keys(record)) {
|
|
17401
|
+
const found = findNqlBindingRefMarker(
|
|
17402
|
+
record[key],
|
|
17403
|
+
`${path}${formatGuardPathSegment(key)}`,
|
|
17404
|
+
seen
|
|
17405
|
+
);
|
|
17406
|
+
if (found) return found;
|
|
17407
|
+
}
|
|
17408
|
+
return void 0;
|
|
17409
|
+
}
|
|
17410
|
+
function guardCompiledQuery(query, context) {
|
|
17411
|
+
const found = findNqlBindingRefMarker(query.parameters, "parameters");
|
|
17412
|
+
if (found) {
|
|
17413
|
+
throw new Error(
|
|
17414
|
+
`NQL binding reference marker '${found.ref}' survived into emitted SQL parameters at ${found.path} while compiling ${context}. Binding references must resolve to CTE subqueries before SQL emission.`
|
|
17415
|
+
);
|
|
17416
|
+
}
|
|
17417
|
+
return query;
|
|
17418
|
+
}
|
|
17419
|
+
function guardCompileResultWithIncludes(result, context) {
|
|
17420
|
+
return {
|
|
17421
|
+
...result,
|
|
17422
|
+
main: guardCompiledQuery(result.main, context)
|
|
17423
|
+
};
|
|
17424
|
+
}
|
|
17425
|
+
function findPhysicalTableNameCollision(model, bindingName, naming) {
|
|
17426
|
+
for (const [modelTableName, table] of model.tables) {
|
|
17427
|
+
if (bindingName === table.name) return table.name;
|
|
17428
|
+
if (bindingName === modelTableName) return table.name;
|
|
17429
|
+
const emittedTableName = naming.toDatabase(table.name);
|
|
17430
|
+
if (bindingName === emittedTableName) return emittedTableName;
|
|
17431
|
+
const emittedModelTableName = naming.toDatabase(modelTableName);
|
|
17432
|
+
if (bindingName === emittedModelTableName) return emittedModelTableName;
|
|
17433
|
+
}
|
|
17434
|
+
return void 0;
|
|
17435
|
+
}
|
|
17436
|
+
function findDuplicateEmittedNqlBindingName(bindingNames, naming) {
|
|
17437
|
+
const seen = /* @__PURE__ */ new Map();
|
|
17438
|
+
for (const bindingName of bindingNames) {
|
|
17439
|
+
const emittedName = emittedBindName(bindingName, naming);
|
|
17440
|
+
const originalName = seen.get(emittedName);
|
|
17441
|
+
if (originalName !== void 0 && originalName !== bindingName) {
|
|
17442
|
+
return { originalName, duplicateName: bindingName, emittedName };
|
|
17443
|
+
}
|
|
17444
|
+
seen.set(emittedName, bindingName);
|
|
17445
|
+
}
|
|
17446
|
+
return void 0;
|
|
17447
|
+
}
|
|
17096
17448
|
var PgsqlAdapter = class _PgsqlAdapter {
|
|
17097
17449
|
pool;
|
|
17098
17450
|
client;
|
|
@@ -17159,17 +17511,19 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17159
17511
|
...overrides
|
|
17160
17512
|
};
|
|
17161
17513
|
}
|
|
17162
|
-
buildCompileDeps(options) {
|
|
17514
|
+
buildCompileDeps(options, bindingNames) {
|
|
17163
17515
|
if (options?.schemaName) {
|
|
17164
17516
|
validateIdentifier(options.schemaName, "schema");
|
|
17165
17517
|
}
|
|
17518
|
+
const naming = options?.naming ?? this.naming;
|
|
17166
17519
|
return {
|
|
17167
|
-
naming
|
|
17520
|
+
naming,
|
|
17168
17521
|
// `||` (not `??`): empty string is treated as "no override" and falls back to this.schemaName (which may be a configured schema or undefined)
|
|
17169
17522
|
schemaName: options?.schemaName || this.schemaName,
|
|
17170
17523
|
model: options?.model ?? this.model,
|
|
17171
17524
|
defaultPk: this.defaultPk,
|
|
17172
|
-
deriveFk: this.deriveFk
|
|
17525
|
+
deriveFk: this.deriveFk,
|
|
17526
|
+
...bindingNames !== void 0 && { bindingNames }
|
|
17173
17527
|
};
|
|
17174
17528
|
}
|
|
17175
17529
|
requireNqlCompileModel(options) {
|
|
@@ -17181,7 +17535,24 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17181
17535
|
}
|
|
17182
17536
|
return model;
|
|
17183
17537
|
}
|
|
17184
|
-
|
|
17538
|
+
assertNqlBindingNamesDisjointFromTables(bindingNames, options) {
|
|
17539
|
+
if (bindingNames === void 0 || bindingNames.size === 0) return;
|
|
17540
|
+
const model = this.requireNqlCompileModel(options);
|
|
17541
|
+
const naming = this.buildCompileDeps(options, bindingNames).naming;
|
|
17542
|
+
for (const bindingName of bindingNames) {
|
|
17543
|
+
const physicalTableName = findPhysicalTableNameCollision(
|
|
17544
|
+
model,
|
|
17545
|
+
bindingName,
|
|
17546
|
+
naming
|
|
17547
|
+
);
|
|
17548
|
+
if (physicalTableName !== void 0) {
|
|
17549
|
+
throw new Error(
|
|
17550
|
+
`NQL binding '${bindingName}' collides with physical table name '${physicalTableName}'. NQL binding names must be disjoint from model table names.`
|
|
17551
|
+
);
|
|
17552
|
+
}
|
|
17553
|
+
}
|
|
17554
|
+
}
|
|
17555
|
+
compileNqlMutation(bundle, options, bindingNames) {
|
|
17185
17556
|
const mutation = bundle.mutation;
|
|
17186
17557
|
if (mutation === void 0) {
|
|
17187
17558
|
throw new Error("NQL bundle did not contain a mutation intent.");
|
|
@@ -17191,84 +17562,124 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17191
17562
|
return compileInsert2(
|
|
17192
17563
|
mutation,
|
|
17193
17564
|
options,
|
|
17194
|
-
this.buildCompileDeps(options)
|
|
17565
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17195
17566
|
);
|
|
17196
17567
|
case "insert_from":
|
|
17197
17568
|
return compileInsertFrom2(
|
|
17198
17569
|
mutation,
|
|
17199
17570
|
options,
|
|
17200
|
-
this.buildCompileDeps(options)
|
|
17571
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17201
17572
|
);
|
|
17202
17573
|
case "update":
|
|
17203
17574
|
return compileUpdate2(
|
|
17204
17575
|
mutation,
|
|
17205
17576
|
options,
|
|
17206
|
-
this.buildCompileDeps(options)
|
|
17577
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17207
17578
|
);
|
|
17208
17579
|
case "delete":
|
|
17209
17580
|
return compileDelete2(
|
|
17210
17581
|
mutation,
|
|
17211
17582
|
options,
|
|
17212
|
-
this.buildCompileDeps(options)
|
|
17583
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17213
17584
|
);
|
|
17214
17585
|
case "upsert":
|
|
17215
17586
|
return compileUpsert2(
|
|
17216
17587
|
mutation,
|
|
17217
17588
|
options,
|
|
17218
|
-
this.buildCompileDeps(options)
|
|
17589
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17219
17590
|
);
|
|
17220
17591
|
case "upsert_from":
|
|
17221
17592
|
return compileUpsertFrom2(
|
|
17222
17593
|
mutation,
|
|
17223
17594
|
options,
|
|
17224
|
-
this.buildCompileDeps(options)
|
|
17595
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17225
17596
|
);
|
|
17226
17597
|
}
|
|
17227
17598
|
throw new Error(
|
|
17228
17599
|
`Unsupported NQL mutation type: ${mutation.type}`
|
|
17229
17600
|
);
|
|
17230
17601
|
}
|
|
17231
|
-
compileNqlBundleLeaf(bundle, options) {
|
|
17602
|
+
compileNqlBundleLeaf(bundle, options, bindingNames) {
|
|
17232
17603
|
if (bundle.query !== void 0) {
|
|
17604
|
+
const naming = this.buildCompileDeps(options, bindingNames).naming;
|
|
17605
|
+
if (hasBindingName(bindingNames, bundle.query.from, naming)) {
|
|
17606
|
+
throw new Error(
|
|
17607
|
+
`NQL binding '${bundle.query.from}' cannot be used as the final FROM source yet. Use the binding from a mutation source or WHERE IN predicate, or select from a real table.`
|
|
17608
|
+
);
|
|
17609
|
+
}
|
|
17233
17610
|
const model = this.requireNqlCompileModel(options);
|
|
17234
|
-
const planReport =
|
|
17611
|
+
const planReport = planFn2(bundle.query, model, {
|
|
17235
17612
|
dialectCapabilities: this.dialectCapabilities
|
|
17236
17613
|
});
|
|
17237
|
-
return
|
|
17238
|
-
|
|
17239
|
-
|
|
17240
|
-
|
|
17614
|
+
return guardCompiledQuery(
|
|
17615
|
+
compileSelect(
|
|
17616
|
+
planReport,
|
|
17617
|
+
options,
|
|
17618
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17619
|
+
),
|
|
17620
|
+
"NQL query"
|
|
17241
17621
|
);
|
|
17242
17622
|
}
|
|
17243
17623
|
if (bundle.cteQuery !== void 0) {
|
|
17244
|
-
return
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17624
|
+
return guardCompiledQuery(
|
|
17625
|
+
compileCteQuery(
|
|
17626
|
+
bundle.cteQuery,
|
|
17627
|
+
options,
|
|
17628
|
+
this.buildCompileDeps(options, bindingNames)
|
|
17629
|
+
),
|
|
17630
|
+
"NQL CTE query"
|
|
17248
17631
|
);
|
|
17249
17632
|
}
|
|
17250
17633
|
if (bundle.setOperation !== void 0) {
|
|
17251
17634
|
const model = this.requireNqlCompileModel(options);
|
|
17252
|
-
return
|
|
17253
|
-
|
|
17254
|
-
|
|
17255
|
-
|
|
17635
|
+
return guardCompiledQuery(
|
|
17636
|
+
this.compileSetOperationWithBindings(
|
|
17637
|
+
bundle.setOperation,
|
|
17638
|
+
model,
|
|
17639
|
+
options,
|
|
17640
|
+
bindingNames
|
|
17641
|
+
),
|
|
17642
|
+
"NQL set operation"
|
|
17256
17643
|
);
|
|
17257
17644
|
}
|
|
17258
17645
|
if (bundle.mutation !== void 0) {
|
|
17259
|
-
return
|
|
17646
|
+
return guardCompiledQuery(
|
|
17647
|
+
this.compileNqlMutation(
|
|
17648
|
+
bundle,
|
|
17649
|
+
options,
|
|
17650
|
+
bindingNames
|
|
17651
|
+
),
|
|
17652
|
+
"NQL mutation"
|
|
17653
|
+
);
|
|
17260
17654
|
}
|
|
17261
17655
|
throw new Error("NQL bundle did not contain a compilable intent.");
|
|
17262
17656
|
}
|
|
17263
17657
|
compileNqlBundle(bundle, options) {
|
|
17264
17658
|
const ctes = [];
|
|
17265
17659
|
const parameters = [];
|
|
17660
|
+
const naming = this.buildCompileDeps(options).naming;
|
|
17661
|
+
const duplicateEmittedBinding = bundle.bindings !== void 0 ? findDuplicateEmittedNqlBindingName(bundle.bindings.keys(), naming) : void 0;
|
|
17662
|
+
if (duplicateEmittedBinding !== void 0) {
|
|
17663
|
+
throw new Error(
|
|
17664
|
+
`NQL bindings '${duplicateEmittedBinding.originalName}' and '${duplicateEmittedBinding.duplicateName}' emit to duplicate CTE name '${duplicateEmittedBinding.emittedName}'. NQL binding names must be unique after database naming.`
|
|
17665
|
+
);
|
|
17666
|
+
}
|
|
17667
|
+
const bindingNames = bundle.bindings !== void 0 ? new Set(
|
|
17668
|
+
[...bundle.bindings.keys()].map(
|
|
17669
|
+
(name) => emittedBindName(name, naming)
|
|
17670
|
+
)
|
|
17671
|
+
) : void 0;
|
|
17672
|
+
this.assertNqlBindingNamesDisjointFromTables(bindingNames, options);
|
|
17266
17673
|
for (const [name, queryIntent] of bundle.bindings ?? []) {
|
|
17267
|
-
const cteName = quoteIdent2(name, "alias");
|
|
17674
|
+
const cteName = quoteIdent2(emittedBindName(name, naming), "alias");
|
|
17268
17675
|
const bindingBundle = bundle.mutationBindings?.has(name) ? { mutation: bundle.mutationBindings.get(name) } : { query: queryIntent };
|
|
17269
|
-
const compiled2 = this.compileNqlBundleLeaf(
|
|
17676
|
+
const compiled2 = this.compileNqlBundleLeaf(
|
|
17677
|
+
bindingBundle,
|
|
17678
|
+
options,
|
|
17679
|
+
bindingNames
|
|
17680
|
+
);
|
|
17270
17681
|
ctes.push(
|
|
17271
|
-
`${cteName} as (${
|
|
17682
|
+
`${cteName} as (${renumberSqlParams2(compiled2.sql, parameters.length)})`
|
|
17272
17683
|
);
|
|
17273
17684
|
parameters.push(...compiled2.parameters);
|
|
17274
17685
|
}
|
|
@@ -17281,14 +17692,21 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17281
17692
|
setOperation: bundle.setOperation
|
|
17282
17693
|
}
|
|
17283
17694
|
};
|
|
17284
|
-
const compiled = this.compileNqlBundleLeaf(
|
|
17695
|
+
const compiled = this.compileNqlBundleLeaf(
|
|
17696
|
+
leafBundle,
|
|
17697
|
+
options,
|
|
17698
|
+
bindingNames
|
|
17699
|
+
);
|
|
17285
17700
|
if (ctes.length === 0) {
|
|
17286
|
-
return compiled;
|
|
17701
|
+
return guardCompiledQuery(compiled, "NQL bundle");
|
|
17287
17702
|
}
|
|
17288
|
-
return
|
|
17289
|
-
|
|
17290
|
-
|
|
17291
|
-
|
|
17703
|
+
return guardCompiledQuery(
|
|
17704
|
+
{
|
|
17705
|
+
sql: `WITH ${ctes.join(", ")} ${renumberSqlParams2(compiled.sql, parameters.length)}`,
|
|
17706
|
+
parameters: [...parameters, ...compiled.parameters]
|
|
17707
|
+
},
|
|
17708
|
+
"NQL bundle"
|
|
17709
|
+
);
|
|
17292
17710
|
}
|
|
17293
17711
|
/**
|
|
17294
17712
|
* Returns the pool/client executor, or throws if in compile-only mode.
|
|
@@ -17308,7 +17726,7 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17308
17726
|
}
|
|
17309
17727
|
/** PostgreSQL dialect capabilities for planner strategy selection */
|
|
17310
17728
|
get dialectCapabilities() {
|
|
17311
|
-
return
|
|
17729
|
+
return POSTGRESQL_CAPABILITIES2;
|
|
17312
17730
|
}
|
|
17313
17731
|
/**
|
|
17314
17732
|
* DB column casing convention used by this adapter.
|
|
@@ -17332,16 +17750,18 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17332
17750
|
if (isCompiledNqlQuery(plan)) {
|
|
17333
17751
|
return this.compileNqlBundle(plan, options);
|
|
17334
17752
|
}
|
|
17335
|
-
return
|
|
17753
|
+
return guardCompiledQuery(
|
|
17754
|
+
compileSelect(plan, options, this.buildCompileDeps(options)),
|
|
17755
|
+
"select plan"
|
|
17756
|
+
);
|
|
17336
17757
|
}
|
|
17337
17758
|
/**
|
|
17338
17759
|
* Compile a plan with includes, returning subquery include metadata (DX-033).
|
|
17339
17760
|
*/
|
|
17340
17761
|
compileWithIncludes(plan, options) {
|
|
17341
|
-
return
|
|
17342
|
-
plan,
|
|
17343
|
-
|
|
17344
|
-
this.buildCompileDeps(options)
|
|
17762
|
+
return guardCompileResultWithIncludes(
|
|
17763
|
+
compileWithIncludes(plan, options, this.buildCompileDeps(options)),
|
|
17764
|
+
"select plan with includes"
|
|
17345
17765
|
);
|
|
17346
17766
|
}
|
|
17347
17767
|
/**
|
|
@@ -17354,11 +17774,14 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17354
17774
|
* @returns Compiled query for fetching related records
|
|
17355
17775
|
*/
|
|
17356
17776
|
compileSubqueryInclude(info, parentIds, options) {
|
|
17357
|
-
return
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17361
|
-
|
|
17777
|
+
return guardCompiledQuery(
|
|
17778
|
+
compileSubqueryInclude(
|
|
17779
|
+
info,
|
|
17780
|
+
parentIds,
|
|
17781
|
+
options,
|
|
17782
|
+
this.buildCompileDeps(options)
|
|
17783
|
+
),
|
|
17784
|
+
"subquery include"
|
|
17362
17785
|
);
|
|
17363
17786
|
}
|
|
17364
17787
|
/**
|
|
@@ -17402,7 +17825,10 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17402
17825
|
targetList: [{ ResTarget: { val: node } }]
|
|
17403
17826
|
});
|
|
17404
17827
|
const sql = deparseQuoted(ast);
|
|
17405
|
-
return
|
|
17828
|
+
return guardCompiledQuery(
|
|
17829
|
+
{ sql, parameters: state.parameters },
|
|
17830
|
+
"select expression"
|
|
17831
|
+
);
|
|
17406
17832
|
}
|
|
17407
17833
|
/**
|
|
17408
17834
|
* Compile an insert intent to executable SQL.
|
|
@@ -17412,24 +17838,29 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17412
17838
|
* - rows > batchThreshold OR batchThreshold === 0: SELECT unnest($1::type[]),...
|
|
17413
17839
|
*/
|
|
17414
17840
|
compileInsert(intent, options) {
|
|
17415
|
-
return
|
|
17841
|
+
return guardCompiledQuery(
|
|
17842
|
+
compileInsert2(intent, options, this.buildCompileDeps(options)),
|
|
17843
|
+
"insert"
|
|
17844
|
+
);
|
|
17416
17845
|
}
|
|
17417
17846
|
/**
|
|
17418
17847
|
* Compile an insert-from intent to executable SQL (NQL-ALIGN).
|
|
17419
17848
|
* INSERT INTO target (cols) SELECT cols FROM source WHERE ... LIMIT ... RETURNING ...
|
|
17420
17849
|
*/
|
|
17421
17850
|
compileInsertFrom(intent, options) {
|
|
17422
|
-
return
|
|
17423
|
-
intent,
|
|
17424
|
-
|
|
17425
|
-
this.buildCompileDeps(options)
|
|
17851
|
+
return guardCompiledQuery(
|
|
17852
|
+
compileInsertFrom2(intent, options, this.buildCompileDeps(options)),
|
|
17853
|
+
"insert from"
|
|
17426
17854
|
);
|
|
17427
17855
|
}
|
|
17428
17856
|
/**
|
|
17429
17857
|
* Compile an update intent to executable SQL.
|
|
17430
17858
|
*/
|
|
17431
17859
|
compileUpdate(intent, options) {
|
|
17432
|
-
return
|
|
17860
|
+
return guardCompiledQuery(
|
|
17861
|
+
compileUpdate2(intent, options, this.buildCompileDeps(options)),
|
|
17862
|
+
"update"
|
|
17863
|
+
);
|
|
17433
17864
|
}
|
|
17434
17865
|
/**
|
|
17435
17866
|
* Compile a batch update intent to executable SQL using unnest FROM strategy (BATCH-001).
|
|
@@ -17441,33 +17872,37 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17441
17872
|
* [RETURNING ...]
|
|
17442
17873
|
*/
|
|
17443
17874
|
compileBatchUpdate(intent, options) {
|
|
17444
|
-
return
|
|
17445
|
-
intent,
|
|
17446
|
-
|
|
17447
|
-
this.buildCompileDeps(options)
|
|
17875
|
+
return guardCompiledQuery(
|
|
17876
|
+
compileBatchUpdate(intent, options, this.buildCompileDeps(options)),
|
|
17877
|
+
"batch update"
|
|
17448
17878
|
);
|
|
17449
17879
|
}
|
|
17450
17880
|
/**
|
|
17451
17881
|
* Compile a delete intent to executable SQL.
|
|
17452
17882
|
*/
|
|
17453
17883
|
compileDelete(intent, options) {
|
|
17454
|
-
return
|
|
17884
|
+
return guardCompiledQuery(
|
|
17885
|
+
compileDelete2(intent, options, this.buildCompileDeps(options)),
|
|
17886
|
+
"delete"
|
|
17887
|
+
);
|
|
17455
17888
|
}
|
|
17456
17889
|
/**
|
|
17457
17890
|
* Compile an upsert intent to executable SQL (DX-026).
|
|
17458
17891
|
*/
|
|
17459
17892
|
compileUpsert(intent, options) {
|
|
17460
|
-
return
|
|
17893
|
+
return guardCompiledQuery(
|
|
17894
|
+
compileUpsert2(intent, options, this.buildCompileDeps(options)),
|
|
17895
|
+
"upsert"
|
|
17896
|
+
);
|
|
17461
17897
|
}
|
|
17462
17898
|
/**
|
|
17463
17899
|
* Compile an upsert-from intent to executable SQL (NQL-BIND).
|
|
17464
17900
|
* INSERT INTO target SELECT ... FROM source ON CONFLICT (cols) DO UPDATE SET ...
|
|
17465
17901
|
*/
|
|
17466
17902
|
compileUpsertFrom(intent, options) {
|
|
17467
|
-
return
|
|
17468
|
-
intent,
|
|
17469
|
-
|
|
17470
|
-
this.buildCompileDeps(options)
|
|
17903
|
+
return guardCompiledQuery(
|
|
17904
|
+
compileUpsertFrom2(intent, options, this.buildCompileDeps(options)),
|
|
17905
|
+
"upsert from"
|
|
17471
17906
|
);
|
|
17472
17907
|
}
|
|
17473
17908
|
/**
|
|
@@ -17475,11 +17910,14 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17475
17910
|
* Supports adjacency-list and edge-table traversal modes.
|
|
17476
17911
|
*/
|
|
17477
17912
|
compileRecursive(report, model, options) {
|
|
17478
|
-
return
|
|
17479
|
-
|
|
17480
|
-
|
|
17481
|
-
|
|
17482
|
-
|
|
17913
|
+
return guardCompiledQuery(
|
|
17914
|
+
compileRecursive(
|
|
17915
|
+
report,
|
|
17916
|
+
model,
|
|
17917
|
+
options,
|
|
17918
|
+
this.buildCompileDeps(options)
|
|
17919
|
+
),
|
|
17920
|
+
"recursive query"
|
|
17483
17921
|
);
|
|
17484
17922
|
}
|
|
17485
17923
|
/**
|
|
@@ -17490,18 +17928,42 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
17490
17928
|
* to start after CTE params and prepend WITH clause.
|
|
17491
17929
|
*/
|
|
17492
17930
|
compileCteQuery(intent, options) {
|
|
17493
|
-
return
|
|
17931
|
+
return guardCompiledQuery(
|
|
17932
|
+
compileCteQuery(intent, options, this.buildCompileDeps(options)),
|
|
17933
|
+
"CTE query"
|
|
17934
|
+
);
|
|
17494
17935
|
}
|
|
17495
17936
|
/**
|
|
17496
17937
|
* Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.
|
|
17497
17938
|
*/
|
|
17498
17939
|
compileSetOperation(intent, model, options) {
|
|
17499
|
-
|
|
17940
|
+
return guardCompiledQuery(
|
|
17941
|
+
this.compileSetOperationWithBindings(intent, model, options),
|
|
17942
|
+
"set operation"
|
|
17943
|
+
);
|
|
17944
|
+
}
|
|
17945
|
+
compileSetOperationWithBindings(intent, model, options, bindingNames) {
|
|
17946
|
+
const compileFn = createLeafCompileFn(
|
|
17947
|
+
{
|
|
17948
|
+
dialectCapabilities: this.dialectCapabilities,
|
|
17949
|
+
compile: (planReport, leafOptions) => compileSelect(
|
|
17950
|
+
planReport,
|
|
17951
|
+
leafOptions,
|
|
17952
|
+
this.buildCompileDeps(leafOptions, bindingNames)
|
|
17953
|
+
)
|
|
17954
|
+
},
|
|
17955
|
+
model,
|
|
17956
|
+
planFn2,
|
|
17957
|
+
options
|
|
17958
|
+
);
|
|
17500
17959
|
const result = compileSetOperation(intent, compileFn);
|
|
17501
|
-
return
|
|
17502
|
-
|
|
17503
|
-
|
|
17504
|
-
|
|
17960
|
+
return guardCompiledQuery(
|
|
17961
|
+
{
|
|
17962
|
+
sql: result.sql,
|
|
17963
|
+
parameters: result.parameters
|
|
17964
|
+
},
|
|
17965
|
+
"set operation"
|
|
17966
|
+
);
|
|
17505
17967
|
}
|
|
17506
17968
|
/**
|
|
17507
17969
|
* Create a dump for observability.
|