@mikro-orm/sql 7.0.0-rc.1 → 7.0.0-rc.3

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 (47) hide show
  1. package/AbstractSqlConnection.js +2 -1
  2. package/AbstractSqlDriver.d.ts +18 -12
  3. package/AbstractSqlDriver.js +187 -38
  4. package/AbstractSqlPlatform.d.ts +1 -0
  5. package/AbstractSqlPlatform.js +5 -3
  6. package/PivotCollectionPersister.js +2 -2
  7. package/SqlEntityManager.d.ts +5 -4
  8. package/SqlEntityManager.js +5 -5
  9. package/dialects/mssql/MsSqlNativeQueryBuilder.d.ts +2 -0
  10. package/dialects/mssql/MsSqlNativeQueryBuilder.js +8 -4
  11. package/dialects/mysql/BaseMySqlPlatform.js +1 -2
  12. package/dialects/mysql/MySqlSchemaHelper.js +21 -10
  13. package/dialects/postgresql/BasePostgreSqlPlatform.js +38 -30
  14. package/dialects/postgresql/PostgreSqlSchemaHelper.js +63 -47
  15. package/dialects/sqlite/BaseSqliteConnection.d.ts +4 -1
  16. package/dialects/sqlite/BaseSqliteConnection.js +4 -0
  17. package/dialects/sqlite/NodeSqliteDialect.d.ts +21 -0
  18. package/dialects/sqlite/NodeSqliteDialect.js +43 -0
  19. package/dialects/sqlite/SqliteDriver.d.ts +12 -0
  20. package/dialects/sqlite/SqliteDriver.js +14 -0
  21. package/dialects/sqlite/{BaseSqlitePlatform.d.ts → SqlitePlatform.d.ts} +5 -2
  22. package/dialects/sqlite/{BaseSqlitePlatform.js → SqlitePlatform.js} +30 -4
  23. package/dialects/sqlite/SqliteSchemaHelper.d.ts +5 -0
  24. package/dialects/sqlite/SqliteSchemaHelper.js +31 -10
  25. package/dialects/sqlite/index.d.ts +3 -1
  26. package/dialects/sqlite/index.js +3 -1
  27. package/package.json +30 -30
  28. package/plugin/transformer.js +17 -16
  29. package/query/CriteriaNode.js +28 -10
  30. package/query/CriteriaNodeFactory.js +5 -1
  31. package/query/NativeQueryBuilder.d.ts +25 -0
  32. package/query/NativeQueryBuilder.js +61 -1
  33. package/query/ObjectCriteriaNode.js +71 -27
  34. package/query/QueryBuilder.d.ts +177 -48
  35. package/query/QueryBuilder.js +233 -54
  36. package/query/QueryBuilderHelper.d.ts +4 -3
  37. package/query/QueryBuilderHelper.js +47 -17
  38. package/query/ScalarCriteriaNode.js +14 -7
  39. package/query/raw.js +1 -1
  40. package/schema/DatabaseSchema.js +21 -15
  41. package/schema/DatabaseTable.js +114 -54
  42. package/schema/SchemaComparator.js +56 -32
  43. package/schema/SchemaHelper.js +28 -8
  44. package/schema/SqlSchemaGenerator.d.ts +2 -1
  45. package/schema/SqlSchemaGenerator.js +15 -8
  46. package/tsconfig.build.tsbuildinfo +1 -1
  47. package/typings.d.ts +15 -4
@@ -7,7 +7,8 @@ const COLLECTION_OPERATORS = ['$some', '$none', '$every', '$size'];
7
7
  */
