drivers refactoring; renamed mongoEntityManager to simply mongoManager

This commit is contained in:
Umed Khudoiberdiev 2017-06-19 11:30:35 +05:00
parent 835cdf889c
commit 5f403335d6
9 changed files with 166 additions and 1075 deletions

View File

@ -39,7 +39,7 @@ createConnection(options).then(async connection => {
console.log("Post retrieved via cursor #2: ", await cursor1.next());
// we can also perform mongodb-specific queries using mongodb-specific entity manager
const cursor2 = connection.mongoEntityManager.createEntityCursor(Post, { title: "hello" });
const cursor2 = connection.mongoManager.createEntityCursor(Post, { title: "hello" });
console.log("Only two posts retrieved via cursor: ", await cursor2.limit(2).toArray());
}, error => console.log("Error: ", error));

View File

@ -115,7 +115,7 @@ export class Connection {
*
* Available only in mongodb connections.
*/
get mongoEntityManager(): MongoEntityManager {
get mongoManager(): MongoEntityManager {
if (!(this.manager instanceof MongoEntityManager))
throw new Error(`MongoEntityManager is only available for MongoDB databases.`);

View File

@ -321,6 +321,15 @@ export class MongoQueryRunner implements QueryRunner {
// Public Implemented Methods (from QueryRunner)
// -------------------------------------------------------------------------
/**
* Removes all collections from the currently connected database.
* Be careful with using this method and avoid using it in production or migrations
* (because it can clear all your database).
*/
async clearDatabase(): Promise<void> {
await this.databaseConnection.dropDatabase();
}
/**
* For MongoDB database we don't create connection, because its single connection already created by a driver.
*/
@ -334,15 +343,6 @@ export class MongoQueryRunner implements QueryRunner {
// releasing connection are not supported by mongodb driver, so simply don't do anything here
}
/**
* Removes all collections from the currently connected database.
* Be careful with using this method and avoid using it in production or migrations
* (because it can clear all your database).
*/
async clearDatabase(): Promise<void> {
await this.databaseConnection.dropDatabase();
}
/**
* Starts transaction.
*/
@ -392,16 +392,6 @@ export class MongoQueryRunner implements QueryRunner {
.updateOne(conditions, valuesMap);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(collectionName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(collectionName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
@ -464,16 +454,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(collectionName: string, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
@ -481,16 +461,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(collectionName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
@ -498,16 +468,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(collectionName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -515,16 +475,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
@ -560,16 +510,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Creates a new foreign key.
*/
async createForeignKey(collectionName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
@ -577,16 +517,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(collectionName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
@ -594,16 +524,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(collectionName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
@ -611,16 +531,6 @@ export class MongoQueryRunner implements QueryRunner {
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(collectionName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/

View File

@ -41,7 +41,7 @@ export class MysqlQueryRunner implements QueryRunner {
protected databaseConnection: any;
/**
* Promise used to obtain a database connection for a first time.
* Promise used to obtain a database connection from a pool for a first time.
*/
protected databaseConnectionPromise: Promise<any>;
@ -88,43 +88,10 @@ export class MysqlQueryRunner implements QueryRunner {
return Promise.resolve();
}
/**
* Removes all tables from the currently connected database.
* Be careful with using this method and avoid using it in production or migrations
* (because it can clear all your database).
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
await this.startTransaction();
try {
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS query FROM information_schema.tables WHERE table_schema = '${this.dbName}'`;
const enableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 1;`;
await this.query(disableForeignKeysCheckQuery);
const dropQueries: ObjectLiteral[] = await this.query(dropTablesQuery);
await Promise.all(dropQueries.map(query => this.query(query["query"])));
await this.query(enableForeignKeysCheckQuery);
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
/**
* Starts transaction on the current connection.
*/
async startTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
@ -137,9 +104,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -152,9 +116,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -189,9 +150,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `\`${key}\``).join(", ");
const values = keys.map(key => "?").join(",");
@ -205,9 +163,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updateValues = this.parametrize(valuesMap).join(", ");
const conditionString = this.parametrize(conditions).join(" AND ");
const sql = `UPDATE \`${tableName}\` SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
@ -221,9 +176,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -235,9 +187,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Inserts rows into the closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// todo: escape column names as well
if (hasLevel) {
await this.query(
@ -268,9 +217,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -366,15 +312,12 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new table from the given table schema and column schemas inside it.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column, false)).join(", ");
let sql = `CREATE TABLE \`${table.name}\` (${columnDefinitions}`;
const primaryKeyColumns = table.columns.filter(column => column.isPrimary && !column.isGenerated);
if (primaryKeyColumns.length > 0)
sql += `, PRIMARY KEY(${primaryKeyColumns.map(column => `\`${column.name}\``).join(", ")})`;
sql += `) ENGINE=${table.engine || "InnoDB"};`; // todo: remove engine from here - todo: why?
sql += `) ENGINE=${table.engine || "InnoDB"};`;
await this.query(sql);
}
@ -400,9 +343,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE \`${tableName}\` ADD ${this.buildCreateColumnSql(column, false)}`;
return this.query(sql);
@ -412,9 +352,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const queries = columns.map(column => this.addColumn(tableSchemaOrName as any, column));
await Promise.all(queries);
}
@ -459,9 +396,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
tableSchema = tableSchemaOrName;
@ -492,9 +426,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Changes a column in the table.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatePromises = changedColumns.map(async changedColumn => {
return this.changeColumn(tableSchema, changedColumn.oldColumn, changedColumn.newColumn);
});
@ -513,9 +444,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const dropPromises = columns.map(column => this.dropColumn(table, column));
await Promise.all(dropPromises);
}
@ -524,9 +452,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Updates table's primary keys.
*/
async updatePrimaryKeys(tableSchema: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!tableSchema.hasGeneratedColumn)
await this.query(`ALTER TABLE \`${tableSchema.name}\` DROP PRIMARY KEY`);
@ -539,9 +464,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const columnNames = foreignKey.columnNames.map(column => "`" + column + "`").join(", ");
const referencedColumnNames = foreignKey.referencedColumnNames.map(column => "`" + column + "`").join(",");
@ -556,8 +478,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.createForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
@ -566,9 +486,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
return this.query(`ALTER TABLE \`${tableName}\` DROP FOREIGN KEY \`${foreignKey.name}\``);
}
@ -577,9 +494,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.dropForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
@ -588,9 +502,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columns = index.columnNames.map(columnName => "`" + columnName + "`").join(", ");
const sql = `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX \`${index.name}\` ON \`${tableName}\`(${columns})`;
await this.query(sql);
@ -600,9 +511,6 @@ export class MysqlQueryRunner implements QueryRunner {
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const sql = `ALTER TABLE \`${tableName}\` DROP INDEX \`${indexName}\``;
await this.query(sql);
}
@ -614,6 +522,33 @@ export class MysqlQueryRunner implements QueryRunner {
await this.query(`TRUNCATE TABLE \`${tableName}\``);
}
/**
* Removes all tables from the currently connected database.
* Be careful using this method and avoid using it in production or migrations
* (because it can clear all your database).
*/
async clearDatabase(): Promise<void> {
await this.startTransaction();
try {
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS query FROM information_schema.tables WHERE table_schema = '${this.dbName}'`;
const enableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 1;`;
await this.query(disableForeignKeysCheckQuery);
const dropQueries: ObjectLiteral[] = await this.query(dropTablesQuery);
await Promise.all(dropQueries.map(query => this.query(query["query"])));
await this.query(enableForeignKeysCheckQuery);
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------
@ -633,7 +568,7 @@ export class MysqlQueryRunner implements QueryRunner {
}
/**
* Builds a query for create column.
* Builds a part of query to create/change a column.
*/
protected buildCreateColumnSql(column: ColumnSchema, skipPrimary: boolean) {
let c = "`" + column.name + "` " + column.type;
@ -647,9 +582,9 @@ export class MysqlQueryRunner implements QueryRunner {
c += " AUTO_INCREMENT";
if (column.comment)
c += " COMMENT '" + column.comment + "'";
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
if (column.default !== undefined && column.default !== null)
c += " DEFAULT " + column.default;
}
return c;
}

View File

@ -12,7 +12,7 @@ import {QueryRunnerAlreadyReleasedError} from "../../query-runner/error/QueryRun
import {OracleDriver} from "./OracleDriver";
/**
* Runs queries on a single mysql database connection.
* Runs queries on a single oracle database connection.
*
* todo: this driver is not 100% finished yet, need to fix all issues that are left
*/
@ -98,35 +98,6 @@ export class OracleQueryRunner implements QueryRunner {
});
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
await this.startTransaction();
try {
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS query FROM information_schema.tables WHERE table_schema = '${this.dbName}'`;
const enableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 1;`;
await this.query(disableForeignKeysCheckQuery);
const dropQueries: ObjectLiteral[] = await this.query(dropTablesQuery);
await Promise.all(dropQueries.map(query => this.query(query["query"])));
await this.query(enableForeignKeysCheckQuery);
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
/**
* Starts transaction.
*/
@ -146,9 +117,6 @@ export class OracleQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -161,9 +129,6 @@ export class OracleQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -203,9 +168,6 @@ export class OracleQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map(key => ":" + key).join(", ");
@ -230,9 +192,6 @@ export class OracleQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updateValues = this.parametrize(valuesMap).join(", ");
const conditionString = this.parametrize(conditions).join(" AND ");
const sql = `UPDATE "${tableName}" SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
@ -242,23 +201,10 @@ export class OracleQueryRunner implements QueryRunner {
await this.query(sql, allParameters);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -270,9 +216,6 @@ export class OracleQueryRunner implements QueryRunner {
* Inserts rows into the closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let sql = "";
if (hasLevel) {
sql = `INSERT INTO "${tableName}"("ancestor", "descendant", "level") ` +
@ -300,9 +243,6 @@ export class OracleQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -412,9 +352,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Creates a new table from the given table metadata and column metadatas.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column)).join(", ");
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
const primaryKeyColumns = table.columns.filter(column => column.isPrimary);
@ -441,59 +378,23 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
return result.length ? true : false;
}
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableName: string, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" ADD ${this.buildCreateColumnSql(column)}`;
return this.query(sql);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const queries = columns.map(column => this.addColumn(tableSchemaOrName as any, column));
await Promise.all(queries);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -530,22 +431,10 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
return this.changeColumn(tableSchema, oldColumn, newColumn);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
@ -604,9 +493,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Changes a column in the table.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatePromises = changedColumns.map(async changedColumn => {
return this.changeColumn(tableSchema, changedColumn.oldColumn, changedColumn.newColumn);
});
@ -624,9 +510,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const dropPromises = columns.map(column => this.dropColumn(table, column));
await Promise.all(dropPromises);
}
@ -635,9 +518,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Updates table's primary keys.
*/
async updatePrimaryKeys(dbTable: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const primaryColumnNames = dbTable.primaryKeys.map(primaryKey => "\"" + primaryKey.columnName + "\"");
// console.log(dbTable.primaryKeys);
if (dbTable.primaryKeys.length > 0 && dbTable.primaryKeys[0].name)
@ -646,23 +526,10 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
await this.query(`ALTER TABLE "${dbTable.name}" ADD PRIMARY KEY (${primaryColumnNames.join(", ")})`);
}
/**
* Creates a new foreign key.
*/
async createForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const columnNames = foreignKey.columnNames.map(column => "\"" + column + "\"").join(", ");
const referencedColumnNames = foreignKey.referencedColumnNames.map(column => "\"" + column + "\"").join(",");
@ -673,66 +540,27 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
return this.query(sql);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.createForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" DROP CONSTRAINT "${foreignKey.name}"`;
return this.query(sql);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.dropForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
@ -741,9 +569,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columns = index.columnNames.map(columnName => "\"" + columnName + "\"").join(", ");
const sql = `CREATE ${index.isUnique ? "UNIQUE" : ""} INDEX "${index.name}" ON "${tableName}"(${columns})`;
await this.query(sql);
@ -753,9 +578,6 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const sql = `ALTER TABLE "${tableName}" DROP INDEX "${indexName}"`;
await this.query(sql);
}
@ -767,6 +589,32 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
await this.query(`TRUNCATE TABLE "${tableName}"`);
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
await this.startTransaction();
try {
const disableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 0;`;
const dropTablesQuery = `SELECT concat('DROP TABLE IF EXISTS ', table_name, ';') AS query FROM information_schema.tables WHERE table_schema = '${this.dbName}'`;
const enableForeignKeysCheckQuery = `SET FOREIGN_KEY_CHECKS = 1;`;
await this.query(disableForeignKeysCheckQuery);
const dropQueries: ObjectLiteral[] = await this.query(dropTablesQuery);
await Promise.all(dropQueries.map(query => this.query(query["query"])));
await this.query(enableForeignKeysCheckQuery);
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -111,35 +111,10 @@ export class PostgresQueryRunner implements QueryRunner {
return Promise.resolve();
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
await this.startTransaction();
try {
const selectDropsQuery = `SELECT 'DROP TABLE IF EXISTS "' || tablename || '" CASCADE;' as query FROM pg_tables WHERE schemaname = '${this.schemaName}'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
/**
* Starts transaction.
*/
async startTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
@ -152,8 +127,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -166,8 +139,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -204,9 +175,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
@ -225,9 +193,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updateValues = this.parametrize(valuesMap).join(", ");
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
const query = `UPDATE "${tableName}" SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
@ -237,23 +202,10 @@ export class PostgresQueryRunner implements QueryRunner {
await this.query(query, allParameters);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -265,9 +217,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Inserts rows into closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let sql = "";
if (hasLevel) {
sql = `INSERT INTO "${tableName}"("ancestor", "descendant", "level") ` +
@ -295,9 +244,6 @@ export class PostgresQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -405,9 +351,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Creates a new table from the given table metadata and column metadatas.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column, false)).join(", ");
await this.query(`CREATE SCHEMA IF NOT EXISTS "${this.schemaName}"`);
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
@ -439,59 +382,23 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
return result.length ? true : false;
}
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableName: string, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" ADD ${this.buildCreateColumnSql(column, false)}`;
return this.query(sql);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const queries = columns.map(column => this.addColumn(tableSchemaOrName as any, column));
await Promise.all(queries);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -528,22 +435,10 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
return this.changeColumn(tableSchema, oldColumn, newColumn);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
@ -628,9 +523,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Changes a column in the table.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatePromises = changedColumns.map(async changedColumn => {
return this.changeColumn(tableSchema, changedColumn.oldColumn, changedColumn.newColumn);
});
@ -649,9 +541,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const dropPromises = columns.map(column => this.dropColumn(table, column));
await Promise.all(dropPromises);
}
@ -660,9 +549,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Updates table's primary keys.
*/
async updatePrimaryKeys(dbTable: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const primaryColumnNames = dbTable.primaryKeys.map(primaryKey => `"${primaryKey.columnName}"`);
await this.query(`ALTER TABLE "${dbTable.name}" DROP CONSTRAINT IF EXISTS "${dbTable.name}_pkey"`);
await this.query(`DROP INDEX IF EXISTS "${dbTable.name}_pkey"`);
@ -670,23 +556,10 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
await this.query(`ALTER TABLE "${dbTable.name}" ADD PRIMARY KEY (${primaryColumnNames.join(", ")})`);
}
/**
* Creates a new foreign key.
*/
async createForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
let sql = `ALTER TABLE "${tableName}" ADD CONSTRAINT "${foreignKey.name}" ` +
`FOREIGN KEY ("${foreignKey.columnNames.join("\", \"")}") ` +
@ -695,66 +568,27 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
return this.query(sql);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.createForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" DROP CONSTRAINT "${foreignKey.name}"`;
return this.query(sql);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.dropForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
@ -763,9 +597,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnNames = index.columnNames.map(columnName => `"${columnName}"`).join(",");
const sql = `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${index.name}" ON "${tableName}"(${columnNames})`;
await this.query(sql);
@ -775,9 +606,6 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string, isGenerated: boolean = false): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (isGenerated) {
await this.query(`ALTER SEQUENCE "${tableName}_id_seq" OWNED BY NONE`);
}
@ -793,6 +621,26 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
await this.query(`TRUNCATE TABLE "${tableName}"`);
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
await this.startTransaction();
try {
const selectDropsQuery = `SELECT 'DROP TABLE IF EXISTS "' || tablename || '" CASCADE;' as query FROM pg_tables WHERE schemaname = '${this.schemaName}'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -35,20 +35,6 @@ export class SqliteQueryRunner implements QueryRunner {
*/
isTransactionActive = false;
// -------------------------------------------------------------------------
// Protected Properties
// -------------------------------------------------------------------------
/**
* Real database connection from a connection pool used to perform queries.
*/
protected databaseConnection: any;
/**
* Promise used to obtain a database connection for a first time.
*/
protected databaseConnectionPromise: Promise<any>;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
@ -76,38 +62,10 @@ export class SqliteQueryRunner implements QueryRunner {
return Promise.resolve();
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
await this.query(`PRAGMA foreign_keys = OFF;`);
await this.startTransaction();
try {
const selectDropsQuery = `select 'drop table ' || name || ';' as query from sqlite_master where type = 'table' and name != 'sqlite_sequence'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
} finally {
await this.query(`PRAGMA foreign_keys = ON;`);
}
}
/**
* Starts transaction.
*/
async startTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (this.isTransactionActive)
throw new TransactionAlreadyStartedError();
@ -120,8 +78,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async commitTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -134,8 +90,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Error will be thrown if transaction was not started.
*/
async rollbackTransaction(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
if (!this.isTransactionActive)
throw new TransactionNotStartedError();
@ -170,9 +124,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
@ -202,9 +153,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updateValues = this.parametrize(valuesMap).join(", ");
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
const query = `UPDATE "${tableName}" SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
@ -214,23 +162,10 @@ export class SqliteQueryRunner implements QueryRunner {
await this.query(query, allParameters);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -242,9 +177,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Inserts rows into closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let sql = "";
if (hasLevel) {
sql = `INSERT INTO "${tableName}"("ancestor", "descendant", "level") ` +
@ -272,11 +204,7 @@ export class SqliteQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -405,9 +333,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Creates a new table from the given table metadata and column metadatas.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// skip columns with foreign keys, we will add them later
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column)).join(", ");
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
@ -435,62 +360,26 @@ export class SqliteQueryRunner implements QueryRunner {
return !!columns.find(column => column["name"] === columnName);
}
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableName: string, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const newTableSchema = tableSchema.clone();
newTableSchema.addColumns([column]);
await this.recreateTable(newTableSchema, tableSchema);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const newTableSchema = tableSchema.clone();
newTableSchema.addColumns(columns);
await this.recreateTable(newTableSchema, tableSchema);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -527,23 +416,10 @@ export class SqliteQueryRunner implements QueryRunner {
return this.changeColumn(tableSchema, oldColumn, newColumn);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
tableSchema = tableSchemaOrName;
@ -573,9 +449,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Changed column looses all its keys in the db.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// todo: fix it. it should not depend on tableSchema
return this.recreateTable(tableSchema);
}
@ -591,9 +464,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatingTableSchema = table.clone();
updatingTableSchema.removeColumns(columns);
return this.recreateTable(updatingTableSchema);
@ -603,92 +473,37 @@ export class SqliteQueryRunner implements QueryRunner {
* Updates table's primary keys.
*/
async updatePrimaryKeys(dbTable: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.recreateTable(dbTable);
}
/**
* Creates a new foreign key.
*/
async createForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.createForeignKeys(tableSchemaOrName as any, [foreignKey]);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const changedTableSchema = tableSchema.clone();
changedTableSchema.addForeignKeys(foreignKeys);
return this.recreateTable(changedTableSchema);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.dropForeignKeys(tableSchemaOrName as any, [foreignKey]);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const changedTableSchema = tableSchema.clone();
changedTableSchema.removeForeignKeys(foreignKeys);
@ -699,9 +514,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnNames = index.columnNames.map(columnName => `"${columnName}"`).join(",");
const sql = `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${index.name}" ON "${tableName}"(${columnNames})`;
await this.query(sql);
@ -711,9 +523,6 @@ export class SqliteQueryRunner implements QueryRunner {
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const sql = `DROP INDEX "${indexName}"`;
await this.query(sql);
}
@ -725,6 +534,29 @@ export class SqliteQueryRunner implements QueryRunner {
await this.query(`DELETE FROM "${tableName}"`);
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
await this.query(`PRAGMA foreign_keys = OFF;`);
await this.startTransaction();
try {
const selectDropsQuery = `select 'drop table ' || name || ';' as query from sqlite_master where type = 'table' and name != 'sqlite_sequence'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
} finally {
await this.query(`PRAGMA foreign_keys = ON;`);
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -77,40 +77,6 @@ export class SqlServerQueryRunner implements QueryRunner {
return Promise.resolve();
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
await this.startTransaction();
try {
const allTablesSql = `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'`;
const allTablesResults: ObjectLiteral[] = await this.query(allTablesSql);
const tableNames = allTablesResults.map(result => result["TABLE_NAME"]);
await Promise.all(tableNames.map(async tableName => {
const dropForeignKeySql = `SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT ' + name as query FROM sys.foreign_keys WHERE referenced_object_id = object_id('${tableName}')`;
const dropFkQueries: ObjectLiteral[] = await this.query(dropForeignKeySql);
return Promise.all(dropFkQueries.map(result => result["query"]).map(dropQuery => {
return this.query(dropQuery);
}));
}));
await Promise.all(tableNames.map(tableName => {
const dropTableSql = `DROP TABLE "${tableName}"`;
return this.query(dropTableSql);
}));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
/**
* Starts transaction.
*/
@ -234,9 +200,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map((key, index) => "@" + index).join(",");
@ -254,9 +217,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionParams = Object.keys(conditions).map(key => conditions[key]);
const updateParams = Object.keys(valuesMap).map(key => valuesMap[key]);
const allParameters = updateParams.concat(conditionParams);
@ -268,23 +228,10 @@ export class SqlServerQueryRunner implements QueryRunner {
await this.query(sql, allParameters);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -296,9 +243,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Inserts rows into the closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let sql = "";
if (hasLevel) {
sql = `INSERT INTO "${tableName}"("ancestor", "descendant", "level") ` +
@ -326,11 +270,8 @@ export class SqlServerQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -444,9 +385,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Creates a new table from the given table metadata and column metadatas.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column, false, true)).join(", ");
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
sql += table.columns
@ -481,45 +419,19 @@ export class SqlServerQueryRunner implements QueryRunner {
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" ADD ${this.buildCreateColumnSql(column, false, true)}`;
return this.query(sql);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const queries = columns.map(column => this.addColumn(tableSchemaOrName as any, column));
await Promise.all(queries);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -556,22 +468,10 @@ export class SqlServerQueryRunner implements QueryRunner {
return this.changeColumn(tableSchema, oldColumn, newColumn);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
@ -627,9 +527,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Changes a column in the table.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatePromises = changedColumns.map(async changedColumn => {
return this.changeColumn(tableSchema, changedColumn.oldColumn, changedColumn.newColumn);
});
@ -654,9 +551,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const dropPromises = columns.map(column => this.dropColumn(table, column));
await Promise.all(dropPromises);
}
@ -665,9 +559,6 @@ export class SqlServerQueryRunner implements QueryRunner {
* Updates table's primary keys.
*/
async updatePrimaryKeys(dbTable: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const oldPrimaryKeySql = `SELECT columnUsages.*, tableConstraints.CONSTRAINT_TYPE FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE columnUsages
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tableConstraints ON tableConstraints.CONSTRAINT_NAME = columnUsages.CONSTRAINT_NAME AND tableConstraints.CONSTRAINT_TYPE = 'PRIMARY KEY'
WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_CATALOG = '${this.dbName}'`;
@ -681,23 +572,10 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
}
/**
* Creates a new foreign key.
*/
async createForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const columnNames = foreignKey.columnNames.map(column => `"` + column + `"`).join(", ");
const referencedColumnNames = foreignKey.referencedColumnNames.map(column => `"` + column + `"`).join(",");
@ -708,66 +586,27 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
return this.query(sql);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.createForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
const sql = `ALTER TABLE "${tableName}" DROP CONSTRAINT "${foreignKey.name}"`;
return this.query(sql);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const promises = foreignKeys.map(foreignKey => this.dropForeignKey(tableSchemaOrName as any, foreignKey));
await Promise.all(promises);
}
@ -776,9 +615,6 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columns = index.columnNames.map(columnName => `"${columnName}"`).join(", ");
const sql = `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${index.name}" ON "${tableName}"(${columns})`;
await this.query(sql);
@ -788,9 +624,6 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const sql = `DROP INDEX "${tableName}"."${indexName}"`;
await this.query(sql);
}
@ -802,6 +635,37 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
await this.query(`TRUNCATE TABLE "${tableName}"`);
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
await this.startTransaction();
try {
const allTablesSql = `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'`;
const allTablesResults: ObjectLiteral[] = await this.query(allTablesSql);
const tableNames = allTablesResults.map(result => result["TABLE_NAME"]);
await Promise.all(tableNames.map(async tableName => {
const dropForeignKeySql = `SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT ' + name as query FROM sys.foreign_keys WHERE referenced_object_id = object_id('${tableName}')`;
const dropFkQueries: ObjectLiteral[] = await this.query(dropForeignKeySql);
return Promise.all(dropFkQueries.map(result => result["query"]).map(dropQuery => {
return this.query(dropQuery);
}));
}));
await Promise.all(tableNames.map(tableName => {
const dropTableSql = `DROP TABLE "${tableName}"`;
return this.query(dropTableSql);
}));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------

View File

@ -98,31 +98,6 @@ export class WebsqlQueryRunner implements QueryRunner {
return Promise.resolve();
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// await this.query(`PRAGMA foreign_keys = OFF;`);
await this.startTransaction();
try {
const selectDropsQuery = `select 'drop table ' || name || ';' as query from sqlite_master where type = 'table' and name != 'sqlite_sequence'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
// await this.query(`PRAGMA foreign_keys = ON;`);
}
}
/**
* Starts transaction.
*/
@ -201,9 +176,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Returns value of the generated column if given and generate column exist in the table.
*/
async insert(tableName: string, keyValues: ObjectLiteral, generatedColumn?: ColumnMetadata): Promise<any> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const keys = Object.keys(keyValues);
const columns = keys.map(key => `"${key}"`).join(", ");
const values = keys.map((key, index) => "$" + (index + 1)).join(",");
@ -234,9 +206,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Updates rows that match given conditions in the given table.
*/
async update(tableName: string, valuesMap: ObjectLiteral, conditions: ObjectLiteral): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updateValues = this.parametrize(valuesMap).join(", ");
const conditionString = this.parametrize(conditions, Object.keys(valuesMap).length).join(" AND ");
const query = `UPDATE "${tableName}" SET ${updateValues} ${conditionString ? (" WHERE " + conditionString) : ""}`;
@ -246,23 +215,10 @@ export class WebsqlQueryRunner implements QueryRunner {
await this.query(query, allParameters);
}
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, condition: string, parameters?: any[]): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral): Promise<void>;
/**
* Deletes from the given table by a given conditions.
*/
async delete(tableName: string, conditions: ObjectLiteral|string, maybeParameters?: any[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const conditionString = typeof conditions === "string" ? conditions : this.parametrize(conditions).join(" AND ");
const parameters = conditions instanceof Object ? Object.keys(conditions).map(key => (conditions as ObjectLiteral)[key]) : maybeParameters;
@ -274,9 +230,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Inserts rows into closure table.
*/
async insertIntoClosureTable(tableName: string, newEntityId: any, parentId: any, hasLevel: boolean): Promise<number> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let sql = "";
if (hasLevel) {
sql = `INSERT INTO "${tableName}"("ancestor", "descendant", "level") ` +
@ -304,11 +257,8 @@ export class WebsqlQueryRunner implements QueryRunner {
* Loads all tables (with given names) from the database and creates a TableSchema from them.
*/
async loadTableSchemas(tableNames: string[]): Promise<TableSchema[]> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// if no tables given then no need to proceed
if (!tableNames || !tableNames.length)
return [];
@ -434,9 +384,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Creates a new table from the given table metadata and column metadatas.
*/
async createTable(table: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// skip columns with foreign keys, we will add them later
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column)).join(", ");
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
@ -464,62 +411,26 @@ export class WebsqlQueryRunner implements QueryRunner {
return !!columns.find(column => column["name"] === columnName);
}
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableName: string, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
/**
* Creates a new column from the column schema in the table.
*/
async addColumn(tableSchemaOrName: TableSchema|string, column: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const newTableSchema = tableSchema.clone();
newTableSchema.addColumns([column]);
await this.recreateTable(newTableSchema, tableSchema);
}
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableName: string, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
/**
* Creates a new columns from the column schema in the table.
*/
async addColumns(tableSchemaOrName: TableSchema|string, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const newTableSchema = tableSchema.clone();
newTableSchema.addColumns(columns);
await this.recreateTable(newTableSchema, tableSchema);
}
/**
* Renames column in the given table.
*/
renameColumn(table: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Renames column in the given table.
*/
renameColumn(tableName: string, oldColumnName: string, newColumnName: string): Promise<void>;
/**
* Renames column in the given table.
*/
@ -556,22 +467,10 @@ export class WebsqlQueryRunner implements QueryRunner {
return this.changeColumn(tableSchema, oldColumn, newColumn);
}
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: TableSchema, oldColumn: ColumnSchema, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
changeColumn(tableSchema: string, oldColumn: string, newColumn: ColumnSchema): Promise<void>;
/**
* Changes a column in the table.
*/
async changeColumn(tableSchemaOrName: TableSchema|string, oldColumnSchemaOrName: ColumnSchema|string, newColumn: ColumnSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
let tableSchema: TableSchema|undefined = undefined;
if (tableSchemaOrName instanceof TableSchema) {
@ -602,9 +501,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Changed column looses all its keys in the db.
*/
async changeColumns(tableSchema: TableSchema, changedColumns: { newColumn: ColumnSchema, oldColumn: ColumnSchema }[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
// todo: fix it. it should not depend on tableSchema
return this.recreateTable(tableSchema);
}
@ -620,9 +516,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Drops the columns in the table.
*/
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const updatingTableSchema = table.clone();
updatingTableSchema.removeColumns(columns);
return this.recreateTable(updatingTableSchema);
@ -632,92 +525,37 @@ export class WebsqlQueryRunner implements QueryRunner {
* Updates table's primary keys.
*/
async updatePrimaryKeys(dbTable: TableSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.recreateTable(dbTable);
}
/**
* Creates a new foreign key.
*/
async createForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Creates a new foreign key.
*/
async createForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.createForeignKeys(tableSchemaOrName as any, [foreignKey]);
}
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Creates a new foreign keys.
*/
async createForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const changedTableSchema = tableSchema.clone();
changedTableSchema.addForeignKeys(foreignKeys);
return this.recreateTable(changedTableSchema);
}
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableName: string, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchema: TableSchema, foreignKey: ForeignKeySchema): Promise<void>;
/**
* Drops a foreign key from the table.
*/
async dropForeignKey(tableSchemaOrName: TableSchema|string, foreignKey: ForeignKeySchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
return this.dropForeignKeys(tableSchemaOrName as any, [foreignKey]);
}
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableName: string, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchema: TableSchema, foreignKeys: ForeignKeySchema[]): Promise<void>;
/**
* Drops a foreign keys from the table.
*/
async dropForeignKeys(tableSchemaOrName: TableSchema|string, foreignKeys: ForeignKeySchema[]): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const tableSchema = await this.getTableSchema(tableSchemaOrName);
const changedTableSchema = tableSchema.clone();
changedTableSchema.removeForeignKeys(foreignKeys);
@ -728,9 +566,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Creates a new index.
*/
async createIndex(tableName: string, index: IndexSchema): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const columnNames = index.columnNames.map(columnName => `"${columnName}"`).join(",");
const sql = `CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${index.name}" ON "${tableName}"(${columnNames})`;
await this.query(sql);
@ -740,9 +575,6 @@ export class WebsqlQueryRunner implements QueryRunner {
* Drops an index from the table.
*/
async dropIndex(tableName: string, indexName: string): Promise<void> {
if (this.isReleased)
throw new QueryRunnerAlreadyReleasedError();
const sql = `DROP INDEX "${indexName}"`;
await this.query(sql);
}
@ -754,6 +586,28 @@ export class WebsqlQueryRunner implements QueryRunner {
await this.query(`DELETE FROM "${tableName}"`);
}
/**
* Removes all tables from the currently connected database.
*/
async clearDatabase(): Promise<void> {
// await this.query(`PRAGMA foreign_keys = OFF;`);
await this.startTransaction();
try {
const selectDropsQuery = `select 'drop table ' || name || ';' as query from sqlite_master where type = 'table' and name != 'sqlite_sequence'`;
const dropQueries: ObjectLiteral[] = await this.query(selectDropsQuery);
await Promise.all(dropQueries.map(q => this.query(q["query"])));
await this.commitTransaction();
} catch (error) {
try { // we throw original error even if rollback thrown an error
await this.rollbackTransaction();
} catch (rollbackError) { }
throw error;
// await this.query(`PRAGMA foreign_keys = ON;`);
}
}
// -------------------------------------------------------------------------
// Protected Methods
// -------------------------------------------------------------------------