@mikro-orm/sql 7.0.0-dev.98 → 7.0.0-rc.0

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 (64) hide show
  1. package/AbstractSqlConnection.d.ts +6 -7
  2. package/AbstractSqlConnection.js +27 -24
  3. package/AbstractSqlDriver.d.ts +82 -23
  4. package/AbstractSqlDriver.js +584 -184
  5. package/AbstractSqlPlatform.d.ts +3 -4
  6. package/AbstractSqlPlatform.js +0 -4
  7. package/PivotCollectionPersister.d.ts +5 -0
  8. package/PivotCollectionPersister.js +30 -12
  9. package/SqlEntityManager.d.ts +2 -2
  10. package/dialects/mysql/{MySqlPlatform.d.ts → BaseMySqlPlatform.d.ts} +3 -2
  11. package/dialects/mysql/{MySqlPlatform.js → BaseMySqlPlatform.js} +5 -1
  12. package/dialects/mysql/MySqlSchemaHelper.d.ts +12 -1
  13. package/dialects/mysql/MySqlSchemaHelper.js +97 -6
  14. package/dialects/mysql/index.d.ts +1 -2
  15. package/dialects/mysql/index.js +1 -2
  16. package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +106 -0
  17. package/dialects/postgresql/BasePostgreSqlPlatform.js +350 -0
  18. package/dialects/postgresql/FullTextType.d.ts +14 -0
  19. package/dialects/postgresql/FullTextType.js +59 -0
  20. package/dialects/postgresql/PostgreSqlExceptionConverter.d.ts +8 -0
  21. package/dialects/postgresql/PostgreSqlExceptionConverter.js +47 -0
  22. package/dialects/postgresql/PostgreSqlSchemaHelper.d.ts +90 -0
  23. package/dialects/postgresql/PostgreSqlSchemaHelper.js +732 -0
  24. package/dialects/postgresql/index.d.ts +3 -0
  25. package/dialects/postgresql/index.js +3 -0
  26. package/dialects/sqlite/BaseSqliteConnection.d.ts +1 -0
  27. package/dialects/sqlite/BaseSqliteConnection.js +14 -1
  28. package/dialects/sqlite/BaseSqlitePlatform.d.ts +6 -0
  29. package/dialects/sqlite/BaseSqlitePlatform.js +12 -0
  30. package/dialects/sqlite/SqliteSchemaHelper.d.ts +25 -0
  31. package/dialects/sqlite/SqliteSchemaHelper.js +145 -19
  32. package/dialects/sqlite/index.d.ts +0 -1
  33. package/dialects/sqlite/index.js +0 -1
  34. package/package.json +5 -6
  35. package/plugin/transformer.d.ts +1 -1
  36. package/plugin/transformer.js +1 -1
  37. package/query/CriteriaNode.d.ts +9 -5
  38. package/query/CriteriaNode.js +16 -15
  39. package/query/CriteriaNodeFactory.d.ts +6 -6
  40. package/query/CriteriaNodeFactory.js +33 -31
  41. package/query/NativeQueryBuilder.d.ts +3 -2
  42. package/query/NativeQueryBuilder.js +1 -2
  43. package/query/ObjectCriteriaNode.js +50 -35
  44. package/query/QueryBuilder.d.ts +548 -79
  45. package/query/QueryBuilder.js +537 -159
  46. package/query/QueryBuilderHelper.d.ts +22 -14
  47. package/query/QueryBuilderHelper.js +158 -69
  48. package/query/ScalarCriteriaNode.js +2 -2
  49. package/query/raw.d.ts +11 -3
  50. package/query/raw.js +1 -2
  51. package/schema/DatabaseSchema.d.ts +15 -2
  52. package/schema/DatabaseSchema.js +143 -15
  53. package/schema/DatabaseTable.d.ts +12 -0
  54. package/schema/DatabaseTable.js +91 -31
  55. package/schema/SchemaComparator.d.ts +8 -0
  56. package/schema/SchemaComparator.js +126 -3
  57. package/schema/SchemaHelper.d.ts +26 -3
  58. package/schema/SchemaHelper.js +98 -11
  59. package/schema/SqlSchemaGenerator.d.ts +10 -0
  60. package/schema/SqlSchemaGenerator.js +137 -9
  61. package/tsconfig.build.tsbuildinfo +1 -0
  62. package/typings.d.ts +74 -36
  63. package/dialects/postgresql/PostgreSqlTableCompiler.d.ts +0 -1
  64. package/dialects/postgresql/PostgreSqlTableCompiler.js +0 -1
@@ -1,9 +1,9 @@
1
- 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';
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';
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
- import type { Field, ICriteriaNodeProcessOptions, JoinOptions } from '../typings.js';
6
+ import type { ICriteriaNodeProcessOptions, InternalField, JoinOptions } from '../typings.js';
7
7
  import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
8
8
  import { NativeQueryBuilder } from './NativeQueryBuilder.js';
