@mikro-orm/sql 7.2.2-dev.24 → 7.2.2-dev.26

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.
@@ -1809,7 +1809,11 @@ export class AbstractSqlDriver extends DatabaseDriver {
1809
1809
  if (!this.platform.shouldHaveColumn(prop, populate, exclude)) {
1810
1810
  return false;
1811
1811
  }
1812
- if (!fields || fields.includes('*') || prop.primary || meta.root.discriminatorColumn === prop.name) {
1812
+ if (!fields ||
1813
+ fields.includes('*') ||
1814
+ prop.primary ||
1815
+ meta.root.discriminatorColumn === prop.name ||
1816
+ meta.root.targetKeys?.includes(prop.name)) {
1813
1817
  return true;
1814
1818
  }
1815
1819
  return fields.some(f => f === prop.name || f.toString().startsWith(prop.name + '.'));
@@ -1865,11 +1869,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
1865
1869
  const tptMeta = this.metadata.get(targetMeta.class);
1866
1870
  this.addTPTPolymorphicJoinsForRelation(qb, tptMeta, tableAlias, fields);
1867
1871
  }
1868
- if (ref) {
1869
- // For filter :ref hints, schedule filter check for each target (no field selection)
1870
- qb.scheduleFilterCheck(targetPath);
1871
- }
1872
- else {
1872
+ // target filters apply per target, both for filter :ref hints and populated relations
1873
+ qb.scheduleFilterCheck(targetPath);
1874
+ if (!ref) {
1873
1875
  // Select fields from each target table
1874
1876
  fields.push(...this.getFieldsForJoinedLoad(qb, targetMeta, {
1875
1877
  ...options,
@@ -2469,6 +2471,8 @@ export class AbstractSqlDriver extends DatabaseDriver {
2469
2471
  }
2470
2472
  if (!options.fields.includes('*') && !options.fields.includes(`${qb.alias}.*`)) {
2471
2473
  ret.unshift(...meta.primaryKeys.filter(pk => !options.fields.includes(pk)));
2474
+ // `targetKey` values identify the entity like its PK, references resolve it by them
2475
+ ret.push(...(meta.root.targetKeys ?? []).filter(key => meta.properties[key] && !options.fields.includes(key)));
2472
2476
  }
2473
2477
  if (meta.root.inheritanceType === 'sti' &&
2474
2478
  !options.fields.includes(`${qb.alias}.${meta.root.discriminatorColumn}`)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.2.2-dev.24",
3
+ "version": "7.2.2-dev.26",
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
  "keywords": [
6
6
  "data-mapper",
@@ -53,7 +53,7 @@
53
53
  "@mikro-orm/core": "^7.2.1"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.2.2-dev.24"
56
+ "@mikro-orm/core": "7.2.2-dev.26"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"
@@ -186,8 +186,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
186
186
  const operator = Utils.isObject(payload) &&
187
187
  Utils.getObjectQueryKeys(payload).every(k => {
188
188
  if (k === '$not' && Utils.isPlainObject(payload[k])) {
189
- // $not wrapping non-operator conditions (entity props) should be inlined
190
- return Utils.getObjectQueryKeys(payload[k]).every(ik => Utils.isOperator(ik, false));
189
+ // $not wrapping non-operator conditions (entity props) or an empty one should be inlined
190
+ const inner = Utils.getObjectQueryKeys(payload[k]);
191
+ return inner.length > 0 && inner.every(ik => Utils.isOperator(ik, false));
191
192
  }
192
193
  return Utils.isOperator(k, false);
193
194
  });
@@ -218,9 +219,12 @@ export class ObjectCriteriaNode extends CriteriaNode {
218
219
  }
219
220
  else if (k === '$not' &&
220
221
  Utils.isPlainObject(payload[k]) &&
221
- Utils.getObjectQueryKeys(payload[k]).some(ik => !Utils.isOperator(ik, false))) {
222
- // $not wraps entity conditions (from auto-join), inline at current level
223
- this.inlineCondition(k, o, payload[k]);
222
+ (!Utils.hasObjectKeys(payload[k]) ||
223
+ Utils.getObjectQueryKeys(payload[k]).some(ik => !Utils.isOperator(ik, false)))) {
224
+ // $not wraps entity conditions (from auto-join) or an empty one, inline at current level with the same key mapping
225
+ const inner = {};
226
+ this.inlineChildPayload(inner, payload[k], field, alias, childAlias);
227
+ this.inlineCondition(k, o, inner);
224
228
  }
225
229
  else if (Utils.isOperator(k, false)) {
226
230
  const tmp = payload[k];
@@ -291,6 +295,13 @@ export class ObjectCriteriaNode extends CriteriaNode {
291
295
  });
292
296
  const primaryKeys = knownKey &&
293
297
  keys.every(key => {
298
+ if (key === '$not') {
299
+ // e.g. `{ author: { $not: { id: 1 } } }` compares the FK column, relation PKs still need the join
300
+ const childPayload = this.payload[key].payload;
301
+ return (Utils.isPlainObject(childPayload) &&
302
+ Utils.getObjectQueryKeys(childPayload).every(k => meta.primaryKeys.includes(k) &&
303
+ meta.properties[k].kind === ReferenceKind.SCALAR));
304
+ }
294
305
  if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
295
306
  return false;
296
307
  }
@@ -1032,9 +1032,11 @@ export class QueryBuilder {
1032
1032
  * @internal
1033
1033
  */
1034
1034
  addPolymorphicJoin(prop, targetMeta, ownerAlias, alias, type, path, schema) {
1035
- // Override referencedColumnNames to use the specific target's PK columns
1035
+ // Override referencedColumnNames to use the specific target's PK (or `targetKey`) columns
1036
1036
  // (polymorphic targets may have different PK column names, e.g. org_id vs user_id)
1037
- const referencedColumnNames = targetMeta.getPrimaryProps().flatMap(pk => pk.fieldNames);
1037
+ const referencedColumnNames = prop.targetKey
1038
+ ? targetMeta.properties[prop.targetKey].fieldNames
1039
+ : targetMeta.getPrimaryProps().flatMap(pk => pk.fieldNames);
1038
1040
  const targetProp = { ...prop, targetMeta, referencedColumnNames };
1039
1041
  const aliasedName = `${ownerAlias}.${prop.name}[${targetMeta.className}]#${alias}`;
1040
1042
  this.#state.joins[aliasedName] = this.helper.joinManyToOneReference(targetProp, ownerAlias, alias, type, {}, schema);