@mikro-orm/sql 7.0.0-dev.114 → 7.0.0-dev.116
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/AbstractSqlDriver.d.ts +13 -13
- package/AbstractSqlDriver.js +43 -52
- package/PivotCollectionPersister.js +3 -3
- package/SqlEntityManager.d.ts +1 -1
- package/dialects/postgresql/BasePostgreSqlPlatform.js +1 -0
- package/package.json +3 -3
- package/plugin/transformer.js +1 -1
- package/query/CriteriaNode.d.ts +3 -3
- package/query/CriteriaNode.js +3 -2
- package/query/CriteriaNodeFactory.d.ts +6 -6
- package/query/CriteriaNodeFactory.js +1 -1
- package/query/ObjectCriteriaNode.js +5 -5
- package/query/QueryBuilder.d.ts +10 -6
- package/query/QueryBuilder.js +53 -57
- package/query/QueryBuilderHelper.d.ts +5 -5
- package/query/QueryBuilderHelper.js +10 -13
- package/query/ScalarCriteriaNode.js +1 -1
- package/schema/SqlSchemaGenerator.js +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/typings.d.ts +6 -5
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -15,23 +15,23 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
15
15
|
getPlatform(): Platform;
|
|
16
16
|
createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
|
|
17
17
|
private createQueryBuilderFromOptions;
|
|
18
|
-
find<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName:
|
|
19
|
-
findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName:
|
|
18
|
+
find<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: EntityName<T>, where: ObjectQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
|
|
19
|
+
findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: EntityName<T>, where: ObjectQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
|
|
20
20
|
protected hasToManyJoins<T extends object>(hint: PopulateOptions<T>, meta: EntityMetadata<T>): boolean;
|
|
21
|
-
findVirtual<T extends object>(entityName:
|
|
22
|
-
countVirtual<T extends object>(entityName:
|
|
23
|
-
protected findFromVirtual<T extends object>(entityName:
|
|
21
|
+
findVirtual<T extends object>(entityName: EntityName<T>, where: ObjectQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
|
|
22
|
+
countVirtual<T extends object>(entityName: EntityName<T>, where: ObjectQuery<T>, options: CountOptions<T, any>): Promise<number>;
|
|
23
|
+
protected findFromVirtual<T extends object>(entityName: EntityName<T>, where: ObjectQuery<T>, options: FindOptions<T, any> | CountOptions<T, any>, type: QueryType): Promise<EntityData<T>[] | number>;
|
|
24
24
|
protected streamFromVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T, any>): AsyncIterableIterator<EntityData<T>>;
|
|
25
25
|
protected wrapVirtualExpressionInSubquery<T extends object>(meta: EntityMetadata<T>, expression: string, where: FilterQuery<T>, options: FindOptions<T, any>, type: QueryType): Promise<T[] | number>;
|
|
26
26
|
protected wrapVirtualExpressionInSubqueryStream<T extends object>(meta: EntityMetadata<T>, expression: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>, type: QueryType.SELECT): AsyncIterableIterator<T>;
|
|
27
27
|
mapResult<T extends object>(result: EntityData<T>, meta: EntityMetadata<T>, populate?: PopulateOptions<T>[], qb?: QueryBuilder<T, any, any, any>, map?: Dictionary): EntityData<T> | null;
|
|
28
28
|
private mapJoinedProps;
|
|
29
|
-
count<T extends object>(entityName:
|
|
30
|
-
nativeInsert<T extends object>(entityName:
|
|
31
|
-
nativeInsertMany<T extends object>(entityName:
|
|
32
|
-
nativeUpdate<T extends object>(entityName:
|
|
33
|
-
nativeUpdateMany<T extends object>(entityName:
|
|
34
|
-
nativeDelete<T extends object>(entityName:
|
|
29
|
+
count<T extends object>(entityName: EntityName<T>, where: any, options?: CountOptions<T>): Promise<number>;
|
|
30
|
+
nativeInsert<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
31
|
+
nativeInsertMany<T extends object>(entityName: EntityName<T>, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>, transform?: (sql: string) => string): Promise<QueryResult<T>>;
|
|
32
|
+
nativeUpdate<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T> & UpsertOptions<T>): Promise<QueryResult<T>>;
|
|
33
|
+
nativeUpdateMany<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
|
|
34
|
+
nativeDelete<T extends object>(entityName: EntityName<T>, where: FilterQuery<T> | string | any, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
|
|
35
35
|
/**
|
|
36
36
|
* Fast comparison for collection snapshots that are represented by PK arrays.
|
|
37
37
|
* Compares scalars via `===` and fallbacks to Utils.equals()` for more complex types like Buffer.
|
|
@@ -69,8 +69,8 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
69
69
|
ctx?: Transaction;
|
|
70
70
|
connectionType?: ConnectionType;
|
|
71
71
|
}): ConnectionType;
|
|
72
|
-
protected extractManyToMany<T>(
|
|
73
|
-
protected processManyToMany<T extends object>(meta: EntityMetadata<T
|
|
72
|
+
protected extractManyToMany<T>(meta: EntityMetadata<T>, data: EntityDictionary<T>): EntityData<T>;
|
|
73
|
+
protected processManyToMany<T extends object>(meta: EntityMetadata<T>, pks: Primary<T>[], collections: EntityData<T>, clear: boolean, options?: DriverMethodOptions): Promise<void>;
|
|
74
74
|
lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
|
|
75
75
|
protected buildPopulateWhere<T extends object>(meta: EntityMetadata<T>, joinedProps: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'populateWhere'>): ObjectQuery<T>;
|
|
76
76
|
protected buildOrderBy<T extends object>(qb: QueryBuilder<T, any, any, any>, meta: EntityMetadata<T>, populate: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'strategy' | 'orderBy' | 'populateOrderBy'>): QueryOrderMap<T>[];
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -25,7 +25,8 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
25
25
|
const connectionType = this.resolveConnectionType({ ctx: options.ctx, connectionType: options.connectionType });
|
|
26
26
|
const populate = this.autoJoinOneToOneOwner(meta, options.populate, options.fields);
|
|
27
27
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
28
|
-
const qb = this.createQueryBuilder(meta.
|
|
28
|
+
const qb = this.createQueryBuilder(meta.class, options.ctx, connectionType, false, options.logging, undefined, options.em)
|
|
29
|
+
.withSchema(this.getSchemaName(meta, options));
|
|
29
30
|
const fields = this.buildFields(meta, populate, joinedProps, qb, qb.alias, options);
|
|
30
31
|
const orderBy = this.buildOrderBy(qb, meta, populate, options);
|
|
31
32
|
const populateWhere = this.buildPopulateWhere(meta, joinedProps, options);
|
|
@@ -44,8 +45,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
44
45
|
.having(options.having)
|
|
45
46
|
.indexHint(options.indexHint)
|
|
46
47
|
.comment(options.comments)
|
|
47
|
-
.hintComment(options.hintComments)
|
|
48
|
-
.withSchema(this.getSchemaName(meta, options));
|
|
48
|
+
.hintComment(options.hintComments);
|
|
49
49
|
if (isCursorPagination) {
|
|
50
50
|
const { orderBy: newOrderBy, where } = this.processCursorOptions(meta, options, orderBy);
|
|
51
51
|
qb.andWhere(where).orderBy(newOrderBy);
|
|
@@ -66,8 +66,8 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
66
66
|
}
|
|
67
67
|
async find(entityName, where, options = {}) {
|
|
68
68
|
options = { populate: [], orderBy: [], ...options };
|
|
69
|
-
const meta = this.metadata.
|
|
70
|
-
if (meta
|
|
69
|
+
const meta = this.metadata.get(entityName);
|
|
70
|
+
if (meta.virtual) {
|
|
71
71
|
return this.findVirtual(entityName, where, options);
|
|
72
72
|
}
|
|
73
73
|
const qb = await this.createQueryBuilderFromOptions(meta, where, options);
|
|
@@ -226,7 +226,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
226
226
|
return;
|
|
227
227
|
}
|
|
228
228
|
const pivotRefJoin = prop.kind === ReferenceKind.MANY_TO_MANY && ref;
|
|
229
|
-
const meta2 =
|
|
229
|
+
const meta2 = prop.targetMeta;
|
|
230
230
|
let path = parentJoinPath ? `${parentJoinPath}.${prop.name}` : `${meta.name}.${prop.name}`;
|
|
231
231
|
if (!parentJoinPath) {
|
|
232
232
|
path = '[populate]' + path;
|
|
@@ -322,10 +322,10 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
322
322
|
if (prop.kind === ReferenceKind.EMBEDDED && (prop.object || meta.embeddable)) {
|
|
323
323
|
const item = parseJsonSafe(relationPojo[prop.name]);
|
|
324
324
|
if (Array.isArray(item)) {
|
|
325
|
-
relationPojo[prop.name] = item.map(row => row == null ? row : this.comparator.mapResult(prop.
|
|
325
|
+
relationPojo[prop.name] = item.map(row => row == null ? row : this.comparator.mapResult(prop.targetMeta, row));
|
|
326
326
|
}
|
|
327
327
|
else {
|
|
328
|
-
relationPojo[prop.name] = item == null ? item : this.comparator.mapResult(prop.
|
|
328
|
+
relationPojo[prop.name] = item == null ? item : this.comparator.mapResult(prop.targetMeta, item);
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
}
|
|
@@ -382,19 +382,18 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
382
382
|
}
|
|
383
383
|
async nativeInsert(entityName, data, options = {}) {
|
|
384
384
|
options.convertCustomTypes ??= true;
|
|
385
|
-
const meta = this.metadata.
|
|
386
|
-
const collections = this.extractManyToMany(
|
|
387
|
-
const pks = meta?.primaryKeys ?? [this.config.getNamingStrategy().referenceColumnName()];
|
|
385
|
+
const meta = this.metadata.get(entityName);
|
|
386
|
+
const collections = this.extractManyToMany(meta, data);
|
|
388
387
|
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes, options.loggerContext).withSchema(this.getSchemaName(meta, options));
|
|
389
388
|
const res = await this.rethrow(qb.insert(data).execute('run', false));
|
|
390
389
|
res.row = res.row || {};
|
|
391
390
|
let pk;
|
|
392
|
-
if (
|
|
393
|
-
pk = Utils.getPrimaryKeyCond(data,
|
|
391
|
+
if (meta.primaryKeys.length > 1) { // owner has composite pk
|
|
392
|
+
pk = Utils.getPrimaryKeyCond(data, meta.primaryKeys);
|
|
394
393
|
}
|
|
395
394
|
else {
|
|
396
395
|
/* v8 ignore next */
|
|
397
|
-
res.insertId = data[
|
|
396
|
+
res.insertId = data[meta.primaryKeys[0]] ?? res.insertId ?? res.row[meta.primaryKeys[0]];
|
|
398
397
|
pk = [res.insertId];
|
|
399
398
|
}
|
|
400
399
|
await this.processManyToMany(meta, pk, collections, false, options);
|
|
@@ -403,23 +402,22 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
403
402
|
async nativeInsertMany(entityName, data, options = {}, transform) {
|
|
404
403
|
options.processCollections ??= true;
|
|
405
404
|
options.convertCustomTypes ??= true;
|
|
406
|
-
const meta = this.metadata.
|
|
407
|
-
const collections = options.processCollections ? data.map(d => this.extractManyToMany(
|
|
408
|
-
const pks = this.getPrimaryKeyFields(
|
|
405
|
+
const meta = this.metadata.get(entityName).root;
|
|
406
|
+
const collections = options.processCollections ? data.map(d => this.extractManyToMany(meta, d)) : [];
|
|
407
|
+
const pks = this.getPrimaryKeyFields(meta);
|
|
409
408
|
const set = new Set();
|
|
410
409
|
data.forEach(row => Utils.keys(row).forEach(k => set.add(k)));
|
|
411
|
-
const props = [...set].map(name => meta
|
|
410
|
+
const props = [...set].map(name => meta.properties[name] ?? { name, fieldNames: [name] });
|
|
412
411
|
let fields = Utils.flatten(props.map(prop => prop.fieldNames));
|
|
413
412
|
const duplicates = Utils.findDuplicates(fields);
|
|
414
413
|
const params = [];
|
|
415
414
|
if (duplicates.length) {
|
|
416
415
|
fields = Utils.unique(fields);
|
|
417
416
|
}
|
|
418
|
-
|
|
419
|
-
const tableName = meta ? this.getTableName(meta, options) : this.platform.quoteIdentifier(entityName);
|
|
417
|
+
const tableName = this.getTableName(meta, options);
|
|
420
418
|
let sql = `insert into ${tableName} `;
|
|
421
419
|
sql += fields.length > 0 ? '(' + fields.map(k => this.platform.quoteIdentifier(k)).join(', ') + ')' : `(${this.platform.quoteIdentifier(pks[0])})`;
|
|
422
|
-
if (
|
|
420
|
+
if (this.platform.usesOutputStatement()) {
|
|
423
421
|
const returningProps = meta.props
|
|
424
422
|
.filter(prop => prop.persist !== false && prop.defaultRaw || prop.autoincrement || prop.generated)
|
|
425
423
|
.filter(prop => !(prop.name in data[0]) || isRaw(data[0][prop.name]));
|
|
@@ -536,13 +534,13 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
536
534
|
}
|
|
537
535
|
async nativeUpdate(entityName, where, data, options = {}) {
|
|
538
536
|
options.convertCustomTypes ??= true;
|
|
539
|
-
const meta = this.metadata.
|
|
540
|
-
const pks = this.getPrimaryKeyFields(
|
|
541
|
-
const collections = this.extractManyToMany(
|
|
537
|
+
const meta = this.metadata.get(entityName);
|
|
538
|
+
const pks = this.getPrimaryKeyFields(meta);
|
|
539
|
+
const collections = this.extractManyToMany(meta, data);
|
|
542
540
|
let res = { affectedRows: 0, insertId: 0, row: {} };
|
|
543
541
|
if (Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
544
542
|
/* v8 ignore next */
|
|
545
|
-
where = { [meta
|
|
543
|
+
where = { [meta.primaryKeys[0] ?? pks[0]]: where };
|
|
546
544
|
}
|
|
547
545
|
if (Utils.hasObjectKeys(data)) {
|
|
548
546
|
const qb = this.createQueryBuilder(entityName, options.ctx, 'write', options.convertCustomTypes, options.loggerContext)
|
|
@@ -566,7 +564,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
566
564
|
qb.update(data).where(where);
|
|
567
565
|
// reload generated columns and version fields
|
|
568
566
|
const returning = [];
|
|
569
|
-
meta
|
|
567
|
+
meta.props
|
|
570
568
|
.filter(prop => (prop.generated && !prop.primary) || prop.version)
|
|
571
569
|
.forEach(prop => returning.push(prop.name));
|
|
572
570
|
qb.returning(returning);
|
|
@@ -598,7 +596,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
598
596
|
}
|
|
599
597
|
return this.rethrow(qb.execute('run', false));
|
|
600
598
|
}
|
|
601
|
-
const collections = options.processCollections ? data.map(d => this.extractManyToMany(
|
|
599
|
+
const collections = options.processCollections ? data.map(d => this.extractManyToMany(meta, d)) : [];
|
|
602
600
|
const keys = new Set();
|
|
603
601
|
const fields = new Set();
|
|
604
602
|
const returning = new Set();
|
|
@@ -611,7 +609,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
611
609
|
}
|
|
612
610
|
}
|
|
613
611
|
// reload generated columns and version fields
|
|
614
|
-
meta
|
|
612
|
+
meta.props
|
|
615
613
|
.filter(prop => prop.generated || prop.version || prop.primary)
|
|
616
614
|
.forEach(prop => returning.add(prop.name));
|
|
617
615
|
const pkCond = Utils.flatten(meta.primaryKeys.map(pk => meta.properties[pk].fieldNames)).map(pk => `${this.platform.quoteIdentifier(pk)} = ?`).join(' and ');
|
|
@@ -704,8 +702,8 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
704
702
|
return res;
|
|
705
703
|
}
|
|
706
704
|
async nativeDelete(entityName, where, options = {}) {
|
|
707
|
-
const meta = this.metadata.
|
|
708
|
-
const pks = this.getPrimaryKeyFields(
|
|
705
|
+
const meta = this.metadata.get(entityName);
|
|
706
|
+
const pks = this.getPrimaryKeyFields(meta);
|
|
709
707
|
if (Utils.isPrimaryKey(where) && pks.length === 1) {
|
|
710
708
|
where = { [pks[0]]: where };
|
|
711
709
|
}
|
|
@@ -758,7 +756,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
758
756
|
}
|
|
759
757
|
if (coll.property.kind === ReferenceKind.ONE_TO_MANY) {
|
|
760
758
|
const cols = coll.property.referencedColumnNames;
|
|
761
|
-
const qb = this.createQueryBuilder(coll.property.
|
|
759
|
+
const qb = this.createQueryBuilder(coll.property.targetMeta.class, options?.ctx, 'write')
|
|
762
760
|
.withSchema(this.getSchemaName(meta, options));
|
|
763
761
|
if (coll.getSnapshot() === undefined) {
|
|
764
762
|
if (coll.property.orphanRemoval) {
|
|
@@ -779,7 +777,6 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
779
777
|
await this.rethrow(query.execute());
|
|
780
778
|
continue;
|
|
781
779
|
}
|
|
782
|
-
/* v8 ignore next */
|
|
783
780
|
const pivotMeta = this.metadata.find(coll.property.pivotEntity);
|
|
784
781
|
let schema = pivotMeta.schema;
|
|
785
782
|
if (schema === '*') {
|
|
@@ -807,10 +804,10 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
807
804
|
if (owners.length === 0) {
|
|
808
805
|
return {};
|
|
809
806
|
}
|
|
810
|
-
const pivotMeta = this.metadata.
|
|
807
|
+
const pivotMeta = this.metadata.get(prop.pivotEntity);
|
|
811
808
|
const pivotProp1 = pivotMeta.relations[prop.owner ? 1 : 0];
|
|
812
809
|
const pivotProp2 = pivotMeta.relations[prop.owner ? 0 : 1];
|
|
813
|
-
const ownerMeta =
|
|
810
|
+
const ownerMeta = pivotProp2.targetMeta;
|
|
814
811
|
const cond = {
|
|
815
812
|
[pivotProp2.name]: { $in: ownerMeta.compositePK ? owners : owners.map(o => o[0]) },
|
|
816
813
|
};
|
|
@@ -825,7 +822,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
825
822
|
const fields = pivotJoin
|
|
826
823
|
? [pivotProp1.name, pivotProp2.name]
|
|
827
824
|
: [pivotProp1.name, pivotProp2.name, ...childFields];
|
|
828
|
-
const res = await this.find(pivotMeta.
|
|
825
|
+
const res = await this.find(pivotMeta.class, where, {
|
|
829
826
|
ctx,
|
|
830
827
|
...options,
|
|
831
828
|
fields,
|
|
@@ -870,8 +867,8 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
870
867
|
}
|
|
871
868
|
async *stream(entityName, where, options) {
|
|
872
869
|
options = { populate: [], orderBy: [], ...options };
|
|
873
|
-
const meta = this.metadata.
|
|
874
|
-
if (meta
|
|
870
|
+
const meta = this.metadata.get(entityName);
|
|
871
|
+
if (meta.virtual) {
|
|
875
872
|
yield* this.streamFromVirtual(entityName, where, options);
|
|
876
873
|
return;
|
|
877
874
|
}
|
|
@@ -1008,7 +1005,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1008
1005
|
if (ref && !hint.filter && (prop.kind === ReferenceKind.MANY_TO_ONE || (prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner))) {
|
|
1009
1006
|
continue;
|
|
1010
1007
|
}
|
|
1011
|
-
const meta2 =
|
|
1008
|
+
const meta2 = prop.targetMeta;
|
|
1012
1009
|
const pivotRefJoin = prop.kind === ReferenceKind.MANY_TO_MANY && ref;
|
|
1013
1010
|
const tableAlias = qb.getNextAlias(prop.name);
|
|
1014
1011
|
const field = `${options.parentTableAlias}.${prop.name}`;
|
|
@@ -1119,26 +1116,20 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1119
1116
|
}
|
|
1120
1117
|
return 'write';
|
|
1121
1118
|
}
|
|
1122
|
-
extractManyToMany(
|
|
1123
|
-
if (!this.metadata.has(entityName)) {
|
|
1124
|
-
return {};
|
|
1125
|
-
}
|
|
1119
|
+
extractManyToMany(meta, data) {
|
|
1126
1120
|
const ret = {};
|
|
1127
|
-
|
|
1121
|
+
for (const prop of meta.relations) {
|
|
1128
1122
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && data[prop.name]) {
|
|
1129
1123
|
ret[prop.name] = data[prop.name].map((item) => Utils.asArray(item));
|
|
1130
1124
|
delete data[prop.name];
|
|
1131
1125
|
}
|
|
1132
|
-
}
|
|
1126
|
+
}
|
|
1133
1127
|
return ret;
|
|
1134
1128
|
}
|
|
1135
1129
|
async processManyToMany(meta, pks, collections, clear, options) {
|
|
1136
|
-
if (!meta) {
|
|
1137
|
-
return;
|
|
1138
|
-
}
|
|
1139
1130
|
for (const prop of meta.relations) {
|
|
1140
1131
|
if (collections[prop.name]) {
|
|
1141
|
-
const pivotMeta = this.metadata.
|
|
1132
|
+
const pivotMeta = this.metadata.get(prop.pivotEntity);
|
|
1142
1133
|
const persister = new PivotCollectionPersister(pivotMeta, this, options?.ctx, options?.schema, options?.loggerContext);
|
|
1143
1134
|
persister.enqueueUpdate(prop, collections[prop.name], clear, pks);
|
|
1144
1135
|
await this.rethrow(persister.execute());
|
|
@@ -1147,7 +1138,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1147
1138
|
}
|
|
1148
1139
|
async lockPessimistic(entity, options) {
|
|
1149
1140
|
const meta = helper(entity).__meta;
|
|
1150
|
-
const qb = this.createQueryBuilder(
|
|
1141
|
+
const qb = this.createQueryBuilder(meta.class, options.ctx, undefined, undefined, options.logging).withSchema(options.schema ?? meta.schema);
|
|
1151
1142
|
const cond = Utils.getPrimaryKeyCond(entity, meta.primaryKeys);
|
|
1152
1143
|
qb.select(raw('1')).where(cond).setLockMode(options.lockMode, options.lockTableAliases);
|
|
1153
1144
|
await this.rethrow(qb.execute());
|
|
@@ -1205,7 +1196,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1205
1196
|
throw new Error(`Trying to order by not existing property ${meta.className}.${field}`);
|
|
1206
1197
|
}
|
|
1207
1198
|
let path = parentPath;
|
|
1208
|
-
const meta2 =
|
|
1199
|
+
const meta2 = prop.targetMeta;
|
|
1209
1200
|
if (prop.kind !== ReferenceKind.SCALAR && (![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) || !prop.owner || Utils.isPlainObject(childOrder))) {
|
|
1210
1201
|
path += `.${field}`;
|
|
1211
1202
|
}
|
|
@@ -1254,7 +1245,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1254
1245
|
}
|
|
1255
1246
|
const join = qb.getJoinForPath(path, { matchPopulateJoins: true });
|
|
1256
1247
|
const propAlias = qb.getAliasForJoinPath(join ?? path, { matchPopulateJoins: true });
|
|
1257
|
-
const meta2 =
|
|
1248
|
+
const meta2 = prop.targetMeta;
|
|
1258
1249
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && prop.fixedOrder && join) {
|
|
1259
1250
|
const alias = ref ? propAlias : join.ownerAlias;
|
|
1260
1251
|
orderBy.push({ [`${alias}.${prop.fixedOrderColumn}`]: QueryOrder.ASC });
|
|
@@ -1338,7 +1329,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
|
|
|
1338
1329
|
const prop = QueryHelper.findProperty(rootPropName, {
|
|
1339
1330
|
metadata: this.metadata,
|
|
1340
1331
|
platform: this.platform,
|
|
1341
|
-
entityName: meta.
|
|
1332
|
+
entityName: meta.class,
|
|
1342
1333
|
where: {},
|
|
1343
1334
|
aliasMap: qb.getAliasMap(),
|
|
1344
1335
|
});
|
|
@@ -120,7 +120,7 @@ export class PivotCollectionPersister {
|
|
|
120
120
|
for (const item of chunk) {
|
|
121
121
|
cond.$or.push(item.getCondition());
|
|
122
122
|
}
|
|
123
|
-
await this.driver.nativeDelete(this.meta.
|
|
123
|
+
await this.driver.nativeDelete(this.meta.class, cond, {
|
|
124
124
|
ctx: this.ctx,
|
|
125
125
|
schema: this.schema,
|
|
126
126
|
loggerContext: this.loggerContext,
|
|
@@ -131,7 +131,7 @@ export class PivotCollectionPersister {
|
|
|
131
131
|
const filtered = this.collectStatements(this.inserts);
|
|
132
132
|
for (let i = 0; i < filtered.length; i += this.batchSize) {
|
|
133
133
|
const chunk = filtered.slice(i, i + this.batchSize);
|
|
134
|
-
await this.driver.nativeInsertMany(this.meta.
|
|
134
|
+
await this.driver.nativeInsertMany(this.meta.class, chunk, {
|
|
135
135
|
ctx: this.ctx,
|
|
136
136
|
schema: this.schema,
|
|
137
137
|
convertCustomTypes: false,
|
|
@@ -144,7 +144,7 @@ export class PivotCollectionPersister {
|
|
|
144
144
|
const filtered = this.collectStatements(this.upserts);
|
|
145
145
|
for (let i = 0; i < filtered.length; i += this.batchSize) {
|
|
146
146
|
const chunk = filtered.slice(i, i + this.batchSize);
|
|
147
|
-
await this.driver.nativeUpdateMany(this.meta.
|
|
147
|
+
await this.driver.nativeUpdateMany(this.meta.class, [], chunk, {
|
|
148
148
|
ctx: this.ctx,
|
|
149
149
|
schema: this.schema,
|
|
150
150
|
convertCustomTypes: false,
|
package/SqlEntityManager.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare class SqlEntityManager<Driver extends AbstractSqlDriver = Abstrac
|
|
|
27
27
|
getKysely<TDB = undefined, TOptions extends GetKyselyOptions = GetKyselyOptions>(options?: TOptions): Kysely<TDB extends undefined ? InferKyselyDB<EntitiesFromManager<this>, TOptions> : TDB>;
|
|
28
28
|
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(query: string | NativeQueryBuilder | RawQueryFragment, params?: any[], method?: 'all' | 'get' | 'run', loggerContext?: LoggingOptions): Promise<T>;
|
|
29
29
|
getRepository<T extends object, U extends EntityRepository<T> = SqlEntityRepository<T>>(entityName: EntityName<T>): GetRepository<T, U>;
|
|
30
|
-
protected applyDiscriminatorCondition<Entity extends object>(entityName:
|
|
30
|
+
protected applyDiscriminatorCondition<Entity extends object>(entityName: EntityName<Entity>, where: FilterQuery<Entity>): FilterQuery<Entity>;
|
|
31
31
|
}
|
|
32
32
|
type EntitiesFromManager<TEntityManager extends EntityManager<any>> = NonNullable<TEntityManager['~entities']> extends any[] ? (Extract<NonNullable<TEntityManager['~entities']>[number], EntitySchemaWithMeta>) : never;
|
|
33
33
|
export {};
|
|
@@ -172,6 +172,7 @@ export class BasePostgreSqlPlatform extends AbstractSqlPlatform {
|
|
|
172
172
|
const quote = (v) => v === '' || v.match(/["{},\\]/) ? JSON.stringify(v) : v;
|
|
173
173
|
return `{${values.map(v => quote('' + v)).join(',')}}`;
|
|
174
174
|
}
|
|
175
|
+
/* v8 ignore next */
|
|
175
176
|
unmarshallArray(value) {
|
|
176
177
|
if (value === '{}') {
|
|
177
178
|
return [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/sql",
|
|
3
|
-
"version": "7.0.0-dev.
|
|
3
|
+
"version": "7.0.0-dev.116",
|
|
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
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"kysely": "0.28.9"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@mikro-orm/core": "^6.6.
|
|
56
|
+
"@mikro-orm/core": "^6.6.3"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.116"
|
|
60
60
|
}
|
|
61
61
|
}
|
package/plugin/transformer.js
CHANGED
|
@@ -706,7 +706,7 @@ export class MikroTransformer extends OperationNodeTransformer {
|
|
|
706
706
|
* Find entity metadata by table name or entity name
|
|
707
707
|
*/
|
|
708
708
|
findEntityMetadata(name) {
|
|
709
|
-
const byEntity = this.metadata.
|
|
709
|
+
const byEntity = this.metadata.getByClassName(name, false);
|
|
710
710
|
if (byEntity) {
|
|
711
711
|
return byEntity;
|
|
712
712
|
}
|
package/query/CriteriaNode.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type EntityKey, type EntityProperty, type MetadataStorage, type RawQueryFragmentSymbol } from '@mikro-orm/core';
|
|
1
|
+
import { type EntityKey, type EntityProperty, type MetadataStorage, type RawQueryFragmentSymbol, type EntityName } from '@mikro-orm/core';
|
|
2
2
|
import type { ICriteriaNode, ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
|
|
3
3
|
/**
|
|
4
4
|
* Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
|
|
@@ -7,14 +7,14 @@ import type { ICriteriaNode, ICriteriaNodeProcessOptions, IQueryBuilder } from '
|
|
|
7
7
|
*/
|
|
8
8
|
export declare class CriteriaNode<T extends object> implements ICriteriaNode<T> {
|
|
9
9
|
protected readonly metadata: MetadataStorage;
|
|
10
|
-
readonly entityName:
|
|
10
|
+
readonly entityName: EntityName<T>;
|
|
11
11
|
readonly parent?: ICriteriaNode<T> | undefined;
|
|
12
12
|
readonly key?: (EntityKey<T> | RawQueryFragmentSymbol) | undefined;
|
|
13
13
|
readonly strict: boolean;
|
|
14
14
|
payload: any;
|
|
15
15
|
prop?: EntityProperty<T>;
|
|
16
16
|
index?: number;
|
|
17
|
-
constructor(metadata: MetadataStorage, entityName:
|
|
17
|
+
constructor(metadata: MetadataStorage, entityName: EntityName<T>, parent?: ICriteriaNode<T> | undefined, key?: (EntityKey<T> | RawQueryFragmentSymbol) | undefined, validate?: boolean, strict?: boolean);
|
|
18
18
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
19
19
|
unwrap(): any;
|
|
20
20
|
shouldInline(payload: any): boolean;
|
package/query/CriteriaNode.js
CHANGED
|
@@ -30,7 +30,7 @@ export class CriteriaNode {
|
|
|
30
30
|
const isProp = this.prop || meta.props.find(prop => (prop.fieldNames || []).includes(k));
|
|
31
31
|
// do not validate if the key is prefixed or type casted (e.g. `k::text`)
|
|
32
32
|
if (validate && !isProp && !k.includes('.') && !k.includes('::') && !Utils.isOperator(k)) {
|
|
33
|
-
throw new Error(`Trying to query by not existing property ${entityName}.${k}`);
|
|
33
|
+
throw new Error(`Trying to query by not existing property ${Utils.className(entityName)}.${k}`);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -79,7 +79,7 @@ export class CriteriaNode {
|
|
|
79
79
|
getPath(addIndex = false) {
|
|
80
80
|
// use index on parent only if we are processing to-many relation
|
|
81
81
|
const addParentIndex = this.prop && [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(this.prop.kind);
|
|
82
|
-
const parentPath = this.parent?.getPath(addParentIndex) ?? this.entityName;
|
|
82
|
+
const parentPath = this.parent?.getPath(addParentIndex) ?? Utils.className(this.entityName);
|
|
83
83
|
const index = addIndex && this.index != null ? `[${this.index}]` : '';
|
|
84
84
|
// ignore group operators to allow easier mapping (e.g. for orderBy)
|
|
85
85
|
const key = this.key && !RawQueryFragment.isKnownFragmentSymbol(this.key) && !['$and', '$or', '$not'].includes(this.key) ? '.' + this.key : '';
|
|
@@ -109,6 +109,7 @@ export class CriteriaNode {
|
|
|
109
109
|
return this.strict;
|
|
110
110
|
}
|
|
111
111
|
/** @ignore */
|
|
112
|
+
/* v8 ignore next */
|
|
112
113
|
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
113
114
|
const o = {};
|
|
114
115
|
['entityName', 'key', 'index', 'payload']
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { type Dictionary, type EntityKey, type EntityMetadata, type MetadataStorage, type RawQueryFragmentSymbol } from '@mikro-orm/core';
|
|
1
|
+
import { type Dictionary, type EntityKey, type EntityMetadata, type EntityName, type MetadataStorage, type RawQueryFragmentSymbol } from '@mikro-orm/core';
|
|
2
2
|
import type { ICriteriaNode } from '../typings.js';
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
6
|
export declare class CriteriaNodeFactory {
|
|
7
|
-
static createNode<T extends object>(metadata: MetadataStorage, entityName:
|
|
8
|
-
static createScalarNode<T extends object>(metadata: MetadataStorage, entityName:
|
|
9
|
-
static createArrayNode<T extends object>(metadata: MetadataStorage, entityName:
|
|
10
|
-
static createObjectNode<T extends object>(metadata: MetadataStorage, entityName:
|
|
11
|
-
static createObjectItemNode<T extends object>(metadata: MetadataStorage, entityName:
|
|
7
|
+
static createNode<T extends object>(metadata: MetadataStorage, entityName: EntityName<T>, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T> | RawQueryFragmentSymbol): ICriteriaNode<T>;
|
|
8
|
+
static createScalarNode<T extends object>(metadata: MetadataStorage, entityName: EntityName<T>, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T> | RawQueryFragmentSymbol): ICriteriaNode<T>;
|
|
9
|
+
static createArrayNode<T extends object>(metadata: MetadataStorage, entityName: EntityName<T>, payload: any[], parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
10
|
+
static createObjectNode<T extends object>(metadata: MetadataStorage, entityName: EntityName<T>, payload: Dictionary, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
|
|
11
|
+
static createObjectItemNode<T extends object>(metadata: MetadataStorage, entityName: EntityName<T>, node: ICriteriaNode<T>, payload: Dictionary, key: EntityKey<T> | RawQueryFragmentSymbol, meta?: EntityMetadata<T>): ICriteriaNode<T>;
|
|
12
12
|
}
|
|
@@ -46,7 +46,7 @@ export class CriteriaNodeFactory {
|
|
|
46
46
|
static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
|
|
47
47
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
|
|
48
48
|
const prop = rawField ? null : meta?.properties[key];
|
|
49
|
-
const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.
|
|
49
|
+
const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.targetMeta.class : entityName;
|
|
50
50
|
const isNotEmbedded = rawField || prop?.kind !== ReferenceKind.EMBEDDED;
|
|
51
51
|
const val = payload[key];
|
|
52
52
|
if (isNotEmbedded && prop?.customType instanceof JsonType) {
|
|
@@ -35,10 +35,10 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
35
35
|
throw new Error('Mixing collection operators with other filters is not allowed.');
|
|
36
36
|
}
|
|
37
37
|
const payload = this.payload[key].unwrap();
|
|
38
|
-
const qb2 = qb.clone(true);
|
|
38
|
+
const qb2 = qb.clone(true, ['_schema']);
|
|
39
39
|
const sub = qb2
|
|
40
|
-
.from(parentMeta.
|
|
41
|
-
.innerJoin(this.key, qb2.getNextAlias(this.prop.
|
|
40
|
+
.from(parentMeta.class)
|
|
41
|
+
.innerJoin(this.key, qb2.getNextAlias(this.prop.targetMeta.class))
|
|
42
42
|
.select(parentMeta.primaryKeys);
|
|
43
43
|
if (key === '$every') {
|
|
44
44
|
sub.where({ $not: { [this.key]: payload } });
|
|
@@ -100,7 +100,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
100
100
|
this.inlineCondition(field.replaceAll(ALIAS_REPLACEMENT, alias), o, payload);
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
this.inlineCondition(`${alias}.${field}`, o, payload);
|
|
103
|
+
this.inlineCondition(`${alias ?? qb.alias}.${field}`, o, payload);
|
|
104
104
|
}
|
|
105
105
|
return o;
|
|
106
106
|
}, {});
|
|
@@ -217,7 +217,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
|
|
|
217
217
|
return !primaryKeys && !nestedAlias && !operatorKeys && !embeddable;
|
|
218
218
|
}
|
|
219
219
|
autoJoin(qb, alias, options) {
|
|
220
|
-
const nestedAlias = qb.getNextAlias(this.prop?.
|
|
220
|
+
const nestedAlias = qb.getNextAlias(this.prop?.pivotEntity ?? this.entityName);
|
|
221
221
|
const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
|
|
222
222
|
const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || rawField;
|
|
223
223
|
const operator = Utils.isPlainObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
|
package/query/QueryBuilder.d.ts
CHANGED
|
@@ -220,8 +220,8 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
220
220
|
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
221
221
|
* Allows setting a main string alias of the selection data.
|
|
222
222
|
*/
|
|
223
|
-
from<Entity extends
|
|
224
|
-
from<Entity extends
|
|
223
|
+
from<Entity extends object>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
224
|
+
from<Entity extends object>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
|
|
225
225
|
getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
|
|
226
226
|
/**
|
|
227
227
|
* Returns the query with parameters as wildcards.
|
|
@@ -254,11 +254,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
254
254
|
/**
|
|
255
255
|
* @internal
|
|
256
256
|
*/
|
|
257
|
-
getNextAlias(entityName?: string): string;
|
|
257
|
+
getNextAlias(entityName?: string | EntityName): string;
|
|
258
258
|
/**
|
|
259
259
|
* @internal
|
|
260
260
|
*/
|
|
261
|
-
getAliasMap(): Dictionary<
|
|
261
|
+
getAliasMap(): Dictionary<EntityName>;
|
|
262
262
|
/**
|
|
263
263
|
* Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
|
|
264
264
|
* Use `method` to specify what kind of result you want to get (array/single/meta).
|
|
@@ -307,10 +307,14 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
|
|
|
307
307
|
getResultAndCount(): Promise<[Entity[], number]>;
|
|
308
308
|
/**
|
|
309
309
|
* Returns native query builder instance with sub-query aliased with given alias.
|
|
310
|
-
* You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
|
|
311
310
|
*/
|
|
312
311
|
as(alias: string): NativeQueryBuilder;
|
|
313
|
-
|
|
312
|
+
/**
|
|
313
|
+
* Returns native query builder instance with sub-query aliased with given alias.
|
|
314
|
+
* You can provide the target entity name as the first parameter and use the second parameter to point to an existing property to infer its field name.
|
|
315
|
+
*/
|
|
316
|
+
as<T>(targetEntity: EntityName<T>, alias: EntityKey<T>): NativeQueryBuilder;
|
|
317
|
+
clone(reset?: boolean | string[], preserve?: string[]): QueryBuilder<Entity>;
|
|
314
318
|
/**
|
|
315
319
|
* Sets logger context for this query builder.
|
|
316
320
|
*/
|