@mikro-orm/knex 6.0.0-dev.111 → 6.0.0-dev.112
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
CHANGED
|
@@ -29,7 +29,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
29
29
|
nativeUpdateMany<T extends object>(entityName: string, where: FilterQuery<T>[], data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T> & UpsertManyOptions<T>): Promise<QueryResult<T>>;
|
|
30
30
|
nativeDelete<T extends object>(entityName: string, where: FilterQuery<T> | string | any, options?: DeleteOptions<T>): Promise<QueryResult<T>>;
|
|
31
31
|
syncCollection<T extends object, O extends object>(coll: Collection<T, O>, options?: DriverMethodOptions): Promise<void>;
|
|
32
|
-
loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: OrderDefinition<T>, ctx?: Transaction, options?: FindOptions<T, any, any
|
|
32
|
+
loadFromPivotTable<T extends object, O extends object>(prop: EntityProperty, owners: Primary<O>[][], where?: FilterQuery<any>, orderBy?: OrderDefinition<T>, ctx?: Transaction, options?: FindOptions<T, any, any>, pivotJoin?: boolean): Promise<Dictionary<T[]>>;
|
|
33
33
|
private getPivotOrderBy;
|
|
34
34
|
execute<T extends QueryResult | EntityData<AnyEntity> | EntityData<AnyEntity>[] = EntityData<AnyEntity>[]>(queryOrKnex: string | Knex.QueryBuilder | Knex.Raw, params?: any[], method?: 'all' | 'get' | 'run', ctx?: Transaction): Promise<T>;
|
|
35
35
|
/**
|
|
@@ -61,5 +61,5 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
61
61
|
protected buildJoinedPropsOrderBy<T extends object>(entityName: string, qb: QueryBuilder<T>, meta: EntityMetadata<T>, populate: PopulateOptions<T>[], parentPath?: string): QueryOrderMap<T>[];
|
|
62
62
|
protected normalizeFields<T extends object>(fields: Field<T>[], prefix?: string): string[];
|
|
63
63
|
protected processField<T extends object>(meta: EntityMetadata<T>, prop: EntityProperty<T> | undefined, field: string, ret: Field<T>[], populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T>): void;
|
|
64
|
-
protected buildFields<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T>, fields?: Field<T>[]): Field<T>[];
|
|
64
|
+
protected buildFields<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], joinedProps: PopulateOptions<T>[], qb: QueryBuilder<T>, alias: string, fields?: Field<T>[]): Field<T>[];
|
|
65
65
|
}
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -30,7 +30,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
30
30
|
const populate = this.autoJoinOneToOneOwner(meta, options.populate, options.fields);
|
|
31
31
|
const joinedProps = this.joinedProps(meta, populate);
|
|
32
32
|
const qb = this.createQueryBuilder(entityName, options.ctx, options.connectionType, false, options.logging);
|
|
33
|
-
const fields = this.buildFields(meta, populate, joinedProps, qb, options.fields);
|
|
33
|
+
const fields = this.buildFields(meta, populate, joinedProps, qb, qb.alias, options.fields);
|
|
34
34
|
const joinedPropsOrderBy = this.buildJoinedPropsOrderBy(entityName, qb, meta, joinedProps);
|
|
35
35
|
const orderBy = [...core_1.Utils.asArray(options.orderBy), ...joinedPropsOrderBy];
|
|
36
36
|
if (core_1.Utils.isPrimaryKey(where, meta.compositePK)) {
|
|
@@ -575,18 +575,18 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
575
575
|
}
|
|
576
576
|
return this.rethrow(this.updateCollectionDiff(meta, coll.property, pks, deleteDiff, insertDiff, options));
|
|
577
577
|
}
|
|
578
|
-
async loadFromPivotTable(prop, owners, where = {}, orderBy, ctx, options) {
|
|
579
|
-
const pivotProp2 = this.getPivotInverseProperty(prop);
|
|
580
|
-
const prop2 = prop.targetMeta.properties[prop.mappedBy ?? prop.inversedBy];
|
|
581
|
-
const ownerMeta = this.metadata.find(pivotProp2.type);
|
|
578
|
+
async loadFromPivotTable(prop, owners, where = {}, orderBy, ctx, options, pivotJoin) {
|
|
582
579
|
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
580
|
+
const pivotProp1 = pivotMeta.relations[prop.owner ? 1 : 0];
|
|
581
|
+
const pivotProp2 = pivotMeta.relations[prop.owner ? 0 : 1];
|
|
582
|
+
const ownerMeta = this.metadata.find(pivotProp2.type);
|
|
583
583
|
options = { ...options };
|
|
584
|
-
const qb = this.createQueryBuilder(prop.
|
|
585
|
-
.withSchema(this.getSchemaName(
|
|
584
|
+
const qb = this.createQueryBuilder(prop.pivotEntity, ctx, options.connectionType)
|
|
585
|
+
.withSchema(this.getSchemaName(pivotMeta, options))
|
|
586
586
|
.indexHint(options.indexHint)
|
|
587
587
|
.comment(options.comments)
|
|
588
588
|
.hintComment(options.hintComments);
|
|
589
|
-
const pivotAlias = qb.
|
|
589
|
+
const pivotAlias = qb.alias;
|
|
590
590
|
const pivotKey = pivotProp2.joinColumns.map(column => `${pivotAlias}.${column}`).join(core_1.Utils.PK_SEPARATOR);
|
|
591
591
|
const cond = {
|
|
592
592
|
[pivotKey]: { $in: ownerMeta.compositePK ? owners : owners.map(o => o[0]) },
|
|
@@ -598,9 +598,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
598
598
|
else {
|
|
599
599
|
where = { ...where, ...cond };
|
|
600
600
|
}
|
|
601
|
-
orderBy = this.getPivotOrderBy(prop, pivotAlias, orderBy);
|
|
601
|
+
orderBy = this.getPivotOrderBy(prop, pivotProp1, pivotAlias, orderBy);
|
|
602
602
|
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, []);
|
|
603
|
-
const fields =
|
|
603
|
+
const fields = [];
|
|
604
604
|
const k1 = !prop.owner ? 'joinColumns' : 'inverseJoinColumns';
|
|
605
605
|
const k2 = prop.owner ? 'joinColumns' : 'inverseJoinColumns';
|
|
606
606
|
const cols = [
|
|
@@ -608,25 +608,36 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
608
608
|
...prop[k2].map(col => `${pivotAlias}.${col} as fk__${col}`),
|
|
609
609
|
];
|
|
610
610
|
fields.push(...cols);
|
|
611
|
+
if (!pivotJoin) {
|
|
612
|
+
const targetAlias = qb.getNextAlias(prop.targetMeta.tableName);
|
|
613
|
+
const targetSchema = this.getSchemaName(prop.targetMeta, options) ?? this.platform.getDefaultSchemaName();
|
|
614
|
+
qb.innerJoin(pivotProp1.name, targetAlias, {}, targetSchema);
|
|
615
|
+
const targetFields = this.buildFields(prop.targetMeta, (options.populate ?? []), [], qb, targetAlias, options.fields);
|
|
616
|
+
for (const field of targetFields) {
|
|
617
|
+
const f = field.toString();
|
|
618
|
+
fields.unshift(f.includes('.') ? field : `${targetAlias}.${f}`);
|
|
619
|
+
}
|
|
620
|
+
// we need to handle 1:1 owner auto-joins explicitly, as the QB type is the pivot table, not the target
|
|
621
|
+
populate.forEach(hint => {
|
|
622
|
+
const alias = qb.getNextAlias(prop.targetMeta.tableName);
|
|
623
|
+
qb.leftJoin(`${targetAlias}.${hint.field}`, alias);
|
|
624
|
+
// eslint-disable-next-line dot-notation
|
|
625
|
+
Object.values(qb['_joins']).forEach(join => {
|
|
626
|
+
if (join.alias === alias && join.prop.name === hint.field) {
|
|
627
|
+
fields.push(...qb.helper.mapJoinColumns(qb.type, join));
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
}
|
|
611
632
|
qb.select(fields)
|
|
612
|
-
.
|
|
613
|
-
.populate(populate)
|
|
614
|
-
.where(where)
|
|
633
|
+
.where({ [pivotProp1.name]: where })
|
|
615
634
|
.orderBy(orderBy)
|
|
616
635
|
.setLockMode(options.lockMode, options.lockTableAliases);
|
|
617
636
|
if (owners.length === 1 && (options.offset != null || options.limit != null)) {
|
|
618
637
|
qb.limit(options.limit, options.offset);
|
|
619
638
|
}
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
// eslint-disable-next-line dot-notation
|
|
623
|
-
qb['finalize']();
|
|
624
|
-
// eslint-disable-next-line dot-notation
|
|
625
|
-
Object.values(qb['_joins']).forEach(join => {
|
|
626
|
-
join.schema = schema;
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
const items = owners.length ? await this.rethrow(qb.execute('all')) : [];
|
|
639
|
+
const res = owners.length ? await this.rethrow(qb.execute('all', false)) : [];
|
|
640
|
+
const items = res.map((row) => super.mapResult(row, prop.targetMeta));
|
|
630
641
|
const map = {};
|
|
631
642
|
const pkProps = ownerMeta.getPrimaryProps();
|
|
632
643
|
owners.forEach(owner => {
|
|
@@ -643,16 +654,19 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
643
654
|
}));
|
|
644
655
|
map[key].push(item);
|
|
645
656
|
prop.joinColumns.forEach(col => delete item[`fk__${col}`]);
|
|
646
|
-
prop.inverseJoinColumns.forEach(col =>
|
|
657
|
+
prop.inverseJoinColumns.forEach((col, idx) => {
|
|
658
|
+
core_1.Utils.renameKey(item, `fk__${col}`, prop.targetMeta.primaryKeys[idx]);
|
|
659
|
+
});
|
|
647
660
|
});
|
|
648
661
|
return map;
|
|
649
662
|
}
|
|
650
|
-
getPivotOrderBy(prop, pivotAlias, orderBy) {
|
|
663
|
+
getPivotOrderBy(prop, pivotProp, pivotAlias, orderBy) {
|
|
664
|
+
// FIXME this is ignoring the rest of the array items
|
|
651
665
|
if (!core_1.Utils.isEmpty(orderBy)) {
|
|
652
|
-
return orderBy;
|
|
666
|
+
return [{ [pivotProp.name]: core_1.Utils.asArray(orderBy)[0] }];
|
|
653
667
|
}
|
|
654
668
|
if (!core_1.Utils.isEmpty(prop.orderBy)) {
|
|
655
|
-
return core_1.Utils.asArray(prop.orderBy);
|
|
669
|
+
return [{ [pivotProp.name]: core_1.Utils.asArray(prop.orderBy)[0] }];
|
|
656
670
|
}
|
|
657
671
|
if (prop.fixedOrder) {
|
|
658
672
|
return [{ [`${pivotAlias}.${prop.fixedOrderColumn}`]: core_1.QueryOrder.ASC }];
|
|
@@ -728,7 +742,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
728
742
|
.filter(prop => shouldHaveColumn(prop, populate, explicitFields))
|
|
729
743
|
.forEach(prop => fields.push(...this.mapPropToFieldNames(qb, prop, parentTableAlias)));
|
|
730
744
|
joinedProps.forEach(relation => {
|
|
731
|
-
const
|
|
745
|
+
const [propName] = relation.field.split(':', 2);
|
|
746
|
+
const prop = meta.properties[propName];
|
|
732
747
|
const meta2 = this.metadata.find(prop.type);
|
|
733
748
|
const tableAlias = qb.getNextAlias(prop.name);
|
|
734
749
|
const field = parentTableAlias ? `${parentTableAlias}.${prop.name}` : prop.name;
|
|
@@ -858,7 +873,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
858
873
|
const orderBy = [];
|
|
859
874
|
const joinedProps = this.joinedProps(meta, populate);
|
|
860
875
|
joinedProps.forEach(relation => {
|
|
861
|
-
const
|
|
876
|
+
const [propName] = relation.field.split(':', 2);
|
|
877
|
+
const prop = meta.properties[propName];
|
|
862
878
|
const propOrderBy = prop.orderBy;
|
|
863
879
|
const path = `${parentPath ? parentPath : entityName}.${relation.field}`;
|
|
864
880
|
const propAlias = qb.getAliasForJoinPath(path);
|
|
@@ -909,7 +925,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
909
925
|
}
|
|
910
926
|
ret.push(prop.name);
|
|
911
927
|
}
|
|
912
|
-
buildFields(meta, populate, joinedProps, qb, fields) {
|
|
928
|
+
buildFields(meta, populate, joinedProps, qb, alias, fields) {
|
|
913
929
|
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => p.field === prop.name || p.all));
|
|
914
930
|
const hasLazyFormulas = meta.props.some(p => p.lazy && p.formula);
|
|
915
931
|
const requiresSQLConversion = meta.props.some(p => p.customType?.convertToJSValueSQL);
|
|
@@ -951,9 +967,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
951
967
|
meta.props
|
|
952
968
|
.filter(prop => prop.formula && !lazyProps.includes(prop))
|
|
953
969
|
.forEach(prop => {
|
|
954
|
-
const
|
|
970
|
+
const a = this.connection.getKnex().ref(alias).toString();
|
|
955
971
|
const aliased = this.connection.getKnex().ref(prop.fieldNames[0]).toString();
|
|
956
|
-
ret.push((0, core_1.raw)(`${prop.formula(
|
|
972
|
+
ret.push((0, core_1.raw)(`${prop.formula(a)} as ${aliased}`));
|
|
957
973
|
});
|
|
958
974
|
meta.props
|
|
959
975
|
.filter(prop => prop.hasConvertToDatabaseValueSQL || prop.hasConvertToJSValueSQL)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.0.0-dev.
|
|
3
|
+
"version": "6.0.0-dev.112",
|
|
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
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -66,6 +66,6 @@
|
|
|
66
66
|
"@mikro-orm/core": "^5.8.5"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.0.0-dev.
|
|
69
|
+
"@mikro-orm/core": "6.0.0-dev.112"
|
|
70
70
|
}
|
|
71
71
|
}
|
package/query/QueryBuilder.js
CHANGED
|
@@ -274,6 +274,7 @@ class QueryBuilder {
|
|
|
274
274
|
aliasMap: this.getAliasMap(),
|
|
275
275
|
aliased: !this.type || [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(this.type),
|
|
276
276
|
convertCustomTypes: false,
|
|
277
|
+
type: 'orderBy',
|
|
277
278
|
});
|
|
278
279
|
this._orderBy.push(CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processed).process(this));
|
|
279
280
|
});
|
|
@@ -26,7 +26,7 @@ export declare class QueryBuilderHelper {
|
|
|
26
26
|
private processJoinClause;
|
|
27
27
|
private wrapQueryGroup;
|
|
28
28
|
mapJoinColumns(type: QueryType, join: JoinOptions): (string | Knex.Raw)[];
|
|
29
|
-
isOneToOneInverse(field: string): boolean;
|
|
29
|
+
isOneToOneInverse(field: string, meta?: EntityMetadata): boolean;
|
|
30
30
|
getTableName(entityName: string): string;
|
|
31
31
|
/**
|
|
32
32
|
* Checks whether the RE can be rewritten to simple LIKE query
|
|
@@ -157,6 +157,8 @@ class QueryBuilderHelper {
|
|
|
157
157
|
const prop2 = prop.owner ? pivotMeta.relations[1] : pivotMeta.relations[0];
|
|
158
158
|
ret[`${pivotAlias}.${prop2.name}#${alias}`] = this.joinManyToOneReference(prop2, pivotAlias, alias, type, cond, schema);
|
|
159
159
|
ret[`${pivotAlias}.${prop2.name}#${alias}`].path = path;
|
|
160
|
+
const tmp = prop2.referencedTableName.split('.');
|
|
161
|
+
ret[`${pivotAlias}.${prop2.name}#${alias}`].schema ??= tmp.length > 1 ? tmp[0] : undefined;
|
|
160
162
|
return ret;
|
|
161
163
|
}
|
|
162
164
|
processJoins(qb, joins, schema) {
|
|
@@ -177,7 +179,7 @@ class QueryBuilderHelper {
|
|
|
177
179
|
conditions.push(`${left} = ${this.knex.ref(right)}`);
|
|
178
180
|
return;
|
|
179
181
|
}
|
|
180
|
-
const left =
|
|
182
|
+
const left = `${join.ownerAlias}.${primaryKey}`;
|
|
181
183
|
conditions.push(`${this.knex.ref(left)} = ${this.knex.ref(right)}`);
|
|
182
184
|
});
|
|
183
185
|
}
|
|
@@ -282,8 +284,8 @@ class QueryBuilderHelper {
|
|
|
282
284
|
...join.inverseJoinColumns.map(col => this.mapper(`${join.alias}.${col}`, type, undefined, `fk__${col}`)),
|
|
283
285
|
];
|
|
284
286
|
}
|
|
285
|
-
isOneToOneInverse(field) {
|
|
286
|
-
|
|
287
|
+
isOneToOneInverse(field, meta) {
|
|
288
|
+
meta ??= this.metadata.find(this.entityName);
|
|
287
289
|
const prop = meta.properties[field];
|
|
288
290
|
return prop && prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner;
|
|
289
291
|
}
|
|
@@ -474,7 +476,12 @@ class QueryBuilderHelper {
|
|
|
474
476
|
if (core_1.Utils.isRawSql(colPart)) {
|
|
475
477
|
colPart = this.platform.formatQuery(colPart.sql, colPart.params);
|
|
476
478
|
}
|
|
477
|
-
|
|
479
|
+
if (Array.isArray(order)) {
|
|
480
|
+
order.forEach(part => ret.push(this.getQueryOrderFromObject(type, part, populate)));
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
ret.push(`${colPart} ${order.toLowerCase()}`);
|
|
484
|
+
}
|
|
478
485
|
});
|
|
479
486
|
});
|
|
480
487
|
return ret.join(', ');
|