@mikro-orm/knex 6.4.17-dev.65 → 6.4.17-dev.66
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.js
CHANGED
|
@@ -758,80 +758,39 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
758
758
|
}
|
|
759
759
|
}
|
|
760
760
|
async loadFromPivotTable(prop, owners, where = {}, orderBy, ctx, options, pivotJoin) {
|
|
761
|
+
if (owners.length === 0) {
|
|
762
|
+
return {};
|
|
763
|
+
}
|
|
761
764
|
const pivotMeta = this.metadata.find(prop.pivotEntity);
|
|
762
765
|
const pivotProp1 = pivotMeta.relations[prop.owner ? 1 : 0];
|
|
763
766
|
const pivotProp2 = pivotMeta.relations[prop.owner ? 0 : 1];
|
|
764
767
|
const ownerMeta = this.metadata.find(pivotProp2.type);
|
|
765
|
-
options = { ...options };
|
|
766
|
-
const qb = this.createQueryBuilder(prop.pivotEntity, ctx, options.connectionType, undefined, options?.logging)
|
|
767
|
-
.withSchema(this.getSchemaName(pivotMeta, options))
|
|
768
|
-
.indexHint(options.indexHint)
|
|
769
|
-
.comment(options.comments)
|
|
770
|
-
.hintComment(options.hintComments);
|
|
771
|
-
const pivotAlias = qb.alias;
|
|
772
|
-
const pivotKey = pivotProp2.joinColumns.map(column => `${pivotAlias}.${column}`).join(core_1.Utils.PK_SEPARATOR);
|
|
773
768
|
const cond = {
|
|
774
|
-
[
|
|
769
|
+
[pivotProp2.name]: { $in: ownerMeta.compositePK ? owners : owners.map(o => o[0]) },
|
|
775
770
|
};
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const
|
|
788
|
-
|
|
789
|
-
...
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
const additionalFields = [];
|
|
799
|
-
for (const field of targetFields) {
|
|
800
|
-
const f = field.toString();
|
|
801
|
-
additionalFields.push(f.includes('.') ? field : `${targetAlias}.${f}`);
|
|
802
|
-
if (core_1.RawQueryFragment.isKnownFragment(field)) {
|
|
803
|
-
qb.rawFragments.add(f);
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
fields.unshift(...additionalFields);
|
|
807
|
-
// we need to handle 1:1 owner auto-joins explicitly, as the QB type is the pivot table, not the target
|
|
808
|
-
populate.forEach(hint => {
|
|
809
|
-
const alias = qb.getNextAlias(prop.targetMeta.tableName);
|
|
810
|
-
qb.leftJoin(`${targetAlias}.${hint.field}`, alias);
|
|
811
|
-
// eslint-disable-next-line dot-notation
|
|
812
|
-
for (const join of Object.values(qb['_joins'])) {
|
|
813
|
-
const [propName] = hint.field.split(':', 2);
|
|
814
|
-
if (join.alias === alias && join.prop.name === propName) {
|
|
815
|
-
fields.push(...qb.helper.mapJoinColumns(qb.type, join));
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
});
|
|
819
|
-
}
|
|
820
|
-
qb.select(fields)
|
|
821
|
-
.where({ [pivotProp1.name]: where })
|
|
822
|
-
.orderBy(orderBy)
|
|
823
|
-
.setLockMode(options.lockMode, options.lockTableAliases);
|
|
824
|
-
if (owners.length === 1 && (options.offset != null || options.limit != null)) {
|
|
825
|
-
qb.limit(options.limit, options.offset);
|
|
826
|
-
}
|
|
827
|
-
const res = owners.length ? await this.rethrow(qb.execute('all', { mergeResults: false, mapResults: false })) : [];
|
|
828
|
-
const tmp = {};
|
|
829
|
-
const items = res.map((row) => {
|
|
830
|
-
const root = super.mapResult(row, prop.targetMeta);
|
|
831
|
-
this.mapJoinedProps(root, prop.targetMeta, populate, qb, root, tmp, pivotMeta.className + '.' + pivotProp1.name);
|
|
832
|
-
return root;
|
|
771
|
+
if (!core_1.Utils.isEmpty(where)) {
|
|
772
|
+
cond[pivotProp1.name] = { ...where };
|
|
773
|
+
}
|
|
774
|
+
where = cond;
|
|
775
|
+
const populateField = pivotJoin ? `${pivotProp1.name}:ref` : pivotProp1.name;
|
|
776
|
+
const populate = this.autoJoinOneToOneOwner(prop.targetMeta, options?.populate ?? [], options?.fields);
|
|
777
|
+
const childFields = !core_1.Utils.isEmpty(options?.fields) ? options.fields.map(f => `${pivotProp1.name}.${f}`) : [];
|
|
778
|
+
const childExclude = !core_1.Utils.isEmpty(options?.exclude) ? options.exclude.map(f => `${pivotProp1.name}.${f}`) : [];
|
|
779
|
+
const fields = pivotJoin
|
|
780
|
+
? [pivotProp1.name, pivotProp2.name]
|
|
781
|
+
: [pivotProp1.name, pivotProp2.name, ...childFields];
|
|
782
|
+
const res = await this.find(pivotMeta.className, where, {
|
|
783
|
+
ctx,
|
|
784
|
+
...options,
|
|
785
|
+
fields,
|
|
786
|
+
exclude: childExclude,
|
|
787
|
+
orderBy: this.getPivotOrderBy(prop, pivotProp1, orderBy, options?.orderBy),
|
|
788
|
+
populate: [{ field: populateField, strategy: core_1.LoadStrategy.JOINED, joinType: query_1.JoinType.innerJoin, children: populate }],
|
|
789
|
+
populateWhere: undefined,
|
|
790
|
+
// @ts-ignore
|
|
791
|
+
_populateWhere: 'infer',
|
|
792
|
+
populateFilter: !core_1.Utils.isEmpty(options?.populateFilter) ? { [pivotProp2.name]: options?.populateFilter } : undefined,
|
|
833
793
|
});
|
|
834
|
-
qb.clearRawFragmentsCache();
|
|
835
794
|
const map = {};
|
|
836
795
|
const pkProps = ownerMeta.getPrimaryProps();
|
|
837
796
|
for (const owner of owners) {
|
|
@@ -841,29 +800,26 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
841
800
|
}));
|
|
842
801
|
map[key] = [];
|
|
843
802
|
}
|
|
844
|
-
for (const item of
|
|
845
|
-
const key = core_1.Utils.getPrimaryKeyHash(
|
|
846
|
-
|
|
847
|
-
return pkProp.customType ? pkProp.customType.convertToJSValue(item[`fk__${col}`], this.platform) : item[`fk__${col}`];
|
|
848
|
-
}));
|
|
849
|
-
map[key].push(item);
|
|
850
|
-
prop.joinColumns.forEach(col => delete item[`fk__${col}`]);
|
|
851
|
-
prop.inverseJoinColumns.forEach((col, idx) => {
|
|
852
|
-
core_1.Utils.renameKey(item, `fk__${col}`, prop.targetMeta.primaryKeys[idx]);
|
|
853
|
-
});
|
|
803
|
+
for (const item of res) {
|
|
804
|
+
const key = core_1.Utils.getPrimaryKeyHash(core_1.Utils.asArray(item[pivotProp2.name]));
|
|
805
|
+
map[key].push(item[pivotProp1.name]);
|
|
854
806
|
}
|
|
855
807
|
return map;
|
|
856
808
|
}
|
|
857
|
-
getPivotOrderBy(prop, pivotProp,
|
|
858
|
-
// FIXME this is ignoring the rest of the array items
|
|
809
|
+
getPivotOrderBy(prop, pivotProp, orderBy, parentOrderBy) {
|
|
859
810
|
if (!core_1.Utils.isEmpty(orderBy)) {
|
|
860
|
-
return
|
|
811
|
+
return core_1.Utils.asArray(orderBy).map(o => ({ [pivotProp.name]: o }));
|
|
812
|
+
}
|
|
813
|
+
if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && core_1.Utils.asArray(parentOrderBy).some(o => o[prop.name])) {
|
|
814
|
+
return core_1.Utils.asArray(parentOrderBy)
|
|
815
|
+
.filter(o => o[prop.name])
|
|
816
|
+
.map(o => ({ [pivotProp.name]: o[prop.name] }));
|
|
861
817
|
}
|
|
862
818
|
if (!core_1.Utils.isEmpty(prop.orderBy)) {
|
|
863
|
-
return
|
|
819
|
+
return core_1.Utils.asArray(prop.orderBy).map(o => ({ [pivotProp.name]: o }));
|
|
864
820
|
}
|
|
865
821
|
if (prop.fixedOrder) {
|
|
866
|
-
return [{ [
|
|
822
|
+
return [{ [prop.fixedOrderColumn]: core_1.QueryOrder.ASC }];
|
|
867
823
|
}
|
|
868
824
|
return [];
|
|
869
825
|
}
|
|
@@ -881,7 +837,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
881
837
|
const toPopulate = meta.relations
|
|
882
838
|
.filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !prop.lazy && !relationsToPopulate.includes(prop.name))
|
|
883
839
|
.filter(prop => fields.length === 0 || fields.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
|
|
884
|
-
.map(prop => ({ field: `${prop.name}:ref`, strategy: prop.strategy }));
|
|
840
|
+
.map(prop => ({ field: `${prop.name}:ref`, strategy: prop.strategy ?? core_1.LoadStrategy.JOINED }));
|
|
885
841
|
return [...populate, ...toPopulate];
|
|
886
842
|
}
|
|
887
843
|
/**
|
|
@@ -889,16 +845,17 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
889
845
|
*/
|
|
890
846
|
joinedProps(meta, populate, options) {
|
|
891
847
|
return populate.filter(hint => {
|
|
892
|
-
const [propName
|
|
848
|
+
const [propName] = hint.field.split(':', 2);
|
|
893
849
|
const prop = meta.properties[propName] || {};
|
|
894
|
-
|
|
850
|
+
const strategy = (0, core_1.getLoadingStrategy)(hint.strategy || options?.strategy || prop.strategy || this.config.get('loadStrategy'), prop.kind);
|
|
851
|
+
if (hint.filter && (0, core_1.getLoadingStrategy)(hint.strategy, prop.kind) === core_1.LoadStrategy.JOINED) {
|
|
895
852
|
return true;
|
|
896
853
|
}
|
|
897
854
|
// skip redundant joins for 1:1 owner population hints when using `mapToPk`
|
|
898
855
|
if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && prop.mapToPk && prop.owner) {
|
|
899
856
|
return false;
|
|
900
857
|
}
|
|
901
|
-
if (
|
|
858
|
+
if (strategy !== core_1.LoadStrategy.JOINED) {
|
|
902
859
|
// force joined strategy for explicit 1:1 owner populate hint as it would require a join anyway
|
|
903
860
|
return prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner;
|
|
904
861
|
}
|
|
@@ -967,7 +924,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
967
924
|
const [propName, ref] = hint.field.split(':', 2);
|
|
968
925
|
const prop = meta.properties[propName];
|
|
969
926
|
// ignore ref joins of known FKs unless it's a filter hint
|
|
970
|
-
if (ref && !hint.filter && (prop.kind === core_1.ReferenceKind.MANY_TO_ONE || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE &&
|
|
927
|
+
if (ref && !hint.filter && (prop.kind === core_1.ReferenceKind.MANY_TO_ONE || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && prop.owner))) {
|
|
971
928
|
continue;
|
|
972
929
|
}
|
|
973
930
|
if (count && (!options?.populateFilter || !options.populateFilter[prop.name])) {
|
|
@@ -983,9 +940,11 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
983
940
|
}
|
|
984
941
|
const joinType = pivotRefJoin
|
|
985
942
|
? query_1.JoinType.pivotJoin
|
|
986
|
-
: hint.
|
|
987
|
-
?
|
|
988
|
-
:
|
|
943
|
+
: hint.joinType
|
|
944
|
+
? hint.joinType
|
|
945
|
+
: hint.filter && !prop.nullable
|
|
946
|
+
? query_1.JoinType.innerJoin
|
|
947
|
+
: query_1.JoinType.leftJoin;
|
|
989
948
|
qb.join(field, tableAlias, {}, joinType, path);
|
|
990
949
|
if (pivotRefJoin) {
|
|
991
950
|
fields.push(...prop.joinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)), ...prop.inverseJoinColumns.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
|
|
@@ -1003,7 +962,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1003
962
|
if (!ref && !prop.mapToPk) {
|
|
1004
963
|
fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path, count));
|
|
1005
964
|
}
|
|
1006
|
-
else if (hint.filter || prop.mapToPk) {
|
|
965
|
+
else if (hint.filter || prop.mapToPk || (ref && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind))) {
|
|
1007
966
|
fields.push(...prop.referencedColumnNames.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
|
|
1008
967
|
}
|
|
1009
968
|
}
|
|
@@ -1148,7 +1107,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1148
1107
|
let path = parentPath;
|
|
1149
1108
|
const meta2 = this.metadata.find(prop.type);
|
|
1150
1109
|
const childOrder = orderHint[prop.name];
|
|
1151
|
-
if (![core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind) || !prop.owner || core_1.Utils.isPlainObject(childOrder)) {
|
|
1110
|
+
if (prop.kind !== core_1.ReferenceKind.SCALAR && (![core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(prop.kind) || !prop.owner || core_1.Utils.isPlainObject(childOrder))) {
|
|
1152
1111
|
path += `.${propName}`;
|
|
1153
1112
|
}
|
|
1154
1113
|
if (prop.kind === core_1.ReferenceKind.MANY_TO_MANY && typeof childOrder !== 'object') {
|
|
@@ -1156,7 +1115,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
|
|
|
1156
1115
|
}
|
|
1157
1116
|
const join = qb.getJoinForPath(path, { matchPopulateJoins: true });
|
|
1158
1117
|
const propAlias = qb.getAliasForJoinPath(join ?? path, { matchPopulateJoins: true }) ?? parentAlias;
|
|
1159
|
-
if (!join
|
|
1118
|
+
if (!join) {
|
|
1160
1119
|
continue;
|
|
1161
1120
|
}
|
|
1162
1121
|
if (join && ![core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.EMBEDDED].includes(prop.kind) && typeof childOrder === 'object') {
|
package/index.mjs
CHANGED
|
@@ -221,6 +221,8 @@ export const createSqlFunction = mod.createSqlFunction;
|
|
|
221
221
|
export const defineConfig = mod.defineConfig;
|
|
222
222
|
export const defineEntity = mod.defineEntity;
|
|
223
223
|
export const equals = mod.equals;
|
|
224
|
+
export const expandDotPaths = mod.expandDotPaths;
|
|
225
|
+
export const getLoadingStrategy = mod.getLoadingStrategy;
|
|
224
226
|
export const getOnConflictFields = mod.getOnConflictFields;
|
|
225
227
|
export const getOnConflictReturningFields = mod.getOnConflictReturningFields;
|
|
226
228
|
export const helper = mod.helper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/knex",
|
|
3
|
-
"version": "6.4.17-dev.
|
|
3
|
+
"version": "6.4.17-dev.66",
|
|
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,7 +66,7 @@
|
|
|
66
66
|
"@mikro-orm/core": "^6.4.16"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@mikro-orm/core": "6.4.17-dev.
|
|
69
|
+
"@mikro-orm/core": "6.4.17-dev.66",
|
|
70
70
|
"better-sqlite3": "*",
|
|
71
71
|
"libsql": "*",
|
|
72
72
|
"mariadb": "*"
|
package/query/CriteriaNode.js
CHANGED
|
@@ -69,7 +69,7 @@ class CriteriaNode {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
renameFieldToPK(qb) {
|
|
72
|
-
let joinAlias = qb.getAliasForJoinPath(this.getPath());
|
|
72
|
+
let joinAlias = qb.getAliasForJoinPath(this.getPath(), { matchPopulateJoins: true });
|
|
73
73
|
if (!joinAlias && this.parent && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(this.prop.kind) && this.prop.owner) {
|
|
74
74
|
joinAlias = qb.getAliasForJoinPath(this.parent.getPath());
|
|
75
75
|
return core_1.Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${joinAlias ?? qb.alias}.${col}`));
|
|
@@ -9,7 +9,8 @@ const enums_1 = require("./enums");
|
|
|
9
9
|
*/
|
|
10
10
|
class ObjectCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
11
11
|
process(qb, options) {
|
|
12
|
-
const
|
|
12
|
+
const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
|
|
13
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
|
|
13
14
|
const ownerAlias = options?.alias || qb.alias;
|
|
14
15
|
const keys = Object.keys(this.payload);
|
|
15
16
|
let alias = options?.alias;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { CriteriaNode } from './CriteriaNode';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings';
|
|
3
3
|
/**
|
|
4
4
|
* @internal
|
|
5
5
|
*/
|
|
6
6
|
export declare class ScalarCriteriaNode<T extends object> extends CriteriaNode<T> {
|
|
7
7
|
process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
|
|
8
|
-
willAutoJoin
|
|
9
|
-
shouldJoin
|
|
8
|
+
willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
|
|
9
|
+
private shouldJoin;
|
|
10
10
|
}
|
|
@@ -9,7 +9,9 @@ const enums_1 = require("./enums");
|
|
|
9
9
|
*/
|
|
10
10
|
class ScalarCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
11
11
|
process(qb, options) {
|
|
12
|
-
|
|
12
|
+
const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
|
|
13
|
+
const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
|
|
14
|
+
if (this.shouldJoin(qb, nestedAlias)) {
|
|
13
15
|
const path = this.getPath();
|
|
14
16
|
const parentPath = this.parent.getPath(); // the parent is always there, otherwise `shouldJoin` would return `false`
|
|
15
17
|
const nestedAlias = qb.getAliasForJoinPath(path) || qb.getNextAlias(this.prop?.pivotTable ?? this.entityName);
|
|
@@ -30,10 +32,10 @@ class ScalarCriteriaNode extends CriteriaNode_1.CriteriaNode {
|
|
|
30
32
|
return this.payload;
|
|
31
33
|
}
|
|
32
34
|
willAutoJoin(qb, alias, options) {
|
|
33
|
-
return this.shouldJoin();
|
|
35
|
+
return this.shouldJoin(qb, alias);
|
|
34
36
|
}
|
|
35
|
-
shouldJoin() {
|
|
36
|
-
if (!this.parent || !this.prop) {
|
|
37
|
+
shouldJoin(qb, nestedAlias) {
|
|
38
|
+
if (!this.parent || !this.prop || (nestedAlias && [enums_1.QueryType.SELECT, enums_1.QueryType.COUNT].includes(qb.type ?? enums_1.QueryType.SELECT))) {
|
|
37
39
|
return false;
|
|
38
40
|
}
|
|
39
41
|
switch (this.prop.kind) {
|