9
9
  export interface ExecuteOptions {
@@ -34,26 +34,101 @@ export interface QBStreamOptions {
34
34
  */
35
35
  rawResults?: boolean;
36
36
  }
37
- type AnyString = string & {};
38
- type Compute<T> = {
39
- [K in keyof T]: T[K];
40
- } & {};
41
37
  type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
42
38
  type GetAlias<T extends string> = T extends `${infer A}.${string}` ? A : never;
43
39
  type GetPropName<T extends string> = T extends `${string}.${infer P}` ? P : T;
44
40
  type AppendToHint<Parent extends string, Child extends string> = `${Parent}.${Child}`;
41
+ /**
42
+ * Context tuple format: [Path, Alias, Type, Select]
43
+ * - Path: The relation path from root entity (e.g., 'books', 'books.author')
44
+ * - Alias: The SQL alias used in the query (e.g., 'b', 'a1')
45
+ * - Type: The entity type of the joined relation
46
+ * - Select: Whether this join was created via joinAndSelect (affects Fields tracking)
47
+ *
48
+ * Example: After `qb.leftJoin('a.books', 'b')`, Context becomes:
49
+ * { b: ['books', 'b', Book, false] }
50
+ */
45
51
  type AddToContext<Type extends object, Context, Field extends string, Alias extends string, Select extends boolean> = {
46
52
  [K in Alias]: [GetPath<Context, Field>, K, ExpandProperty<Type[GetPropName<Field> & keyof Type]>, Select];
47
53
  };
48
54
  type GetPath<Context, Field extends string> = GetAlias<Field> extends infer Alias ? IsNever<Alias> extends true ? GetPropName<Field> : Alias extends keyof Context ? Context[Alias] extends [infer Path, ...any[]] ? AppendToHint<Path & string, GetPropName<Field>> : GetPropName<Field> : GetPropName<Field> : GetPropName<Field>;
49
- type GetType<Type extends object, Context, Field extends string> = GetAlias<Field> extends infer Alias ? IsNever<Alias> extends true ? Type : Alias extends keyof Context ? Context[Alias] extends [string, string, infer PropType] ? PropType & object : Type : Type : Type;
55
+ type GetType<Type extends object, Context, Field extends string> = GetAlias<Field> extends infer Alias ? IsNever<Alias> extends true ? Type : Alias extends keyof Context ? Context[Alias] extends [string, string, infer PropType, any] ? PropType & object : Type : Type : Type;
50
56
  type AddToHint<RootAlias, Context, Field extends string, Select extends boolean = false> = Select extends true ? GetAlias<Field> extends infer Alias ? IsNever<Alias> extends true ? GetPropName<Field> : Alias extends RootAlias ? GetPropName<Field> : Alias extends keyof Context ? Context[Alias] extends [infer Path, ...any[]] ? AppendToHint<Path & string, GetPropName<Field>> : GetPropName<Field> : GetPropName<Field> : GetPropName<Field> : never;
51
57
  export type ModifyHint<RootAlias, Context, Hint extends string, Field extends string, Select extends boolean = false> = Hint | AddToHint<RootAlias, Context, Field, Select>;
52
- export type ModifyContext<Entity extends object, Context, Field extends string, Alias extends string, Select extends boolean = false> = Compute<IsNever<Context> extends true ? AddToContext<GetType<Entity, object, Field>, object, Field, Alias, Select> : Context & AddToContext<GetType<Entity, Context, Field>, Context, Field, Alias, Select>>;
58
+ export type ModifyContext<Entity extends object, Context, Field extends string, Alias extends string, Select extends boolean = false> = IsNever<Context> extends true ? AddToContext<GetType<Entity, object, Field>, object, Field, Alias, Select> : Context & AddToContext<GetType<Entity, Context, Field>, Context, Field, Alias, Select>;
59
+ type StripRootAlias<F extends string, RootAlias extends string, Context = never> = F extends `${RootAlias}.${infer Field}` ? Field : F extends `${infer Alias}.${string}` ? Alias extends AliasNames<Context> ? never : F : F;
60
+ type ExtractRootFields<Fields, RootAlias extends string, Context = never> = [Fields] extends ['*'] ? '*' : Fields extends `${RootAlias}.*` ? '*' : Fields extends string ? StripRootAlias<Fields, RootAlias, Context> : never;
61
+ type PrefixWithPath<Path extends string, Field extends string> = `${Path}.${Field}`;
62
+ type StripJoinAlias<F extends string, Alias extends string> = F extends `${Alias}.${infer Field}` ? Field : F;
63
+ type AddJoinFields<RootAlias, Context, Field extends string, Alias extends string, JoinFields extends readonly string[]> = JoinFields extends readonly (infer F)[] ? F extends string ? PrefixWithPath<AddToHint<RootAlias, Context, Field, true> & string, StripJoinAlias<F, Alias>> : never : never;
64
+ export type ModifyFields<CurrentFields extends string, RootAlias, Context, Field extends string, Alias extends string, JoinFields extends readonly string[] | undefined> = JoinFields extends readonly string[] ? CurrentFields | AddJoinFields<RootAlias, Context, Field, Alias, JoinFields> : CurrentFields;
53
65
  type EntityRelations<T> = EntityKey<T, true>;
54
- type AddAliasesFromContext<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? `${Alias & string}.${EntityRelations<Type & {}>}` : never : never : never;
55
- export type QBField<Entity, RootAlias extends string, Context> = (EntityRelations<Entity> | `${RootAlias}.${EntityRelations<Entity>}` | AddAliasesFromContext<Context>) & {} | AnyString;
56
- type EntityKeyOrString<Entity extends object = AnyEntity> = AnyString | keyof Entity;
66
+ type JoinedEntityType<Entity extends object, Context, Field extends string> = ExpandProperty<GetType<Entity, Context, Field>[GetPropName<Field> & keyof GetType<Entity, Context, Field>]>;
67
+ type AliasNames<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, any, any] ? Alias & string : never : never : never;
68
+ type ContextRelationKeys<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? `${Alias & string}.${EntityRelations<Type & object>}` : never : never : never;
69
+ export type QBField<Entity, RootAlias extends string, Context> = EntityRelations<Entity> | `${RootAlias}.${EntityRelations<Entity>}` | ([Context] extends [never] ? never : ContextRelationKeys<Context>);
70
+ type ContextFieldKeys<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? `${Alias & string}.${keyof Type & string}` : never : never : never;
71
+ export type Field<Entity, RootAlias extends string = never, Context = never> = EntityKey<Entity> | (IsNever<RootAlias> extends true ? never : `${RootAlias}.${EntityKey<Entity>}` | `${RootAlias}.*`) | ([Context] extends [never] ? never : ContextFieldKeys<Context> | `${AliasNames<Context>}.*`) | '*' | QueryBuilder<any> | NativeQueryBuilder | RawQueryFragment<any> | (RawQueryFragment & symbol);
72
+ type RootAliasOrderKeys<RootAlias extends string, Entity> = {
73
+ [K in `${RootAlias}.${EntityKey<Entity>}`]?: QueryOrderKeysFlat;
74
+ };
75
+ type ContextOrderKeys<Context> = {
76
+ [K in ContextFieldKeys<Context>]?: QueryOrderKeysFlat;
77
+ };
78
+ export type ContextOrderByMap<Entity, RootAlias extends string = never, Context = never> = QueryOrderMap<Entity> | ((IsNever<RootAlias> extends true ? {} : RootAliasOrderKeys<RootAlias, Entity>) & ([Context] extends [never] ? {} : ContextOrderKeys<Context>));
79
+ 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;
80
+ 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;
81
+ type NestedAutoPath<Entity, RootAlias extends string, Context, P extends string> = P extends `${string}:ref` ? never : AliasedPath<RootAlias, Entity, P> | ContextAliasedPath<Context, P> | AutoPath<Entity, P, `${PopulatePath.ALL}`>;
82
+ type AliasedObjectQuery<Entity extends object, Alias extends string> = {
83
+ [K in EntityKey<Entity> as `${Alias}.${K}`]?: ObjectQuery<Entity>[K];
84
+ };
85
+ type JoinCondition<JoinedEntity extends object, Alias extends string> = ObjectQuery<JoinedEntity> | AliasedObjectQuery<JoinedEntity, Alias>;
86
+ type RawJoinCondition = {
87
+ [key: string]: FilterValue<Scalar> | RawQueryFragment;
88
+ };
89
+ type ExtractRawAliasFromField<F> = F extends RawQueryFragment<infer A> ? (A extends string ? A : never) : never;
90
+ type ExtractRawAliasesFromTuple<T extends readonly unknown[]> = T extends readonly [infer Head, ...infer Tail] ? ExtractRawAliasFromField<Head> | ExtractRawAliasesFromTuple<Tail> : never;
91
+ type ExtractRawAliases<Fields> = Fields extends readonly unknown[] ? ExtractRawAliasesFromTuple<Fields> : ExtractRawAliasFromField<Fields>;
92
+ type FlatOperatorMap = {
93
+ $eq?: Scalar | readonly Scalar[] | Subquery | null;
94
+ $ne?: Scalar | readonly Scalar[] | Subquery | null;
95
+ $in?: readonly Scalar[] | Raw | Subquery;
96
+ $nin?: readonly Scalar[] | Raw | Subquery;
97
+ $gt?: Scalar | Subquery;
98
+ $gte?: Scalar | Subquery;
99
+ $lt?: Scalar | Subquery;
100
+ $lte?: Scalar | Subquery;
101
+ $like?: string;
102
+ $re?: string;
103
+ $ilike?: string;
104
+ $fulltext?: string;
105
+ $overlap?: readonly string[] | string | object;
106
+ $contains?: readonly string[] | string | object;
107
+ $contained?: readonly string[] | string | object;
108
+ $exists?: boolean;
109
+ $hasKey?: string;
110
+ $hasKeys?: readonly string[];
111
+ $hasSomeKeys?: readonly string[];
112
+ };
113
+ type AliasedFilterValue = Scalar | FlatOperatorMap | readonly Scalar[] | null | QueryBuilder<any> | NativeQueryBuilder;
114
+ type TypedAliasedFilterValue<T> = FilterValue<ExpandProperty<T>> | QueryBuilder<any> | NativeQueryBuilder;
115
+ type RootAliasFilterKeys<RootAlias extends string, Entity> = {
116
+ [K in EntityKey<Entity> as `${RootAlias}.${K}`]?: TypedAliasedFilterValue<Entity[K]>;
117
+ };
118
+ type ContextFilterKeys<Context> = {
119
+ [K in ContextFieldKeys<Context>]?: AliasedFilterValue;
120
+ };
121
+ type RawFilterKeys<RawAliases extends string> = {
122
+ [K in RawAliases]?: AliasedFilterValue;
123
+ };
124
+ type NestedFilterCondition<Entity, RootAlias extends string, Context, RawAliases extends string> = ObjectQuery<Entity> & (IsNever<RootAlias> extends true ? {} : string extends RootAlias ? {} : RootAliasFilterKeys<RootAlias, Entity>) & ([Context] extends [never] ? {} : ContextFilterKeys<Context>) & (IsNever<RawAliases> extends true ? {} : string extends RawAliases ? {} : RawFilterKeys<RawAliases>);
125
+ type GroupOperators<RootAlias extends string, Context, Entity, RawAliases extends string> = {
126
+ $and?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>[];
127
+ $or?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>[];
128
+ $not?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>;
129
+ };
130
+ export type AliasedFilterCondition<RootAlias extends string, Context, Entity, RawAliases extends string = never> = (IsNever<RootAlias> extends true ? {} : string extends RootAlias ? {} : RootAliasFilterKeys<RootAlias, Entity>) & ([Context] extends [never] ? {} : ContextFilterKeys<Context>) & (IsNever<RawAliases> extends true ? {} : string extends RawAliases ? {} : RawFilterKeys<RawAliases>) & GroupOperators<RootAlias, Context, Entity, RawAliases>;
131
+ export type QBFilterQuery<Entity, RootAlias extends string = never, Context = never, RawAliases extends string = never> = FilterObject<Entity> & AliasedFilterCondition<RootAlias, Context, Entity, RawAliases>;
57
132
  /**
58
133
  * SQL query builder with fluent interface.
59
134
  *
@@ -73,13 +148,14 @@ type EntityKeyOrString<Entity extends object = AnyEntity> = AnyString | keyof En
73
148
  * const publisher = await qb.getSingleResult();
74
149
  * ```
75
150
  */
