@mikro-orm/knex 6.0.0-dev.306 → 6.0.0-dev.307

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.
@@ -35,7 +35,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
35
35
  /**
36
36
  * 1:1 owner side needs to be marked for population so QB auto-joins the owner id
37
37
  */
38
- protected autoJoinOneToOneOwner<T extends object, P extends string = never>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, any>[]): PopulateOptions<T>[];
38
+ protected autoJoinOneToOneOwner<T extends object>(meta: EntityMetadata<T>, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, any>[]): PopulateOptions<T>[];
39
39
  /**
40
40
  * @internal
41
41
  */
@@ -766,7 +766,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
766
766
  if (!this.config.get('autoJoinOneToOneOwner')) {
767
767
  return populate;
768
768
  }
769
- const relationsToPopulate = populate.map(({ field }) => field);
769
+ const relationsToPopulate = populate.map(({ field }) => field.split(':')[0]);
770
770
  const toPopulate = meta.relations
771
771
  .filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name))
772
772
  .filter(prop => fields.length === 0 || fields.some(f => prop.name === f || prop.name.startsWith(`${String(f)}.`)))
@@ -778,14 +778,14 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
778
778
  */
779
779
  joinedProps(meta, populate, options) {
780
780
  return populate.filter(hint => {
781
- const [propName, ref] = hint.field.split(':', 2);
781
+ const [propName] = hint.field.split(':', 2);
782
782
  const prop = meta.properties[propName] || {};
783
+ if (hint.filter && hint.strategy === core_1.LoadStrategy.JOINED) {
784
+ return true;
785
+ }
783
786
  if ((options?.strategy || hint.strategy || prop.strategy || this.config.get('loadStrategy')) !== core_1.LoadStrategy.JOINED) {
784
787
  return false;
785
788
  }
786
- if (ref) {
787
- return [core_1.ReferenceKind.MANY_TO_MANY, core_1.ReferenceKind.ONE_TO_MANY].includes(prop.kind);
788
- }
789
789
  return ![core_1.ReferenceKind.SCALAR, core_1.ReferenceKind.EMBEDDED].includes(prop.kind);
790
790
  });
791
791
  }
