@mikro-orm/knex 7.0.0-dev.8 → 7.0.0-dev.80

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.
Files changed (55) hide show
  1. package/AbstractSqlConnection.d.ts +11 -5
  2. package/AbstractSqlConnection.js +78 -32
  3. package/AbstractSqlDriver.d.ts +9 -5
  4. package/AbstractSqlDriver.js +274 -226
  5. package/AbstractSqlPlatform.js +5 -5
  6. package/PivotCollectionPersister.d.ts +3 -2
  7. package/PivotCollectionPersister.js +12 -21
  8. package/README.md +3 -2
  9. package/SqlEntityManager.d.ts +9 -2
  10. package/SqlEntityManager.js +2 -2
  11. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
  12. package/dialects/mssql/MsSqlNativeQueryBuilder.js +44 -3
  13. package/dialects/mysql/MySqlExceptionConverter.d.ts +3 -3
  14. package/dialects/mysql/MySqlExceptionConverter.js +4 -5
  15. package/dialects/mysql/MySqlSchemaHelper.js +2 -2
  16. package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +1 -0
  17. package/dialects/postgresql/PostgreSqlTableCompiler.js +1 -0
  18. package/dialects/sqlite/BaseSqliteConnection.d.ts +3 -2
  19. package/dialects/sqlite/BaseSqliteConnection.js +2 -8
  20. package/dialects/sqlite/BaseSqlitePlatform.js +1 -2
  21. package/dialects/sqlite/SqliteExceptionConverter.d.ts +2 -2
  22. package/dialects/sqlite/SqliteExceptionConverter.js +6 -4
  23. package/dialects/sqlite/SqliteSchemaHelper.js +5 -6
  24. package/index.d.ts +1 -1
  25. package/index.js +1 -1
  26. package/package.json +5 -5
  27. package/query/ArrayCriteriaNode.d.ts +1 -0
  28. package/query/ArrayCriteriaNode.js +3 -0
  29. package/query/CriteriaNode.d.ts +4 -2
  30. package/query/CriteriaNode.js +11 -6
  31. package/query/CriteriaNodeFactory.js +12 -7
  32. package/query/NativeQueryBuilder.js +1 -1
  33. package/query/ObjectCriteriaNode.d.ts +1 -0
  34. package/query/ObjectCriteriaNode.js +39 -10
  35. package/query/QueryBuilder.d.ts +59 -7
  36. package/query/QueryBuilder.js +177 -53
  37. package/query/QueryBuilderHelper.d.ts +1 -1
  38. package/query/QueryBuilderHelper.js +18 -11
  39. package/query/ScalarCriteriaNode.d.ts +3 -3
  40. package/query/ScalarCriteriaNode.js +9 -7
  41. package/query/index.d.ts +1 -0
  42. package/query/index.js +1 -0
  43. package/query/raw.d.ts +59 -0
  44. package/query/raw.js +68 -0
  45. package/query/rawKnex.d.ts +58 -0
  46. package/query/rawKnex.js +72 -0
  47. package/schema/DatabaseSchema.js +25 -4
  48. package/schema/DatabaseTable.d.ts +5 -4
  49. package/schema/DatabaseTable.js +68 -34
  50. package/schema/SchemaComparator.js +4 -4
  51. package/schema/SchemaHelper.d.ts +2 -0
  52. package/schema/SchemaHelper.js +14 -10
  53. package/schema/SqlSchemaGenerator.d.ts +13 -6
  54. package/schema/SqlSchemaGenerator.js +40 -19
  55. package/typings.d.ts +85 -3
