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.js
CHANGED
|
@@ -371,16 +371,27 @@ var operandTypes = /* @__PURE__ */ new Set([
|
|
|
371
371
|
"BitwiseExpression",
|
|
372
372
|
"Collate"
|
|
373
373
|
]);
|
|
374
|
-
var
|
|
374
|
+
var getNodeType = (value) => {
|
|
375
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
376
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
377
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
378
|
+
return descriptor.value;
|
|
379
|
+
}
|
|
380
|
+
if ("type" in value) {
|
|
381
|
+
const type = value.type;
|
|
382
|
+
return typeof type === "string" ? type : void 0;
|
|
383
|
+
}
|
|
384
|
+
return void 0;
|
|
385
|
+
};
|
|
375
386
|
var isOperandNode = (node) => {
|
|
376
|
-
|
|
377
|
-
return operandTypes.has(
|
|
378
|
-
};
|
|
379
|
-
var isFunctionNode = (node) => isOperandNode(node) && node
|
|
380
|
-
var isCaseExpressionNode = (node) => isOperandNode(node) && node
|
|
381
|
-
var isCastExpressionNode = (node) => isOperandNode(node) && node
|
|
382
|
-
var isCollateExpressionNode = (node) => isOperandNode(node) && node
|
|
383
|
-
var isWindowFunctionNode = (node) => isOperandNode(node) && node
|
|
387
|
+
const type = getNodeType(node);
|
|
388
|
+
return type !== void 0 && operandTypes.has(type);
|
|
389
|
+
};
|
|
390
|
+
var isFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "Function";
|
|
391
|
+
var isCaseExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "CaseExpression";
|
|
392
|
+
var isCastExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Cast";
|
|
393
|
+
var isCollateExpressionNode = (node) => isOperandNode(node) && getNodeType(node) === "Collate";
|
|
394
|
+
var isWindowFunctionNode = (node) => isOperandNode(node) && getNodeType(node) === "WindowFunction";
|
|
384
395
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isCastExpressionNode(node) || isWindowFunctionNode(node);
|
|
385
396
|
|
|
386
397
|
// src/core/ast/expression-builders.ts
|
|
@@ -759,23 +770,34 @@ var registerExpressionDispatcher = (type, dispatcher) => {
|
|
|
759
770
|
var registerOperandDispatcher = (type, dispatcher) => {
|
|
760
771
|
operandRegistry = operandRegistry.register(type, dispatcher);
|
|
761
772
|
};
|
|
773
|
+
var hasExpressionDispatcher = (type) => expressionRegistry.get(type) !== void 0;
|
|
774
|
+
var hasOperandDispatcher = (type) => operandRegistry.get(type) !== void 0;
|
|
762
775
|
var clearExpressionDispatchers = () => {
|
|
763
776
|
expressionRegistry = expressionRegistry.clear();
|
|
764
777
|
};
|
|
765
778
|
var clearOperandDispatchers = () => {
|
|
766
779
|
operandRegistry = operandRegistry.clear();
|
|
767
780
|
};
|
|
768
|
-
var
|
|
781
|
+
var getNodeType2 = (node) => {
|
|
782
|
+
if (typeof node !== "object" || node === null) return void 0;
|
|
783
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
784
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
785
|
+
return descriptor.value;
|
|
786
|
+
}
|
|
787
|
+
const type = node.type;
|
|
788
|
+
return typeof type === "string" ? type : void 0;
|
|
789
|
+
};
|
|
769
790
|
var unsupportedExpression = (node) => {
|
|
770
|
-
throw new Error(`Unsupported expression type "${
|
|
791
|
+
throw new Error(`Unsupported expression type "${getNodeType2(node) ?? "unknown"}"`);
|
|
771
792
|
};
|
|
772
793
|
var unsupportedOperand = (node) => {
|
|
773
|
-
throw new Error(`Unsupported operand type "${
|
|
794
|
+
throw new Error(`Unsupported operand type "${getNodeType2(node) ?? "unknown"}"`);
|
|
774
795
|
};
|
|
775
796
|
var visitExpression = (node, visitor) => {
|
|
776
|
-
const
|
|
797
|
+
const type = getNodeType2(node);
|
|
798
|
+
const dynamic = type ? expressionRegistry.get(type) : void 0;
|
|
777
799
|
if (dynamic) return dynamic(node, visitor);
|
|
778
|
-
switch (
|
|
800
|
+
switch (type) {
|
|
779
801
|
case "BinaryExpression":
|
|
780
802
|
if (visitor.visitBinaryExpression) return visitor.visitBinaryExpression(node);
|
|
781
803
|
break;
|
|
@@ -807,9 +829,10 @@ var visitExpression = (node, visitor) => {
|
|
|
807
829
|
return unsupportedExpression(node);
|
|
808
830
|
};
|
|
809
831
|
var visitOperand = (node, visitor) => {
|
|
810
|
-
const
|
|
832
|
+
const type = getNodeType2(node);
|
|
833
|
+
const dynamic = type ? operandRegistry.get(type) : void 0;
|
|
811
834
|
if (dynamic) return dynamic(node, visitor);
|
|
812
|
-
switch (
|
|
835
|
+
switch (type) {
|
|
813
836
|
case "Column":
|
|
814
837
|
if (visitor.visitColumn) return visitor.visitColumn(node);
|
|
815
838
|
break;
|
|
@@ -843,6 +866,12 @@ var visitOperand = (node, visitor) => {
|
|
|
843
866
|
case "Collate":
|
|
844
867
|
if (visitor.visitCollate) return visitor.visitCollate(node);
|
|
845
868
|
break;
|
|
869
|
+
case "ArithmeticExpression":
|
|
870
|
+
if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
|
|
871
|
+
break;
|
|
872
|
+
case "BitwiseExpression":
|
|
873
|
+
if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
|
|
874
|
+
break;
|
|
846
875
|
default:
|
|
847
876
|
break;
|
|
848
877
|
}
|
|
@@ -1538,9 +1567,11 @@ var Dialect = class _Dialect {
|
|
|
1538
1567
|
* @returns Compiled SQL operand
|
|
1539
1568
|
*/
|
|
1540
1569
|
compileOperand(node, ctx) {
|
|
1541
|
-
const
|
|
1570
|
+
const descriptor = Object.getOwnPropertyDescriptor(node, "type");
|
|
1571
|
+
const nodeType = typeof descriptor?.value === "string" ? descriptor.value : typeof node.type === "string" ? node.type : void 0;
|
|
1572
|
+
const compiler = nodeType ? this.operandCompilers.get(nodeType) : void 0;
|
|
1542
1573
|
if (!compiler) {
|
|
1543
|
-
throw new Error(`Unsupported operand node type "${
|
|
1574
|
+
throw new Error(`Unsupported operand node type "${nodeType ?? "unknown"}" for ${this.constructor.name}`);
|
|
1544
1575
|
}
|
|
1545
1576
|
return compiler(node, ctx);
|
|
1546
1577
|
}
|
|
@@ -3861,6 +3892,10 @@ var QueryAstService = class {
|
|
|
3861
3892
|
* @returns Normalized ordering term
|
|
3862
3893
|
*/
|
|
3863
3894
|
normalizeOrderingTerm(term) {
|
|
3895
|
+
const paramNode = this.toParamNode(term);
|
|
3896
|
+
if (paramNode) {
|
|
3897
|
+
return paramNode;
|
|
3898
|
+
}
|
|
3864
3899
|
const from = this.state.ast.from;
|
|
3865
3900
|
const tableRef2 = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
3866
3901
|
const termType = term.type;
|
|
@@ -3878,6 +3913,14 @@ var QueryAstService = class {
|
|
|
3878
3913
|
}
|
|
3879
3914
|
return buildColumnNode(tableRef2, term);
|
|
3880
3915
|
}
|
|
3916
|
+
toParamNode(value) {
|
|
3917
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
3918
|
+
const type = Object.getOwnPropertyDescriptor(value, "type")?.value;
|
|
3919
|
+
if (type !== "Param") return void 0;
|
|
3920
|
+
const name = Object.getOwnPropertyDescriptor(value, "name")?.value;
|
|
3921
|
+
if (typeof name !== "string") return void 0;
|
|
3922
|
+
return { type: "Param", name };
|
|
3923
|
+
}
|
|
3881
3924
|
};
|
|
3882
3925
|
|
|
3883
3926
|
// src/query-builder/relation-projection-helper.ts
|
|
@@ -6117,9 +6160,9 @@ var flattenResults = (results) => {
|
|
|
6117
6160
|
}
|
|
6118
6161
|
return rows;
|
|
6119
6162
|
};
|
|
6120
|
-
var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
6163
|
+
var executeWithContexts = async (execCtx, entityCtx, qb, options) => {
|
|
6121
6164
|
const ast = qb.getAST();
|
|
6122
|
-
const compiled = execCtx.dialect.compileSelect(ast);
|
|
6165
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true }) : execCtx.dialect.compileSelect(ast);
|
|
6123
6166
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6124
6167
|
const rows = flattenResults(executed);
|
|
6125
6168
|
const lazyRelations = qb.getLazyRelations();
|
|
@@ -6137,9 +6180,9 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
|
6137
6180
|
await preloadRelationIncludes(entities, includeTree);
|
|
6138
6181
|
return entities;
|
|
6139
6182
|
};
|
|
6140
|
-
var executePlainWithContexts = async (execCtx, qb) => {
|
|
6183
|
+
var executePlainWithContexts = async (execCtx, qb, options) => {
|
|
6141
6184
|
const ast = qb.getAST();
|
|
6142
|
-
const compiled = execCtx.dialect.compileSelect(ast);
|
|
6185
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(ast, { allowParams: true }) : execCtx.dialect.compileSelect(ast);
|
|
6143
6186
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6144
6187
|
const rows = flattenResults(executed);
|
|
6145
6188
|
if (ast.setOps && ast.setOps.length > 0) {
|
|
@@ -6147,21 +6190,21 @@ var executePlainWithContexts = async (execCtx, qb) => {
|
|
|
6147
6190
|
}
|
|
6148
6191
|
return hydrateRows(rows, qb.getHydrationPlan());
|
|
6149
6192
|
};
|
|
6150
|
-
async function executeHydrated(session, qb) {
|
|
6151
|
-
return executeWithContexts(session.getExecutionContext(), session, qb);
|
|
6193
|
+
async function executeHydrated(session, qb, options) {
|
|
6194
|
+
return executeWithContexts(session.getExecutionContext(), session, qb, options);
|
|
6152
6195
|
}
|
|
6153
|
-
async function executeHydratedPlain(session, qb) {
|
|
6154
|
-
return executePlainWithContexts(session.getExecutionContext(), qb);
|
|
6196
|
+
async function executeHydratedPlain(session, qb, options) {
|
|
6197
|
+
return executePlainWithContexts(session.getExecutionContext(), qb, options);
|
|
6155
6198
|
}
|
|
6156
|
-
async function executeHydratedWithContexts(execCtx, hydCtx, qb) {
|
|
6199
|
+
async function executeHydratedWithContexts(execCtx, hydCtx, qb, options) {
|
|
6157
6200
|
const entityCtx = hydCtx.entityContext;
|
|
6158
6201
|
if (!entityCtx) {
|
|
6159
6202
|
throw new Error("Hydration context is missing an EntityContext");
|
|
6160
6203
|
}
|
|
6161
|
-
return executeWithContexts(execCtx, entityCtx, qb);
|
|
6204
|
+
return executeWithContexts(execCtx, entityCtx, qb, options);
|
|
6162
6205
|
}
|
|
6163
|
-
async function executeHydratedPlainWithContexts(execCtx, qb) {
|
|
6164
|
-
return executePlainWithContexts(execCtx, qb);
|
|
6206
|
+
async function executeHydratedPlainWithContexts(execCtx, qb, options) {
|
|
6207
|
+
return executePlainWithContexts(execCtx, qb, options);
|
|
6165
6208
|
}
|
|
6166
6209
|
var loadLazyRelationsForTable = async (ctx, table, lazyRelations, lazyRelationOptions) => {
|
|
6167
6210
|
if (!lazyRelations.length) return;
|
|
@@ -6362,7 +6405,7 @@ function applyOrderBy(context, predicateFacet, term, directionOrOptions) {
|
|
|
6362
6405
|
const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
|
|
6363
6406
|
return predicateFacet.orderBy(context, term, dir, options.nulls, options.collation);
|
|
6364
6407
|
}
|
|
6365
|
-
async function executeCount(context, env, session) {
|
|
6408
|
+
async function executeCount(context, env, session, options) {
|
|
6366
6409
|
const unpagedAst = {
|
|
6367
6410
|
...context.state.ast,
|
|
6368
6411
|
orderBy: void 0,
|
|
@@ -6382,7 +6425,7 @@ async function executeCount(context, env, session) {
|
|
|
6382
6425
|
joins: []
|
|
6383
6426
|
};
|
|
6384
6427
|
const execCtx = session.getExecutionContext();
|
|
6385
|
-
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
6428
|
+
const compiled = options?.allowParamOperands ? execCtx.dialect.compileSelectWithOptions(countQuery, { allowParams: true }) : execCtx.dialect.compileSelect(countQuery);
|
|
6386
6429
|
const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
6387
6430
|
const value = results[0]?.values?.[0]?.[0];
|
|
6388
6431
|
if (typeof value === "number") return value;
|
|
@@ -6390,7 +6433,7 @@ async function executeCount(context, env, session) {
|
|
|
6390
6433
|
if (typeof value === "string") return Number(value);
|
|
6391
6434
|
return value === null || value === void 0 ? 0 : Number(value);
|
|
6392
6435
|
}
|
|
6393
|
-
async function executePagedQuery(builder, session, options, countCallback) {
|
|
6436
|
+
async function executePagedQuery(builder, session, options, countCallback, paramOptions) {
|
|
6394
6437
|
const { page, pageSize } = options;
|
|
6395
6438
|
if (!Number.isInteger(page) || page < 1) {
|
|
6396
6439
|
throw new Error("executePaged: page must be an integer >= 1");
|
|
@@ -6400,7 +6443,7 @@ async function executePagedQuery(builder, session, options, countCallback) {
|
|
|
6400
6443
|
}
|
|
6401
6444
|
const offset = (page - 1) * pageSize;
|
|
6402
6445
|
const totalItems = await countCallback(session);
|
|
6403
|
-
const items = await builder.limit(pageSize).offset(offset).execute(session);
|
|
6446
|
+
const items = await builder.limit(pageSize).offset(offset).execute(session, paramOptions);
|
|
6404
6447
|
return { items, totalItems, page, pageSize };
|
|
6405
6448
|
}
|
|
6406
6449
|
function buildWhereHasPredicate(env, context, relationFacet, createChildBuilder, relationName, callbackOrOptions, maybeOptions, negate = false) {
|
|
@@ -7483,225 +7526,235 @@ var buildFilterParameters = (table, where, from, options = {}) => {
|
|
|
7483
7526
|
}];
|
|
7484
7527
|
};
|
|
7485
7528
|
|
|
7486
|
-
// src/core/ast/
|
|
7487
|
-
var
|
|
7488
|
-
|
|
7489
|
-
|
|
7529
|
+
// src/core/ast/query-visitor.ts
|
|
7530
|
+
var getNodeType3 = (value) => {
|
|
7531
|
+
if (typeof value !== "object" || value === null) return void 0;
|
|
7532
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, "type");
|
|
7533
|
+
if (descriptor && typeof descriptor.value === "string") {
|
|
7534
|
+
return descriptor.value;
|
|
7535
|
+
}
|
|
7536
|
+
if ("type" in value) {
|
|
7537
|
+
const type = value.type;
|
|
7538
|
+
return typeof type === "string" ? type : void 0;
|
|
7539
|
+
}
|
|
7540
|
+
return void 0;
|
|
7541
|
+
};
|
|
7542
|
+
var visitSelectQuery = (ast, visitor) => {
|
|
7543
|
+
const visitExpressionNode = (node) => {
|
|
7544
|
+
visitExpression(node, expressionVisitor);
|
|
7545
|
+
};
|
|
7546
|
+
const visitOperandNode = (node) => {
|
|
7547
|
+
visitOperand(node, operandVisitor);
|
|
7548
|
+
};
|
|
7549
|
+
const visitOrderingTerm = (term) => {
|
|
7550
|
+
if (!term || typeof term !== "object") return;
|
|
7551
|
+
if (isOperandNode(term)) {
|
|
7552
|
+
visitOperandNode(term);
|
|
7553
|
+
return;
|
|
7554
|
+
}
|
|
7555
|
+
const type = getNodeType3(term);
|
|
7556
|
+
if (type && hasOperandDispatcher(type)) {
|
|
7557
|
+
visitOperandNode(term);
|
|
7558
|
+
return;
|
|
7559
|
+
}
|
|
7560
|
+
if (type) {
|
|
7561
|
+
visitExpressionNode(term);
|
|
7562
|
+
}
|
|
7563
|
+
};
|
|
7564
|
+
const visitOrderByNode = (node) => {
|
|
7565
|
+
visitor.visitOrderBy?.(node);
|
|
7566
|
+
visitOrderingTerm(node.term);
|
|
7567
|
+
};
|
|
7568
|
+
const visitTableSource = (source) => {
|
|
7569
|
+
visitor.visitTableSource?.(source);
|
|
7570
|
+
if (source.type === "DerivedTable") {
|
|
7571
|
+
visitor.visitDerivedTable?.(source);
|
|
7572
|
+
visitSelectQuery(source.query, visitor);
|
|
7573
|
+
return;
|
|
7574
|
+
}
|
|
7575
|
+
if (source.type === "FunctionTable") {
|
|
7576
|
+
visitor.visitFunctionTable?.(source);
|
|
7577
|
+
source.args?.forEach((arg) => visitOperandNode(arg));
|
|
7578
|
+
}
|
|
7579
|
+
};
|
|
7580
|
+
const expressionVisitor = {
|
|
7490
7581
|
visitBinaryExpression: (node) => {
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
},
|
|
7495
|
-
otherwise: () => {
|
|
7496
|
-
}
|
|
7497
|
-
});
|
|
7498
|
-
visitOperand(node.right, {
|
|
7499
|
-
visitParam: () => {
|
|
7500
|
-
hasParams = true;
|
|
7501
|
-
},
|
|
7502
|
-
otherwise: () => {
|
|
7503
|
-
}
|
|
7504
|
-
});
|
|
7582
|
+
visitor.visitExpression?.(node);
|
|
7583
|
+
visitOperandNode(node.left);
|
|
7584
|
+
visitOperandNode(node.right);
|
|
7505
7585
|
if (node.escape) {
|
|
7506
|
-
|
|
7507
|
-
visitParam: () => {
|
|
7508
|
-
hasParams = true;
|
|
7509
|
-
},
|
|
7510
|
-
otherwise: () => {
|
|
7511
|
-
}
|
|
7512
|
-
});
|
|
7586
|
+
visitOperandNode(node.escape);
|
|
7513
7587
|
}
|
|
7514
7588
|
},
|
|
7515
7589
|
visitLogicalExpression: (node) => {
|
|
7516
|
-
|
|
7517
|
-
|
|
7518
|
-
hasParams = true;
|
|
7519
|
-
}
|
|
7520
|
-
});
|
|
7590
|
+
visitor.visitExpression?.(node);
|
|
7591
|
+
node.operands.forEach((operand) => visitExpressionNode(operand));
|
|
7521
7592
|
},
|
|
7522
|
-
visitNullExpression: () => {
|
|
7593
|
+
visitNullExpression: (node) => {
|
|
7594
|
+
visitor.visitExpression?.(node);
|
|
7595
|
+
visitOperandNode(node.left);
|
|
7523
7596
|
},
|
|
7524
7597
|
visitInExpression: (node) => {
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
hasParams = true;
|
|
7528
|
-
},
|
|
7529
|
-
otherwise: () => {
|
|
7530
|
-
}
|
|
7531
|
-
});
|
|
7598
|
+
visitor.visitExpression?.(node);
|
|
7599
|
+
visitOperandNode(node.left);
|
|
7532
7600
|
if (Array.isArray(node.right)) {
|
|
7533
|
-
node.right.forEach((operand) =>
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
},
|
|
7537
|
-
otherwise: () => {
|
|
7538
|
-
}
|
|
7539
|
-
}));
|
|
7601
|
+
node.right.forEach((operand) => visitOperandNode(operand));
|
|
7602
|
+
} else {
|
|
7603
|
+
visitOperandNode(node.right);
|
|
7540
7604
|
}
|
|
7541
7605
|
},
|
|
7542
|
-
visitExistsExpression: () => {
|
|
7606
|
+
visitExistsExpression: (node) => {
|
|
7607
|
+
visitor.visitExpression?.(node);
|
|
7608
|
+
visitSelectQuery(node.subquery, visitor);
|
|
7543
7609
|
},
|
|
7544
7610
|
visitBetweenExpression: (node) => {
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
otherwise: () => {
|
|
7550
|
-
}
|
|
7551
|
-
});
|
|
7552
|
-
visitOperand(node.lower, {
|
|
7553
|
-
visitParam: () => {
|
|
7554
|
-
hasParams = true;
|
|
7555
|
-
},
|
|
7556
|
-
otherwise: () => {
|
|
7557
|
-
}
|
|
7558
|
-
});
|
|
7559
|
-
visitOperand(node.upper, {
|
|
7560
|
-
visitParam: () => {
|
|
7561
|
-
hasParams = true;
|
|
7562
|
-
},
|
|
7563
|
-
otherwise: () => {
|
|
7564
|
-
}
|
|
7565
|
-
});
|
|
7611
|
+
visitor.visitExpression?.(node);
|
|
7612
|
+
visitOperandNode(node.left);
|
|
7613
|
+
visitOperandNode(node.lower);
|
|
7614
|
+
visitOperandNode(node.upper);
|
|
7566
7615
|
},
|
|
7567
7616
|
visitArithmeticExpression: (node) => {
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
},
|
|
7572
|
-
otherwise: () => {
|
|
7573
|
-
}
|
|
7574
|
-
});
|
|
7575
|
-
visitOperand(node.right, {
|
|
7576
|
-
visitParam: () => {
|
|
7577
|
-
hasParams = true;
|
|
7578
|
-
},
|
|
7579
|
-
otherwise: () => {
|
|
7580
|
-
}
|
|
7581
|
-
});
|
|
7617
|
+
visitor.visitExpression?.(node);
|
|
7618
|
+
visitOperandNode(node.left);
|
|
7619
|
+
visitOperandNode(node.right);
|
|
7582
7620
|
},
|
|
7583
7621
|
visitBitwiseExpression: (node) => {
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
},
|
|
7588
|
-
otherwise: () => {
|
|
7589
|
-
}
|
|
7590
|
-
});
|
|
7591
|
-
visitOperand(node.right, {
|
|
7592
|
-
visitParam: () => {
|
|
7593
|
-
hasParams = true;
|
|
7594
|
-
},
|
|
7595
|
-
otherwise: () => {
|
|
7596
|
-
}
|
|
7597
|
-
});
|
|
7622
|
+
visitor.visitExpression?.(node);
|
|
7623
|
+
visitOperandNode(node.left);
|
|
7624
|
+
visitOperandNode(node.right);
|
|
7598
7625
|
},
|
|
7599
|
-
|
|
7626
|
+
visitOperand: (node) => {
|
|
7627
|
+
visitOperandNode(node);
|
|
7628
|
+
},
|
|
7629
|
+
visitSelectQuery: (node) => {
|
|
7630
|
+
visitSelectQuery(node, visitor);
|
|
7631
|
+
},
|
|
7632
|
+
otherwise: (node) => {
|
|
7633
|
+
visitor.visitExpression?.(node);
|
|
7600
7634
|
}
|
|
7601
|
-
}
|
|
7602
|
-
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
let hasParams = false;
|
|
7606
|
-
visitOperand(operand, {
|
|
7607
|
-
visitColumn: () => {
|
|
7635
|
+
};
|
|
7636
|
+
const operandVisitor = {
|
|
7637
|
+
visitColumn: (node) => {
|
|
7638
|
+
visitor.visitOperand?.(node);
|
|
7608
7639
|
},
|
|
7609
|
-
visitLiteral: () => {
|
|
7640
|
+
visitLiteral: (node) => {
|
|
7641
|
+
visitor.visitOperand?.(node);
|
|
7610
7642
|
},
|
|
7611
|
-
visitParam: () => {
|
|
7612
|
-
|
|
7643
|
+
visitParam: (node) => {
|
|
7644
|
+
visitor.visitOperand?.(node);
|
|
7645
|
+
visitor.visitParam?.(node);
|
|
7613
7646
|
},
|
|
7614
7647
|
visitFunction: (node) => {
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7648
|
+
visitor.visitOperand?.(node);
|
|
7649
|
+
node.args?.forEach((arg) => visitOperandNode(arg));
|
|
7650
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order));
|
|
7651
|
+
if (node.separator) {
|
|
7652
|
+
visitOperandNode(node.separator);
|
|
7653
|
+
}
|
|
7620
7654
|
},
|
|
7621
|
-
visitJsonPath: () => {
|
|
7655
|
+
visitJsonPath: (node) => {
|
|
7656
|
+
visitor.visitOperand?.(node);
|
|
7657
|
+
visitOperandNode(node.column);
|
|
7622
7658
|
},
|
|
7623
|
-
visitScalarSubquery: () => {
|
|
7659
|
+
visitScalarSubquery: (node) => {
|
|
7660
|
+
visitor.visitOperand?.(node);
|
|
7661
|
+
visitSelectQuery(node.query, visitor);
|
|
7624
7662
|
},
|
|
7625
7663
|
visitCaseExpression: (node) => {
|
|
7664
|
+
visitor.visitOperand?.(node);
|
|
7626
7665
|
node.conditions.forEach((cond) => {
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
}
|
|
7630
|
-
if (hasParamOperandsInOperand(cond.then)) {
|
|
7631
|
-
hasParams = true;
|
|
7632
|
-
}
|
|
7666
|
+
visitExpressionNode(cond.when);
|
|
7667
|
+
visitOperandNode(cond.then);
|
|
7633
7668
|
});
|
|
7634
|
-
if (node.else
|
|
7635
|
-
|
|
7669
|
+
if (node.else) {
|
|
7670
|
+
visitOperandNode(node.else);
|
|
7636
7671
|
}
|
|
7637
7672
|
},
|
|
7638
7673
|
visitCast: (node) => {
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
}
|
|
7674
|
+
visitor.visitOperand?.(node);
|
|
7675
|
+
visitOperandNode(node.expression);
|
|
7642
7676
|
},
|
|
7643
7677
|
visitWindowFunction: (node) => {
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
|
|
7654
|
-
|
|
7655
|
-
|
|
7678
|
+
visitor.visitOperand?.(node);
|
|
7679
|
+
node.args?.forEach((arg) => visitOperandNode(arg));
|
|
7680
|
+
node.partitionBy?.forEach((term) => visitOperandNode(term));
|
|
7681
|
+
node.orderBy?.forEach((order) => visitOrderByNode(order));
|
|
7682
|
+
},
|
|
7683
|
+
visitArithmeticExpression: (node) => {
|
|
7684
|
+
visitor.visitOperand?.(node);
|
|
7685
|
+
visitOperandNode(node.left);
|
|
7686
|
+
visitOperandNode(node.right);
|
|
7687
|
+
},
|
|
7688
|
+
visitBitwiseExpression: (node) => {
|
|
7689
|
+
visitor.visitOperand?.(node);
|
|
7690
|
+
visitOperandNode(node.left);
|
|
7691
|
+
visitOperandNode(node.right);
|
|
7692
|
+
},
|
|
7693
|
+
visitExpression: (node) => {
|
|
7694
|
+
visitExpressionNode(node);
|
|
7695
|
+
},
|
|
7696
|
+
visitSelectQuery: (node) => {
|
|
7697
|
+
visitSelectQuery(node, visitor);
|
|
7656
7698
|
},
|
|
7657
7699
|
visitCollate: (node) => {
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
}
|
|
7700
|
+
visitor.visitOperand?.(node);
|
|
7701
|
+
visitOperandNode(node.expression);
|
|
7661
7702
|
},
|
|
7662
|
-
visitAliasRef: () => {
|
|
7703
|
+
visitAliasRef: (node) => {
|
|
7704
|
+
visitor.visitOperand?.(node);
|
|
7663
7705
|
},
|
|
7664
|
-
otherwise: () => {
|
|
7706
|
+
otherwise: (node) => {
|
|
7707
|
+
visitor.visitOperand?.(node);
|
|
7708
|
+
}
|
|
7709
|
+
};
|
|
7710
|
+
visitor.visitSelectQuery?.(ast);
|
|
7711
|
+
if (ast.ctes) {
|
|
7712
|
+
for (const cte of ast.ctes) {
|
|
7713
|
+
visitor.visitCte?.(cte);
|
|
7714
|
+
visitSelectQuery(cte.query, visitor);
|
|
7665
7715
|
}
|
|
7666
|
-
});
|
|
7667
|
-
return hasParams;
|
|
7668
|
-
};
|
|
7669
|
-
var hasParamOperandsInQuery = (ast) => {
|
|
7670
|
-
if (ast.where && hasParamOperandsInExpression(ast.where)) {
|
|
7671
|
-
return true;
|
|
7672
|
-
}
|
|
7673
|
-
if (ast.having && hasParamOperandsInExpression(ast.having)) {
|
|
7674
|
-
return true;
|
|
7675
7716
|
}
|
|
7717
|
+
visitTableSource(ast.from);
|
|
7676
7718
|
ast.columns?.forEach((col2) => {
|
|
7677
|
-
|
|
7678
|
-
if (hasParamOperandsInOperand(col2)) {
|
|
7679
|
-
return true;
|
|
7680
|
-
}
|
|
7681
|
-
}
|
|
7719
|
+
visitOperandNode(col2);
|
|
7682
7720
|
});
|
|
7683
|
-
ast.
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
}
|
|
7688
|
-
}
|
|
7721
|
+
ast.joins?.forEach((join) => {
|
|
7722
|
+
visitor.visitJoin?.(join);
|
|
7723
|
+
visitTableSource(join.table);
|
|
7724
|
+
visitExpressionNode(join.condition);
|
|
7689
7725
|
});
|
|
7690
|
-
if (ast.
|
|
7691
|
-
|
|
7692
|
-
if (cte.query.where && hasParamOperandsInExpression(cte.query.where)) {
|
|
7693
|
-
return true;
|
|
7694
|
-
}
|
|
7695
|
-
}
|
|
7726
|
+
if (ast.where) {
|
|
7727
|
+
visitExpressionNode(ast.where);
|
|
7696
7728
|
}
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7729
|
+
ast.groupBy?.forEach((term) => {
|
|
7730
|
+
visitOrderingTerm(term);
|
|
7731
|
+
});
|
|
7732
|
+
if (ast.having) {
|
|
7733
|
+
visitExpressionNode(ast.having);
|
|
7734
|
+
}
|
|
7735
|
+
ast.orderBy?.forEach((order) => {
|
|
7736
|
+
visitOrderByNode(order);
|
|
7737
|
+
});
|
|
7738
|
+
ast.distinct?.forEach((col2) => {
|
|
7739
|
+
visitOperandNode(col2);
|
|
7740
|
+
});
|
|
7741
|
+
ast.setOps?.forEach((op) => {
|
|
7742
|
+
visitor.visitSetOperation?.(op);
|
|
7743
|
+
visitSelectQuery(op.query, visitor);
|
|
7744
|
+
});
|
|
7745
|
+
};
|
|
7746
|
+
|
|
7747
|
+
// src/core/ast/ast-validation.ts
|
|
7748
|
+
var findFirstParamOperandName = (ast) => {
|
|
7749
|
+
let name;
|
|
7750
|
+
visitSelectQuery(ast, {
|
|
7751
|
+
visitParam: (node) => {
|
|
7752
|
+
if (!name) {
|
|
7753
|
+
name = node.name;
|
|
7701
7754
|
}
|
|
7702
7755
|
}
|
|
7703
|
-
}
|
|
7704
|
-
return
|
|
7756
|
+
});
|
|
7757
|
+
return name;
|
|
7705
7758
|
};
|
|
7706
7759
|
|
|
7707
7760
|
// src/query-builder/select.ts
|
|
@@ -8181,11 +8234,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8181
8234
|
* Validates that the query does not contain Param operands.
|
|
8182
8235
|
* Param proxies are only for schema generation, not execution.
|
|
8183
8236
|
*/
|
|
8184
|
-
validateNoParamOperands() {
|
|
8237
|
+
validateNoParamOperands(options) {
|
|
8238
|
+
if (options?.allowParamOperands) return;
|
|
8185
8239
|
const ast = this.context.hydration.applyToAst(this.context.state.ast);
|
|
8186
|
-
const
|
|
8187
|
-
if (
|
|
8188
|
-
throw new Error(
|
|
8240
|
+
const paramName = findFirstParamOperandName(ast);
|
|
8241
|
+
if (paramName) {
|
|
8242
|
+
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.`);
|
|
8189
8243
|
}
|
|
8190
8244
|
}
|
|
8191
8245
|
/**
|
|
@@ -8200,13 +8254,13 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8200
8254
|
* // users is User[]
|
|
8201
8255
|
* users[0] instanceof User; // true
|
|
8202
8256
|
*/
|
|
8203
|
-
async execute(ctx) {
|
|
8204
|
-
this.validateNoParamOperands();
|
|
8257
|
+
async execute(ctx, options) {
|
|
8258
|
+
this.validateNoParamOperands(options);
|
|
8205
8259
|
if (this.entityConstructor) {
|
|
8206
|
-
return this.executeAs(this.entityConstructor, ctx);
|
|
8260
|
+
return this.executeAs(this.entityConstructor, ctx, options);
|
|
8207
8261
|
}
|
|
8208
8262
|
const builder = this.ensureDefaultSelection();
|
|
8209
|
-
return executeHydrated(ctx, builder);
|
|
8263
|
+
return executeHydrated(ctx, builder, options);
|
|
8210
8264
|
}
|
|
8211
8265
|
/**
|
|
8212
8266
|
* Executes the query and returns plain row objects (POJOs), ignoring any entity materialization.
|
|
@@ -8219,10 +8273,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8219
8273
|
* // rows is EntityInstance<UserTable>[] (plain objects)
|
|
8220
8274
|
* rows[0] instanceof User; // false
|
|
8221
8275
|
*/
|
|
8222
|
-
async executePlain(ctx) {
|
|
8223
|
-
this.validateNoParamOperands();
|
|
8276
|
+
async executePlain(ctx, options) {
|
|
8277
|
+
this.validateNoParamOperands(options);
|
|
8224
8278
|
const builder = this.ensureDefaultSelection();
|
|
8225
|
-
const rows = await executeHydratedPlain(ctx, builder);
|
|
8279
|
+
const rows = await executeHydratedPlain(ctx, builder, options);
|
|
8226
8280
|
return rows;
|
|
8227
8281
|
}
|
|
8228
8282
|
/**
|
|
@@ -8239,10 +8293,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8239
8293
|
* users[0] instanceof User; // true!
|
|
8240
8294
|
* users[0].getFullName(); // works!
|
|
8241
8295
|
*/
|
|
8242
|
-
async executeAs(entityClass, ctx) {
|
|
8243
|
-
this.validateNoParamOperands();
|
|
8296
|
+
async executeAs(entityClass, ctx, options) {
|
|
8297
|
+
this.validateNoParamOperands(options);
|
|
8244
8298
|
const builder = this.ensureDefaultSelection();
|
|
8245
|
-
const results = await executeHydrated(ctx, builder);
|
|
8299
|
+
const results = await executeHydrated(ctx, builder, options);
|
|
8246
8300
|
return materializeAs(entityClass, results);
|
|
8247
8301
|
}
|
|
8248
8302
|
/**
|
|
@@ -8251,9 +8305,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8251
8305
|
* @example
|
|
8252
8306
|
* const total = await qb.count(session);
|
|
8253
8307
|
*/
|
|
8254
|
-
async count(session) {
|
|
8255
|
-
this.validateNoParamOperands();
|
|
8256
|
-
return executeCount(this.context, this.env, session);
|
|
8308
|
+
async count(session, options) {
|
|
8309
|
+
this.validateNoParamOperands(options);
|
|
8310
|
+
return executeCount(this.context, this.env, session, options);
|
|
8257
8311
|
}
|
|
8258
8312
|
/**
|
|
8259
8313
|
* Executes the query and returns both the paged items and the total.
|
|
@@ -8262,9 +8316,9 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8262
8316
|
* const { items, totalItems, page, pageSize } = await qb.executePaged(session, { page: 1, pageSize: 20 });
|
|
8263
8317
|
*/
|
|
8264
8318
|
async executePaged(session, options) {
|
|
8265
|
-
this.validateNoParamOperands();
|
|
8319
|
+
this.validateNoParamOperands(options);
|
|
8266
8320
|
const builder = this.ensureDefaultSelection();
|
|
8267
|
-
return executePagedQuery(builder, session, options, (sess) => builder.count(sess));
|
|
8321
|
+
return executePagedQuery(builder, session, options, (sess) => builder.count(sess, options), options);
|
|
8268
8322
|
}
|
|
8269
8323
|
/**
|
|
8270
8324
|
* Executes the query with provided execution and hydration contexts
|
|
@@ -8276,10 +8330,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8276
8330
|
* const hydCtx = new HydrationContext();
|
|
8277
8331
|
* const users = await qb.executeWithContexts(execCtx, hydCtx);
|
|
8278
8332
|
*/
|
|
8279
|
-
async executeWithContexts(execCtx, hydCtx) {
|
|
8280
|
-
this.validateNoParamOperands();
|
|
8333
|
+
async executeWithContexts(execCtx, hydCtx, options) {
|
|
8334
|
+
this.validateNoParamOperands(options);
|
|
8281
8335
|
const builder = this.ensureDefaultSelection();
|
|
8282
|
-
const results = await executeHydratedWithContexts(execCtx, hydCtx, builder);
|
|
8336
|
+
const results = await executeHydratedWithContexts(execCtx, hydCtx, builder, options);
|
|
8283
8337
|
if (this.entityConstructor) {
|
|
8284
8338
|
return materializeAs(this.entityConstructor, results);
|
|
8285
8339
|
}
|
|
@@ -8512,9 +8566,17 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8512
8566
|
* .compile('postgres');
|
|
8513
8567
|
* console.log(compiled.sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
|
|
8514
8568
|
*/
|
|
8515
|
-
compile(dialect) {
|
|
8569
|
+
compile(dialect, options) {
|
|
8516
8570
|
const resolved = resolveDialectInput(dialect);
|
|
8517
|
-
|
|
8571
|
+
const ast = this.getAST();
|
|
8572
|
+
if (!options?.allowParamOperands) {
|
|
8573
|
+
const paramName = findFirstParamOperandName(ast);
|
|
8574
|
+
if (paramName) {
|
|
8575
|
+
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.`);
|
|
8576
|
+
}
|
|
8577
|
+
return resolved.compileSelect(ast);
|
|
8578
|
+
}
|
|
8579
|
+
return resolved.compileSelectWithOptions(ast, { allowParams: true });
|
|
8518
8580
|
}
|
|
8519
8581
|
/**
|
|
8520
8582
|
* Converts the query to SQL string for a specific dialect
|
|
@@ -8526,8 +8588,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8526
8588
|
* .toSql('postgres');
|
|
8527
8589
|
* console.log(sql); // SELECT "id", "name" FROM "users" WHERE "active" = true
|
|
8528
8590
|
*/
|
|
8529
|
-
toSql(dialect) {
|
|
8530
|
-
return this.compile(dialect).sql;
|
|
8591
|
+
toSql(dialect, options) {
|
|
8592
|
+
return this.compile(dialect, options).sql;
|
|
8531
8593
|
}
|
|
8532
8594
|
/**
|
|
8533
8595
|
* Gets hydration plan for query
|
|
@@ -14215,8 +14277,10 @@ export {
|
|
|
14215
14277
|
groupConcat,
|
|
14216
14278
|
gt,
|
|
14217
14279
|
gte,
|
|
14280
|
+
hasExpressionDispatcher,
|
|
14218
14281
|
hasMany,
|
|
14219
14282
|
hasOne,
|
|
14283
|
+
hasOperandDispatcher,
|
|
14220
14284
|
hour,
|
|
14221
14285
|
hydrateRows,
|
|
14222
14286
|
ifNull,
|