1647 lines
58 KiB
TypeScript
1647 lines
58 KiB
TypeScript
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';
|
|
import { JoinType, QueryType } from './enums.js';
|
|
import type { AbstractSqlDriver } from '../AbstractSqlDriver.js';
|
|
import { type Alias, type OnConflictClause, QueryBuilderHelper } from './QueryBuilderHelper.js';
|
|
import type { SqlEntityManager } from '../SqlEntityManager.js';
|
|
import type { ICriteriaNodeProcessOptions, InternalField, JoinOptions } from '../typings.js';
|
|
import type { AbstractSqlPlatform } from '../AbstractSqlPlatform.js';
|
|
import { type CteOptions, NativeQueryBuilder } from './NativeQueryBuilder.js';
|
|
export interface ExecuteOptions {
|
|
mapResults?: boolean;
|
|
mergeResults?: boolean;
|
|
}
|
|
export interface QBStreamOptions {
|
|
/**
|
|
* Results are mapped to entities, if you set `mapResults: false` you will get POJOs instead.
|
|
*
|
|
* @default true
|
|
*/
|
|
mapResults?: boolean;
|
|
/**
|
|
* When populating to-many relations, the ORM streams fully merged entities instead of yielding every row.
|
|
* You can opt out of this behavior by specifying `mergeResults: false`. This will yield every row from
|
|
* the SQL result, but still mapped to entities, meaning that to-many collections will contain at most
|
|
* one item, and you will get duplicate root entities when they have multiple items in the populated
|
|
* collection.
|
|
*
|
|
* @default true
|
|
*/
|
|
mergeResults?: boolean;
|
|
/**
|
|
* When enabled, the driver will return the raw database results without renaming the fields to match the entity property names.
|
|
*
|
|
* @default false
|
|
*/
|
|
rawResults?: boolean;
|
|
}
|
|
type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False;
|
|
type GetAlias<T extends string> = T extends `${infer A}.${string}` ? A : never;
|
|
type GetPropName<T extends string> = T extends `${string}.${infer P}` ? P : T;
|
|
type AppendToHint<Parent extends string, Child extends string> = `${Parent}.${Child}`;
|
|
/**
|
|
* Context tuple format: [Path, Alias, Type, Select]
|
|
* - Path: The relation path from root entity (e.g., 'books', 'books.author')
|
|
* - Alias: The SQL alias used in the query (e.g., 'b', 'a1')
|
|
* - Type: The entity type of the joined relation
|
|
* - Select: Whether this join was created via joinAndSelect (affects Fields tracking)
|
|
*
|
|
* Example: After `qb.leftJoin('a.books', 'b')`, Context becomes:
|
|
* { b: ['books', 'b', Book, false] }
|
|
*/
|
|
type AddToContext<Type extends object, Context, Field extends string, Alias extends string, Select extends boolean> = {
|
|
[K in Alias]: [GetPath<Context, Field>, K, ExpandProperty<Type[GetPropName<Field> & keyof Type]>, Select];
|
|
};
|
|
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>;
|
|
type GetType<Type extends object, Context, Field extends string> =
|
|
GetAlias<Field> extends infer Alias
|
|
? IsNever<Alias> extends true
|
|
? Type
|
|
: [Context] extends [never]
|
|
? Type
|
|
: Alias extends keyof Context
|
|
? Context[Alias] extends [string, string, infer PropType, any]
|
|
? PropType & object
|
|
: Type
|
|
: Type
|
|
: Type;
|
|
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;
|
|
export type ModifyHint<RootAlias, Context, Hint extends string, Field extends string, Select extends boolean = false> =
|
|
| Hint
|
|
| AddToHint<RootAlias, Context, Field, Select>;
|
|
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>;
|
|
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;
|
|
type StripFieldAlias<F extends string> = F extends `${infer Path} as ${string}` ? Path : F;
|
|
type ExtractRootFields<Fields, RootAlias extends string, Context = never> = [Fields] extends ['*']
|
|
? '*'
|
|
: Fields extends `${RootAlias}.*`
|
|
? '*'
|
|
: Fields extends string
|
|
? StripRootAlias<StripFieldAlias<Fields>, RootAlias, Context>
|
|
: never;
|
|
type PrefixWithPath<Path extends string, Field extends string> = `${Path}.${Field}`;
|
|
type StripJoinAlias<F extends string, Alias extends string> = F extends `${Alias}.${infer Field}` ? Field : F;
|
|
export type JoinSelectField<JoinedEntity, Alias extends string> =
|
|
| (keyof JoinedEntity & string)
|
|
| `${Alias}.${keyof JoinedEntity & string}`;
|
|
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;
|
|
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;
|
|
type EntityRelations<T> = EntityKey<T, true>;
|
|
type JoinedEntityType<Entity extends object, Context, Field extends string> = ExpandProperty<
|
|
GetType<Entity, Context, Field>[GetPropName<Field> & keyof GetType<Entity, Context, Field>]
|
|
>;
|
|
type AliasNames<Context> = Context[keyof Context] extends infer Join
|
|
? Join extends any
|
|
? Join extends [string, infer Alias, any, any]
|
|
? Alias & string
|
|
: never
|
|
: never
|
|
: never;
|
|
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;
|
|
export type QBField<Entity, RootAlias extends string, Context> =
|
|
| EntityRelations<Entity>
|
|
| `${RootAlias}.${EntityRelations<Entity>}`
|
|
| ([Context] extends [never] ? never : ContextRelationKeys<Context>);
|
|
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;
|
|
type WithAlias<T extends string> = T | `${T} as ${string}`;
|
|
export type Field<Entity, RootAlias extends string = never, Context = never> =
|
|
| WithAlias<EntityKey<Entity>>
|
|
| (IsNever<RootAlias> extends true ? never : WithAlias<`${RootAlias}.${EntityKey<Entity>}`> | `${RootAlias}.*`)
|
|
| ([Context] extends [never] ? never : WithAlias<ContextFieldKeys<Context>> | `${AliasNames<Context>}.*`)
|
|
| '*'
|
|
| QueryBuilder<any>
|
|
| NativeQueryBuilder
|
|
| RawQueryFragment<any>
|
|
| (RawQueryFragment & symbol);
|
|
type RootAliasOrderKeys<RootAlias extends string, Entity> = {
|
|
[K in `${RootAlias}.${EntityKey<Entity>}`]?: QueryOrderKeysFlat;
|
|
};
|
|
type ContextOrderKeys<Context> = {
|
|
[K in ContextFieldKeys<Context>]?: QueryOrderKeysFlat;
|
|
};
|
|
type RawOrderKeys<RawAliases extends string> = {
|
|
[K in RawAliases]?: QueryOrderKeysFlat;
|
|
};
|
|
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>));
|
|
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;
|
|
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;
|
|
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}`>;
|
|
type AliasedObjectQuery<Entity extends object, Alias extends string> = {
|
|
[K in EntityKey<Entity> as `${Alias}.${K}`]?: ObjectQuery<Entity>[K];
|
|
};
|
|
type JoinCondition<JoinedEntity extends object, Alias extends string> = (
|
|
| ObjectQuery<JoinedEntity>
|
|
| AliasedObjectQuery<JoinedEntity, Alias>
|
|
) & {
|
|
$not?: JoinCondition<JoinedEntity, Alias>;
|
|
$or?: JoinCondition<JoinedEntity, Alias>[];
|
|
$and?: JoinCondition<JoinedEntity, Alias>[];
|
|
};
|
|
type RawJoinCondition = {
|
|
[key: string]: FilterValue<Scalar> | RawQueryFragment;
|
|
};
|
|
type ExtractRawAliasFromField<F> =
|
|
F extends RawQueryFragment<infer A>
|
|
? A extends string
|
|
? A
|
|
: never
|
|
: F extends `${string} as ${infer A}`
|
|
? A
|
|
: never;
|
|
type ExtractRawAliasesFromTuple<T extends readonly unknown[]> = T extends readonly [infer Head, ...infer Tail]
|
|
? ExtractRawAliasFromField<Head> | ExtractRawAliasesFromTuple<Tail>
|
|
: never;
|
|
type ExtractRawAliases<Fields> = Fields extends readonly unknown[]
|
|
? ExtractRawAliasesFromTuple<Fields>
|
|
: ExtractRawAliasFromField<Fields>;
|
|
type FlatOperatorMap = {
|
|
$eq?: Scalar | readonly Scalar[] | Subquery | null;
|
|
$ne?: Scalar | readonly Scalar[] | Subquery | null;
|
|
$in?: readonly Scalar[] | Raw | Subquery;
|
|
$nin?: readonly Scalar[] | Raw | Subquery;
|
|
$gt?: Scalar | Subquery;
|
|
$gte?: Scalar | Subquery;
|
|
$lt?: Scalar | Subquery;
|
|
$lte?: Scalar | Subquery;
|
|
$like?: string;
|
|
$re?: string;
|
|
$ilike?: string;
|
|
$fulltext?: string;
|
|
$overlap?: readonly string[] | string | object;
|
|
$contains?: readonly string[] | string | object;
|
|
$contained?: readonly string[] | string | object;
|
|
$exists?: boolean;
|
|
$hasKey?: string;
|
|
$hasKeys?: readonly string[];
|
|
$hasSomeKeys?: readonly string[];
|
|
};
|
|
type AliasedFilterValue = Scalar | FlatOperatorMap | readonly Scalar[] | null | QueryBuilder<any> | NativeQueryBuilder;
|
|
type TypedAliasedFilterValue<T> = FilterValue<ExpandProperty<T>> | QueryBuilder<any> | NativeQueryBuilder;
|
|
type RootAliasFilterKeys<RootAlias extends string, Entity> = {
|
|
[K in EntityKey<Entity> as `${RootAlias}.${K}`]?: TypedAliasedFilterValue<Entity[K]>;
|
|
};
|
|
type ContextFilterKeys<Context> = {
|
|
[K in ContextFieldKeys<Context>]?: AliasedFilterValue;
|
|
};
|
|
type RawFilterKeys<RawAliases extends string> = {
|
|
[K in RawAliases]?: AliasedFilterValue;
|
|
};
|
|
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>);
|
|
type GroupOperators<RootAlias extends string, Context, Entity, RawAliases extends string> = {
|
|
$and?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>[];
|
|
$or?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>[];
|
|
$not?: NestedFilterCondition<Entity, RootAlias, Context, RawAliases>;
|
|
};
|
|
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>;
|
|
export type QBFilterQuery<
|
|
Entity,
|
|
RootAlias extends string = never,
|
|
Context = never,
|
|
RawAliases extends string = never,
|
|
> = FilterObject<Entity> & AliasedFilterCondition<RootAlias, Context, Entity, RawAliases>;
|
|
/** @internal */
|
|
export interface QBState<Entity extends object> {
|
|
type?: QueryType;
|
|
fields?: InternalField<Entity>[];
|
|
populate: PopulateOptions<Entity>[];
|
|
populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
|
|
populateFilter?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
|
|
resolvedPopulateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`;
|
|
populateMap: Dictionary<string>;
|
|
aliasCounter: number;
|
|
flags: Set<QueryFlag>;
|
|
finalized: boolean;
|
|
populateHintFinalized: boolean;
|
|
joins: Dictionary<JoinOptions>;
|
|
explicitAlias: boolean;
|
|
schema?: string;
|
|
cond: Dictionary;
|
|
data?: Dictionary;
|
|
orderBy: QueryOrderMap<Entity>[];
|
|
groupBy: InternalField<Entity>[];
|
|
having: Dictionary;
|
|
returning?: InternalField<Entity>[];
|
|
onConflict?: OnConflictClause<Entity>[];
|
|
limit?: number;
|
|
offset?: number;
|
|
distinctOn?: string[];
|
|
joinedProps: Map<string, PopulateOptions<any>>;
|
|
cache?: boolean | number | [string, number];
|
|
indexHint?: string;
|
|
collation?: string;
|
|
comments: string[];
|
|
hintComments: string[];
|
|
flushMode?: FlushMode;
|
|
lockMode?: LockMode;
|
|
lockTables?: string[];
|
|
subQueries: Dictionary<string>;
|
|
mainAlias?: Alias<Entity>;
|
|
aliases: Dictionary<Alias<any>>;
|
|
tptAlias: Dictionary<string>;
|
|
unionQuery?: {
|
|
sql: string;
|
|
params: readonly unknown[];
|
|
};
|
|
ctes: (CteOptions & {
|
|
name: string;
|
|
query: NativeQueryBuilder | RawQueryFragment;
|
|
recursive?: boolean;
|
|
})[];
|
|
tptJoinsApplied: boolean;
|
|
autoJoinedPaths: string[];
|
|
}
|
|
/**
|
|
* SQL query builder with fluent interface.
|
|
*
|
|
* ```ts
|
|
* const qb = orm.em.createQueryBuilder(Publisher);
|
|
* qb.select('*')
|
|
* .where({
|
|
* name: 'test 123',
|
|
* type: PublisherType.GLOBAL,
|
|
* })
|
|
* .orderBy({
|
|
* name: QueryOrder.DESC,
|
|
* type: QueryOrder.ASC,
|
|
* })
|
|
* .limit(2, 1);
|
|
*
|
|
* const publisher = await qb.getSingleResult();
|
|
* ```
|
|
*/
|
|
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 {
|
|
#private;
|
|
protected readonly metadata: MetadataStorage;
|
|
protected readonly driver: AbstractSqlDriver;
|
|
protected readonly context?: Transaction | undefined;
|
|
protected connectionType?: ConnectionType | undefined;
|
|
protected em?: SqlEntityManager | undefined;
|
|
protected loggerContext?: (LoggingOptions & Dictionary) | undefined;
|
|
readonly __subquery: true;
|
|
/** @internal */
|
|
static createDefaultState<T extends object>(): QBState<T>;
|
|
get mainAlias(): Alias<Entity>;
|
|
get alias(): string;
|
|
get helper(): QueryBuilderHelper;
|
|
get type(): QueryType;
|
|
/** @internal */
|
|
get state(): QBState<Entity>;
|
|
protected readonly platform: AbstractSqlPlatform;
|
|
/**
|
|
* @internal
|
|
*/
|
|
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,
|
|
);
|
|
/**
|
|
* Creates a SELECT query, specifying the fields to retrieve.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Select specific fields
|
|
* const qb = em.createQueryBuilder(User, 'u');
|
|
* qb.select(['u.id', 'u.name', 'u.email']);
|
|
*
|
|
* // Select with raw expressions
|
|
* qb.select([raw('count(*) as total')]);
|
|
*
|
|
* // Select with aliases (works for regular and formula properties)
|
|
* qb.select(['id', 'fullName as displayName']);
|
|
* qb.select(['id', sql.ref('fullName').as('displayName')]);
|
|
*
|
|
* // Select with distinct
|
|
* qb.select('*', true);
|
|
* ```
|
|
*/
|
|
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
|
|
>;
|
|
/**
|
|
* Creates a SELECT query, specifying the fields to retrieve.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Select specific fields
|
|
* const qb = em.createQueryBuilder(User, 'u');
|
|
* qb.select(['u.id', 'u.name', 'u.email']);
|
|
*
|
|
* // Select with raw expressions
|
|
* qb.select([raw('count(*) as total')]);
|
|
*
|
|
* // Select with distinct
|
|
* qb.select('*', true);
|
|
* ```
|
|
*/
|
|
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>;
|
|
/**
|
|
* Creates a SELECT query, specifying the fields to retrieve.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Select specific fields with nested paths (e.g., for embedded properties)
|
|
* const qb = em.createQueryBuilder(User, 'u');
|
|
* qb.select('address.city');
|
|
* ```
|
|
*/
|
|
select<const P extends string>(
|
|
fields: NestedAutoPath<Entity, RootAlias, Context, P>,
|
|
distinct?: boolean,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, ExtractRootFields<P, RootAlias, Context>, CTEs>;
|
|
/**
|
|
* Creates a SELECT query, specifying the fields to retrieve.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Select specific fields
|
|
* const qb = em.createQueryBuilder(User, 'u');
|
|
* qb.select(['u.id', 'u.name', 'u.email']);
|
|
*
|
|
* // Select with raw expressions
|
|
* qb.select([raw('count(*) as total')]);
|
|
*
|
|
* // Select with distinct
|
|
* qb.select('*', true);
|
|
* ```
|
|
*/
|
|
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
|
|
>;
|
|
/**
|
|
* Adds fields to an existing SELECT query.
|
|
*/
|
|
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
|
|
>;
|
|
distinct(): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/** postgres only */
|
|
distinctOn<const F extends readonly Field<Entity, RootAlias, Context>[]>(
|
|
fields: F,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/** postgres only */
|
|
distinctOn<F extends Field<Entity, RootAlias, Context>>(
|
|
fields: F,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Creates an INSERT query with the given data.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* await em.createQueryBuilder(User)
|
|
* .insert({ name: 'John', email: 'john@example.com' })
|
|
* .execute();
|
|
*
|
|
* // Bulk insert
|
|
* await em.createQueryBuilder(User)
|
|
* .insert([{ name: 'John' }, { name: 'Jane' }])
|
|
* .execute();
|
|
* ```
|
|
*/
|
|
insert(
|
|
data: RequiredEntityData<Entity> | RequiredEntityData<Entity>[],
|
|
): InsertQueryBuilder<Entity, RootAlias, Context>;
|
|
/**
|
|
* Creates an UPDATE query with the given data.
|
|
* Use `where()` to specify which rows to update.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* await em.createQueryBuilder(User)
|
|
* .update({ name: 'John Doe' })
|
|
* .where({ id: 1 })
|
|
* .execute();
|
|
* ```
|
|
*/
|
|
update(data: EntityData<Entity>): UpdateQueryBuilder<Entity, RootAlias, Context>;
|
|
/**
|
|
* Creates a DELETE query.
|
|
* Use `where()` to specify which rows to delete.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* await em.createQueryBuilder(User)
|
|
* .delete()
|
|
* .where({ id: 1 })
|
|
* .execute();
|
|
*
|
|
* // Or pass the condition directly
|
|
* await em.createQueryBuilder(User)
|
|
* .delete({ isActive: false })
|
|
* .execute();
|
|
* ```
|
|
*/
|
|
delete(cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): DeleteQueryBuilder<Entity, RootAlias, Context>;
|
|
/**
|
|
* Creates a TRUNCATE query to remove all rows from the table.
|
|
*/
|
|
truncate(): TruncateQueryBuilder<Entity>;
|
|
/**
|
|
* Creates a COUNT query to count matching rows.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const count = await em.createQueryBuilder(User)
|
|
* .count()
|
|
* .where({ isActive: true })
|
|
* .execute('get');
|
|
* ```
|
|
*/
|
|
count<F extends Field<Entity, RootAlias, Context>>(field?: F | F[], distinct?: boolean): CountQueryBuilder<Entity>;
|
|
/**
|
|
* Adds a JOIN clause to the query for an entity relation.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const qb = em.createQueryBuilder(Book, 'b');
|
|
* qb.select('*')
|
|
* .join('b.author', 'a')
|
|
* .where({ 'a.name': 'John' });
|
|
* ```
|
|
*/
|
|
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
|
|
>;
|
|
/**
|
|
* Adds a JOIN clause to the query for a subquery.
|
|
*/
|
|
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>;
|
|
/**
|
|
* Adds an INNER JOIN clause to the query for an entity relation.
|
|
*/
|
|
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
|
|
>;
|
|
/**
|
|
* Adds an INNER JOIN clause to the query for a subquery.
|
|
*/
|
|
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>;
|
|
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>;
|
|
/**
|
|
* Adds a LEFT JOIN clause to the query for an entity relation.
|
|
*/
|
|
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
|
|
>;
|
|
/**
|
|
* Adds a LEFT JOIN clause to the query for a subquery.
|
|
*/
|
|
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>;
|
|
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>;
|
|
/**
|
|
* Adds a JOIN clause and automatically selects the joined entity's fields.
|
|
* This is useful for eager loading related entities.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const qb = em.createQueryBuilder(Book, 'b');
|
|
* qb.select('*')
|
|
* .joinAndSelect('b.author', 'a')
|
|
* .where({ 'a.name': 'John' });
|
|
* ```
|
|
*/
|
|
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>,
|
|
CTEs
|
|
>;
|
|
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>,
|
|
CTEs
|
|
>;
|
|
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>,
|
|
CTEs
|
|
>;
|
|
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>,
|
|
CTEs
|
|
>;
|
|
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>,
|
|
CTEs
|
|
>;
|
|
protected getFieldsForJoinedLoad(
|
|
prop: EntityProperty<Entity>,
|
|
alias: string,
|
|
explicitFields?: readonly string[],
|
|
): InternalField<Entity>[];
|
|
/**
|
|
* Apply filters to the QB where condition.
|
|
*/
|
|
applyFilters(filterOptions?: FilterOptions): Promise<void>;
|
|
/**
|
|
* @internal
|
|
*/
|
|
scheduleFilterCheck(path: string): void;
|
|
/**
|
|
* @internal
|
|
*/
|
|
applyJoinedFilters(em: EntityManager, filterOptions: FilterOptions | undefined): Promise<void>;
|
|
withSubQuery(subQuery: RawQueryFragment | NativeQueryBuilder, alias: string): this;
|
|
/**
|
|
* Adds a WHERE clause to the query using an object condition.
|
|
*
|
|
* Supports filtering by:
|
|
* - Direct entity properties: `{ name: 'John' }`
|
|
* - Nested relations/embedded: `{ author: { name: 'John' } }`
|
|
* - Aliased properties after joins: `{ 'a.name': 'John' }` or `{ 'b.title': 'test' }`
|
|
* - Filter operators: `{ age: { $gte: 18 } }`
|
|
* - Logical operators: `{ $or: [{ name: 'John' }, { name: 'Jane' }] }`
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Filter by entity properties
|
|
* qb.where({ name: 'John', age: { $gte: 18 } });
|
|
*
|
|
* // Filter by nested relation
|
|
* qb.where({ author: { name: 'John' } });
|
|
*
|
|
* // Filter by aliased properties after join
|
|
* qb.leftJoin('a.books', 'b').where({ 'b.title': 'test' });
|
|
*
|
|
* // Combine with logical operators
|
|
* qb.where({ $or: [{ status: 'active' }, { role: 'admin' }] });
|
|
* ```
|
|
*/
|
|
where(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>, operator?: keyof typeof GroupOperator): this;
|
|
/**
|
|
* Adds a WHERE clause to the query using a raw SQL string or fragment.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* // Raw SQL with parameters
|
|
* qb.where('name = ? AND age >= ?', ['John', 18]);
|
|
*
|
|
* // Using raw() helper
|
|
* qb.where(raw('lower(name) = ?', ['john']));
|
|
* ```
|
|
*/
|
|
where(cond: string | RawQueryFragment, params?: any[], operator?: keyof typeof GroupOperator): this;
|
|
/**
|
|
* Adds an AND WHERE clause to the query using an object condition.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.where({ status: 'active' }).andWhere({ role: 'admin' });
|
|
* qb.where({ name: 'John' }).andWhere({ 'b.title': 'test' });
|
|
* ```
|
|
*/
|
|
andWhere(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): this;
|
|
/**
|
|
* Adds an AND WHERE clause to the query using a raw SQL string or fragment.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.where({ status: 'active' }).andWhere('age >= ?', [18]);
|
|
* ```
|
|
*/
|
|
andWhere(cond: string | RawQueryFragment, params?: any[]): this;
|
|
/**
|
|
* Adds an OR WHERE clause to the query using an object condition.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.where({ status: 'active' }).orWhere({ role: 'admin' });
|
|
* qb.where({ name: 'John' }).orWhere({ name: 'Jane' });
|
|
* ```
|
|
*/
|
|
orWhere(cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases>): this;
|
|
/**
|
|
* Adds an OR WHERE clause to the query using a raw SQL string or fragment.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.where({ status: 'active' }).orWhere('role = ?', ['admin']);
|
|
* ```
|
|
*/
|
|
orWhere(cond: string | RawQueryFragment, params?: any[]): this;
|
|
/**
|
|
* Adds an ORDER BY clause to the query, replacing any existing order.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.orderBy({ name: 'asc', createdAt: 'desc' });
|
|
* qb.orderBy([{ name: 'asc' }, { createdAt: 'desc' }]);
|
|
* qb.orderBy({ profile: { bio: 'asc' } }); // nested via object
|
|
* qb.orderBy({ 'profile.bio': 'asc' }); // nested via dot notation
|
|
* ```
|
|
*/
|
|
orderBy(
|
|
orderBy:
|
|
| ContextOrderByMap<Entity, RootAlias, Context, RawAliases>
|
|
| ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[],
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Adds an ORDER BY clause to the query, replacing any existing order.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.orderBy({ name: 'asc', createdAt: 'desc' });
|
|
* qb.orderBy([{ name: 'asc' }, { createdAt: 'desc' }]);
|
|
* qb.orderBy({ profile: { bio: 'asc' } }); // nested via object
|
|
* qb.orderBy({ 'profile.bio': 'asc' }); // nested via dot notation
|
|
* ```
|
|
*/
|
|
orderBy<const T extends Record<string, QueryOrderKeysFlat>>(
|
|
orderBy: T & {
|
|
[K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string>
|
|
? T[K]
|
|
: K extends RawAliases
|
|
? T[K]
|
|
: never;
|
|
},
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Adds additional ORDER BY clause without replacing existing order.
|
|
*/
|
|
andOrderBy(
|
|
orderBy:
|
|
| ContextOrderByMap<Entity, RootAlias, Context, RawAliases>
|
|
| ContextOrderByMap<Entity, RootAlias, Context, RawAliases>[],
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Adds additional ORDER BY clause without replacing existing order.
|
|
*/
|
|
andOrderBy<const T extends Record<string, QueryOrderKeysFlat>>(
|
|
orderBy: T & {
|
|
[K in keyof T]: K extends NestedAutoPath<Entity, RootAlias, Context, K & string>
|
|
? T[K]
|
|
: K extends RawAliases
|
|
? T[K]
|
|
: never;
|
|
},
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
private processOrderBy;
|
|
/** Collect custom aliases from select fields (stored as 'resolved as alias' strings by select()). */
|
|
private getSelectAliases;
|
|
/**
|
|
* Adds a GROUP BY clause to the query.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select([raw('count(*) as count'), 'status'])
|
|
* .groupBy('status');
|
|
* ```
|
|
*/
|
|
groupBy<const F extends readonly Field<Entity, RootAlias, Context>[]>(
|
|
fields: F,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Adds a GROUP BY clause to the query.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select([raw('count(*) as count'), 'status'])
|
|
* .groupBy('status');
|
|
* ```
|
|
*/
|
|
groupBy<F extends Field<Entity, RootAlias, Context>>(
|
|
fields: F,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Adds a GROUP BY clause to the query.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select([raw('count(*) as count'), 'status'])
|
|
* .groupBy('status');
|
|
* ```
|
|
*/
|
|
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>;
|
|
/**
|
|
* Adds a HAVING clause to the query, typically used with GROUP BY.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select([raw('count(*) as count'), 'status'])
|
|
* .groupBy('status')
|
|
* .having({ count: { $gt: 5 } });
|
|
* ```
|
|
*/
|
|
having(
|
|
cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string,
|
|
params?: any[],
|
|
operator?: keyof typeof GroupOperator,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
andHaving(
|
|
cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string,
|
|
params?: any[],
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
orHaving(
|
|
cond?: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string,
|
|
params?: any[],
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
onConflict<F extends Field<Entity, RootAlias, Context>>(
|
|
fields?: F | F[] | RawQueryFragment,
|
|
): InsertQueryBuilder<Entity, RootAlias, Context>;
|
|
ignore(): this;
|
|
merge<const P extends string>(data: readonly NestedAutoPath<Entity, RootAlias, Context, P>[]): this;
|
|
merge<F extends Field<Entity, RootAlias, Context>>(data?: EntityData<Entity> | F[]): this;
|
|
returning<F extends Field<Entity, RootAlias, Context>>(fields?: F | F[]): this;
|
|
/**
|
|
* @internal
|
|
*/
|
|
populate(
|
|
populate: PopulateOptions<Entity>[],
|
|
populateWhere?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`,
|
|
populateFilter?: ObjectQuery<Entity> | PopulateHint | `${PopulateHint}`,
|
|
): this;
|
|
/**
|
|
* Sets a LIMIT clause to restrict the number of results.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select('*').limit(10); // First 10 results
|
|
* qb.select('*').limit(10, 20); // 10 results starting from offset 20
|
|
* ```
|
|
*/
|
|
limit(
|
|
limit?: number,
|
|
offset?: number,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Sets an OFFSET clause to skip a number of results.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* qb.select('*').limit(10).offset(20); // Results 21-30
|
|
* ```
|
|
*/
|
|
offset(offset?: number): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
withSchema(schema?: string): this;
|
|
setLockMode(mode?: LockMode, tables?: string[]): this;
|
|
setFlushMode(flushMode?: FlushMode): this;
|
|
setFlag(flag: QueryFlag): this;
|
|
unsetFlag(flag: QueryFlag): this;
|
|
hasFlag(flag: QueryFlag): boolean;
|
|
cache(config?: boolean | number | [string, number]): this;
|
|
/**
|
|
* Adds index hint to the FROM clause.
|
|
*/
|
|
indexHint(sql: string | undefined): this;
|
|
/**
|
|
* Adds COLLATE clause to ORDER BY expressions.
|
|
*/
|
|
collation(collation: string | undefined): this;
|
|
/**
|
|
* Prepend comment to the sql query using the syntax `/* ... *‍/`. Some characters are forbidden such as `/*, *‍/` and `?`.
|
|
*/
|
|
comment(comment: string | string[] | undefined): this;
|
|
/**
|
|
* Add hints to the query using comment-like syntax `/*+ ... *‍/`. MySQL and Oracle use this syntax for optimizer hints.
|
|
* Also various DB proxies and routers use this syntax to pass hints to alter their behavior. In other dialects the hints
|
|
* are ignored as simple comments.
|
|
*/
|
|
hintComment(comment: string | string[] | undefined): this;
|
|
/**
|
|
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
* Allows setting a main string alias of the selection data.
|
|
*/
|
|
from<Entity extends object>(
|
|
target: QueryBuilder<Entity>,
|
|
aliasName?: string,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
|
|
* Allows setting a main string alias of the selection data.
|
|
*/
|
|
from<Entity extends object>(
|
|
target: EntityName<Entity>,
|
|
): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Specifies a CTE name as the FROM source, with full type safety.
|
|
* The entity type is inferred from the CTE definition passed to `.with()`.
|
|
*/
|
|
from<Name extends string & keyof CTEs, Alias extends string = Name>(
|
|
target: Name,
|
|
aliasName?: Alias,
|
|
): SelectQueryBuilder<CTEs[Name], Alias, never, never, never, '*', CTEs>;
|
|
getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
|
|
protected processReturningStatement(
|
|
qb: NativeQueryBuilder,
|
|
meta?: EntityMetadata,
|
|
data?: Dictionary,
|
|
returning?: Field<any>[],
|
|
): void;
|
|
/**
|
|
* Returns the query with parameters as wildcards.
|
|
*/
|
|
getQuery(): string;
|
|
/**
|
|
* Returns raw fragment representation of this QueryBuilder.
|
|
*/
|
|
toRaw(): RawQueryFragment;
|
|
toQuery(): {
|
|
sql: string;
|
|
params: readonly unknown[];
|
|
};
|
|
/**
|
|
* Returns the list of all parameters for this query.
|
|
*/
|
|
getParams(): readonly unknown[];
|
|
/**
|
|
* Returns raw interpolated query string with all the parameters inlined.
|
|
*/
|
|
getFormattedQuery(): string;
|
|
/**
|
|
* @internal
|
|
*/
|
|
getAliasForJoinPath(path?: string | JoinOptions, options?: ICriteriaNodeProcessOptions): string | undefined;
|
|
/**
|
|
* @internal
|
|
*/
|
|
getJoinForPath(path: string, options?: ICriteriaNodeProcessOptions): JoinOptions | undefined;
|
|
/**
|
|
* @internal
|
|
*/
|
|
getNextAlias(entityName?: string | EntityName): string;
|
|
/**
|
|
* Registers a join for a specific polymorphic target type.
|
|
* Used by the driver to create per-target LEFT JOINs for JOINED loading.
|
|
* @internal
|
|
*/
|
|
addPolymorphicJoin(
|
|
prop: EntityProperty,
|
|
targetMeta: EntityMetadata,
|
|
ownerAlias: string,
|
|
alias: string,
|
|
type: JoinType,
|
|
path: string,
|
|
schema?: string,
|
|
): void;
|
|
/**
|
|
* @internal
|
|
*/
|
|
getAliasMap(): Dictionary<EntityName>;
|
|
/**
|
|
* Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
|
|
* Use `method` to specify what kind of result you want to get (array/single/meta).
|
|
*/
|
|
execute<U = any>(method?: 'all' | 'get' | 'run', options?: ExecuteOptions | boolean): Promise<U>;
|
|
private getConnection;
|
|
/**
|
|
* Executes the query and returns an async iterable (async generator) that yields results one by one.
|
|
* By default, the results are merged and mapped to entity instances, without adding them to the identity map.
|
|
* You can disable merging and mapping by passing the options `{ mergeResults: false, mapResults: false }`.
|
|
* This is useful for processing large datasets without loading everything into memory at once.
|
|
*
|
|
* ```ts
|
|
* const qb = em.createQueryBuilder(Book, 'b');
|
|
* qb.select('*').where({ title: '1984' }).leftJoinAndSelect('b.author', 'a');
|
|
*
|
|
* for await (const book of qb.stream()) {
|
|
* // book is an instance of Book entity
|
|
* console.log(book.title, book.author.name);
|
|
* }
|
|
* ```
|
|
*/
|
|
stream(options?: QBStreamOptions): AsyncIterableIterator<Loaded<Entity, Hint, Fields>>;
|
|
/**
|
|
* Alias for `qb.getResultList()`
|
|
*/
|
|
getResult(): Promise<Loaded<Entity, Hint, Fields>[]>;
|
|
/**
|
|
* Executes the query, returning array of results mapped to entity instances.
|
|
*/
|
|
getResultList(limit?: number): Promise<Loaded<Entity, Hint, Fields>[]>;
|
|
private propagatePopulateHint;
|
|
private mapResult;
|
|
private mapResults;
|
|
/**
|
|
* Executes the query, returning the first result or null
|
|
*/
|
|
getSingleResult(): Promise<Loaded<Entity, Hint, Fields> | null>;
|
|
/**
|
|
* Executes count query (without offset and limit), returning total count of results
|
|
*/
|
|
getCount<F extends Field<Entity, RootAlias, Context>>(field?: F | F[], distinct?: boolean): Promise<number>;
|
|
/**
|
|
* Executes the query, returning both array of results and total count query (without offset and limit).
|
|
*/
|
|
getResultAndCount(): Promise<[Loaded<Entity, Hint, Fields>[], number]>;
|
|
/**
|
|
* Returns native query builder instance with sub-query aliased with given alias.
|
|
*/
|
|
as(alias: string): NativeQueryBuilder;
|
|
/**
|
|
* Returns native query builder instance with sub-query aliased with given alias.
|
|
* 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.
|
|
*/
|
|
as<T>(targetEntity: EntityName<T>, alias: EntityKey<T>): NativeQueryBuilder;
|
|
/**
|
|
* Combines the current query with one or more other queries using `UNION ALL`.
|
|
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
*
|
|
* ```ts
|
|
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
* const qb3 = em.createQueryBuilder(Employee).select('id').where(condition3);
|
|
* const subquery = qb1.unionAll(qb2, qb3);
|
|
*
|
|
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
* ```
|
|
*/
|
|
unionAll(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
|
|
/**
|
|
* Combines the current query with one or more other queries using `UNION` (with deduplication).
|
|
* All queries must select the same columns. Returns a `QueryBuilder` that
|
|
* can be used with `$in`, passed to `qb.from()`, or converted via `.getQuery()`,
|
|
* `.getParams()`, `.toQuery()`, `.toRaw()`, etc.
|
|
*
|
|
* ```ts
|
|
* const qb1 = em.createQueryBuilder(Employee).select('id').where(condition1);
|
|
* const qb2 = em.createQueryBuilder(Employee).select('id').where(condition2);
|
|
* const subquery = qb1.union(qb2);
|
|
*
|
|
* const results = await em.find(Employee, { id: { $in: subquery } });
|
|
* ```
|
|
*/
|
|
union(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
|
|
private buildUnionQuery;
|
|
/**
|
|
* Adds a Common Table Expression (CTE) to the query.
|
|
* When a `QueryBuilder` is passed, its entity type is tracked for type-safe `from()`.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const recentBooks = em.createQueryBuilder(Book, 'b').select('*').where({ ... });
|
|
* const qb = em.createQueryBuilder(Author, 'a')
|
|
* .with('recent_books', recentBooks)
|
|
* .select('*')
|
|
* .from('recent_books', 'rb'); // entity type inferred as Book
|
|
* ```
|
|
*/
|
|
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>
|
|
>;
|
|
/**
|
|
* Adds a Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
|
|
* The CTE name is tracked but without entity type inference — use `from()` to query from it.
|
|
*/
|
|
with<Name extends string>(
|
|
name: Name,
|
|
query: NativeQueryBuilder | RawQueryFragment,
|
|
options?: CteOptions,
|
|
): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, object>>;
|
|
/**
|
|
* Adds a recursive Common Table Expression (CTE) to the query.
|
|
* When a `QueryBuilder` is passed, its entity type is tracked for type-safe `from()`.
|
|
*
|
|
* @example
|
|
* ```ts
|
|
* const base = em.createQueryBuilder(Category).select('*').where({ parent: null });
|
|
* const rec = em.createQueryBuilder(Category, 'c').select('c.*')
|
|
* .leftJoin('c.parent', 'ct', { id: sql.ref('c.parentId') });
|
|
* const qb = em.createQueryBuilder(Category)
|
|
* .withRecursive('category_tree', base.unionAll(rec))
|
|
* .select('*')
|
|
* .from('category_tree', 'ct'); // entity type inferred as Category
|
|
* ```
|
|
*/
|
|
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>
|
|
>;
|
|
/**
|
|
* Adds a recursive Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
|
|
* The CTE name is tracked but without entity type inference — use `from()` to query from it.
|
|
*/
|
|
withRecursive<Name extends string>(
|
|
name: Name,
|
|
query: NativeQueryBuilder | RawQueryFragment,
|
|
options?: CteOptions,
|
|
): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, object>>;
|
|
private addCte;
|
|
clone(
|
|
reset?: boolean | (keyof QBState<Entity>)[],
|
|
preserve?: (keyof QBState<Entity>)[],
|
|
): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
|
|
/**
|
|
* Sets logger context for this query builder.
|
|
*/
|
|
setLoggerContext(context: LoggingOptions & Dictionary): void;
|
|
/**
|
|
* Gets logger context for this query builder.
|
|
*/
|
|
getLoggerContext<T extends Dictionary & LoggingOptions = Dictionary>(): T;
|
|
private fromVirtual;
|
|
/**
|
|
* Adds a join from a property object. Used internally for TPT joins where the property
|
|
* is synthetic (not in entity.properties) but defined on metadata (e.g., tptParentProp).
|
|
* The caller must create the alias first via createAlias().
|
|
* @internal
|
|
*/
|
|
addPropertyJoin(
|
|
prop: EntityProperty,
|
|
ownerAlias: string,
|
|
alias: string,
|
|
type: JoinType,
|
|
path: string,
|
|
schema?: string,
|
|
): string;
|
|
private joinReference;
|
|
protected prepareFields<T>(
|
|
fields: InternalField<T>[],
|
|
type?: 'where' | 'groupBy' | 'sub-query',
|
|
schema?: string,
|
|
): (string | RawQueryFragment)[];
|
|
/**
|
|
* Resolves nested paths like `a.books.title` to their actual field references.
|
|
* Auto-joins relations as needed and returns `{alias}.{field}`.
|
|
* For embeddeds: navigates into flattened embeddeds to return the correct field name.
|
|
*/
|
|
protected resolveNestedPath(field: string): string | string[];
|
|
protected init(type: QueryType, data?: any, cond?: any): this;
|
|
private getQueryBase;
|
|
private applyDiscriminatorCondition;
|
|
/**
|
|
* Ensures TPT joins are applied. Can be called early before finalize() to populate
|
|
* the _tptAlias map for use in join resolution. Safe to call multiple times.
|
|
* @internal
|
|
*/
|
|
ensureTPTJoins(): void;
|
|
/**
|
|
* For TPT (Table-Per-Type) inheritance: INNER JOINs parent tables.
|
|
* When querying a child entity, we need to join all parent tables.
|
|
* Field selection is handled separately in addTPTParentFields().
|
|
*/
|
|
private applyTPTJoins;
|
|
/**
|
|
* For TPT inheritance: adds field selections from parent tables.
|
|
*/
|
|
private addTPTParentFields;
|
|
/**
|
|
* For TPT polymorphic queries: LEFT JOINs all child tables when querying a TPT base class.
|
|
* Adds discriminator and child fields to determine and load the concrete type.
|
|
*/
|
|
private applyTPTPolymorphicJoins;
|
|
private finalize;
|
|
/** @internal */
|
|
processPopulateHint(): void;
|
|
private processPopulateWhere;
|
|
private mergeOnConditions;
|
|
/**
|
|
* When adding an inner join on a left joined relation, we need to nest them,
|
|
* otherwise the inner join could discard rows of the root table.
|
|
*/
|
|
private processNestedJoins;
|
|
private hasToManyJoins;
|
|
protected wrapPaginateSubQuery(meta: EntityMetadata): void;
|
|
/**
|
|
* Computes the set of populate paths from the _populate hints.
|
|
*/
|
|
protected getPopulatePaths(): Set<string>;
|
|
protected normalizeJoinPath(join: JoinOptions, meta: EntityMetadata): string;
|
|
/**
|
|
* Transfers WHERE conditions to ORDER BY joins that are not used for population.
|
|
* This ensures the outer query's ORDER BY uses the same filtered rows as the subquery.
|
|
* GH #6160
|
|
*/
|
|
protected transferConditionsForOrderByJoins(
|
|
meta: EntityMetadata,
|
|
cond: Dictionary | undefined,
|
|
populatePaths: Set<string>,
|
|
): void;
|
|
/**
|
|
* Removes joins that are not used for population or ordering to improve performance.
|
|
*/
|
|
protected pruneJoinsForPagination(meta: EntityMetadata, populatePaths: Set<string>): void;
|
|
/**
|
|
* Transfers WHERE conditions that reference a join alias to the join's ON clause.
|
|
* This is needed when a join is kept for ORDER BY after pagination wrapping,
|
|
* so the outer query orders by the same filtered rows as the subquery.
|
|
* @internal
|
|
*/
|
|
protected transferConditionsToJoin(cond: Dictionary, join: JoinOptions, path?: string): void;
|
|
private wrapModifySubQuery;
|
|
private getSchema;
|
|
/** @internal */
|
|
createAlias<U = unknown>(
|
|
entityName: EntityName<U>,
|
|
aliasName: string,
|
|
subQuery?: NativeQueryBuilder | RawQueryFragment,
|
|
): Alias<U>;
|
|
private createMainAlias;
|
|
private fromSubQuery;
|
|
private fromEntityName;
|
|
private fromRawTable;
|
|
private createQueryBuilderHelper;
|
|
private ensureFromClause;
|
|
private ensureNotFinalized;
|
|
}
|
|
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'
|
|
> {
|
|
where(
|
|
cond: QBFilterQuery<Entity, RootAlias, Context, RawAliases> | string,
|
|
params?: keyof typeof GroupOperator | any[],
|
|
operator?: keyof typeof GroupOperator,
|
|
): this;
|
|
execute<Result = QueryResult<Entity>>(method?: 'all' | 'get' | 'run', mapResults?: boolean): Promise<Result>;
|
|
}
|
|
/**
|
|
* @internal Optimized DTO type for execute().
|
|
* Bypasses the double mapped type of EntityDTO<Loaded<T, H, F>> by using DirectDTO
|
|
* which only iterates selected keys instead of all entity keys.
|
|
*
|
|
* - Wildcard, no joins: EntityDTO<T>
|
|
* - Selected fields, no joins: DirectDTO<T, F> (~132x faster than Pick<EntityDTO<T>, F>)
|
|
* - Wildcard + single-level join: Omit<EntityDTO<T>> + override populated relations
|
|
* - Selected fields + single-level join: DirectDTO for root + DirectDTO for joined (~60x faster)
|
|
* - Wildcard + nested joins: uses SerializeDTO<T, H> (~40x faster than EntityDTO<Loaded<T, H>>)
|
|
* - Fields + nested joins: falls back to EntityDTO<Loaded<T, H, F>>
|
|
*/
|
|
type DirectDTO<T, F extends keyof T> = {
|
|
[K in F]: EntityDTOProp<T, NonNullable<T[K]>> | Extract<T[K], null | undefined>;
|
|
};
|
|
type PopulatedDTO<T, K extends keyof T> =
|
|
NonNullable<T[K]> extends Collection<infer U> ? EntityDTOFlat<U & object>[] : EntityDTOFlat<ExpandProperty<T[K]>>;
|
|
type SubFields<F extends string, Rel extends string> = F extends `${Rel}.${infer Sub}` ? Sub : never;
|
|
type RootFields<F extends string, H extends string> = F extends `${string}.${string}`
|
|
? F extends `${H}.${string}`
|
|
? never
|
|
: F
|
|
: F;
|
|
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>;
|
|
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>> & {
|
|
[K in H & keyof T as K & keyof EntityDTOFlat<T>]: PopulatedDTO<T, K> | Extract<T[K], null | undefined>;
|
|
}
|
|
: true extends (H extends `${string}.${string}` ? true : false)
|
|
? EntityDTOFlat<Loaded<T, H, F>>
|
|
: DirectDTO<T, (RootFields<F, H> | PrimaryProperty<T>) & keyof T> & {
|
|
[K in H & keyof T]: JoinDTO<T, K, F>;
|
|
};
|
|
/** Shorthand for `QueryBuilder` with all generic parameters set to `any`. */
|
|
export type AnyQueryBuilder<T extends object = AnyEntity> = QueryBuilder<T, any, any, any, any, any, any>;
|
|
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> {
|
|
execute<Result = ExecuteDTO<Entity, Hint, Fields>[]>(
|
|
method?: 'all' | 'get' | 'run',
|
|
mapResults?: boolean,
|
|
): Promise<Result>;
|
|
execute<Result = ExecuteDTO<Entity, Hint, Fields>[]>(method: 'all', mapResults?: boolean): Promise<Result>;
|
|
execute<Result = ExecuteDTO<Entity, Hint, Fields>>(method: 'get', mapResults?: boolean): Promise<Result>;
|
|
execute<Result = QueryResult<Entity>>(method: 'run', mapResults?: boolean): Promise<Result>;
|
|
}
|
|
export interface CountQueryBuilder<Entity extends object> extends QueryBuilder<Entity, any, any> {
|
|
execute<
|
|
Result = {
|
|
count: number;
|
|
}[],
|
|
>(
|
|
method?: 'all' | 'get' | 'run',
|
|
mapResults?: boolean,
|
|
): Promise<Result>;
|
|
execute<
|
|
Result = {
|
|
count: number;
|
|
}[],
|
|
>(
|
|
method: 'all',
|
|
mapResults?: boolean,
|
|
): Promise<Result>;
|
|
execute<
|
|
Result = {
|
|
count: number;
|
|
},
|
|
>(
|
|
method: 'get',
|
|
mapResults?: boolean,
|
|
): Promise<Result>;
|
|
execute<
|
|
Result = QueryResult<{
|
|
count: number;
|
|
}>,
|
|
>(
|
|
method: 'run',
|
|
mapResults?: boolean,
|
|
): Promise<Result>;
|
|
}
|
|
export interface InsertQueryBuilder<
|
|
T extends object,
|
|
RootAlias extends string = never,
|
|
Context extends object = never,
|
|
> extends RunQueryBuilder<T, RootAlias, Context> {}
|
|
export interface UpdateQueryBuilder<
|
|
T extends object,
|
|
RootAlias extends string = never,
|
|
Context extends object = never,
|
|
> extends RunQueryBuilder<T, RootAlias, Context> {}
|
|
export interface DeleteQueryBuilder<
|
|
T extends object,
|
|
RootAlias extends string = never,
|
|
Context extends object = never,
|
|
> extends RunQueryBuilder<T, RootAlias, Context> {}
|
|
export interface TruncateQueryBuilder<T extends object> extends RunQueryBuilder<T> {}
|
|
export {};
|