@mikro-orm/sql 7.1.13-dev.14 → 7.1.13-dev.16
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/SqlEntityManager.js +3 -1
- package/package.json +2 -2
- package/plugin/transformer.d.ts +7 -1
- package/plugin/transformer.js +60 -1
package/SqlEntityManager.js
CHANGED
|
@@ -81,7 +81,9 @@ export class SqlEntityManager extends EntityManager {
|
|
|
81
81
|
const { where: rawWhere, ...countOptions } = options;
|
|
82
82
|
await em.tryFlush(entityName, options);
|
|
83
83
|
const where = await em.processWhere(entityName, rawWhere ?? {}, options, 'read');
|
|
84
|
-
|
|
84
|
+
// match `em.count()` semantics: an active transaction always wins over the requested connection type
|
|
85
|
+
const connectionType = em.getTransactionContext() ? 'write' : options.connectionType;
|
|
86
|
+
const qb = em.createQueryBuilder(meta.class, undefined, connectionType);
|
|
85
87
|
qb
|
|
86
88
|
.select([...fields, raw('count(*) as cnt')])
|
|
87
89
|
.where(where)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.1.13-dev.
|
|
3
|
+
"version": "7.1.13-dev.16",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@mikro-orm/core": "^7.1.12"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mikro-orm/core": "7.1.13-dev.
|
|
56
|
+
"@mikro-orm/core": "7.1.13-dev.16"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">= 22.17.0"
|
package/plugin/transformer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type EntityMetadata, type EntityProperty, type Type } from '@mikro-orm/core';
|
|
2
|
-
import { type CommonTableExpressionNameNode, type DeleteQueryNode, type InsertQueryNode, type JoinNode, type MergeQueryNode, type OperationNode, type QueryId, type SelectQueryNode, type UpdateQueryNode, type WithNode, ColumnNode, IdentifierNode, OperationNodeTransformer, SelectionNode, TableNode, ValueNode } from 'kysely';
|
|
2
|
+
import { type BinaryOperationNode, type CommonTableExpressionNameNode, type DeleteQueryNode, type InsertQueryNode, type JoinNode, type MergeQueryNode, type OperationNode, type QueryId, type SelectQueryNode, type UpdateQueryNode, type WithNode, ColumnNode, IdentifierNode, OperationNodeTransformer, SelectionNode, TableNode, ValueNode } from 'kysely';
|
|
3
3
|
import type { MikroKyselyPluginOptions } from './index.js';
|
|
4
4
|
import type { SqlEntityManager } from '../SqlEntityManager.js';
|
|
5
5
|
export declare class MikroTransformer extends OperationNodeTransformer {
|
|
@@ -28,6 +28,12 @@ export declare class MikroTransformer extends OperationNodeTransformer {
|
|
|
28
28
|
processOnUpdateHooks(node: UpdateQueryNode, meta: EntityMetadata): UpdateQueryNode;
|
|
29
29
|
processInsertValues(node: InsertQueryNode, meta: EntityMetadata): InsertQueryNode;
|
|
30
30
|
processUpdateValues(node: UpdateQueryNode, meta: EntityMetadata): UpdateQueryNode;
|
|
31
|
+
transformBinaryOperation(node: BinaryOperationNode, queryId: QueryId): BinaryOperationNode;
|
|
32
|
+
/** Resolve the entity property a comparison's left operand refers to, so its value operand can be converted. */
|
|
33
|
+
resolveOperandProperty(operand: OperationNode): {
|
|
34
|
+
prop: EntityProperty;
|
|
35
|
+
fieldName: string;
|
|
36
|
+
} | undefined;
|
|
31
37
|
processInputValueNode(prop: EntityProperty | undefined, fieldName: string | undefined, valueNode: ValueNode): OperationNode;
|
|
32
38
|
expandSelections(selections: readonly SelectionNode[]): readonly SelectionNode[];
|
|
33
39
|
expandSelection(sel: SelectionNode): SelectionNode[] | null;
|
package/plugin/transformer.js
CHANGED
|
@@ -455,6 +455,60 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
455
455
|
updates,
|
|
456
456
|
};
|
|
457
457
|
}
|
|
458
|
+
transformBinaryOperation(node, queryId) {
|
|
459
|
+
const transformed = super.transformBinaryOperation(node, queryId);
|
|
460
|
+
if (!this.#options.convertValues) {
|
|
461
|
+
return transformed;
|
|
462
|
+
}
|
|
463
|
+
const resolved = this.resolveOperandProperty(transformed.leftOperand);
|
|
464
|
+
if (!resolved) {
|
|
465
|
+
return transformed;
|
|
466
|
+
}
|
|
467
|
+
const { prop, fieldName } = resolved;
|
|
468
|
+
const right = transformed.rightOperand;
|
|
469
|
+
if (ValueNode.is(right)) {
|
|
470
|
+
const converted = this.processInputValueNode(prop, fieldName, right);
|
|
471
|
+
return converted === right ? transformed : { ...transformed, rightOperand: converted };
|
|
472
|
+
}
|
|
473
|
+
if (PrimitiveValueListNode.is(right)) {
|
|
474
|
+
// upgrade to ValueListNode when the type needs SQL-side wrapping, since
|
|
475
|
+
// PrimitiveValueListNode can only hold primitives
|
|
476
|
+
if (prop.hasConvertToDatabaseValueSQL) {
|
|
477
|
+
const values = right.values.map(value => this.processInputValueNode(prop, fieldName, ValueNode.create(value)));
|
|
478
|
+
return { ...transformed, rightOperand: ValueListNode.create(values) };
|
|
479
|
+
}
|
|
480
|
+
const values = right.values.map(value => this.prepareInputValue(prop, value, true));
|
|
481
|
+
return values.every((value, idx) => value === right.values[idx])
|
|
482
|
+
? transformed
|
|
483
|
+
: { ...transformed, rightOperand: PrimitiveValueListNode.create(values) };
|
|
484
|
+
}
|
|
485
|
+
if (ValueListNode.is(right)) {
|
|
486
|
+
let changed = false;
|
|
487
|
+
const values = right.values.map(valueNode => {
|
|
488
|
+
if (!ValueNode.is(valueNode)) {
|
|
489
|
+
return valueNode;
|
|
490
|
+
}
|
|
491
|
+
const converted = this.processInputValueNode(prop, fieldName, valueNode);
|
|
492
|
+
if (converted !== valueNode) {
|
|
493
|
+
changed = true;
|
|
494
|
+
}
|
|
495
|
+
return converted;
|
|
496
|
+
});
|
|
497
|
+
return changed ? { ...transformed, rightOperand: ValueListNode.create(values) } : transformed;
|
|
498
|
+
}
|
|
499
|
+
return transformed;
|
|
500
|
+
}
|
|
501
|
+
/** Resolve the entity property a comparison's left operand refers to, so its value operand can be converted. */
|
|
502
|
+
resolveOperandProperty(operand) {
|
|
503
|
+
if (!ReferenceNode.is(operand) || !ColumnNode.is(operand.column)) {
|
|
504
|
+
return undefined;
|
|
505
|
+
}
|
|
506
|
+
const tableName = operand.table ? this.getTableName(operand.table) : undefined;
|
|
507
|
+
const meta = this.findOwnerMeta(tableName);
|
|
508
|
+
const fieldName = this.normalizeColumnName(operand.column.column);
|
|
509
|
+
const prop = this.findProperty(meta, fieldName);
|
|
510
|
+
return prop ? { prop, fieldName } : undefined;
|
|
511
|
+
}
|
|
458
512
|
processInputValueNode(prop, fieldName, valueNode) {
|
|
459
513
|
const converted = this.prepareInputValue(prop, valueNode.value, true);
|
|
460
514
|
const newValueNode = converted === valueNode.value
|
|
@@ -543,8 +597,13 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
543
597
|
if (name) {
|
|
544
598
|
return this.lookupInContextStack(name) ?? this.#subqueryAliasMap.get(name) ?? this.findEntityMetadata(name);
|
|
545
599
|
}
|
|
600
|
+
// the stack can be empty when transforming a raw root node with embedded expressions
|
|
601
|
+
const context = this.#contextStack[this.#contextStack.length - 1];
|
|
602
|
+
if (!context) {
|
|
603
|
+
return undefined;
|
|
604
|
+
}
|
|
546
605
|
let single;
|
|
547
|
-
for (const meta of
|
|
606
|
+
for (const meta of context.values()) {
|
|
548
607
|
if (!meta) {
|
|
549
608
|
continue;
|
|
550
609
|
}
|