refactoring query runner - moved transaction active status into the query runner itself

This commit is contained in:
Umed Khudoiberdiev 2017-06-13 18:22:16 +05:00
parent f1c566f2ef
commit 90eacdfcea
19 changed files with 123 additions and 127 deletions

View File

@ -18,11 +18,6 @@ export interface DatabaseConnection {
*/
transaction?: any;
/**
* Indicates if transaction is active for this connection.
*/
isTransactionActive: boolean;
/**
* Special function that holds a connection release logic.
* Releases connection when its called.

View File

@ -98,8 +98,7 @@ export class MongoDriver implements Driver {
this.databaseConnection = dbConnection;
const databaseConnection: DatabaseConnection = {
id: 1,
connection: dbConnection,
isTransactionActive: false
connection: dbConnection
};
this.queryRunner = new MongoQueryRunner(this.connection, databaseConnection);
ok();

View File

@ -45,6 +45,23 @@ import {Connection} from "../../connection/Connection";
*/
export class MongoQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
* Always false for mongodb since mongodb has a single query executor instance.
*/
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
* Always false for mongodb since mongodb does not support transactions.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
@ -338,13 +355,6 @@ export class MongoQueryRunner implements QueryRunner {
// transactions are not supported by mongodb driver, so simply don't do anything here
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
}
/**
* Executes a given SQL query.
*/

View File

@ -298,7 +298,6 @@ export class MysqlDriver implements Driver {
dbConnection = {
id: this.databaseConnections.length,
connection: connection,
isTransactionActive: false,
releaseCallback: function() {
if (driver.pool) {
connection.release();

View File

@ -22,14 +22,19 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class MysqlQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
@ -95,10 +100,10 @@ export class MysqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
await this.query("START TRANSACTION");
}
@ -109,11 +114,11 @@ export class MysqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("COMMIT");
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
}
/**
@ -123,18 +128,11 @@ export class MysqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("ROLLBACK");
this.databaseConnection.isTransactionActive = false;
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
this.isTransactionActive = false;
}
/**

View File

@ -314,7 +314,6 @@ export class OracleDriver implements Driver {
dbConnection = {
id: this.databaseConnectionPool.length,
connection: connection,
isTransactionActive: false
};
dbConnection.releaseCallback = () => {
return new Promise<void>((ok, fail) => {

View File

@ -24,14 +24,19 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class OracleQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
@ -96,11 +101,11 @@ export class OracleQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
// await this.query("START TRANSACTION");
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
}
/**
@ -110,11 +115,11 @@ export class OracleQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("COMMIT");
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
}
/**
@ -124,18 +129,11 @@ export class OracleQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("ROLLBACK");
this.databaseConnection.isTransactionActive = false;
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
this.isTransactionActive = false;
}
/**
@ -157,7 +155,7 @@ export class OracleQueryRunner implements QueryRunner {
ok(result.rows || result.outBinds);
};
const executionOptions = {
autoCommit: this.databaseConnection.isTransactionActive ? false : true
autoCommit: this.isTransactionActive ? false : true
};
this.databaseConnection.connection.execute(query, parameters || {}, executionOptions, handler);
});

View File

@ -335,8 +335,7 @@ export class PostgresDriver implements Driver {
if (!dbConnection) {
dbConnection = {
id: this.databaseConnectionPool.length,
connection: connection,
isTransactionActive: false
connection: connection
};
this.databaseConnectionPool.push(dbConnection);
}

View File

@ -22,16 +22,25 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class PostgresQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
private schemaName: string;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
protected schemaName: string;
// -------------------------------------------------------------------------
// Constructor
@ -89,10 +98,10 @@ export class PostgresQueryRunner implements QueryRunner {
async beginTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
await this.query("START TRANSACTION");
}
@ -102,11 +111,11 @@ export class PostgresQueryRunner implements QueryRunner {
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("COMMIT");
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
}
/**
@ -115,18 +124,11 @@ export class PostgresQueryRunner implements QueryRunner {
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("ROLLBACK");
this.databaseConnection.isTransactionActive = false;
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
this.isTransactionActive = false;
}
/**

View File

@ -125,8 +125,7 @@ export class SqliteDriver implements Driver {
this.databaseConnection = {
id: 1,
connection: connection,
isTransactionActive: false
connection: connection
};
// we need to enable foreign keys in sqlite to make sure all foreign key related features

View File

@ -25,14 +25,19 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class SqliteQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
@ -90,10 +95,10 @@ export class SqliteQueryRunner implements QueryRunner {
async beginTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
await this.query("BEGIN TRANSACTION");
}
@ -103,11 +108,11 @@ export class SqliteQueryRunner implements QueryRunner {
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("COMMIT");
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
}
/**
@ -116,18 +121,11 @@ export class SqliteQueryRunner implements QueryRunner {
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
await this.query("ROLLBACK");
this.databaseConnection.isTransactionActive = false;
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
this.isTransactionActive = false;
}
/**

View File

@ -315,8 +315,7 @@ export class SqlServerDriver implements Driver {
return new Promise((ok, fail) => {
let dbConnection: DatabaseConnection = {
id: this.databaseConnectionPool.length,
connection: this.connectionPool,
isTransactionActive: false
connection: this.connectionPool
};
dbConnection.releaseCallback = () => {
this.databaseConnectionPool.splice(this.databaseConnectionPool.indexOf(dbConnection), 1);

View File

@ -22,14 +22,19 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class SqlServerQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
@ -124,15 +129,15 @@ export class SqlServerQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
return new Promise<void>((ok, fail) => {
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
this.databaseConnection.transaction = this.databaseConnection.connection.transaction();
this.databaseConnection.transaction.begin((err: any) => {
if (err) {
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
return fail(err);
}
ok();
@ -147,13 +152,13 @@ export class SqlServerQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
return new Promise<void>((ok, fail) => {
this.databaseConnection.transaction.commit((err: any) => {
if (err) return fail(err);
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
ok();
});
});
@ -166,25 +171,18 @@ export class SqlServerQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
return new Promise<void>((ok, fail) => {
this.databaseConnection.transaction.rollback((err: any) => {
if (err) return fail(err);
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
ok();
});
});
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
}
/**
* Executes a given SQL query.
*/
@ -196,7 +194,7 @@ export class SqlServerQueryRunner implements QueryRunner {
this.connection.logger.logQuery(query, parameters);
const mssql = this.connection.driver.nativeInterface().driver;
const request = new mssql.Request(this.isTransactionActive() ? this.databaseConnection.transaction : this.databaseConnection.connection);
const request = new mssql.Request(this.isTransactionActive ? this.databaseConnection.transaction : this.databaseConnection.connection);
if (parameters && parameters.length) {
parameters.forEach((parameter, index) => {
request.input(index, parameters![index]);

View File

@ -137,8 +137,7 @@ export class WebsqlDriver implements Driver {
);
this.databaseConnection = {
id: 1,
connection: connection,
isTransactionActive: false
connection: connection
};
ok();
});

View File

@ -20,14 +20,19 @@ import {ColumnOptions} from "../../decorator/options/ColumnOptions";
export class WebsqlQueryRunner implements QueryRunner {
// -------------------------------------------------------------------------
// Protected Properties
// Public Implemented Properties
// -------------------------------------------------------------------------
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
protected isReleased = false;
isReleased = false;
/**
* Indicates if transaction is active in this query executor.
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Constructor
@ -87,10 +92,10 @@ export class WebsqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.databaseConnection.isTransactionActive)
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
this.databaseConnection.isTransactionActive = true;
this.isTransactionActive = true;
// await this.query("BEGIN TRANSACTION");
}
@ -101,11 +106,11 @@ export class WebsqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
// await this.query("COMMIT");
this.databaseConnection.isTransactionActive = false;
this.isTransactionActive = false;
}
/**
@ -115,18 +120,11 @@ export class WebsqlQueryRunner implements QueryRunner {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.databaseConnection.isTransactionActive)
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
// await this.query("ROLLBACK");
this.databaseConnection.isTransactionActive = false;
}
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean {
return this.databaseConnection.isTransactionActive;
this.isTransactionActive = false;
}
/**

View File

@ -79,7 +79,7 @@ export class MigrationExecutor {
// start transaction if its not started yet
let transactionStartedByUs = false;
if (!queryRunner.isTransactionActive()) {
if (!queryRunner.isTransactionActive) {
await queryRunner.beginTransaction();
transactionStartedByUs = true;
}
@ -148,7 +148,7 @@ export class MigrationExecutor {
// start transaction if its not started yet
let transactionStartedByUs = false;
if (!queryRunner.isTransactionActive()) {
if (!queryRunner.isTransactionActive) {
await queryRunner.beginTransaction();
transactionStartedByUs = true;
}

View File

@ -106,7 +106,7 @@ export class SubjectOperationExecutor {
this.queryRunner = await this.queryRunnerProvider.provide();
// open transaction if its not opened yet
if (!this.queryRunner.isTransactionActive()) {
if (!this.queryRunner.isTransactionActive) {
isTransactionStartedByItself = true;
await this.queryRunner.beginTransaction();
}

View File

@ -905,7 +905,7 @@ export class QueryBuilder<Entity> {
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") && !queryRunner.isTransactionActive())
if ((this.expressionMap.lockMode === "pessimistic_read" || this.expressionMap.lockMode === "pessimistic_write") && !queryRunner.isTransactionActive)
throw new PessimisticLockTransactionRequiredError();
if (this.expressionMap.lockMode === "optimistic") {

View File

@ -13,6 +13,17 @@ import {ColumnOptions} from "../decorator/options/ColumnOptions";
*/
export interface QueryRunner {
/**
* Indicates if connection for this query runner is released.
* Once its released, query runner cannot run queries anymore.
*/
readonly isReleased: boolean;
/**
* Checks if transaction is in progress.
*/
readonly isTransactionActive: boolean;
/**
* Releases database connection. This is needed when using connection pooling.
* If connection is not from a pool, it should not be released.
@ -42,11 +53,6 @@ export interface QueryRunner {
*/
rollbackTransaction(): Promise<void>;
/**
* Checks if transaction is in progress.
*/
isTransactionActive(): boolean;
/**
* Executes a given SQL query and returns raw database results.
*/