@mikro-orm/sql 7.3.0-dev.3 → 7.3.0-dev.4

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.3.0-dev.3",
3
+ "version": "7.3.0-dev.4",
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.3.0-dev.3"
56
+ "@mikro-orm/core": "7.3.0-dev.4"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"
@@ -192,8 +192,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
192
192
  const operator = Utils.isObject(payload) &&
193
193
  Utils.getObjectQueryKeys(payload).every(k => {
194
194
  if (k === '$not' && Utils.isPlainObject(payload[k])) {
195
- // $not wrapping non-operator conditions (entity props) should be inlined
196
- return Utils.getObjectQueryKeys(payload[k]).every(ik => Utils.isOperator(ik, false));
195
+ // $not wrapping non-operator conditions (entity props) or an empty one should be inlined
196
+ const inner = Utils.getObjectQueryKeys(payload[k]);
197
+ return inner.length > 0 && inner.every(ik => Utils.isOperator(ik, false));
197
198
  }
198
199
  return Utils.isOperator(k, false);
199
200
  });
@@ -224,9 +225,12 @@ export class ObjectCriteriaNode extends CriteriaNode {
224
225
  }
225
226
  else if (k === '$not' &&
226
227
  Utils.isPlainObject(payload[k]) &&
227
- Utils.getObjectQueryKeys(payload[k]).some(ik => !Utils.isOperator(ik, false))) {
228
- // $not wraps entity conditions (from auto-join), inline at current level
229
- this.inlineCondition(k, o, payload[k]);
228
+ (!Utils.hasObjectKeys(payload[k]) ||
229
+ Utils.getObjectQueryKeys(payload[k]).some(ik => !Utils.isOperator(ik, false)))) {
230
+ // $not wraps entity conditions (from auto-join) or an empty one, inline at current level with the same key mapping
231
+ const inner = {};
232
+ this.inlineChildPayload(inner, payload[k], field, alias, childAlias);
233
+ this.inlineCondition(k, o, inner);
230
234
  }
231
235
  else if (Utils.isOperator(k, false)) {
232
236
  const tmp = payload[k];
@@ -301,6 +305,13 @@ export class ObjectCriteriaNode extends CriteriaNode {
301
305
  });
302
306
  const primaryKeys = knownKey &&
303
307
  keys.every(key => {
308
+ if (key === '$not') {
309
+ // e.g. `{ author: { $not: { id: 1 } } }` compares the FK column, relation PKs still need the join
310
+ const childPayload = this.payload[key].payload;
311
+ return (Utils.isPlainObject(childPayload) &&
312
+ Utils.getObjectQueryKeys(childPayload).every(k => meta.primaryKeys.includes(k) &&
313
+ meta.properties[k].kind === ReferenceKind.SCALAR));
314
+ }
304
315
  if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
305
316
  return false;
306
317
  }
@@ -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);