76
- export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never> {
151
+ 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 {
77
152
  protected readonly metadata: MetadataStorage;
78
153
  protected readonly driver: AbstractSqlDriver;
79
154
  protected readonly context?: Transaction | undefined;
80
155
  protected connectionType?: ConnectionType | undefined;
81
156
  protected em?: SqlEntityManager | undefined;
82
157
  protected loggerContext?: (LoggingOptions & Dictionary) | undefined;
158
+ readonly __subquery: true;
83
159
  get mainAlias(): Alias<Entity>;
84
160
  get alias(): string;
85
161
  get helper(): QueryBuilderHelper;
@@ -87,7 +163,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
87
163
  /** @internal */
88
164
  _type?: QueryType;
89
165
  /** @internal */
90
- _fields?: Field<Entity>[];
166
+ _fields?: InternalField<Entity>[];
91
167
  /** @internal */
92
168
  _populate: PopulateOptions<Entity>[];
93
169
  /** @internal */
@@ -98,8 +174,6 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
98
174
  __populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
99
175
  /** @internal */
100
176
  _populateMap: Dictionary<string>;
101
- /** @internal */
102
- readonly rawFragments: Set<string>;
103
177
  protected aliasCounter: number;
104
178
  protected flags: Set<QueryFlag>;
105
179
  protected finalized: boolean;
@@ -110,9 +184,9 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
110
184
  protected _cond: Dictionary;
111
185
  protected _data: Dictionary;
112
186
  protected _orderBy: QueryOrderMap<Entity>[];
113
- protected _groupBy: Field<Entity>[];
187
+ protected _groupBy: InternalField<Entity>[];
114
188
  protected _having: Dictionary;
115
- protected _returning?: Field<Entity>[];
189
+ protected _returning?: InternalField<Entity>[];
116
190
  protected _onConflict?: OnConflictClause<Entity>[];
117
191
  protected _limit?: number;
118
192
  protected _offset?: number;
@@ -128,6 +202,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
128
202
  protected subQueries: Dictionary<string>;
129
203
  protected _mainAlias?: Alias<Entity>;
130
204
  protected _aliases: Dictionary<Alias<any>>;
205
+ protected _tptAlias: Dictionary<string>;
131
206
  protected _helper?: QueryBuilderHelper;
132
207
  protected _query?: {
133
208
  sql?: string;
@@ -135,36 +210,202 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
135
210
  qb: NativeQueryBuilder;
136
211
  };
137
212
  protected readonly platform: AbstractSqlPlatform;
213
+ private tptJoinsApplied;
214
+ private readonly autoJoinedPaths;
138
215
  /**
139
216
  * @internal
140
217
  */
141
- constructor(entityName: EntityName<Entity> | QueryBuilder<Entity, any, any>, metadata: MetadataStorage, driver: AbstractSqlDriver, context?: Transaction | undefined, alias?: string, connectionType?: ConnectionType | undefined, em?: SqlEntityManager | undefined, loggerContext?: (LoggingOptions & Dictionary) | undefined);
142
- select(fields: Field<Entity> | Field<Entity>[], distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
143
- addSelect(fields: Field<Entity> | Field<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
144
- distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
218
+ constructor(entityName: EntityName<Entity> | QueryBuilder<Entity, any, any, any>, metadata: MetadataStorage, driver: AbstractSqlDriver, context?: Transaction | undefined, alias?: string, connectionType?: ConnectionType | undefined, em?: SqlEntityManager | undefined, loggerContext?: (LoggingOptions & Dictionary) | undefined);
219
+ /**
220
+ * Creates a SELECT query, specifying the fields to retrieve.
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * // Select specific fields
225
+ * const qb = em.createQueryBuilder(User, 'u');
226
+ * qb.select(['u.id', 'u.name', 'u.email']);
227
+ *
228
+ * // Select with raw expressions
229
+ * qb.select([raw('count(*) as total')]);
230
+ *
231
+ * // Select with distinct
232
+ * qb.select('*', true);
233
+ * ```
234
+ */
235
+ 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>>;
236
+ /**
237
+ * Creates a SELECT query, specifying the fields to retrieve.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * // Select specific fields
242
+ * const qb = em.createQueryBuilder(User, 'u');
243
+ * qb.select(['u.id', 'u.name', 'u.email']);
244
+ *
245
+ * // Select with raw expressions
246
+ * qb.select([raw('count(*) as total')]);
247
+ *
248
+ * // Select with distinct
249
+ * qb.select('*', true);
250
+ * ```
251
+ */
252
+ select<const P extends string>(fields: readonly NestedAutoPath<Entity, RootAlias, Context, P>[], distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>>;
253
+ /**
254
+ * Creates a SELECT query, specifying the fields to retrieve.
255
+ *
256
+ * @example
257
+ * ```ts
258
+ * // Select specific fields with nested paths (e.g., for embedded properties)
259
+ * const qb = em.createQueryBuilder(User, 'u');
260
+ * qb.select('address.city');
261
+ * ```
262
+ */
263
+ select<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P>, distinct?: boolean): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>>;
264
+ /**
265
+ * Creates a SELECT query, specifying the fields to retrieve.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * // Select specific fields
270
+ * const qb = em.createQueryBuilder(User, 'u');
271
+ * qb.select(['u.id', 'u.name', 'u.email']);
272
+ *
273
+ * // Select with raw expressions
274
+ * qb.select([raw('count(*) as total')]);
275
+ *
276
+ * // Select with distinct
277
+ * qb.select('*', true);
278
+ * ```
279
+ */
280
+ 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>>;
281
+ /**
282
+ * Adds fields to an existing SELECT query.
283
+ */
284
+ 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>>;
285
+ distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
145
286
  /** postgres only */
146
- distinctOn(fields: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
147
- insert(data: RequiredEntityData<Entity> | RequiredEntityData<Entity>[]): InsertQueryBuilder<Entity>;
148
- update(data: EntityData<Entity>): UpdateQueryBuilder<Entity>;
149
- delete(cond?: QBFilterQuery): DeleteQueryBuilder<Entity>;
287
+ distinctOn<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
288
+ /** postgres only */
289
+ distinctOn<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
290
+ /**
291
+ * Creates an INSERT query with the given data.
292
+ *
293
+ * @example
294
+ * ```ts
295
+ * await em.createQueryBuilder(User)
296
+ * .insert({ name: 'John', email: 'john@example.com' })
297
+ * .execute();
298
+ *
299
+ * // Bulk insert
300
+ * await em.createQueryBuilder(User)
301
+ * .insert([{ name: 'John' }, { name: 'Jane' }])
302
+ * .execute();
303
+ * ```
304
+ */
305
+ insert(data: RequiredEntityData<Entity> | RequiredEntityData<Entity>[]): InsertQueryBuilder<Entity, RootAlias, Context>;
306
+ /**
307
+ * Creates an UPDATE query with the given data.
308
+ * Use `where()` to specify which rows to update.
309
+ *
310
+ * @example
311
+ * ```ts
312
+ * await em.createQueryBuilder(User)
313
+ * .update({ name: 'John Doe' })
314
+ * .where({ id: 1 })
315
+ * .execute();
316
+ * ```
317
+ */
318
+ update(data: EntityData<Entity>): UpdateQueryBuilder<Entity, RootAlias, Context>;
319
+ /**
320
+ * Creates a DELETE query.
321
+ * Use `where()` to specify which rows to delete.
322
+ *
323
+ * @example
324
+ * ```ts
325
+ * await em.createQueryBuilder(User)
326
+ * .delete()
327
+ * .where({ id: 1 })
328
+ * .execute();
329
+ *
330
+ * // Or pass the condition directly
331
+ * await em.createQueryBuilder(User)
332
+ * .delete({ isActive: false })
333
+ * .execute();
334
+ * ```
335
+ */
336
+ delete(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): DeleteQueryBuilder<Entity, RootAlias, Context>;
337
+ /**
338
+ * Creates a TRUNCATE query to remove all rows from the table.
339
+ */
150
340
  truncate(): TruncateQueryBuilder<Entity>;
151
- count(field?: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[], distinct?: boolean): CountQueryBuilder<Entity>;
152
- join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: QBFilterQuery, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>>;
153
- innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: QBFilterQuery, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>>;
154
- innerJoinLateral(field: RawQueryFragment | QueryBuilder<any>, alias: string, cond: QBFilterQuery, schema?: string): this;
155
- leftJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: QBFilterQuery, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>>;
156
- leftJoinLateral(field: RawQueryFragment | QueryBuilder<any>, alias: string, cond: QBFilterQuery, schema?: string): this;
157
- joinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | [field: Field, qb: RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, type?: JoinType, path?: string, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
158
- leftJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | [field: Field, qb: RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
159
- leftJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: [field: Field, qb: RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
160
- innerJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field | [field: Field, qb: RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
161
- innerJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: [field: Field, qb: RawQueryFragment | QueryBuilder<any>], alias: Alias, cond?: QBFilterQuery, fields?: string[], schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field, true> & {}, ModifyContext<Entity, Context, Field, Alias, true>>;
162
- protected getFieldsForJoinedLoad(prop: EntityProperty<Entity>, alias: string, explicitFields?: string[]): Field<Entity>[];
341
+ /**
342
+ * Creates a COUNT query to count matching rows.
343
+ *
344
+ * @example
345
+ * ```ts
346
+ * const count = await em.createQueryBuilder(User)
347
+ * .count()
348
+ * .where({ isActive: true })
349
+ * .execute('get');
350
+ * ```
351
+ */
352
+ count<F extends Field<Entity, RootAlias, Context>>(field?: F | F[], distinct?: boolean): CountQueryBuilder<Entity>;
353
+ /**
354
+ * Adds a JOIN clause to the query for an entity relation.
355
+ *
356
+ * @example
357
+ * ```ts
358
+ * const qb = em.createQueryBuilder(Book, 'b');
359
+ * qb.select('*')
360
+ * .join('b.author', 'a')
361
+ * .where({ 'a.name': 'John' });
362
+ * ```
363
+ */
364
+ 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>;
365
+ /**
366
+ * Adds a JOIN clause to the query for a subquery.
367
+ */
368
+ 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>;
369
+ /**
370
+ * Adds an INNER JOIN clause to the query for an entity relation.
371
+ */
372
+ 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>;
373
+ /**
374
+ * Adds an INNER JOIN clause to the query for a subquery.
375
+ */
376
+ innerJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
377
+ innerJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
378
+ /**
379
+ * Adds a LEFT JOIN clause to the query for an entity relation.
380
+ */
381
+ 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>;
382
+ /**
383
+ * Adds a LEFT JOIN clause to the query for a subquery.
384
+ */
385
+ leftJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
386
+ leftJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases>;
387
+ /**
388
+ * Adds a JOIN clause and automatically selects the joined entity's fields.
389
+ * This is useful for eager loading related entities.
390
+ *
391
+ * @example
392
+ * ```ts
393
+ * const qb = em.createQueryBuilder(Book, 'b');
394
+ * qb.select('*')
395
+ * .joinAndSelect('b.author', 'a')
396
+ * .where({ 'a.name': 'John' });
397
+ * ```
398
+ */
399
+ joinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly string[] | 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>>;
400
+ leftJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly string[] | 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>>;
401
+ leftJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly string[] | 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>>;
402
+ innerJoinAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly string[] | 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>>;
403
+ innerJoinLateralAndSelect<Field extends QBField<Entity, RootAlias, Context>, Alias extends string, const JoinFields extends readonly string[] | 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>>;
404
+ protected getFieldsForJoinedLoad(prop: EntityProperty<Entity>, alias: string, explicitFields?: readonly string[]): InternalField<Entity>[];
163
405
  /**
164
406
  * Apply filters to the QB where condition.
165
407
  */
166
408
  applyFilters(filterOptions?: FilterOptions): Promise<void>;
167
- private readonly autoJoinedPaths;
168
409
  /**
169
410
  * @internal
170
411
  */
@@ -174,29 +415,191 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
174
415
  */
175
416
  applyJoinedFilters(em: EntityManager, filterOptions: FilterOptions | undefined): Promise<void>;
176
417
  withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this;
177
- where(cond: QBFilterQuery<Entity>, operator?: keyof typeof GroupOperator): this;
178
- where(cond: string, params?: any[], operator?: keyof typeof GroupOperator): this;
179
- andWhere(cond: QBFilterQuery<Entity>): this;
180
- andWhere(cond: string, params?: any[]): this;
181
- orWhere(cond: QBFilterQuery<Entity>): this;
182
- orWhere(cond: string, params?: any[]): this;
183
- orderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
184
- andOrderBy(orderBy: QBQueryOrderMap<Entity> | QBQueryOrderMap<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
418
+ /**
419
+ * Adds a WHERE clause to the query using an object condition.
420
+ *
421
+ * Supports filtering by:
422
+ * - Direct entity properties: `{ name: 'John' }`
423
+ * - Nested relations/embedded: `{ author: { name: 'John' } }`
424
+ * - Aliased properties after joins: `{ 'a.name': 'John' }` or `{ 'b.title': 'test' }`
425
+ * - Filter operators: `{ age: { $gte: 18 } }`
426
+ * - Logical operators: `{ $or: [{ name: 'John' }, { name: 'Jane' }] }`
427
+ *
428
+ * @example
429
+ * ```ts
430
+ * // Filter by entity properties
431
+ * qb.where({ name: 'John', age: { $gte: 18 } });
432
+ *
433
+ * // Filter by nested relation
434
+ * qb.where({ author: { name: 'John' } });
435
+ *
436
+ * // Filter by aliased properties after join
437
+ * qb.leftJoin('a.books', 'b').where({ 'b.title': 'test' });
438
+ *
439
+ * // Combine with logical operators
440
+ * qb.where({ $or: [{ status: 'active' }, { role: 'admin' }] });
441
+ * ```
442
+ */
443
+ where(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>, operator?: keyof typeof GroupOperator): this;
444
+ /**
445
+ * Adds a WHERE clause to the query using a raw SQL string or fragment.
446
+ *
447
+ * @example
448
+ * ```ts
449
+ * // Raw SQL with parameters
450
+ * qb.where('name = ? AND age >= ?', ['John', 18]);
451
+ *
452
+ * // Using raw() helper
453
+ * qb.where(raw('lower(name) = ?', ['john']));
454
+ * ```
455
+ */
456
+ where(cond: string | RawQueryFragment, params?: any[], operator?: keyof typeof GroupOperator): this;
457
+ /**
458
+ * Adds an AND WHERE clause to the query using an object condition.
459
+ *
460
+ * @example
461
+ * ```ts
462
+ * qb.where({ status: 'active' }).andWhere({ role: 'admin' });
463
+ * qb.where({ name: 'John' }).andWhere({ 'b.title': 'test' });
464
+ * ```
465
+ */
466
+ andWhere(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): this;
467
+ /**
468
+ * Adds an AND WHERE clause to the query using a raw SQL string or fragment.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * qb.where({ status: 'active' }).andWhere('age >= ?', [18]);
473
+ * ```
474
+ */
475
+ andWhere(cond: string | RawQueryFragment, params?: any[]): this;
476
+ /**
477
+ * Adds an OR WHERE clause to the query using an object condition.
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * qb.where({ status: 'active' }).orWhere({ role: 'admin' });
482
+ * qb.where({ name: 'John' }).orWhere({ name: 'Jane' });
483
+ * ```
484
+ */
485
+ orWhere(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): this;
486
+ /**
487
+ * Adds an OR WHERE clause to the query using a raw SQL string or fragment.
488
+ *
489
+ * @example
490
+ * ```ts
491
+ * qb.where({ status: 'active' }).orWhere('role = ?', ['admin']);
492
+ * ```
493
+ */
494
+ orWhere(cond: string | RawQueryFragment, params?: any[]): this;
495
+ /**
496
+ * Adds an ORDER BY clause to the query, replacing any existing order.
497
+ *
498
+ * @example
499
+ * ```ts
500
+ * qb.orderBy({ name: 'asc', createdAt: 'desc' });
501
+ * qb.orderBy([{ name: 'asc' }, { createdAt: 'desc' }]);
502
+ * qb.orderBy({ profile: { bio: 'asc' } }); // nested via object
503
+ * qb.orderBy({ 'profile.bio': 'asc' }); // nested via dot notation
504
+ * ```
505
+ */
506
+ orderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context> | ContextOrderByMap<Entity, RootAlias, Context>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
507
+ /**
508
+ * Adds an ORDER BY clause to the query, replacing any existing order.
509
+ *
510
+ * @example
511
+ * ```ts
512
+ * qb.orderBy({ name: 'asc', createdAt: 'desc' });
513
+ * qb.orderBy([{ name: 'asc' }, { createdAt: 'desc' }]);
514
+ * qb.orderBy({ profile: { bio: 'asc' } }); // nested via object
515
+ * qb.orderBy({ 'profile.bio': 'asc' }); // nested via dot notation
516
+ * ```
517
+ */
518
+ orderBy<const T extends Record<string, QueryOrderKeysFlat>>(orderBy: T & {
519
+ [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : never;
520
+ }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
521
+ /**
522
+ * Adds additional ORDER BY clause without replacing existing order.
523
+ */
524
+ andOrderBy(orderBy: ContextOrderByMap<Entity, RootAlias, Context> | ContextOrderByMap<Entity, RootAlias, Context>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
525
+ /**
526
+ * Adds additional ORDER BY clause without replacing existing order.
527
+ */
528
+ andOrderBy<const T extends Record<string, QueryOrderKeysFlat>>(orderBy: T & {
529
+ [K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string> ? T[K] : never;
530
+ }): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
185
531
  private processOrderBy;
186
- groupBy(fields: EntityKeyOrString<Entity> | readonly EntityKeyOrString<Entity>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
187
- having(cond?: QBFilterQuery | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
188
- andHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
189
- orHaving(cond?: QBFilterQuery | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
190
- onConflict(fields?: Field<Entity> | Field<Entity>[]): InsertQueryBuilder<Entity>;
532
+ /**
533
+ * Adds a GROUP BY clause to the query.
534
+ *
535
+ * @example
536
+ * ```ts
537
+ * qb.select([raw('count(*) as count'), 'status'])
538
+ * .groupBy('status');
539
+ * ```
540
+ */
541
+ groupBy<const F extends readonly Field<Entity, RootAlias, Context>[]>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
542
+ /**
543
+ * Adds a GROUP BY clause to the query.
544
+ *
545
+ * @example
546
+ * ```ts
547
+ * qb.select([raw('count(*) as count'), 'status'])
548
+ * .groupBy('status');
549
+ * ```
550
+ */
551
+ groupBy<F extends Field<Entity, RootAlias, Context>>(fields: F): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
552
+ /**
553
+ * Adds a GROUP BY clause to the query.
554
+ *
555
+ * @example
556
+ * ```ts
557
+ * qb.select([raw('count(*) as count'), 'status'])
558
+ * .groupBy('status');
559
+ * ```
560
+ */
561
+ groupBy<const P extends string>(fields: NestedAutoPath<Entity, RootAlias, Context, P> | readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
562
+ /**
563
+ * Adds a HAVING clause to the query, typically used with GROUP BY.
564
+ *
565
+ * @example
566
+ * ```ts
567
+ * qb.select([raw('count(*) as count'), 'status'])
568
+ * .groupBy('status')
569
+ * .having({ count: { $gt: 5 } });
570
+ * ```
571
+ */
572
+ having(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[], operator?: keyof typeof GroupOperator): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
573
+ andHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
574
+ orHaving(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: any[]): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
575
+ onConflict<F extends Field<Entity, RootAlias, Context>>(fields?: F | F[] | RawQueryFragment): InsertQueryBuilder<Entity, RootAlias, Context>;
191
576
  ignore(): this;
192
- merge(data?: EntityData<Entity> | Field<Entity>[]): this;
193
- returning(fields?: Field<Entity> | Field<Entity>[]): this;
577
+ merge<const P extends string>(data: readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): this;
578
+ merge<F extends Field<Entity, RootAlias, Context>>(data?: EntityData<Entity> | F[]): this;
579
+ returning<F extends Field<Entity, RootAlias, Context>>(fields?: F | F[]): this;
194
580
  /**
195
581
  * @internal
196
582
  */
197
583
  populate(populate: PopulateOptions<Entity>[], populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`, populateFilter?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`): this;
198
- limit(limit?: number, offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
199
- offset(offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
584
+ /**
585
+ * Sets a LIMIT clause to restrict the number of results.
586
+ *
587
+ * @example
588
+ * ```ts
589
+ * qb.select('*').limit(10); // First 10 results
590
+ * qb.select('*').limit(10, 20); // 10 results starting from offset 20
591
+ * ```
592
+ */
593
+ limit(limit?: number, offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
594
+ /**
595
+ * Sets an OFFSET clause to skip a number of results.
596
+ *
597
+ * @example
598
+ * ```ts
599
+ * qb.select('*').limit(10).offset(20); // Results 21-30
600
+ * ```
601
+ */
602
+ offset(offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
200
603
  withSchema(schema?: string): this;
201
604
  setLockMode(mode?: LockMode, tables?: string[]): this;
202
605
  setFlushMode(flushMode?: FlushMode): this;
@@ -222,13 +625,13 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
222
625
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
223
626
  * Allows setting a main string alias of the selection data.
224
627
  */
225
- from<Entity extends AnyEntity<Entity> = AnyEntity>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
226
- from<Entity extends AnyEntity<Entity> = AnyEntity>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context>;
227
- getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
628
+ from<Entity extends object>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
228
629
  /**
229
- * @internal
630
+ * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
631
+ * Allows setting a main string alias of the selection data.
230
632
  */
231
- clearRawFragmentsCache(): void;
633
+ from<Entity extends object>(target: EntityName<Entity>): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
634
+ getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
232
635
  /**
233
636
  * Returns the query with parameters as wildcards.
234
637
  */
@@ -260,11 +663,17 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
260
663
  /**
261
664
  * @internal
262
665
  */
263
- getNextAlias(entityName?: string): string;
666
+ getNextAlias(entityName?: string | EntityName): string;
667
+ /**
668
+ * Registers a join for a specific polymorphic target type.
669
+ * Used by the driver to create per-target LEFT JOINs for JOINED loading.
670
+ * @internal
671
+ */
672
+ addPolymorphicJoin(prop: EntityProperty, targetMeta: EntityMetadata, ownerAlias: string, alias: string, type: JoinType, path: string, schema?: string): void;
264
673
  /**
265
674
  * @internal
266
675
  */
267
- getAliasMap(): Dictionary<string>;
676
+ getAliasMap(): Dictionary<EntityName>;
268
677
  /**
269
678
  * Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
270
679
  * Use `method` to specify what kind of result you want to get (array/single/meta).
@@ -287,36 +696,40 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
287
696
  * }
288
697
  * ```
289
698
  */
290
- stream(options?: QBStreamOptions): AsyncIterableIterator<Loaded<Entity, Hint>>;
699
+ stream(options?: QBStreamOptions): AsyncIterableIterator<Loaded<Entity, Hint, Fields>>;
291
700
  /**
292
701
  * Alias for `qb.getResultList()`
293
702
  */
294
- getResult(): Promise<Loaded<Entity, Hint>[]>;
703
+ getResult(): Promise<Loaded<Entity, Hint, Fields>[]>;
295
704
  /**
296
705
  * Executes the query, returning array of results mapped to entity instances.
297
706
  */
298
- getResultList(limit?: number): Promise<Loaded<Entity, Hint>[]>;
707
+ getResultList(limit?: number): Promise<Loaded<Entity, Hint, Fields>[]>;
299
708
  private propagatePopulateHint;
300
709
  private mapResult;
301
710
  private mapResults;
302
711
  /**
303
712
  * Executes the query, returning the first result or null
304
713
  */
305
- getSingleResult(): Promise<Entity | null>;
714
+ getSingleResult(): Promise<Loaded<Entity, Hint, Fields> | null>;
306
715
  /**
307
716
  * Executes count query (without offset and limit), returning total count of results
308
717
  */
309
- getCount(field?: EntityKeyOrString<Entity> | EntityKeyOrString<Entity>[], distinct?: boolean): Promise<number>;
718
+ getCount<F extends Field<Entity, RootAlias, Context>>(field?: F | F[], distinct?: boolean): Promise<number>;
310
719
  /**
311
720
  * Executes the query, returning both array of results and total count query (without offset and limit).
312
721
  */
313
- getResultAndCount(): Promise<[Entity[], number]>;
722
+ getResultAndCount(): Promise<[Loaded<Entity, Hint, Fields>[], number]>;
314
723
  /**
315
724
  * Returns native query builder instance with sub-query aliased with given alias.
316
- * You can provide `EntityName.propName` as alias, then the field name will be used based on the metadata
317
725
  */
318
726
  as(alias: string): NativeQueryBuilder;
319
- clone(reset?: boolean | string[]): QueryBuilder<Entity>;
727
+ /**
728
+ * Returns native query builder instance with sub-query aliased with given alias.
729
+ * 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.
730
+ */
731
+ as<T>(targetEntity: EntityName<T>, alias: EntityKey<T>): NativeQueryBuilder;
732
+ clone(reset?: boolean | string[], preserve?: string[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields>;
320
733
  /**
321
734
  * Sets logger context for this query builder.
322
735
  */
@@ -326,11 +739,45 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
326
739
  */
327
740
  getLoggerContext<T extends Dictionary & LoggingOptions = Dictionary>(): T;
328
741
  private fromVirtual;
742
+ /**
743
+ * Adds a join from a property object. Used internally for TPT joins where the property
744
+ * is synthetic (not in entity.properties) but defined on metadata (e.g., tptParentProp).
745
+ * The caller must create the alias first via createAlias().
746
+ * @internal
747
+ */
748
+ addPropertyJoin(prop: EntityProperty, ownerAlias: string, alias: string, type: JoinType, path: string, schema?: string): string;
329
749
  private joinReference;
330
- protected prepareFields<T>(fields: Field<T>[], type?: 'where' | 'groupBy' | 'sub-query'): (string | RawQueryFragment)[];
750
+ protected prepareFields<T>(fields: InternalField<T>[], type?: 'where' | 'groupBy' | 'sub-query', schema?: string): (string | RawQueryFragment)[];
751
+ /**
752
+ * Resolves nested paths like `a.books.title` to their actual field references.
753
+ * Auto-joins relations as needed and returns `{alias}.{field}`.
754
+ * For embeddeds: navigates into flattened embeddeds to return the correct field name.
755
+ */
756
+ protected resolveNestedPath(field: string): string | string[];
331
757
  private init;
332
758
  private getQueryBase;
333
759
  private applyDiscriminatorCondition;
760
+ /**
761
+ * Ensures TPT joins are applied. Can be called early before finalize() to populate
762
+ * the _tptAlias map for use in join resolution. Safe to call multiple times.
763
+ * @internal
764
+ */
765
+ ensureTPTJoins(): void;
766
+ /**
767
+ * For TPT (Table-Per-Type) inheritance: INNER JOINs parent tables.
768
+ * When querying a child entity, we need to join all parent tables.
769
+ * Field selection is handled separately in addTPTParentFields().
770
+ */
771
+ private applyTPTJoins;
772
+ /**
773
+ * For TPT inheritance: adds field selections from parent tables.
774
+ */
775
+ private addTPTParentFields;
776
+ /**
777
+ * For TPT polymorphic queries: LEFT JOINs all child tables when querying a TPT base class.
778
+ * Adds discriminator and child fields to determine and load the concrete type.
779
+ */
780
+ private applyTPTPolymorphicJoins;
334
781
  private finalize;
335
782
  /** @internal */
336
783
  processPopulateHint(): void;
@@ -343,10 +790,32 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
343
790
  private processNestedJoins;
344
791
  private hasToManyJoins;
345
792
  protected wrapPaginateSubQuery(meta: EntityMetadata): void;
346
- private pruneExtraJoins;
793
+ /**
794
+ * Computes the set of populate paths from the _populate hints.
795
+ */
796
+ protected getPopulatePaths(): Set<string>;
797
+ protected normalizeJoinPath(join: JoinOptions, meta: EntityMetadata): string;
798
+ /**
799
+ * Transfers WHERE conditions to ORDER BY joins that are not used for population.
800
+ * This ensures the outer query's ORDER BY uses the same filtered rows as the subquery.
801
+ * GH #6160
802
+ */
803
+ protected transferConditionsForOrderByJoins(meta: EntityMetadata, cond: Dictionary | undefined, populatePaths: Set<string>): void;
804
+ /**
805
+ * Removes joins that are not used for population or ordering to improve performance.
806
+ */
807
+ protected pruneJoinsForPagination(meta: EntityMetadata, populatePaths: Set<string>): void;
808
+ /**
809
+ * Transfers WHERE conditions that reference a join alias to the join's ON clause.
810
+ * This is needed when a join is kept for ORDER BY after pagination wrapping,
811
+ * so the outer query orders by the same filtered rows as the subquery.
812
+ * @internal
813
+ */
814
+ protected transferConditionsToJoin(cond: Dictionary, join: JoinOptions, path?: string): void;
347
815
  private wrapModifySubQuery;
348
816
  private getSchema;
349
- private createAlias;
817
+ /** @internal */
818
+ createAlias<U = unknown>(entityName: EntityName<U>, aliasName: string, subQuery?: NativeQueryBuilder): Alias<U>;
350
819
  private createMainAlias;
351
820
  private fromSubQuery;
352
821
  private fromEntityName;
@@ -354,11 +823,11 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
354
823
  private ensureFromClause;
355
824
  private ensureNotFinalized;
356
825
  }
357
- export interface RunQueryBuilder<Entity extends object> extends Omit<QueryBuilder<Entity, any, any>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
358
- where(cond: QBFilterQuery<Entity> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
826
+ export interface RunQueryBuilder<Entity extends object, RootAlias extends string = never, Context extends object = never, RawAliases extends string = never> extends Omit<QueryBuilder<Entity, RootAlias, never, Context, RawAliases, '*'>, 'getResult' | 'getSingleResult' | 'getResultList' | 'where'> {
827
+ where(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string, params?: keyof typeof GroupOperator | any[], operator?: keyof typeof GroupOperator): this;
359
828
  execute<Result = QueryResult<Entity>>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
360
829
  }
361
- export interface SelectQueryBuilder<Entity extends object = AnyEntity, RootAlias extends string = never, Hint extends string = never, Context extends object = never> extends QueryBuilder<Entity, RootAlias, Hint, Context> {
830
+ 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> {
362
831
  execute<Result = Entity[]>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
363
832
  execute<Result = Entity[]>(method: 'all', mapResults?: boolean): Promise<Result>;
364
833
  execute<Result = Entity>(method: 'get', mapResults?: boolean): Promise<Result>;
@@ -378,11 +847,11 @@ export interface CountQueryBuilder<Entity extends object> extends QueryBuilder<E
378
847
  count: number;
379
848
  }>>(method: 'run', mapResults?: boolean): Promise<Result>;
380
849
  }
381
- export interface InsertQueryBuilder<T extends object> extends RunQueryBuilder<T> {
850
+ export interface InsertQueryBuilder<T extends object, RootAlias extends string = never, Context extends object = never> extends RunQueryBuilder<T, RootAlias, Context> {
382
851
  }
383
- export interface UpdateQueryBuilder<T extends object> extends RunQueryBuilder<T> {
852
+ export interface UpdateQueryBuilder<T extends object, RootAlias extends string = never, Context extends object = never> extends RunQueryBuilder<T, RootAlias, Context> {
384
853
  }
385
- export interface DeleteQueryBuilder<T extends object> extends RunQueryBuilder<T> {
854
+ export interface DeleteQueryBuilder<T extends object, RootAlias extends string = never, Context extends object = never> extends RunQueryBuilder<T, RootAlias, Context> {
386
855
  }
387
856
  export interface TruncateQueryBuilder<T extends object> extends RunQueryBuilder<T> {
388
857
  }