@mikro-orm/sql 7.1.16-dev.1 → 7.1.16-dev.10

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.
@@ -1333,7 +1333,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
1333
1333
  ],
1334
1334
  populateWhere: undefined,
1335
1335
  _populateWhere: 'infer',
1336
- populateFilter: this.wrapPopulateFilter(options, pivotProp2.name),
1336
+ populateFilter: this.wrapPopulateFilter(options, pivotProp1.name),
1337
1337
  };
1338
1338
  if (pivotFindOptions._partitionLimit) {
1339
1339
  pivotFindOptions._partitionLimit.partitionBy = pivotProp2.name;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.1.16-dev.1",
3
+ "version": "7.1.16-dev.10",
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.1.15"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.1.16-dev.1"
56
+ "@mikro-orm/core": "7.1.16-dev.10"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"
@@ -13,6 +13,7 @@ export declare class ObjectCriteriaNode<T extends object> extends CriteriaNode<T
13
13
  private inlineArrayChildPayload;
14
14
  private inlineChildPayload;
15
15
  private inlineCondition;
16
+ private isCollectionOperator;
16
17
  private shouldAutoJoin;
17
18
  private autoJoin;
18
19
  private isPrefixed;
@@ -1,7 +1,7 @@
1
1
  import { ALIAS_REPLACEMENT, GroupOperator, QueryFlag, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
2
2
  import { CriteriaNode } from './CriteriaNode.js';
3
3
  import { JoinType, QueryType } from './enums.js';
4
- const COLLECTION_OPERATORS = ['$some', '$none', '$every', '$size'];
4
+ const COLLECTION_OPERATORS = ['$some', '$none', '$every', '$size', '$all'];
5
5
  /**
6
6
  * @internal
7
7
  */
@@ -17,7 +17,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
17
17
  alias = nestedAlias;
18
18
  }
19
19
  if (this.shouldAutoJoin(qb, nestedAlias)) {
20
- if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
20
+ if (keys.some(k => this.isCollectionOperator(k))) {
21
21
  if (![ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(this.prop.kind)) {
22
22
  // ignore collection operators when used on a non-relational property - this can happen when they get into
23
23
  // populateWhere via `infer` on m:n properties with select-in strategy
@@ -34,11 +34,24 @@ export class ObjectCriteriaNode extends CriteriaNode {
34
34
  const primaryKeys = parentMeta.primaryKeys.map(pk => {
35
35
  return [QueryType.SELECT, QueryType.COUNT].includes(qb.type) ? `${knownKey ? alias : ownerAlias}.${pk}` : pk;
36
36
  });
37
+ const conditions = [];
38
+ let matchNothing = false;
37
39
  for (const key of keys) {
38
40
  if (typeof key !== 'string' || !COLLECTION_OPERATORS.includes(key)) {
39
41
  throw new Error('Mixing collection operators with other filters is not allowed.');
40
42
  }
41
43
  const payload = this.payload[key].unwrap();
44
+ // `$all` requires every listed item to be present, which is an intersection of `$some` conditions
45
+ if (key === '$all') {
46
+ // an empty `$all` matches nothing, same as in mongo
47
+ matchNothing ||= payload.length === 0;
48
+ conditions.push(...payload.map(item => ['$some', item]));
49
+ }
50
+ else {
51
+ conditions.push([key, payload]);
52
+ }
53
+ }
54
+ for (const [key, payload] of conditions) {
42
55
  // entities with a fixed schema must resolve the `from` table's own schema in the subquery,
43
56
  // otherwise a nested operator inherits the root entity's schema (GH #7894); for wildcard or
44
57
  // schema-less entities the schema is resolved dynamically and needs to be carried over
@@ -70,6 +83,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
70
83
  [Utils.getPrimaryKeyHash(primaryKeys)]: { [op]: sub.getNativeQuery().toRaw() },
71
84
  });
72
85
  }
86
+ if (matchNothing) {
87
+ $and.push({ [Utils.getPrimaryKeyHash(primaryKeys)]: { $in: [] } });
88
+ }
73
89
  if ($and.length === 1) {
74
90
  return $and[0];
75
91
  }
@@ -154,7 +170,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
154
170
  alias = nestedAlias;
155
171
  }
156
172
  if (this.shouldAutoJoin(qb, nestedAlias)) {
157
- return !keys.some(k => COLLECTION_OPERATORS.includes(k));
173
+ return !keys.some(k => this.isCollectionOperator(k));
158
174
  }
159
175
  return keys.some(field => {
160
176
  const childNode = this.payload[field];
@@ -238,6 +254,14 @@ export class ObjectCriteriaNode extends CriteriaNode {
238
254
  delete o[key];
239
255
  o.$and = $and;
240
256
  }
257
+ isCollectionOperator(key) {
258
+ if (typeof key !== 'string' || !COLLECTION_OPERATORS.includes(key)) {
259
+ return false;
260
+ }
261
+ // `$all` is primarily a mongo array operator, in SQL it is supported only on collections
262
+ return (key !== '$all' ||
263
+ (!!this.prop && [ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(this.prop.kind)));
264
+ }
241
265
  shouldAutoJoin(qb, nestedAlias) {
242
266
  if (!this.prop || !this.parent) {
243
267
  return false;
@@ -246,7 +270,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
246
270
  if (keys.every(k => typeof k === 'string' && k.includes('.') && k.startsWith(`${qb.alias}.`))) {
247
271
  return false;
248
272
  }
249
- if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
273
+ if (keys.some(k => this.isCollectionOperator(k))) {
250
274
  return true;
251
275
  }
252
276
  const meta = this.metadata.find(this.entityName);
@@ -643,6 +643,10 @@ export class QueryBuilderHelper {
643
643
  return '?';
644
644
  }
645
645
  getOperatorReplacement(op, value) {
646
+ // collection properties expand `$all` into `$some` sub-queries in `ObjectCriteriaNode`, nothing else has a SQL equivalent
647
+ if (op === '$all') {
648
+ throw new Error('The `$all` operator is supported only on collection properties in SQL drivers, use `$contains` for array columns instead.');
649
+ }
646
650
  let replacement = QueryOperator[op];
647
651
  if (op === '$exists') {
648
652
  replacement = value[op] ? 'is not' : 'is';