metal-orm 1.0.83 → 1.0.86
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 +299 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -13
- package/dist/index.d.ts +28 -13
- package/dist/index.js +297 -233
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/ast/ast-validation.ts +11 -180
- package/src/core/ast/expression-nodes.ts +35 -25
- package/src/core/ast/expression-visitor.ts +53 -25
- package/src/core/ast/query-visitor.ts +273 -0
- package/src/core/dialect/abstract.ts +11 -7
- package/src/orm/execute.ts +60 -46
- package/src/query-builder/query-ast-service.ts +13 -0
- package/src/query-builder/select/select-operations.ts +32 -24
- package/src/query-builder/select.ts +49 -35
package/dist/index.cjs
CHANGED
|
@@ -175,8 +175,10 @@ __export(index_exports, {
|
|
|
175
175
|
groupConcat: () => groupConcat,
|
|
176
176
|
gt: () => gt,
|
|
177
177
|
gte: () => gte,
|
|
178
|
+
hasExpressionDispatcher: () => hasExpressionDispatcher,
|
|
178
179
|
hasMany: () => hasMany,
|
|
179
180
|
hasOne: () => hasOne,
|
|
181
|
+
hasOperandDispatcher: () => hasOperandDispatcher,
|
|
180
182
|
hour: () => hour,
|
|
181
183
|
hydrateRows: () => hydrateRows,
|
|
182
184
|
ifNull: () => ifNull,
|
|
@@ -655,16 +657,27 @@ var operandTypes = /* @__PURE__ */ new Set([
|
|
|
655
657
|
"BitwiseExpression",
|
|
656
658
|
"Collate"
|
|
657
659
|
]);
|
|
658
|
-
var
|
|
660
|
+
var getNodeType = (value) => {
|
|
661
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
662
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
663
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
664
|
+
return descriptor.value;
|
|
665
|
+
}
|
|
666
|
+
if ("type" in value) {
|
|
667
|
+
const type = value.type;
|
|
668
|
+
return typeof type === "string" ? type : void 0;
|
|
669
|
+
}
|
|
670
|
+
return void 0;
|
|
671
|
+
};
|
|
659
672
|
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
|
|
673
|
+
const type = getNodeType(node);
|
|
674
|
+
return type !== void 0 && operandTypes.has(type);
|
|
675
|
+
};
|
|
676
|
+
var isFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "Function";
|
|
677
|
+
var isCaseExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "CaseExpression";
|
|
678
|
+
var isCastExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Cast";
|
|
679
|
+
var isCollateExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Collate";
|
|
680
|
+
var isWindowFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "WindowFunction";
|
|
668
681
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isCastExpressionNode(node) || isWindowFunctionNode(node);
|
|
669
682
|
|
|
670
683
|
// src/core/ast/expression-builders.ts
|
|
@@ -1043,23 +1056,34 @@ var registerExpressionDispatcher = (type, dispatcher) => {
|
|
|
1043
1056
|
var registerOperandDispatcher = (type, dispatcher) => {
|
|
1044
1057
|
operandRegistry = operandRegistry.register(type, dispatcher);
|
|
1045
1058
|
};
|
|
1059
|
+
var hasExpressionDispatcher = (type) => expressionRegistry.get(type) !== void 0;
|
|
1060
|
+
var hasOperandDispatcher = (type) => operandRegistry.get(type) !== void 0;
|
|
1046
1061
|
var clearExpressionDispatchers = () => {
|
|
1047
1062
|
expressionRegistry = expressionRegistry.clear();
|
|
1048
1063
|
};
|
|
1049
1064
|
var clearOperandDispatchers = () => {
|
|
1050
1065
|
operandRegistry = operandRegistry.clear();
|
|
1051
1066
|
};
|
|
1052
|
-
var
|
|
1067
|
+
var getNodeType2 = (node) => {
|
|
1068
|
+
if (typeof node !== "object" || node === null) return void 0;
|
|
1069
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
1070
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
1071
|
+
return descriptor.value;
|
|
1072
|
+
}
|
|
1073
|
+
const type = node.type;
|
|
1074
|
+
return typeof type === "string" ? type : void 0;
|
|
1075
|
+
};
|
|
1053
1076
|
var unsupportedExpression = (node) => {
|
|
1054
|
-
throw new Error(`Unsupported expression type "${
|
|
1077
|
+
throw new Error(`Unsupported expression type "${getNodeType2(node) ?? "unknown"}"`);
|
|
1055
1078
|
};
|
|
1056
1079
|
var unsupportedOperand = (node) => {
|
|
1057
|
-
throw new Error(`Unsupported operand type "${
|
|
1080
|
+
throw new Error(`Unsupported operand type "${getNodeType2(node) ?? "unknown"}"`);
|
|
1058
1081
|
};
|
|
1059
1082
|
var visitExpression = (node, visitor) => {
|
|
1060
|
-
const
|
|
1083
|
+
const type = getNodeType2(node);
|
|
1084
|
+
const dynamic = type ? expressionRegistry.get(type) : void 0;
|
|
1061
1085
|
if (dynamic) return dynamic(node, visitor);
|
|
1062
|
-
switch (
|
|
1086
|
+
switch (type) {
|
|
1063
1087
|
case "BinaryExpression":
|
|
1064
1088
|
if (visitor.visitBinaryExpression) return visitor.visitBinaryExpression(node);
|
|
1065
1089
|
break;
|
|
@@ -1091,9 +1115,10 @@ var visitExpression = (node, visitor) => {
|
|
|
1091
1115
|
return unsupportedExpression(node);
|
|
1092
1116
|
};
|
|
1093
1117
|
var visitOperand = (node, visitor) => {
|
|
1094
|
-
const
|
|
1118
|
+
const type = getNodeType2(node);
|
|
1119
|
+
const dynamic = type ? operandRegistry.get(type) : void 0;
|
|
1095
1120
|
if (dynamic) return dynamic(node, visitor);
|
|
1096
|
-
switch (
|
|
1121
|
+
switch (type) {
|
|
1097
1122
|
case "Column":
|
|
1098
1123
|
if (visitor.visitColumn) return visitor.visitColumn(node);
|
|
1099
1124
|
break;
|
|
@@ -1127,6 +1152,12 @@ var visitOperand = (node, visitor) => {
|
|
|
1127
1152
|
case "Collate":
|
|
1128
1153
|
if (visitor.visitCollate) return visitor.visitCollate(node);
|
|
1129
1154
|
break;
|
|
1155
|
+
case "ArithmeticExpression":
|
|
1156
|
+
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
|
|
1157
|
+
break;
|
|
1158
|
+
case "BitwiseExpression":
|
|
1159
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
1160
|
+
break;
|
|
1130
1161
|
default:
|
|
1131
1162
|
break;
|
|
1132
1163
|
}
|
|
@@ -1822,9 +1853,11 @@ var Dialect = class _Dialect {
|
|
|
1822
1853
|
* @returns Compiled SQL operand
|
|
1823
1854
|
*/
|
|
1824
1855
|
compileOperand(node, ctx) {
|
|
1825
|
-
const
|
|
1856
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
1857
|
+
const nodeType = typeof descriptor?.value === "string" ? descriptor.value : typeof node.type === "string" ? node.type : void 0;
|
|
1858
|
+
const compiler = nodeType ? this.operandCompilers.get(nodeType) : void 0;
|
|
1826
1859
|
if (!compiler) {
|
|
1827
|
-
throw new Error(`Unsupported operand node type "${
|
|
1860
|
+
throw new Error(`Unsupported operand node type "${nodeType ?? "unknown"}" for ${this.constructor.name}`);
|
|
1828
1861
|
}
|
|
1829
1862
|
return compiler(node, ctx);
|
|
1830
1863
|
}
|
|
@@ -4145,6 +4178,10 @@ var QueryAstService = class {
|
|
|
4145
4178
|
* @returns Normalized ordering term
|
|
4146
4179
|
*/
|
|
4147
4180
|
normalizeOrderingTerm(term) {
|
|
4181
|
+
const paramNode = this.toParamNode(term);
|
|
4182
|
+
if (paramNode) {
|
|
4183
|
+
return paramNode;
|
|
4184
|
+
}
|
|
4148
4185
|
const from = this.state.ast.from;
|
|
4149
4186
|
const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
4150
4187
|
const termType = term.type;
|
|
@@ -4162,6 +4199,14 @@ var QueryAstService = class {
|
|
|
4162
4199
|
}
|
|
4163
4200
|
return buildColumnNode(tableRef2, term);
|
|
4164
4201
|
}
|
|
4202
|
+
toParamNode(value) {
|
|
4203
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
4204
|
+
const type = Object.getOwnPropertyDescriptor(value, "type")?.value;
|
|
4205
|
+
if (type !== "Param") return void 0;
|
|
4206
|
+
const name = Object.getOwnPropertyDescriptor(value, "name")?.value;
|
|
4207
|
+
if (typeof name !== "string") return void 0;
|
|
4208
|
+
return { type: "Param", name };
|
|
4209
|
+
}
|
|
4165
4210
|
};
|
|
4166
4211
|
|
|
4167
4212
|
// src/query-builder/relation-projection-helper.ts
|
|
@@ -6401,9 +6446,9 @@ var flattenResults = (results) => {
|
|
|
6401
6446
|
}
|
|
6402
6447
|
return rows;
|
|
6403
6448
|
};
|
|
6404
|
-
var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
6449
|
+
var executeWithContexts = async (execCtx, entityCtx, qb, options) => {
|
|
6405
6450
|
const ast = qb.getAST();
|
|
6406
|
-
const compiled = execCtx.dialect.compileSelect(ast);
|
|
6451
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true }) : execCtx.dialect.compileSelect(ast);
|
|
6407
6452
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6408
6453
|
const rows = flattenResults(executed);
|
|
6409
6454
|
const lazyRelations = qb.getLazyRelations();
|
|
@@ -6421,9 +6466,9 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
|
6421
6466
|
await preloadRelationIncludes(entities, includeTree);
|
|
6422
6467
|
return entities;
|
|
6423
6468
|
};
|
|
6424
|
-
var executePlainWithContexts = async (execCtx, qb) => {
|
|
6469
|
+
var executePlainWithContexts = async (execCtx, qb, options) => {
|
|
6425
6470
|
const ast = qb.getAST();
|
|
6426
|
-
const compiled = execCtx.dialect.compileSelect(ast);
|
|
6471
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true }) : execCtx.dialect.compileSelect(ast);
|
|
6427
6472
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6428
6473
|
const rows = flattenResults(executed);
|
|
6429
6474
|
if (ast.setOps && ast.setOps.length > 0) {
|
|
@@ -6431,21 +6476,21 @@ var executePlainWithContexts = async (execCtx, qb) => {
|
|
|
6431
6476
|
}
|
|
6432
6477
|
return hydrateRows(rows, qb.getHydrationPlan());
|
|
6433
6478
|
};
|
|
6434
|
-
async function executeHydrated(session, qb) {
|
|
6435
|
-
return executeWithContexts(session.getExecutionContext(), session, qb);
|
|
6479
|
+
async function executeHydrated(session, qb, options) {
|
|
6480
|
+
return executeWithContexts(session.getExecutionContext(), session, qb, options);
|
|
6436
6481
|
}
|
|
6437
|
-
async function executeHydratedPlain(session, qb) {
|
|
6438
|
-
return executePlainWithContexts(session.getExecutionContext(), qb);
|
|
6482
|
+
async function executeHydratedPlain(session, qb, options) {
|
|
6483
|
+
return executePlainWithContexts(session.getExecutionContext(), qb, options);
|
|
6439
6484
|
}
|
|
6440
|
-
async function executeHydratedWithContexts(execCtx, hydCtx, qb) {
|
|
6485
|
+
async function executeHydratedWithContexts(execCtx, hydCtx, qb, options) {
|
|
6441
6486
|
const entityCtx = hydCtx.entityContext;
|
|
6442
6487
|
if (!entityCtx) {
|
|
6443
6488
|
throw new Error("Hydration context is missing an EntityContext");
|
|
6444
6489
|
}
|
|
6445
|
-
return executeWithContexts(execCtx, entityCtx, qb);
|
|
6490
|
+
return executeWithContexts(execCtx, entityCtx, qb, options);
|
|
6446
6491
|
}
|
|
6447
|
-
async function executeHydratedPlainWithContexts(execCtx, qb) {
|
|
6448
|
-
return executePlainWithContexts(execCtx, qb);
|
|
6492
|
+
async function executeHydratedPlainWithContexts(execCtx, qb, options) {
|
|
6493
|
+
return executePlainWithContexts(execCtx, qb, options);
|
|
6449
6494
|
}
|
|
6450
6495
|
var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOptions) => {
|
|
6451
6496
|
if (!lazyRelations.length) return;
|
|
@@ -6646,7 +6691,7 @@ function applyOrderBy(context, predicateFacet, term, directionOrOptions) {
|
|
|
6646
6691
|
const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
|
|
6647
6692
|
return predicateFacet.orderBy(context, term, dir, options.nulls, options.collation);
|
|
6648
6693
|
}
|
|
6649
|
-
async function executeCount(context, env, session) {
|
|
6694
|
+
async function executeCount(context, env, session, options) {
|
|
6650
6695
|
const unpagedAst = {
|
|
6651
6696
|
...context.state.ast,
|
|
6652
6697
|
orderBy: void 0,
|
|
@@ -6666,7 +6711,7 @@ async function executeCount(context, env, session) {
|
|
|
6666
6711
|
joins: []
|
|
6667
6712
|
};
|
|
6668
6713
|
const execCtx = session.getExecutionContext();
|
|
6669
|
-
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
6714
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(countQuery, { allowParams: true }) : execCtx.dialect.compileSelect(countQuery);
|
|
6670
6715
|
const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6671
6716
|
const value = results[0]?.values?.[0]?.[0];
|
|
6672
6717
|
if (typeof value === "number") return value;
|
|
@@ -6674,7 +6719,7 @@ async function executeCount(context, env, session) {
|
|
|
6674
6719
|
if (typeof value === "string") return Number(value);
|
|
6675
6720
|
return value === null || value === void 0 ? 0 : Number(value);
|
|
6676
6721
|
}
|
|
6677
|
-
async function executePagedQuery(builder, session, options, countCallback) {
|
|
6722
|
+
async function executePagedQuery(builder, session, options, countCallback, paramOptions) {
|
|
6678
6723
|
const { page, pageSize } = options;
|
|
6679
6724
|
if (!Number.isInteger(page) || page < 1) {
|
|
6680
6725
|
throw new Error("executePaged: page must be an integer >= 1");
|
|
@@ -6684,7 +6729,7 @@ async function executePagedQuery(builder, session, options, countCallback) {
|
|
|
6684
6729
|
}
|
|
6685
6730
|
const offset = (page - 1) * pageSize;
|
|
6686
6731
|
const totalItems = await countCallback(session);
|
|
6687
|
-
const items = await builder.limit(pageSize).offset(offset).execute(session);
|
|
6732
|
+
const items = await builder.limit(pageSize).offset(offset).execute(session, paramOptions);
|
|
6688
6733
|
return { items, totalItems, page, pageSize };
|
|
6689
6734
|
}
|
|
6690
6735
|
function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder, relationName, callbackOrOptions, maybeOptions, negate = false) {
|
|
@@ -7767,225 +7812,235 @@ var buildFilterParameters = (table, where, from, options = {}) => {
|
|
|
7767
7812
|
}];
|
|
7768
7813
|
};
|
|
7769
7814
|
|
|
7770
|
-
// src/core/ast/
|
|
7771
|
-
var
|
|
7772
|
-
|
|
7773
|
-
|
|
7815
|
+
// src/core/ast/query-visitor.ts
|
|
7816
|
+
var getNodeType3 = (value) => {
|
|
7817
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7818
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
7819
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
7820
|
+
return descriptor.value;
|
|
7821
|
+
}
|
|
7822
|
+
if ("type" in value) {
|
|
7823
|
+
const type = value.type;
|
|
7824
|
+
return typeof type === "string" ? type : void 0;
|
|
7825
|
+
}
|
|
7826
|
+
return void 0;
|
|
7827
|
+
};
|
|
7828
|
+
var visitSelectQuery = (ast, visitor) => {
|
|
7829
|
+
const visitExpressionNode = (node) => {
|
|
7830
|
+
visitExpression(node, expressionVisitor);
|
|
7831
|
+
};
|
|
7832
|
+
const visitOperandNode = (node) => {
|
|
7833
|
+
visitOperand(node, operandVisitor);
|
|
7834
|
+
};
|
|
7835
|
+
const visitOrderingTerm = (term) => {
|
|
7836
|
+
if (!term || typeof term !== "object") return;
|
|
7837
|
+
if (isOperandNode(term)) {
|
|
7838
|
+
visitOperandNode(term);
|
|
7839
|
+
return;
|
|
7840
|
+
}
|
|
7841
|
+
const type = getNodeType3(term);
|
|
7842
|
+
if (type && hasOperandDispatcher(type)) {
|
|
7843
|
+
visitOperandNode(term);
|
|
7844
|
+
return;
|
|
7845
|
+
}
|
|
7846
|
+
if (type) {
|
|
7847
|
+
visitExpressionNode(term);
|
|
7848
|
+
}
|
|
7849
|
+
};
|
|
7850
|
+
const visitOrderByNode = (node) => {
|
|
7851
|
+
visitor.visitOrderBy?.(node);
|
|
7852
|
+
visitOrderingTerm(node.term);
|
|
7853
|
+
};
|
|
7854
|
+
const visitTableSource = (source) => {
|
|
7855
|
+
visitor.visitTableSource?.(source);
|
|
7856
|
+
if (source.type === "DerivedTable") {
|
|
7857
|
+
visitor.visitDerivedTable?.(source);
|
|
7858
|
+
visitSelectQuery(source.query, visitor);
|
|
7859
|
+
return;
|
|
7860
|
+
}
|
|
7861
|
+
if (source.type === "FunctionTable") {
|
|
7862
|
+
visitor.visitFunctionTable?.(source);
|
|
7863
|
+
source.args?.forEach((arg) => visitOperandNode(arg));
|
|
7864
|
+
}
|
|
7865
|
+
};
|
|
7866
|
+
const expressionVisitor = {
|
|
7774
7867
|
visitBinaryExpression: (node) => {
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
},
|
|
7779
|
-
otherwise: () => {
|
|
7780
|
-
}
|
|
7781
|
-
});
|
|
7782
|
-
visitOperand(node.right, {
|
|
7783
|
-
visitParam: () => {
|
|
7784
|
-
hasParams = true;
|
|
7785
|
-
},
|
|
7786
|
-
otherwise: () => {
|
|
7787
|
-
}
|
|
7788
|
-
});
|
|
7868
|
+
visitor.visitExpression?.(node);
|
|
7869
|
+
visitOperandNode(node.left);
|
|
7870
|
+
visitOperandNode(node.right);
|
|
7789
7871
|
if (node.escape) {
|
|
7790
|
-
|
|
7791
|
-
visitParam: () => {
|
|
7792
|
-
hasParams = true;
|
|
7793
|
-
},
|
|
7794
|
-
otherwise: () => {
|
|
7795
|
-
}
|
|
7796
|
-
});
|
|
7872
|
+
visitOperandNode(node.escape);
|
|
7797
7873
|
}
|
|
7798
7874
|
},
|
|
7799
7875
|
visitLogicalExpression: (node) => {
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
hasParams = true;
|
|
7803
|
-
}
|
|
7804
|
-
});
|
|
7876
|
+
visitor.visitExpression?.(node);
|
|
7877
|
+
node.operands.forEach((operand) => visitExpressionNode(operand));
|
|
7805
7878
|
},
|
|
7806
|
-
visitNullExpression: () => {
|
|
7879
|
+
visitNullExpression: (node) => {
|
|
7880
|
+
visitor.visitExpression?.(node);
|
|
7881
|
+
visitOperandNode(node.left);
|
|
7807
7882
|
},
|
|
7808
7883
|
visitInExpression: (node) => {
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
hasParams = true;
|
|
7812
|
-
},
|
|
7813
|
-
otherwise: () => {
|
|
7814
|
-
}
|
|
7815
|
-
});
|
|
7884
|
+
visitor.visitExpression?.(node);
|
|
7885
|
+
visitOperandNode(node.left);
|
|
7816
7886
|
if (Array.isArray(node.right)) {
|
|
7817
|
-
node.right.forEach((operand) =>
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
},
|
|
7821
|
-
otherwise: () => {
|
|
7822
|
-
}
|
|
7823
|
-
}));
|
|
7887
|
+
node.right.forEach((operand) => visitOperandNode(operand));
|
|
7888
|
+
} else {
|
|
7889
|
+
visitOperandNode(node.right);
|
|
7824
7890
|
}
|
|
7825
7891
|
},
|
|
7826
|
-
visitExistsExpression: () => {
|
|
7892
|
+
visitExistsExpression: (node) => {
|
|
7893
|
+
visitor.visitExpression?.(node);
|
|
7894
|
+
visitSelectQuery(node.subquery, visitor);
|
|
7827
7895
|
},
|
|
7828
7896
|
visitBetweenExpression: (node) => {
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
otherwise: () => {
|
|
7834
|
-
}
|
|
7835
|
-
});
|
|
7836
|
-
visitOperand(node.lower, {
|
|
7837
|
-
visitParam: () => {
|
|
7838
|
-
hasParams = true;
|
|
7839
|
-
},
|
|
7840
|
-
otherwise: () => {
|
|
7841
|
-
}
|
|
7842
|
-
});
|
|
7843
|
-
visitOperand(node.upper, {
|
|
7844
|
-
visitParam: () => {
|
|
7845
|
-
hasParams = true;
|
|
7846
|
-
},
|
|
7847
|
-
otherwise: () => {
|
|
7848
|
-
}
|
|
7849
|
-
});
|
|
7897
|
+
visitor.visitExpression?.(node);
|
|
7898
|
+
visitOperandNode(node.left);
|
|
7899
|
+
visitOperandNode(node.lower);
|
|
7900
|
+
visitOperandNode(node.upper);
|
|
7850
7901
|
},
|
|
7851
7902
|
visitArithmeticExpression: (node) => {
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
},
|
|
7856
|
-
otherwise: () => {
|
|
7857
|
-
}
|
|
7858
|
-
});
|
|
7859
|
-
visitOperand(node.right, {
|
|
7860
|
-
visitParam: () => {
|
|
7861
|
-
hasParams = true;
|
|
7862
|
-
},
|
|
7863
|
-
otherwise: () => {
|
|
7864
|
-
}
|
|
7865
|
-
});
|
|
7903
|
+
visitor.visitExpression?.(node);
|
|
7904
|
+
visitOperandNode(node.left);
|
|
7905
|
+
visitOperandNode(node.right);
|
|
7866
7906
|
},
|
|
7867
7907
|
visitBitwiseExpression: (node) => {
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
},
|
|
7872
|
-
otherwise: () => {
|
|
7873
|
-
}
|
|
7874
|
-
});
|
|
7875
|
-
visitOperand(node.right, {
|
|
7876
|
-
visitParam: () => {
|
|
7877
|
-
hasParams = true;
|
|
7878
|
-
},
|
|
7879
|
-
otherwise: () => {
|
|
7880
|
-
}
|
|
7881
|
-
});
|
|
7908
|
+
visitor.visitExpression?.(node);
|
|
7909
|
+
visitOperandNode(node.left);
|
|
7910
|
+
visitOperandNode(node.right);
|
|
7882
7911
|
},
|
|
7883
|
-
|
|
7912
|
+
visitOperand: (node) => {
|
|
7913
|
+
visitOperandNode(node);
|
|
7914
|
+
},
|
|
7915
|
+
visitSelectQuery: (node) => {
|
|
7916
|
+
visitSelectQuery(node, visitor);
|
|
7917
|
+
},
|
|
7918
|
+
otherwise: (node) => {
|
|
7919
|
+
visitor.visitExpression?.(node);
|
|
7884
7920
|
}
|
|
7885
|
-
}
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
let hasParams = false;
|
|
7890
|
-
visitOperand(operand, {
|
|
7891
|
-
visitColumn: () => {
|
|
7921
|
+
};
|
|
7922
|
+
const operandVisitor = {
|
|
7923
|
+
visitColumn: (node) => {
|
|
7924
|
+
visitor.visitOperand?.(node);
|
|
7892
7925
|
},
|
|
7893
|
-
visitLiteral: () => {
|
|
7926
|
+
visitLiteral: (node) => {
|
|
7927
|
+
visitor.visitOperand?.(node);
|
|
7894
7928
|
},
|
|
7895
|
-
visitParam: () => {
|
|
7896
|
-
|
|
7929
|
+
visitParam: (node) => {
|
|
7930
|
+
visitor.visitOperand?.(node);
|
|
7931
|
+
visitor.visitParam?.(node);
|
|
7897
7932
|
},
|
|
7898
7933
|
visitFunction: (node) => {
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7934
|
+
visitor.visitOperand?.(node);
|
|
7935
|
+
node.args?.forEach((arg) => visitOperandNode(arg));
|
|
7936
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order));
|
|
7937
|
+
if (node.separator) {
|
|
7938
|
+
visitOperandNode(node.separator);
|
|
7939
|
+
}
|
|
7904
7940
|
},
|
|
7905
|
-
visitJsonPath: () => {
|
|
7941
|
+
visitJsonPath: (node) => {
|
|
7942
|
+
visitor.visitOperand?.(node);
|
|
7943
|
+
visitOperandNode(node.column);
|
|
7906
7944
|
},
|
|
7907
|
-
visitScalarSubquery: () => {
|
|
7945
|
+
visitScalarSubquery: (node) => {
|
|
7946
|
+
visitor.visitOperand?.(node);
|
|
7947
|
+
visitSelectQuery(node.query, visitor);
|
|
7908
7948
|
},
|
|
7909
7949
|
visitCaseExpression: (node) => {
|
|
7950
|
+
visitor.visitOperand?.(node);
|
|
7910
7951
|
node.conditions.forEach((cond) => {
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
}
|
|
7914
|
-
if (hasParamOperandsInOperand(cond.then)) {
|
|
7915
|
-
hasParams = true;
|
|
7916
|
-
}
|
|
7952
|
+
visitExpressionNode(cond.when);
|
|
7953
|
+
visitOperandNode(cond.then);
|
|
7917
7954
|
});
|
|
7918
|
-
if (node.else
|
|
7919
|
-
|
|
7955
|
+
if (node.else) {
|
|
7956
|
+
visitOperandNode(node.else);
|
|
7920
7957
|
}
|
|
7921
7958
|
},
|
|
7922
7959
|
visitCast: (node) => {
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
}
|
|
7960
|
+
visitor.visitOperand?.(node);
|
|
7961
|
+
visitOperandNode(node.expression);
|
|
7926
7962
|
},
|
|
7927
7963
|
visitWindowFunction: (node) => {
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7964
|
+
visitor.visitOperand?.(node);
|
|
7965
|
+
node.args?.forEach((arg) => visitOperandNode(arg));
|
|
7966
|
+
node.partitionBy?.forEach((term) => visitOperandNode(term));
|
|
7967
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order));
|
|
7968
|
+
},
|
|
7969
|
+
visitArithmeticExpression: (node) => {
|
|
7970
|
+
visitor.visitOperand?.(node);
|
|
7971
|
+
visitOperandNode(node.left);
|
|
7972
|
+
visitOperandNode(node.right);
|
|
7973
|
+
},
|
|
7974
|
+
visitBitwiseExpression: (node) => {
|
|
7975
|
+
visitor.visitOperand?.(node);
|
|
7976
|
+
visitOperandNode(node.left);
|
|
7977
|
+
visitOperandNode(node.right);
|
|
7978
|
+
},
|
|
7979
|
+
visitExpression: (node) => {
|
|
7980
|
+
visitExpressionNode(node);
|
|
7981
|
+
},
|
|
7982
|
+
visitSelectQuery: (node) => {
|
|
7983
|
+
visitSelectQuery(node, visitor);
|
|
7940
7984
|
},
|
|
7941
7985
|
visitCollate: (node) => {
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
}
|
|
7986
|
+
visitor.visitOperand?.(node);
|
|
7987
|
+
visitOperandNode(node.expression);
|
|
7945
7988
|
},
|
|
7946
|
-
visitAliasRef: () => {
|
|
7989
|
+
visitAliasRef: (node) => {
|
|
7990
|
+
visitor.visitOperand?.(node);
|
|
7947
7991
|
},
|
|
7948
|
-
otherwise: () => {
|
|
7992
|
+
otherwise: (node) => {
|
|
7993
|
+
visitor.visitOperand?.(node);
|
|
7994
|
+
}
|
|
7995
|
+
};
|
|
7996
|
+
visitor.visitSelectQuery?.(ast);
|
|
7997
|
+
if (ast.ctes) {
|
|
7998
|
+
for (const cte of ast.ctes) {
|
|
7999
|
+
visitor.visitCte?.(cte);
|
|
8000
|
+
visitSelectQuery(cte.query, visitor);
|
|
7949
8001
|
}
|
|
7950
|
-
});
|
|
7951
|
-
return hasParams;
|
|
7952
|
-
};
|
|
7953
|
-
var hasParamOperandsInQuery = (ast) => {
|
|
7954
|
-
if (ast.where && hasParamOperandsInExpression(ast.where)) {
|
|
7955
|
-
return true;
|
|
7956
|
-
}
|
|
7957
|
-
if (ast.having && hasParamOperandsInExpression(ast.having)) {
|
|
7958
|
-
return true;
|
|
7959
8002
|
}
|
|
8003
|
+
visitTableSource(ast.from);
|
|
7960
8004
|
ast.columns?.forEach((col2) => {
|
|
7961
|
-
|
|
7962
|
-
if (hasParamOperandsInOperand(col2)) {
|
|
7963
|
-
return true;
|
|
7964
|
-
}
|
|
7965
|
-
}
|
|
8005
|
+
visitOperandNode(col2);
|
|
7966
8006
|
});
|
|
7967
|
-
ast.
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
}
|
|
7972
|
-
}
|
|
8007
|
+
ast.joins?.forEach((join) => {
|
|
8008
|
+
visitor.visitJoin?.(join);
|
|
8009
|
+
visitTableSource(join.table);
|
|
8010
|
+
visitExpressionNode(join.condition);
|
|
7973
8011
|
});
|
|
7974
|
-
if (ast.
|
|
7975
|
-
|
|
7976
|
-
if (cte.query.where && hasParamOperandsInExpression(cte.query.where)) {
|
|
7977
|
-
return true;
|
|
7978
|
-
}
|
|
7979
|
-
}
|
|
8012
|
+
if (ast.where) {
|
|
8013
|
+
visitExpressionNode(ast.where);
|
|
7980
8014
|
}
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
8015
|
+
ast.groupBy?.forEach((term) => {
|
|
8016
|
+
visitOrderingTerm(term);
|
|
8017
|
+
});
|
|
8018
|
+
if (ast.having) {
|
|
8019
|
+
visitExpressionNode(ast.having);
|
|
8020
|
+
}
|
|
8021
|
+
ast.orderBy?.forEach((order) => {
|
|
8022
|
+
visitOrderByNode(order);
|
|
8023
|
+
});
|
|
8024
|
+
ast.distinct?.forEach((col2) => {
|
|
8025
|
+
visitOperandNode(col2);
|
|
8026
|
+
});
|
|
8027
|
+
ast.setOps?.forEach((op) => {
|
|
8028
|
+
visitor.visitSetOperation?.(op);
|
|
8029
|
+
visitSelectQuery(op.query, visitor);
|
|
8030
|
+
});
|
|
8031
|
+
};
|
|
8032
|
+
|
|
8033
|
+
// src/core/ast/ast-validation.ts
|
|
8034
|
+
var findFirstParamOperandName = (ast) => {
|
|
8035
|
+
let name;
|
|
8036
|
+
visitSelectQuery(ast, {
|
|
8037
|
+
visitParam: (node) => {
|
|
8038
|
+
if (!name) {
|
|
8039
|
+
name = node.name;
|
|
7985
8040
|
}
|
|
7986
8041
|
}
|
|
7987
|
-
}
|
|
7988
|
-
return
|
|
8042
|
+
});
|
|
8043
|
+
return name;
|
|
7989
8044
|
};
|
|
7990
8045
|
|
|
7991
8046
|
// src/query-builder/select.ts
|
|
@@ -8465,11 +8520,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8465
8520
|
* Validates that the query does not contain Param operands.
|
|
8466
8521
|
* Param proxies are only for schema generation, not execution.
|
|
8467
8522
|
*/
|
|
8468
|
-
validateNoParamOperands() {
|
|
8523
|
+
validateNoParamOperands(options) {
|
|
8524
|
+
if (options?.allowParamOperands) return;
|
|
8469
8525
|
const ast = this.context.hydration.applyToAst(this.context.state.ast);
|
|
8470
|
-
const
|
|
8471
|
-
if (
|
|
8472
|
-
throw new Error(
|
|
8526
|
+
const paramName = findFirstParamOperandName(ast);
|
|
8527
|
+
if (paramName) {
|
|
8528
|
+
throw new Error(`Cannot execute query containing Param operand "${paramName}". Param proxies are only for schema generation (getSchema()). If you need real parameters, use literal values.`);
|
|
8473
8529
|
}
|
|
8474
8530
|
}
|
|
8475
8531
|
/**
|
|
@@ -8484,13 +8540,13 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8484
8540
|
* // users is User[]
|
|
8485
8541
|
* users[0] instanceof User; // true
|
|
8486
8542
|
*/
|
|
8487
|
-
async execute(ctx) {
|
|
8488
|
-
this.validateNoParamOperands();
|
|
8543
|
+
async execute(ctx, options) {
|
|
8544
|
+
this.validateNoParamOperands(options);
|
|
8489
8545
|
if (this.entityConstructor) {
|
|
8490
|
-
return this.executeAs(this.entityConstructor, ctx);
|
|
8546
|
+
return this.executeAs(this.entityConstructor, ctx, options);
|
|
8491
8547
|
}
|
|
8492
8548
|
const builder = this.ensureDefaultSelection();
|
|
8493
|
-
return executeHydrated(ctx, builder);
|
|
8549
|
+
return executeHydrated(ctx, builder, options);
|
|
8494
8550
|
}
|
|
8495
8551
|
/**
|
|
8496
8552
|
* Executes the query and returns plain row objects (POJOs), ignoring any entity materialization.
|
|
@@ -8503,10 +8559,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8503
8559
|
* // rows is EntityInstance<UserTable>[] (plain objects)
|
|
8504
8560
|
* rows[0] instanceof User; // false
|
|
8505
8561
|
*/
|
|
8506
|
-
async executePlain(ctx) {
|
|
8507
|
-
this.validateNoParamOperands();
|
|
8562
|
+
async executePlain(ctx, options) {
|
|
8563
|
+
this.validateNoParamOperands(options);
|
|
8508
8564
|
const builder = this.ensureDefaultSelection();
|
|
8509
|
-
const rows = await executeHydratedPlain(ctx, builder);
|
|
8565
|
+
const rows = await executeHydratedPlain(ctx, builder, options);
|
|
8510
8566
|
return rows;
|
|
8511
8567
|
}
|
|
8512
8568
|
/**
|
|
@@ -8523,10 +8579,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8523
8579
|
* users[0] instanceof User; // true!
|
|
8524
8580
|
* users[0].getFullName(); // works!
|
|
8525
8581
|
*/
|
|
8526
|
-
async executeAs(entityClass, ctx) {
|
|
8527
|
-
this.validateNoParamOperands();
|
|
8582
|
+
async executeAs(entityClass, ctx, options) {
|
|
8583
|
+
this.validateNoParamOperands(options);
|
|
8528
8584
|
const builder = this.ensureDefaultSelection();
|
|
8529
|
-
const results = await executeHydrated(ctx, builder);
|
|
8585
|
+
const results = await executeHydrated(ctx, builder, options);
|
|
8530
8586
|
return materializeAs(entityClass, results);
|
|
8531
8587
|
}
|
|
8532
8588
|
/**
|
|
@@ -8535,9 +8591,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8535
8591
|
* @example
|
|
8536
8592
|
* const total = await qb.count(session);
|
|
8537
8593
|
*/
|
|
8538
|
-
async count(session) {
|
|
8539
|
-
this.validateNoParamOperands();
|
|
8540
|
-
return executeCount(this.context, this.env, session);
|
|
8594
|
+
async count(session, options) {
|
|
8595
|
+
this.validateNoParamOperands(options);
|
|
8596
|
+
return executeCount(this.context, this.env, session, options);
|
|
8541
8597
|
}
|
|
8542
8598
|
/**
|
|
8543
8599
|
* Executes the query and returns both the paged items and the total.
|
|
@@ -8546,9 +8602,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8546
8602
|
* const { items, totalItems, page, pageSize } = await qb.executePaged(session, { page: 1, pageSize: 20 });
|
|
8547
8603
|
*/
|
|
8548
8604
|
async executePaged(session, options) {
|
|
8549
|
-
this.validateNoParamOperands();
|
|
8605
|
+
this.validateNoParamOperands(options);
|
|
8550
8606
|
const builder = this.ensureDefaultSelection();
|
|
8551
|
-
return executePagedQuery(builder, session, options, (sess) => builder.count(sess));
|
|
8607
|
+
return executePagedQuery(builder, session, options, (sess) => builder.count(sess, options), options);
|
|
8552
8608
|
}
|
|
8553
8609
|
/**
|
|
8554
8610
|
* Executes the query with provided execution and hydration contexts
|
|
@@ -8560,10 +8616,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8560
8616
|
* const hydCtx = new HydrationContext();
|
|
8561
8617
|
* const users = await qb.executeWithContexts(execCtx, hydCtx);
|
|
8562
8618
|
*/
|
|
8563
|
-
async executeWithContexts(execCtx, hydCtx) {
|
|
8564
|
-
this.validateNoParamOperands();
|
|
8619
|
+
async executeWithContexts(execCtx, hydCtx, options) {
|
|
8620
|
+
this.validateNoParamOperands(options);
|
|
8565
8621
|
const builder = this.ensureDefaultSelection();
|
|
8566
|
-
const results = await executeHydratedWithContexts(execCtx, hydCtx, builder);
|
|
8622
|
+
const results = await executeHydratedWithContexts(execCtx, hydCtx, builder, options);
|
|
8567
8623
|
if (this.entityConstructor) {
|
|
8568
8624
|
return materializeAs(this.entityConstructor, results);
|
|
8569
8625
|
}
|
|
@@ -8796,9 +8852,17 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8796
8852
|
* .compile('postgres');
|
|
8797
8853
|
* console.log(compiled.sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
|
|
8798
8854
|
*/
|
|
8799
|
-
compile(dialect) {
|
|
8855
|
+
compile(dialect, options) {
|
|
8800
8856
|
const resolved = resolveDialectInput(dialect);
|
|
8801
|
-
|
|
8857
|
+
const ast = this.getAST();
|
|
8858
|
+
if (!options?.allowParamOperands) {
|
|
8859
|
+
const paramName = findFirstParamOperandName(ast);
|
|
8860
|
+
if (paramName) {
|
|
8861
|
+
throw new Error(`Cannot compile query containing Param operand "${paramName}". Param proxies are only for schema generation (getSchema()). If you need real parameters, use literal values.`);
|
|
8862
|
+
}
|
|
8863
|
+
return resolved.compileSelect(ast);
|
|
8864
|
+
}
|
|
8865
|
+
return resolved.compileSelectWithOptions(ast, { allowParams: true });
|
|
8802
8866
|
}
|
|
8803
8867
|
/**
|
|
8804
8868
|
* Converts the query to SQL string for a specific dialect
|
|
@@ -8810,8 +8874,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8810
8874
|
* .toSql('postgres');
|
|
8811
8875
|
* console.log(sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
|
|
8812
8876
|
*/
|
|
8813
|
-
toSql(dialect) {
|
|
8814
|
-
return this.compile(dialect).sql;
|
|
8877
|
+
toSql(dialect, options) {
|
|
8878
|
+
return this.compile(dialect, options).sql;
|
|
8815
8879
|
}
|
|
8816
8880
|
/**
|
|
8817
8881
|
* Gets hydration plan for query
|
|
@@ -14500,8 +14564,10 @@ function createPooledExecutorFactory(opts) {
|
|
|
14500
14564
|
groupConcat,
|
|
14501
14565
|
gt,
|
|
14502
14566
|
gte,
|
|
14567
|
+
hasExpressionDispatcher,
|
|
14503
14568
|
hasMany,
|
|
14504
14569
|
hasOne,
|
|
14570
|
+
hasOperandDispatcher,
|
|
14505
14571
|
hour,
|
|
14506
14572
|
hydrateRows,
|
|
14507
14573
|
ifNull,
|