@mikro-orm/sql 7.0.0-dev.129 → 7.0.0-dev.131

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.0.0-dev.129",
3
+ "version": "7.0.0-dev.131",
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
  "type": "module",
6
6
  "exports": {
@@ -56,6 +56,6 @@
56
56
  "@mikro-orm/core": "^6.6.4"
57
57
  },
58
58
  "peerDependencies": {
59
- "@mikro-orm/core": "7.0.0-dev.129"
59
+ "@mikro-orm/core": "7.0.0-dev.131"
60
60
  }
61
61
  }
@@ -1,6 +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
5
  /**
5
6
  * @internal
6
7
  */
@@ -15,7 +16,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
15
16
  alias = nestedAlias;
16
17
  }
17
18
  if (this.shouldAutoJoin(qb, nestedAlias)) {
18
- if (keys.some(k => ['$some', '$none', '$every'].includes(k))) {
19
+ if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
19
20
  if (![ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(this.prop.kind)) {
20
21
  // ignore collection operators when used on a non-relational property - this can happen when they get into
21
22
  // populateWhere via `infer` on m:n properties with select-in strategy
@@ -31,22 +32,31 @@ export class ObjectCriteriaNode extends CriteriaNode {
31
32
  return [QueryType.SELECT, QueryType.COUNT].includes(qb.type) ? `${knownKey ? alias : ownerAlias}.${pk}` : pk;
32
33
  });
33
34
  for (const key of keys) {
34
- if (typeof key !== 'string' || !['$some', '$none', '$every'].includes(key)) {
35
+ if (typeof key !== 'string' || !COLLECTION_OPERATORS.includes(key)) {
35
36
  throw new Error('Mixing collection operators with other filters is not allowed.');
36
37
  }
37
38
  const payload = this.payload[key].unwrap();
38
39
  const qb2 = qb.clone(true, ['_schema']);
40
+ const joinAlias = qb2.getNextAlias(this.prop.targetMeta.class);
39
41
  const sub = qb2
40
42
  .from(parentMeta.class)
41
- .innerJoin(this.key, qb2.getNextAlias(this.prop.targetMeta.class))
43
+ // eslint-disable-next-line no-unexpected-multiline
44
+ [key === '$size' ? 'leftJoin' : 'innerJoin'](this.key, joinAlias)
42
45
  .select(parentMeta.primaryKeys);
43
- if (key === '$every') {
46
+ if (key === '$size') {
47
+ const sizeCondition = typeof payload === 'number' ? { $eq: payload } : payload;
48
+ const pks = this.prop.referencedColumnNames;
49
+ const countExpr = raw(`count(${pks.map(() => '??').join(', ')})`, pks.map(pk => `${joinAlias}.${pk}`));
50
+ sub.groupBy(parentMeta.primaryKeys);
51
+ sub.having({ $and: Object.keys(sizeCondition).map(op => ({ [countExpr]: { [op]: sizeCondition[op] } })) });
52
+ }
53
+ else if (key === '$every') {
44
54
  sub.where({ $not: { [this.key]: payload } });
45
55
  }
46
56
  else {
47
57
  sub.where({ [this.key]: payload });
48
58
  }
49
- const op = key === '$some' ? '$in' : '$nin';
59
+ const op = ['$size', '$some'].includes(key) ? '$in' : '$nin';
50
60
  $and.push({
51
61
  [Utils.getPrimaryKeyHash(primaryKeys)]: { [op]: sub.getNativeQuery().toRaw() },
52
62
  });
@@ -124,7 +134,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
124
134
  alias = nestedAlias;
125
135
  }
126
136
  if (this.shouldAutoJoin(qb, nestedAlias)) {
127
- return !keys.some(k => ['$some', '$none', '$every'].includes(k));
137
+ return !keys.some(k => COLLECTION_OPERATORS.includes(k));
128
138
  }
129
139
  return keys.some(field => {
130
140
  const childNode = this.payload[field];
@@ -198,7 +208,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
198
208
  if (keys.every(k => typeof k === 'string' && k.includes('.') && k.startsWith(`${qb.alias}.`))) {
199
209
  return false;
200
210
  }
201
- if (keys.some(k => ['$some', '$none', '$every'].includes(k))) {
211
+ if (keys.some(k => COLLECTION_OPERATORS.includes(k))) {
202
212
  return true;
203
213
  }
204
214
  const meta = this.metadata.find(this.entityName);
@@ -280,7 +280,7 @@ export class QueryBuilder {
280
280
  if (Utils.hasObjectKeys(cond) || RawQueryFragment.hasObjectFragments(cond)) {
281
281
  // remove nested filters, we only care about scalars here, nesting would require another join branch
282
282
  for (const key of Object.keys(cond)) {
283
- if (Utils.isPlainObject(cond[key]) && Object.keys(cond[key]).every(k => !(Utils.isOperator(k) && !['$some', '$none', '$every'].includes(k)))) {
283
+ if (Utils.isPlainObject(cond[key]) && Object.keys(cond[key]).every(k => !(Utils.isOperator(k) && !['$some', '$none', '$every', '$size'].includes(k)))) {
284
284
  delete cond[key];
285
285
  }
286
286
  }