@mikro-orm/knex 6.0.0-dev.200 → 6.0.0-dev.201
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 +1 -0
- package/AbstractSqlDriver.js +58 -33
- package/package.json +2 -2
package/AbstractSqlDriver.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
|
|
|
15
15
|
createEntityManager<D extends IDatabaseDriver = IDatabaseDriver>(useContext?: boolean): D[typeof EntityManagerType];
|
|
16
16
|
find<T extends object, P extends string = never, F extends string = '*'>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F>): Promise<EntityData<T>[]>;
|
|
17
17
|
findOne<T extends object, P extends string = never, F extends string = '*'>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F>): Promise<EntityData<T> | null>;
|
|
18
|
+
protected hasToManyJoins<T extends object>(hint: PopulateOptions<T>, meta: EntityMetadata<T>): boolean;
|
|
18
19
|
findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any>): Promise<EntityData<T>[]>;
|
|
19
20
|
countVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: CountOptions<T, any>): Promise<number>;
|
|
20
21
|
protected findFromVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any> | CountOptions<T, any>, type: QueryType): Promise<EntityData<T>[] | number>;
|
package/AbstractSqlDriver.js
CHANGED
|
@@ -74,11 +74,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
74
74
|
const meta = this.metadata.find(entityName);
|
|
75
75
|
const populate = this.autoJoinOneToOneOwner(meta, opts.populate, opts.fields);
|
|
76
76
|
const joinedProps = this.joinedProps(meta, populate, options);
|
|
77
|
-
const hasToManyJoins = joinedProps.some(hint =>
|
|
78
|
-
const [propName] = hint.field.split(':', 2);
|
|
79
|
-
const prop = meta.properties[propName];
|
|
80
|
-
return prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind);
|
|
81
|
-
});
|
|
77
|
+
const hasToManyJoins = joinedProps.some(hint => this.hasToManyJoins(hint, meta));
|
|
82
78
|
if (joinedProps.length === 0 || !hasToManyJoins) {
|
|
83
79
|
opts.limit = 1;
|
|
84
80
|
}
|
|
@@ -89,6 +85,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
89
85
|
const res = await this.find(entityName, where, opts);
|
|
90
86
|
return res[0] || null;
|
|
91
87
|
}
|
|
88
|
+
hasToManyJoins(hint, meta) {
|
|
89
|
+
const [propName] = hint.field.split(':', 2);
|
|
90
|
+
const prop = meta.properties[propName];
|
|
91
|
+
if (prop && [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(prop.kind)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
if (hint.children && prop.targetMeta) {
|
|
95
|
+
return hint.children.some(hint => this.hasToManyJoins(hint, prop.targetMeta));
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
92
99
|
async findVirtual(entityName, where, options) {
|
|
93
100
|
return this.findFromVirtual(entityName, where, options, query_1.QueryType.SELECT);
|
|
94
101
|
}
|
|
@@ -161,16 +168,16 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
161
168
|
}
|
|
162
169
|
mapJoinedProps(result, meta, populate, qb, root, map, parentJoinPath) {
|
|
163
170
|
const joinedProps = this.joinedProps(meta, populate);
|
|
164
|
-
joinedProps.forEach(
|
|
165
|
-
const [propName, ref] =
|
|
166
|
-
const
|
|
171
|
+
joinedProps.forEach(hint => {
|
|
172
|
+
const [propName, ref] = hint.field.split(':', 2);
|
|
173
|
+
const prop = meta.properties[propName];
|
|
167
174
|
/* istanbul ignore next */
|
|
168
|
-
if (!
|
|
175
|
+
if (!prop) {
|
|
169
176
|
return;
|
|
170
177
|
}
|
|
171
|
-
const pivotRefJoin =
|
|
172
|
-
const meta2 = this.metadata.find(
|
|
173
|
-
let path = parentJoinPath ? `${parentJoinPath}.${
|
|
178
|
+
const pivotRefJoin = prop.kind === core_1.ReferenceKind.MANY_TO_MANY && ref;
|
|
179
|
+
const meta2 = this.metadata.find(prop.type);
|
|
180
|
+
let path = parentJoinPath ? `${parentJoinPath}.${prop.name}` : `${meta.name}.${prop.name}`;
|
|
174
181
|
if (!parentJoinPath) {
|
|
175
182
|
path = '[populate]' + path;
|
|
176
183
|
}
|
|
@@ -181,18 +188,18 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
181
188
|
// pivot ref joins via joined strategy need to be handled separately here, as they dont join the target entity
|
|
182
189
|
if (pivotRefJoin) {
|
|
183
190
|
let item;
|
|
184
|
-
if (
|
|
185
|
-
item =
|
|
191
|
+
if (prop.inverseJoinColumns.length > 1) { // composite keys
|
|
192
|
+
item = prop.inverseJoinColumns.map(name => root[`${relationAlias}__${name}`]);
|
|
186
193
|
}
|
|
187
194
|
else {
|
|
188
|
-
const alias = `${relationAlias}__${
|
|
195
|
+
const alias = `${relationAlias}__${prop.inverseJoinColumns[0]}`;
|
|
189
196
|
item = root[alias];
|
|
190
197
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
result[
|
|
198
|
+
prop.joinColumns.forEach(name => delete root[`${relationAlias}__${name}`]);
|
|
199
|
+
prop.inverseJoinColumns.forEach(name => delete root[`${relationAlias}__${name}`]);
|
|
200
|
+
result[prop.name] ??= [];
|
|
194
201
|
if (item) {
|
|
195
|
-
result[
|
|
202
|
+
result[prop.name].push(item);
|
|
196
203
|
}
|
|
197
204
|
return;
|
|
198
205
|
}
|
|
@@ -202,18 +209,20 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
202
209
|
return root[`${relationAlias}__${name}`] != null;
|
|
203
210
|
}));
|
|
204
211
|
if (!hasPK) {
|
|
205
|
-
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(
|
|
206
|
-
result[
|
|
212
|
+
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(prop.kind)) {
|
|
213
|
+
result[prop.name] ??= [];
|
|
207
214
|
}
|
|
208
|
-
if ([core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(
|
|
209
|
-
result[
|
|
215
|
+
if ([core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind)) {
|
|
216
|
+
result[prop.name] ??= null;
|
|
210
217
|
}
|
|
211
218
|
return;
|
|
212
219
|
}
|
|
213
220
|
const relationPojo = {};
|
|
214
221
|
meta2.props
|
|
215
222
|
.filter(prop => prop.persist === false && prop.fieldNames)
|
|
223
|
+
.filter(prop => !prop.lazy || populate.some(p => p.field === prop.name || p.all))
|
|
216
224
|
.forEach(prop => {
|
|
225
|
+
/* istanbul ignore if */
|
|
217
226
|
if (prop.fieldNames.length > 1) { // composite keys
|
|
218
227
|
relationPojo[prop.name] = prop.fieldNames.map(name => root[`${relationAlias}__${name}`]);
|
|
219
228
|
}
|
|
@@ -223,11 +232,12 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
223
232
|
}
|
|
224
233
|
});
|
|
225
234
|
meta2.props
|
|
226
|
-
.filter(prop => this.platform.shouldHaveColumn(prop,
|
|
235
|
+
.filter(prop => this.platform.shouldHaveColumn(prop, hint.children || []))
|
|
227
236
|
.forEach(prop => {
|
|
228
237
|
if (prop.fieldNames.length > 1) { // composite keys
|
|
229
|
-
|
|
238
|
+
const fk = prop.fieldNames.map(name => root[`${relationAlias}__${name}`]);
|
|
230
239
|
prop.fieldNames.map(name => delete root[`${relationAlias}__${name}`]);
|
|
240
|
+
relationPojo[prop.name] = core_1.Utils.mapFlatCompositePrimaryKey(fk, prop);
|
|
231
241
|
}
|
|
232
242
|
else if (prop.runtimeType === 'Date') {
|
|
233
243
|
const alias = `${relationAlias}__${prop.fieldNames[0]}`;
|
|
@@ -240,14 +250,14 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
240
250
|
delete root[alias];
|
|
241
251
|
}
|
|
242
252
|
});
|
|
243
|
-
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(
|
|
244
|
-
result[
|
|
245
|
-
result[
|
|
253
|
+
if ([core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(prop.kind)) {
|
|
254
|
+
result[prop.name] ??= [];
|
|
255
|
+
result[prop.name].push(relationPojo);
|
|
246
256
|
}
|
|
247
257
|
else {
|
|
248
|
-
result[
|
|
258
|
+
result[prop.name] = relationPojo;
|
|
249
259
|
}
|
|
250
|
-
const populateChildren =
|
|
260
|
+
const populateChildren = hint.children || [];
|
|
251
261
|
this.mapJoinedProps(relationPojo, meta2, populateChildren, qb, root, map, path);
|
|
252
262
|
});
|
|
253
263
|
}
|
|
@@ -744,7 +754,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
744
754
|
return populate.filter(hint => {
|
|
745
755
|
const [propName, ref] = hint.field.split(':', 2);
|
|
746
756
|
const prop = meta.properties[propName] || {};
|
|
747
|
-
|
|
757
|
+
if (ref) {
|
|
758
|
+
// keep only pivot ref joins here, as that only triggers actual join
|
|
759
|
+
return prop.kind === core_1.ReferenceKind.MANY_TO_MANY;
|
|
760
|
+
}
|
|
761
|
+
return (prop.strategy || options?.strategy || hint.strategy || this.config.get('loadStrategy')) === core_1.LoadStrategy.JOINED && ![core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.EMBEDDED].includes(prop.kind);
|
|
748
762
|
});
|
|
749
763
|
}
|
|
750
764
|
/**
|
|
@@ -842,7 +856,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
842
856
|
mapPropToFieldNames(qb, prop, tableAlias) {
|
|
843
857
|
const knex = this.connection.getKnex();
|
|
844
858
|
const aliased = knex.ref(tableAlias ? `${tableAlias}__${prop.fieldNames[0]}` : prop.fieldNames[0]).toString();
|
|
845
|
-
if (prop.
|
|
859
|
+
if (tableAlias && prop.customTypes?.some(type => type.convertToJSValueSQL)) {
|
|
860
|
+
return prop.fieldNames.map((col, idx) => {
|
|
861
|
+
if (!prop.customTypes[idx].convertToJSValueSQL) {
|
|
862
|
+
return col;
|
|
863
|
+
}
|
|
864
|
+
const prefixed = knex.ref(col).withSchema(tableAlias).toString();
|
|
865
|
+
const aliased = knex.ref(`${tableAlias}__${col}`).toString();
|
|
866
|
+
return (0, core_1.raw)(`${prop.customTypes[idx].convertToJSValueSQL(prefixed, this.platform)} as ${aliased}`);
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
if (tableAlias && prop.customType?.convertToJSValueSQL) {
|
|
846
870
|
const prefixed = knex.ref(prop.fieldNames[0]).withSchema(tableAlias).toString();
|
|
847
871
|
return [(0, core_1.raw)(`${prop.customType.convertToJSValueSQL(prefixed, this.platform)} as ${aliased}`)];
|
|
848
872
|
}
|
|
@@ -973,7 +997,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
973
997
|
const propAlias = qb.getAliasForJoinPath(join ?? path, { matchPopulateJoins: true });
|
|
974
998
|
const meta2 = this.metadata.find(prop.type);
|
|
975
999
|
if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && prop.fixedOrder && join) {
|
|
976
|
-
|
|
1000
|
+
const alias = ref ? propAlias : join.ownerAlias;
|
|
1001
|
+
orderBy.push({ [`${alias}.${prop.fixedOrderColumn}`]: core_1.QueryOrder.ASC });
|
|
977
1002
|
}
|
|
978
1003
|
if (propOrderBy) {
|
|
979
1004
|
core_1.Utils.keys(propOrderBy).forEach(field => {
|
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.201",
|
|
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.9.2"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.0.0-dev.
|
|
69
|
+
"@mikro-orm/core": "6.0.0-dev.201"
|
|
70
70
|
}
|
|
71
71
|
}
|