@@ -853,15 +853,23 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
853
853
  joinedProps.forEach(hint => {
854
854
  const [propName, ref] = hint.field.split(':', 2);
855
855
  const prop = meta.properties[propName];
856
+ // ignore ref joins of known FKs unless it's a filter hint
857
+ if (ref && !hint.filter && (prop.kind === core_1.ReferenceKind.MANY_TO_ONE || (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner))) {
858
+ return;
859
+ }
856
860
  const meta2 = this.metadata.find(prop.type);
857
861
  const pivotRefJoin = prop.kind === core_1.ReferenceKind.MANY_TO_MANY && ref;
858
862
  const tableAlias = qb.getNextAlias(prop.name);
859
863
  const field = parentTableAlias ? `${parentTableAlias}.${prop.name}` : prop.name;
860
864
  let path = parentJoinPath ? `${parentJoinPath}.${prop.name}` : `${meta.name}.${prop.name}`;
861
- if (!parentJoinPath && populateWhereAll && !path.startsWith('[populate]')) {
865
+ if (!parentJoinPath && populateWhereAll && !hint.filter && !path.startsWith('[populate]')) {
862
866
  path = '[populate]' + path;
863
867
  }
864
- const joinType = pivotRefJoin ? query_1.JoinType.pivotJoin : query_1.JoinType.leftJoin;
868
+ const joinType = pivotRefJoin
869
+ ? query_1.JoinType.pivotJoin
870
+ : hint.filter && !prop.nullable
871
+ ? query_1.JoinType.innerJoin
872
+ : query_1.JoinType.leftJoin;
865
873
  qb.join(field, tableAlias, {}, joinType, path);
866
874
  if (pivotRefJoin) {
867
875
  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}`)));
@@ -879,6 +887,9 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
879
887
  if (!ref) {
880
888
  fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path));
881
889
  }
890
+ else if (hint.filter) {
891
+ fields.push(field);
892
+ }
882
893
  });
883
894
  return fields;
884
895
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "6.0.0-dev.306",
3
+ "version": "6.0.0-dev.307",
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.0.0"
67
67
  },
68
68
  "peerDependencies": {
69
- "@mikro-orm/core": "6.0.0-dev.306"
69
+ "@mikro-orm/core": "6.0.0-dev.307"
70
70
  }
71
71
  }
@@ -2,7 +2,7 @@
2
2
  import { inspect } from 'util';
3
3
  import type { Knex } from 'knex';
4
4
  import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityName, type EntityProperty, type FlushMode, type GroupOperator, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryResult, type RequiredEntityData } from '@mikro-orm/core';
5
- import { QueryType, JoinType } from './enums';
5
+ import { JoinType, QueryType } from './enums';
6
6
  import type { AbstractSqlDriver } from '../AbstractSqlDriver';
7
7
  import { type Alias, QueryBuilderHelper } from './QueryBuilderHelper';
8
8
  import type { SqlEntityManager } from '../SqlEntityManager';
@@ -264,19 +264,20 @@ class QueryBuilder {
264
264
  const op = operator || params;
265
265
  const topLevel = !op || !core_1.Utils.hasObjectKeys(this._cond);
266
266
  const criteriaNode = CriteriaNodeFactory_1.CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond);
267
+ const ignoreBranching = this.__populateWhere === 'infer';
267
268
  if ([enums_1.QueryType.UPDATE, enums_1.QueryType.DELETE].includes(this.type) && criteriaNode.willAutoJoin(this)) {
268
269
  // use sub-query to support joining
269
270
  this.setFlag(this.type === enums_1.QueryType.UPDATE ? core_1.QueryFlag.UPDATE_SUB_QUERY : core_1.QueryFlag.DELETE_SUB_QUERY);
270
271
  this.select(this.mainAlias.metadata.primaryKeys, true);
271
272
  }
272
273
  if (topLevel) {
273
- this._cond = criteriaNode.process(this);
274
+ this._cond = criteriaNode.process(this, { ignoreBranching });
274
275
  }
275
276
  else if (Array.isArray(this._cond[op])) {
276
- this._cond[op].push(criteriaNode.process(this));
277
+ this._cond[op].push(criteriaNode.process(this, { ignoreBranching }));
277
278
  }
278
279
  else {
279
- const cond1 = [this._cond, criteriaNode.process(this)];
280
+ const cond1 = [this._cond, criteriaNode.process(this, { ignoreBranching })];
280
281
  this._cond = { [op]: cond1 };
281
282
  }
282
283
  if (this._onConflict) {
@@ -1060,18 +1061,24 @@ class QueryBuilder {
1060
1061
  join.cond_ = join.cond;
1061
1062
  join.cond = {};
1062
1063
  });
1063
- const replaceOnConditions = (cond) => {
1064
+ const replaceOnConditions = (cond, op) => {
1064
1065
  Object.keys(cond).forEach(k => {
1065
1066
  if (core_1.Utils.isOperator(k)) {
1066
1067
  if (Array.isArray(cond[k])) {
1067
- return cond[k].forEach((c) => replaceOnConditions(c));
1068
+ return cond[k].forEach((c) => replaceOnConditions(c, k));
1068
1069
  }
1069
- return replaceOnConditions(cond[k]);
1070
+ /* istanbul ignore next */
1071
+ return replaceOnConditions(cond[k], k);
1070
1072
  }
1071
1073
  const [alias] = this.helper.splitField(k);
1072
1074
  const join = joins.find(j => j.alias === alias);
1073
1075
  if (join) {
1074
- join.cond = { ...join.cond, [k]: cond[k] };
1076
+ if (join.cond[k]) {
1077
+ join.cond = { [op ?? '$and']: [join.cond, { [k]: cond[k] }] };
1078
+ }
1079
+ else {
1080
+ join.cond = { ...join.cond, [k]: cond[k] };
1081
+ }
1075
1082
  }
1076
1083
  });
1077
1084
  };
@@ -288,9 +288,10 @@ class QueryBuilderHelper {
288
288
  return `(${parts.join(` ${core_1.GroupOperator[operator]} `)})`;
289
289
  }
290
290
  mapJoinColumns(type, join) {
291
- if (join.prop && join.prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !join.prop.owner) {
291
+ if (join.prop && [core_1.ReferenceKind.MANY_TO_ONE, core_1.ReferenceKind.ONE_TO_ONE].includes(join.prop.kind)) {
292
292
  return join.prop.fieldNames.map((fieldName, idx) => {
293
- return this.mapper(`${join.alias}.${join.inverseJoinColumns[idx]}`, type, undefined, fieldName);
293
+ const columns = join.prop.owner ? join.joinColumns : join.inverseJoinColumns;
294
+ return this.mapper(`${join.alias}.${columns[idx]}`, type, undefined, fieldName);
294
295
  });
295
296
  }
296
297
  return [