mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fixes #537 and fixed issues with schema sync of "default" value
This commit is contained in:
parent
003e770315
commit
e1c08a2410
@ -49,10 +49,11 @@ More env variable names you can find in `ConnectionOptionsEnvReader` class.
|
||||
* `nativeInterface` has been removed from a driver interface and implementations.
|
||||
Now
|
||||
* now typeorm works with the latest version of mssql (version 4)
|
||||
* fixed how orm creates default values for SqlServer - now it creates constraints for it as well
|
||||
|
||||
### DEPRECATIONS
|
||||
|
||||
* `Embedded` decorator is deprecated now. use `@Column(type => SomeEmbedded)` instead now
|
||||
* `Embedded` decorator is deprecated now. use `@Column(type => SomeEmbedded)` instead
|
||||
|
||||
### NEW FEATURES
|
||||
|
||||
@ -76,6 +77,7 @@ Now
|
||||
|
||||
* fixes [#285](https://github.com/typeorm/typeorm/issues/285) - issue when cli commands rise `CannotCloseNotConnectedError`
|
||||
* fixes [#309](https://github.com/typeorm/typeorm/issues/309) - issue when `andHaving` didn't work without calling `having` on `QueryBuilder`
|
||||
* fixes issues with default value being updated by schema sync
|
||||
|
||||
# 0.0.10
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "typeorm",
|
||||
"private": true,
|
||||
"version": "0.1.0-alpha.9",
|
||||
"version": "0.1.0-alpha.10",
|
||||
"description": "Data-Mapper ORM for TypeScript, ES7, ES6, ES5. Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL, MongoDB databases.",
|
||||
"license": "MIT",
|
||||
"readmeFilename": "README.md",
|
||||
|
||||
@ -3,28 +3,36 @@ import {createConnection, ConnectionOptions} from "../../src/index";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
const options: ConnectionOptions = {
|
||||
type: "oracle",
|
||||
host: "localhost",
|
||||
username: "system",
|
||||
password: "oracle",
|
||||
port: 1521,
|
||||
sid: "xe.oracle.docker",
|
||||
// type: "oracle",
|
||||
// host: "localhost",
|
||||
// username: "system",
|
||||
// password: "oracle",
|
||||
// port: 1521,
|
||||
// sid: "xe.oracle.docker",
|
||||
// "name": "mysql",
|
||||
// "type": "mysql",
|
||||
// "host": "localhost",
|
||||
// "port": 3306,
|
||||
// "username": "test",
|
||||
// "password": "test",
|
||||
// "database": "test",
|
||||
// type: "postgres",
|
||||
// host: "localhost",
|
||||
// port: 5432,
|
||||
// username: "root",
|
||||
// password: "admin",
|
||||
// database: "test"
|
||||
// type: "mssql",
|
||||
// host: "192.168.1.10",
|
||||
// username: "sa",
|
||||
// password: "admin12345",
|
||||
// username: "test",
|
||||
// password: "test",
|
||||
// database: "test",
|
||||
// port: 1521
|
||||
"type": "mssql",
|
||||
"host": "192.168.1.6",
|
||||
"username": "sa",
|
||||
"password": "admin12345",
|
||||
"database": "test",
|
||||
// port: 1521,
|
||||
// type: "sqlite",
|
||||
// storage: "temp/sqlitedb.db"
|
||||
// database: "temp/sqlitedb.db",
|
||||
logging: {
|
||||
logQueries: true,
|
||||
logFailedQueryError: false,
|
||||
logSchemaCreation: true
|
||||
},
|
||||
autoSchemaSync: true,
|
||||
|
||||
@ -322,7 +322,9 @@ export class Connection {
|
||||
return result;
|
||||
|
||||
} catch (err) {
|
||||
await usedQueryRunner.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await usedQueryRunner.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw err;
|
||||
|
||||
} finally {
|
||||
|
||||
@ -9,21 +9,11 @@ import {ColumnMetadataArgs} from "../../metadata-args/ColumnMetadataArgs";
|
||||
export function UpdateDateColumn(options?: ColumnOptions): Function {
|
||||
return function (object: Object, propertyName: string) {
|
||||
|
||||
// const reflectedType = ColumnTypes.typeToString((Reflect as any).getMetadata("design:type", object, propertyName));
|
||||
|
||||
// if column options are not given then create a new empty options
|
||||
if (!options) options = {} as ColumnOptions;
|
||||
|
||||
// implicitly set a type, because this column's type cannot be anything else except date
|
||||
// options = Object.assign({ type: Date } as ColumnOptions, options);
|
||||
|
||||
// create and register a new column metadata
|
||||
const args: ColumnMetadataArgs = {
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
// propertyType: reflectedType,
|
||||
mode: "updateDate",
|
||||
options: options
|
||||
options: options ? options : {}
|
||||
};
|
||||
getMetadataArgsStorage().columns.push(args);
|
||||
};
|
||||
|
||||
@ -78,4 +78,9 @@ export interface Driver {
|
||||
*/
|
||||
normalizeType(column: ColumnMetadata): string;
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string;
|
||||
|
||||
}
|
||||
@ -42,7 +42,9 @@ export class MongoDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "int",
|
||||
createDateDefault: "",
|
||||
updateDate: "int",
|
||||
updateDateDefault: "",
|
||||
version: "int",
|
||||
treeLevel: "int",
|
||||
migrationName: "int",
|
||||
@ -173,6 +175,13 @@ export class MongoDriver implements Driver {
|
||||
throw new Error(`MongoDB is schema-less, not supported by this driver.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
throw new Error(`MongoDB is schema-less, not supported by this driver.`);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -542,34 +542,14 @@ export class MongoQueryRunner implements QueryRunner {
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(collectionName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(collectionName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
throw new Error(`Schema update queries are not supported by MongoDB driver.`);
|
||||
}
|
||||
|
||||
|
||||
@ -86,11 +86,13 @@ export class MysqlDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "datetime",
|
||||
createDateDefault: "CURRENT_TIMESTAMP",
|
||||
updateDate: "datetime",
|
||||
updateDateDefault: "CURRENT_TIMESTAMP",
|
||||
version: "int",
|
||||
treeLevel: "int",
|
||||
migrationName: "varchar",
|
||||
migrationTimestamp: "timestamp",
|
||||
migrationTimestamp: "timestamp"
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -284,6 +286,10 @@ export class MysqlDriver implements Driver {
|
||||
type += column.type;
|
||||
}
|
||||
|
||||
// normalize shortcuts
|
||||
if (type === "integer")
|
||||
type = "int";
|
||||
|
||||
if (column.length) {
|
||||
type += "(" + column.length + ")";
|
||||
|
||||
@ -322,6 +328,27 @@ export class MysqlDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "1" : "0";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return column.default();
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -111,7 +111,9 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -503,20 +505,18 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
|
||||
const columnName = columnSchemaOrName instanceof ColumnSchema ? columnSchemaOrName.name : columnSchemaOrName;
|
||||
return this.query(`ALTER TABLE \`${tableName}\` DROP \`${columnName}\``);
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
return this.query(`ALTER TABLE \`${table.name}\` DROP \`${column.name}\``);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const dropPromises = (columnSchemasOrNames as any[]).map(column => this.dropColumn(tableSchemaOrName as any, column as any));
|
||||
const dropPromises = columns.map(column => this.dropColumn(table, column));
|
||||
await Promise.all(dropPromises);
|
||||
}
|
||||
|
||||
@ -648,17 +648,7 @@ export class MysqlQueryRunner implements QueryRunner {
|
||||
if (column.comment)
|
||||
c += " COMMENT '" + column.comment + "'";
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "TRUE" : "FALSE") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
}
|
||||
c += " DEFAULT " + column.default;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -91,7 +91,9 @@ export class OracleDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "datetime",
|
||||
createDateDefault: "CURRENT_TIMESTAMP",
|
||||
updateDate: "datetime",
|
||||
updateDateDefault: "CURRENT_TIMESTAMP",
|
||||
version: "number",
|
||||
treeLevel: "number",
|
||||
migrationName: "varchar",
|
||||
@ -318,6 +320,27 @@ export class OracleDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "true" : "false";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return column.default();
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -119,7 +119,9 @@ export class OracleQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
}
|
||||
|
||||
@ -614,40 +616,18 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
|
||||
const columnName = columnSchemaOrName instanceof ColumnSchema ? columnSchemaOrName.name : columnSchemaOrName;
|
||||
return this.query(`ALTER TABLE "${tableName}" DROP COLUMN "${columnName}"`);
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
return this.query(`ALTER TABLE "${table.name}" DROP COLUMN "${column.name}"`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const dropPromises = (columnSchemasOrNames as any[]).map(column => this.dropColumn(tableSchemaOrName as any, column as any));
|
||||
const dropPromises = columns.map(column => this.dropColumn(table, column));
|
||||
await Promise.all(dropPromises);
|
||||
}
|
||||
|
||||
@ -819,17 +799,7 @@ AND cons.constraint_name = cols.constraint_name AND cons.owner = cols.owner ORDE
|
||||
// if (column.comment) // todo: less priority, fix it later
|
||||
// c += " COMMENT '" + column.comment + "'";
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "TRUE" : "FALSE") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
}
|
||||
c += " DEFAULT " + column.default;
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
@ -111,7 +111,9 @@ export class PostgresDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "timestamp",
|
||||
createDateDefault: "now()",
|
||||
updateDate: "timestamp",
|
||||
updateDateDefault: "now()",
|
||||
version: "int",
|
||||
treeLevel: "int",
|
||||
migrationName: "varchar",
|
||||
@ -325,6 +327,15 @@ export class PostgresDriver implements Driver {
|
||||
} else {
|
||||
type += column.type;
|
||||
}
|
||||
|
||||
// normalize shortcuts
|
||||
if (type === "int") {
|
||||
type = "integer";
|
||||
|
||||
} else if (type === "timestamp") {
|
||||
type = "timestamp without time zone";
|
||||
}
|
||||
|
||||
if (column.length) {
|
||||
type += "(" + column.length + ")";
|
||||
|
||||
@ -340,6 +351,27 @@ export class PostgresDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "true" : "false";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return column.default();
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -74,6 +74,8 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
|
||||
this.databaseConnectionPromise = new Promise((ok, fail) => {
|
||||
this.driver.pool.connect((err: any, connection: any, release: Function) => {
|
||||
if (err) return fail(err);
|
||||
|
||||
this.driver.connectedQueryRunners.push(this);
|
||||
this.databaseConnection = connection;
|
||||
this.releaseCallback = release;
|
||||
@ -125,7 +127,9 @@ export class PostgresQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -340,7 +344,7 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
const columnSchema = new ColumnSchema();
|
||||
columnSchema.name = dbColumn["column_name"];
|
||||
columnSchema.type = columnType;
|
||||
columnSchema.default = dbColumn["column_default"] !== null && dbColumn["column_default"] !== undefined ? dbColumn["column_default"] : undefined;
|
||||
columnSchema.default = dbColumn["column_default"] !== null && dbColumn["column_default"] !== undefined ? dbColumn["column_default"].replace(/::character varying/, "") : undefined;
|
||||
columnSchema.isNullable = dbColumn["is_nullable"] === "YES";
|
||||
// columnSchema.isPrimary = dbColumn["column_key"].indexOf("PRI") !== -1;
|
||||
columnSchema.isGenerated = isGenerated;
|
||||
@ -608,6 +612,16 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (newColumn.default !== oldColumn.default) {
|
||||
if (newColumn.default !== null && newColumn.default !== undefined) {
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" ALTER COLUMN "${newColumn.name}" SET DEFAULT ${newColumn.default}`);
|
||||
|
||||
} else if (oldColumn.default !== null && oldColumn.default !== undefined) {
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" ALTER COLUMN "${newColumn.name}" DROP DEFAULT`);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -627,40 +641,18 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
|
||||
const columnName = columnSchemaOrName instanceof ColumnSchema ? columnSchemaOrName.name : columnSchemaOrName;
|
||||
return this.query(`ALTER TABLE "${tableName}" DROP "${columnName}"`);
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
return this.query(`ALTER TABLE "${table.name}" DROP "${column.name}"`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const dropPromises = (columnSchemasOrNames as any[]).map(column => this.dropColumn(tableSchemaOrName as any, column as any));
|
||||
const dropPromises = columns.map(column => this.dropColumn(table, column));
|
||||
await Promise.all(dropPromises);
|
||||
}
|
||||
|
||||
@ -840,17 +832,7 @@ where constraint_type = 'PRIMARY KEY' AND c.table_schema = '${this.schemaName}'
|
||||
if (column.isGenerated)
|
||||
c += " PRIMARY KEY";
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "TRUE" : "FALSE") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
}
|
||||
c += " DEFAULT " + column.default;
|
||||
}
|
||||
if (column.isGenerated && column.type === "uuid" && !column.default)
|
||||
c += " DEFAULT uuid_generate_v4()";
|
||||
|
||||
@ -95,7 +95,9 @@ export class SqliteDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "datetime",
|
||||
createDateDefault: "datetime('now')",
|
||||
updateDate: "datetime",
|
||||
updateDateDefault: "datetime('now')",
|
||||
version: "integer",
|
||||
treeLevel: "integer",
|
||||
migrationName: "varchar",
|
||||
@ -306,6 +308,27 @@ export class SqliteDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "1" : "0";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return column.default();
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -92,7 +92,9 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
|
||||
} finally {
|
||||
@ -581,51 +583,18 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
return this.dropColumns(tableSchemaOrName as any, [columnSchemaOrName as any]);
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
return this.dropColumns(table, [column]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const tableSchema = await this.getTableSchema(tableSchemaOrName);
|
||||
const updatingTableSchema = tableSchema.clone();
|
||||
const columns = (columnSchemasOrNames as any[]).map(columnSchemasOrName => {
|
||||
if (typeof columnSchemasOrName === "string") {
|
||||
const column = tableSchema.columns.find(column => column.name === columnSchemasOrName);
|
||||
if (!column)
|
||||
throw new Error(`Cannot drop a column - column "${columnSchemasOrName}" was not found in the "${tableSchema.name}" table.`);
|
||||
|
||||
return column;
|
||||
|
||||
} else {
|
||||
return columnSchemasOrName as ColumnSchema;
|
||||
}
|
||||
});
|
||||
const updatingTableSchema = table.clone();
|
||||
updatingTableSchema.removeColumns(columns);
|
||||
return this.recreateTable(updatingTableSchema);
|
||||
}
|
||||
@ -785,17 +754,7 @@ export class SqliteQueryRunner implements QueryRunner {
|
||||
c += " PRIMARY KEY AUTOINCREMENT";
|
||||
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "1" : "0") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
}
|
||||
c += " DEFAULT (" + column.default + ")";
|
||||
}
|
||||
|
||||
return c;
|
||||
|
||||
@ -94,7 +94,9 @@ export class SqlServerDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "datetime",
|
||||
createDateDefault: "getdate()",
|
||||
updateDate: "datetime",
|
||||
updateDateDefault: "getdate()",
|
||||
version: "int",
|
||||
treeLevel: "int",
|
||||
migrationName: "varchar",
|
||||
@ -308,6 +310,11 @@ export class SqlServerDriver implements Driver {
|
||||
} else {
|
||||
type += column.type;
|
||||
}
|
||||
|
||||
// make sure aliases to have original type names
|
||||
if (type === "integer")
|
||||
type = "int";
|
||||
|
||||
if (column.length) {
|
||||
type += "(" + column.length + ")";
|
||||
|
||||
@ -328,6 +335,27 @@ export class SqlServerDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "1" : "0";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return "(" + column.default() + ")";
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@ -104,7 +104,9 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -212,7 +214,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
let waitingPromiseIndex = this.queryResponsibilityChain.indexOf(waitingPromise);
|
||||
if (err) {
|
||||
this.driver.connection.logger.logFailedQuery(query, parameters);
|
||||
this.driver.connection.logger.logQueryError(err);
|
||||
this.driver.connection.logger.logQueryError((err.originalError && err.originalError.info) ? err.originalError.info.message : err);
|
||||
resolveChain();
|
||||
return fail(err);
|
||||
}
|
||||
@ -363,7 +365,6 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
tableSchema.columns = dbColumns
|
||||
.filter(dbColumn => dbColumn["TABLE_NAME"] === tableSchema.name)
|
||||
.map(dbColumn => {
|
||||
|
||||
const isPrimary = !!dbConstraints.find(dbConstraint => {
|
||||
return dbConstraint["TABLE_NAME"] === tableSchema.name &&
|
||||
dbConstraint["COLUMN_NAME"] === dbColumn["COLUMN_NAME"] &&
|
||||
@ -446,7 +447,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column, false)).join(", ");
|
||||
const columnDefinitions = table.columns.map(column => this.buildCreateColumnSql(column, false, true)).join(", ");
|
||||
let sql = `CREATE TABLE "${table.name}" (${columnDefinitions}`;
|
||||
sql += table.columns
|
||||
.filter(column => column.isUnique)
|
||||
@ -476,16 +477,6 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
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.
|
||||
*/
|
||||
@ -494,7 +485,7 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
|
||||
const sql = `ALTER TABLE "${tableName}" ADD ${this.buildCreateColumnSql(column)}`;
|
||||
const sql = `ALTER TABLE "${tableName}" ADD ${this.buildCreateColumnSql(column, false, true)}`;
|
||||
return this.query(sql);
|
||||
}
|
||||
|
||||
@ -605,10 +596,10 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
// to update an identy column we have to drop column and recreate it again
|
||||
if (newColumn.isGenerated !== oldColumn.isGenerated) {
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" DROP COLUMN "${newColumn.name}"`);
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" ADD ${this.buildCreateColumnSql(newColumn)}`);
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" ADD ${this.buildCreateColumnSql(newColumn, false, false)}`);
|
||||
}
|
||||
|
||||
const sql = `ALTER TABLE "${tableSchema.name}" ALTER COLUMN ${this.buildCreateColumnSql(newColumn, true)}`; // todo: CHANGE OR MODIFY COLUMN ????
|
||||
const sql = `ALTER TABLE "${tableSchema.name}" ALTER COLUMN ${this.buildCreateColumnSql(newColumn, true, false)}`; // todo: CHANGE OR MODIFY COLUMN ????
|
||||
await this.query(sql);
|
||||
|
||||
if (newColumn.isUnique !== oldColumn.isUnique) {
|
||||
@ -620,6 +611,16 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
|
||||
}
|
||||
}
|
||||
if (newColumn.default !== oldColumn.default) {
|
||||
if (newColumn.default !== null && newColumn.default !== undefined) {
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" DROP CONSTRAINT "df_${newColumn.name}"`);
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" ADD CONSTRAINT "df_${newColumn.name}" DEFAULT ${newColumn.default} FOR "${newColumn.name}"`);
|
||||
|
||||
} else if (oldColumn.default !== null && oldColumn.default !== undefined) {
|
||||
await this.query(`ALTER TABLE "${tableSchema.name}" DROP CONSTRAINT "df_${newColumn.name}"`);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -639,40 +640,24 @@ export class SqlServerQueryRunner implements QueryRunner {
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
// drop depend constraints
|
||||
if (column.default)
|
||||
await this.query(`ALTER TABLE "${table.name}" DROP CONSTRAINT "df_${column.name}"`);
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
const tableName = tableSchemaOrName instanceof TableSchema ? tableSchemaOrName.name : tableSchemaOrName;
|
||||
const columnName = columnSchemaOrName instanceof ColumnSchema ? columnSchemaOrName.name : columnSchemaOrName;
|
||||
return this.query(`ALTER TABLE "${tableName}" DROP COLUMN "${columnName}"`);
|
||||
// drop column itself
|
||||
await this.query(`ALTER TABLE "${table.name}" DROP COLUMN "${column.name}"`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const dropPromises = (columnSchemasOrNames as any[]).map(column => this.dropColumn(tableSchemaOrName as any, column as any));
|
||||
const dropPromises = columns.map(column => this.dropColumn(table, column));
|
||||
await Promise.all(dropPromises);
|
||||
}
|
||||
|
||||
@ -840,7 +825,7 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
|
||||
/**
|
||||
* Builds a query for create column.
|
||||
*/
|
||||
protected buildCreateColumnSql(column: ColumnSchema, skipIdentity: boolean = false) {
|
||||
protected buildCreateColumnSql(column: ColumnSchema, skipIdentity: boolean, createDefault: boolean) {
|
||||
let c = `"${column.name}" ${column.type}`;
|
||||
if (column.isNullable !== true)
|
||||
c += " NOT NULL";
|
||||
@ -850,17 +835,9 @@ WHERE columnUsages.TABLE_CATALOG = '${this.dbName}' AND tableConstraints.TABLE_C
|
||||
// c += " PRIMARY KEY";
|
||||
if (column.comment)
|
||||
c += " COMMENT '" + column.comment + "'";
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "1" : "0") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
if (createDefault) {
|
||||
if (column.default !== undefined && column.default !== null) {
|
||||
c += ` CONSTRAINT "df_${column.name}" DEFAULT ${column.default}`;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
|
||||
@ -11,11 +11,21 @@ export interface MappedColumnTypes {
|
||||
*/
|
||||
createDate: ColumnType;
|
||||
|
||||
/**
|
||||
* Default value should be used by a database for "created date" column.
|
||||
*/
|
||||
createDateDefault: string;
|
||||
|
||||
/**
|
||||
* Column type for the update date column.
|
||||
*/
|
||||
updateDate: ColumnType;
|
||||
|
||||
/**
|
||||
* Default value should be used by a database for "updated date" column.
|
||||
*/
|
||||
updateDateDefault: string;
|
||||
|
||||
/**
|
||||
* Column type for the version column.
|
||||
*/
|
||||
|
||||
@ -78,7 +78,9 @@ export class WebsqlDriver implements Driver {
|
||||
*/
|
||||
mappedDataTypes: MappedColumnTypes = {
|
||||
createDate: "datetime",
|
||||
createDateDefault: "DATETIME()",
|
||||
updateDate: "datetime",
|
||||
updateDateDefault: "DATETIME()",
|
||||
version: "number",
|
||||
treeLevel: "number",
|
||||
migrationName: "varchar",
|
||||
@ -279,4 +281,25 @@ export class WebsqlDriver implements Driver {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes "default" value of the column.
|
||||
*/
|
||||
normalizeDefault(column: ColumnMetadata): string {
|
||||
if (typeof column.default === "number") {
|
||||
return "" + column.default;
|
||||
|
||||
} else if (typeof column.default === "boolean") {
|
||||
return column.default === true ? "1" : "0";
|
||||
|
||||
} else if (typeof column.default === "function") {
|
||||
return column.default();
|
||||
|
||||
} else if (typeof column.default === "string") {
|
||||
return `'${column.default}'`;
|
||||
|
||||
} else {
|
||||
return column.default;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -114,7 +114,9 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
await this.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.rollbackTransaction();
|
||||
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;`);
|
||||
@ -610,51 +612,18 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchema: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops column in the table.
|
||||
*/
|
||||
async dropColumn(tableSchemaOrName: TableSchema|string, columnSchemaOrName: ColumnSchema|string): Promise<void> {
|
||||
return this.dropColumns(tableSchemaOrName as any, [columnSchemaOrName as any]);
|
||||
async dropColumn(table: TableSchema, column: ColumnSchema): Promise<void> {
|
||||
return this.dropColumns(table, [column]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchema: TableSchema, columns: ColumnSchema[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
async dropColumns(tableSchemaOrName: TableSchema|string, columnSchemasOrNames: ColumnSchema[]|string[]): Promise<void> {
|
||||
async dropColumns(table: TableSchema, columns: ColumnSchema[]): Promise<void> {
|
||||
if (this.isReleased)
|
||||
throw new QueryRunnerAlreadyReleasedError();
|
||||
|
||||
const tableSchema = await this.getTableSchema(tableSchemaOrName);
|
||||
const updatingTableSchema = tableSchema.clone();
|
||||
const columns = (columnSchemasOrNames as any[]).map(columnSchemasOrName => {
|
||||
if (typeof columnSchemasOrName === "string") {
|
||||
const column = tableSchema.columns.find(column => column.name === columnSchemasOrName);
|
||||
if (!column)
|
||||
throw new Error(`Cannot drop a column - column "${columnSchemasOrName}" was not found in the "${tableSchema.name}" table.`);
|
||||
|
||||
return column;
|
||||
|
||||
} else {
|
||||
return columnSchemasOrName as ColumnSchema;
|
||||
}
|
||||
});
|
||||
const updatingTableSchema = table.clone();
|
||||
updatingTableSchema.removeColumns(columns);
|
||||
return this.recreateTable(updatingTableSchema);
|
||||
}
|
||||
@ -812,19 +781,8 @@ export class WebsqlQueryRunner implements QueryRunner {
|
||||
c += " UNIQUE";
|
||||
if (column.isGenerated === true) // don't use skipPrimary here since updates can update already exist primary without auto inc.
|
||||
c += " PRIMARY KEY AUTOINCREMENT";
|
||||
if (column.default !== undefined && column.default !== null) { // todo: same code in all drivers. make it DRY
|
||||
if (typeof column.default === "number") {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
} else if (typeof column.default === "boolean") {
|
||||
c += " DEFAULT " + (column.default === true ? "TRUE" : "FALSE") + "";
|
||||
} else if (typeof column.default === "function") {
|
||||
c += " DEFAULT " + column.default() + "";
|
||||
} else if (typeof column.default === "string") {
|
||||
c += " DEFAULT '" + column.default + "'";
|
||||
} else {
|
||||
c += " DEFAULT " + column.default + "";
|
||||
}
|
||||
}
|
||||
if (column.default !== undefined && column.default !== null) // todo: same code in all drivers. make it DRY
|
||||
c += ` DEFAULT ${column.default}`;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -221,10 +221,16 @@ export class ColumnMetadata {
|
||||
}
|
||||
if (this.isTreeLevel)
|
||||
this.type = options.connection.driver.mappedDataTypes.treeLevel;
|
||||
if (this.isCreateDate)
|
||||
if (this.isCreateDate) {
|
||||
this.type = options.connection.driver.mappedDataTypes.createDate;
|
||||
if (this.isUpdateDate)
|
||||
if (!this.default)
|
||||
this.default = () => options.connection.driver.mappedDataTypes.createDateDefault;
|
||||
}
|
||||
if (this.isUpdateDate) {
|
||||
this.type = options.connection.driver.mappedDataTypes.updateDate;
|
||||
if (!this.default)
|
||||
this.default = () => options.connection.driver.mappedDataTypes.updateDateDefault;
|
||||
}
|
||||
if (this.isVersion)
|
||||
this.type = options.connection.driver.mappedDataTypes.version;
|
||||
}
|
||||
|
||||
@ -100,8 +100,11 @@ export class MigrationExecutor {
|
||||
await this.queryRunner.commitTransaction();
|
||||
|
||||
} catch (err) { // rollback transaction if we started it
|
||||
if (transactionStartedByUs)
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
if (transactionStartedByUs) {
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
@ -161,8 +164,11 @@ export class MigrationExecutor {
|
||||
await this.queryRunner.commitTransaction();
|
||||
|
||||
} catch (err) { // rollback transaction if we started it
|
||||
if (transactionStartedByUs)
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
if (transactionStartedByUs) {
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
@ -135,9 +135,7 @@ export class SubjectOperationExecutor {
|
||||
if (isTransactionStartedByItself) {
|
||||
try {
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
|
||||
} catch (secondaryError) {
|
||||
}
|
||||
} catch (rollbackError) { }
|
||||
}
|
||||
|
||||
throw error;
|
||||
|
||||
@ -166,26 +166,11 @@ export interface QueryRunner {
|
||||
*/
|
||||
changeColumns(table: TableSchema, changedColumns: { oldColumn: ColumnSchema, newColumn: ColumnSchema }[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the column in the table.
|
||||
*/
|
||||
dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the column in the table.
|
||||
*/
|
||||
dropColumn(tableName: string, columnName: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the column in the table.
|
||||
*/
|
||||
dropColumn(table: TableSchema, column: ColumnSchema): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
dropColumns(tableName: string, columnNames: string[]): Promise<void>;
|
||||
|
||||
/**
|
||||
* Drops the columns in the table.
|
||||
*/
|
||||
|
||||
@ -74,7 +74,10 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
await this.queryRunner.commitTransaction();
|
||||
|
||||
} catch (error) {
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
|
||||
try { // we throw original error even if rollback thrown an error
|
||||
await this.queryRunner.rollbackTransaction();
|
||||
} catch (rollbackError) { }
|
||||
throw error;
|
||||
|
||||
} finally {
|
||||
@ -244,7 +247,7 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
// generate a map of new/old columns
|
||||
const newAndOldColumnSchemas = updatedColumnSchemas.map(changedColumnSchema => {
|
||||
const columnMetadata = metadata.columns.find(column => column.databaseName === changedColumnSchema.name);
|
||||
const newColumnSchema = ColumnSchema.create(columnMetadata!, this.connection.driver.normalizeType(columnMetadata!));
|
||||
const newColumnSchema = ColumnSchema.create(columnMetadata!, this.connection.driver.normalizeType(columnMetadata!), this.connection.driver.normalizeDefault(columnMetadata!));
|
||||
tableSchema.replaceColumn(changedColumnSchema, newColumnSchema);
|
||||
|
||||
return {
|
||||
@ -427,7 +430,11 @@ export class RdbmsSchemaBuilder implements SchemaBuilder {
|
||||
*/
|
||||
protected metadataColumnsToColumnSchemas(columns: ColumnMetadata[]): ColumnSchema[] {
|
||||
return columns.map(columnMetadata => {
|
||||
return ColumnSchema.create(columnMetadata, this.connection.driver.normalizeType(columnMetadata));
|
||||
return ColumnSchema.create(
|
||||
columnMetadata,
|
||||
this.connection.driver.normalizeType(columnMetadata),
|
||||
this.connection.driver.normalizeDefault(columnMetadata),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -102,10 +102,10 @@ export class ColumnSchema {
|
||||
/**
|
||||
* Creates a new column based on the given column metadata.
|
||||
*/
|
||||
static create(columnMetadata: ColumnMetadata, normalizedType: string): ColumnSchema {
|
||||
static create(columnMetadata: ColumnMetadata, normalizedType: string, normalizedDefault: string): ColumnSchema {
|
||||
const columnSchema = new ColumnSchema();
|
||||
columnSchema.name = columnMetadata.databaseName;
|
||||
columnSchema.default = columnMetadata.default;
|
||||
columnSchema.default = normalizedDefault;
|
||||
columnSchema.comment = columnMetadata.comment;
|
||||
columnSchema.isGenerated = columnMetadata.isGenerated;
|
||||
columnSchema.isNullable = columnMetadata.isNullable;
|
||||
|
||||
@ -209,10 +209,18 @@ export class TableSchema {
|
||||
if (!columnMetadata)
|
||||
return false; // we don't need new columns, we only need exist and changed
|
||||
|
||||
// console.log(columnSchema.name, "!==", columnMetadata.databaseName); // ||
|
||||
// console.log(columnSchema.type, "!==", driver.normalizeType(columnMetadata)); // ||
|
||||
// console.log(columnSchema.comment, "!==", columnMetadata.comment); // ||
|
||||
// console.log(this.compareDefaultValues(driver.normalizeDefault(columnMetadata), columnSchema.default)); // || // we included check for generated here, because generated columns already can have default values
|
||||
// console.log(columnSchema.isNullable, "!==", columnMetadata.isNullable); // ||
|
||||
// console.log(columnSchema.isUnique, "!==", columnMetadata.isUnique); // ||
|
||||
// console.log(columnSchema.isGenerated, "!==", columnMetadata.isGenerated); // d;
|
||||
|
||||
return columnSchema.name !== columnMetadata.databaseName ||
|
||||
columnSchema.type !== driver.normalizeType(columnMetadata) ||
|
||||
columnSchema.comment !== columnMetadata.comment ||
|
||||
(!columnSchema.isGenerated && !this.compareDefaultValues(columnMetadata.default, columnSchema.default)) || // we included check for generated here, because generated columns already can have default values
|
||||
(!columnSchema.isGenerated && !this.compareDefaultValues(driver.normalizeDefault(columnMetadata), columnSchema.default)) || // we included check for generated here, because generated columns already can have default values
|
||||
columnSchema.isNullable !== columnMetadata.isNullable ||
|
||||
columnSchema.isUnique !== columnMetadata.isUnique ||
|
||||
// columnSchema.isPrimary !== columnMetadata.isPrimary ||
|
||||
@ -227,15 +235,36 @@ export class TableSchema {
|
||||
/**
|
||||
* Checks if "DEFAULT" values in the column metadata and in the database schema are equal.
|
||||
*/
|
||||
protected compareDefaultValues(columnMetadataValue: any, databaseValue: any): boolean {
|
||||
protected compareDefaultValues(columnMetadataValue: string, databaseValue: string): boolean {
|
||||
|
||||
if (typeof columnMetadataValue === "number")
|
||||
return columnMetadataValue === parseInt(databaseValue);
|
||||
if (typeof columnMetadataValue === "boolean")
|
||||
return columnMetadataValue === (!!databaseValue || databaseValue === "false");
|
||||
if (typeof columnMetadataValue === "function")
|
||||
return columnMetadataValue() === databaseValue;
|
||||
// if (typeof columnMetadataValue === "number")
|
||||
// return columnMetadataValue === parseInt(databaseValue);
|
||||
// if (typeof columnMetadataValue === "boolean")
|
||||
// return columnMetadataValue === (!!databaseValue || databaseValue === "false");
|
||||
// if (typeof columnMetadataValue === "function")
|
||||
// if (typeof columnMetadataValue === "string" && typeof databaseValue === "string")
|
||||
// return columnMetadataValue.toLowerCase() === databaseValue.toLowerCase();
|
||||
|
||||
|
||||
if (typeof columnMetadataValue === "string" && typeof databaseValue === "string") {
|
||||
|
||||
// we need to cut out "((x))" where x number generated by mssql
|
||||
columnMetadataValue = columnMetadataValue.replace(/\(\([0-9.]*\)\)$/g, "$1");
|
||||
databaseValue = databaseValue.replace(/\(\(([0-9.]*?)\)\)$/g, "$1");
|
||||
|
||||
// we need to cut out "(" because in mssql we can understand returned value is a string or a function
|
||||
// as result compare cannot understand if default is really changed or not
|
||||
columnMetadataValue = columnMetadataValue.replace(/^\(|\)$/g, "");
|
||||
databaseValue = databaseValue.replace(/^\(|\)$/g, "");
|
||||
|
||||
// we need to cut out "'" because in mysql we can understand returned value is a string or a function
|
||||
// as result compare cannot understand if default is really changed or not
|
||||
columnMetadataValue = columnMetadataValue.replace(/^'+|'+$/g, "");
|
||||
databaseValue = databaseValue.replace(/^'+|'+$/g, "");
|
||||
}
|
||||
|
||||
// console.log("columnMetadataValue", columnMetadataValue);
|
||||
// console.log("databaseValue", databaseValue);
|
||||
return columnMetadataValue === databaseValue;
|
||||
}
|
||||
|
||||
@ -252,7 +281,7 @@ export class TableSchema {
|
||||
const tableSchema = new TableSchema(entityMetadata.tableName);
|
||||
tableSchema.engine = entityMetadata.engine;
|
||||
entityMetadata.columns.forEach(column => {
|
||||
tableSchema.columns.push(ColumnSchema.create(column, driver.normalizeType(column)));
|
||||
tableSchema.columns.push(ColumnSchema.create(column, driver.normalizeType(column), driver.normalizeDefault(column)));
|
||||
});
|
||||
|
||||
return tableSchema;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user