@mikro-orm/sql 7.0.0-dev.112 → 7.0.0-dev.114

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.
@@ -167,7 +167,12 @@ export class AbstractSqlDriver extends DatabaseDriver {
167
167
  async wrapVirtualExpressionInSubquery(meta, expression, where, options, type) {
168
168
  const qb = await this.createQueryBuilderFromOptions(meta, where, options);
169
169
  qb.setFlag(QueryFlag.DISABLE_PAGINATE);
170
- const isCursorPagination = [options.first, options.last, options.before, options.after].some(v => v != null);
170
+ const isCursorPagination = [
171
+ options.first,
172
+ options.last,
173
+ options.before,
174
+ options.after,
175
+ ].some(v => v != null);
171
176
  const native = qb.getNativeQuery(false);
172
177
  if (type === QueryType.COUNT) {
173
178
  native
@@ -830,7 +835,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
830
835
  populateWhere: undefined,
831
836
  // @ts-ignore
832
837
  _populateWhere: 'infer',
833
- populateFilter: !Utils.isEmpty(options?.populateFilter) ? { [pivotProp2.name]: options?.populateFilter } : undefined,
838
+ populateFilter: !Utils.isEmpty(options?.populateFilter) || RawQueryFragment.hasObjectFragments(options?.populateFilter) ? { [pivotProp2.name]: options?.populateFilter } : undefined,
834
839
  });
835
840
  const map = {};
836
841
  for (const owner of owners) {
@@ -844,7 +849,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
844
849
  return map;
845
850
  }
846
851
  getPivotOrderBy(prop, pivotProp, orderBy, parentOrderBy) {
847
- if (!Utils.isEmpty(orderBy)) {
852
+ if (!Utils.isEmpty(orderBy) || RawQueryFragment.hasObjectFragments(orderBy)) {
848
853
  return Utils.asArray(orderBy).map(o => ({ [pivotProp.name]: o }));
849
854
  }
850
855
  if (prop.kind === ReferenceKind.MANY_TO_MANY && Utils.asArray(parentOrderBy).some(o => o[prop.name])) {
@@ -852,7 +857,7 @@ export class AbstractSqlDriver extends DatabaseDriver {
852
857
  .filter(o => o[prop.name])
853
858
  .map(o => ({ [pivotProp.name]: o[prop.name] }));
854
859
  }
855
- if (!Utils.isEmpty(prop.orderBy)) {
860
+ if (!Utils.isEmpty(prop.orderBy) || RawQueryFragment.hasObjectFragments(prop.orderBy)) {
856
861
  return Utils.asArray(prop.orderBy).map(o => ({ [pivotProp.name]: o }));
857
862
  }
858
863
  if (prop.fixedOrder) {
@@ -1152,21 +1157,21 @@ export class AbstractSqlDriver extends DatabaseDriver {
1152
1157
  for (const hint of joinedProps) {
1153
1158
  const [propName] = hint.field.split(':', 2);
1154
1159
  const prop = meta.properties[propName];
1155
- if (!Utils.isEmpty(prop.where)) {
1160
+ if (!Utils.isEmpty(prop.where) || RawQueryFragment.hasObjectFragments(prop.where)) {
1156
1161
  where[prop.name] = Utils.copy(prop.where);
1157
1162
  }
1158
1163
  if (hint.children) {
1159
1164
  const inner = this.buildPopulateWhere(prop.targetMeta, hint.children, {});
1160
- if (!Utils.isEmpty(inner)) {
1165
+ if (!Utils.isEmpty(inner) || RawQueryFragment.hasObjectFragments(inner)) {
1161
1166
  where[prop.name] ??= {};
1162
1167
  Object.assign(where[prop.name], inner);
1163
1168
  }
1164
1169
  }
1165
1170
  }
1166
- if (Utils.isEmpty(options.populateWhere)) {
1171
+ if (Utils.isEmpty(options.populateWhere) && !RawQueryFragment.hasObjectFragments(options.populateWhere)) {
1167
1172
  return where;
1168
1173
  }
1169
- if (Utils.isEmpty(where)) {
1174
+ if (Utils.isEmpty(where) && !RawQueryFragment.hasObjectFragments(where)) {
1170
1175
  return options.populateWhere;
1171
1176
  }
1172
1177
  /* v8 ignore next */
@@ -1178,31 +1183,31 @@ export class AbstractSqlDriver extends DatabaseDriver {
1178
1183
  // as `options.populateWhere` will be always recomputed to respect filters
1179
1184
  const populateWhereAll = options._populateWhere !== 'infer' && !Utils.isEmpty(options._populateWhere);
1180
1185
  const path = (populateWhereAll ? '[populate]' : '') + meta.className;
1186
+ const optionsOrderBy = Utils.asArray(options.orderBy);
1181
1187
  const populateOrderBy = this.buildPopulateOrderBy(qb, meta, Utils.asArray(options.populateOrderBy ?? options.orderBy), path, !!options.populateOrderBy);
1182
1188
  const joinedPropsOrderBy = this.buildJoinedPropsOrderBy(qb, meta, joinedProps, options, path);
1183
- return [...Utils.asArray(options.orderBy), ...populateOrderBy, ...joinedPropsOrderBy];
1189
+ return [...optionsOrderBy, ...populateOrderBy, ...joinedPropsOrderBy];
1184
1190
  }
1185
1191
  buildPopulateOrderBy(qb, meta, populateOrderBy, parentPath, explicit, parentAlias = qb.alias) {
1186
1192
  const orderBy = [];
1187
1193
  for (let i = 0; i < populateOrderBy.length; i++) {
1188
1194
  const orderHint = populateOrderBy[i];
1189
- for (const propName of Utils.keys(orderHint)) {
1190
- const raw = RawQueryFragment.getKnownFragment(propName, explicit);
1191
- if (raw) {
1192
- const sql = raw.sql.replace(new RegExp(ALIAS_REPLACEMENT_RE, 'g'), parentAlias);
1193
- const raw2 = new RawQueryFragment(sql, raw.params);
1194
- orderBy.push({ [raw2]: orderHint[propName] });
1195
+ for (const field of Utils.getObjectQueryKeys(orderHint)) {
1196
+ const childOrder = orderHint[field];
1197
+ if (RawQueryFragment.isKnownFragmentSymbol(field)) {
1198
+ const { sql, params } = RawQueryFragment.getKnownFragment(field);
1199
+ const key = raw(sql.replace(new RegExp(ALIAS_REPLACEMENT_RE, 'g'), parentAlias), params);
1200
+ orderBy.push({ [key]: childOrder });
1195
1201
  continue;
1196
1202
  }
1197
- const prop = meta.properties[propName];
1203
+ const prop = meta.properties[field];
1198
1204
  if (!prop) {
1199
- throw new Error(`Trying to order by not existing property ${meta.className}.${propName}`);
1205
+ throw new Error(`Trying to order by not existing property ${meta.className}.${field}`);
1200
1206
  }
1201
1207
  let path = parentPath;
1202
1208
  const meta2 = this.metadata.find(prop.type);
1203
- const childOrder = orderHint[prop.name];
1204
1209
  if (prop.kind !== ReferenceKind.SCALAR && (![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) || !prop.owner || Utils.isPlainObject(childOrder))) {
1205
- path += `.${propName}`;
1210
+ path += `.${field}`;
1206
1211
  }
1207
1212
  if (prop.kind === ReferenceKind.MANY_TO_MANY && typeof childOrder !== 'object') {
1208
1213
  path += '[pivot]';
@@ -1228,9 +1233,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
1228
1233
  }
1229
1234
  continue;
1230
1235
  }
1231
- const order = typeof childOrder === 'object' ? childOrder[propName] : childOrder;
1236
+ const order = typeof childOrder === 'object' ? childOrder[field] : childOrder;
1232
1237
  if (order) {
1233
- orderBy.push({ [`${propAlias}.${propName}`]: order });
1238
+ orderBy.push({ [`${propAlias}.${field}`]: order });
1234
1239
  }
1235
1240
  }
1236
1241
  }
@@ -1256,15 +1261,16 @@ export class AbstractSqlDriver extends DatabaseDriver {
1256
1261
  }
1257
1262
  if (propOrderBy) {
1258
1263
  for (const item of Utils.asArray(propOrderBy)) {
1259
- for (const field of Utils.keys(item)) {
1260
- const rawField = RawQueryFragment.getKnownFragment(field, false);
1261
- if (rawField) {
1262
- const sql = propAlias ? rawField.sql.replace(new RegExp(ALIAS_REPLACEMENT_RE, 'g'), propAlias) : rawField.sql;
1263
- const raw2 = raw(sql, rawField.params);
1264
- orderBy.push({ [raw2.toString()]: item[field] });
1264
+ for (const field of Utils.getObjectQueryKeys(item)) {
1265
+ const order = item[field];
1266
+ if (RawQueryFragment.isKnownFragmentSymbol(field)) {
1267
+ const { sql, params } = RawQueryFragment.getKnownFragment(field);
1268
+ const sql2 = propAlias ? sql.replace(new RegExp(ALIAS_REPLACEMENT_RE, 'g'), propAlias) : sql;
1269
+ const key = raw(sql2, params);
1270
+ orderBy.push({ [key]: order });
1265
1271
  continue;
1266
1272
  }
1267
- orderBy.push({ [`${propAlias}.${field}`]: item[field] });
1273
+ orderBy.push({ [`${propAlias}.${field}`]: order });
1268
1274
  }
1269
1275
  }
1270
1276
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.0.0-dev.112",
3
+ "version": "7.0.0-dev.114",
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.2"
57
57
  },
58
58
  "peerDependencies": {
59
- "@mikro-orm/core": "7.0.0-dev.112"
59
+ "@mikro-orm/core": "7.0.0-dev.114"
60
60
  }
61
61
  }
@@ -1,4 +1,4 @@
1
- import { type EntityKey, type EntityProperty, type MetadataStorage } from '@mikro-orm/core';
1
+ import { type EntityKey, type EntityProperty, type MetadataStorage, type RawQueryFragmentSymbol } from '@mikro-orm/core';
2
2
  import type { ICriteriaNode, ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
3
3
  /**
4
4
  * Helper for working with deeply nested where/orderBy/having criteria. Uses composite pattern to build tree from the payload.
@@ -9,12 +9,12 @@ export declare class CriteriaNode<T extends object> implements ICriteriaNode<T>
9
9
  protected readonly metadata: MetadataStorage;
10
10
  readonly entityName: string;
11
11
  readonly parent?: ICriteriaNode<T> | undefined;
12
- readonly key?: EntityKey<T> | undefined;
12
+ readonly key?: (EntityKey<T> | RawQueryFragmentSymbol) | undefined;
13
13
  readonly strict: boolean;
14
14
  payload: any;
15
15
  prop?: EntityProperty<T>;
16
16
  index?: number;
17
- constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode<T> | undefined, key?: EntityKey<T> | undefined, validate?: boolean, strict?: boolean);
17
+ constructor(metadata: MetadataStorage, entityName: string, parent?: ICriteriaNode<T> | undefined, key?: (EntityKey<T> | RawQueryFragmentSymbol) | undefined, validate?: boolean, strict?: boolean);
18
18
  process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
19
19
  unwrap(): any;
20
20
  shouldInline(payload: any): boolean;
@@ -20,7 +20,7 @@ export class CriteriaNode {
20
20
  this.key = key;
21
21
  this.strict = strict;
22
22
  const meta = parent && metadata.find(parent.entityName);
23
- if (meta && key) {
23
+ if (meta && key && !RawQueryFragment.isKnownFragmentSymbol(key)) {
24
24
  const pks = Utils.splitPrimaryKeys(key);
25
25
  if (pks.length > 1) {
26
26
  return;
@@ -29,7 +29,7 @@ export class CriteriaNode {
29
29
  this.prop = meta.props.find(prop => prop.name === k || (prop.fieldNames?.length === 1 && prop.fieldNames[0] === k && prop.persist !== false));
30
30
  const isProp = this.prop || meta.props.find(prop => (prop.fieldNames || []).includes(k));
31
31
  // do not validate if the key is prefixed or type casted (e.g. `k::text`)
32
- if (validate && !isProp && !k.includes('.') && !k.includes('::') && !Utils.isOperator(k) && !RawQueryFragment.isKnownFragment(k)) {
32
+ if (validate && !isProp && !k.includes('.') && !k.includes('::') && !Utils.isOperator(k)) {
33
33
  throw new Error(`Trying to query by not existing property ${entityName}.${k}`);
34
34
  }
35
35
  }
@@ -50,11 +50,9 @@ export class CriteriaNode {
50
50
  shouldRename(payload) {
51
51
  const type = this.prop ? this.prop.kind : null;
52
52
  const composite = this.prop?.joinColumns ? this.prop.joinColumns.length > 1 : false;
53
- const customExpression = RawQueryFragment.isKnownFragment(this.key);
54
- const scalar = payload === null || Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
55
- const plainObject = Utils.isPlainObject(payload);
56
- const keys = plainObject ? Object.keys(payload) : [];
57
- const operator = plainObject && keys.every(k => Utils.isOperator(k, false));
53
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
54
+ const scalar = payload === null || Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
55
+ const operator = Utils.isPlainObject(payload) && Utils.getObjectQueryKeys(payload).every(k => Utils.isOperator(k, false));
58
56
  if (composite) {
59
57
  return true;
60
58
  }
@@ -84,7 +82,7 @@ export class CriteriaNode {
84
82
  const parentPath = this.parent?.getPath(addParentIndex) ?? this.entityName;
85
83
  const index = addIndex && this.index != null ? `[${this.index}]` : '';
86
84
  // ignore group operators to allow easier mapping (e.g. for orderBy)
87
- const key = this.key && !['$and', '$or', '$not'].includes(this.key) ? '.' + this.key : '';
85
+ const key = this.key && !RawQueryFragment.isKnownFragmentSymbol(this.key) && !['$and', '$or', '$not'].includes(this.key) ? '.' + this.key : '';
88
86
  const ret = parentPath + index + key;
89
87
  if (this.isPivotJoin()) {
90
88
  // distinguish pivot table join from target entity join
@@ -96,9 +94,9 @@ export class CriteriaNode {
96
94
  if (!this.key || !this.prop) {
97
95
  return false;
98
96
  }
99
- const customExpression = RawQueryFragment.isKnownFragment(this.key);
100
- const scalar = this.payload === null || Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
101
- const operator = Utils.isObject(this.payload) && Object.keys(this.payload).every(k => Utils.isOperator(k, false));
97
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
98
+ const scalar = this.payload === null || Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || rawField;
99
+ const operator = Utils.isObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
102
100
  return this.prop.kind === ReferenceKind.MANY_TO_MANY && (scalar || operator);
103
101
  }
104
102
  getPivotPath(path) {
@@ -1,12 +1,12 @@
1
- import { type Dictionary, type EntityKey, type EntityMetadata, type MetadataStorage } from '@mikro-orm/core';
1
+ import { type Dictionary, type EntityKey, type EntityMetadata, type MetadataStorage, type RawQueryFragmentSymbol } from '@mikro-orm/core';
2
2
  import type { ICriteriaNode } from '../typings.js';
3
3
  /**
4
4
  * @internal
5
5
  */
6
6
  export declare class CriteriaNodeFactory {
7
- static createNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
8
- static createScalarNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
7
+ static createNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T> | RawQueryFragmentSymbol): ICriteriaNode<T>;
8
+ static createScalarNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any, parent?: ICriteriaNode<T>, key?: EntityKey<T> | RawQueryFragmentSymbol): ICriteriaNode<T>;
9
9
  static createArrayNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: any[], parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
10
10
  static createObjectNode<T extends object>(metadata: MetadataStorage, entityName: string, payload: Dictionary, parent?: ICriteriaNode<T>, key?: EntityKey<T>): ICriteriaNode<T>;
11
- static createObjectItemNode<T extends object>(metadata: MetadataStorage, entityName: string, node: ICriteriaNode<T>, payload: Dictionary, key: EntityKey<T>, meta?: EntityMetadata<T>): ICriteriaNode<T>;
11
+ static createObjectItemNode<T extends object>(metadata: MetadataStorage, entityName: string, node: ICriteriaNode<T>, payload: Dictionary, key: EntityKey<T> | RawQueryFragmentSymbol, meta?: EntityMetadata<T>): ICriteriaNode<T>;
12
12
  }
@@ -7,8 +7,8 @@ import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
7
7
  */
8
8
  export class CriteriaNodeFactory {
9
9
  static createNode(metadata, entityName, payload, parent, key) {
10
- const customExpression = RawQueryFragment.isKnownFragment(key || '');
11
- const scalar = Utils.isPrimaryKey(payload) || isRaw(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
10
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
11
+ const scalar = Utils.isPrimaryKey(payload) || isRaw(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
12
12
  if (Array.isArray(payload) && !scalar) {
13
13
  return this.createArrayNode(metadata, entityName, payload, parent, key);
14
14
  }
@@ -38,25 +38,27 @@ export class CriteriaNodeFactory {
38
38
  const meta = metadata.find(entityName);
39
39
  const node = new ObjectCriteriaNode(metadata, entityName, parent, key, true, payload.__strict);
40
40
  node.payload = {};
41
- for (const key of Object.keys(payload)) {
42
- node.payload[key] = this.createObjectItemNode(metadata, entityName, node, payload, key, meta);
41
+ for (const k of Utils.getObjectQueryKeys(payload)) {
42
+ node.payload[k] = this.createObjectItemNode(metadata, entityName, node, payload, k, meta);
43
43
  }
44
44
  return node;
45
45
  }
46
46
  static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
47
- const prop = meta?.properties[key];
47
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(key);
48
+ const prop = rawField ? null : meta?.properties[key];
48
49
  const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.type : entityName;
49
- const isNotEmbedded = prop?.kind !== ReferenceKind.EMBEDDED;
50
+ const isNotEmbedded = rawField || prop?.kind !== ReferenceKind.EMBEDDED;
51
+ const val = payload[key];
50
52
  if (isNotEmbedded && prop?.customType instanceof JsonType) {
51
- return this.createScalarNode(metadata, childEntity, payload[key], node, key);
53
+ return this.createScalarNode(metadata, childEntity, val, node, key);
52
54
  }
53
- if (prop?.kind === ReferenceKind.SCALAR && payload[key] != null && Object.keys(payload[key]).some(f => f in GroupOperator)) {
55
+ if (prop?.kind === ReferenceKind.SCALAR && val != null && Object.keys(val).some(f => f in GroupOperator)) {
54
56
  throw ValidationError.cannotUseGroupOperatorsInsideScalars(entityName, prop.name, payload);
55
57
  }
56
58
  if (isNotEmbedded) {
57
- return this.createNode(metadata, childEntity, payload[key], node, key);
59
+ return this.createNode(metadata, childEntity, val, node, key);
58
60
  }
59
- if (payload[key] == null) {
61
+ if (val == null) {
60
62
  const map = Object.keys(prop.embeddedProps).reduce((oo, k) => {
61
63
  oo[prop.embeddedProps[k].name] = null;
62
64
  return oo;
@@ -65,23 +67,23 @@ export class CriteriaNodeFactory {
65
67
  }
66
68
  // array operators can be used on embedded properties
67
69
  const allowedOperators = ['$contains', '$contained', '$overlap'];
68
- const operator = Object.keys(payload[key]).some(f => Utils.isOperator(f) && !allowedOperators.includes(f));
70
+ const operator = Object.keys(val).some(f => Utils.isOperator(f) && !allowedOperators.includes(f));
69
71
  if (operator) {
70
72
  throw ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
71
73
  }
72
- const map = Object.keys(payload[key]).reduce((oo, k) => {
74
+ const map = Object.keys(val).reduce((oo, k) => {
73
75
  const embeddedProp = prop.embeddedProps[k] ?? Object.values(prop.embeddedProps).find(p => p.name === k);
74
76
  if (!embeddedProp && !allowedOperators.includes(k)) {
75
77
  throw ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
76
78
  }
77
79
  if (embeddedProp) {
78
- oo[embeddedProp.name] = payload[key][k];
80
+ oo[embeddedProp.name] = val[k];
79
81
  }
80
- else if (typeof payload[key][k] === 'object') {
81
- oo[k] = JSON.stringify(payload[key][k]);
82
+ else if (typeof val[k] === 'object') {
83
+ oo[k] = JSON.stringify(val[k]);
82
84
  }
83
85
  else {
84
- oo[k] = payload[key][k];
86
+ oo[k] = val[k];
85
87
  }
86
88
  return oo;
87
89
  }, {});
@@ -27,8 +27,7 @@ export class NativeQueryBuilder {
27
27
  }
28
28
  from(tableName, options) {
29
29
  if (tableName instanceof NativeQueryBuilder) {
30
- const { sql, params } = tableName.compile();
31
- tableName = raw(sql, params);
30
+ tableName = tableName.toRaw();
32
31
  }
33
32
  if (typeof tableName === 'string') {
34
33
  const alias = options?.alias ? ` as ${this.platform.quoteIdentifier(options.alias)}` : '';
@@ -9,7 +9,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
9
9
  const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
10
10
  const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
11
11
  const ownerAlias = options?.alias || qb.alias;
12
- const keys = Object.keys(this.payload);
12
+ const keys = Utils.getObjectQueryKeys(this.payload);
13
13
  let alias = options?.alias;
14
14
  if (nestedAlias) {
15
15
  alias = nestedAlias;
@@ -31,7 +31,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
31
31
  return [QueryType.SELECT, QueryType.COUNT].includes(qb.type) ? `${knownKey ? alias : ownerAlias}.${pk}` : pk;
32
32
  });
33
33
  for (const key of keys) {
34
- if (!['$some', '$none', '$every'].includes(key)) {
34
+ if (typeof key !== 'string' || !['$some', '$none', '$every'].includes(key)) {
35
35
  throw new Error('Mixing collection operators with other filters is not allowed.');
36
36
  }
37
37
  const payload = this.payload[key].unwrap();
@@ -78,7 +78,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
78
78
  const childNode = this.payload[field];
79
79
  const payload = childNode.process(qb, { ...options, alias: this.prop ? alias : ownerAlias });
80
80
  const operator = Utils.isOperator(field);
81
- const isRawField = RawQueryFragment.isKnownFragment(field);
81
+ const isRawField = RawQueryFragment.isKnownFragmentSymbol(field);
82
82
  // we need to keep the prefixing for formulas otherwise we would lose aliasing context when nesting inside group operators
83
83
  const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
84
84
  // if key is missing, we are inside group operator and we need to prefix with alias
@@ -106,12 +106,12 @@ export class ObjectCriteriaNode extends CriteriaNode {
106
106
  }, {});
107
107
  }
108
108
  isStrict() {
109
- return this.strict || Object.keys(this.payload).some(key => {
109
+ return this.strict || Utils.getObjectQueryKeys(this.payload).some(key => {
110
110
  return this.payload[key].isStrict();
111
111
  });
112
112
  }
113
113
  unwrap() {
114
- return Object.keys(this.payload).reduce((o, field) => {
114
+ return Utils.getObjectQueryKeys(this.payload).reduce((o, field) => {
115
115
  o[field] = this.payload[field].unwrap();
116
116
  return o;
117
117
  }, {});
@@ -119,7 +119,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
119
119
  willAutoJoin(qb, alias, options) {
120
120
  const nestedAlias = qb.getAliasForJoinPath(this.getPath(), options);
121
121
  const ownerAlias = alias || qb.alias;
122
- const keys = Object.keys(this.payload);
122
+ const keys = Utils.getObjectQueryKeys(this.payload);
123
123
  if (nestedAlias) {
124
124
  alias = nestedAlias;
125
125
  }
@@ -132,9 +132,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
132
132
  });
133
133
  }
134
134
  shouldInline(payload) {
135
- const customExpression = RawQueryFragment.isKnownFragment(this.key);
136
- const scalar = Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || customExpression;
137
- const operator = Utils.isObject(payload) && Object.keys(payload).every(k => Utils.isOperator(k, false));
135
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
136
+ const scalar = Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
137
+ const operator = Utils.isObject(payload) && Utils.getObjectQueryKeys(payload).every(k => Utils.isOperator(k, false));
138
138
  return !!this.prop && this.prop.kind !== ReferenceKind.SCALAR && !scalar && !operator;
139
139
  }
140
140
  getChildKey(k, prop, childAlias, alias) {
@@ -145,8 +145,8 @@ export class ObjectCriteriaNode extends CriteriaNode {
145
145
  }
146
146
  inlineArrayChildPayload(obj, payload, k, prop, childAlias, alias) {
147
147
  const key = this.getChildKey(k, prop, childAlias);
148
- const value = payload.map((child) => Object.keys(child).reduce((inner, childKey) => {
149
- const key = (this.isPrefixed(childKey) || Utils.isOperator(childKey)) ? childKey : this.aliased(childKey, childAlias);
148
+ const value = payload.map((child) => Utils.getObjectQueryKeys(child).reduce((inner, childKey) => {
149
+ const key = (RawQueryFragment.isKnownFragmentSymbol(childKey) || this.isPrefixed(childKey) || Utils.isOperator(childKey)) ? childKey : this.aliased(childKey, childAlias);
150
150
  inner[key] = child[childKey];
151
151
  return inner;
152
152
  }, {}));
@@ -154,8 +154,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
154
154
  }
155
155
  inlineChildPayload(o, payload, field, alias, childAlias) {
156
156
  const prop = this.metadata.find(this.entityName).properties[field];
157
- for (const k of Object.keys(payload)) {
158
- if (Utils.isOperator(k, false)) {
157
+ for (const k of Utils.getObjectQueryKeys(payload)) {
158
+ if (RawQueryFragment.isKnownFragmentSymbol(k)) {
159
+ o[k] = payload[k];
160
+ }
161
+ else if (Utils.isOperator(k, false)) {
159
162
  const tmp = payload[k];
160
163
  delete payload[k];
161
164
  o[this.aliased(field, alias)] = { [k]: tmp, ...o[this.aliased(field, alias)] };
@@ -167,9 +170,6 @@ export class ObjectCriteriaNode extends CriteriaNode {
167
170
  const key = this.getChildKey(k, prop, childAlias, alias);
168
171
  this.inlineCondition(key, o, payload[k]);
169
172
  }
170
- else if (RawQueryFragment.isKnownFragment(k)) {
171
- o[k] = payload[k];
172
- }
173
173
  else {
174
174
  o[this.aliased(k, childAlias)] = payload[k];
175
175
  }
@@ -194,8 +194,8 @@ export class ObjectCriteriaNode extends CriteriaNode {
194
194
  if (!this.prop || !this.parent) {
195
195
  return false;
196
196
  }
197
- const keys = Object.keys(this.payload);
198
- if (keys.every(k => k.includes('.') && k.startsWith(`${qb.alias}.`))) {
197
+ const keys = Utils.getObjectQueryKeys(this.payload);
198
+ if (keys.every(k => typeof k === 'string' && k.includes('.') && k.startsWith(`${qb.alias}.`))) {
199
199
  return false;
200
200
  }
201
201
  if (keys.some(k => ['$some', '$none', '$every'].includes(k))) {
@@ -206,21 +206,21 @@ export class ObjectCriteriaNode extends CriteriaNode {
206
206
  const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
207
207
  const operatorKeys = knownKey && keys.every(key => Utils.isOperator(key, false));
208
208
  const primaryKeys = knownKey && keys.every(key => {
209
- if (!meta.primaryKeys.includes(key)) {
209
+ if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
210
210
  return false;
211
211
  }
212
212
  if (!Utils.isPlainObject(this.payload[key].payload) || ![ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
213
213
  return true;
214
214
  }
215
- return Object.keys(this.payload[key].payload).every(k => meta.properties[key].targetMeta.primaryKeys.includes(k));
215
+ return Utils.getObjectQueryKeys(this.payload[key].payload).every(k => typeof k === 'string' && meta.properties[key].targetMeta.primaryKeys.includes(k));
216
216
  });
217
217
  return !primaryKeys && !nestedAlias && !operatorKeys && !embeddable;
218
218
  }
219
219
  autoJoin(qb, alias, options) {
220
220
  const nestedAlias = qb.getNextAlias(this.prop?.pivotTable ?? this.entityName);
221
- const customExpression = RawQueryFragment.isKnownFragment(this.key);
222
- const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
223
- const operator = Utils.isPlainObject(this.payload) && Object.keys(this.payload).every(k => Utils.isOperator(k, false));
221
+ const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
222
+ const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || rawField;
223
+ const operator = Utils.isPlainObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
224
224
  const field = `${alias}.${this.prop.name}`;
225
225
  const method = qb.hasFlag(QueryFlag.INFER_POPULATE) ? 'joinAndSelect' : 'join';
226
226
  const path = this.getPath();
@@ -98,8 +98,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
98
98
  __populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
99
99
  /** @internal */
100
100
  _populateMap: Dictionary<string>;
101
- /** @internal */
102
- readonly rawFragments: Set<string>;
103
101
  protected aliasCounter: number;
104
102
  protected flags: Set<QueryFlag>;
105
103
  protected finalized: boolean;
@@ -175,11 +173,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
175
173
  applyJoinedFilters(em: EntityManager, filterOptions: FilterOptions | undefined): Promise<void>;
176
174
  withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this;
177
175
  where(cond: QBFilterQuery<Entity>, operator?: keyof typeof GroupOperator): this;
178
- where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
176
+ where(cond: string | RawQueryFragment, params?: any[], operator?: keyof typeof GroupOperator): this;
179
177
  andWhere(cond: QBFilterQuery<Entity>): this;
180
- andWhere(cond: string, params?: any[]): this;
178
+ andWhere(cond: string | RawQueryFragment, params?: any[]): this;
181
179
  orWhere(cond: QBFilterQuery<Entity>): this;
182
- orWhere(cond: string, params?: any[]): this;
180
+ orWhere(cond: string | RawQueryFragment, params?: any[]): this;
183
181
  orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
184
182
  andOrderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
185
183
  private processOrderBy;
@@ -225,10 +223,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
225
223
  from<Entity extends AnyEntity<Entity> = AnyEntity>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
226
224
  from<Entity extends AnyEntity<Entity> = AnyEntity>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
227
225
  getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
228
- /**
229
- * @internal
230
- */
231
- clearRawFragmentsCache(): void;
232
226
  /**
233
227
  * Returns the query with parameters as wildcards.
234
228
  */