mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
QueryBuilder is abstract now and all different kinds of query builders were created for different query types -
`SelectQueryBuilder`, `UpdateQueryBuilder`, `InsertQueryBuilder` and `DeleteQueryBuilder` with individual method available.
This commit is contained in:
parent
a019f03488
commit
b5140d245c
@ -75,6 +75,8 @@ of `QueryRunner`, e.g. `queryRunner.connection` and `queryRunner.manager`
|
||||
* refactored how query runner works, removed query runner provider
|
||||
* fixed some issues with sqlite, sqlite now strongly works on a single connection
|
||||
* `Connection` how has `createQueryRunner` that can be used to control database connection and its transaction state
|
||||
* `QueryBuilder` is abtract now and all different kinds of query builders were created for different query types -
|
||||
`SelectQueryBuilder`, `UpdateQueryBuilder`, `InsertQueryBuilder` and `DeleteQueryBuilder` with individual method available.
|
||||
|
||||
### BUG FIXES
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@ import {RepositoryFactory} from "../repository/RepositoryFactory";
|
||||
import {DriverFactory} from "../driver/DriverFactory";
|
||||
import {ConnectionMetadataBuilder} from "./ConnectionMetadataBuilder";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Connection is a single database ORM connection to a specific DBMS database.
|
||||
@ -368,28 +369,28 @@ export class Connection {
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder<Entity>(entityClass: ObjectType<Entity>|Function|string, alias: string, queryRunner?: QueryRunner): QueryBuilder<Entity>;
|
||||
createQueryBuilder<Entity>(entityClass: ObjectType<Entity>|Function|string, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity>;
|
||||
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder(queryRunner?: QueryRunner): QueryBuilder<any>;
|
||||
createQueryBuilder(queryRunner?: QueryRunner): SelectQueryBuilder<any>;
|
||||
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder<Entity>(entityClass?: ObjectType<Entity>|Function|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): QueryBuilder<Entity> {
|
||||
createQueryBuilder<Entity>(entityOrRunner?: ObjectType<Entity>|Function|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity> {
|
||||
if (this instanceof MongoEntityManager)
|
||||
throw new Error(`Query Builder is not supported by MongoDB.`);
|
||||
|
||||
if (alias) {
|
||||
const metadata = this.getMetadata(entityClass as Function|string);
|
||||
return new QueryBuilder(this, queryRunner)
|
||||
const metadata = this.getMetadata(entityOrRunner as Function|string);
|
||||
return new SelectQueryBuilder(this, queryRunner)
|
||||
.select(alias)
|
||||
.from(metadata.target, alias);
|
||||
|
||||
} else {
|
||||
return new QueryBuilder(this, entityClass as QueryRunner|undefined);
|
||||
return new SelectQueryBuilder(this, entityOrRunner as QueryRunner|undefined);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {RelationCountMetadataArgs} from "../../metadata-args/RelationCountMetadataArgs";
|
||||
import {QueryBuilder} from "../../query-builder/QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Holds a number of children in the closure table of the column.
|
||||
*/
|
||||
export function RelationCount<T>(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>): Function {
|
||||
export function RelationCount<T>(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
const args: RelationCountMetadataArgs = {
|
||||
target: object.constructor,
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
import {getMetadataArgsStorage} from "../../index";
|
||||
import {RelationIdMetadataArgs} from "../../metadata-args/RelationIdMetadataArgs";
|
||||
import {QueryBuilder} from "../../query-builder/QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Special decorator used to extract relation id into separate entity property.
|
||||
*/
|
||||
export function RelationId<T>(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>): Function {
|
||||
export function RelationId<T>(relation: string|((object: T) => any), alias?: string, queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
const args: RelationIdMetadataArgs = {
|
||||
target: object.constructor,
|
||||
|
||||
@ -23,6 +23,7 @@ import {getMetadataArgsStorage} from "../index";
|
||||
import {AbstractRepository} from "../repository/AbstractRepository";
|
||||
import {CustomRepositoryCannotInheritRepositoryError} from "../repository/error/CustomRepositoryCannotInheritRepositoryError";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Entity manager supposed to work with any entity, automatically find its repository and call its methods,
|
||||
@ -86,17 +87,17 @@ export class EntityManager {
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder<Entity>(entityClass: ObjectType<Entity>|Function|string, alias: string, queryRunner?: QueryRunner): QueryBuilder<Entity>;
|
||||
createQueryBuilder<Entity>(entityClass: ObjectType<Entity>|Function|string, alias: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity>;
|
||||
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder(queryRunner?: QueryRunner): QueryBuilder<any>;
|
||||
createQueryBuilder(queryRunner?: QueryRunner): SelectQueryBuilder<any>;
|
||||
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder<Entity>(entityClass?: ObjectType<Entity>|Function|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): QueryBuilder<Entity> {
|
||||
createQueryBuilder<Entity>(entityClass?: ObjectType<Entity>|Function|string|QueryRunner, alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity> {
|
||||
if (alias) {
|
||||
return this.connection.createQueryBuilder(entityClass as Function|string, alias, queryRunner || this.queryRunner);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {FindManyOptions} from "./FindManyOptions";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {FindOneOptions} from "./FindOneOptions";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Utilities to work with FindOptions.
|
||||
@ -59,7 +59,7 @@ export class FindOptionsUtils {
|
||||
/**
|
||||
* Applies give find one options to the given query builder.
|
||||
*/
|
||||
static applyFindOneOptionsOrConditionsToQueryBuilder<T>(qb: QueryBuilder<T>, options: FindOneOptions<T>|Partial<T>|undefined): QueryBuilder<T> {
|
||||
static applyFindOneOptionsOrConditionsToQueryBuilder<T>(qb: SelectQueryBuilder<T>, options: FindOneOptions<T>|Partial<T>|undefined): SelectQueryBuilder<T> {
|
||||
if (this.isFindOneOptions(options))
|
||||
return this.applyOptionsToQueryBuilder(qb, options);
|
||||
|
||||
@ -72,7 +72,7 @@ export class FindOptionsUtils {
|
||||
/**
|
||||
* Applies give find many options to the given query builder.
|
||||
*/
|
||||
static applyFindManyOptionsOrConditionsToQueryBuilder<T>(qb: QueryBuilder<T>, options: FindManyOptions<T>|Partial<T>|undefined): QueryBuilder<T> {
|
||||
static applyFindManyOptionsOrConditionsToQueryBuilder<T>(qb: SelectQueryBuilder<T>, options: FindManyOptions<T>|Partial<T>|undefined): SelectQueryBuilder<T> {
|
||||
if (this.isFindManyOptions(options))
|
||||
return this.applyOptionsToQueryBuilder(qb, options);
|
||||
|
||||
@ -85,7 +85,7 @@ export class FindOptionsUtils {
|
||||
/**
|
||||
* Applies give find options to the given query builder.
|
||||
*/
|
||||
static applyOptionsToQueryBuilder<T>(qb: QueryBuilder<T>, options: FindOneOptions<T>|FindManyOptions<T>|undefined): QueryBuilder<T> {
|
||||
static applyOptionsToQueryBuilder<T>(qb: SelectQueryBuilder<T>, options: FindOneOptions<T>|FindManyOptions<T>|undefined): SelectQueryBuilder<T> {
|
||||
|
||||
// if options are not set then simply return query builder. This is made for simplicity of usage.
|
||||
if (!options || !this.isFindOneOptions(options))
|
||||
@ -134,7 +134,7 @@ export class FindOptionsUtils {
|
||||
/**
|
||||
* Applies given simple conditions set to a given query builder.
|
||||
*/
|
||||
static applyConditions<T>(qb: QueryBuilder<T>, conditions: ObjectLiteral): QueryBuilder<T> {
|
||||
static applyConditions<T>(qb: SelectQueryBuilder<T>, conditions: ObjectLiteral): SelectQueryBuilder<T> {
|
||||
Object.keys(conditions).forEach((key, index) => {
|
||||
if (conditions![key] === null) {
|
||||
qb.andWhere(`${qb.alias}.${key} IS NULL`);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
/**
|
||||
* Arguments for RelationCountMetadata class.
|
||||
*/
|
||||
@ -27,6 +28,6 @@ export interface RelationCountMetadataArgs {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
readonly queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
readonly queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
/**
|
||||
* Arguments for RelationIdMetadataArgs class.
|
||||
*/
|
||||
@ -27,6 +28,6 @@ export interface RelationIdMetadataArgs {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
readonly queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
readonly queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import {RelationCountMetadataArgs} from "../metadata-args/RelationCountMetadataA
|
||||
import {EntityMetadata} from "./EntityMetadata";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {RelationMetadata} from "./RelationMetadata";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Contains all information about entity's relation count.
|
||||
@ -45,7 +46,7 @@ export class RelationCountMetadata {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
||||
@ -2,6 +2,7 @@ import {RelationIdMetadataArgs} from "../metadata-args/RelationIdMetadataArgs";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {EntityMetadata} from "./EntityMetadata";
|
||||
import {RelationMetadata} from "./RelationMetadata";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Contains all information about entity's relation count.
|
||||
@ -45,7 +46,7 @@ export class RelationIdMetadata {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
||||
57
src/query-builder/DeleteQueryBuilder.ts
Normal file
57
src/query-builder/DeleteQueryBuilder.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
|
||||
/**
|
||||
* Allows to build complex sql queries in a fashion way and execute those queries.
|
||||
*/
|
||||
export class DeleteQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets WHERE condition in the query builder.
|
||||
* If you had previously WHERE expression defined,
|
||||
* calling this function will override previously set WHERE conditions.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
where(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "simple", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new AND WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
andWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "and", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new OR WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
orWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "or", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones query builder as it is.
|
||||
* Note: it uses new query runner, if you want query builder that uses exactly same query runner,
|
||||
* you can create query builder this way: new DeleteQueryBuilder(queryBuilder) where queryBuilder
|
||||
* is cloned QueryBuilder.
|
||||
*/
|
||||
clone(): DeleteQueryBuilder<Entity> {
|
||||
const qb = new DeleteQueryBuilder<Entity>(this.connection);
|
||||
qb.expressionMap = this.expressionMap.clone();
|
||||
return qb;
|
||||
}
|
||||
|
||||
}
|
||||
24
src/query-builder/InsertQueryBuilder.ts
Normal file
24
src/query-builder/InsertQueryBuilder.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
|
||||
/**
|
||||
* Allows to build complex sql queries in a fashion way and execute those queries.
|
||||
*/
|
||||
export class InsertQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clones query builder as it is.
|
||||
* Note: it uses new query runner, if you want query builder that uses exactly same query runner,
|
||||
* you can create query builder this way: new InsertQueryBuilder(queryBuilder) where queryBuilder
|
||||
* is cloned QueryBuilder.
|
||||
*/
|
||||
clone(): InsertQueryBuilder<Entity> {
|
||||
const qb = new InsertQueryBuilder<Entity>(this.connection);
|
||||
qb.expressionMap = this.expressionMap.clone();
|
||||
return qb;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ export class QueryExpressionMap {
|
||||
/**
|
||||
* Represents query type. QueryBuilder is able to build SELECT, UPDATE and DELETE queries.
|
||||
*/
|
||||
queryType: "select"|"update"|"delete" = "select";
|
||||
queryType: "select"|"update"|"delete"|"insert" = "select";
|
||||
|
||||
/**
|
||||
* Data needs to be SELECT-ed.
|
||||
|
||||
942
src/query-builder/SelectQueryBuilder.ts
Normal file
942
src/query-builder/SelectQueryBuilder.ts
Normal file
@ -0,0 +1,942 @@
|
||||
import {RawSqlResultsToEntityTransformer} from "./transformer/RawSqlResultsToEntityTransformer";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SqlServerDriver} from "../driver/sqlserver/SqlServerDriver";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {JoinOptions} from "./JoinOptions";
|
||||
import {PessimisticLockTransactionRequiredError} from "./error/PessimisticLockTransactionRequiredError";
|
||||
import {NoVersionOrUpdateDateColumnError} from "./error/NoVersionOrUpdateDateColumnError";
|
||||
import {OptimisticLockVersionMismatchError} from "./error/OptimisticLockVersionMismatchError";
|
||||
import {OptimisticLockCanNotBeUsedError} from "./error/OptimisticLockCanNotBeUsedError";
|
||||
import {PostgresDriver} from "../driver/postgres/PostgresDriver";
|
||||
import {MysqlDriver} from "../driver/mysql/MysqlDriver";
|
||||
import {LockNotSupportedOnGivenDriverError} from "./error/LockNotSupportedOnGivenDriverError";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {JoinAttribute} from "./JoinAttribute";
|
||||
import {RelationIdAttribute} from "./relation-id/RelationIdAttribute";
|
||||
import {RelationCountAttribute} from "./relation-count/RelationCountAttribute";
|
||||
import {QueryExpressionMap} from "./QueryExpressionMap";
|
||||
import {SelectQuery} from "./SelectQuery";
|
||||
import {RelationIdLoader} from "./relation-id/RelationIdLoader";
|
||||
import {RelationIdLoadResult} from "./relation-id/RelationIdLoadResult";
|
||||
import {RelationIdMetadataToAttributeTransformer} from "./relation-id/RelationIdMetadataToAttributeTransformer";
|
||||
import {RelationCountLoadResult} from "./relation-count/RelationCountLoadResult";
|
||||
import {RelationCountLoader} from "./relation-count/RelationCountLoader";
|
||||
import {RelationCountMetadataToAttributeTransformer} from "./relation-count/RelationCountMetadataToAttributeTransformer";
|
||||
import {OracleDriver} from "../driver/oracle/OracleDriver";
|
||||
import {Broadcaster} from "../subscriber/Broadcaster";
|
||||
import {UpdateQueryBuilder} from "./UpdateQueryBuilder";
|
||||
import {DeleteQueryBuilder} from "./DeleteQueryBuilder";
|
||||
import {InsertQueryBuilder} from "./InsertQueryBuilder";
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
|
||||
/**
|
||||
* Allows to build complex sql queries in a fashion way and execute those queries.
|
||||
*/
|
||||
export class SelectQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* INNER JOINs (without selection) entity's property.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoin(property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs (without selection) given entity's table.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoin(entity: Function|string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs (without selection) given table.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoin(tableName: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs (without selection).
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoin(entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.join("INNER", entityOrProperty, aliasName, condition, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LEFT JOINs (without selection) entity's property.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoin(property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs (without selection) entity's table.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoin(entity: Function|string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs (without selection) given table.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoin(tableName: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs (without selection).
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoin(entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.join("LEFT", entityOrProperty, aliasName, condition, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* INNER JOINs entity's property and adds all selection properties to SELECT.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndSelect(property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs entity and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndSelect(entity: Function|string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs table and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndSelect(tableName: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndSelect(entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.innerJoin(entityOrProperty, aliasName, condition, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity's property and adds all selection properties to SELECT.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndSelect(property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndSelect(entity: Function|string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs table and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndSelect(tableName: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs and adds all selection properties to SELECT.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndSelect(entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.leftJoin(entityOrProperty, aliasName, condition, options);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* INNER JOINs entity's property, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapMany(mapToProperty: string, property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs entity's table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapMany(mapToProperty: string, entity: Function|string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapMany(mapToProperty: string, tableName: string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapMany(mapToProperty: string, entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.join("INNER", entityOrProperty, aliasName, condition, options, mapToProperty, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* INNER JOINs entity's property, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapOne(mapToProperty: string, property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs entity's table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapOne(mapToProperty: string, entity: Function|string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapOne(mapToProperty: string, tableName: string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* INNER JOINs, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
innerJoinAndMapOne(mapToProperty: string, entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.join("INNER", entityOrProperty, aliasName, condition, options, mapToProperty, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity's property, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapMany(mapToProperty: string, property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity's table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapMany(mapToProperty: string, entity: Function|string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapMany(mapToProperty: string, tableName: string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there are multiple rows of selecting data, and mapped result will be an array.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapMany(mapToProperty: string, entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.join("LEFT", entityOrProperty, aliasName, condition, options, mapToProperty, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity's property, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* Given entity property should be a relation.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapOne(mapToProperty: string, property: string, aliasName: string, condition?: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs entity's table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapOne(mapToProperty: string, entity: Function|string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs table, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapOne(mapToProperty: string, tableName: string, aliasName: string, condition: string, options?: JoinOptions): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs, SELECTs the data returned by a join and MAPs all that data to some entity's property.
|
||||
* This is extremely useful when you want to select some data and map it to some virtual property.
|
||||
* It will assume that there is a single row of selecting data, and mapped result will be a single selected value.
|
||||
* You also need to specify an alias of the joined data.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
leftJoinAndMapOne(mapToProperty: string, entityOrProperty: Function|string, aliasName: string, condition: string = "", options?: JoinOptions): this {
|
||||
this.addSelect(aliasName);
|
||||
this.join("LEFT", entityOrProperty, aliasName, condition, options, mapToProperty, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LEFT JOINs relation id and maps it into some entity's property.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
loadRelationIdAndMap(mapToProperty: string, relationName: string): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs relation id and maps it into some entity's property.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
loadRelationIdAndMap(mapToProperty: string, relationName: string, options: { disableMixedMap: boolean }): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs relation id and maps it into some entity's property.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
loadRelationIdAndMap(mapToProperty: string, relationName: string, aliasName: string, queryBuilderFactory: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): this;
|
||||
|
||||
/**
|
||||
* LEFT JOINs relation id and maps it into some entity's property.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
loadRelationIdAndMap(mapToProperty: string,
|
||||
relationName: string,
|
||||
aliasNameOrOptions?: string|{ disableMixedMap?: boolean },
|
||||
queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): this {
|
||||
const relationIdAttribute = new RelationIdAttribute(this.expressionMap);
|
||||
relationIdAttribute.mapToProperty = mapToProperty;
|
||||
relationIdAttribute.relationName = relationName;
|
||||
if (typeof aliasNameOrOptions === "string")
|
||||
relationIdAttribute.alias = aliasNameOrOptions;
|
||||
if (aliasNameOrOptions instanceof Object && (aliasNameOrOptions as any).disableMixedMap)
|
||||
relationIdAttribute.disableMixedMap = true;
|
||||
|
||||
relationIdAttribute.queryBuilderFactory = queryBuilderFactory;
|
||||
this.expressionMap.relationIdAttributes.push(relationIdAttribute);
|
||||
|
||||
if (relationIdAttribute.relation.junctionEntityMetadata) {
|
||||
this.expressionMap.createAlias({
|
||||
name: relationIdAttribute.junctionAlias,
|
||||
metadata: relationIdAttribute.relation.junctionEntityMetadata
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts number of entities of entity's relation and maps the value into some entity's property.
|
||||
* Optionally, you can add condition and parameters used in condition.
|
||||
*/
|
||||
loadRelationCountAndMap(mapToProperty: string, relationName: string, aliasName?: string, queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>): this {
|
||||
const relationCountAttribute = new RelationCountAttribute(this.expressionMap);
|
||||
relationCountAttribute.mapToProperty = mapToProperty;
|
||||
relationCountAttribute.relationName = relationName;
|
||||
relationCountAttribute.alias = aliasName;
|
||||
relationCountAttribute.queryBuilderFactory = queryBuilderFactory;
|
||||
this.expressionMap.relationCountAttributes.push(relationCountAttribute);
|
||||
|
||||
this.expressionMap.createAlias({
|
||||
name: relationCountAttribute.junctionAlias
|
||||
});
|
||||
if (relationCountAttribute.relation.junctionEntityMetadata) {
|
||||
this.expressionMap.createAlias({
|
||||
name: relationCountAttribute.junctionAlias,
|
||||
metadata: relationCountAttribute.relation.junctionEntityMetadata
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets WHERE condition in the query builder.
|
||||
* If you had previously WHERE expression defined,
|
||||
* calling this function will override previously set WHERE conditions.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
where(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "simple", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new AND WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
andWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "and", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new OR WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
orWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "or", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets HAVING condition in the query builder.
|
||||
* If you had previously HAVING expression defined,
|
||||
* calling this function will override previously set HAVING conditions.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
having(having: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.havings.push({ type: "simple", condition: having });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new AND HAVING condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
andHaving(having: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.havings.push({ type: "and", condition: having });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new OR HAVING condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
orHaving(having: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.havings.push({ type: "or", condition: having });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets GROUP BY condition in the query builder.
|
||||
* If you had previously GROUP BY expression defined,
|
||||
* calling this function will override previously set GROUP BY conditions.
|
||||
*/
|
||||
groupBy(groupBy: string): this {
|
||||
this.expressionMap.groupBys = [groupBy];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds GROUP BY condition in the query builder.
|
||||
*/
|
||||
addGroupBy(groupBy: string): this {
|
||||
this.expressionMap.groupBys.push(groupBy);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets ORDER BY condition in the query builder.
|
||||
* If you had previously ORDER BY expression defined,
|
||||
* calling this function will override previously set ORDER BY conditions.
|
||||
*/
|
||||
orderBy(sort: string, order?: "ASC"|"DESC"): this;
|
||||
|
||||
/**
|
||||
* Sets ORDER BY condition in the query builder.
|
||||
* If you had previously ORDER BY expression defined,
|
||||
* calling this function will override previously set ORDER BY conditions.
|
||||
*/
|
||||
orderBy(sort: undefined): this;
|
||||
|
||||
/**
|
||||
* Sets ORDER BY condition in the query builder.
|
||||
* If you had previously ORDER BY expression defined,
|
||||
* calling this function will override previously set ORDER BY conditions.
|
||||
*/
|
||||
orderBy(sort?: string, order: "ASC"|"DESC" = "ASC"): this {
|
||||
if (sort) {
|
||||
this.expressionMap.orderBys = { [sort]: order };
|
||||
} else {
|
||||
this.expressionMap.orderBys = {};
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds ORDER BY condition in the query builder.
|
||||
*/
|
||||
addOrderBy(sort: string, order: "ASC"|"DESC" = "ASC"): this {
|
||||
this.expressionMap.orderBys[sort] = order;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set's LIMIT - maximum number of rows to be selected.
|
||||
* NOTE that it may not work as you expect if you are using joins.
|
||||
* If you want to implement pagination, and you are having join in your query,
|
||||
* then use instead take method instead.
|
||||
*/
|
||||
limit(limit?: number): this {
|
||||
this.expressionMap.limit = limit;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set's OFFSET - selection offset.
|
||||
* NOTE that it may not work as you expect if you are using joins.
|
||||
* If you want to implement pagination, and you are having join in your query,
|
||||
* then use instead skip method instead.
|
||||
*/
|
||||
offset(offset?: number): this {
|
||||
this.expressionMap.offset = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximal number of entities to take.
|
||||
*/
|
||||
take(take?: number): this {
|
||||
this.expressionMap.take = take;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of entities to skip.
|
||||
*/
|
||||
skip(skip?: number): this {
|
||||
this.expressionMap.skip = skip;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maximal number of entities to take.
|
||||
*
|
||||
* @deprecated use take method instead
|
||||
*/
|
||||
setMaxResults(take?: number): this {
|
||||
this.expressionMap.take = take;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of entities to skip.
|
||||
*
|
||||
* @deprecated use skip method instead
|
||||
*/
|
||||
setFirstResult(skip?: number): this {
|
||||
this.expressionMap.skip = skip;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets locking mode.
|
||||
*/
|
||||
setLock(lockMode: "optimistic", lockVersion: number): this;
|
||||
|
||||
/**
|
||||
* Sets locking mode.
|
||||
*/
|
||||
setLock(lockMode: "optimistic", lockVersion: Date): this;
|
||||
|
||||
/**
|
||||
* Sets locking mode.
|
||||
*/
|
||||
setLock(lockMode: "pessimistic_read"|"pessimistic_write"): this;
|
||||
|
||||
/**
|
||||
* Sets locking mode.
|
||||
*/
|
||||
setLock(lockMode: "optimistic"|"pessimistic_read"|"pessimistic_write", lockVersion?: number|Date): this {
|
||||
this.expressionMap.lockMode = lockMode;
|
||||
this.expressionMap.lockVersion = lockVersion;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes sql generated by query builder and returns object with raw results and entities created from them.
|
||||
*/
|
||||
async getEntitiesAndRawResults(): Promise<{ entities: Entity[], rawResults: any[] }> {
|
||||
const broadcaster = new Broadcaster(this.connection);
|
||||
const relationIdLoader = new RelationIdLoader(this.connection, this.queryRunner, this.expressionMap.relationIdAttributes);
|
||||
const relationCountLoader = new RelationCountLoader(this.connection, this.queryRunner, this.expressionMap.relationCountAttributes);
|
||||
const relationIdMetadataTransformer = new RelationIdMetadataToAttributeTransformer(this.expressionMap);
|
||||
relationIdMetadataTransformer.transform();
|
||||
const relationCountMetadataTransformer = new RelationCountMetadataToAttributeTransformer(this.expressionMap);
|
||||
relationCountMetadataTransformer.transform();
|
||||
|
||||
try {
|
||||
if (!this.expressionMap.mainAlias)
|
||||
throw new Error(`Alias is not set. Looks like nothing is selected. Use select*, delete, update method to set an alias.`);
|
||||
|
||||
if ((this.expressionMap.lockMode === "pessimistic_read" || this.expressionMap.lockMode === "pessimistic_write") && !this.queryRunner.isTransactionActive)
|
||||
throw new PessimisticLockTransactionRequiredError();
|
||||
|
||||
if (this.expressionMap.lockMode === "optimistic") {
|
||||
const metadata = this.expressionMap.mainAlias!.metadata;
|
||||
if (!metadata.versionColumn && !metadata.updateDateColumn)
|
||||
throw new NoVersionOrUpdateDateColumnError(metadata.name);
|
||||
}
|
||||
|
||||
const mainAliasName = this.expressionMap.mainAlias.name;
|
||||
if (this.expressionMap.skip || this.expressionMap.take) {
|
||||
// we are skipping order by here because its not working in subqueries anyway
|
||||
// to make order by working we need to apply it on a distinct query
|
||||
const [sql, parameters] = this.getSqlWithParameters({ skipOrderBy: true });
|
||||
const [selects, orderBys] = this.createOrderByCombinedWithSelectExpression("distinctAlias");
|
||||
|
||||
const distinctAlias = this.escapeTable("distinctAlias");
|
||||
const metadata = this.expressionMap.mainAlias!.metadata;
|
||||
let idsQuery = `SELECT `;
|
||||
idsQuery += metadata.primaryColumns.map((primaryColumn, index) => {
|
||||
const propertyName = this.escapeAlias(mainAliasName + "_" + primaryColumn.databaseName);
|
||||
if (index === 0) {
|
||||
return `DISTINCT(${distinctAlias}.${propertyName}) as "ids_${primaryColumn.databaseName}"`;
|
||||
} else {
|
||||
return `${distinctAlias}.${propertyName}) as "ids_${primaryColumn.databaseName}"`;
|
||||
}
|
||||
}).join(", ");
|
||||
if (selects.length > 0)
|
||||
idsQuery += ", " + selects;
|
||||
|
||||
idsQuery += ` FROM (${sql}) ${distinctAlias}`; // TODO: WHAT TO DO WITH PARAMETERS HERE? DO THEY WORK?
|
||||
|
||||
if (orderBys.length > 0) {
|
||||
idsQuery += " ORDER BY " + orderBys;
|
||||
} else {
|
||||
idsQuery += ` ORDER BY "ids_${metadata.primaryColumns[0].databaseName}"`; // this is required for mssql driver if firstResult is used. Other drivers don't care about it
|
||||
}
|
||||
|
||||
if (this.connection.driver instanceof SqlServerDriver) { // todo: temporary. need to refactor and make a proper abstraction
|
||||
|
||||
if (this.expressionMap.skip || this.expressionMap.take) {
|
||||
idsQuery += ` OFFSET ${this.expressionMap.skip || 0} ROWS`;
|
||||
if (this.expressionMap.take)
|
||||
idsQuery += " FETCH NEXT " + this.expressionMap.take + " ROWS ONLY";
|
||||
}
|
||||
} else {
|
||||
|
||||
if (this.expressionMap.take)
|
||||
idsQuery += " LIMIT " + this.expressionMap.take;
|
||||
if (this.expressionMap.skip)
|
||||
idsQuery += " OFFSET " + this.expressionMap.skip;
|
||||
}
|
||||
|
||||
let entities: any[] = [];
|
||||
let rawResults: any[] = await this.queryRunner.query(idsQuery, parameters);
|
||||
if (rawResults.length > 0) {
|
||||
let condition = "";
|
||||
const parameters: ObjectLiteral = {};
|
||||
if (metadata.hasMultiplePrimaryKeys) {
|
||||
condition = rawResults.map(result => {
|
||||
return metadata.primaryColumns.map(primaryColumn => {
|
||||
parameters["ids_" + primaryColumn.propertyName] = result["ids_" + primaryColumn.propertyName];
|
||||
return mainAliasName + "." + primaryColumn.propertyName + "=:ids_" + primaryColumn.propertyName;
|
||||
}).join(" AND ");
|
||||
}).join(" OR ");
|
||||
} else {
|
||||
const ids = rawResults.map(result => result["ids_" + metadata.primaryColumns[0].propertyName]);
|
||||
const areAllNumbers = ids.every((id: any) => typeof id === "number");
|
||||
if (areAllNumbers) {
|
||||
// fixes #190. if all numbers then its safe to perform query without parameter
|
||||
condition = `${mainAliasName}.${metadata.primaryColumns[0].propertyName} IN (${ids.join(", ")})`;
|
||||
} else {
|
||||
parameters["ids"] = ids;
|
||||
condition = mainAliasName + "." + metadata.primaryColumns[0].propertyName + " IN (:ids)";
|
||||
}
|
||||
}
|
||||
const clonnedQb = new SelectQueryBuilder(this);
|
||||
clonnedQb.expressionMap.extraAppendedAndWhereCondition = condition;
|
||||
const [queryWithIdsSql, queryWithIdsParameters] = clonnedQb
|
||||
.setParameters(parameters)
|
||||
.getSqlWithParameters();
|
||||
rawResults = await this.queryRunner.query(queryWithIdsSql, queryWithIdsParameters);
|
||||
const rawRelationIdResults = await relationIdLoader.load(rawResults);
|
||||
const rawRelationCountResults = await relationCountLoader.load(rawResults);
|
||||
entities = this.rawResultsToEntities(rawResults, rawRelationIdResults, rawRelationCountResults);
|
||||
if (this.expressionMap.mainAlias.hasMetadata) {
|
||||
await broadcaster.broadcastLoadEventsForAll(this.expressionMap.mainAlias.target, rawResults);
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
entities: entities,
|
||||
rawResults: rawResults
|
||||
};
|
||||
|
||||
} else {
|
||||
|
||||
const [sql, parameters] = this.getSqlWithParameters();
|
||||
|
||||
const rawResults = await this.queryRunner.query(sql, parameters);
|
||||
|
||||
const rawRelationIdResults = await relationIdLoader.load(rawResults);
|
||||
const rawRelationCountResults = await relationCountLoader.load(rawResults);
|
||||
const entities = this.rawResultsToEntities(rawResults, rawRelationIdResults, rawRelationCountResults);
|
||||
if (this.expressionMap.mainAlias.hasMetadata)
|
||||
await broadcaster.broadcastLoadEventsForAll(this.expressionMap.mainAlias.target, rawResults);
|
||||
|
||||
return {
|
||||
entities: entities,
|
||||
rawResults: rawResults
|
||||
};
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (this.ownQueryRunner) // means we created our own query runner
|
||||
await this.queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets count - number of entities selected by sql generated by this query builder.
|
||||
* Count excludes all limitations set by setFirstResult and setMaxResults methods call.
|
||||
*/
|
||||
async getCount(): Promise<number> {
|
||||
if (this.expressionMap.lockMode === "optimistic")
|
||||
throw new OptimisticLockCanNotBeUsedError();
|
||||
|
||||
const mainAlias = this.expressionMap.mainAlias!.name; // todo: will this work with "fromTableName"?
|
||||
const metadata = this.expressionMap.mainAlias!.metadata;
|
||||
|
||||
const distinctAlias = this.escapeAlias(mainAlias);
|
||||
let countSql = `COUNT(` + metadata.primaryColumns.map((primaryColumn, index) => {
|
||||
const propertyName = this.escapeColumn(primaryColumn.databaseName);
|
||||
if (index === 0) {
|
||||
return `DISTINCT(${distinctAlias}.${propertyName})`;
|
||||
} else {
|
||||
return `${distinctAlias}.${propertyName})`;
|
||||
}
|
||||
}).join(", ") + ") as \"cnt\"";
|
||||
|
||||
const countQueryBuilder = new SelectQueryBuilder(this)
|
||||
.orderBy(undefined)
|
||||
.offset(undefined)
|
||||
.limit(undefined)
|
||||
.select(countSql);
|
||||
countQueryBuilder.expressionMap.ignoreParentTablesJoins = true;
|
||||
|
||||
const [countQuerySql, countQueryParameters] = countQueryBuilder.getSqlWithParameters();
|
||||
|
||||
try {
|
||||
const results = await this.queryRunner.query(countQuerySql, countQueryParameters);
|
||||
if (!results || !results[0] || !results[0]["cnt"])
|
||||
return 0;
|
||||
|
||||
return parseInt(results[0]["cnt"]);
|
||||
|
||||
} finally {
|
||||
if (this.ownQueryRunner) // means we created our own query runner
|
||||
await this.queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all raw results returned by execution of generated query builder sql.
|
||||
*/
|
||||
async getRawMany(): Promise<any[]> {
|
||||
if (this.expressionMap.lockMode === "optimistic")
|
||||
throw new OptimisticLockCanNotBeUsedError();
|
||||
|
||||
return this.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets first raw result returned by execution of generated query builder sql.
|
||||
*/
|
||||
async getRawOne(): Promise<any> {
|
||||
if (this.expressionMap.lockMode === "optimistic")
|
||||
throw new OptimisticLockCanNotBeUsedError();
|
||||
|
||||
const results = await this.execute();
|
||||
return results[0];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets entities and count returned by execution of generated query builder sql.
|
||||
*/
|
||||
async getManyAndCount(): Promise<[Entity[], number]> {
|
||||
if (this.expressionMap.lockMode === "optimistic")
|
||||
throw new OptimisticLockCanNotBeUsedError();
|
||||
|
||||
// todo: share database connection and counter
|
||||
return Promise.all([
|
||||
this.getMany(),
|
||||
this.getCount()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets entities returned by execution of generated query builder sql.
|
||||
*/
|
||||
async getMany(): Promise<Entity[]> {
|
||||
if (this.expressionMap.lockMode === "optimistic")
|
||||
throw new OptimisticLockCanNotBeUsedError();
|
||||
|
||||
const results = await this.getEntitiesAndRawResults();
|
||||
return results.entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets single entity returned by execution of generated query builder sql.
|
||||
*/
|
||||
async getOne(): Promise<Entity|undefined> {
|
||||
const results = await this.getEntitiesAndRawResults();
|
||||
const result = results.entities[0] as any;
|
||||
|
||||
if (result && this.expressionMap.lockMode === "optimistic" && this.expressionMap.lockVersion) {
|
||||
const metadata = this.expressionMap.mainAlias!.metadata;
|
||||
|
||||
if (this.expressionMap.lockVersion instanceof Date) {
|
||||
const actualVersion = result[metadata.updateDateColumn!.propertyName]; // what if columns arent set?
|
||||
this.expressionMap.lockVersion.setMilliseconds(0);
|
||||
if (actualVersion.getTime() !== this.expressionMap.lockVersion.getTime())
|
||||
throw new OptimisticLockVersionMismatchError(metadata.name, this.expressionMap.lockVersion, actualVersion);
|
||||
|
||||
} else {
|
||||
const actualVersion = result[metadata.versionColumn!.propertyName]; // what if columns arent set?
|
||||
if (actualVersion !== this.expressionMap.lockVersion)
|
||||
throw new OptimisticLockVersionMismatchError(metadata.name, this.expressionMap.lockVersion, actualVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones query builder as it is.
|
||||
* Note: it uses new query runner, if you want query builder that uses exactly same query runner,
|
||||
* you can create query builder this way: new SelectQueryBuilder(queryBuilder) where queryBuilder
|
||||
* is cloned QueryBuilder.
|
||||
*/
|
||||
clone(): SelectQueryBuilder<Entity> {
|
||||
const qb = new SelectQueryBuilder<Entity>(this.connection);
|
||||
qb.expressionMap = this.expressionMap.clone();
|
||||
return qb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables special query builder options.
|
||||
*
|
||||
* @deprecated looks like enableRelationIdValues is not used anymore. What to do? Remove this method? What about persistence?
|
||||
*/
|
||||
enableAutoRelationIdsLoad(): this {
|
||||
this.expressionMap.mainAlias!.metadata.relations.forEach(relation => {
|
||||
this.loadRelationIdAndMap(this.expressionMap.mainAlias!.name + "." + relation.propertyPath,
|
||||
this.expressionMap.mainAlias!.name + "." + relation.propertyPath,
|
||||
{ disableMixedMap: true });
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new AND WHERE with conditions for the given ids.
|
||||
*
|
||||
* @experimental Maybe this method should be moved to repository?
|
||||
* @deprecated
|
||||
*/
|
||||
andWhereInIds(ids: any[]): this {
|
||||
const [whereExpression, parameters] = this.createWhereIdsExpression(ids);
|
||||
this.andWhere(whereExpression, parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new OR WHERE with conditions for the given ids.
|
||||
*
|
||||
* @experimental Maybe this method should be moved to repository?
|
||||
* @deprecated
|
||||
*/
|
||||
orWhereInIds(ids: any[]): this {
|
||||
const [whereExpression, parameters] = this.createWhereIdsExpression(ids);
|
||||
this.orWhere(whereExpression, parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected join(direction: "INNER"|"LEFT", entityOrProperty: Function|string, aliasName: string, condition?: string, options?: JoinOptions, mapToProperty?: string, isMappingMany?: boolean): void {
|
||||
|
||||
const joinAttribute = new JoinAttribute(this.connection, this.expressionMap);
|
||||
joinAttribute.direction = direction;
|
||||
joinAttribute.mapToProperty = mapToProperty;
|
||||
joinAttribute.options = options;
|
||||
joinAttribute.isMappingMany = isMappingMany;
|
||||
joinAttribute.entityOrProperty = entityOrProperty; // relationName
|
||||
joinAttribute.condition = condition; // joinInverseSideCondition
|
||||
// joinAttribute.junctionAlias = joinAttribute.relation.isOwning ? parentAlias + "_" + destinationTableAlias : destinationTableAlias + "_" + parentAlias;
|
||||
this.expressionMap.joinAttributes.push(joinAttribute);
|
||||
|
||||
// todo: find and set metadata right there?
|
||||
joinAttribute.alias = this.expressionMap.createAlias({
|
||||
name: aliasName,
|
||||
metadata: joinAttribute.metadata!
|
||||
});
|
||||
if (joinAttribute.relation && joinAttribute.relation.junctionEntityMetadata) {
|
||||
this.expressionMap.createAlias({
|
||||
name: joinAttribute.junctionAlias,
|
||||
metadata: joinAttribute.relation.junctionEntityMetadata
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected rawResultsToEntities(results: any[], rawRelationIdResults: RelationIdLoadResult[], rawRelationCountResults: RelationCountLoadResult[]) {
|
||||
return new RawSqlResultsToEntityTransformer(this.connection.driver, this.expressionMap.joinAttributes, rawRelationIdResults, rawRelationCountResults)
|
||||
.transform(results, this.expressionMap.mainAlias!);
|
||||
}
|
||||
|
||||
}
|
||||
57
src/query-builder/UpdateQueryBuilder.ts
Normal file
57
src/query-builder/UpdateQueryBuilder.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import {QueryBuilder} from "./QueryBuilder";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
|
||||
/**
|
||||
* Allows to build complex sql queries in a fashion way and execute those queries.
|
||||
*/
|
||||
export class UpdateQueryBuilder<Entity> extends QueryBuilder<Entity> {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sets WHERE condition in the query builder.
|
||||
* If you had previously WHERE expression defined,
|
||||
* calling this function will override previously set WHERE conditions.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
where(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "simple", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new AND WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
andWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "and", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new OR WHERE condition in the query builder.
|
||||
* Additionally you can add parameters used in where expression.
|
||||
*/
|
||||
orWhere(where: string, parameters?: ObjectLiteral): this {
|
||||
this.expressionMap.wheres.push({ type: "or", condition: where });
|
||||
if (parameters) this.setParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones query builder as it is.
|
||||
* Note: it uses new query runner, if you want query builder that uses exactly same query runner,
|
||||
* you can create query builder this way: new UpdateQueryBuilder(queryBuilder) where queryBuilder
|
||||
* is cloned QueryBuilder.
|
||||
*/
|
||||
clone(): UpdateQueryBuilder<Entity> {
|
||||
const qb = new UpdateQueryBuilder<Entity>(this.connection);
|
||||
qb.expressionMap = this.expressionMap.clone();
|
||||
return qb;
|
||||
}
|
||||
|
||||
}
|
||||
@ -3,6 +3,7 @@ import {QueryBuilderUtils} from "../QueryBuilderUtils";
|
||||
import {RelationMetadata} from "../../metadata/RelationMetadata";
|
||||
import {QueryExpressionMap} from "../QueryExpressionMap";
|
||||
import {QueryBuilder} from "../QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../SelectQueryBuilder";
|
||||
|
||||
export class RelationCountAttribute {
|
||||
|
||||
@ -24,7 +25,7 @@ export class RelationCountAttribute {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
|
||||
@ -3,6 +3,7 @@ import {QueryBuilderUtils} from "../QueryBuilderUtils";
|
||||
import {EntityMetadata} from "../../metadata/EntityMetadata";
|
||||
import {QueryBuilder} from "../QueryBuilder";
|
||||
import {QueryExpressionMap} from "../QueryExpressionMap";
|
||||
import {SelectQueryBuilder} from "../SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Stores all join relation id attributes which will be used to build a JOIN query.
|
||||
@ -31,7 +32,7 @@ export class RelationIdAttribute {
|
||||
/**
|
||||
* Extra condition applied to "ON" section of join.
|
||||
*/
|
||||
queryBuilderFactory?: (qb: QueryBuilder<any>) => QueryBuilder<any>;
|
||||
queryBuilderFactory?: (qb: SelectQueryBuilder<any>) => SelectQueryBuilder<any>;
|
||||
|
||||
/**
|
||||
* Indicates if relation id should NOT be loaded as id map.
|
||||
|
||||
@ -7,6 +7,7 @@ import {ObjectType} from "../common/ObjectType";
|
||||
import {CustomRepositoryDoesNotHaveEntityError} from "./error/CustomRepositoryDoesNotHaveEntityError";
|
||||
import {getMetadataArgsStorage} from "../index";
|
||||
import {CustomRepositoryNotFoundError} from "./error/CustomRepositoryNotFoundError";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Provides abstract class for custom repositories that do not inherit from original orm Repository.
|
||||
@ -62,7 +63,7 @@ export class AbstractRepository<Entity extends ObjectLiteral> {
|
||||
* Creates a new query builder for the repository's entity that can be used to build a sql query.
|
||||
* If current repository does not manage any entity, then exception will be thrown.
|
||||
*/
|
||||
protected createQueryBuilder(alias: string): QueryBuilder<Entity> {
|
||||
protected createQueryBuilder(alias: string): SelectQueryBuilder<Entity> {
|
||||
const target = this.getCustomRepositoryTarget(this.constructor);
|
||||
if (!target)
|
||||
throw new CustomRepositoryDoesNotHaveEntityError(this.constructor);
|
||||
@ -73,7 +74,7 @@ export class AbstractRepository<Entity extends ObjectLiteral> {
|
||||
/**
|
||||
* Creates a new query builder for the given entity that can be used to build a sql query.
|
||||
*/
|
||||
protected createQueryBuilderFor<T>(entity: ObjectType<T>, alias: string): QueryBuilder<T> {
|
||||
protected createQueryBuilderFor<T>(entity: ObjectType<T>, alias: string): SelectQueryBuilder<T> {
|
||||
return this.getRepositoryFor(entity).createQueryBuilder(alias);
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import {RemoveOptions} from "./RemoveOptions";
|
||||
import {FindManyOptions} from "../find-options/FindManyOptions";
|
||||
import {Connection} from "../connection/Connection";
|
||||
import {ObjectType} from "../common/ObjectType";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Base abstract entity for all entities, used in ActiveRecord patterns.
|
||||
@ -96,7 +97,7 @@ export class EntityModel {
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
static createQueryBuilder<T extends EntityModel>(this: ObjectType<T>, alias: string): QueryBuilder<T> {
|
||||
static createQueryBuilder<T extends EntityModel>(this: ObjectType<T>, alias: string): SelectQueryBuilder<T> {
|
||||
return (this as any).getRepository().createQueryBuilder(alias);
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,7 @@ import {
|
||||
} from "../driver/mongodb/typings";
|
||||
import {MongoEntityManager} from "../entity-manager/MongoEntityManager";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Repository used to manage mongodb documents of a single entity type.
|
||||
@ -66,7 +67,7 @@ export class MongoRepository<Entity extends ObjectLiteral> extends Repository<En
|
||||
* Using Query Builder with MongoDB is not supported yet.
|
||||
* Calling this method will return an error.
|
||||
*/
|
||||
createQueryBuilder(alias: string, queryRunner?: QueryRunner): QueryBuilder<Entity> {
|
||||
createQueryBuilder(alias: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity> {
|
||||
throw new Error(`Query Builder is not supported by MongoDB.`);
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import {SaveOptions} from "./SaveOptions";
|
||||
import {RemoveOptions} from "./RemoveOptions";
|
||||
import {EntityManager} from "../entity-manager/EntityManager";
|
||||
import {QueryRunner} from "../query-runner/QueryRunner";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Repository is supposed to work with your entity objects. Find entities, insert, update, delete, etc.
|
||||
@ -64,7 +65,7 @@ export class Repository<Entity extends ObjectLiteral> {
|
||||
/**
|
||||
* Creates a new query builder that can be used to build a sql query.
|
||||
*/
|
||||
createQueryBuilder(alias: string, queryRunner?: QueryRunner): QueryBuilder<Entity> {
|
||||
createQueryBuilder(alias: string, queryRunner?: QueryRunner): SelectQueryBuilder<Entity> {
|
||||
return this.manager.createQueryBuilder(this.metadata.target, alias, queryRunner || this.queryRunner);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {Repository} from "./Repository";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {SelectQueryBuilder} from "../query-builder/SelectQueryBuilder";
|
||||
|
||||
/**
|
||||
* Repository with additional functions to work with trees.
|
||||
@ -41,7 +42,7 @@ export class TreeRepository<Entity> extends Repository<Entity> {
|
||||
/**
|
||||
* Creates a query builder used to get descendants of the entities in a tree.
|
||||
*/
|
||||
createDescendantsQueryBuilder(alias: string, closureTableAlias: string, entity: Entity): QueryBuilder<Entity> {
|
||||
createDescendantsQueryBuilder(alias: string, closureTableAlias: string, entity: Entity): SelectQueryBuilder<Entity> {
|
||||
|
||||
// create shortcuts for better readability
|
||||
const escapeAlias = (alias: string) => this.manager.connection.driver.escapeAlias(alias);
|
||||
@ -89,7 +90,7 @@ export class TreeRepository<Entity> extends Repository<Entity> {
|
||||
/**
|
||||
* Creates a query builder used to get ancestors of the entities in the tree.
|
||||
*/
|
||||
createAncestorsQueryBuilder(alias: string, closureTableAlias: string, entity: Entity): QueryBuilder<Entity> {
|
||||
createAncestorsQueryBuilder(alias: string, closureTableAlias: string, entity: Entity): SelectQueryBuilder<Entity> {
|
||||
|
||||
// create shortcuts for better readability
|
||||
const escapeAlias = (alias: string) => this.manager.connection.driver.escapeAlias(alias);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user