metal-orm 1.0.82 → 1.0.85
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.cjs +300 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +300 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/ast-validation.ts +14 -0
- package/src/core/ast/expression-builders.ts +43 -24
- package/src/core/ast/expression-nodes.ts +35 -25
- package/src/core/ast/expression-visitor.ts +34 -25
- package/src/core/ast/param-proxy.ts +1 -4
- package/src/core/ast/query-visitor.ts +227 -0
- package/src/core/dialect/abstract.ts +70 -46
- package/src/query-builder/query-ast-service.ts +13 -0
- package/src/query-builder/select.ts +128 -109
package/dist/index.cjs
CHANGED
|
@@ -655,16 +655,27 @@ var operandTypes = /* @__PURE__ */ new Set([
|
|
|
655
655
|
"BitwiseExpression",
|
|
656
656
|
"Collate"
|
|
657
657
|
]);
|
|
658
|
-
var
|
|
658
|
+
var getNodeType = (value) => {
|
|
659
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
660
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
661
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
662
|
+
return descriptor.value;
|
|
663
|
+
}
|
|
664
|
+
if ("type" in value) {
|
|
665
|
+
const type = value.type;
|
|
666
|
+
return typeof type === "string" ? type : void 0;
|
|
667
|
+
}
|
|
668
|
+
return void 0;
|
|
669
|
+
};
|
|
659
670
|
var isOperandNode = (node) => {
|
|
660
|
-
|
|
661
|
-
return operandTypes.has(
|
|
662
|
-
};
|
|
663
|
-
var isFunctionNode = (node) => isOperandNode(node) && node
|
|
664
|
-
var isCaseExpressionNode = (node) => isOperandNode(node) && node
|
|
665
|
-
var isCastExpressionNode = (node) => isOperandNode(node) && node
|
|
666
|
-
var isCollateExpressionNode = (node) => isOperandNode(node) && node
|
|
667
|
-
var isWindowFunctionNode = (node) => isOperandNode(node) && node
|
|
671
|
+
const type = getNodeType(node);
|
|
672
|
+
return type !== void 0 && operandTypes.has(type);
|
|
673
|
+
};
|
|
674
|
+
var isFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "Function";
|
|
675
|
+
var isCaseExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "CaseExpression";
|
|
676
|
+
var isCastExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Cast";
|
|
677
|
+
var isCollateExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Collate";
|
|
678
|
+
var isWindowFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "WindowFunction";
|
|
668
679
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isCastExpressionNode(node) || isWindowFunctionNode(node);
|
|
669
680
|
|
|
670
681
|
// src/core/ast/expression-builders.ts
|
|
@@ -673,6 +684,14 @@ var toLiteralNode = (value) => ({
|
|
|
673
684
|
type: "Literal",
|
|
674
685
|
value: value instanceof Date ? value.toISOString() : value
|
|
675
686
|
});
|
|
687
|
+
var toParamNode = (value) => {
|
|
688
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
689
|
+
const type = Object.getOwnPropertyDescriptor(value, "type")?.value;
|
|
690
|
+
if (type !== "Param") return void 0;
|
|
691
|
+
const name = Object.getOwnPropertyDescriptor(value, "name")?.value;
|
|
692
|
+
if (typeof name !== "string") return void 0;
|
|
693
|
+
return { type: "Param", name };
|
|
694
|
+
};
|
|
676
695
|
var columnRefToNode = (col2) => {
|
|
677
696
|
if (!col2.table) {
|
|
678
697
|
throw new Error(
|
|
@@ -682,6 +701,10 @@ var columnRefToNode = (col2) => {
|
|
|
682
701
|
return { type: "Column", table: col2.table, name: col2.name };
|
|
683
702
|
};
|
|
684
703
|
var toOperandNode = (value) => {
|
|
704
|
+
const paramNode = toParamNode(value);
|
|
705
|
+
if (paramNode) {
|
|
706
|
+
return paramNode;
|
|
707
|
+
}
|
|
685
708
|
if (isOperandNode(value)) {
|
|
686
709
|
return value;
|
|
687
710
|
}
|
|
@@ -691,6 +714,10 @@ var toOperandNode = (value) => {
|
|
|
691
714
|
return columnRefToNode(value);
|
|
692
715
|
};
|
|
693
716
|
var valueToOperand = (value) => {
|
|
717
|
+
const paramNode = toParamNode(value);
|
|
718
|
+
if (paramNode) {
|
|
719
|
+
return paramNode;
|
|
720
|
+
}
|
|
694
721
|
if (isOperandNode(value)) {
|
|
695
722
|
return value;
|
|
696
723
|
}
|
|
@@ -1033,17 +1060,26 @@ var clearExpressionDispatchers = () => {
|
|
|
1033
1060
|
var clearOperandDispatchers = () => {
|
|
1034
1061
|
operandRegistry = operandRegistry.clear();
|
|
1035
1062
|
};
|
|
1036
|
-
var
|
|
1063
|
+
var getNodeType2 = (node) => {
|
|
1064
|
+
if (typeof node !== "object" || node === null) return void 0;
|
|
1065
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
1066
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
1067
|
+
return descriptor.value;
|
|
1068
|
+
}
|
|
1069
|
+
const type = node.type;
|
|
1070
|
+
return typeof type === "string" ? type : void 0;
|
|
1071
|
+
};
|
|
1037
1072
|
var unsupportedExpression = (node) => {
|
|
1038
|
-
throw new Error(`Unsupported expression type "${
|
|
1073
|
+
throw new Error(`Unsupported expression type "${getNodeType2(node) ?? "unknown"}"`);
|
|
1039
1074
|
};
|
|
1040
1075
|
var unsupportedOperand = (node) => {
|
|
1041
|
-
throw new Error(`Unsupported operand type "${
|
|
1076
|
+
throw new Error(`Unsupported operand type "${getNodeType2(node) ?? "unknown"}"`);
|
|
1042
1077
|
};
|
|
1043
1078
|
var visitExpression = (node, visitor) => {
|
|
1044
|
-
const
|
|
1079
|
+
const type = getNodeType2(node);
|
|
1080
|
+
const dynamic = type ? expressionRegistry.get(type) : void 0;
|
|
1045
1081
|
if (dynamic) return dynamic(node, visitor);
|
|
1046
|
-
switch (
|
|
1082
|
+
switch (type) {
|
|
1047
1083
|
case "BinaryExpression":
|
|
1048
1084
|
if (visitor.visitBinaryExpression) return visitor.visitBinaryExpression(node);
|
|
1049
1085
|
break;
|
|
@@ -1075,9 +1111,10 @@ var visitExpression = (node, visitor) => {
|
|
|
1075
1111
|
return unsupportedExpression(node);
|
|
1076
1112
|
};
|
|
1077
1113
|
var visitOperand = (node, visitor) => {
|
|
1078
|
-
const
|
|
1114
|
+
const type = getNodeType2(node);
|
|
1115
|
+
const dynamic = type ? operandRegistry.get(type) : void 0;
|
|
1079
1116
|
if (dynamic) return dynamic(node, visitor);
|
|
1080
|
-
switch (
|
|
1117
|
+
switch (type) {
|
|
1081
1118
|
case "Column":
|
|
1082
1119
|
if (visitor.visitColumn) return visitor.visitColumn(node);
|
|
1083
1120
|
break;
|
|
@@ -1132,7 +1169,7 @@ var buildParamProxy = (name) => {
|
|
|
1132
1169
|
const nextName2 = name ? `${name}.${trimmed}` : trimmed;
|
|
1133
1170
|
return buildParamProxy(nextName2);
|
|
1134
1171
|
}
|
|
1135
|
-
if (prop in t) {
|
|
1172
|
+
if (prop in t && name === "") {
|
|
1136
1173
|
return t[prop];
|
|
1137
1174
|
}
|
|
1138
1175
|
const nextName = name ? `${name}.${prop}` : prop;
|
|
@@ -1151,9 +1188,6 @@ var createParamProxy = () => {
|
|
|
1151
1188
|
if (typeof prop === "string" && prop.startsWith("$")) {
|
|
1152
1189
|
return buildParamProxy(prop.slice(1));
|
|
1153
1190
|
}
|
|
1154
|
-
if (prop in t) {
|
|
1155
|
-
return t[prop];
|
|
1156
|
-
}
|
|
1157
1191
|
return buildParamProxy(String(prop));
|
|
1158
1192
|
}
|
|
1159
1193
|
});
|
|
@@ -1570,6 +1604,16 @@ var Dialect = class _Dialect {
|
|
|
1570
1604
|
params: [...ctx.params]
|
|
1571
1605
|
};
|
|
1572
1606
|
}
|
|
1607
|
+
compileSelectWithOptions(ast, options = {}) {
|
|
1608
|
+
const ctx = this.createCompilerContext(options);
|
|
1609
|
+
const normalized = this.normalizeSelectAst(ast);
|
|
1610
|
+
const rawSql = this.compileSelectAst(normalized, ctx).trim();
|
|
1611
|
+
const sql = rawSql.endsWith(";") ? rawSql : `${rawSql};`;
|
|
1612
|
+
return {
|
|
1613
|
+
sql,
|
|
1614
|
+
params: [...ctx.params]
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1573
1617
|
compileInsert(ast) {
|
|
1574
1618
|
const ctx = this.createCompilerContext();
|
|
1575
1619
|
const rawSql = this.compileInsertAst(ast, ctx).trim();
|
|
@@ -1640,13 +1684,15 @@ var Dialect = class _Dialect {
|
|
|
1640
1684
|
}
|
|
1641
1685
|
/**
|
|
1642
1686
|
* Creates a new compiler context
|
|
1687
|
+
* @param options - Optional compiler context options
|
|
1643
1688
|
* @returns Compiler context with parameter management
|
|
1644
1689
|
*/
|
|
1645
|
-
createCompilerContext() {
|
|
1690
|
+
createCompilerContext(options = {}) {
|
|
1646
1691
|
const params = [];
|
|
1647
1692
|
let counter = 0;
|
|
1648
1693
|
return {
|
|
1649
1694
|
params,
|
|
1695
|
+
allowParams: options.allowParams ?? false,
|
|
1650
1696
|
addParameter: (value) => {
|
|
1651
1697
|
counter += 1;
|
|
1652
1698
|
params.push(value);
|
|
@@ -1797,9 +1843,11 @@ var Dialect = class _Dialect {
|
|
|
1797
1843
|
* @returns Compiled SQL operand
|
|
1798
1844
|
*/
|
|
1799
1845
|
compileOperand(node, ctx) {
|
|
1800
|
-
const
|
|
1846
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
1847
|
+
const nodeType = typeof descriptor?.value === "string" ? descriptor.value : typeof node.type === "string" ? node.type : void 0;
|
|
1848
|
+
const compiler = nodeType ? this.operandCompilers.get(nodeType) : void 0;
|
|
1801
1849
|
if (!compiler) {
|
|
1802
|
-
throw new Error(`Unsupported operand node type "${
|
|
1850
|
+
throw new Error(`Unsupported operand node type "${nodeType ?? "unknown"}" for ${this.constructor.name}`);
|
|
1803
1851
|
}
|
|
1804
1852
|
return compiler(node, ctx);
|
|
1805
1853
|
}
|
|
@@ -1868,7 +1916,12 @@ var Dialect = class _Dialect {
|
|
|
1868
1916
|
}
|
|
1869
1917
|
registerDefaultOperandCompilers() {
|
|
1870
1918
|
this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
|
|
1871
|
-
this.registerOperandCompiler("Param", (_param, ctx) =>
|
|
1919
|
+
this.registerOperandCompiler("Param", (_param, ctx) => {
|
|
1920
|
+
if (!ctx.allowParams) {
|
|
1921
|
+
throw new Error("Cannot compile query with Param operands. Param proxies are only for schema generation (getSchema()). If you need real parameters, use literal values.");
|
|
1922
|
+
}
|
|
1923
|
+
return ctx.addParameter(null);
|
|
1924
|
+
});
|
|
1872
1925
|
this.registerOperandCompiler("AliasRef", (alias, _ctx) => {
|
|
1873
1926
|
void _ctx;
|
|
1874
1927
|
return this.quoteIdentifier(alias.name);
|
|
@@ -4115,6 +4168,10 @@ var QueryAstService = class {
|
|
|
4115
4168
|
* @returns Normalized ordering term
|
|
4116
4169
|
*/
|
|
4117
4170
|
normalizeOrderingTerm(term) {
|
|
4171
|
+
const paramNode = this.toParamNode(term);
|
|
4172
|
+
if (paramNode) {
|
|
4173
|
+
return paramNode;
|
|
4174
|
+
}
|
|
4118
4175
|
const from = this.state.ast.from;
|
|
4119
4176
|
const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
4120
4177
|
const termType = term.type;
|
|
@@ -4132,6 +4189,14 @@ var QueryAstService = class {
|
|
|
4132
4189
|
}
|
|
4133
4190
|
return buildColumnNode(tableRef2, term);
|
|
4134
4191
|
}
|
|
4192
|
+
toParamNode(value) {
|
|
4193
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
4194
|
+
const type = Object.getOwnPropertyDescriptor(value, "type")?.value;
|
|
4195
|
+
if (type !== "Param") return void 0;
|
|
4196
|
+
const name = Object.getOwnPropertyDescriptor(value, "name")?.value;
|
|
4197
|
+
if (typeof name !== "string") return void 0;
|
|
4198
|
+
return { type: "Param", name };
|
|
4199
|
+
}
|
|
4135
4200
|
};
|
|
4136
4201
|
|
|
4137
4202
|
// src/query-builder/relation-projection-helper.ts
|
|
@@ -7586,7 +7651,7 @@ var collectFilterColumns = (expr, table, rootTables) => {
|
|
|
7586
7651
|
columns.add(node.name);
|
|
7587
7652
|
}
|
|
7588
7653
|
};
|
|
7589
|
-
const
|
|
7654
|
+
const visitOrderingTerm2 = (term) => {
|
|
7590
7655
|
if (!term || typeof term !== "object") return;
|
|
7591
7656
|
if (isOperandNode(term)) {
|
|
7592
7657
|
visitOperand2(term);
|
|
@@ -7598,7 +7663,7 @@ var collectFilterColumns = (expr, table, rootTables) => {
|
|
|
7598
7663
|
};
|
|
7599
7664
|
const visitOrderBy = (orderBy) => {
|
|
7600
7665
|
if (!orderBy) return;
|
|
7601
|
-
orderBy.forEach((node) =>
|
|
7666
|
+
orderBy.forEach((node) => visitOrderingTerm2(node.term));
|
|
7602
7667
|
};
|
|
7603
7668
|
const visitOperand2 = (node) => {
|
|
7604
7669
|
switch (node.type) {
|
|
@@ -7737,6 +7802,198 @@ var buildFilterParameters = (table, where, from, options = {}) => {
|
|
|
7737
7802
|
}];
|
|
7738
7803
|
};
|
|
7739
7804
|
|
|
7805
|
+
// src/core/ast/query-visitor.ts
|
|
7806
|
+
var getNodeType3 = (value) => {
|
|
7807
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7808
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
7809
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
7810
|
+
return descriptor.value;
|
|
7811
|
+
}
|
|
7812
|
+
if ("type" in value) {
|
|
7813
|
+
const type = value.type;
|
|
7814
|
+
return typeof type === "string" ? type : void 0;
|
|
7815
|
+
}
|
|
7816
|
+
return void 0;
|
|
7817
|
+
};
|
|
7818
|
+
var visitOrderingTerm = (term, visitor) => {
|
|
7819
|
+
if (isOperandNode(term)) {
|
|
7820
|
+
visitOperandNode(term, visitor);
|
|
7821
|
+
return;
|
|
7822
|
+
}
|
|
7823
|
+
visitExpressionNode(term, visitor);
|
|
7824
|
+
};
|
|
7825
|
+
var visitOrderByNode = (node, visitor) => {
|
|
7826
|
+
visitor.visitOrderBy?.(node);
|
|
7827
|
+
visitOrderingTerm(node.term, visitor);
|
|
7828
|
+
};
|
|
7829
|
+
var visitTableSource = (source, visitor) => {
|
|
7830
|
+
visitor.visitTableSource?.(source);
|
|
7831
|
+
if (source.type === "DerivedTable") {
|
|
7832
|
+
visitor.visitDerivedTable?.(source);
|
|
7833
|
+
visitSelectQuery(source.query, visitor);
|
|
7834
|
+
return;
|
|
7835
|
+
}
|
|
7836
|
+
if (source.type === "FunctionTable") {
|
|
7837
|
+
visitor.visitFunctionTable?.(source);
|
|
7838
|
+
source.args?.forEach((arg) => visitOperandNode(arg, visitor));
|
|
7839
|
+
}
|
|
7840
|
+
};
|
|
7841
|
+
var visitExpressionNode = (node, visitor) => {
|
|
7842
|
+
visitor.visitExpression?.(node);
|
|
7843
|
+
const type = getNodeType3(node);
|
|
7844
|
+
if (!type) return;
|
|
7845
|
+
switch (type) {
|
|
7846
|
+
case "BinaryExpression":
|
|
7847
|
+
visitOperandNode(node.left, visitor);
|
|
7848
|
+
visitOperandNode(node.right, visitor);
|
|
7849
|
+
if (node.escape) {
|
|
7850
|
+
visitOperandNode(node.escape, visitor);
|
|
7851
|
+
}
|
|
7852
|
+
return;
|
|
7853
|
+
case "LogicalExpression":
|
|
7854
|
+
node.operands.forEach((operand) => visitExpressionNode(operand, visitor));
|
|
7855
|
+
return;
|
|
7856
|
+
case "NullExpression":
|
|
7857
|
+
visitOperandNode(node.left, visitor);
|
|
7858
|
+
return;
|
|
7859
|
+
case "InExpression":
|
|
7860
|
+
visitOperandNode(node.left, visitor);
|
|
7861
|
+
if (Array.isArray(node.right)) {
|
|
7862
|
+
node.right.forEach((operand) => visitOperandNode(operand, visitor));
|
|
7863
|
+
} else {
|
|
7864
|
+
visitOperandNode(node.right, visitor);
|
|
7865
|
+
}
|
|
7866
|
+
return;
|
|
7867
|
+
case "ExistsExpression":
|
|
7868
|
+
visitSelectQuery(node.subquery, visitor);
|
|
7869
|
+
return;
|
|
7870
|
+
case "BetweenExpression":
|
|
7871
|
+
visitOperandNode(node.left, visitor);
|
|
7872
|
+
visitOperandNode(node.lower, visitor);
|
|
7873
|
+
visitOperandNode(node.upper, visitor);
|
|
7874
|
+
return;
|
|
7875
|
+
case "ArithmeticExpression":
|
|
7876
|
+
visitOperandNode(node.left, visitor);
|
|
7877
|
+
visitOperandNode(node.right, visitor);
|
|
7878
|
+
return;
|
|
7879
|
+
case "BitwiseExpression":
|
|
7880
|
+
visitOperandNode(node.left, visitor);
|
|
7881
|
+
visitOperandNode(node.right, visitor);
|
|
7882
|
+
return;
|
|
7883
|
+
default: {
|
|
7884
|
+
return;
|
|
7885
|
+
}
|
|
7886
|
+
}
|
|
7887
|
+
};
|
|
7888
|
+
var visitOperandNode = (node, visitor) => {
|
|
7889
|
+
visitor.visitOperand?.(node);
|
|
7890
|
+
const type = getNodeType3(node);
|
|
7891
|
+
if (type === "Param") {
|
|
7892
|
+
visitor.visitParam?.(node);
|
|
7893
|
+
}
|
|
7894
|
+
if (!type) return;
|
|
7895
|
+
switch (type) {
|
|
7896
|
+
case "Column":
|
|
7897
|
+
case "Literal":
|
|
7898
|
+
case "Param":
|
|
7899
|
+
case "AliasRef":
|
|
7900
|
+
return;
|
|
7901
|
+
case "Function":
|
|
7902
|
+
node.args?.forEach((arg) => visitOperandNode(arg, visitor));
|
|
7903
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order, visitor));
|
|
7904
|
+
if (node.separator) {
|
|
7905
|
+
visitOperandNode(node.separator, visitor);
|
|
7906
|
+
}
|
|
7907
|
+
return;
|
|
7908
|
+
case "JsonPath":
|
|
7909
|
+
visitOperandNode(node.column, visitor);
|
|
7910
|
+
return;
|
|
7911
|
+
case "ScalarSubquery":
|
|
7912
|
+
visitSelectQuery(node.query, visitor);
|
|
7913
|
+
return;
|
|
7914
|
+
case "CaseExpression":
|
|
7915
|
+
node.conditions.forEach((cond) => {
|
|
7916
|
+
visitExpressionNode(cond.when, visitor);
|
|
7917
|
+
visitOperandNode(cond.then, visitor);
|
|
7918
|
+
});
|
|
7919
|
+
if (node.else) {
|
|
7920
|
+
visitOperandNode(node.else, visitor);
|
|
7921
|
+
}
|
|
7922
|
+
return;
|
|
7923
|
+
case "Cast":
|
|
7924
|
+
visitOperandNode(node.expression, visitor);
|
|
7925
|
+
return;
|
|
7926
|
+
case "WindowFunction":
|
|
7927
|
+
node.args?.forEach((arg) => visitOperandNode(arg, visitor));
|
|
7928
|
+
node.partitionBy?.forEach((term) => visitOperandNode(term, visitor));
|
|
7929
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order, visitor));
|
|
7930
|
+
return;
|
|
7931
|
+
case "ArithmeticExpression":
|
|
7932
|
+
visitOperandNode(node.left, visitor);
|
|
7933
|
+
visitOperandNode(node.right, visitor);
|
|
7934
|
+
return;
|
|
7935
|
+
case "BitwiseExpression":
|
|
7936
|
+
visitOperandNode(node.left, visitor);
|
|
7937
|
+
visitOperandNode(node.right, visitor);
|
|
7938
|
+
return;
|
|
7939
|
+
case "Collate":
|
|
7940
|
+
visitOperandNode(node.expression, visitor);
|
|
7941
|
+
return;
|
|
7942
|
+
default: {
|
|
7943
|
+
const _exhaustive = node;
|
|
7944
|
+
return _exhaustive;
|
|
7945
|
+
}
|
|
7946
|
+
}
|
|
7947
|
+
};
|
|
7948
|
+
var visitSelectQuery = (ast, visitor) => {
|
|
7949
|
+
visitor.visitSelectQuery?.(ast);
|
|
7950
|
+
if (ast.ctes) {
|
|
7951
|
+
for (const cte of ast.ctes) {
|
|
7952
|
+
visitor.visitCte?.(cte);
|
|
7953
|
+
visitSelectQuery(cte.query, visitor);
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
visitTableSource(ast.from, visitor);
|
|
7957
|
+
ast.columns?.forEach((col2) => {
|
|
7958
|
+
visitOperandNode(col2, visitor);
|
|
7959
|
+
});
|
|
7960
|
+
ast.joins?.forEach((join) => {
|
|
7961
|
+
visitor.visitJoin?.(join);
|
|
7962
|
+
visitTableSource(join.table, visitor);
|
|
7963
|
+
visitExpressionNode(join.condition, visitor);
|
|
7964
|
+
});
|
|
7965
|
+
if (ast.where) {
|
|
7966
|
+
visitExpressionNode(ast.where, visitor);
|
|
7967
|
+
}
|
|
7968
|
+
ast.groupBy?.forEach((term) => {
|
|
7969
|
+
visitOrderingTerm(term, visitor);
|
|
7970
|
+
});
|
|
7971
|
+
if (ast.having) {
|
|
7972
|
+
visitExpressionNode(ast.having, visitor);
|
|
7973
|
+
}
|
|
7974
|
+
ast.orderBy?.forEach((order) => {
|
|
7975
|
+
visitOrderByNode(order, visitor);
|
|
7976
|
+
});
|
|
7977
|
+
ast.distinct?.forEach((col2) => {
|
|
7978
|
+
visitOperandNode(col2, visitor);
|
|
7979
|
+
});
|
|
7980
|
+
ast.setOps?.forEach((op) => {
|
|
7981
|
+
visitor.visitSetOperation?.(op);
|
|
7982
|
+
visitSelectQuery(op.query, visitor);
|
|
7983
|
+
});
|
|
7984
|
+
};
|
|
7985
|
+
|
|
7986
|
+
// src/core/ast/ast-validation.ts
|
|
7987
|
+
var hasParamOperandsInQuery = (ast) => {
|
|
7988
|
+
let hasParams = false;
|
|
7989
|
+
visitSelectQuery(ast, {
|
|
7990
|
+
visitParam: () => {
|
|
7991
|
+
hasParams = true;
|
|
7992
|
+
}
|
|
7993
|
+
});
|
|
7994
|
+
return hasParams;
|
|
7995
|
+
};
|
|
7996
|
+
|
|
7740
7997
|
// src/query-builder/select.ts
|
|
7741
7998
|
var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
7742
7999
|
env;
|
|
@@ -8210,6 +8467,17 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8210
8467
|
}
|
|
8211
8468
|
return this;
|
|
8212
8469
|
}
|
|
8470
|
+
/**
|
|
8471
|
+
* Validates that the query does not contain Param operands.
|
|
8472
|
+
* Param proxies are only for schema generation, not execution.
|
|
8473
|
+
*/
|
|
8474
|
+
validateNoParamOperands() {
|
|
8475
|
+
const ast = this.context.hydration.applyToAst(this.context.state.ast);
|
|
8476
|
+
const hasParams = hasParamOperandsInQuery(ast);
|
|
8477
|
+
if (hasParams) {
|
|
8478
|
+
throw new Error("Cannot execute query containing Param operands. Param proxies are only for schema generation (getSchema()). If you need real parameters, use literal values.");
|
|
8479
|
+
}
|
|
8480
|
+
}
|
|
8213
8481
|
/**
|
|
8214
8482
|
* Executes the query and returns hydrated results.
|
|
8215
8483
|
* If the builder was created with an entity constructor (e.g. via selectFromEntity),
|
|
@@ -8223,6 +8491,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8223
8491
|
* users[0] instanceof User; // true
|
|
8224
8492
|
*/
|
|
8225
8493
|
async execute(ctx) {
|
|
8494
|
+
this.validateNoParamOperands();
|
|
8226
8495
|
if (this.entityConstructor) {
|
|
8227
8496
|
return this.executeAs(this.entityConstructor, ctx);
|
|
8228
8497
|
}
|
|
@@ -8241,6 +8510,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8241
8510
|
* rows[0] instanceof User; // false
|
|
8242
8511
|
*/
|
|
8243
8512
|
async executePlain(ctx) {
|
|
8513
|
+
this.validateNoParamOperands();
|
|
8244
8514
|
const builder = this.ensureDefaultSelection();
|
|
8245
8515
|
const rows = await executeHydratedPlain(ctx, builder);
|
|
8246
8516
|
return rows;
|
|
@@ -8260,6 +8530,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8260
8530
|
* users[0].getFullName(); // works!
|
|
8261
8531
|
*/
|
|
8262
8532
|
async executeAs(entityClass, ctx) {
|
|
8533
|
+
this.validateNoParamOperands();
|
|
8263
8534
|
const builder = this.ensureDefaultSelection();
|
|
8264
8535
|
const results = await executeHydrated(ctx, builder);
|
|
8265
8536
|
return materializeAs(entityClass, results);
|
|
@@ -8271,6 +8542,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8271
8542
|
* const total = await qb.count(session);
|
|
8272
8543
|
*/
|
|
8273
8544
|
async count(session) {
|
|
8545
|
+
this.validateNoParamOperands();
|
|
8274
8546
|
return executeCount(this.context, this.env, session);
|
|
8275
8547
|
}
|
|
8276
8548
|
/**
|
|
@@ -8280,6 +8552,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8280
8552
|
* const { items, totalItems, page, pageSize } = await qb.executePaged(session, { page: 1, pageSize: 20 });
|
|
8281
8553
|
*/
|
|
8282
8554
|
async executePaged(session, options) {
|
|
8555
|
+
this.validateNoParamOperands();
|
|
8283
8556
|
const builder = this.ensureDefaultSelection();
|
|
8284
8557
|
return executePagedQuery(builder, session, options, (sess) => builder.count(sess));
|
|
8285
8558
|
}
|
|
@@ -8294,6 +8567,7 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8294
8567
|
* const users = await qb.executeWithContexts(execCtx, hydCtx);
|
|
8295
8568
|
*/
|
|
8296
8569
|
async executeWithContexts(execCtx, hydCtx) {
|
|
8570
|
+
this.validateNoParamOperands();
|
|
8297
8571
|
const builder = this.ensureDefaultSelection();
|
|
8298
8572
|
const results = await executeHydratedWithContexts(execCtx, hydCtx, builder);
|
|
8299
8573
|
if (this.entityConstructor) {
|