@dbsp/adapter-pgsql 1.1.1 → 1.2.1
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 +50 -16
- package/dist/index.js +996 -215
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1074,6 +1074,19 @@ var init_param_ref = __esm({
|
|
|
1074
1074
|
}
|
|
1075
1075
|
});
|
|
1076
1076
|
|
|
1077
|
+
// src/handlers/expression/param-value.ts
|
|
1078
|
+
function bindParameter(value, state) {
|
|
1079
|
+
const idx = ++state.paramIndex;
|
|
1080
|
+
state.parameters.push(value);
|
|
1081
|
+
return createParamRef(idx);
|
|
1082
|
+
}
|
|
1083
|
+
var init_param_value = __esm({
|
|
1084
|
+
"src/handlers/expression/param-value.ts"() {
|
|
1085
|
+
"use strict";
|
|
1086
|
+
init_param_ref();
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1077
1090
|
// src/handlers/expression/case-value.ts
|
|
1078
1091
|
function resolveCaseValue(value, alias, schema, naming, state, nestedCaseHandler) {
|
|
1079
1092
|
if (value === null || value === void 0) {
|
|
@@ -1083,12 +1096,12 @@ function resolveCaseValue(value, alias, schema, naming, state, nestedCaseHandler
|
|
|
1083
1096
|
return columnRef(value, alias, schema, naming);
|
|
1084
1097
|
}
|
|
1085
1098
|
if (typeof value !== "object") {
|
|
1086
|
-
|
|
1087
|
-
state.parameters.push(value);
|
|
1088
|
-
return createParamRef(idx);
|
|
1099
|
+
return bindParameter(value, state);
|
|
1089
1100
|
}
|
|
1090
1101
|
const expr = value;
|
|
1091
1102
|
switch (expr.kind) {
|
|
1103
|
+
case "param":
|
|
1104
|
+
return bindParameter(expr.value, state);
|
|
1092
1105
|
case "literal":
|
|
1093
1106
|
if (expr.value === null || expr.value === void 0)
|
|
1094
1107
|
return nullConstNode();
|
|
@@ -1099,11 +1112,7 @@ function resolveCaseValue(value, alias, schema, naming, state, nestedCaseHandler
|
|
|
1099
1112
|
return integerNode(expr.value);
|
|
1100
1113
|
return floatNode(String(expr.value));
|
|
1101
1114
|
}
|
|
1102
|
-
|
|
1103
|
-
const idx = ++state.paramIndex;
|
|
1104
|
-
state.parameters.push(expr.value);
|
|
1105
|
-
return createParamRef(idx);
|
|
1106
|
-
}
|
|
1115
|
+
return bindParameter(expr.value, state);
|
|
1107
1116
|
case "column":
|
|
1108
1117
|
return columnRef(expr.column, alias, schema, naming);
|
|
1109
1118
|
case "arithmetic": {
|
|
@@ -1139,9 +1148,7 @@ function resolveCaseValue(value, alias, schema, naming, state, nestedCaseHandler
|
|
|
1139
1148
|
}
|
|
1140
1149
|
// falls through
|
|
1141
1150
|
default: {
|
|
1142
|
-
|
|
1143
|
-
state.parameters.push(value);
|
|
1144
|
-
return createParamRef(idx);
|
|
1151
|
+
return bindParameter(value, state);
|
|
1145
1152
|
}
|
|
1146
1153
|
}
|
|
1147
1154
|
}
|
|
@@ -1149,7 +1156,7 @@ var init_case_value = __esm({
|
|
|
1149
1156
|
"src/handlers/expression/case-value.ts"() {
|
|
1150
1157
|
"use strict";
|
|
1151
1158
|
init_ast_helpers();
|
|
1152
|
-
|
|
1159
|
+
init_param_value();
|
|
1153
1160
|
}
|
|
1154
1161
|
});
|
|
1155
1162
|
|
|
@@ -1348,7 +1355,9 @@ function compileExpressionIntent(intent, ctx, state) {
|
|
|
1348
1355
|
}
|
|
1349
1356
|
case "relationColumn": {
|
|
1350
1357
|
const rc = intent;
|
|
1351
|
-
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;
|
|
1352
1361
|
return columnRef(rc.column, alias, void 0, ctx.naming);
|
|
1353
1362
|
}
|
|
1354
1363
|
case "case": {
|
|
@@ -1428,7 +1437,17 @@ function handleAggregateExpression(expr, rootTable, decisions, applyFilter) {
|
|
|
1428
1437
|
const aggAs = expr.as;
|
|
1429
1438
|
const aggDistinct = expr.distinct;
|
|
1430
1439
|
const aggFilter = expr.filter;
|
|
1431
|
-
|
|
1440
|
+
const aggExtraArgs = Array.isArray(expr.extraArgs) ? expr.extraArgs : void 0;
|
|
1441
|
+
if (!aggField && aggExtraArgs?.length) {
|
|
1442
|
+
const decision = {
|
|
1443
|
+
type: "selectNqlFunction",
|
|
1444
|
+
function: aggFunc,
|
|
1445
|
+
args: aggExtraArgs,
|
|
1446
|
+
table: rootTable
|
|
1447
|
+
};
|
|
1448
|
+
if (aggAs) decision.alias = aggAs;
|
|
1449
|
+
decisions.push(decision);
|
|
1450
|
+
} else if (aggFunc === "count" && !aggField) {
|
|
1432
1451
|
const decision = {
|
|
1433
1452
|
type: "selectFunction",
|
|
1434
1453
|
function: "count",
|
|
@@ -1480,6 +1499,16 @@ function handleRawExpression(expr, rootTable, decisions) {
|
|
|
1480
1499
|
if (expr.as) decision.alias = expr.as;
|
|
1481
1500
|
decisions.push(decision);
|
|
1482
1501
|
}
|
|
1502
|
+
function handleFunctionExpression(expr, rootTable, decisions) {
|
|
1503
|
+
const decision = {
|
|
1504
|
+
type: "selectNqlFunction",
|
|
1505
|
+
function: expr.name,
|
|
1506
|
+
args: expr.args ?? [],
|
|
1507
|
+
table: rootTable
|
|
1508
|
+
};
|
|
1509
|
+
if (expr.as) decision.alias = expr.as;
|
|
1510
|
+
decisions.push(decision);
|
|
1511
|
+
}
|
|
1483
1512
|
function handleWindowExpression(expr, rootTable, decisions) {
|
|
1484
1513
|
const windowFunc = expr.function;
|
|
1485
1514
|
const windowAlias = expr.alias;
|
|
@@ -1592,6 +1621,7 @@ var init_select_expression_handlers = __esm({
|
|
|
1592
1621
|
aggregate: (expr, rootTable, decisions, applyFilter) => handleAggregateExpression(expr, rootTable, decisions, applyFilter),
|
|
1593
1622
|
coalesce: (expr, rootTable, decisions) => handleCoalesceExpression(expr, rootTable, decisions),
|
|
1594
1623
|
raw: (expr, rootTable, decisions) => handleRawExpression(expr, rootTable, decisions),
|
|
1624
|
+
function: (expr, rootTable, decisions) => handleFunctionExpression(expr, rootTable, decisions),
|
|
1595
1625
|
window: (expr, rootTable, decisions) => handleWindowExpression(expr, rootTable, decisions),
|
|
1596
1626
|
case: (expr, rootTable, decisions, applyFilter, convertCondition) => handleCaseExpression(
|
|
1597
1627
|
expr,
|
|
@@ -1601,7 +1631,8 @@ var init_select_expression_handlers = __esm({
|
|
|
1601
1631
|
convertCondition
|
|
1602
1632
|
),
|
|
1603
1633
|
relationColumn: (expr, rootTable, decisions) => handleRelationColumnExpression(expr, rootTable, decisions),
|
|
1604
|
-
|
|
1634
|
+
pseudoColumn: () => {
|
|
1635
|
+
},
|
|
1605
1636
|
arithmetic: (expr, rootTable, decisions) => handleArithmeticExpression(expr, rootTable, decisions),
|
|
1606
1637
|
jsonExtract: (expr, rootTable, decisions) => handleJsonExtractExpression(expr, rootTable, decisions),
|
|
1607
1638
|
jsonPathExtract: (expr, rootTable, decisions) => handleJsonPathExtractExpression(expr, rootTable, decisions),
|
|
@@ -1612,12 +1643,17 @@ var init_select_expression_handlers = __esm({
|
|
|
1612
1643
|
ref: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1613
1644
|
param: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1614
1645
|
cast: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1615
|
-
unary: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions)
|
|
1646
|
+
unary: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1647
|
+
subquery: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1648
|
+
namedArg: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1649
|
+
star: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions),
|
|
1650
|
+
array: (expr, rootTable, decisions) => handleCustomExpressionSelect(expr, rootTable, decisions)
|
|
1616
1651
|
};
|
|
1617
1652
|
}
|
|
1618
1653
|
});
|
|
1619
1654
|
|
|
1620
1655
|
// src/intent-to-decisions.ts
|
|
1656
|
+
import { isParamIntent } from "@dbsp/types";
|
|
1621
1657
|
function intentToDecisions(intent, rootTable) {
|
|
1622
1658
|
const decisions = [];
|
|
1623
1659
|
if (intent.select) {
|
|
@@ -1680,16 +1716,18 @@ function convertSelect(select, rootTable) {
|
|
|
1680
1716
|
const columns = select.columns;
|
|
1681
1717
|
for (const exprUnknown of columns) {
|
|
1682
1718
|
const expr = exprUnknown;
|
|
1683
|
-
const
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
rootTable,
|
|
1688
|
-
decisions,
|
|
1689
|
-
applyFilterCondition,
|
|
1690
|
-
convertWhereCondition
|
|
1691
|
-
);
|
|
1719
|
+
const kind = typeof expr.kind === "string" ? expr.kind : String(expr.kind);
|
|
1720
|
+
const handler = EXPRESSION_HANDLERS[kind];
|
|
1721
|
+
if (!handler) {
|
|
1722
|
+
throw new UnknownSelectExpressionKindError(kind);
|
|
1692
1723
|
}
|
|
1724
|
+
handler(
|
|
1725
|
+
expr,
|
|
1726
|
+
rootTable,
|
|
1727
|
+
decisions,
|
|
1728
|
+
(decision, filter, table) => applyFilterCondition(decision, filter, table),
|
|
1729
|
+
(condition, table) => convertWhereCondition(condition, table)
|
|
1730
|
+
);
|
|
1693
1731
|
}
|
|
1694
1732
|
return decisions;
|
|
1695
1733
|
}
|
|
@@ -1822,10 +1860,12 @@ function isOuterRef(value) {
|
|
|
1822
1860
|
function containsOuterRef(where) {
|
|
1823
1861
|
if (!where || typeof where !== "object") return false;
|
|
1824
1862
|
const w = where;
|
|
1863
|
+
if (isParamIntent(w)) return false;
|
|
1825
1864
|
if (isOuterRef(w)) return true;
|
|
1826
1865
|
for (const value of Object.values(w)) {
|
|
1827
1866
|
if (Array.isArray(value)) {
|
|
1828
|
-
for (
|
|
1867
|
+
for (let i = 0; i < value.length; i++) {
|
|
1868
|
+
const item = value[i];
|
|
1829
1869
|
if (containsOuterRef(item)) return true;
|
|
1830
1870
|
}
|
|
1831
1871
|
} else if (typeof value === "object" && value !== null) {
|
|
@@ -2122,7 +2162,7 @@ function convertWhereCondition(condition, rootTable) {
|
|
|
2122
2162
|
table: rootTable
|
|
2123
2163
|
};
|
|
2124
2164
|
}
|
|
2125
|
-
case "jsonContains":
|
|
2165
|
+
case "jsonContains": {
|
|
2126
2166
|
return {
|
|
2127
2167
|
type: "where",
|
|
2128
2168
|
column: cond.field,
|
|
@@ -2130,6 +2170,7 @@ function convertWhereCondition(condition, rootTable) {
|
|
|
2130
2170
|
value: cond.value,
|
|
2131
2171
|
table: rootTable
|
|
2132
2172
|
};
|
|
2173
|
+
}
|
|
2133
2174
|
case "any":
|
|
2134
2175
|
return {
|
|
2135
2176
|
type: "where",
|
|
@@ -2186,10 +2227,20 @@ function convertOrderBy(order, rootTable) {
|
|
|
2186
2227
|
}
|
|
2187
2228
|
return decision;
|
|
2188
2229
|
}
|
|
2230
|
+
var UnknownSelectExpressionKindError;
|
|
2189
2231
|
var init_intent_to_decisions = __esm({
|
|
2190
2232
|
"src/intent-to-decisions.ts"() {
|
|
2191
2233
|
"use strict";
|
|
2192
2234
|
init_select_expression_handlers();
|
|
2235
|
+
UnknownSelectExpressionKindError = class extends Error {
|
|
2236
|
+
constructor(kind) {
|
|
2237
|
+
super(`Unknown SELECT expression kind: ${kind}`);
|
|
2238
|
+
this.kind = kind;
|
|
2239
|
+
this.name = "UnknownSelectExpressionKindError";
|
|
2240
|
+
}
|
|
2241
|
+
kind;
|
|
2242
|
+
code = "ERR_ADAPTER_UNKNOWN_SELECT_EXPRESSION_KIND";
|
|
2243
|
+
};
|
|
2193
2244
|
}
|
|
2194
2245
|
});
|
|
2195
2246
|
|
|
@@ -2750,12 +2801,24 @@ var init_compiler_utils = __esm({
|
|
|
2750
2801
|
}
|
|
2751
2802
|
});
|
|
2752
2803
|
|
|
2804
|
+
// src/param-intent.ts
|
|
2805
|
+
import { isParamIntent as isParamIntent2 } from "@dbsp/types";
|
|
2806
|
+
function unwrapParamIntent(value) {
|
|
2807
|
+
return isParamIntent2(value) ? value.value : value;
|
|
2808
|
+
}
|
|
2809
|
+
var init_param_intent = __esm({
|
|
2810
|
+
"src/param-intent.ts"() {
|
|
2811
|
+
"use strict";
|
|
2812
|
+
}
|
|
2813
|
+
});
|
|
2814
|
+
|
|
2753
2815
|
// src/handlers/where/utils.ts
|
|
2754
|
-
import { isFieldRef } from "@dbsp/types";
|
|
2816
|
+
import { isFieldRef, isParamIntent as isParamIntent3 } from "@dbsp/types";
|
|
2755
2817
|
function buildColumnRef(column, ctx) {
|
|
2756
2818
|
if (column.includes(".")) {
|
|
2757
|
-
const dotIndex = column.
|
|
2758
|
-
const
|
|
2819
|
+
const dotIndex = column.lastIndexOf(".");
|
|
2820
|
+
const relation = column.substring(0, dotIndex);
|
|
2821
|
+
const table = ctx.aliases?.get(relation) ?? relation;
|
|
2759
2822
|
const col = column.substring(dotIndex + 1);
|
|
2760
2823
|
return columnRef(col, table, void 0, ctx.naming);
|
|
2761
2824
|
}
|
|
@@ -2763,15 +2826,27 @@ function buildColumnRef(column, ctx) {
|
|
|
2763
2826
|
return columnRef(column, alias, void 0, ctx.naming);
|
|
2764
2827
|
}
|
|
2765
2828
|
function buildParamRef(value, state) {
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2829
|
+
const boundValue = unwrapParamIntent(value);
|
|
2830
|
+
if (isParamRef(boundValue)) {
|
|
2831
|
+
state.parameters.push(boundValue.value);
|
|
2832
|
+
return createParamRef(boundValue.paramIndex);
|
|
2769
2833
|
}
|
|
2770
2834
|
state.paramIndex++;
|
|
2771
|
-
state.parameters.push(
|
|
2835
|
+
state.parameters.push(boundValue);
|
|
2772
2836
|
return createParamRef(state.paramIndex);
|
|
2773
2837
|
}
|
|
2774
|
-
function compileValue(value, state, columnType) {
|
|
2838
|
+
function compileValue(value, state, columnType, forceParam = false) {
|
|
2839
|
+
const boundValue = unwrapParamIntent(value);
|
|
2840
|
+
if (isParamIntent3(value)) {
|
|
2841
|
+
const idx2 = ++state.paramIndex;
|
|
2842
|
+
state.parameters.push(boundValue);
|
|
2843
|
+
return columnType ? createTypeCastParamRef(idx2, columnType) : createParamRef(idx2);
|
|
2844
|
+
}
|
|
2845
|
+
if (forceParam) {
|
|
2846
|
+
const idx2 = ++state.paramIndex;
|
|
2847
|
+
state.parameters.push(boundValue);
|
|
2848
|
+
return columnType ? createTypeCastParamRef(idx2, columnType) : createParamRef(idx2);
|
|
2849
|
+
}
|
|
2775
2850
|
if (value === null || value === void 0) {
|
|
2776
2851
|
return nullConstNode();
|
|
2777
2852
|
}
|
|
@@ -2783,7 +2858,10 @@ function compileValue(value, state, columnType) {
|
|
|
2783
2858
|
state.parameters.push(value);
|
|
2784
2859
|
return columnType ? createTypeCastParamRef(idx, columnType) : createParamRef(idx);
|
|
2785
2860
|
}
|
|
2786
|
-
function compileValueOrFieldRef(value, ctx, state, columnType) {
|
|
2861
|
+
function compileValueOrFieldRef(value, ctx, state, columnType, forceParam = false) {
|
|
2862
|
+
if (forceParam || isParamIntent3(value)) {
|
|
2863
|
+
return compileValue(value, state, columnType, true);
|
|
2864
|
+
}
|
|
2787
2865
|
if (isFieldRef(value)) {
|
|
2788
2866
|
const alias = value.scope === "outer" ? ctx.outerAlias ?? ctx.rootTable : ctx.currentAlias ?? ctx.rootTable;
|
|
2789
2867
|
return columnRef(value.column, alias, void 0, ctx.naming);
|
|
@@ -2803,9 +2881,11 @@ var init_utils = __esm({
|
|
|
2803
2881
|
"src/handlers/where/utils.ts"() {
|
|
2804
2882
|
"use strict";
|
|
2805
2883
|
init_ast_helpers();
|
|
2884
|
+
init_param_intent();
|
|
2806
2885
|
init_param_ref();
|
|
2807
2886
|
init_validate();
|
|
2808
2887
|
init_types();
|
|
2888
|
+
init_param_intent();
|
|
2809
2889
|
}
|
|
2810
2890
|
});
|
|
2811
2891
|
|
|
@@ -2835,6 +2915,7 @@ var init_any = __esm({
|
|
|
2835
2915
|
"src/handlers/where/any.ts"() {
|
|
2836
2916
|
"use strict";
|
|
2837
2917
|
init_compiler_utils();
|
|
2918
|
+
init_param_intent();
|
|
2838
2919
|
init_param_ref();
|
|
2839
2920
|
init_types();
|
|
2840
2921
|
init_utils();
|
|
@@ -2845,7 +2926,8 @@ var init_any = __esm({
|
|
|
2845
2926
|
if (!column) {
|
|
2846
2927
|
throw new Error("ANY handler requires a column");
|
|
2847
2928
|
}
|
|
2848
|
-
const
|
|
2929
|
+
const rawValues = unwrapParamIntent(decision.values);
|
|
2930
|
+
const values = Array.isArray(rawValues) ? rawValues : [];
|
|
2849
2931
|
const columnNode = buildColumnRef(column, ctx);
|
|
2850
2932
|
let pgBaseType;
|
|
2851
2933
|
if (decision.dataType) {
|
|
@@ -2875,6 +2957,7 @@ var betweenHandler;
|
|
|
2875
2957
|
var init_between = __esm({
|
|
2876
2958
|
"src/handlers/where/between.ts"() {
|
|
2877
2959
|
"use strict";
|
|
2960
|
+
init_param_intent();
|
|
2878
2961
|
init_param_ref();
|
|
2879
2962
|
init_utils();
|
|
2880
2963
|
betweenHandler = {
|
|
@@ -2884,16 +2967,18 @@ var init_between = __esm({
|
|
|
2884
2967
|
if (!column) {
|
|
2885
2968
|
throw new Error("BETWEEN handler requires a column");
|
|
2886
2969
|
}
|
|
2887
|
-
const range = decision.value;
|
|
2970
|
+
const range = unwrapParamIntent(decision.value);
|
|
2888
2971
|
if (!Array.isArray(range) || range.length !== 2) {
|
|
2889
2972
|
throw new Error("BETWEEN condition requires [min, max] array");
|
|
2890
2973
|
}
|
|
2891
2974
|
const columnNode = buildColumnRef(column, ctx);
|
|
2975
|
+
const minValue = unwrapParamIntent(range[0]);
|
|
2976
|
+
const maxValue = unwrapParamIntent(range[1]);
|
|
2892
2977
|
const minIdx = ++state.paramIndex;
|
|
2893
|
-
state.parameters.push(
|
|
2978
|
+
state.parameters.push(minValue);
|
|
2894
2979
|
const minNode = createParamRef(minIdx);
|
|
2895
2980
|
const maxIdx = ++state.paramIndex;
|
|
2896
|
-
state.parameters.push(
|
|
2981
|
+
state.parameters.push(maxValue);
|
|
2897
2982
|
const maxNode = createParamRef(maxIdx);
|
|
2898
2983
|
return {
|
|
2899
2984
|
A_Expr: {
|
|
@@ -2969,6 +3054,7 @@ var init_custom_expression = __esm({
|
|
|
2969
3054
|
"src/handlers/where/custom-expression.ts"() {
|
|
2970
3055
|
"use strict";
|
|
2971
3056
|
init_ast_helpers();
|
|
3057
|
+
init_param_intent();
|
|
2972
3058
|
init_param_ref();
|
|
2973
3059
|
init_custom();
|
|
2974
3060
|
OP_MAP = {
|
|
@@ -2994,7 +3080,7 @@ var init_custom_expression = __esm({
|
|
|
2994
3080
|
return leftNode;
|
|
2995
3081
|
}
|
|
2996
3082
|
const idx = ++state.paramIndex;
|
|
2997
|
-
state.parameters.push(decision.value);
|
|
3083
|
+
state.parameters.push(unwrapParamIntent(decision.value));
|
|
2998
3084
|
const rightNode = createParamRef(idx);
|
|
2999
3085
|
const rawOp = decision.subqueryOperator ?? decision.operator ?? "=";
|
|
3000
3086
|
const sqlOp = OP_MAP[rawOp];
|
|
@@ -3202,6 +3288,7 @@ var init_exists = __esm({
|
|
|
3202
3288
|
});
|
|
3203
3289
|
|
|
3204
3290
|
// src/handlers/where/in.ts
|
|
3291
|
+
import { isParamIntent as isParamIntent4 } from "@dbsp/types";
|
|
3205
3292
|
function createInExpr(columnNode, state, values, columnType) {
|
|
3206
3293
|
state.paramIndex++;
|
|
3207
3294
|
state.parameters.push(values);
|
|
@@ -3228,11 +3315,22 @@ function createNotInExpr(columnNode, state, values, columnType) {
|
|
|
3228
3315
|
}
|
|
3229
3316
|
};
|
|
3230
3317
|
}
|
|
3318
|
+
function isWholeArrayParamList(value) {
|
|
3319
|
+
return value.length === 1 && isParamIntent4(value[0]) && Array.isArray(value[0].value);
|
|
3320
|
+
}
|
|
3321
|
+
function unwrapCompilerInListValues(value) {
|
|
3322
|
+
const values = [];
|
|
3323
|
+
for (const item of value) {
|
|
3324
|
+
values.push(unwrapParamIntent(item));
|
|
3325
|
+
}
|
|
3326
|
+
return values;
|
|
3327
|
+
}
|
|
3231
3328
|
var inHandler;
|
|
3232
3329
|
var init_in = __esm({
|
|
3233
3330
|
"src/handlers/where/in.ts"() {
|
|
3234
3331
|
"use strict";
|
|
3235
3332
|
init_ast_helpers();
|
|
3333
|
+
init_param_intent();
|
|
3236
3334
|
init_param_ref();
|
|
3237
3335
|
init_types();
|
|
3238
3336
|
init_utils();
|
|
@@ -3241,7 +3339,7 @@ var init_in = __esm({
|
|
|
3241
3339
|
compile(decision, ctx, state) {
|
|
3242
3340
|
const operator = decision.operator ?? "in";
|
|
3243
3341
|
const column = decision.column;
|
|
3244
|
-
const value = decision.value;
|
|
3342
|
+
const value = unwrapParamIntent(decision.value);
|
|
3245
3343
|
if (!column) {
|
|
3246
3344
|
throw new Error("In handler requires a column");
|
|
3247
3345
|
}
|
|
@@ -3251,7 +3349,7 @@ var init_in = __esm({
|
|
|
3251
3349
|
`[in handler] Received a non-array value for operator '${operator}' on column '${column}'. This is a compiler bug: ${hint}. File a bug report.`
|
|
3252
3350
|
);
|
|
3253
3351
|
}
|
|
3254
|
-
const values = value;
|
|
3352
|
+
const values = isWholeArrayParamList(value) ? value[0].value : unwrapCompilerInListValues(value);
|
|
3255
3353
|
if (values.length === 0) {
|
|
3256
3354
|
if (operator === COLLECTION_OPERATORS.NOT_IN || operator === "notIn") {
|
|
3257
3355
|
return booleanConstNode(true);
|
|
@@ -3494,6 +3592,7 @@ var RANGE_OP_MAP, rangeHandler;
|
|
|
3494
3592
|
var init_range = __esm({
|
|
3495
3593
|
"src/handlers/where/range.ts"() {
|
|
3496
3594
|
"use strict";
|
|
3595
|
+
init_param_intent();
|
|
3497
3596
|
init_param_ref();
|
|
3498
3597
|
init_types();
|
|
3499
3598
|
init_utils();
|
|
@@ -3511,11 +3610,14 @@ var init_range = __esm({
|
|
|
3511
3610
|
}
|
|
3512
3611
|
const operator = decision.operator ?? "contains";
|
|
3513
3612
|
const pgOp = RANGE_OP_MAP[operator] ?? operator;
|
|
3514
|
-
const
|
|
3613
|
+
const rawValue = decision.value;
|
|
3614
|
+
const value = unwrapParamIntent(rawValue);
|
|
3515
3615
|
const columnNode = buildColumnRef(column, ctx);
|
|
3516
3616
|
let paramValue;
|
|
3517
3617
|
let isScalar = false;
|
|
3518
|
-
if (
|
|
3618
|
+
if (value !== rawValue) {
|
|
3619
|
+
paramValue = value;
|
|
3620
|
+
} else if (isRangeValue(value)) {
|
|
3519
3621
|
const lower = value.lower ?? "";
|
|
3520
3622
|
const upper = value.upper ?? "";
|
|
3521
3623
|
paramValue = `[${lower},${upper})`;
|
|
@@ -3699,7 +3801,7 @@ function handleExpressionIntent(intent, ctx, handlerCtx) {
|
|
|
3699
3801
|
return leftNode;
|
|
3700
3802
|
}
|
|
3701
3803
|
const idx = ++ctx.paramState.paramIndex;
|
|
3702
|
-
ctx.paramState.parameters.push(exprIntent.value);
|
|
3804
|
+
ctx.paramState.parameters.push(unwrapParamIntent(exprIntent.value));
|
|
3703
3805
|
const rightNode = createParamRef(idx);
|
|
3704
3806
|
const sqlOp = OP_MAP2[exprIntent.operator] ?? "=";
|
|
3705
3807
|
return binaryExpr(sqlOp, leftNode, rightNode);
|
|
@@ -3981,9 +4083,13 @@ function compileWhereIntent(intent, ctx) {
|
|
|
3981
4083
|
if (exprRefResult !== null) return exprRefResult;
|
|
3982
4084
|
}
|
|
3983
4085
|
const needsColumn = intent.kind === "comparison" || intent.kind === "null";
|
|
4086
|
+
const rawIntent = intent;
|
|
3984
4087
|
const bridged = needsColumn ? {
|
|
3985
4088
|
...intent,
|
|
3986
|
-
column:
|
|
4089
|
+
column: rawIntent.field,
|
|
4090
|
+
..."value" in rawIntent && {
|
|
4091
|
+
value: rawIntent.value
|
|
4092
|
+
}
|
|
3987
4093
|
} : intent;
|
|
3988
4094
|
return dispatcher(bridged, handlerCtx, ctx.paramState);
|
|
3989
4095
|
}
|
|
@@ -3999,6 +4105,7 @@ var init_compile_where = __esm({
|
|
|
3999
4105
|
init_utils();
|
|
4000
4106
|
init_intent_to_decisions();
|
|
4001
4107
|
init_naming_plugin();
|
|
4108
|
+
init_param_intent();
|
|
4002
4109
|
init_param_ref();
|
|
4003
4110
|
registerWhereDispatcherFactory(createWhereDispatcher);
|
|
4004
4111
|
OP_MAP2 = {
|
|
@@ -4037,7 +4144,8 @@ var init_raw_exists = __esm({
|
|
|
4037
4144
|
subIntent,
|
|
4038
4145
|
state.paramIndex,
|
|
4039
4146
|
ctx.naming,
|
|
4040
|
-
ctx.schema
|
|
4147
|
+
ctx.schema,
|
|
4148
|
+
"rawExists"
|
|
4041
4149
|
);
|
|
4042
4150
|
if (innerParams) {
|
|
4043
4151
|
for (const p of innerParams) {
|
|
@@ -4169,6 +4277,7 @@ var init_relation_filter = __esm({
|
|
|
4169
4277
|
});
|
|
4170
4278
|
|
|
4171
4279
|
// src/subquery-emission.ts
|
|
4280
|
+
import { isParamIntent as isParamIntent5 } from "@dbsp/types";
|
|
4172
4281
|
function assertNoDroppedDecisionModifiers(decision, use) {
|
|
4173
4282
|
const d = decision;
|
|
4174
4283
|
const unsupported = [];
|
|
@@ -4287,6 +4396,12 @@ function buildPredicateSubquerySelect(use, sourceIntent, decision, ctx, state, d
|
|
|
4287
4396
|
if (decision.limit != null) {
|
|
4288
4397
|
if (typeof decision.limit === "number") {
|
|
4289
4398
|
stmt.limitCount = integerNode(decision.limit);
|
|
4399
|
+
} else if (isParamIntent5(decision.limit)) {
|
|
4400
|
+
state.parameters.push(unwrapParamIntent(decision.limit));
|
|
4401
|
+
state.paramIndex++;
|
|
4402
|
+
stmt.limitCount = {
|
|
4403
|
+
ParamRef: { number: state.paramIndex }
|
|
4404
|
+
};
|
|
4290
4405
|
} else {
|
|
4291
4406
|
const limitObj = decision.limit;
|
|
4292
4407
|
if (typeof limitObj.paramIndex !== "number") {
|
|
@@ -4304,6 +4419,7 @@ var init_subquery_emission = __esm({
|
|
|
4304
4419
|
"use strict";
|
|
4305
4420
|
init_ast_helpers();
|
|
4306
4421
|
init_intent_to_decisions();
|
|
4422
|
+
init_param_intent();
|
|
4307
4423
|
}
|
|
4308
4424
|
});
|
|
4309
4425
|
|
|
@@ -4714,12 +4830,13 @@ var init_join = __esm({
|
|
|
4714
4830
|
const targets = [];
|
|
4715
4831
|
const columns = decision.columns;
|
|
4716
4832
|
const columnAliases = decision.columnAliases;
|
|
4833
|
+
const hydrationPrefix = decision.hydrationPrefix ?? relation ?? targetAlias;
|
|
4717
4834
|
if (columns && columns.length > 0) {
|
|
4718
4835
|
if (columns.length === 1 && columns[0] === "*") {
|
|
4719
4836
|
targets.push(starTarget(targetAlias, ctx.naming));
|
|
4720
4837
|
} else {
|
|
4721
4838
|
for (const col of columns) {
|
|
4722
|
-
const outputAlias = columnAliases?.[col] ?? `${
|
|
4839
|
+
const outputAlias = columnAliases?.[col] ?? `${hydrationPrefix}.${col}`;
|
|
4723
4840
|
targets.push(columnTarget(col, outputAlias, targetAlias, ctx.naming));
|
|
4724
4841
|
}
|
|
4725
4842
|
}
|
|
@@ -5048,6 +5165,7 @@ __export(handlers_exports, {
|
|
|
5048
5165
|
genericWindowHandler: () => genericWindowHandler,
|
|
5049
5166
|
getExpressionHandler: () => getExpressionHandler,
|
|
5050
5167
|
getIncludeHandler: () => getIncludeHandler,
|
|
5168
|
+
getNqlSafeExpressionHandler: () => getNqlSafeExpressionHandler,
|
|
5051
5169
|
getRegisteredOperators: () => getRegisteredOperators,
|
|
5052
5170
|
getRegistryStats: () => getRegistryStats,
|
|
5053
5171
|
getWhereHandler: () => getWhereHandler,
|
|
@@ -5158,6 +5276,10 @@ function getExpressionHandler(type) {
|
|
|
5158
5276
|
}
|
|
5159
5277
|
return handler;
|
|
5160
5278
|
}
|
|
5279
|
+
function getNqlSafeExpressionHandler(type) {
|
|
5280
|
+
const handler = expressionHandlers.get(type);
|
|
5281
|
+
return handler?.nqlSafe === true ? handler : void 0;
|
|
5282
|
+
}
|
|
5161
5283
|
function getIncludeHandler(strategy) {
|
|
5162
5284
|
const handler = includeHandlers.get(strategy);
|
|
5163
5285
|
if (!handler) {
|
|
@@ -5179,7 +5301,7 @@ function ensureHandlersRegistered() {
|
|
|
5179
5301
|
handlersInitialized = true;
|
|
5180
5302
|
registerAllWhereHandlers();
|
|
5181
5303
|
}
|
|
5182
|
-
function normalizeToDecision(input) {
|
|
5304
|
+
function normalizeToDecision(input, ctx) {
|
|
5183
5305
|
if (input.column !== void 0) {
|
|
5184
5306
|
const raw2 = input;
|
|
5185
5307
|
if (raw2.jsonPath && raw2.jsonPath.length > 0) {
|
|
@@ -5202,7 +5324,7 @@ function normalizeToDecision(input) {
|
|
|
5202
5324
|
type: op3,
|
|
5203
5325
|
operator: op3,
|
|
5204
5326
|
conditions: (raw.conditions ?? []).map(
|
|
5205
|
-
(c) => normalizeToDecision(c)
|
|
5327
|
+
(c) => normalizeToDecision(c, ctx)
|
|
5206
5328
|
)
|
|
5207
5329
|
};
|
|
5208
5330
|
}
|
|
@@ -5214,7 +5336,7 @@ function normalizeToDecision(input) {
|
|
|
5214
5336
|
switch (kind) {
|
|
5215
5337
|
case "comparison": {
|
|
5216
5338
|
if (raw.jsonPath) {
|
|
5217
|
-
|
|
5339
|
+
const decision = {
|
|
5218
5340
|
type: "where",
|
|
5219
5341
|
column: raw.field,
|
|
5220
5342
|
operator: "jsonComparison",
|
|
@@ -5222,6 +5344,7 @@ function normalizeToDecision(input) {
|
|
|
5222
5344
|
jsonPath: raw.jsonPath,
|
|
5223
5345
|
jsonMode: raw.jsonMode ?? "text"
|
|
5224
5346
|
};
|
|
5347
|
+
return decision;
|
|
5225
5348
|
}
|
|
5226
5349
|
return {
|
|
5227
5350
|
type: "where",
|
|
@@ -5235,7 +5358,7 @@ function normalizeToDecision(input) {
|
|
|
5235
5358
|
type: "and",
|
|
5236
5359
|
operator: "and",
|
|
5237
5360
|
conditions: (raw.conditions ?? []).map(
|
|
5238
|
-
(c) => normalizeToDecision(c)
|
|
5361
|
+
(c) => normalizeToDecision(c, ctx)
|
|
5239
5362
|
)
|
|
5240
5363
|
};
|
|
5241
5364
|
case "or":
|
|
@@ -5243,14 +5366,14 @@ function normalizeToDecision(input) {
|
|
|
5243
5366
|
type: "or",
|
|
5244
5367
|
operator: "or",
|
|
5245
5368
|
conditions: (raw.conditions ?? []).map(
|
|
5246
|
-
(c) => normalizeToDecision(c)
|
|
5369
|
+
(c) => normalizeToDecision(c, ctx)
|
|
5247
5370
|
)
|
|
5248
5371
|
};
|
|
5249
5372
|
case "not":
|
|
5250
5373
|
return {
|
|
5251
5374
|
type: "not",
|
|
5252
5375
|
operator: "not",
|
|
5253
|
-
conditions: [normalizeToDecision(raw.condition)]
|
|
5376
|
+
conditions: [normalizeToDecision(raw.condition, ctx)]
|
|
5254
5377
|
};
|
|
5255
5378
|
case "null":
|
|
5256
5379
|
return {
|
|
@@ -5274,7 +5397,7 @@ function normalizeToDecision(input) {
|
|
|
5274
5397
|
);
|
|
5275
5398
|
const rawSelect = sub.select;
|
|
5276
5399
|
const selectColumn = typeof rawSelect === "string" ? rawSelect : isSelectWithFields(rawSelect) ? rawSelect.fields?.[0] ?? "*" : "*";
|
|
5277
|
-
const subConditions = sub.where ? [normalizeToDecision(sub.where)] : [];
|
|
5400
|
+
const subConditions = sub.where ? [normalizeToDecision(sub.where, ctx)] : [];
|
|
5278
5401
|
const rawLimit = sub.limit;
|
|
5279
5402
|
const rawOrderBy = sub.orderBy;
|
|
5280
5403
|
return {
|
|
@@ -5309,13 +5432,14 @@ function normalizeToDecision(input) {
|
|
|
5309
5432
|
operator: raw.caseInsensitive ? "ilike" : "like",
|
|
5310
5433
|
value: raw.pattern
|
|
5311
5434
|
};
|
|
5312
|
-
case "jsonContains":
|
|
5435
|
+
case "jsonContains": {
|
|
5313
5436
|
return {
|
|
5314
5437
|
type: "where",
|
|
5315
5438
|
column: raw.field,
|
|
5316
5439
|
operator: raw.reversed ? "jsonContainedBy" : "jsonContains",
|
|
5317
5440
|
value: raw.value
|
|
5318
5441
|
};
|
|
5442
|
+
}
|
|
5319
5443
|
case "jsonExists":
|
|
5320
5444
|
return {
|
|
5321
5445
|
type: "where",
|
|
@@ -5326,7 +5450,7 @@ function normalizeToDecision(input) {
|
|
|
5326
5450
|
case "exists":
|
|
5327
5451
|
case "notExists": {
|
|
5328
5452
|
const relation = raw.relation;
|
|
5329
|
-
const conditions = raw.where ? [normalizeToDecision(raw.where)] : void 0;
|
|
5453
|
+
const conditions = raw.where ? [normalizeToDecision(raw.where, ctx)] : void 0;
|
|
5330
5454
|
const targetTable = raw.targetTable ?? relation;
|
|
5331
5455
|
const sourceColumn = raw.sourceColumn;
|
|
5332
5456
|
const targetColumn = raw.targetColumn;
|
|
@@ -5355,7 +5479,7 @@ function normalizeToDecision(input) {
|
|
|
5355
5479
|
function createWhereDispatcher() {
|
|
5356
5480
|
return (decision, ctx, state) => {
|
|
5357
5481
|
ensureHandlersRegistered();
|
|
5358
|
-
const normalized = normalizeToDecision(decision);
|
|
5482
|
+
const normalized = normalizeToDecision(decision, ctx);
|
|
5359
5483
|
const rawOperator = normalized.operator ?? "=";
|
|
5360
5484
|
const operator = OPERATOR_ALIASES[rawOperator] ?? rawOperator;
|
|
5361
5485
|
const handler = getWhereHandler(operator);
|
|
@@ -5508,16 +5632,18 @@ function resolveOperand(operand, ctx, state) {
|
|
|
5508
5632
|
const alias = ctx.currentAlias ?? ctx.rootTable;
|
|
5509
5633
|
return columnRef(operand, alias, void 0, ctx.naming);
|
|
5510
5634
|
}
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5635
|
+
if (typeof operand === "object" && operand !== null && "kind" in operand && ctx.compileNqlSelectExpression) {
|
|
5636
|
+
return ctx.compileNqlSelectExpression(operand, ctx, state);
|
|
5637
|
+
}
|
|
5638
|
+
return bindParameter(unwrapParamIntent(operand), state);
|
|
5514
5639
|
}
|
|
5515
5640
|
var arithmeticHandler;
|
|
5516
5641
|
var init_arithmetic = __esm({
|
|
5517
5642
|
"src/handlers/expression/arithmetic.ts"() {
|
|
5518
5643
|
"use strict";
|
|
5519
5644
|
init_ast_helpers();
|
|
5520
|
-
|
|
5645
|
+
init_param_intent();
|
|
5646
|
+
init_param_value();
|
|
5521
5647
|
arithmeticHandler = {
|
|
5522
5648
|
types: ["arithmetic", "math", "calc"],
|
|
5523
5649
|
compile(decision, ctx, state) {
|
|
@@ -5552,8 +5678,9 @@ var init_case = __esm({
|
|
|
5552
5678
|
"src/handlers/expression/case.ts"() {
|
|
5553
5679
|
"use strict";
|
|
5554
5680
|
init_ast_helpers();
|
|
5555
|
-
|
|
5681
|
+
init_param_intent();
|
|
5556
5682
|
init_case_value();
|
|
5683
|
+
init_param_value();
|
|
5557
5684
|
caseHandler = {
|
|
5558
5685
|
types: ["case", "CASE", "caseWhen"],
|
|
5559
5686
|
compile(decision, ctx, state) {
|
|
@@ -5599,13 +5726,12 @@ var init_case = __esm({
|
|
|
5599
5726
|
const tableAlias = ctx.currentAlias ?? ctx.rootTable;
|
|
5600
5727
|
const testExpr = columnRef(column, tableAlias, void 0, ctx.naming);
|
|
5601
5728
|
const args = conditions.map((cond) => {
|
|
5602
|
-
const whenParamNumber = ++state.paramIndex;
|
|
5603
5729
|
const whenDecision = cond.when;
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
const thenResult =
|
|
5730
|
+
const whenExpr = bindParameter(
|
|
5731
|
+
unwrapParamIntent(whenDecision.value ?? cond.when),
|
|
5732
|
+
state
|
|
5733
|
+
);
|
|
5734
|
+
const thenResult = bindParameter(unwrapParamIntent(cond.then), state);
|
|
5609
5735
|
const caseWhen = {
|
|
5610
5736
|
expr: whenExpr,
|
|
5611
5737
|
result: thenResult
|
|
@@ -5614,9 +5740,7 @@ var init_case = __esm({
|
|
|
5614
5740
|
});
|
|
5615
5741
|
let defresult;
|
|
5616
5742
|
if (elseValue !== void 0) {
|
|
5617
|
-
|
|
5618
|
-
state.parameters.push(elseValue);
|
|
5619
|
-
defresult = createParamRef(paramNumber);
|
|
5743
|
+
defresult = bindParameter(unwrapParamIntent(elseValue), state);
|
|
5620
5744
|
}
|
|
5621
5745
|
const caseExpr = {
|
|
5622
5746
|
arg: testExpr,
|
|
@@ -5642,18 +5766,21 @@ function buildValueNode(value, ctx, state) {
|
|
|
5642
5766
|
return columnRef(decision.column, tableAlias, void 0, ctx.naming);
|
|
5643
5767
|
}
|
|
5644
5768
|
}
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5769
|
+
if (typeof value === "object" && value !== null && "kind" in value && ctx.compileNqlSelectExpression) {
|
|
5770
|
+
return ctx.compileNqlSelectExpression(value, ctx, state);
|
|
5771
|
+
}
|
|
5772
|
+
return bindParameter(unwrapParamIntent(value), state);
|
|
5648
5773
|
}
|
|
5649
5774
|
var coalesceHandler, nullIfHandler, greatestHandler, leastHandler;
|
|
5650
5775
|
var init_coalesce = __esm({
|
|
5651
5776
|
"src/handlers/expression/coalesce.ts"() {
|
|
5652
5777
|
"use strict";
|
|
5653
5778
|
init_ast_helpers();
|
|
5654
|
-
|
|
5779
|
+
init_param_intent();
|
|
5780
|
+
init_param_value();
|
|
5655
5781
|
coalesceHandler = {
|
|
5656
5782
|
types: ["coalesce", "COALESCE", "ifNull", "nvl"],
|
|
5783
|
+
nqlSafe: true,
|
|
5657
5784
|
compile(decision, ctx, state) {
|
|
5658
5785
|
const args = decision.args;
|
|
5659
5786
|
const column = decision.column;
|
|
@@ -5693,9 +5820,7 @@ var init_coalesce = __esm({
|
|
|
5693
5820
|
}
|
|
5694
5821
|
const tableAlias = ctx.currentAlias ?? ctx.rootTable;
|
|
5695
5822
|
const colRef = columnRef(column, tableAlias, void 0, ctx.naming);
|
|
5696
|
-
const
|
|
5697
|
-
state.parameters.push(value);
|
|
5698
|
-
const valueRef = createParamRef(paramNumber);
|
|
5823
|
+
const valueRef = bindParameter(unwrapParamIntent(value), state);
|
|
5699
5824
|
return {
|
|
5700
5825
|
NullIfExpr: {
|
|
5701
5826
|
args: [colRef, valueRef]
|
|
@@ -5793,11 +5918,30 @@ var init_column = __esm({
|
|
|
5793
5918
|
});
|
|
5794
5919
|
|
|
5795
5920
|
// src/handlers/expression/json.ts
|
|
5921
|
+
function normalizeJsonPathArgs(args) {
|
|
5922
|
+
if (!args || args.length === 0) return [];
|
|
5923
|
+
if (args.length === 1) {
|
|
5924
|
+
const first = args[0];
|
|
5925
|
+
const unwrappedFirst = unwrapParamIntent(first);
|
|
5926
|
+
if (first !== unwrappedFirst) {
|
|
5927
|
+
return unwrappedFirst;
|
|
5928
|
+
}
|
|
5929
|
+
if (Array.isArray(first)) {
|
|
5930
|
+
return first.map(unwrapParamIntent);
|
|
5931
|
+
}
|
|
5932
|
+
if (typeof first === "string" && first.startsWith("{") && first.endsWith("}")) {
|
|
5933
|
+
const inner = first.slice(1, -1);
|
|
5934
|
+
return inner.length === 0 ? [] : inner.split(",");
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
return args.map(unwrapParamIntent);
|
|
5938
|
+
}
|
|
5796
5939
|
var jsonExtractHandler, jsonPathExtractHandler;
|
|
5797
5940
|
var init_json2 = __esm({
|
|
5798
5941
|
"src/handlers/expression/json.ts"() {
|
|
5799
5942
|
"use strict";
|
|
5800
5943
|
init_ast_helpers();
|
|
5944
|
+
init_param_intent();
|
|
5801
5945
|
init_utils();
|
|
5802
5946
|
jsonExtractHandler = {
|
|
5803
5947
|
types: ["jsonExtract"],
|
|
@@ -5834,10 +5978,10 @@ var init_json2 = __esm({
|
|
|
5834
5978
|
throw new Error("JSON path extract handler requires a column");
|
|
5835
5979
|
}
|
|
5836
5980
|
const mode = decision.jsonMode ?? "text";
|
|
5837
|
-
const
|
|
5981
|
+
const path = normalizeJsonPathArgs(decision.args);
|
|
5838
5982
|
const alias = ctx.currentAlias ?? ctx.rootTable;
|
|
5839
5983
|
const left = columnRef(column, alias, void 0, ctx.naming);
|
|
5840
|
-
const right = compileValue(
|
|
5984
|
+
const right = compileValue(path, state);
|
|
5841
5985
|
const op3 = mode === "text" ? "#>>" : "#>";
|
|
5842
5986
|
return {
|
|
5843
5987
|
A_Expr: {
|
|
@@ -6432,6 +6576,8 @@ var rawHandler, sqlFunctionHandler, literalHandler;
|
|
|
6432
6576
|
var init_raw = __esm({
|
|
6433
6577
|
"src/handlers/expression/raw.ts"() {
|
|
6434
6578
|
"use strict";
|
|
6579
|
+
init_param_intent();
|
|
6580
|
+
init_param_value();
|
|
6435
6581
|
rawHandler = {
|
|
6436
6582
|
types: ["raw", "RAW", "rawSql", "rawExpression"],
|
|
6437
6583
|
compile(decision, ctx, _state) {
|
|
@@ -6466,17 +6612,9 @@ var init_raw = __esm({
|
|
|
6466
6612
|
if (args && Array.isArray(args)) {
|
|
6467
6613
|
for (const arg of args) {
|
|
6468
6614
|
if (typeof arg === "object" && arg !== null && "type" in arg) {
|
|
6469
|
-
|
|
6470
|
-
state.parameters.push(arg);
|
|
6471
|
-
argNodes.push({
|
|
6472
|
-
ParamRef: { number: paramNumber }
|
|
6473
|
-
});
|
|
6615
|
+
argNodes.push(bindParameter(unwrapParamIntent(arg), state));
|
|
6474
6616
|
} else {
|
|
6475
|
-
|
|
6476
|
-
state.parameters.push(arg);
|
|
6477
|
-
argNodes.push({
|
|
6478
|
-
ParamRef: { number: paramNumber }
|
|
6479
|
-
});
|
|
6617
|
+
argNodes.push(bindParameter(unwrapParamIntent(arg), state));
|
|
6480
6618
|
}
|
|
6481
6619
|
}
|
|
6482
6620
|
}
|
|
@@ -6550,7 +6688,7 @@ var init_relation = __esm({
|
|
|
6550
6688
|
if (relation.includes(".")) {
|
|
6551
6689
|
const segments = relation.split(".");
|
|
6552
6690
|
const leaf = segments[segments.length - 1];
|
|
6553
|
-
alias = state.aliases.get(
|
|
6691
|
+
alias = state.aliases.get(relation) ?? state.aliases.get(leaf) ?? leaf;
|
|
6554
6692
|
} else {
|
|
6555
6693
|
alias = state.aliases.get(relation) ?? relation;
|
|
6556
6694
|
}
|
|
@@ -6698,13 +6836,9 @@ function createLagLeadHandler(funcName, types) {
|
|
|
6698
6836
|
const colRef = columnRef(column, tableAlias, void 0, ctx.naming);
|
|
6699
6837
|
const args = [colRef];
|
|
6700
6838
|
const offset = decision.args?.[0] ?? 1;
|
|
6701
|
-
|
|
6702
|
-
state.parameters.push(offset);
|
|
6703
|
-
args.push(createParamRef(offsetParamNumber));
|
|
6839
|
+
args.push(bindParameter(unwrapParamIntent(offset), state));
|
|
6704
6840
|
if (decision.value !== void 0) {
|
|
6705
|
-
|
|
6706
|
-
state.parameters.push(decision.value);
|
|
6707
|
-
args.push(createParamRef(defaultParamNumber));
|
|
6841
|
+
args.push(bindParameter(unwrapParamIntent(decision.value), state));
|
|
6708
6842
|
}
|
|
6709
6843
|
return buildWindowFunction(funcName, args, decision, ctx);
|
|
6710
6844
|
}
|
|
@@ -6730,7 +6864,8 @@ var init_window = __esm({
|
|
|
6730
6864
|
"src/handlers/expression/window.ts"() {
|
|
6731
6865
|
"use strict";
|
|
6732
6866
|
init_ast_helpers();
|
|
6733
|
-
|
|
6867
|
+
init_param_intent();
|
|
6868
|
+
init_param_value();
|
|
6734
6869
|
WINDOW_FRAME_DEFAULT = 1034;
|
|
6735
6870
|
rowNumberHandler = createNoArgWindowHandler("row_number", [
|
|
6736
6871
|
"rowNumber",
|
|
@@ -6747,9 +6882,7 @@ var init_window = __esm({
|
|
|
6747
6882
|
types: ["ntile", "NTILE"],
|
|
6748
6883
|
compile(decision, ctx, state) {
|
|
6749
6884
|
const n = decision.value ?? decision.args?.[0] ?? 4;
|
|
6750
|
-
const
|
|
6751
|
-
state.parameters.push(n);
|
|
6752
|
-
const nRef = createParamRef(paramNumber);
|
|
6885
|
+
const nRef = bindParameter(unwrapParamIntent(n), state);
|
|
6753
6886
|
return buildWindowFunction("ntile", [nRef], decision, ctx);
|
|
6754
6887
|
}
|
|
6755
6888
|
};
|
|
@@ -6790,15 +6923,11 @@ var init_window = __esm({
|
|
|
6790
6923
|
}
|
|
6791
6924
|
if (decision.args && Array.isArray(decision.args)) {
|
|
6792
6925
|
for (const arg of decision.args) {
|
|
6793
|
-
|
|
6794
|
-
state.parameters.push(arg);
|
|
6795
|
-
args.push(createParamRef(paramNumber));
|
|
6926
|
+
args.push(bindParameter(unwrapParamIntent(arg), state));
|
|
6796
6927
|
}
|
|
6797
6928
|
}
|
|
6798
6929
|
if (decision.value !== void 0) {
|
|
6799
|
-
|
|
6800
|
-
state.parameters.push(decision.value);
|
|
6801
|
-
args.push(createParamRef(defaultParamNumber));
|
|
6930
|
+
args.push(bindParameter(unwrapParamIntent(decision.value), state));
|
|
6802
6931
|
}
|
|
6803
6932
|
return buildWindowFunction(funcName, args, decision, ctx);
|
|
6804
6933
|
}
|
|
@@ -6915,6 +7044,12 @@ init_ast_helpers();
|
|
|
6915
7044
|
// src/compiler.ts
|
|
6916
7045
|
init_assert_field();
|
|
6917
7046
|
init_ast_helpers();
|
|
7047
|
+
import { InvalidOperationError as InvalidOperationError2 } from "@dbsp/core";
|
|
7048
|
+
import {
|
|
7049
|
+
isParamIntent as isParamIntent6,
|
|
7050
|
+
NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST,
|
|
7051
|
+
NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST
|
|
7052
|
+
} from "@dbsp/types";
|
|
6918
7053
|
|
|
6919
7054
|
// src/pgsql-deparser.ts
|
|
6920
7055
|
function deparse(node) {
|
|
@@ -7972,6 +8107,7 @@ function deparseQuoted(ast) {
|
|
|
7972
8107
|
init_case_value();
|
|
7973
8108
|
init_custom();
|
|
7974
8109
|
init_expression();
|
|
8110
|
+
init_param_value();
|
|
7975
8111
|
init_window();
|
|
7976
8112
|
init_include();
|
|
7977
8113
|
init_shared();
|
|
@@ -7980,9 +8116,39 @@ init_types();
|
|
|
7980
8116
|
init_utils();
|
|
7981
8117
|
init_intent_to_decisions();
|
|
7982
8118
|
init_naming_plugin();
|
|
8119
|
+
init_param_intent();
|
|
7983
8120
|
init_param_ref();
|
|
7984
8121
|
init_subquery_emission();
|
|
8122
|
+
init_validate();
|
|
7985
8123
|
registerWhereDispatcherFactory(createWhereDispatcher);
|
|
8124
|
+
var UnhandledNqlSelectExpressionKindError = class extends Error {
|
|
8125
|
+
constructor(kind) {
|
|
8126
|
+
super(`Unhandled NQL SELECT expression intent kind: ${kind}`);
|
|
8127
|
+
this.kind = kind;
|
|
8128
|
+
this.name = "UnhandledNqlSelectExpressionKindError";
|
|
8129
|
+
}
|
|
8130
|
+
kind;
|
|
8131
|
+
code = "ERR_ADAPTER_UNHANDLED_NQL_SELECT_EXPRESSION_KIND";
|
|
8132
|
+
};
|
|
8133
|
+
var UnsupportedNqlSelectFunctionError = class extends Error {
|
|
8134
|
+
constructor(functionName) {
|
|
8135
|
+
super(`Unsupported function in SELECT context: ${functionName}()`);
|
|
8136
|
+
this.functionName = functionName;
|
|
8137
|
+
this.name = "UnsupportedNqlSelectFunctionError";
|
|
8138
|
+
}
|
|
8139
|
+
functionName;
|
|
8140
|
+
code = "ERR_ADAPTER_UNSUPPORTED_NQL_SELECT_FUNCTION";
|
|
8141
|
+
};
|
|
8142
|
+
function assertNqlSelectScalarFunctionAllowed(functionName) {
|
|
8143
|
+
if (!NQL_SELECT_SCALAR_FUNCTION_ALLOWLIST.has(functionName.toLowerCase())) {
|
|
8144
|
+
throw new UnsupportedNqlSelectFunctionError(functionName);
|
|
8145
|
+
}
|
|
8146
|
+
}
|
|
8147
|
+
function assertNqlSelectWindowFunctionAllowed(functionName) {
|
|
8148
|
+
if (!NQL_SELECT_WINDOW_FUNCTION_ALLOWLIST.has(functionName.toLowerCase())) {
|
|
8149
|
+
throw new UnsupportedNqlSelectFunctionError(functionName);
|
|
8150
|
+
}
|
|
8151
|
+
}
|
|
7986
8152
|
function mapToHandlerDecision(pd, rootTable, defaultPk, deriveFk) {
|
|
7987
8153
|
return {
|
|
7988
8154
|
type: pd.type,
|
|
@@ -8006,6 +8172,8 @@ function mapToHandlerDecision(pd, rootTable, defaultPk, deriveFk) {
|
|
|
8006
8172
|
strategy: pd.choice === "subquery" ? "json_agg" : pd.choice,
|
|
8007
8173
|
relation: pd.relation ?? pd.relationName,
|
|
8008
8174
|
relationName: pd.relationName,
|
|
8175
|
+
relationPath: pd.relationPath,
|
|
8176
|
+
hydrationPrefix: pd.hydrationPrefix,
|
|
8009
8177
|
relationType: pd.relationType,
|
|
8010
8178
|
foreignKey: pd.foreignKey,
|
|
8011
8179
|
parentKey: pd.parentKey,
|
|
@@ -8058,6 +8226,77 @@ function isPrecompiledJoinDecision(d) {
|
|
|
8058
8226
|
function isBatchValuesJoinDecision(d) {
|
|
8059
8227
|
return isPrecompiledJoinDecision(d) && d.batchValuesParams !== void 0;
|
|
8060
8228
|
}
|
|
8229
|
+
function getRelationIdentityPath(decision, rootTable) {
|
|
8230
|
+
if (decision.relationPath) return decision.relationPath;
|
|
8231
|
+
const relationName = decision.relationName ?? decision.relation;
|
|
8232
|
+
if (!relationName && !decision.targetTable) return void 0;
|
|
8233
|
+
const source = decision.sourceTable ?? rootTable;
|
|
8234
|
+
const target = decision.targetTable ?? "";
|
|
8235
|
+
const sourceColumn = decision.sourceColumn ?? decision.foreignKey ?? "";
|
|
8236
|
+
return `__legacy__:${source}:${relationName ?? target}:${sourceColumn}:${target}`;
|
|
8237
|
+
}
|
|
8238
|
+
function getParentRelationPath(relationPath) {
|
|
8239
|
+
if (!relationPath || relationPath.startsWith("__legacy__:")) return void 0;
|
|
8240
|
+
const lastDot = relationPath.lastIndexOf(".");
|
|
8241
|
+
return lastDot > 0 ? relationPath.slice(0, lastDot) : void 0;
|
|
8242
|
+
}
|
|
8243
|
+
function mergeColumnLists(current, next) {
|
|
8244
|
+
if (!current) return next ? [...next] : void 0;
|
|
8245
|
+
if (!next) return current;
|
|
8246
|
+
if (current.includes("*") || next.includes("*")) return ["*"];
|
|
8247
|
+
const merged = [...current];
|
|
8248
|
+
for (const column of next) {
|
|
8249
|
+
if (!merged.includes(column)) merged.push(column);
|
|
8250
|
+
}
|
|
8251
|
+
return merged;
|
|
8252
|
+
}
|
|
8253
|
+
function mergeDuplicateJoinIncludeDecisions(decisions, rootTable) {
|
|
8254
|
+
const merged = [];
|
|
8255
|
+
const seenByPath = /* @__PURE__ */ new Map();
|
|
8256
|
+
for (const decision of decisions) {
|
|
8257
|
+
const identityPath = decision.type === "includeStrategy" && decision.choice === "join" ? getRelationIdentityPath(decision, rootTable) : void 0;
|
|
8258
|
+
if (!identityPath) {
|
|
8259
|
+
merged.push(decision);
|
|
8260
|
+
continue;
|
|
8261
|
+
}
|
|
8262
|
+
const existing = seenByPath.get(identityPath);
|
|
8263
|
+
if (!existing) {
|
|
8264
|
+
const copy = {
|
|
8265
|
+
...decision,
|
|
8266
|
+
...decision.columns ? { columns: [...decision.columns] } : {},
|
|
8267
|
+
...decision.columnAliases ? { columnAliases: { ...decision.columnAliases } } : {},
|
|
8268
|
+
...decision.conditions ? { conditions: [...decision.conditions] } : {}
|
|
8269
|
+
};
|
|
8270
|
+
seenByPath.set(identityPath, copy);
|
|
8271
|
+
merged.push(copy);
|
|
8272
|
+
continue;
|
|
8273
|
+
}
|
|
8274
|
+
const existingJoinType = existing.joinType ?? "left";
|
|
8275
|
+
const nextJoinType = decision.joinType ?? "left";
|
|
8276
|
+
if (existingJoinType !== nextJoinType) {
|
|
8277
|
+
throw new InvalidOperationError2(
|
|
8278
|
+
"include",
|
|
8279
|
+
`Conflicting join options for relation path '${identityPath}'. Already registered as ${existingJoinType}, got ${nextJoinType}.`
|
|
8280
|
+
);
|
|
8281
|
+
}
|
|
8282
|
+
const mutable = existing;
|
|
8283
|
+
const columns = mergeColumnLists(existing.columns, decision.columns);
|
|
8284
|
+
if (columns) mutable.columns = columns;
|
|
8285
|
+
if (decision.columnAliases) {
|
|
8286
|
+
mutable.columnAliases = {
|
|
8287
|
+
...decision.columnAliases,
|
|
8288
|
+
...existing.columnAliases ?? {}
|
|
8289
|
+
};
|
|
8290
|
+
}
|
|
8291
|
+
if (decision.conditions && decision.conditions.length > 0) {
|
|
8292
|
+
mutable.conditions = [
|
|
8293
|
+
...existing.conditions ?? [],
|
|
8294
|
+
...decision.conditions
|
|
8295
|
+
];
|
|
8296
|
+
}
|
|
8297
|
+
}
|
|
8298
|
+
return merged;
|
|
8299
|
+
}
|
|
8061
8300
|
function renumberParamRefsInAst(node, offset) {
|
|
8062
8301
|
if (offset === 0) return node;
|
|
8063
8302
|
return renumberNode(node, offset);
|
|
@@ -8114,13 +8353,14 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8114
8353
|
/** CTE nodes from include handlers (e.g., CTE strategy) */
|
|
8115
8354
|
pendingCtes = [];
|
|
8116
8355
|
/**
|
|
8117
|
-
* Maps
|
|
8118
|
-
* Populated as join decisions are compiled so later hops can find
|
|
8119
|
-
*
|
|
8356
|
+
* Maps relation-dotted include path → JOIN alias for multi-hop FK resolution.
|
|
8357
|
+
* Populated as join decisions are compiled so later hops can find the
|
|
8358
|
+
* correct source alias (e.g., 'callee.file' reads parent path 'callee').
|
|
8120
8359
|
*/
|
|
8121
8360
|
joinAliasMap = /* @__PURE__ */ new Map();
|
|
8122
8361
|
/**
|
|
8123
8362
|
* Tracks all join aliases in use for the current query.
|
|
8363
|
+
* Entries are stored in emitted database-alias space, after naming.toDatabase().
|
|
8124
8364
|
* Ensures no two JOINs share the same alias (DOUBLE-ALIAS prevention).
|
|
8125
8365
|
*/
|
|
8126
8366
|
usedJoinAliases = /* @__PURE__ */ new Set();
|
|
@@ -8136,6 +8376,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8136
8376
|
return {
|
|
8137
8377
|
naming: this.naming,
|
|
8138
8378
|
rootTable: this.currentRootTable,
|
|
8379
|
+
aliases: this.resolvedJoinAliases(),
|
|
8139
8380
|
maxRecursiveDepth: 100,
|
|
8140
8381
|
defaultPkColumnName: this.defaultPk,
|
|
8141
8382
|
deriveFkColumnName: this.deriveFk,
|
|
@@ -8143,6 +8384,31 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8143
8384
|
...this.model != null && { model: this.model }
|
|
8144
8385
|
};
|
|
8145
8386
|
}
|
|
8387
|
+
findAliasForLegacySourceTable(sourceTable) {
|
|
8388
|
+
let alias;
|
|
8389
|
+
for (const entry of this.joinAliasMap.values()) {
|
|
8390
|
+
if (entry.targetTable === sourceTable) alias = entry.alias;
|
|
8391
|
+
}
|
|
8392
|
+
return alias;
|
|
8393
|
+
}
|
|
8394
|
+
emittedJoinAlias(alias) {
|
|
8395
|
+
const dbAlias = this.naming.toDatabase(alias);
|
|
8396
|
+
validateIdentifier(dbAlias, "alias");
|
|
8397
|
+
return dbAlias;
|
|
8398
|
+
}
|
|
8399
|
+
resolvedJoinAliases() {
|
|
8400
|
+
const aliases = /* @__PURE__ */ new Map();
|
|
8401
|
+
for (const [relationPath, entry] of this.joinAliasMap) {
|
|
8402
|
+
const isLegacyPath = relationPath.startsWith("__legacy__:");
|
|
8403
|
+
if (!isLegacyPath) {
|
|
8404
|
+
aliases.set(relationPath, entry.alias);
|
|
8405
|
+
}
|
|
8406
|
+
if (entry.relationName && (isLegacyPath || relationPath === entry.relationName)) {
|
|
8407
|
+
aliases.set(entry.relationName, entry.alias);
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
return aliases;
|
|
8411
|
+
}
|
|
8146
8412
|
/**
|
|
8147
8413
|
* Dispatch a PlanDecision through the unified WHERE handler system.
|
|
8148
8414
|
* Bridges PlanCompiler's state to handler types, calls dispatcher, syncs back.
|
|
@@ -8293,7 +8559,21 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8293
8559
|
const combined = condNodes.length === 1 ? condNodes[0] : andExpr(...condNodes);
|
|
8294
8560
|
handlerDecision._compiledFilterWhere = combined;
|
|
8295
8561
|
}
|
|
8296
|
-
const
|
|
8562
|
+
const relationIdentityPath = decision.choice === "join" ? getRelationIdentityPath(decision, plan.rootTable) : void 0;
|
|
8563
|
+
const requestedJoinType = decision.joinType ?? "left";
|
|
8564
|
+
const existingJoin = relationIdentityPath ? this.joinAliasMap.get(relationIdentityPath) : void 0;
|
|
8565
|
+
if (existingJoin) {
|
|
8566
|
+
if (existingJoin.joinType !== requestedJoinType) {
|
|
8567
|
+
throw new InvalidOperationError2(
|
|
8568
|
+
"include",
|
|
8569
|
+
`Conflicting join options for relation path '${relationIdentityPath}'. Already registered as ${existingJoin.joinType}, got ${requestedJoinType}.`
|
|
8570
|
+
);
|
|
8571
|
+
}
|
|
8572
|
+
return {};
|
|
8573
|
+
}
|
|
8574
|
+
const parentRelationPath = getParentRelationPath(relationIdentityPath);
|
|
8575
|
+
const parentAlias = parentRelationPath ? this.joinAliasMap.get(parentRelationPath)?.alias : void 0;
|
|
8576
|
+
const sourceAlias = parentAlias ?? (decision.sourceTable && decision.sourceTable !== plan.rootTable ? this.findAliasForLegacySourceTable(decision.sourceTable) ?? decision.sourceTable : plan.rootTable);
|
|
8297
8577
|
const ctx = {
|
|
8298
8578
|
...this.handlerCtx(),
|
|
8299
8579
|
currentAlias: sourceAlias
|
|
@@ -8310,11 +8590,13 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8310
8590
|
const candidateAlias = handlerDecision.relation ?? handlerDecision.targetTable ?? handlerDecision.relationName;
|
|
8311
8591
|
if (candidateAlias) {
|
|
8312
8592
|
let alias = candidateAlias;
|
|
8593
|
+
let emittedAlias = this.emittedJoinAlias(alias);
|
|
8313
8594
|
let counter = 1;
|
|
8314
|
-
while (this.usedJoinAliases.has(
|
|
8595
|
+
while (this.usedJoinAliases.has(emittedAlias)) {
|
|
8315
8596
|
alias = `${candidateAlias}_${counter++}`;
|
|
8597
|
+
emittedAlias = this.emittedJoinAlias(alias);
|
|
8316
8598
|
}
|
|
8317
|
-
this.usedJoinAliases.add(
|
|
8599
|
+
this.usedJoinAliases.add(emittedAlias);
|
|
8318
8600
|
finalJoinAlias = alias;
|
|
8319
8601
|
if (alias !== candidateAlias) {
|
|
8320
8602
|
handlerDecision.relation = alias;
|
|
@@ -8323,11 +8605,15 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8323
8605
|
}
|
|
8324
8606
|
const result = handler.compile(handlerDecision, ctx, handlerState);
|
|
8325
8607
|
this.state.paramIndex = handlerState.paramIndex;
|
|
8326
|
-
if (decision.choice === "join" &&
|
|
8327
|
-
this.joinAliasMap.set(
|
|
8328
|
-
|
|
8329
|
-
|
|
8330
|
-
|
|
8608
|
+
if (decision.choice === "join" && relationIdentityPath && finalJoinAlias) {
|
|
8609
|
+
this.joinAliasMap.set(relationIdentityPath, {
|
|
8610
|
+
alias: finalJoinAlias,
|
|
8611
|
+
joinType: requestedJoinType,
|
|
8612
|
+
...decision.targetTable && { targetTable: decision.targetTable },
|
|
8613
|
+
...(decision.relationName ?? decision.relation) && {
|
|
8614
|
+
relationName: decision.relationName ?? decision.relation
|
|
8615
|
+
}
|
|
8616
|
+
});
|
|
8331
8617
|
}
|
|
8332
8618
|
const out = {};
|
|
8333
8619
|
if (result.targets) out.targets = result.targets;
|
|
@@ -8353,6 +8639,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8353
8639
|
this.rawJoins = [];
|
|
8354
8640
|
this.pendingCtes = [];
|
|
8355
8641
|
this.joinAliasMap = /* @__PURE__ */ new Map();
|
|
8642
|
+
this.usedJoinAliases = /* @__PURE__ */ new Set();
|
|
8356
8643
|
const queryType = this.detectQueryType(plan.decisions);
|
|
8357
8644
|
let ast;
|
|
8358
8645
|
switch (queryType) {
|
|
@@ -8398,11 +8685,14 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8398
8685
|
naming: this.naming,
|
|
8399
8686
|
rootTable: plan.rootTable,
|
|
8400
8687
|
currentAlias: currentAlias ?? plan.rootTable,
|
|
8688
|
+
aliases: this.resolvedJoinAliases(),
|
|
8401
8689
|
maxRecursiveDepth: 100,
|
|
8402
8690
|
defaultPkColumnName: this.defaultPk,
|
|
8403
8691
|
deriveFkColumnName: this.deriveFk,
|
|
8404
8692
|
...plan.schema ?? this.schema ? { schema: plan.schema ?? this.schema } : {},
|
|
8405
|
-
...this.model != null && { model: this.model }
|
|
8693
|
+
...this.model != null && { model: this.model },
|
|
8694
|
+
compileSubquery: (query, paramOffset) => this.compileExpressionSubquery(query, paramOffset),
|
|
8695
|
+
compileNqlSelectExpression: (value, handlerCtx, state) => this.compileNqlFunctionArg(value, handlerCtx, state)
|
|
8406
8696
|
};
|
|
8407
8697
|
}
|
|
8408
8698
|
/** Build a fresh HandlerCompilerState sharing the current parameter array. */
|
|
@@ -8411,10 +8701,251 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8411
8701
|
parameters: this.state.parameters,
|
|
8412
8702
|
paramIndex: this.state.paramIndex,
|
|
8413
8703
|
ctes: /* @__PURE__ */ new Map(),
|
|
8414
|
-
aliases:
|
|
8704
|
+
aliases: this.resolvedJoinAliases(),
|
|
8415
8705
|
joins: []
|
|
8416
8706
|
};
|
|
8417
8707
|
}
|
|
8708
|
+
compileExpressionSubquery(query, paramOffset) {
|
|
8709
|
+
const innerCompiler = new _PlanCompiler({
|
|
8710
|
+
naming: this.naming,
|
|
8711
|
+
...this.schema !== void 0 && {
|
|
8712
|
+
schema: this.schema
|
|
8713
|
+
},
|
|
8714
|
+
defaultPkColumnName: this.defaultPk,
|
|
8715
|
+
deriveFkColumnName: this.deriveFk
|
|
8716
|
+
});
|
|
8717
|
+
const innerPlan = {
|
|
8718
|
+
rootTable: query.from,
|
|
8719
|
+
decisions: intentToDecisions(query, query.from)
|
|
8720
|
+
};
|
|
8721
|
+
const innerResult = innerCompiler.compile(innerPlan);
|
|
8722
|
+
const renumbered = renumberParamRefsInAst(innerResult.ast, paramOffset);
|
|
8723
|
+
return { ast: renumbered, parameters: innerResult.parameters };
|
|
8724
|
+
}
|
|
8725
|
+
compileGenericNqlFunction(functionName, args, ctx, state) {
|
|
8726
|
+
assertNqlSelectScalarFunctionAllowed(functionName);
|
|
8727
|
+
validateIdentifier(functionName, "function");
|
|
8728
|
+
const argNodes = args.map(
|
|
8729
|
+
(arg) => this.compileNqlFunctionArg(arg, ctx, state)
|
|
8730
|
+
);
|
|
8731
|
+
return funcCall(functionName, argNodes);
|
|
8732
|
+
}
|
|
8733
|
+
compileNqlFunctionArg(arg, ctx, state) {
|
|
8734
|
+
if (typeof arg === "string") {
|
|
8735
|
+
return buildColumnRef(arg, ctx);
|
|
8736
|
+
}
|
|
8737
|
+
if (typeof arg === "object" && arg !== null) {
|
|
8738
|
+
const record = arg;
|
|
8739
|
+
if (typeof record.$ref === "string") {
|
|
8740
|
+
return buildColumnRef(record.$ref, ctx);
|
|
8741
|
+
}
|
|
8742
|
+
if (typeof record.kind !== "string") {
|
|
8743
|
+
const legacyKind = typeof record.$op === "string" ? `$op:${record.$op}` : typeof record.$fn === "string" ? `$fn:${record.$fn}` : "object";
|
|
8744
|
+
throw new UnhandledNqlSelectExpressionKindError(legacyKind);
|
|
8745
|
+
}
|
|
8746
|
+
switch (record.kind) {
|
|
8747
|
+
case "column":
|
|
8748
|
+
if (typeof record.column !== "string") {
|
|
8749
|
+
throw new Error("NQL column expression requires a column name");
|
|
8750
|
+
}
|
|
8751
|
+
return buildColumnRef(record.column, ctx);
|
|
8752
|
+
case "columnAlias":
|
|
8753
|
+
if (typeof record.column !== "string") {
|
|
8754
|
+
throw new Error(
|
|
8755
|
+
"NQL columnAlias expression requires a column name"
|
|
8756
|
+
);
|
|
8757
|
+
}
|
|
8758
|
+
return buildColumnRef(record.column, ctx);
|
|
8759
|
+
case "relationColumn": {
|
|
8760
|
+
const relation = record.relation;
|
|
8761
|
+
const column = record.column;
|
|
8762
|
+
if (typeof relation !== "string" || typeof column !== "string") {
|
|
8763
|
+
throw new Error(
|
|
8764
|
+
"NQL relationColumn expression requires relation and column"
|
|
8765
|
+
);
|
|
8766
|
+
}
|
|
8767
|
+
return buildColumnRef(`${relation}.${column}`, ctx);
|
|
8768
|
+
}
|
|
8769
|
+
case "param":
|
|
8770
|
+
if (!("value" in record)) {
|
|
8771
|
+
throw new Error("NQL param expression requires a value");
|
|
8772
|
+
}
|
|
8773
|
+
return bindParameter(record.value, state);
|
|
8774
|
+
case "literal":
|
|
8775
|
+
if (!("value" in record)) {
|
|
8776
|
+
throw new Error("NQL literal expression requires a value");
|
|
8777
|
+
}
|
|
8778
|
+
return compileValue(record.value, state);
|
|
8779
|
+
case "function": {
|
|
8780
|
+
const nestedName = record.name;
|
|
8781
|
+
const nestedArgs = record.args;
|
|
8782
|
+
if (typeof nestedName !== "string") {
|
|
8783
|
+
throw new Error("NQL function argument requires a function name");
|
|
8784
|
+
}
|
|
8785
|
+
return this.compileGenericNqlFunction(
|
|
8786
|
+
nestedName,
|
|
8787
|
+
Array.isArray(nestedArgs) ? nestedArgs : [],
|
|
8788
|
+
ctx,
|
|
8789
|
+
state
|
|
8790
|
+
);
|
|
8791
|
+
}
|
|
8792
|
+
case "coalesce": {
|
|
8793
|
+
const handler = getExpressionHandler("coalesce");
|
|
8794
|
+
return handler.compile(
|
|
8795
|
+
{
|
|
8796
|
+
type: "coalesce",
|
|
8797
|
+
args: Array.isArray(record.fields) ? record.fields : []
|
|
8798
|
+
},
|
|
8799
|
+
ctx,
|
|
8800
|
+
state
|
|
8801
|
+
);
|
|
8802
|
+
}
|
|
8803
|
+
case "aggregate": {
|
|
8804
|
+
const fn4 = record.function;
|
|
8805
|
+
if (typeof fn4 !== "string") {
|
|
8806
|
+
throw new Error(
|
|
8807
|
+
"NQL aggregate expression requires a function name"
|
|
8808
|
+
);
|
|
8809
|
+
}
|
|
8810
|
+
const aggregateArgs = [];
|
|
8811
|
+
if (record.field === "*") {
|
|
8812
|
+
aggregateArgs.push({ kind: "star" });
|
|
8813
|
+
} else if (typeof record.field === "string") {
|
|
8814
|
+
aggregateArgs.push(record.field);
|
|
8815
|
+
}
|
|
8816
|
+
if (Array.isArray(record.extraArgs)) {
|
|
8817
|
+
aggregateArgs.push(...record.extraArgs);
|
|
8818
|
+
}
|
|
8819
|
+
return this.compileGenericNqlFunction(fn4, aggregateArgs, ctx, state);
|
|
8820
|
+
}
|
|
8821
|
+
case "arithmetic": {
|
|
8822
|
+
const operator = record.operator;
|
|
8823
|
+
if (typeof operator !== "string") {
|
|
8824
|
+
throw new Error("NQL arithmetic expression requires an operator");
|
|
8825
|
+
}
|
|
8826
|
+
if (!("left" in record) || !("right" in record)) {
|
|
8827
|
+
throw new Error(
|
|
8828
|
+
"NQL arithmetic expression requires left and right operands"
|
|
8829
|
+
);
|
|
8830
|
+
}
|
|
8831
|
+
const handler = getExpressionHandler("arithmetic");
|
|
8832
|
+
return handler.compile(
|
|
8833
|
+
{
|
|
8834
|
+
type: "arithmetic",
|
|
8835
|
+
operator,
|
|
8836
|
+
args: [record.left, record.right]
|
|
8837
|
+
},
|
|
8838
|
+
ctx,
|
|
8839
|
+
state
|
|
8840
|
+
);
|
|
8841
|
+
}
|
|
8842
|
+
case "case":
|
|
8843
|
+
return this.compileNqlCaseExpressionArg(record, ctx, state);
|
|
8844
|
+
case "jsonExtract": {
|
|
8845
|
+
const handler = getExpressionHandler("jsonExtract");
|
|
8846
|
+
return handler.compile(
|
|
8847
|
+
{
|
|
8848
|
+
type: "jsonExtract",
|
|
8849
|
+
column: record.field,
|
|
8850
|
+
args: Array.isArray(record.path) ? record.path : [],
|
|
8851
|
+
jsonMode: record.mode
|
|
8852
|
+
},
|
|
8853
|
+
ctx,
|
|
8854
|
+
state
|
|
8855
|
+
);
|
|
8856
|
+
}
|
|
8857
|
+
case "jsonPathExtract": {
|
|
8858
|
+
const handler = getExpressionHandler("jsonPathExtract");
|
|
8859
|
+
return handler.compile(
|
|
8860
|
+
{
|
|
8861
|
+
type: "jsonPathExtract",
|
|
8862
|
+
column: record.field,
|
|
8863
|
+
args: Array.isArray(record.path) ? [record.path] : typeof record.path === "string" ? [record.path] : [],
|
|
8864
|
+
jsonMode: record.mode
|
|
8865
|
+
},
|
|
8866
|
+
ctx,
|
|
8867
|
+
state
|
|
8868
|
+
);
|
|
8869
|
+
}
|
|
8870
|
+
case "window":
|
|
8871
|
+
return genericWindowHandler.compile(
|
|
8872
|
+
{
|
|
8873
|
+
type: "window",
|
|
8874
|
+
function: record.function,
|
|
8875
|
+
column: record.field,
|
|
8876
|
+
args: typeof record.offset === "number" ? [record.offset] : void 0,
|
|
8877
|
+
value: record.defaultValue,
|
|
8878
|
+
partition: record.over?.partitionBy,
|
|
8879
|
+
orderBy: record.over?.orderBy?.map((item) => ({
|
|
8880
|
+
column: item.field,
|
|
8881
|
+
direction: item.direction?.toUpperCase()
|
|
8882
|
+
}))
|
|
8883
|
+
},
|
|
8884
|
+
ctx,
|
|
8885
|
+
state
|
|
8886
|
+
);
|
|
8887
|
+
case "customOp":
|
|
8888
|
+
case "customFn":
|
|
8889
|
+
case "ref":
|
|
8890
|
+
case "cast":
|
|
8891
|
+
case "unary":
|
|
8892
|
+
case "namedArg":
|
|
8893
|
+
case "star":
|
|
8894
|
+
case "array":
|
|
8895
|
+
case "subquery":
|
|
8896
|
+
return compileExpressionIntent(
|
|
8897
|
+
record,
|
|
8898
|
+
ctx,
|
|
8899
|
+
state
|
|
8900
|
+
);
|
|
8901
|
+
default:
|
|
8902
|
+
throw new UnhandledNqlSelectExpressionKindError(record.kind);
|
|
8903
|
+
}
|
|
8904
|
+
}
|
|
8905
|
+
return compileValue(arg, state);
|
|
8906
|
+
}
|
|
8907
|
+
compileNqlCaseExpressionArg(expr, ctx, state) {
|
|
8908
|
+
const whenClauses = expr.when;
|
|
8909
|
+
if (!Array.isArray(whenClauses) || whenClauses.length === 0) {
|
|
8910
|
+
throw new Error("NQL CASE expression requires at least one WHEN clause");
|
|
8911
|
+
}
|
|
8912
|
+
const dispatcher = createWhereDispatcher();
|
|
8913
|
+
const args = whenClauses.map((branch) => {
|
|
8914
|
+
const condition = branch.condition;
|
|
8915
|
+
const result = branch.result;
|
|
8916
|
+
const conditionDecision = convertWhereCondition(
|
|
8917
|
+
condition,
|
|
8918
|
+
ctx.rootTable
|
|
8919
|
+
);
|
|
8920
|
+
if (!conditionDecision) {
|
|
8921
|
+
throw new Error("NQL CASE WHEN condition could not be compiled");
|
|
8922
|
+
}
|
|
8923
|
+
const whenNode = dispatcher(
|
|
8924
|
+
mapToHandlerDecision(
|
|
8925
|
+
conditionDecision,
|
|
8926
|
+
ctx.rootTable,
|
|
8927
|
+
this.defaultPk,
|
|
8928
|
+
this.deriveFk
|
|
8929
|
+
),
|
|
8930
|
+
ctx,
|
|
8931
|
+
state
|
|
8932
|
+
);
|
|
8933
|
+
const thenNode = this.compileNqlFunctionArg(result, ctx, state);
|
|
8934
|
+
return {
|
|
8935
|
+
CaseWhen: {
|
|
8936
|
+
expr: whenNode,
|
|
8937
|
+
result: thenNode
|
|
8938
|
+
}
|
|
8939
|
+
};
|
|
8940
|
+
});
|
|
8941
|
+
const defresult = expr.else !== void 0 ? this.compileNqlFunctionArg(expr.else, ctx, state) : void 0;
|
|
8942
|
+
return {
|
|
8943
|
+
CaseExpr: {
|
|
8944
|
+
args,
|
|
8945
|
+
...defresult !== void 0 ? { defresult } : {}
|
|
8946
|
+
}
|
|
8947
|
+
};
|
|
8948
|
+
}
|
|
8418
8949
|
/**
|
|
8419
8950
|
* Compile a SELECT-list target via expression handler.
|
|
8420
8951
|
* Wraps the node in a ResTarget and pushes it onto targetList.
|
|
@@ -8468,6 +8999,41 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8468
8999
|
});
|
|
8469
9000
|
break;
|
|
8470
9001
|
}
|
|
9002
|
+
case "selectNqlFunction": {
|
|
9003
|
+
ensureExpressionHandlersRegistered();
|
|
9004
|
+
const funcType = decision.function;
|
|
9005
|
+
if (!funcType) break;
|
|
9006
|
+
assertNqlSelectScalarFunctionAllowed(funcType);
|
|
9007
|
+
const ctx = this.createHandlerContext(
|
|
9008
|
+
plan,
|
|
9009
|
+
decision.table ?? plan.rootTable
|
|
9010
|
+
);
|
|
9011
|
+
const state = this.createHandlerState();
|
|
9012
|
+
const safeHandler = getNqlSafeExpressionHandler(funcType);
|
|
9013
|
+
const node = safeHandler ? safeHandler.compile(
|
|
9014
|
+
mapToHandlerDecision(
|
|
9015
|
+
decision,
|
|
9016
|
+
plan.rootTable,
|
|
9017
|
+
this.defaultPk,
|
|
9018
|
+
this.deriveFk
|
|
9019
|
+
),
|
|
9020
|
+
ctx,
|
|
9021
|
+
state
|
|
9022
|
+
) : this.compileGenericNqlFunction(
|
|
9023
|
+
funcType,
|
|
9024
|
+
decision.args ?? [],
|
|
9025
|
+
ctx,
|
|
9026
|
+
state
|
|
9027
|
+
);
|
|
9028
|
+
this.state.paramIndex = state.paramIndex;
|
|
9029
|
+
targetList.push({
|
|
9030
|
+
ResTarget: {
|
|
9031
|
+
val: node,
|
|
9032
|
+
...decision.alias ? { name: this.naming.toDatabase(decision.alias) } : {}
|
|
9033
|
+
}
|
|
9034
|
+
});
|
|
9035
|
+
break;
|
|
9036
|
+
}
|
|
8471
9037
|
case "selectExpression": {
|
|
8472
9038
|
if (decision.expressionType === "case") {
|
|
8473
9039
|
const caseNode = this.compileCaseExpression(decision);
|
|
@@ -8564,6 +9130,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8564
9130
|
case "selectWindow": {
|
|
8565
9131
|
const winFuncName = decision.function;
|
|
8566
9132
|
if (!winFuncName) break;
|
|
9133
|
+
assertNqlSelectWindowFunctionAllowed(winFuncName);
|
|
8567
9134
|
const winHandler = genericWindowHandler;
|
|
8568
9135
|
const ctx = this.createHandlerContext(
|
|
8569
9136
|
plan,
|
|
@@ -8592,11 +9159,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8592
9159
|
* Compile an includeStrategy decision and register its results.
|
|
8593
9160
|
* Pushes targets onto targetList, raw joins / CTEs onto instance collections.
|
|
8594
9161
|
*/
|
|
8595
|
-
|
|
8596
|
-
const includeResult = this.compileIncludeViaHandler(decision, plan);
|
|
8597
|
-
if (includeResult.targets) {
|
|
8598
|
-
targetList.push(...includeResult.targets);
|
|
8599
|
-
}
|
|
9162
|
+
registerIncludeCompilationResult(includeResult) {
|
|
8600
9163
|
if (includeResult.rawJoin) {
|
|
8601
9164
|
this.rawJoins.push(includeResult.rawJoin);
|
|
8602
9165
|
}
|
|
@@ -8607,6 +9170,27 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8607
9170
|
this.pendingCtes.push(includeResult.cte);
|
|
8608
9171
|
}
|
|
8609
9172
|
}
|
|
9173
|
+
compileIncludeDecision(decision, plan, targetList, precompiled) {
|
|
9174
|
+
const includeResult = precompiled ?? this.compileIncludeViaHandler(decision, plan);
|
|
9175
|
+
if (includeResult.targets) {
|
|
9176
|
+
targetList.push(...includeResult.targets);
|
|
9177
|
+
}
|
|
9178
|
+
if (!precompiled) {
|
|
9179
|
+
this.registerIncludeCompilationResult(includeResult);
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
compileJoinIncludeAllocationPass(decisions, plan) {
|
|
9183
|
+
const includeResults = /* @__PURE__ */ new Map();
|
|
9184
|
+
for (const decision of decisions) {
|
|
9185
|
+
if (decision.type !== "includeStrategy" || decision.choice !== "join") {
|
|
9186
|
+
continue;
|
|
9187
|
+
}
|
|
9188
|
+
const includeResult = this.compileIncludeViaHandler(decision, plan);
|
|
9189
|
+
includeResults.set(decision, includeResult);
|
|
9190
|
+
this.registerIncludeCompilationResult(includeResult);
|
|
9191
|
+
}
|
|
9192
|
+
return includeResults;
|
|
9193
|
+
}
|
|
8610
9194
|
/**
|
|
8611
9195
|
* Fold a WHERE-family decision into an existing where expression.
|
|
8612
9196
|
* Returns the updated (or new) where node.
|
|
@@ -8726,7 +9310,11 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8726
9310
|
if (decision.choice !== "join" || !decision.conditions || decision.conditions.length === 0) {
|
|
8727
9311
|
return where;
|
|
8728
9312
|
}
|
|
8729
|
-
const
|
|
9313
|
+
const relationIdentityPath = getRelationIdentityPath(
|
|
9314
|
+
decision,
|
|
9315
|
+
this.currentRootTable
|
|
9316
|
+
);
|
|
9317
|
+
const joinAlias = (relationIdentityPath ? this.joinAliasMap.get(relationIdentityPath)?.alias : void 0) ?? decision.relationName;
|
|
8730
9318
|
for (const cond of decision.conditions) {
|
|
8731
9319
|
const condExpr = this.dispatchWhere(
|
|
8732
9320
|
cond,
|
|
@@ -8736,6 +9324,14 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8736
9324
|
}
|
|
8737
9325
|
return where;
|
|
8738
9326
|
}
|
|
9327
|
+
reserveManualJoinAliases(decisions) {
|
|
9328
|
+
for (const decision of decisions) {
|
|
9329
|
+
if (decision.type !== "join") continue;
|
|
9330
|
+
const alias = decision.alias ?? decision.targetTable;
|
|
9331
|
+
if (!alias) continue;
|
|
9332
|
+
this.usedJoinAliases.add(this.emittedJoinAlias(alias));
|
|
9333
|
+
}
|
|
9334
|
+
}
|
|
8739
9335
|
/**
|
|
8740
9336
|
* Apply a single join decision to the FROM clause in-place.
|
|
8741
9337
|
* Chains multiple joins by wrapping from[0] as the left-arg each time.
|
|
@@ -8800,14 +9396,11 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8800
9396
|
*/
|
|
8801
9397
|
compileGroupByDecision(decision) {
|
|
8802
9398
|
const gbCol = decision.column;
|
|
8803
|
-
const gbDot = gbCol.
|
|
9399
|
+
const gbDot = gbCol.lastIndexOf(".");
|
|
8804
9400
|
if (gbDot !== -1) {
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
void 0,
|
|
8809
|
-
this.naming
|
|
8810
|
-
);
|
|
9401
|
+
const relation = gbCol.slice(0, gbDot);
|
|
9402
|
+
const alias = this.resolvedJoinAliases().get(relation) ?? relation;
|
|
9403
|
+
return columnRef(gbCol.slice(gbDot + 1), alias, void 0, this.naming);
|
|
8811
9404
|
}
|
|
8812
9405
|
return columnRef(gbCol, decision.table, void 0, this.naming);
|
|
8813
9406
|
}
|
|
@@ -8853,19 +9446,31 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8853
9446
|
return selectStmt(options);
|
|
8854
9447
|
}
|
|
8855
9448
|
compileSelect(plan) {
|
|
9449
|
+
const decisions = mergeDuplicateJoinIncludeDecisions(
|
|
9450
|
+
plan.decisions,
|
|
9451
|
+
plan.rootTable
|
|
9452
|
+
);
|
|
9453
|
+
this.reserveManualJoinAliases(decisions);
|
|
9454
|
+
const includeJoinResults = this.compileJoinIncludeAllocationPass(
|
|
9455
|
+
decisions,
|
|
9456
|
+
plan
|
|
9457
|
+
);
|
|
9458
|
+
this.state.aliases = this.resolvedJoinAliases();
|
|
8856
9459
|
const targetList = [];
|
|
8857
9460
|
const from = this.compileFromClause(plan);
|
|
8858
9461
|
let where;
|
|
8859
9462
|
const orderBy = [];
|
|
9463
|
+
const orderByDecisions = [];
|
|
8860
9464
|
const groupBy = [];
|
|
8861
9465
|
let having;
|
|
8862
9466
|
let limit;
|
|
8863
9467
|
let offset;
|
|
8864
9468
|
let distinct = false;
|
|
8865
|
-
for (const decision of
|
|
9469
|
+
for (const decision of decisions) {
|
|
8866
9470
|
switch (decision.type) {
|
|
8867
9471
|
case "select":
|
|
8868
9472
|
case "selectFunction":
|
|
9473
|
+
case "selectNqlFunction":
|
|
8869
9474
|
case "selectExpression":
|
|
8870
9475
|
case "selectRelationColumn":
|
|
8871
9476
|
case "selectPseudoColumn":
|
|
@@ -8875,7 +9480,12 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8875
9480
|
this.compileSelectTarget(decision, plan, targetList);
|
|
8876
9481
|
break;
|
|
8877
9482
|
case "includeStrategy":
|
|
8878
|
-
this.compileIncludeDecision(
|
|
9483
|
+
this.compileIncludeDecision(
|
|
9484
|
+
decision,
|
|
9485
|
+
plan,
|
|
9486
|
+
targetList,
|
|
9487
|
+
includeJoinResults.get(decision)
|
|
9488
|
+
);
|
|
8879
9489
|
where = this.compileIncludeWhereConditions(decision, where);
|
|
8880
9490
|
break;
|
|
8881
9491
|
case "where":
|
|
@@ -8888,8 +9498,7 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8888
9498
|
this.compileJoinDecision(decision, plan, from);
|
|
8889
9499
|
break;
|
|
8890
9500
|
case "orderBy": {
|
|
8891
|
-
|
|
8892
|
-
if (obNode) orderBy.push(obNode);
|
|
9501
|
+
orderByDecisions.push(decision);
|
|
8893
9502
|
break;
|
|
8894
9503
|
}
|
|
8895
9504
|
case "groupBy":
|
|
@@ -8903,6 +9512,10 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8903
9512
|
case "limit":
|
|
8904
9513
|
if (typeof decision.limit === "number") {
|
|
8905
9514
|
limit = integerNode(decision.limit);
|
|
9515
|
+
} else if (isParamIntent6(decision.limit)) {
|
|
9516
|
+
this.state.parameters.push(unwrapParamIntent(decision.limit));
|
|
9517
|
+
this.state.paramIndex++;
|
|
9518
|
+
limit = createParamRef(this.state.paramIndex);
|
|
8906
9519
|
} else if (decision.limit?.paramIndex !== void 0) {
|
|
8907
9520
|
limit = createParamRef(decision.limit.paramIndex);
|
|
8908
9521
|
this.state.parameters.push(void 0);
|
|
@@ -8911,6 +9524,10 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8911
9524
|
case "offset":
|
|
8912
9525
|
if (typeof decision.offset === "number") {
|
|
8913
9526
|
offset = integerNode(decision.offset);
|
|
9527
|
+
} else if (isParamIntent6(decision.offset)) {
|
|
9528
|
+
this.state.parameters.push(unwrapParamIntent(decision.offset));
|
|
9529
|
+
this.state.paramIndex++;
|
|
9530
|
+
offset = createParamRef(this.state.paramIndex);
|
|
8914
9531
|
} else if (decision.offset?.paramIndex !== void 0) {
|
|
8915
9532
|
offset = createParamRef(decision.offset.paramIndex);
|
|
8916
9533
|
this.state.parameters.push(void 0);
|
|
@@ -8928,6 +9545,10 @@ var PlanCompiler = class _PlanCompiler {
|
|
|
8928
9545
|
break;
|
|
8929
9546
|
}
|
|
8930
9547
|
}
|
|
9548
|
+
for (const decision of orderByDecisions) {
|
|
9549
|
+
const obNode = this.compileOrderByDecision(decision, plan);
|
|
9550
|
+
if (obNode) orderBy.push(obNode);
|
|
9551
|
+
}
|
|
8931
9552
|
this.flushPendingJoins(from, plan);
|
|
8932
9553
|
return this.buildSelectStmt(
|
|
8933
9554
|
targetList,
|
|
@@ -12520,8 +13141,10 @@ function matchGlob(pattern, value) {
|
|
|
12520
13141
|
init_ast_helpers();
|
|
12521
13142
|
init_compiler_utils();
|
|
12522
13143
|
init_handlers();
|
|
13144
|
+
init_param_intent();
|
|
12523
13145
|
init_param_ref();
|
|
12524
13146
|
import { isSqlRaw } from "@dbsp/core";
|
|
13147
|
+
import { isParamIntent as isParamIntent7 } from "@dbsp/types";
|
|
12525
13148
|
function buildReturningList(columns, tableRef, ctx) {
|
|
12526
13149
|
if (!columns || columns.length === 0) return void 0;
|
|
12527
13150
|
const { naming } = ctx;
|
|
@@ -12779,7 +13402,7 @@ function compileInsertFrom(config, ctx, state) {
|
|
|
12779
13402
|
}
|
|
12780
13403
|
let limitCount;
|
|
12781
13404
|
if (config.limit !== void 0) {
|
|
12782
|
-
limitCount =
|
|
13405
|
+
limitCount = limitToNode(config.limit, state);
|
|
12783
13406
|
}
|
|
12784
13407
|
const sourceRelation = {
|
|
12785
13408
|
relname: dbSourceTable,
|
|
@@ -12854,7 +13477,7 @@ function compileUpsertFrom(config, ctx, state) {
|
|
|
12854
13477
|
}
|
|
12855
13478
|
let limitCount;
|
|
12856
13479
|
if (config.limit !== void 0) {
|
|
12857
|
-
limitCount =
|
|
13480
|
+
limitCount = limitToNode(config.limit, state);
|
|
12858
13481
|
}
|
|
12859
13482
|
const sourceRelation = {
|
|
12860
13483
|
relname: dbSourceTable,
|
|
@@ -12928,11 +13551,22 @@ var RANGE_TYPES = /* @__PURE__ */ new Set([
|
|
|
12928
13551
|
"int8range",
|
|
12929
13552
|
"numrange"
|
|
12930
13553
|
]);
|
|
12931
|
-
function valueToNode(value, state, dbType) {
|
|
12932
|
-
|
|
13554
|
+
function valueToNode(value, state, dbType, forceParam = false) {
|
|
13555
|
+
const isParam = isParamIntent7(value);
|
|
13556
|
+
const boundValue = unwrapParamIntent(value);
|
|
13557
|
+
if (boundValue === null || boundValue === void 0) {
|
|
13558
|
+
if (forceParam || isParam) {
|
|
13559
|
+
state.parameters.push(boundValue);
|
|
13560
|
+
state.paramIndex++;
|
|
13561
|
+
return dbType && RANGE_TYPES.has(dbType) ? createTypeCastParamRef(state.paramIndex, dbType) : {
|
|
13562
|
+
ParamRef: {
|
|
13563
|
+
number: state.paramIndex
|
|
13564
|
+
}
|
|
13565
|
+
};
|
|
13566
|
+
}
|
|
12933
13567
|
return { A_Const: { isnull: true } };
|
|
12934
13568
|
}
|
|
12935
|
-
state.parameters.push(
|
|
13569
|
+
state.parameters.push(boundValue);
|
|
12936
13570
|
state.paramIndex++;
|
|
12937
13571
|
if (dbType && RANGE_TYPES.has(dbType)) {
|
|
12938
13572
|
return createTypeCastParamRef(state.paramIndex, dbType);
|
|
@@ -12943,6 +13577,18 @@ function valueToNode(value, state, dbType) {
|
|
|
12943
13577
|
}
|
|
12944
13578
|
};
|
|
12945
13579
|
}
|
|
13580
|
+
function limitToNode(limit, state) {
|
|
13581
|
+
if (isParamIntent7(limit)) {
|
|
13582
|
+
state.parameters.push(unwrapParamIntent(limit));
|
|
13583
|
+
state.paramIndex++;
|
|
13584
|
+
return {
|
|
13585
|
+
ParamRef: {
|
|
13586
|
+
number: state.paramIndex
|
|
13587
|
+
}
|
|
13588
|
+
};
|
|
13589
|
+
}
|
|
13590
|
+
return { A_Const: { ival: { ival: limit } } };
|
|
13591
|
+
}
|
|
12946
13592
|
function compileMutation(decision, ctx, state) {
|
|
12947
13593
|
const type = decision.type;
|
|
12948
13594
|
const table = decision.table ?? ctx.rootTable;
|
|
@@ -12982,6 +13628,7 @@ function compileMutation(decision, ctx, state) {
|
|
|
12982
13628
|
init_ast_helpers();
|
|
12983
13629
|
init_compiler_utils();
|
|
12984
13630
|
init_handlers();
|
|
13631
|
+
init_param_intent();
|
|
12985
13632
|
init_param_ref();
|
|
12986
13633
|
function buildOnConflictClause(config, ctx, state) {
|
|
12987
13634
|
const naming = ctx.naming;
|
|
@@ -13141,7 +13788,7 @@ function compileUnnestUpsert(config, ctx, state) {
|
|
|
13141
13788
|
}
|
|
13142
13789
|
function valueToParam(state, value) {
|
|
13143
13790
|
if (value !== void 0) {
|
|
13144
|
-
state.parameters.push(value);
|
|
13791
|
+
state.parameters.push(unwrapParamIntent(value));
|
|
13145
13792
|
}
|
|
13146
13793
|
state.paramIndex++;
|
|
13147
13794
|
return {
|
|
@@ -13382,7 +14029,7 @@ function compileSubqueryIncludeManyToMany(info, parentIds, schemaName, state, de
|
|
|
13382
14029
|
// src/adapter-compiler-mutations.ts
|
|
13383
14030
|
init_compile_where();
|
|
13384
14031
|
init_compiler_utils();
|
|
13385
|
-
import { InvalidOperationError as
|
|
14032
|
+
import { InvalidOperationError as InvalidOperationError3, isSqlRaw as isSqlRaw2 } from "@dbsp/core";
|
|
13386
14033
|
init_handlers();
|
|
13387
14034
|
function whereIntentAsDecision(where) {
|
|
13388
14035
|
return where;
|
|
@@ -13460,9 +14107,8 @@ function compileInsert2(intent, options, deps) {
|
|
|
13460
14107
|
const state = createCompilerState();
|
|
13461
14108
|
const firstRow = intent.values?.[0] ?? {};
|
|
13462
14109
|
const columns = Object.keys(firstRow);
|
|
13463
|
-
const
|
|
13464
|
-
|
|
13465
|
-
);
|
|
14110
|
+
const rows = intent.values ?? [];
|
|
14111
|
+
const values = rows.map((row) => columns.map((col) => row[col]));
|
|
13466
14112
|
const columnTypes = getColumnTypes(intent.table, columns, deps);
|
|
13467
14113
|
const config = {
|
|
13468
14114
|
table: intent.table,
|
|
@@ -13473,7 +14119,7 @@ function compileInsert2(intent, options, deps) {
|
|
|
13473
14119
|
};
|
|
13474
14120
|
const maxBatchSize = options?.maxBatchSize;
|
|
13475
14121
|
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
13476
|
-
throw new
|
|
14122
|
+
throw new InvalidOperationError3(
|
|
13477
14123
|
"insert",
|
|
13478
14124
|
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
13479
14125
|
);
|
|
@@ -13549,7 +14195,7 @@ function compileBatchUpdate(intent, _options, deps) {
|
|
|
13549
14195
|
};
|
|
13550
14196
|
const state = createCompilerState();
|
|
13551
14197
|
if (intent.updates.length === 0) {
|
|
13552
|
-
throw new
|
|
14198
|
+
throw new InvalidOperationError3(
|
|
13553
14199
|
"update",
|
|
13554
14200
|
"batchSet requires at least one row"
|
|
13555
14201
|
);
|
|
@@ -13558,7 +14204,7 @@ function compileBatchUpdate(intent, _options, deps) {
|
|
|
13558
14204
|
const matchColumns = [...intent.matchColumns];
|
|
13559
14205
|
for (const mc of matchColumns) {
|
|
13560
14206
|
if (!allColumns.includes(mc)) {
|
|
13561
|
-
throw new
|
|
14207
|
+
throw new InvalidOperationError3(
|
|
13562
14208
|
"update",
|
|
13563
14209
|
`Match column "${mc}" not found in update data. Each row must include the match column(s).`
|
|
13564
14210
|
);
|
|
@@ -13581,7 +14227,13 @@ function compileBatchUpdate(intent, _options, deps) {
|
|
|
13581
14227
|
naming: deps.naming,
|
|
13582
14228
|
...schemaName !== void 0 && { schemaName },
|
|
13583
14229
|
...deps.model !== void 0 && { model: deps.model },
|
|
13584
|
-
compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
|
|
14230
|
+
compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
|
|
14231
|
+
sqIntent,
|
|
14232
|
+
paramOffset,
|
|
14233
|
+
deps.naming,
|
|
14234
|
+
schemaName,
|
|
14235
|
+
"rawExists"
|
|
14236
|
+
)
|
|
13585
14237
|
};
|
|
13586
14238
|
whereGuard = compileWhereIntent(intent.where, whereCtx);
|
|
13587
14239
|
}
|
|
@@ -13685,7 +14337,7 @@ function compileUpsert2(intent, options, deps) {
|
|
|
13685
14337
|
};
|
|
13686
14338
|
const maxBatchSize = options?.maxBatchSize;
|
|
13687
14339
|
if (maxBatchSize !== void 0 && values.length > maxBatchSize) {
|
|
13688
|
-
throw new
|
|
14340
|
+
throw new InvalidOperationError3(
|
|
13689
14341
|
"upsert",
|
|
13690
14342
|
`Batch size ${values.length} exceeds maxBatchSize ${maxBatchSize}`
|
|
13691
14343
|
);
|
|
@@ -13738,6 +14390,7 @@ function compileUpsertFrom2(intent, options, deps) {
|
|
|
13738
14390
|
init_assert_field();
|
|
13739
14391
|
init_ast_helpers();
|
|
13740
14392
|
init_compile_where();
|
|
14393
|
+
import { countDistinctRelationPathsByName } from "@dbsp/core";
|
|
13741
14394
|
init_compiler_utils();
|
|
13742
14395
|
init_types();
|
|
13743
14396
|
init_intent_to_decisions();
|
|
@@ -13746,6 +14399,7 @@ init_param_ref();
|
|
|
13746
14399
|
// src/plan-decision-extractor.ts
|
|
13747
14400
|
init_assert_field();
|
|
13748
14401
|
init_intent_to_decisions();
|
|
14402
|
+
import { deriveRelationPathFromIntentPath } from "@dbsp/core";
|
|
13749
14403
|
function findExistsIntents(where) {
|
|
13750
14404
|
if (!where || typeof where !== "object") return [];
|
|
13751
14405
|
const w = where;
|
|
@@ -13790,7 +14444,9 @@ function resolveIncludeByPath(includes, intentPath, relationName) {
|
|
|
13790
14444
|
}
|
|
13791
14445
|
if (resolved) return resolved;
|
|
13792
14446
|
}
|
|
13793
|
-
return includes.find(
|
|
14447
|
+
return includes.find(
|
|
14448
|
+
(i) => i.relation === relationName || i.via === relationName
|
|
14449
|
+
);
|
|
13794
14450
|
}
|
|
13795
14451
|
function deriveForeignKey(context, deriveFk = defaultFkDerivation, defaultPk = DEFAULT_PK_COLUMN) {
|
|
13796
14452
|
const fk = context.foreignKey ?? context.sourceFK;
|
|
@@ -13815,24 +14471,6 @@ function mapComparisonOperator(op3) {
|
|
|
13815
14471
|
};
|
|
13816
14472
|
return map[op3] ?? "=";
|
|
13817
14473
|
}
|
|
13818
|
-
function valueToNode2(value) {
|
|
13819
|
-
if (typeof value === "string") {
|
|
13820
|
-
return { A_Const: { sval: { sval: value } } };
|
|
13821
|
-
}
|
|
13822
|
-
if (typeof value === "number") {
|
|
13823
|
-
if (Number.isInteger(value)) {
|
|
13824
|
-
return { A_Const: { ival: { ival: value } } };
|
|
13825
|
-
}
|
|
13826
|
-
return { A_Const: { fval: { fval: String(value) } } };
|
|
13827
|
-
}
|
|
13828
|
-
if (typeof value === "boolean") {
|
|
13829
|
-
return { A_Const: { boolval: { boolval: value } } };
|
|
13830
|
-
}
|
|
13831
|
-
if (value === null) {
|
|
13832
|
-
return { A_Const: { isnull: true } };
|
|
13833
|
-
}
|
|
13834
|
-
return { A_Const: { sval: { sval: String(value) } } };
|
|
13835
|
-
}
|
|
13836
14474
|
function convertWhereToDecisions(where, table) {
|
|
13837
14475
|
if (!where || typeof where !== "object") return [];
|
|
13838
14476
|
const w = where;
|
|
@@ -14499,6 +15137,11 @@ function toIncludeDecision(d, choice, plan, defaultPk = DEFAULT_PK_COLUMN, deriv
|
|
|
14499
15137
|
type: "includeStrategy",
|
|
14500
15138
|
choice: effectiveChoice,
|
|
14501
15139
|
relationName,
|
|
15140
|
+
relationPath: deriveRelationPathFromIntentPath(
|
|
15141
|
+
Array.isArray(plan.intent?.include) ? plan.intent.include : void 0,
|
|
15142
|
+
context.intentPath,
|
|
15143
|
+
relationName
|
|
15144
|
+
) ?? relationName,
|
|
14502
15145
|
targetTable: context.target,
|
|
14503
15146
|
...context.sourceTable && { sourceTable: context.sourceTable },
|
|
14504
15147
|
...relationType && { relationType },
|
|
@@ -14513,6 +15156,11 @@ function toJoinIncludeDecision(d, plan, defaultPk = DEFAULT_PK_COLUMN, deriveFk
|
|
|
14513
15156
|
const relationName = context.relation ?? context.includeAlias;
|
|
14514
15157
|
if (!context.target || !relationName) return void 0;
|
|
14515
15158
|
const intentPath = context?.intentPath;
|
|
15159
|
+
const relationPath = deriveRelationPathFromIntentPath(
|
|
15160
|
+
Array.isArray(plan.intent?.include) ? plan.intent.include : void 0,
|
|
15161
|
+
intentPath,
|
|
15162
|
+
relationName
|
|
15163
|
+
) ?? relationName;
|
|
14516
15164
|
const includeIntent = resolveIncludeByPath(
|
|
14517
15165
|
plan.intent?.include,
|
|
14518
15166
|
intentPath,
|
|
@@ -14540,6 +15188,7 @@ function toJoinIncludeDecision(d, plan, defaultPk = DEFAULT_PK_COLUMN, deriveFk
|
|
|
14540
15188
|
type: "includeStrategy",
|
|
14541
15189
|
choice: "join",
|
|
14542
15190
|
relationName,
|
|
15191
|
+
relationPath,
|
|
14543
15192
|
targetTable: context.target,
|
|
14544
15193
|
...context.sourceTable && { sourceTable: context.sourceTable },
|
|
14545
15194
|
...relationType && { relationType },
|
|
@@ -14585,6 +15234,7 @@ function synthesizeMissingJoinDecisions(plan, coveredRelations, model, defaultPk
|
|
|
14585
15234
|
type: "includeStrategy",
|
|
14586
15235
|
choice: "join",
|
|
14587
15236
|
relationName: alias,
|
|
15237
|
+
relationPath: alias,
|
|
14588
15238
|
targetTable: rel.target,
|
|
14589
15239
|
sourceTable,
|
|
14590
15240
|
...rel.type && {
|
|
@@ -14881,22 +15531,11 @@ function buildRelationColumnsMap(decisions, includedRelations) {
|
|
|
14881
15531
|
}
|
|
14882
15532
|
return map;
|
|
14883
15533
|
}
|
|
14884
|
-
function findRelationMapKey(map, relationName) {
|
|
14885
|
-
if (map.has(relationName)) return relationName;
|
|
14886
|
-
const suffix = `.${relationName}`;
|
|
14887
|
-
for (const key of map.keys()) {
|
|
14888
|
-
if (key.endsWith(suffix)) return key;
|
|
14889
|
-
}
|
|
14890
|
-
return void 0;
|
|
14891
|
-
}
|
|
14892
15534
|
function injectAndValidateRelationColumns(enrichedUnifiedDecisions, relationColumnsMap, model) {
|
|
14893
15535
|
if (relationColumnsMap.size === 0) return;
|
|
14894
15536
|
for (const d of enrichedUnifiedDecisions) {
|
|
14895
15537
|
if (d.type === "includeStrategy" && d.relationName) {
|
|
14896
|
-
const mapKey =
|
|
14897
|
-
relationColumnsMap,
|
|
14898
|
-
d.relationName
|
|
14899
|
-
);
|
|
15538
|
+
const mapKey = d.relationPath ?? d.relationName;
|
|
14900
15539
|
const entries = mapKey ? relationColumnsMap.get(mapKey) : void 0;
|
|
14901
15540
|
if (entries) {
|
|
14902
15541
|
const mut = d;
|
|
@@ -14931,6 +15570,27 @@ function injectAndValidateRelationColumns(enrichedUnifiedDecisions, relationColu
|
|
|
14931
15570
|
}
|
|
14932
15571
|
}
|
|
14933
15572
|
}
|
|
15573
|
+
function applyJoinHydrationPrefixes(decisions) {
|
|
15574
|
+
const usages = [];
|
|
15575
|
+
for (const d of decisions) {
|
|
15576
|
+
if (d.type !== "includeStrategy" || d.choice !== "join" || !d.relationName) {
|
|
15577
|
+
continue;
|
|
15578
|
+
}
|
|
15579
|
+
const relationName = d.relationName;
|
|
15580
|
+
const relationPath = d.relationPath ?? relationName;
|
|
15581
|
+
usages.push({ relationName, relationPath });
|
|
15582
|
+
}
|
|
15583
|
+
const pathCountsByRelation = countDistinctRelationPathsByName(usages);
|
|
15584
|
+
for (const d of decisions) {
|
|
15585
|
+
if (d.type !== "includeStrategy" || d.choice !== "join" || !d.relationName) {
|
|
15586
|
+
continue;
|
|
15587
|
+
}
|
|
15588
|
+
const relationName = d.relationName;
|
|
15589
|
+
const relationPath = d.relationPath ?? relationName;
|
|
15590
|
+
const usesFullPath = (pathCountsByRelation.get(relationName) ?? 0) > 1;
|
|
15591
|
+
d.hydrationPrefix = usesFullPath ? relationPath : relationName;
|
|
15592
|
+
}
|
|
15593
|
+
}
|
|
14934
15594
|
function enrichRangeDecisions(allDecisions, model, rootTable) {
|
|
14935
15595
|
if (!model) return;
|
|
14936
15596
|
for (let i = 0; i < allDecisions.length; i++) {
|
|
@@ -15019,6 +15679,7 @@ function compileSelect(plan, options, deps) {
|
|
|
15019
15679
|
...allUnifiedIncludeDecisions
|
|
15020
15680
|
];
|
|
15021
15681
|
stripJoinColumnsForAggregation(enrichedUnifiedDecisions, execIntent);
|
|
15682
|
+
applyJoinHydrationPrefixes(enrichedUnifiedDecisions);
|
|
15022
15683
|
const includedRelations = new Set(
|
|
15023
15684
|
enrichedUnifiedDecisions.filter((d) => d.type === "includeStrategy").map((d) => d.relationName).filter(Boolean)
|
|
15024
15685
|
);
|
|
@@ -15116,6 +15777,7 @@ function compileWithIncludes(plan, options, deps) {
|
|
|
15116
15777
|
init_ast_helpers();
|
|
15117
15778
|
init_compiler_utils();
|
|
15118
15779
|
init_handlers();
|
|
15780
|
+
init_utils();
|
|
15119
15781
|
init_param_ref();
|
|
15120
15782
|
|
|
15121
15783
|
// src/recursive/cte-compiler.ts
|
|
@@ -15829,6 +16491,7 @@ function buildEdgeTableRecursiveCte(config) {
|
|
|
15829
16491
|
// src/adapter-compiler-recursive.ts
|
|
15830
16492
|
function compileRecursive(report, _model, _options, deps) {
|
|
15831
16493
|
const schemaName = deps.schemaName;
|
|
16494
|
+
const state = createCompilerState();
|
|
15832
16495
|
const intent = report.intent;
|
|
15833
16496
|
const traversal = intent.traversal;
|
|
15834
16497
|
const trackPath = intent.track?.path !== void 0;
|
|
@@ -15848,7 +16511,7 @@ function compileRecursive(report, _model, _options, deps) {
|
|
|
15848
16511
|
const selectColumns = Array.from(/* @__PURE__ */ new Set([nodeIdColumn, ...startSelect]));
|
|
15849
16512
|
const edgeFrom = traversal.direction === "in" ? traversal.edgeTo : traversal.edgeFrom;
|
|
15850
16513
|
const edgeTo = traversal.direction === "in" ? traversal.edgeFrom : traversal.edgeTo;
|
|
15851
|
-
const anchorWhere = intent.start.where ? buildRecursiveAnchorWhere(intent.start.where, "__n", deps) : void 0;
|
|
16514
|
+
const anchorWhere = intent.start.where ? buildRecursiveAnchorWhere(intent.start.where, "__n", deps, state) : void 0;
|
|
15852
16515
|
const base = {
|
|
15853
16516
|
cteAlias: intent.cteName,
|
|
15854
16517
|
table,
|
|
@@ -15974,11 +16637,10 @@ function compileRecursive(report, _model, _options, deps) {
|
|
|
15974
16637
|
const sql = deparseQuoted({ SelectStmt: selectStmt2 });
|
|
15975
16638
|
return {
|
|
15976
16639
|
sql,
|
|
15977
|
-
parameters:
|
|
16640
|
+
parameters: state.parameters
|
|
15978
16641
|
};
|
|
15979
16642
|
}
|
|
15980
|
-
function compileCteQuery(intent,
|
|
15981
|
-
const schemaName = deps.schemaName;
|
|
16643
|
+
function compileCteQuery(intent, options, deps) {
|
|
15982
16644
|
const state = createCompilerState();
|
|
15983
16645
|
const allCteParams = [];
|
|
15984
16646
|
const cteSqlFragments = [];
|
|
@@ -15992,8 +16654,8 @@ function compileCteQuery(intent, _options, deps) {
|
|
|
15992
16654
|
isRecursive = true;
|
|
15993
16655
|
const { sql: cteSql, params: cteParams } = buildRawCte(
|
|
15994
16656
|
cte,
|
|
15995
|
-
|
|
15996
|
-
|
|
16657
|
+
deps,
|
|
16658
|
+
options
|
|
15997
16659
|
);
|
|
15998
16660
|
allCteParams.push(...cteParams);
|
|
15999
16661
|
cteSqlFragments.push(cteSql);
|
|
@@ -16011,12 +16673,7 @@ function compileCteQuery(intent, _options, deps) {
|
|
|
16011
16673
|
isAmbiguous: false
|
|
16012
16674
|
}
|
|
16013
16675
|
};
|
|
16014
|
-
const
|
|
16015
|
-
const innerCompiled = compileSelect(
|
|
16016
|
-
innerPlanReport,
|
|
16017
|
-
innerCompileOptions,
|
|
16018
|
-
deps
|
|
16019
|
-
);
|
|
16676
|
+
const innerCompiled = compileSelect(innerPlanReport, options, deps);
|
|
16020
16677
|
const currentParamOffset = allCteParams.length;
|
|
16021
16678
|
const renumberedInnerSql = currentParamOffset > 0 ? innerCompiled.sql.replace(
|
|
16022
16679
|
/\$([0-9]+)/g,
|
|
@@ -16031,7 +16688,6 @@ function compileCteQuery(intent, _options, deps) {
|
|
|
16031
16688
|
);
|
|
16032
16689
|
}
|
|
16033
16690
|
}
|
|
16034
|
-
const outerCompileOptions = schemaName !== void 0 ? { schemaName } : {};
|
|
16035
16691
|
const outerPlanReport = {
|
|
16036
16692
|
rootTable: intent.query.from,
|
|
16037
16693
|
decisions: [],
|
|
@@ -16044,11 +16700,7 @@ function compileCteQuery(intent, _options, deps) {
|
|
|
16044
16700
|
isAmbiguous: false
|
|
16045
16701
|
}
|
|
16046
16702
|
};
|
|
16047
|
-
const outerCompiled = compileSelect(
|
|
16048
|
-
outerPlanReport,
|
|
16049
|
-
outerCompileOptions,
|
|
16050
|
-
deps
|
|
16051
|
-
);
|
|
16703
|
+
const outerCompiled = compileSelect(outerPlanReport, options, deps);
|
|
16052
16704
|
const cteParamCount = allCteParams.length;
|
|
16053
16705
|
const renumberedOuterSql = cteParamCount > 0 ? outerCompiled.sql.replace(
|
|
16054
16706
|
/\$([0-9]+)/g,
|
|
@@ -16114,8 +16766,7 @@ function buildUnnestCte(cte, state, deps) {
|
|
|
16114
16766
|
}
|
|
16115
16767
|
};
|
|
16116
16768
|
}
|
|
16117
|
-
function buildRawCte(cte,
|
|
16118
|
-
const compileOptions = schemaName !== void 0 ? { schemaName } : {};
|
|
16769
|
+
function buildRawCte(cte, deps, options) {
|
|
16119
16770
|
const basePlanReport = {
|
|
16120
16771
|
rootTable: cte.base.from,
|
|
16121
16772
|
decisions: [],
|
|
@@ -16124,7 +16775,7 @@ function buildRawCte(cte, schemaName, deps) {
|
|
|
16124
16775
|
intent: cte.base,
|
|
16125
16776
|
metadata: { planningTimeMs: 0, relationsAnalyzed: 0, isAmbiguous: false }
|
|
16126
16777
|
};
|
|
16127
|
-
const baseCompiled = compileSelect(basePlanReport,
|
|
16778
|
+
const baseCompiled = compileSelect(basePlanReport, options, deps);
|
|
16128
16779
|
const stepPlanReport = {
|
|
16129
16780
|
rootTable: cte.step.from,
|
|
16130
16781
|
decisions: [],
|
|
@@ -16133,7 +16784,7 @@ function buildRawCte(cte, schemaName, deps) {
|
|
|
16133
16784
|
intent: cte.step,
|
|
16134
16785
|
metadata: { planningTimeMs: 0, relationsAnalyzed: 0, isAmbiguous: false }
|
|
16135
16786
|
};
|
|
16136
|
-
const stepCompiled = compileSelect(stepPlanReport,
|
|
16787
|
+
const stepCompiled = compileSelect(stepPlanReport, options, deps);
|
|
16137
16788
|
const baseParamCount = baseCompiled.parameters.length;
|
|
16138
16789
|
const renumberedStepSql = baseParamCount > 0 ? stepCompiled.sql.replace(
|
|
16139
16790
|
/\$([0-9]+)/g,
|
|
@@ -16159,7 +16810,7 @@ function buildRawCte(cte, schemaName, deps) {
|
|
|
16159
16810
|
params: allParams
|
|
16160
16811
|
};
|
|
16161
16812
|
}
|
|
16162
|
-
function buildRecursiveAnchorWhere(where, tableAlias, deps) {
|
|
16813
|
+
function buildRecursiveAnchorWhere(where, tableAlias, deps, state) {
|
|
16163
16814
|
if (!where || typeof where !== "object") {
|
|
16164
16815
|
return { A_Const: { boolval: { boolval: true } } };
|
|
16165
16816
|
}
|
|
@@ -16176,7 +16827,7 @@ function buildRecursiveAnchorWhere(where, tableAlias, deps) {
|
|
|
16176
16827
|
}
|
|
16177
16828
|
};
|
|
16178
16829
|
const op3 = mapComparisonOperator(w.operator);
|
|
16179
|
-
const right =
|
|
16830
|
+
const right = compileValue(w.value, state, void 0, true);
|
|
16180
16831
|
return {
|
|
16181
16832
|
A_Expr: {
|
|
16182
16833
|
kind: "AEXPR_OP",
|
|
@@ -16188,14 +16839,14 @@ function buildRecursiveAnchorWhere(where, tableAlias, deps) {
|
|
|
16188
16839
|
}
|
|
16189
16840
|
case "and": {
|
|
16190
16841
|
const conditions = w.conditions.map(
|
|
16191
|
-
(c) => buildRecursiveAnchorWhere(c, tableAlias, deps)
|
|
16842
|
+
(c) => buildRecursiveAnchorWhere(c, tableAlias, deps, state)
|
|
16192
16843
|
);
|
|
16193
16844
|
if (conditions.length === 1) return conditions[0];
|
|
16194
16845
|
return { BoolExpr: { boolop: "AND_EXPR", args: conditions } };
|
|
16195
16846
|
}
|
|
16196
16847
|
case "or": {
|
|
16197
16848
|
const conditions = w.conditions.map(
|
|
16198
|
-
(c) => buildRecursiveAnchorWhere(c, tableAlias, deps)
|
|
16849
|
+
(c) => buildRecursiveAnchorWhere(c, tableAlias, deps, state)
|
|
16199
16850
|
);
|
|
16200
16851
|
if (conditions.length === 1) return conditions[0];
|
|
16201
16852
|
return { BoolExpr: { boolop: "OR_EXPR", args: conditions } };
|
|
@@ -16374,12 +17025,12 @@ function compileLeafOrBranch(intent, compileFn) {
|
|
|
16374
17025
|
const result = compileFn(intent);
|
|
16375
17026
|
return { sql: result.sql, parameters: result.parameters };
|
|
16376
17027
|
}
|
|
16377
|
-
function createLeafCompileFn(adapter, model, planFn2) {
|
|
17028
|
+
function createLeafCompileFn(adapter, model, planFn2, options) {
|
|
16378
17029
|
return (query) => {
|
|
16379
17030
|
const planReport = planFn2(query, model, {
|
|
16380
17031
|
dialectCapabilities: adapter.dialectCapabilities
|
|
16381
17032
|
});
|
|
16382
|
-
return adapter.compile(planReport, { model });
|
|
17033
|
+
return adapter.compile(planReport, { ...options, model });
|
|
16383
17034
|
};
|
|
16384
17035
|
}
|
|
16385
17036
|
|
|
@@ -16498,6 +17149,15 @@ function mapFetchDirection(direction) {
|
|
|
16498
17149
|
|
|
16499
17150
|
// src/pgsql-adapter.ts
|
|
16500
17151
|
init_validate();
|
|
17152
|
+
function renumberSqlParams(sql, offset) {
|
|
17153
|
+
if (offset === 0) return sql;
|
|
17154
|
+
return sql.replace(/\$(\d+)/g, (_match, num) => {
|
|
17155
|
+
return `$${Number.parseInt(num, 10) + offset}`;
|
|
17156
|
+
});
|
|
17157
|
+
}
|
|
17158
|
+
function isCompiledNqlQuery(input) {
|
|
17159
|
+
return !("intent" in input) && ("query" in input || "cteQuery" in input || "mutation" in input || "setOperation" in input || "bindings" in input || "mutationBindings" in input);
|
|
17160
|
+
}
|
|
16501
17161
|
var PgsqlAdapter = class _PgsqlAdapter {
|
|
16502
17162
|
pool;
|
|
16503
17163
|
client;
|
|
@@ -16577,6 +17237,124 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
16577
17237
|
deriveFk: this.deriveFk
|
|
16578
17238
|
};
|
|
16579
17239
|
}
|
|
17240
|
+
requireNqlCompileModel(options) {
|
|
17241
|
+
const model = options?.model ?? this.model;
|
|
17242
|
+
if (model === void 0) {
|
|
17243
|
+
throw new Error(
|
|
17244
|
+
"Compiling an NQL bundle requires a model. Pass { model } to adapter.compile(compiledNql, { model }) or configure the adapter with a model."
|
|
17245
|
+
);
|
|
17246
|
+
}
|
|
17247
|
+
return model;
|
|
17248
|
+
}
|
|
17249
|
+
compileNqlMutation(bundle, options) {
|
|
17250
|
+
const mutation = bundle.mutation;
|
|
17251
|
+
if (mutation === void 0) {
|
|
17252
|
+
throw new Error("NQL bundle did not contain a mutation intent.");
|
|
17253
|
+
}
|
|
17254
|
+
switch (mutation.type) {
|
|
17255
|
+
case "insert":
|
|
17256
|
+
return compileInsert2(
|
|
17257
|
+
mutation,
|
|
17258
|
+
options,
|
|
17259
|
+
this.buildCompileDeps(options)
|
|
17260
|
+
);
|
|
17261
|
+
case "insert_from":
|
|
17262
|
+
return compileInsertFrom2(
|
|
17263
|
+
mutation,
|
|
17264
|
+
options,
|
|
17265
|
+
this.buildCompileDeps(options)
|
|
17266
|
+
);
|
|
17267
|
+
case "update":
|
|
17268
|
+
return compileUpdate2(
|
|
17269
|
+
mutation,
|
|
17270
|
+
options,
|
|
17271
|
+
this.buildCompileDeps(options)
|
|
17272
|
+
);
|
|
17273
|
+
case "delete":
|
|
17274
|
+
return compileDelete2(
|
|
17275
|
+
mutation,
|
|
17276
|
+
options,
|
|
17277
|
+
this.buildCompileDeps(options)
|
|
17278
|
+
);
|
|
17279
|
+
case "upsert":
|
|
17280
|
+
return compileUpsert2(
|
|
17281
|
+
mutation,
|
|
17282
|
+
options,
|
|
17283
|
+
this.buildCompileDeps(options)
|
|
17284
|
+
);
|
|
17285
|
+
case "upsert_from":
|
|
17286
|
+
return compileUpsertFrom2(
|
|
17287
|
+
mutation,
|
|
17288
|
+
options,
|
|
17289
|
+
this.buildCompileDeps(options)
|
|
17290
|
+
);
|
|
17291
|
+
}
|
|
17292
|
+
throw new Error(
|
|
17293
|
+
`Unsupported NQL mutation type: ${mutation.type}`
|
|
17294
|
+
);
|
|
17295
|
+
}
|
|
17296
|
+
compileNqlBundleLeaf(bundle, options) {
|
|
17297
|
+
if (bundle.query !== void 0) {
|
|
17298
|
+
const model = this.requireNqlCompileModel(options);
|
|
17299
|
+
const planReport = planFn(bundle.query, model, {
|
|
17300
|
+
dialectCapabilities: this.dialectCapabilities
|
|
17301
|
+
});
|
|
17302
|
+
return compileSelect(
|
|
17303
|
+
planReport,
|
|
17304
|
+
options,
|
|
17305
|
+
this.buildCompileDeps(options)
|
|
17306
|
+
);
|
|
17307
|
+
}
|
|
17308
|
+
if (bundle.cteQuery !== void 0) {
|
|
17309
|
+
return compileCteQuery(
|
|
17310
|
+
bundle.cteQuery,
|
|
17311
|
+
options,
|
|
17312
|
+
this.buildCompileDeps(options)
|
|
17313
|
+
);
|
|
17314
|
+
}
|
|
17315
|
+
if (bundle.setOperation !== void 0) {
|
|
17316
|
+
const model = this.requireNqlCompileModel(options);
|
|
17317
|
+
return this.compileSetOperation(
|
|
17318
|
+
bundle.setOperation,
|
|
17319
|
+
model,
|
|
17320
|
+
options
|
|
17321
|
+
);
|
|
17322
|
+
}
|
|
17323
|
+
if (bundle.mutation !== void 0) {
|
|
17324
|
+
return this.compileNqlMutation(bundle, options);
|
|
17325
|
+
}
|
|
17326
|
+
throw new Error("NQL bundle did not contain a compilable intent.");
|
|
17327
|
+
}
|
|
17328
|
+
compileNqlBundle(bundle, options) {
|
|
17329
|
+
const ctes = [];
|
|
17330
|
+
const parameters = [];
|
|
17331
|
+
for (const [name, queryIntent] of bundle.bindings ?? []) {
|
|
17332
|
+
const cteName = quoteIdent2(name, "alias");
|
|
17333
|
+
const bindingBundle = bundle.mutationBindings?.has(name) ? { mutation: bundle.mutationBindings.get(name) } : { query: queryIntent };
|
|
17334
|
+
const compiled2 = this.compileNqlBundleLeaf(bindingBundle, options);
|
|
17335
|
+
ctes.push(
|
|
17336
|
+
`${cteName} as (${renumberSqlParams(compiled2.sql, parameters.length)})`
|
|
17337
|
+
);
|
|
17338
|
+
parameters.push(...compiled2.parameters);
|
|
17339
|
+
}
|
|
17340
|
+
const leafBundle = {
|
|
17341
|
+
...bundle.query !== void 0 && { query: bundle.query },
|
|
17342
|
+
...bundle.cteQuery !== void 0 && { cteQuery: bundle.cteQuery },
|
|
17343
|
+
...bundle.mutation !== void 0 && { mutation: bundle.mutation },
|
|
17344
|
+
...bundle.returning !== void 0 && { returning: bundle.returning },
|
|
17345
|
+
...bundle.setOperation !== void 0 && {
|
|
17346
|
+
setOperation: bundle.setOperation
|
|
17347
|
+
}
|
|
17348
|
+
};
|
|
17349
|
+
const compiled = this.compileNqlBundleLeaf(leafBundle, options);
|
|
17350
|
+
if (ctes.length === 0) {
|
|
17351
|
+
return compiled;
|
|
17352
|
+
}
|
|
17353
|
+
return {
|
|
17354
|
+
sql: `WITH ${ctes.join(", ")} ${renumberSqlParams(compiled.sql, parameters.length)}`,
|
|
17355
|
+
parameters: [...parameters, ...compiled.parameters]
|
|
17356
|
+
};
|
|
17357
|
+
}
|
|
16580
17358
|
/**
|
|
16581
17359
|
* Returns the pool/client executor, or throws if in compile-only mode.
|
|
16582
17360
|
*/
|
|
@@ -16616,6 +17394,9 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
16616
17394
|
* Compile a plan to executable SQL.
|
|
16617
17395
|
*/
|
|
16618
17396
|
compile(plan, options) {
|
|
17397
|
+
if (isCompiledNqlQuery(plan)) {
|
|
17398
|
+
return this.compileNqlBundle(plan, options);
|
|
17399
|
+
}
|
|
16619
17400
|
return compileSelect(plan, options, this.buildCompileDeps(options));
|
|
16620
17401
|
}
|
|
16621
17402
|
/**
|
|
@@ -16779,8 +17560,8 @@ var PgsqlAdapter = class _PgsqlAdapter {
|
|
|
16779
17560
|
/**
|
|
16780
17561
|
* Compile a set operation (UNION / INTERSECT / EXCEPT) to SQL.
|
|
16781
17562
|
*/
|
|
16782
|
-
compileSetOperation(intent, model,
|
|
16783
|
-
const compileFn = createLeafCompileFn(this, model, planFn);
|
|
17563
|
+
compileSetOperation(intent, model, options) {
|
|
17564
|
+
const compileFn = createLeafCompileFn(this, model, planFn, options);
|
|
16784
17565
|
const result = compileSetOperation(intent, compileFn);
|
|
16785
17566
|
return {
|
|
16786
17567
|
sql: result.sql,
|