8
8
  export class ObjectCriteriaNode extends CriteriaNode {
9
9
  process(qb, options) {
10
- const matchPopulateJoins = options?.matchPopulateJoins || (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
10
+ const matchPopulateJoins = options?.matchPopulateJoins ||
11
+ (this.prop && [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind));
11
12
  const nestedAlias = qb.getAliasForJoinPath(this.getPath(options), { ...options, matchPopulateJoins });
12
13
  const ownerAlias = options?.alias || qb.alias;
13
14
  const keys = Utils.getObjectQueryKeys(this.payload);
@@ -20,13 +21,15 @@ export class ObjectCriteriaNode extends CriteriaNode {
20
21
  if (![ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(this.prop.kind)) {
21
22
  // ignore collection operators when used on a non-relational property - this can happen when they get into
22
23
  // populateWhere via `infer` on m:n properties with select-in strategy
23
- if (this.parent?.parent) { // we validate only usage on top level
24
+ if (this.parent?.parent) {
25
+ // we validate only usage on top level
24
26
  return {};
25
27
  }
26
28
  throw new Error(`Collection operators can be used only inside a collection property context, but it was used for ${this.getPath()}.`);
27
29
  }
28
30
  const $and = [];
29
- const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
31
+ const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) ||
32
+ (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
30
33
  const parentMeta = this.metadata.find(this.parent.entityName);
31
34
  const primaryKeys = parentMeta.primaryKeys.map(pk => {
32
35
  return [QueryType.SELECT, QueryType.COUNT].includes(qb.type) ? `${knownKey ? alias : ownerAlias}.${pk}` : pk;
@@ -48,7 +51,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
48
51
  const pks = this.prop.referencedColumnNames;
49
52
  const countExpr = raw(`count(${pks.map(() => '??').join(', ')})`, pks.map(pk => `${joinAlias}.${pk}`));
50
53
  sub.groupBy(parentMeta.primaryKeys);
51
- sub.having({ $and: Object.keys(sizeCondition).map(op => ({ [countExpr]: { [op]: sizeCondition[op] } })) });
54
+ sub.having({
55
+ $and: Object.keys(sizeCondition).map(op => ({ [countExpr]: { [op]: sizeCondition[op] } })),
56
+ });
52
57
  }
53
58
  else if (key === '$every') {
54
59
  sub.where({ $not: { [this.key]: payload } });
@@ -111,7 +116,11 @@ export class ObjectCriteriaNode extends CriteriaNode {
111
116
  // use '??' placeholder to properly quote the identifier
112
117
  o[raw('??', [field])] = payload;
113
118
  }
114
- else if (primaryKey || virtual || operator || field.includes('.') || ![QueryType.SELECT, QueryType.COUNT].includes(qb.type)) {
119
+ else if (primaryKey ||
120
+ virtual ||
121
+ operator ||
122
+ field.includes('.') ||
123
+ ![QueryType.SELECT, QueryType.COUNT].includes(qb.type)) {
115
124
  this.inlineCondition(field.replaceAll(ALIAS_REPLACEMENT, alias), o, payload);
116
125
  }
117
126
  else {
@@ -121,9 +130,10 @@ export class ObjectCriteriaNode extends CriteriaNode {
121
130
  }, {});
122
131
  }
123
132
  isStrict() {
124
- return this.strict || Utils.getObjectQueryKeys(this.payload).some(key => {
125
- return this.payload[key].isStrict();
126
- });
133
+ return (this.strict ||
134
+ Utils.getObjectQueryKeys(this.payload).some(key => {
135
+ return this.payload[key].isStrict();
136
+ }));
127
137
  }
128
138
  unwrap() {
129
139
  return Utils.getObjectQueryKeys(this.payload).reduce((o, field) => {
@@ -148,8 +158,18 @@ export class ObjectCriteriaNode extends CriteriaNode {
148
158
  }
149
159
  shouldInline(payload) {
150
160
  const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
151
- const scalar = Utils.isPrimaryKey(payload) || payload instanceof RegExp || payload instanceof Date || rawField;
152
- const operator = Utils.isObject(payload) && Utils.getObjectQueryKeys(payload).every(k => Utils.isOperator(k, false));
161
+ const scalar = Utils.isPrimaryKey(payload) ||
162
+ payload instanceof RegExp ||
163
+ payload instanceof Date ||
164
+ rawField;
165
+ const operator = Utils.isObject(payload) &&
166
+ Utils.getObjectQueryKeys(payload).every(k => {
167
+ if (k === '$not' && Utils.isPlainObject(payload[k])) {
168
+ // $not wrapping non-operator conditions (entity props) should be inlined
169
+ return Utils.getObjectQueryKeys(payload[k]).every(ik => Utils.isOperator(ik, false));
170
+ }
171
+ return Utils.isOperator(k, false);
172
+ });
153
173
  return !!this.prop && this.prop.kind !== ReferenceKind.SCALAR && !scalar && !operator;
154
174
  }
155
175
  getChildKey(k, prop, childAlias, alias) {
@@ -161,7 +181,9 @@ export class ObjectCriteriaNode extends CriteriaNode {
161
181
  inlineArrayChildPayload(obj, payload, k, prop, childAlias, alias) {
162
182
  const key = this.getChildKey(k, prop, childAlias);
163
183
  const value = payload.map((child) => Utils.getObjectQueryKeys(child).reduce((inner, childKey) => {
164
- const key = (RawQueryFragment.isKnownFragmentSymbol(childKey) || this.isPrefixed(childKey) || Utils.isOperator(childKey)) ? childKey : this.aliased(childKey, childAlias);
184
+ const key = RawQueryFragment.isKnownFragmentSymbol(childKey) || this.isPrefixed(childKey) || Utils.isOperator(childKey)
185
+ ? childKey
186
+ : this.aliased(childKey, childAlias);
165
187
  inner[key] = child[childKey];
166
188
  return inner;
167
189
  }, {}));
@@ -173,6 +195,12 @@ export class ObjectCriteriaNode extends CriteriaNode {
173
195
  if (RawQueryFragment.isKnownFragmentSymbol(k)) {
174
196
  o[k] = payload[k];
175
197
  }
198
+ else if (k === '$not' &&
199
+ Utils.isPlainObject(payload[k]) &&
200
+ Utils.getObjectQueryKeys(payload[k]).some(ik => !Utils.isOperator(ik, false))) {
201
+ // $not wraps entity conditions (from auto-join), inline at current level
202
+ this.inlineCondition(k, o, payload[k]);
203
+ }
176
204
  else if (Utils.isOperator(k, false)) {
177
205
  const tmp = payload[k];
178
206
  delete payload[k];
@@ -218,24 +246,42 @@ export class ObjectCriteriaNode extends CriteriaNode {
218
246
  }
219
247
  const meta = this.metadata.find(this.entityName);
220
248
  const embeddable = this.prop.kind === ReferenceKind.EMBEDDED;
221
- const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) || (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
222
- const operatorKeys = knownKey && keys.every(key => Utils.isOperator(key, false));
223
- const primaryKeys = knownKey && keys.every(key => {
224
- if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
225
- return false;
226
- }
227
- if (!Utils.isPlainObject(this.payload[key].payload) || ![ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
228
- return true;
229
- }
230
- return Utils.getObjectQueryKeys(this.payload[key].payload).every(k => typeof k === 'string' && meta.properties[key].targetMeta.primaryKeys.includes(k));
231
- });
249
+ const knownKey = [ReferenceKind.SCALAR, ReferenceKind.MANY_TO_ONE, ReferenceKind.EMBEDDED].includes(this.prop.kind) ||
250
+ (this.prop.kind === ReferenceKind.ONE_TO_ONE && this.prop.owner);
251
+ const operatorKeys = knownKey &&
252
+ keys.every(key => {
253
+ if (key === '$not') {
254
+ // $not wraps conditions like $and/$or, check if it wraps entity property conditions (needs auto-join)
255
+ // vs simple operator conditions on the FK (doesn't need auto-join)
256
+ const childPayload = this.payload[key].payload;
257
+ if (Utils.isPlainObject(childPayload)) {
258
+ return Utils.getObjectQueryKeys(childPayload).every(k => Utils.isOperator(k, false));
259
+ }
260
+ }
261
+ return Utils.isOperator(key, false);
262
+ });
263
+ const primaryKeys = knownKey &&
264
+ keys.every(key => {
265
+ if (typeof key !== 'string' || !meta.primaryKeys.includes(key)) {
266
+ return false;
267
+ }
268
+ if (!Utils.isPlainObject(this.payload[key].payload) ||
269
+ ![ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[key].kind)) {
270
+ return true;
271
+ }
272
+ return Utils.getObjectQueryKeys(this.payload[key].payload).every(k => typeof k === 'string' && meta.properties[key].targetMeta.primaryKeys.includes(k));
273
+ });
232
274
  return !primaryKeys && !nestedAlias && !operatorKeys && !embeddable;
233
275
  }
234
276
  autoJoin(qb, alias, options) {
235
277
  const nestedAlias = qb.getNextAlias(this.prop?.pivotEntity ?? this.entityName);
236
278
  const rawField = RawQueryFragment.isKnownFragmentSymbol(this.key);
237
- const scalar = Utils.isPrimaryKey(this.payload) || this.payload instanceof RegExp || this.payload instanceof Date || rawField;
238
- const operator = Utils.isPlainObject(this.payload) && Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
279
+ const scalar = Utils.isPrimaryKey(this.payload) ||
280
+ this.payload instanceof RegExp ||
281
+ this.payload instanceof Date ||
282
+ rawField;
283
+ const operator = Utils.isPlainObject(this.payload) &&
284
+ Utils.getObjectQueryKeys(this.payload).every(k => Utils.isOperator(k, false));
239
285
  const field = `${alias}.${this.prop.name}`;
240
286
  const method = qb.hasFlag(QueryFlag.INFER_POPULATE) ? 'joinAndSelect' : 'join';
241
287
  const path = this.getPath();
@@ -245,9 +291,7 @@ export class ObjectCriteriaNode extends CriteriaNode {
245
291
  else {
246
292
  const prev = qb._fields?.slice();
247
293
  const toOneProperty = [ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(this.prop.kind);
248
- const joinType = toOneProperty && !this.prop.nullable
249
- ? JoinType.innerJoin
250
- : JoinType.leftJoin;
294
+ const joinType = toOneProperty && !this.prop.nullable ? JoinType.innerJoin : JoinType.leftJoin;
251
295
  qb[method](field, nestedAlias, undefined, joinType, path);
252
296
  if (!qb.hasFlag(QueryFlag.INFER_POPULATE)) {
253
297
  qb._fields = prev;
@@ -1,11 +1,11 @@
1
- import { type AnyEntity, type AutoPath, type ConnectionType, type Dictionary, type EntityData, type EntityKey, type EntityManager, type EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FilterObject, type FilterOptions, type FilterValue, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type ObjectQuery, PopulateHint, type PopulateOptions, type PopulatePath, QueryFlag, type QueryOrderKeysFlat, type QueryOrderMap, type QueryResult, RawQueryFragment, type Raw, type RequiredEntityData, type Scalar, type Subquery, type Transaction } from '@mikro-orm/core';
1
+ import { type AnyEntity, type AutoPath, type Collection, type ConnectionType, type Dictionary, type EntityData, type EntityDTOFlat, type EntityDTOProp, type EntityKey, type EntityManager, EntityMetadata, type EntityName, type EntityProperty, type ExpandProperty, type FilterObject, type FilterOptions, type FilterValue, type FlushMode, type GroupOperator, type Loaded, LockMode, type LoggingOptions, type MetadataStorage, type PrimaryProperty, type ObjectQuery, PopulateHint, type PopulateOptions, type PopulatePath, QueryFlag, type QueryOrderKeysFlat, type QueryOrderMap, type QueryResult, RawQueryFragment, type Raw, type RequiredEntityData, type Scalar, type SerializeDTO, type Subquery, type Transaction } from '@mikro-orm/core';
2
2
  import { JoinType, QueryType } from './enums.js';
3
3
  import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
4
4
  import { type Alias, type OnConflictClause, QueryBuilderHelper } from './QueryBuilderHelper.js';
5
5
  import type { SqlEntityManager } from '../SqlEntityManager.js';
6
6
  import type { ICriteriaNodeProcessOptions, InternalField, JoinOptions } from '../typings.js';
7
7
  import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
8
- import { NativeQueryBuilder } from './NativeQueryBuilder.js';
8
+ import { type CteOptions, NativeQueryBuilder } from './NativeQueryBuilder.js';
9
9
  export interface ExecuteOptions {
10
10
  mapResults?: boolean;
11
11
  mergeResults?: boolean;
@@ -84,7 +84,7 @@ type RawOrderKeys<RawAliases extends string> = {
84
84
  export type ContextOrderByMap<Entity, RootAlias extends string = never, Context = never, RawAliases extends string = never> = QueryOrderMap<Entity> | ((IsNever<RootAlias> extends true ? {} : RootAliasOrderKeys<RootAlias, Entity>) & ([Context] extends [never] ? {} : ContextOrderKeys<Context>) & (IsNever<RawAliases> extends true ? {} : string extends RawAliases ? {} : RawOrderKeys<RawAliases>));
85
85
  type AliasedPath<Alias extends string, Type, P extends string> = P extends `${Alias}.*` ? P : P extends `${Alias}.${infer Rest}` ? `${Alias}.${AutoPath<Type & object, Rest, `${PopulatePath.ALL}`>}` : never;
86
86
  type ContextAliasedPath<Context, P extends string> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? AliasedPath<Alias & string, Type, P> : never : never : never;
87
- type NestedAutoPath<Entity, RootAlias extends string, Context, P extends string> = P extends `${string}:ref` ? never : P extends `${infer Path} as ${string}` ? (AliasedPath<RootAlias, Entity, Path> | ContextAliasedPath<Context, Path> | AutoPath<Entity, Path, `${PopulatePath.ALL}`>) extends never ? never : P : AliasedPath<RootAlias, Entity, P> | ContextAliasedPath<Context, P> | AutoPath<Entity, P, `${PopulatePath.ALL}`>;
87
+ type NestedAutoPath<Entity, RootAlias extends string, Context, P extends string> = P extends `${string}:ref` ? never : P extends `${infer Path} as ${string}` ? AliasedPath<RootAlias, Entity, Path> | ContextAliasedPath<Context, Path> | AutoPath<Entity, Path, `${PopulatePath.ALL}`> extends never ? never : P : AliasedPath<RootAlias, Entity, P> | ContextAliasedPath<Context, P> | AutoPath<Entity, P, `${PopulatePath.ALL}`>;
88
88
  type AliasedObjectQuery<Entity extends object, Alias extends string> = {
89
89
  [K in EntityKey<Entity> as `${Alias}.${K}`]?: ObjectQuery<Entity>[K];
90
90
  };
@@ -96,7 +96,7 @@ type JoinCondition<JoinedEntity extends object, Alias extends string> = (ObjectQ
96
96
  type RawJoinCondition = {
97
97
  [key: string]: FilterValue<Scalar> | RawQueryFragment;
98
98
  };
99
- type ExtractRawAliasFromField<F> = F extends RawQueryFragment<infer A> ? (A extends string ? A : never) : F extends `${string} as ${infer A}` ? A : never;
99
+ type ExtractRawAliasFromField<F> = F extends RawQueryFragment<infer A> ? A extends string ? A : never : F extends `${string} as ${infer A}` ? A : never;
100
100
  type ExtractRawAliasesFromTuple<T extends readonly unknown[]> = T extends readonly [infer Head, ...infer Tail] ? ExtractRawAliasFromField<Head> | ExtractRawAliasesFromTuple<Tail> : never;
101
101
  type ExtractRawAliases<Fields> = Fields extends readonly unknown[] ? ExtractRawAliasesFromTuple<Fields> : ExtractRawAliasFromField<Fields>;
102
102
  type FlatOperatorMap = {
@@ -158,7 +158,7 @@ export type QBFilterQuery<Entity, RootAlias extends string = never, Context = ne
158
158
  * const publisher = await qb.getSingleResult();
159
159
  * ```
160
160
  */
161
- export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never, RawAliases extends string = never, Fields extends string = '*'> implements Subquery {
161
+ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never, RawAliases extends string = never, Fields extends string = '*', CTEs extends Record<string, object> = {}> implements Subquery {
162
162
  protected readonly metadata: MetadataStorage;
163
163
  protected readonly driver: AbstractSqlDriver;
164
164
  protected readonly context?: Transaction | undefined;
@@ -220,6 +220,15 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
220
220
  params?: readonly unknown[];
221
221
  qb: NativeQueryBuilder;
222
222
  };
223
+ protected _unionQuery?: {
224
+ sql: string;
225
+ params: readonly unknown[];
226
+ };
227
+ protected _ctes: (CteOptions & {
228
+ name: string;
229
+ query: NativeQueryBuilder | RawQueryFragment;
230
+ recursive?: boolean;
231
+ })[];
223
232
  protected readonly platform: AbstractSqlPlatform;
224
233
  private tptJoinsApplied;
225
234
  private readonly autoJoinedPaths;
@@ -247,7 +256,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
247
256
  * qb.select('*', true);
248
257
  * ```
249
258
  */
250
- select<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<F>, ExtractRootFields<F[number] & string, RootAlias, Context>>;
259
+ select<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<F>, ExtractRootFields<F[number] & string, RootAlias, Context>, CTEs>;
251
260
  /**
252
261
  * Creates a SELECT query, specifying the fields to retrieve.
253
262
  *
@@ -264,7 +273,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
264
273
  * qb.select('*', true);
265
274
  * ```
266
275
  */
267
- select<const P extends string>(fields: readonly NestedAutoPath<Entity, RootAlias, Context, P>[], distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>>;
276
+ select<const P extends string>(fields: readonly NestedAutoPath<Entity, RootAlias, Context, P>[], distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>, CTEs>;
268
277
  /**
269
278
  * Creates a SELECT query, specifying the fields to retrieve.
270
279
  *
@@ -275,7 +284,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
275
284
  * qb.select('address.city');
276
285
  * ```
277
286
  */
278
- select<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P>, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>>;
287
+ select<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P>, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>, CTEs>;
279
288
  /**
280
289
  * Creates a SELECT query, specifying the fields to retrieve.
281
290
  *
@@ -292,16 +301,16 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
292
301
  * qb.select('*', true);
293
302
  * ```
294
303
  */
295
- select<const F extends Field<Entity, RootAlias, Context>>(fields: F, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<readonly [F]>, ExtractRootFields<F & string, RootAlias, Context>>;
304
+ select<const F extends Field<Entity, RootAlias, Context>>(fields: F, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<readonly [F]>, ExtractRootFields<F & string, RootAlias, Context>, CTEs>;
296
305
  /**
297
306
  * Adds fields to an existing SELECT query.
298
307
  */
299
- addSelect<const F extends Field<Entity, RootAlias, Context> | readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<F extends readonly unknown[] ? F : [F]>, Fields | ExtractRootFields<F extends readonly (infer U)[] ? U & string : F & string, RootAlias, Context>>;
300
- distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
308
+ addSelect<const F extends Field<Entity, RootAlias, Context> | readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases | ExtractRawAliases<F extends readonly unknown[] ? F : [F]>, Fields | ExtractRootFields<F extends readonly (infer U)[] ? U & string : F & string, RootAlias, Context>, CTEs>;
309
+ distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
301
310
  /** postgres only */
302
- distinctOn<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
311
+ distinctOn<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
303
312
  /** postgres only */
304
- distinctOn<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
313
+ distinctOn<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
305
314
  /**
306
315
  * Creates an INSERT query with the given data.
307
316
  *
@@ -376,29 +385,29 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
376
385
  * .where({ 'a.name': 'John' });
377
386
  * ```
378
387
  */
379
- join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases>;
388
+ join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
380
389
  /**
381
390
  * Adds a JOIN clause to the query for a subquery.
382
391
  */
383
- join<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
392
+ join<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
384
393
  /**
385
394
  * Adds an INNER JOIN clause to the query for an entity relation.
386
395
  */
387
- innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases>;
396
+ innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
388
397
  /**
389
398
  * Adds an INNER JOIN clause to the query for a subquery.
390
399
  */
391
- innerJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
392
- innerJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
400
+ innerJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
401
+ innerJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
393
402
  /**
394
403
  * Adds a LEFT JOIN clause to the query for an entity relation.
395
404
  */
396
- leftJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases>;
405
+ leftJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
397
406
  /**
398
407
  * Adds a LEFT JOIN clause to the query for a subquery.
399
408
  */
400
- leftJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
401
- leftJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
409
+ leftJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
410
+ leftJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
402
411
  /**
403
412
  * Adds a JOIN clause and automatically selects the joined entity's fields.
404
413
  * This is useful for eager loading related entities.
@@ -411,11 +420,26 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
411
420
  * .where({ 'a.name': 'John' });
412
421
  * ```
413
422
  */
414
- joinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>, ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>>;
415
- leftJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>, ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>>;
416
- leftJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>, ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]] | undefined = undefined>(field: [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>>;
417
- innerJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>, ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>>;
418
- innerJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>, ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]] | undefined = undefined>(field: [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>>;
423
+ joinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [
424
+ JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>,
425
+ ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]
426
+ ] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>, CTEs>;
427
+ leftJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [
428
+ JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>,
429
+ ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]
430
+ ] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>, CTEs>;
431
+ leftJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [
432
+ JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>,
433
+ ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]
434
+ ] | undefined = undefined>(field: [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>, CTEs>;
435
+ innerJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [
436
+ JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>,
437
+ ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]
438
+ ] | undefined = undefined>(field: Field | [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>, CTEs>;
439
+ innerJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly [
440
+ JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>,
441
+ ...JoinSelectField<JoinedEntityType<Entity, Context, Field & string>, Alias>[]
442
+ ] | undefined = undefined>(field: [Field, RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, fields?: JoinFields, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>, RawAliases, ModifyFields<Fields, RootAlias, Context, Field, Alias, JoinFields>, CTEs>;
419
443
  protected getFieldsForJoinedLoad(prop: EntityProperty<Entity>, alias: string, explicitFields?: readonly string[]): InternalField<Entity>[];
420
444
  /**
421
445
  * Apply filters to the QB where condition.
@@ -518,7 +542,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
518
542
  * qb.orderBy({ 'profile.bio': 'asc' }); // nested via dot notation
519
543
  * ```
520
544
  */
521
- orderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context, RawAliases> | ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
545
+ orderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context, RawAliases> | ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
522
546
  /**
523
547
  * Adds an ORDER BY clause to the query, replacing any existing order.
524
548
  *
@@ -531,18 +555,18 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
531
555
  * ```
532
556
  */
533
557
  orderBy<const T extends Record<string, QueryOrderKeysFlat>>(orderBy: T & {
534
- [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : (K extends RawAliases ? T[K] : never);
535
- }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
558
+ [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : K extends RawAliases ? T[K] : never;
559
+ }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
536
560
  /**
537
561
  * Adds additional ORDER BY clause without replacing existing order.
538
562
  */
539
- andOrderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context, RawAliases> | ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
563
+ andOrderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context, RawAliases> | ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
540
564
  /**
541
565
  * Adds additional ORDER BY clause without replacing existing order.
542
566
  */
543
567
  andOrderBy<const T extends Record<string, QueryOrderKeysFlat>>(orderBy: T & {
544
- [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : (K extends RawAliases ? T[K] : never);
545
- }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
568
+ [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : K extends RawAliases ? T[K] : never;
569
+ }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
546
570
  private processOrderBy;
547
571
  /** Collect custom aliases from select fields (stored as 'resolved as alias' strings by select()). */
548
572
  private getSelectAliases;
@@ -555,7 +579,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
555
579
  * .groupBy('status');
556
580
  * ```
557
581
  */
558
- groupBy<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
582
+ groupBy<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
559
583
  /**
560
584
  * Adds a GROUP BY clause to the query.
561
585
  *
@@ -565,7 +589,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
565
589
  * .groupBy('status');
566
590
  * ```
567
591
  */
568
- groupBy<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
592
+ groupBy<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
569
593
  /**
570
594
  * Adds a GROUP BY clause to the query.
571
595
  *
@@ -575,7 +599,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
575
599
  * .groupBy('status');
576
600
  * ```
577
601
  */
578
- groupBy<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P> | readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
602
+ groupBy<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P> | readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
579
603
  /**
580
604
  * Adds a HAVING clause to the query, typically used with GROUP BY.
581
605
  *
@@ -586,9 +610,9 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
586
610
  * .having({ count: { $gt: 5 } });
587
611
  * ```
588
612
  */
589
- having(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
590
- andHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
591
- orHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
613
+ having(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
614
+ andHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
615
+ orHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
592
616
  onConflict<F extends Field<Entity, RootAlias, Context>>(fields?: F | F[] | RawQueryFragment): InsertQueryBuilder<Entity, RootAlias, Context>;
593
617
  ignore(): this;
594
618
  merge<const P extends string>(data: readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): this;
@@ -607,7 +631,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
607
631
  * qb.select('*').limit(10, 20); // 10 results starting from offset 20
608
632
  * ```
609
633
  */
610
- limit(limit?: number, offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
634
+ limit(limit?: number, offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
611
635
  /**
612
636
  * Sets an OFFSET clause to skip a number of results.
613
637
  *
@@ -616,7 +640,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
616
640
  * qb.select('*').limit(10).offset(20); // Results 21-30
617
641
  * ```
618
642
  */
619
- offset(offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
643
+ offset(offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
620
644
  withSchema(schema?: string): this;
621
645
  setLockMode(mode?: LockMode, tables?: string[]): this;
622
646
  setFlushMode(flushMode?: FlushMode): this;
@@ -646,12 +670,17 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
646
670
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
647
671
  * Allows setting a main string alias of the selection data.
648
672
  */
649
- from<Entity extends object>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
673
+ from<Entity extends object>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
650
674
  /**
651
675
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
652
676
  * Allows setting a main string alias of the selection data.
653
677
  */
654
- from<Entity extends object>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
678
+ from<Entity extends object>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
679
+ /**
680
+ * Specifies a CTE name as the FROM source, with full type safety.
681
+ * The entity type is inferred from the CTE definition passed to `.with()`.
682
+ */
683
+ from<Name extends string & keyof CTEs, Alias extends string = Name>(target: Name, aliasName?: Alias): SelectQueryBuilder<CTEs[Name], Alias, never, never, never, '*', CTEs>;
655
684
  getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
656
685
  /**
657
686
  * Returns the query with parameters as wildcards.
@@ -750,7 +779,80 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
750
779
  * You can provide the target entity name as the first parameter and use the second parameter to point to an existing property to infer its field name.
751
780
  */
752
781
  as<T>(targetEntity: EntityName<T>, alias: EntityKey<T>): NativeQueryBuilder;
753
- clone(reset?: boolean | string[], preserve?: string[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
782
+ /**
783
+ * Combines the current query with one or more other queries using `UNION ALL`.
784
+ * All queries must select the same columns. Returns a `QueryBuilder` that
785
+ * can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
786
+ * `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
787
+ *
788
+ * ```ts
789
+ * const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
790
+ * const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
791
+ * const qb3 = em.createQueryBuilder(Employee).select('id').where(condition3);
792
+ * const subquery = qb1.unionAll(qb2, qb3);
793
+ *
794
+ * const results = await em.find(Employee, { id: { $in: subquery } });
795
+ * ```
796
+ */
797
+ unionAll(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
798
+ /**
799
+ * Combines the current query with one or more other queries using `UNION` (with deduplication).
800
+ * All queries must select the same columns. Returns a `QueryBuilder` that
801
+ * can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
802
+ * `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
803
+ *
804
+ * ```ts
805
+ * const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
806
+ * const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
807
+ * const subquery = qb1.union(qb2);
808
+ *
809
+ * const results = await em.find(Employee, { id: { $in: subquery } });
810
+ * ```
811
+ */
812
+ union(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
813
+ private buildUnionQuery;
814
+ /**
815
+ * Adds a Common Table Expression (CTE) to the query.
816
+ * When a `QueryBuilder` is passed, its entity type is tracked for type-safe `from()`.
817
+ *
818
+ * @example
819
+ * ```ts
820
+ * const recentBooks = em.createQueryBuilder(Book, 'b').select('*').where({ ... });
821
+ * const qb = em.createQueryBuilder(Author, 'a')
822
+ * .with('recent_books', recentBooks)
823
+ * .select('*')
824
+ * .from('recent_books', 'rb'); // entity type inferred as Book
825
+ * ```
826
+ */
827
+ with<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, Q extends QueryBuilder<infer T> ? T : object>>;
828
+ /**
829
+ * Adds a Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
830
+ * The CTE name is tracked but without entity type inference — use `from()` to query from it.
831
+ */
832
+ with<Name extends string>(name: Name, query: NativeQueryBuilder | RawQueryFragment, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, object>>;
833
+ /**
834
+ * Adds a recursive Common Table Expression (CTE) to the query.
835
+ * When a `QueryBuilder` is passed, its entity type is tracked for type-safe `from()`.
836
+ *
837
+ * @example
838
+ * ```ts
839
+ * const base = em.createQueryBuilder(Category).select('*').where({ parent: null });
840
+ * const rec = em.createQueryBuilder(Category, 'c').select('c.*')
841
+ * .leftJoin('c.parent', 'ct', { id: sql.ref('c.parentId') });
842
+ * const qb = em.createQueryBuilder(Category)
843
+ * .withRecursive('category_tree', base.unionAll(rec))
844
+ * .select('*')
845
+ * .from('category_tree', 'ct'); // entity type inferred as Category
846
+ * ```
847
+ */
848
+ withRecursive<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, Q extends QueryBuilder<infer T> ? T : object>>;
849
+ /**
850
+ * Adds a recursive Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
851
+ * The CTE name is tracked but without entity type inference — use `from()` to query from it.
852
+ */
853
+ withRecursive<Name extends string>(name: Name, query: NativeQueryBuilder | RawQueryFragment, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, object>>;
854
+ private addCte;
855
+ clone(reset?: boolean | string[], preserve?: string[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
754
856
  /**
755
857
  * Sets logger context for this query builder.
756
858
  */
@@ -836,10 +938,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
836
938
  private wrapModifySubQuery;
837
939
  private getSchema;
838
940
  /** @internal */
839
- createAlias<U = unknown>(entityName: EntityName<U>, aliasName: string, subQuery?: NativeQueryBuilder): Alias<U>;
941
+ createAlias<U = unknown>(entityName: EntityName<U>, aliasName: string, subQuery?: NativeQueryBuilder | RawQueryFragment): Alias<U>;
840
942
  private createMainAlias;
841
943
  private fromSubQuery;
842
944
  private fromEntityName;
945
+ private fromRawTable;
843
946
  private createQueryBuilderHelper;
844
947
  private ensureFromClause;
845
948
  private ensureNotFinalized;
@@ -848,10 +951,36 @@ export interface RunQueryBuilder<Entity extends object, RootAlias extends string
848
951
  where(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
849
952
  execute<Result = QueryResult<Entity>>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
850
953
  }
851
- export interface SelectQueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never, RawAliases extends string = never, Fields extends string = '*'> extends QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields> {
852
- execute<Result = Entity[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
853
- execute<Result = Entity[]>(method: 'all', mapResults?: boolean): Promise<Result>;
854
- execute<Result = Entity>(method: 'get', mapResults?: boolean): Promise<Result>;
954
+ /**
955
+ * @internal Optimized DTO type for execute().
956
+ * Bypasses the double mapped type of EntityDTO<Loaded<T, H, F>> by using DirectDTO
957
+ * which only iterates selected keys instead of all entity keys.
958
+ *
959
+ * - Wildcard, no joins: EntityDTO<T>
960
+ * - Selected fields, no joins: DirectDTO<T, F> (~132x faster than Pick<EntityDTO<T>, F>)
961
+ * - Wildcard + single-level join: Omit<EntityDTO<T>> + override populated relations
962
+ * - Selected fields + single-level join: DirectDTO for root + DirectDTO for joined (~60x faster)
963
+ * - Wildcard + nested joins: uses SerializeDTO<T, H> (~40x faster than EntityDTO<Loaded<T, H>>)
964
+ * - Fields + nested joins: falls back to EntityDTO<Loaded<T, H, F>>
965
+ */
966
+ type DirectDTO<T, F extends keyof T> = {
967
+ [K in F]: EntityDTOProp<T, NonNullable<T[K]>> | Extract<T[K], null | undefined>;
968
+ };
969
+ type PopulatedDTO<T, K extends keyof T> = NonNullable<T[K]> extends Collection<infer U> ? EntityDTOFlat<U & object>[] : EntityDTOFlat<ExpandProperty<T[K]>>;
970
+ type SubFields<F extends string, Rel extends string> = F extends `${Rel}.${infer Sub}` ? Sub : never;
971
+ type RootFields<F extends string, H extends string> = F extends `${string}.${string}` ? F extends `${H}.${string}` ? never : F : F;
972
+ type JoinDTO<T, K extends keyof T, F extends string> = NonNullable<T[K]> extends Collection<infer U> ? SubFields<F, K & string> extends never ? EntityDTOProp<T, Collection<U>> : DirectDTO<U, (SubFields<F, K & string> | PrimaryProperty<U>) & keyof U>[] : SubFields<F, K & string> extends never ? EntityDTOProp<T, T[K]> : DirectDTO<NonNullable<T[K]>, (SubFields<F, K & string> | PrimaryProperty<NonNullable<T[K]>>) & keyof NonNullable<T[K]>> | Extract<T[K], null | undefined>;
973
+ type ExecuteDTO<T, H extends string, F extends string> = [H] extends [never] ? [F] extends ['*'] ? EntityDTOFlat<T> : DirectDTO<T, F & keyof T> : [F] extends ['*'] ? true extends (H extends `${string}.${string}` ? true : false) ? SerializeDTO<T, H> : Omit<EntityDTOFlat<T>, H & keyof EntityDTOFlat<T>> & {
974
+ [K in H & keyof T as K & keyof EntityDTOFlat<T>]: PopulatedDTO<T, K> | Extract<T[K], null | undefined>;
975
+ } : true extends (H extends `${string}.${string}` ? true : false) ? EntityDTOFlat<Loaded<T, H, F>> : DirectDTO<T, (RootFields<F, H> | PrimaryProperty<T>) & keyof T> & {
976
+ [K in H & keyof T]: JoinDTO<T, K, F>;
977
+ };
978
+ /** Shorthand for `QueryBuilder` with all generic parameters set to `any`. */
979
+ export type AnyQueryBuilder<T extends object = AnyEntity> = QueryBuilder<T, any, any, any, any, any, any>;
980
+ export interface SelectQueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never, RawAliases extends string = never, Fields extends string = '*', CTEs extends Record<string, object> = {}> extends QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs> {
981
+ execute<Result = ExecuteDTO<Entity, Hint, Fields>[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
982
+ execute<Result = ExecuteDTO<Entity, Hint, Fields>[]>(method: 'all', mapResults?: boolean): Promise<Result>;
983
+ execute<Result = ExecuteDTO<Entity, Hint, Fields>>(method: 'get', mapResults?: boolean): Promise<Result>;
855
984
  execute<Result = QueryResult<Entity>>(method: 'run', mapResults?: boolean): Promise<Result>;
856
985
  }
857
986
  export interface CountQueryBuilder<Entity extends object> extends QueryBuilder<Entity, any, any> {