@@ -10,14 +10,16 @@ export class CriteriaNode {
10
10
  entityName;
11
11
  parent;
12
12
  key;
13
+ strict;
13
14
  payload;
14
15
  prop;
15
16
  index;
16
- constructor(metadata, entityName, parent, key, validate = true) {
17
+ constructor(metadata, entityName, parent, key, validate = true, strict = false) {
17
18
  this.metadata = metadata;
18
19
  this.entityName = entityName;
19
20
  this.parent = parent;
20
21
  this.key = key;
22
+ this.strict = strict;
21
23
  const meta = parent && metadata.find(parent.entityName);
22
24
  if (meta && key) {
23
25
  const pks = Utils.splitPrimaryKeys(key);
@@ -65,13 +67,13 @@ export class CriteriaNode {
65
67
  default: return false;
66
68
  }
67
69
  }
68
- renameFieldToPK(qb) {
69
- let joinAlias = qb.getAliasForJoinPath(this.getPath());
70
+ renameFieldToPK(qb, ownerAlias) {
71
+ const joinAlias = qb.getAliasForJoinPath(this.getPath(), { matchPopulateJoins: true });
70
72
  if (!joinAlias && this.parent && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind) && this.prop.owner) {
71
- joinAlias = qb.getAliasForJoinPath(this.parent.getPath());
72
- return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${joinAlias ?? qb.alias}.${col}`));
73
+ const alias = qb.getAliasForJoinPath(this.parent.getPath()) ?? ownerAlias ?? qb.alias;
74
+ return Utils.getPrimaryKeyHash(this.prop.joinColumns.map(col => `${alias}.${col}`));
73
75
  }
74
- const alias = joinAlias ?? qb.alias;
76
+ const alias = joinAlias ?? ownerAlias ?? qb.alias;
75
77
  if (this.prop.kind === ReferenceKind.MANY_TO_MANY) {
76
78
  return Utils.getPrimaryKeyHash(this.prop.inverseJoinColumns.map(col => `${alias}.${col}`));
77
79
  }
@@ -106,6 +108,9 @@ export class CriteriaNode {
106
108
  aliased(field, alias) {
107
109
  return alias ? `${alias}.${field}` : field;
108
110
  }
111
+ isStrict() {
112
+ return this.strict;
113
+ }
109
114
  /** @ignore */
110
115
  [inspect.custom]() {
111
116
  const o = {};
@@ -1,4 +1,4 @@
1
- import { isRaw, JsonType, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
1
+ import { GroupOperator, isRaw, JsonType, RawQueryFragment, ReferenceKind, Utils, ValidationError, } from '@mikro-orm/core';
2
2
  import { ObjectCriteriaNode } from './ObjectCriteriaNode.js';
3
3
  import { ArrayCriteriaNode } from './ArrayCriteriaNode.js';
4
4
  import { ScalarCriteriaNode } from './ScalarCriteriaNode.js';
@@ -36,7 +36,7 @@ export class CriteriaNodeFactory {
36
36
  }
37
37
  static createObjectNode(metadata, entityName, payload, parent, key) {
38
38
  const meta = metadata.find(entityName);
39
- const node = new ObjectCriteriaNode(metadata, entityName, parent, key);
39
+ const node = new ObjectCriteriaNode(metadata, entityName, parent, key, true, payload.__strict);
40
40
  node.payload = {};
41
41
  for (const key of Object.keys(payload)) {
42
42
  node.payload[key] = this.createObjectItemNode(metadata, entityName, node, payload, key, meta);
@@ -46,10 +46,14 @@ export class CriteriaNodeFactory {
46
46
  static createObjectItemNode(metadata, entityName, node, payload, key, meta) {
47
47
  const prop = meta?.properties[key];
48
48
  const childEntity = prop && prop.kind !== ReferenceKind.SCALAR ? prop.type : entityName;
49
- if (prop?.customType instanceof JsonType) {
49
+ const isNotEmbedded = prop?.kind !== ReferenceKind.EMBEDDED;
50
+ if (isNotEmbedded && prop?.customType instanceof JsonType) {
50
51
  return this.createScalarNode(metadata, childEntity, payload[key], node, key);
51
52
  }
52
- if (prop?.kind !== ReferenceKind.EMBEDDED) {
53
+ if (prop?.kind === ReferenceKind.SCALAR && payload[key] != null && Object.keys(payload[key]).some(f => f in GroupOperator)) {
54
+ throw ValidationError.cannotUseGroupOperatorsInsideScalars(entityName, prop.name, payload);
55
+ }
56
+ if (isNotEmbedded) {
53
57
  return this.createNode(metadata, childEntity, payload[key], node, key);
54
58
  }
55
59
  if (payload[key] == null) {
@@ -66,11 +70,12 @@ export class CriteriaNodeFactory {
66
70
  throw ValidationError.cannotUseOperatorsInsideEmbeddables(entityName, prop.name, payload);
67
71
  }
68
72
  const map = Object.keys(payload[key]).reduce((oo, k) => {
69
- if (!prop.embeddedProps[k] && !allowedOperators.includes(k)) {
73
+ const embeddedProp = prop.embeddedProps[k] ?? Object.values(prop.embeddedProps).find(p => p.name === k);
74
+ if (!embeddedProp && !allowedOperators.includes(k)) {
70
75
  throw ValidationError.invalidEmbeddableQuery(entityName, k, prop.type);
71
76
  }
72
- if (prop.embeddedProps[k]) {
73
- oo[prop.embeddedProps[k].name] = payload[key][k];
77
+ if (embeddedProp) {
78
+ oo[embeddedProp.name] = payload[key][k];
74
79
  }
75
80
  else if (typeof payload[key][k] === 'object') {
76
81
  oo[k] = JSON.stringify(payload[key][k]);
@@ -261,7 +261,7 @@ export class NativeQueryBuilder {
261
261
  }
262
262
  if (this.options.where?.sql.trim()) {
263
263
  this.parts.push(`where ${this.options.where.sql}`);
264
- this.params.push(...this.options.where.params);
264
+ this.options.where.params.forEach(p => this.params.push(p));
265
265
  }
266
266
  if (this.options.groupBy) {
267
267
  const fields = this.options.groupBy.map(field => this.quote(field));
@@ -5,6 +5,7 @@ import type { ICriteriaNodeProcessOptions, IQueryBuilder } from '../typings.js';
5
5
  */
6
6
  export declare class ObjectCriteriaNode<T extends object> extends CriteriaNode<T> {
7
7
  process(qb: IQueryBuilder<T>, options?: ICriteriaNodeProcessOptions): any;
8
+ isStrict(): boolean;
8
9
  unwrap(): any;
9
10
  willAutoJoin(qb: IQueryBuilder<T>, alias?: string, options?: ICriteriaNodeProcessOptions): boolean;
10
11
  shouldInline(payload: any): boolean;
@@ -1,4 +1,4 @@
1
- import { ALIAS_REPLACEMENT, QueryFlag, raw, RawQueryFragment, ReferenceKind, Utils, } from '@mikro-orm/core';
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
4
  /**
@@ -6,7 +6,8 @@ import { JoinType, QueryType } from './enums.js';
6
6
  */
7
7
  export class ObjectCriteriaNode extends CriteriaNode {
8
8
  process(qb, options) {
9
- const nestedAlias = qb.getAliasForJoinPath(this.getPath(), options);
9
+ const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
10
+ const nestedAlias = qb.getAliasForJoinPath(this.getPath(), { ...options, matchPopulateJoins });
10
11
  const ownerAlias = options?.alias || qb.alias;
11
12
  const keys = Object.keys(this.payload);
12
13
  let alias = options?.alias;
@@ -55,7 +56,23 @@ export class ObjectCriteriaNode extends CriteriaNode {
55
56
  }
56
57
  return { $and };
57
58
  }
58
- alias = this.autoJoin(qb, ownerAlias);
59
+ alias = this.autoJoin(qb, ownerAlias, options);
60
+ }
61
+ if (this.prop && nestedAlias) {
62
+ const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
63
+ // if the property is nullable and the filter is strict, we need to use left join, so we mimic the inner join behaviour
64
+ // with an exclusive condition on the join columns:
65
+ // - if the owning column is null, the row is missing, we don't apply the filter
66
+ // - if the target column is not null, the row is matched, we apply the filter
67
+ if (toOneProperty && this.prop.nullable && this.isStrict()) {
68
+ const key = this.prop.owner ? this.prop.name : this.prop.referencedPKs;
69
+ qb.andWhere({
70
+ $or: [
71
+ { [ownerAlias + '.' + key]: null },
72
+ { [nestedAlias + '.' + Utils.getPrimaryKeyHash(this.prop.referencedPKs)]: { $ne: null } },
73
+ ],
74
+ });
75
+ }
59
76
  }
60
77
  return keys.reduce((o, field) => {
61
78
  const childNode = this.payload[field];
@@ -66,13 +83,14 @@ export class ObjectCriteriaNode extends CriteriaNode {
66
83
  const virtual = childNode.prop?.persist === false && !childNode.prop?.formula;
67
84
  // if key is missing, we are inside group operator and we need to prefix with alias
68
85
  const primaryKey = this.key && this.metadata.find(this.entityName)?.primaryKeys.includes(field);
86
+ const isToOne = childNode.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(childNode.prop.kind);
69
87
  if (childNode.shouldInline(payload)) {
70
- const childAlias = qb.getAliasForJoinPath(childNode.getPath(), options);
88
+ const childAlias = qb.getAliasForJoinPath(childNode.getPath(), { preferNoBranch: isToOne, ...options });
71
89
  const a = qb.helper.isTableNameAliasRequired(qb.type) ? alias : undefined;
72
90
  this.inlineChildPayload(o, payload, field, a, childAlias);
73
91
  }
74
92
  else if (childNode.shouldRename(payload)) {
75
- this.inlineCondition(childNode.renameFieldToPK(qb), o, payload);
93
+ this.inlineCondition(childNode.renameFieldToPK(qb, alias), o, payload);
76
94
  }
77
95
  else if (isRawField) {
78
96
  const rawField = RawQueryFragment.getKnownFragment(field);
@@ -87,6 +105,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
87
105
  return o;
88
106
  }, {});
89
107
  }
108
+ isStrict() {
109
+ return this.strict || Object.keys(this.payload).some(key => {
110
+ return this.payload[key].isStrict();
111
+ });
112
+ }
90
113
  unwrap() {
91
114
  return Object.keys(this.payload).reduce((o, field) => {
92
115
  o[field] = this.payload[field].unwrap();
@@ -137,7 +160,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
137
160
  delete payload[k];
138
161
  o[this.aliased(field, alias)] = { [k]: tmp, ...o[this.aliased(field, alias)] };
139
162
  }
140
- else if (Utils.isGroupOperator(k) && Array.isArray(payload[k])) {
163
+ else if (k in GroupOperator && Array.isArray(payload[k])) {
141
164
  this.inlineArrayChildPayload(o, payload[k], k, prop, childAlias, alias);
142
165
  }
143
166
  else if (this.isPrefixed(k) || Utils.isOperator(k) || !childAlias) {
@@ -157,7 +180,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
157
180
  o[key] = value;
158
181
  return;
159
182
  }
160
- /* v8 ignore next 4 */
183
+ /* v8 ignore next */
161
184
  if (key === '$and') {
162
185
  o.$and.push({ [key]: value });
163
186
  return;
@@ -193,7 +216,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
193
216
  });
194
217
  return !primaryKeys && !nestedAlias && !operatorKeys && !embeddable;
195
218
  }
196
- autoJoin(qb, alias) {
219
+ autoJoin(qb, alias, options) {
197
220
  const nestedAlias = qb.getNextAlias(this.prop?.pivotTable ?? this.entityName);
198
221
  const customExpression = RawQueryFragment.isKnownFragment(this.key);
199
222
  const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || customExpression;
@@ -206,12 +229,18 @@ export class ObjectCriteriaNode extends CriteriaNode {
206
229
  }
207
230
  else {
208
231
  const prev = qb._fields?.slice();
209
- qb[method](field, nestedAlias, undefined, JoinType.leftJoin, path);
232
+ const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
233
+ const joinType = toOneProperty && !this.prop.nullable
234
+ ? JoinType.innerJoin
235
+ : JoinType.leftJoin;
236
+ qb[method](field, nestedAlias, undefined, joinType, path);
210
237
  if (!qb.hasFlag(QueryFlag.INFER_POPULATE)) {
211
238
  qb._fields = prev;
212
239
  }
213
240
  }
214
- qb.scheduleFilterCheck(path);
241
+ if (options?.type !== 'orderBy') {
242
+ qb.scheduleFilterCheck(path);
243
+ }
215
244
  return nestedAlias;
216
245
  }
217
246
  isPrefixed(field) {
@@ -1,5 +1,5 @@
1
1
  import { inspect } from 'node:util';
2
- import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type Transaction } from '@mikro-orm/core';
2
+ import { type AnyEntity, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FilterOptions, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type QBFilterQuery, type QBQueryOrderMap, QueryFlag, type QueryOrderMap, type QueryResult, RawQueryFragment, type RequiredEntityData, type Transaction } from '@mikro-orm/core';
3
3
  import { JoinType, QueryType } from './enums.js';
4
4
  import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
5
5
  import { type Alias, type OnConflictClause, QueryBuilderHelper } from './QueryBuilderHelper.js';
@@ -11,6 +11,30 @@ export interface ExecuteOptions {
11
11
  mapResults?: boolean;
12
12
  mergeResults?: boolean;
13
13
  }
14
+ export interface QBStreamOptions {
15
+ /**
16
+ * Results are mapped to entities, if you set `mapResults: false` you will get POJOs instead.
17
+ *
18
+ * @default true
19
+ */
20
+ mapResults?: boolean;
21
+ /**
22
+ * When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
23
+ * You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
24
+ * the SQL result, but still mapped to entities, meaning that to-many collections will contain at most
25
+ * one item, and you will get duplicate root entities when they have multiple items in the populated
26
+ * collection.
27
+ *
28
+ * @default true
29
+ */
30
+ mergeResults?: boolean;
31
+ /**
32
+ * When enabled, the driver will return the raw database results without renaming the fields to match the entity property names.
33
+ *
34
+ * @default false
35
+ */
36
+ rawResults?: boolean;
37
+ }
14
38
  type AnyString = string & {};
15
39
  type Compute<T> = {
16
40
  [K in keyof T]: T[K];
@@ -140,7 +164,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
140
164
  /**
141
165
  * Apply filters to the QB where condition.
142
166
  */
143
- applyFilters(filterOptions?: Dictionary<boolean | Dictionary> | string[] | boolean): Promise<void>;
167
+ applyFilters(filterOptions?: FilterOptions): Promise<void>;
144
168
  private readonly autoJoinedPaths;
145
169
  /**
146
170
  * @internal
@@ -149,7 +173,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
149
173
  /**
150
174
  * @internal
151
175
  */
152
- applyJoinedFilters(em: EntityManager, filterOptions?: Dictionary<boolean | Dictionary> | string[] | boolean): Promise<void>;
176
+ applyJoinedFilters(em: EntityManager, filterOptions: FilterOptions | undefined): Promise<void>;
153
177
  withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this;
154
178
  where(cond: QBFilterQuery<Entity>, operator?: keyof typeof GroupOperator): this;
155
179
  where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
@@ -158,6 +182,8 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
158
182
  orWhere(cond: QBFilterQuery<Entity>): this;
159
183
  orWhere(cond: string, params?: any[]): this;
160
184
  orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
185
+ andOrderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
186
+ private processOrderBy;
161
187
  groupBy(fields: EntityKeyOrString<Entity> | readonly EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
162
188
  having(cond?: QBFilterQuery | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
163
189
  andHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
@@ -182,17 +208,17 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
182
208
  /**
183
209
  * Adds index hint to the FROM clause.
184
210
  */
185
- indexHint(sql: string): this;
211
+ indexHint(sql: string | undefined): this;
186
212
  /**
187
213
  * Prepend comment to the sql query using the syntax `/* ... *&#8205;/`. Some characters are forbidden such as `/*, *&#8205;/` and `?`.
188
214
  */
189
- comment(comment: string | string[]): this;
215
+ comment(comment: string | string[] | undefined): this;
190
216
  /**
191
217
  * Add hints to the query using comment-like syntax `/*+ ... *&#8205;/`. MySQL and Oracle use this syntax for optimizer hints.
192
218
  * Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
193
219
  * are ignored as simple comments.
194
220
  */
195
- hintComment(comment: string | string[]): this;
221
+ hintComment(comment: string | string[] | undefined): this;
196
222
  /**
197
223
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
198
224
  * Allows setting a main string alias of the selection data.
@@ -245,14 +271,35 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
245
271
  * Use `method` to specify what kind of result you want to get (array/single/meta).
246
272
  */
247
273
  execute<U = any>(method?: 'all' | 'get' | 'run', options?: ExecuteOptions | boolean): Promise<U>;
274
+ private getConnection;
275
+ /**
276
+ * Executes the query and returns an async iterable (async generator) that yields results one by one.
277
+ * By default, the results are merged and mapped to entity instances, without adding them to the identity map.
278
+ * You can disable merging and mapping by passing the options `{ mergeResults: false, mapResults: false }`.
279
+ * This is useful for processing large datasets without loading everything into memory at once.
280
+ *
281
+ * ```ts
282
+ * const qb = em.createQueryBuilder(Book, 'b');
283
+ * qb.select('*').where({ title: '1984' }).leftJoinAndSelect('b.author', 'a');
284
+ *
285
+ * for await (const book of qb.stream()) {
286
+ * // book is an instance of Book entity
287
+ * console.log(book.title, book.author.name);
288
+ * }
289
+ * ```
290
+ */
291
+ stream(options?: QBStreamOptions): AsyncIterableIterator<Loaded<Entity, Hint>>;
248
292
  /**
249
293
  * Alias for `qb.getResultList()`
250
294
  */
251
295
  getResult(): Promise<Loaded<Entity, Hint>[]>;
252
296
  /**
253
- * Executes the query, returning array of results
297
+ * Executes the query, returning array of results mapped to entity instances.
254
298
  */
255
299
  getResultList(limit?: number): Promise<Loaded<Entity, Hint>[]>;
300
+ private propagatePopulateHint;
301
+ private mapResult;
302
+ private mapResults;
256
303
  /**
257
304
  * Executes the query, returning the first result or null
258
305
  */
@@ -290,6 +337,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
290
337
  processPopulateHint(): void;
291
338
  private processPopulateWhere;
292
339
  private mergeOnConditions;
340
+ /**
341
+ * When adding an inner join on a left joined relation, we need to nest them,
342
+ * otherwise the inner join could discard rows of the root table.
343
+ */
344
+ private processNestedJoins;
293
345
  private hasToManyJoins;
294
346
  protected wrapPaginateSubQuery(meta: EntityMetadata): void;
295
347
  private pruneExtraJoins;