diff --git a/src/Engine.ts b/src/Engine.ts index 7011ecc..93e26fd 100644 --- a/src/Engine.ts +++ b/src/Engine.ts @@ -528,7 +528,9 @@ function applyNamingStrategy( entity.relationIds .filter(v => v.relationField === oldName) - .forEach(v => (v.relationField = newName)); + .forEach(v => { + v.relationField = newName; + }); relation.fieldName = newName; relation2.relatedField = newName; diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index 7904c24..fb577ee 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -3,7 +3,7 @@ import { WithPrecisionColumnType, WithWidthColumnType } from "typeorm/driver/types/ColumnTypes"; -import { JoinColumnOptions } from "typeorm"; +import { JoinColumnOptions, RelationOptions } from "typeorm"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import EntityInfo from "../oldModels/EntityInfo"; @@ -372,16 +372,17 @@ export default abstract class AbstractDriver { ); } + const relationOptions: RelationOptions = { + onDelete: relationTmp.onDelete, + onUpdate: relationTmp.onUpdate + }; + const ownerRelation: Relation = { fieldName, relatedField: TomgUtils.findNameForNewField( relationTmp.ownerTable.tscName, relationTmp.relatedTable ), - relationOptions: { - onDelete: relationTmp.onDelete, - onUpdate: relationTmp.onUpdate - }, joinColumnOptions: relationTmp.ownerColumns.map((v, idx) => { const retVal: JoinColumnOptions = { name: v, @@ -392,6 +393,9 @@ export default abstract class AbstractDriver { relatedTable: relationTmp.relatedTable.tscName, relationType: isOneToMany ? "ManyToOne" : "OneToOne" }; + if (JSON.stringify(relationOptions) !== "{}") { + ownerRelation.relationOptions = relationOptions; + } const relatedRelation: Relation = { fieldName: ownerRelation.relatedField, relatedField: ownerRelation.fieldName, diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 057357b..1331107 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -4,13 +4,12 @@ import * as TypeormDriver from "typeorm/driver/sqlserver/SqlServerDriver"; import { DataTypeDefaults } from "typeorm/driver/types/DataTypeDefaults"; import * as TomgUtils from "../Utils"; import AbstractDriver from "./AbstractDriver"; -import EntityInfo from "../oldModels/EntityInfo"; -import ColumnInfo from "../oldModels/ColumnInfo"; -import IndexInfo from "../oldModels/IndexInfo"; -import IndexColumnInfo from "../oldModels/IndexColumnInfo"; -import RelationTempInfo from "../oldModels/RelationTempInfo"; import IConnectionOptions from "../IConnectionOptions"; import { Entity } from "../models/Entity"; +import { Column } from "../models/Column"; +import { Index } from "../models/Index"; +import IGenerationOptions from "../IGenerationOptions"; +import { RelationInternal } from "../models/RelationInternal"; export default class MssqlDriver extends AbstractDriver { public defaultValues: DataTypeDefaults = new TypeormDriver.SqlServerDriver({ @@ -45,185 +44,193 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG schema: string, dbNames: string ): Promise { - throw new Error(); - // TODO: Remove - // const request = new MSSQL.Request(this.Connection); - // const response: { - // TABLE_NAME: string; - // COLUMN_NAME: string; - // COLUMN_DEFAULT: string; - // IS_NULLABLE: string; - // DATA_TYPE: string; - // CHARACTER_MAXIMUM_LENGTH: number; - // NUMERIC_PRECISION: number; - // NUMERIC_SCALE: number; - // IsIdentity: number; - // IsUnique: number; - // }[] = (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE, - // DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE, - // COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity, - // (SELECT count(*) - // FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc - // inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu - // on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME - // where - // tc.CONSTRAINT_TYPE = 'UNIQUE' - // and tc.TABLE_NAME = c.TABLE_NAME - // and cu.COLUMN_NAME = c.COLUMN_NAME - // and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique - // FROM INFORMATION_SCHEMA.COLUMNS c - // where TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList( - // dbNames - // )}) - // order by ordinal_position`)).recordset; - // entities.forEach(ent => { - // response - // .filter(filterVal => { - // return filterVal.TABLE_NAME === ent.tsEntityName; - // }) - // .forEach(resp => { - // const colInfo: ColumnInfo = new ColumnInfo(); - // colInfo.tsName = resp.COLUMN_NAME; - // colInfo.options.name = resp.COLUMN_NAME; - // colInfo.options.nullable = resp.IS_NULLABLE === "YES"; - // colInfo.options.generated = resp.IsIdentity === 1; - // colInfo.options.unique = resp.IsUnique === 1; - // colInfo.options.default = MssqlDriver.ReturnDefaultValueFunction( - // resp.COLUMN_DEFAULT - // ); - // colInfo.options.type = resp.DATA_TYPE as any; - // switch (resp.DATA_TYPE) { - // case "bigint": - // colInfo.tsType = "string"; - // break; - // case "bit": - // colInfo.tsType = "boolean"; - // break; - // case "decimal": - // colInfo.tsType = "number"; - // break; - // case "int": - // colInfo.tsType = "number"; - // break; - // case "money": - // colInfo.tsType = "number"; - // break; - // case "numeric": - // colInfo.tsType = "number"; - // break; - // case "smallint": - // colInfo.tsType = "number"; - // break; - // case "smallmoney": - // colInfo.tsType = "number"; - // break; - // case "tinyint": - // colInfo.tsType = "number"; - // break; - // case "float": - // colInfo.tsType = "number"; - // break; - // case "real": - // colInfo.tsType = "number"; - // break; - // case "date": - // colInfo.tsType = "Date"; - // break; - // case "datetime2": - // colInfo.tsType = "Date"; - // break; - // case "datetime": - // colInfo.tsType = "Date"; - // break; - // case "datetimeoffset": - // colInfo.tsType = "Date"; - // break; - // case "smalldatetime": - // colInfo.tsType = "Date"; - // break; - // case "time": - // colInfo.tsType = "Date"; - // break; - // case "char": - // colInfo.tsType = "string"; - // break; - // case "text": - // colInfo.tsType = "string"; - // break; - // case "varchar": - // colInfo.tsType = "string"; - // break; - // case "nchar": - // colInfo.tsType = "string"; - // break; - // case "ntext": - // colInfo.tsType = "string"; - // break; - // case "nvarchar": - // colInfo.tsType = "string"; - // break; - // case "binary": - // colInfo.tsType = "Buffer"; - // break; - // case "image": - // colInfo.tsType = "Buffer"; - // break; - // case "varbinary": - // colInfo.tsType = "Buffer"; - // break; - // case "hierarchyid": - // colInfo.tsType = "string"; - // break; - // case "sql_variant": - // colInfo.tsType = "string"; - // break; - // case "timestamp": - // colInfo.tsType = "Date"; - // break; - // case "uniqueidentifier": - // colInfo.tsType = "string"; - // break; - // case "xml": - // colInfo.tsType = "string"; - // break; - // case "geometry": - // colInfo.tsType = "string"; - // break; - // case "geography": - // colInfo.tsType = "string"; - // break; - // default: - // TomgUtils.LogError( - // `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` - // ); - // break; - // } + const request = new MSSQL.Request(this.Connection); + const response: { + TABLE_NAME: string; + COLUMN_NAME: string; + COLUMN_DEFAULT: string; + IS_NULLABLE: string; + DATA_TYPE: string; + CHARACTER_MAXIMUM_LENGTH: number; + NUMERIC_PRECISION: number; + NUMERIC_SCALE: number; + IsIdentity: number; + IsUnique: number; + }[] = (await request.query(`SELECT TABLE_NAME,COLUMN_NAME,COLUMN_DEFAULT,IS_NULLABLE, + DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE, + COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') IsIdentity, + (SELECT count(*) + FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc + inner join INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu + on cu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME + where + tc.CONSTRAINT_TYPE = 'UNIQUE' + and tc.TABLE_NAME = c.TABLE_NAME + and cu.COLUMN_NAME = c.COLUMN_NAME + and tc.TABLE_SCHEMA=c.TABLE_SCHEMA) IsUnique + FROM INFORMATION_SCHEMA.COLUMNS c + where TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG in (${MssqlDriver.escapeCommaSeparatedList( + dbNames + )}) + order by ordinal_position`)).recordset; + entities.forEach(ent => { + response + .filter(filterVal => { + return filterVal.TABLE_NAME === ent.tscName; + }) + .forEach(resp => { + const tscName = resp.COLUMN_NAME; + const options: Partial = {}; + options.name = resp.COLUMN_NAME; + if (resp.IS_NULLABLE === "YES") options.nullable = true; + if (resp.IsUnique === 1) options.unique = true; + const generated = resp.IsIdentity === 1 ? true : undefined; + const defaultValue = MssqlDriver.ReturnDefaultValueFunction( + resp.COLUMN_DEFAULT + ); + const columnType = resp.DATA_TYPE as any; + let tscType = ""; + switch (resp.DATA_TYPE) { + case "bigint": + tscType = "string"; + break; + case "bit": + tscType = "boolean"; + break; + case "decimal": + tscType = "number"; + break; + case "int": + tscType = "number"; + break; + case "money": + tscType = "number"; + break; + case "numeric": + tscType = "number"; + break; + case "smallint": + tscType = "number"; + break; + case "smallmoney": + tscType = "number"; + break; + case "tinyint": + tscType = "number"; + break; + case "float": + tscType = "number"; + break; + case "real": + tscType = "number"; + break; + case "date": + tscType = "Date"; + break; + case "datetime2": + tscType = "Date"; + break; + case "datetime": + tscType = "Date"; + break; + case "datetimeoffset": + tscType = "Date"; + break; + case "smalldatetime": + tscType = "Date"; + break; + case "time": + tscType = "Date"; + break; + case "char": + tscType = "string"; + break; + case "text": + tscType = "string"; + break; + case "varchar": + tscType = "string"; + break; + case "nchar": + tscType = "string"; + break; + case "ntext": + tscType = "string"; + break; + case "nvarchar": + tscType = "string"; + break; + case "binary": + tscType = "Buffer"; + break; + case "image": + tscType = "Buffer"; + break; + case "varbinary": + tscType = "Buffer"; + break; + case "hierarchyid": + tscType = "string"; + break; + case "sql_variant": + tscType = "string"; + break; + case "timestamp": + tscType = "Date"; + break; + case "uniqueidentifier": + tscType = "string"; + break; + case "xml": + tscType = "string"; + break; + case "geometry": + tscType = "string"; + break; + case "geography": + tscType = "string"; + break; + default: + TomgUtils.LogError( + `Unknown column type: ${resp.DATA_TYPE} table name: ${resp.TABLE_NAME} column name: ${resp.COLUMN_NAME}` + ); + break; + } - // if ( - // this.ColumnTypesWithPrecision.some( - // v => v === colInfo.options.type - // ) - // ) { - // colInfo.options.precision = resp.NUMERIC_PRECISION; - // colInfo.options.scale = resp.NUMERIC_SCALE; - // } - // if ( - // this.ColumnTypesWithLength.some( - // v => v === colInfo.options.type - // ) - // ) { - // colInfo.options.length = - // resp.CHARACTER_MAXIMUM_LENGTH > 0 - // ? resp.CHARACTER_MAXIMUM_LENGTH - // : undefined; - // } + if ( + this.ColumnTypesWithPrecision.some( + v => v === columnType + ) + ) { + if (resp.NUMERIC_PRECISION !== null) { + options.precision = resp.NUMERIC_PRECISION; + } + if (resp.NUMERIC_SCALE !== null) { + options.scale = resp.NUMERIC_SCALE; + } + } + if ( + this.ColumnTypesWithLength.some(v => v === columnType) + ) { + options.length = + resp.CHARACTER_MAXIMUM_LENGTH > 0 + ? resp.CHARACTER_MAXIMUM_LENGTH + : undefined; + } - // if (colInfo.options.type) { - // ent.Columns.push(colInfo); - // } - // }); - // }); - // return entities; + if (columnType) { + ent.columns.push({ + generated, + type: columnType, + default: defaultValue, + options: { name: "", ...options }, // TODO: Change + tscName, + tscType + }); + } + }); + }); + return entities; } public async GetIndexesFromEntity( @@ -231,181 +238,189 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG schema: string, dbNames: string ): Promise { - throw new Error(); - // TODO: Remove - // const request = new MSSQL.Request(this.Connection); - // const response: { - // TableName: string; - // IndexName: string; - // ColumnName: string; - // is_unique: boolean; - // is_primary_key: boolean; - // }[] = []; - // await Promise.all( - // dbNames.split(",").map(async dbName => { - // await this.UseDB(dbName); - // const resp: { - // TableName: string; - // IndexName: string; - // ColumnName: string; - // is_unique: boolean; - // is_primary_key: boolean; - // }[] = (await request.query(`SELECT - // TableName = t.name, - // IndexName = ind.name, - // ColumnName = col.name, - // ind.is_unique, - // ind.is_primary_key - // FROM - // sys.indexes ind - // INNER JOIN - // sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id - // INNER JOIN - // sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id - // INNER JOIN - // sys.tables t ON ind.object_id = t.object_id - // INNER JOIN - // sys.schemas s on s.schema_id=t.schema_id - // WHERE - // t.is_ms_shipped = 0 and s.name in (${schema}) - // ORDER BY - // t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset; - // response.push(...resp); - // }) - // ); - // entities.forEach(ent => { - // response - // .filter(filterVal => filterVal.TableName === ent.tsEntityName) - // .forEach(resp => { - // let indexInfo: IndexInfo = {} as IndexInfo; - // const indexColumnInfo: IndexColumnInfo = {} as IndexColumnInfo; - // if ( - // ent.Indexes.filter(filterVal => { - // return filterVal.name === resp.IndexName; - // }).length > 0 - // ) { - // [indexInfo] = ent.Indexes.filter(filterVal => { - // return filterVal.name === resp.IndexName; - // }); - // } else { - // indexInfo.columns = [] as IndexColumnInfo[]; - // indexInfo.name = resp.IndexName; - // indexInfo.isUnique = resp.is_unique; - // indexInfo.isPrimaryKey = resp.is_primary_key; - // ent.Indexes.push(indexInfo); - // } - // indexColumnInfo.name = resp.ColumnName; - // indexInfo.columns.push(indexColumnInfo); - // }); - // }); + const request = new MSSQL.Request(this.Connection); + const response: { + TableName: string; + IndexName: string; + ColumnName: string; + is_unique: boolean; + is_primary_key: boolean; + }[] = []; + await Promise.all( + dbNames.split(",").map(async dbName => { + await this.UseDB(dbName); + const resp: { + TableName: string; + IndexName: string; + ColumnName: string; + is_unique: boolean; + is_primary_key: boolean; + }[] = (await request.query(`SELECT + TableName = t.name, + IndexName = ind.name, + ColumnName = col.name, + ind.is_unique, + ind.is_primary_key + FROM + sys.indexes ind + INNER JOIN + sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id + INNER JOIN + sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id + INNER JOIN + sys.tables t ON ind.object_id = t.object_id + INNER JOIN + sys.schemas s on s.schema_id=t.schema_id + WHERE + t.is_ms_shipped = 0 and s.name in (${schema}) + ORDER BY + t.name, ind.name, ind.index_id, ic.key_ordinal;`)).recordset; + response.push(...resp); + }) + ); - // return entities; + entities.forEach(ent => { + const entityIndices = response.filter( + filterVal => filterVal.TableName === ent.tscName + ); + const indexNames = new Set(entityIndices.map(v => v.IndexName)); + indexNames.forEach(indexName => { + const records = entityIndices.filter( + v => v.IndexName === indexName + ); + const indexInfo: Index = { + columns: [], + options: {}, + name: records[0].IndexName + }; + if (records[0].is_primary_key) indexInfo.primary = true; + if (records[0].is_unique) indexInfo.options.unique = true; + records.forEach(record => { + indexInfo.columns.push(record.ColumnName); + }); + ent.indices.push(indexInfo); + }); + }); + + return entities; } public async GetRelations( entities: Entity[], schema: string, - dbNames: string + dbNames: string, + generationOptions: IGenerationOptions ): Promise { - throw new Error(); - // TODO: Remove - // const request = new MSSQL.Request(this.Connection); - // const response: { - // TableWithForeignKey: string; - // FK_PartNo: number; - // ForeignKeyColumn: string; - // TableReferenced: string; - // ForeignKeyColumnReferenced: string; - // onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; - // onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; - // objectId: number; - // }[] = []; - // await Promise.all( - // dbNames.split(",").map(async dbName => { - // await this.UseDB(dbName); - // const resp: { - // TableWithForeignKey: string; - // FK_PartNo: number; - // ForeignKeyColumn: string; - // TableReferenced: string; - // ForeignKeyColumnReferenced: string; - // onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; - // onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; - // objectId: number; - // }[] = (await request.query(`select - // parentTable.name as TableWithForeignKey, - // fkc.constraint_column_id as FK_PartNo, - // parentColumn.name as ForeignKeyColumn, - // referencedTable.name as TableReferenced, - // referencedColumn.name as ForeignKeyColumnReferenced, - // fk.delete_referential_action_desc as onDelete, - // fk.update_referential_action_desc as onUpdate, - // fk.object_id as objectId - // from - // sys.foreign_keys fk - // inner join - // sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id - // inner join - // sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id - // inner join - // sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id - // inner join - // sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id - // inner join - // sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id - // inner join - // sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id - // where - // fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema}) - // order by - // TableWithForeignKey, FK_PartNo`)).recordset; - // response.push(...resp); - // }) - // ); - // const relationsTemp: RelationTempInfo[] = [] as RelationTempInfo[]; - // response.forEach(resp => { - // let rels = relationsTemp.find( - // val => val.objectId === resp.objectId - // ); - // if (rels === undefined) { - // rels = {} as RelationTempInfo; - // rels.ownerColumnsNames = []; - // rels.referencedColumnsNames = []; - // switch (resp.onDelete) { - // case "NO_ACTION": - // rels.actionOnDelete = null; - // break; - // case "SET_NULL": - // rels.actionOnDelete = "SET NULL"; - // break; - // default: - // rels.actionOnDelete = resp.onDelete; - // break; - // } - // switch (resp.onUpdate) { - // case "NO_ACTION": - // rels.actionOnUpdate = null; - // break; - // case "SET_NULL": - // rels.actionOnUpdate = "SET NULL"; - // break; - // default: - // rels.actionOnUpdate = resp.onUpdate; - // break; - // } - // rels.objectId = resp.objectId; - // rels.ownerTable = resp.TableWithForeignKey; - // rels.referencedTable = resp.TableReferenced; - // relationsTemp.push(rels); - // } - // rels.ownerColumnsNames.push(resp.ForeignKeyColumn); - // rels.referencedColumnsNames.push(resp.ForeignKeyColumnReferenced); - // }); - // const retVal = MssqlDriver.GetRelationsFromRelationTempInfo( - // relationsTemp, - // entities - // ); - // return retVal; + const request = new MSSQL.Request(this.Connection); + const response: { + TableWithForeignKey: string; + FK_PartNo: number; + ForeignKeyColumn: string; + TableReferenced: string; + ForeignKeyColumnReferenced: string; + onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; + onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; + objectId: number; + }[] = []; + await Promise.all( + dbNames.split(",").map(async dbName => { + await this.UseDB(dbName); + const resp: { + TableWithForeignKey: string; + FK_PartNo: number; + ForeignKeyColumn: string; + TableReferenced: string; + ForeignKeyColumnReferenced: string; + onDelete: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; + onUpdate: "RESTRICT" | "CASCADE" | "SET_NULL" | "NO_ACTION"; + objectId: number; + }[] = (await request.query(`select + parentTable.name as TableWithForeignKey, + fkc.constraint_column_id as FK_PartNo, + parentColumn.name as ForeignKeyColumn, + referencedTable.name as TableReferenced, + referencedColumn.name as ForeignKeyColumnReferenced, + fk.delete_referential_action_desc as onDelete, + fk.update_referential_action_desc as onUpdate, + fk.object_id as objectId + from + sys.foreign_keys fk + inner join + sys.foreign_key_columns as fkc on fkc.constraint_object_id=fk.object_id + inner join + sys.tables as parentTable on fkc.parent_object_id = parentTable.object_id + inner join + sys.columns as parentColumn on fkc.parent_object_id = parentColumn.object_id and fkc.parent_column_id = parentColumn.column_id + inner join + sys.tables as referencedTable on fkc.referenced_object_id = referencedTable.object_id + inner join + sys.columns as referencedColumn on fkc.referenced_object_id = referencedColumn.object_id and fkc.referenced_column_id = referencedColumn.column_id + inner join + sys.schemas as parentSchema on parentSchema.schema_id=parentTable.schema_id + where + fk.is_disabled=0 and fk.is_ms_shipped=0 and parentSchema.name in (${schema}) + order by + TableWithForeignKey, FK_PartNo`)).recordset; + response.push(...resp); + }) + ); + const relationsTemp: RelationInternal[] = [] as RelationInternal[]; + const relationKeys = new Set(response.map(v => v.objectId)); + + relationKeys.forEach(relationId => { + const rows = response.filter(v => v.objectId === relationId); + const ownerTable = entities.find( + v => v.sqlName === rows[0].TableWithForeignKey + ); + const relatedTable = entities.find( + v => v.sqlName === rows[0].TableReferenced + ); + if (!ownerTable || !relatedTable) { + TomgUtils.LogError( + `Relation between tables ${rows[0].TableWithForeignKey} and ${rows[0].TableReferenced} wasn't found in entity model.`, + true + ); + return; + } + const internal: RelationInternal = { + ownerColumns: [], + relatedColumns: [], + ownerTable, + relatedTable + }; + switch (rows[0].onDelete) { + case "NO_ACTION": + break; + case "SET_NULL": + internal.onDelete = "SET NULL"; + break; + default: + internal.onDelete = rows[0].onDelete; + break; + } + switch (rows[0].onUpdate) { + case "NO_ACTION": + break; + case "SET_NULL": + internal.onUpdate = "SET NULL"; + break; + default: + internal.onUpdate = rows[0].onUpdate; + break; + } + rows.forEach(row => { + internal.ownerColumns.push(row.ForeignKeyColumn); + internal.relatedColumns.push(row.ForeignKeyColumnReferenced); + }); + relationsTemp.push(internal); + }); + + const retVal = MssqlDriver.GetRelationsFromRelationTempInfo( + relationsTemp, + entities, + generationOptions + ); + return retVal; } public async DisconnectFromServer() { @@ -472,10 +487,10 @@ WHERE TABLE_TYPE='BASE TABLE' and TABLE_SCHEMA in (${schema}) AND TABLE_CATALOG private static ReturnDefaultValueFunction( defVal: string | null - ): string | null { + ): string | undefined { let defaultValue = defVal; if (!defaultValue) { - return null; + return undefined; } if (defaultValue.startsWith("(") && defaultValue.endsWith(")")) { defaultValue = defaultValue.slice(1, -1); diff --git a/test/integration/entityTypes/mssql/entity/Post.ts b/test/integration/entityTypes/mssql/entity/Post.ts index dc00e73..3f15287 100644 --- a/test/integration/entityTypes/mssql/entity/Post.ts +++ b/test/integration/entityTypes/mssql/entity/Post.ts @@ -2,7 +2,6 @@ import { Entity, PrimaryColumn, Column } from "typeorm"; @Entity("Post") export class Post { - @PrimaryColumn() id: number; @@ -91,7 +90,7 @@ export class Post { hierarchyid: string; @Column("sql_variant") - sql_variant: string; + sqlVariant: string; @Column("timestamp") timestamp: Date; @@ -107,5 +106,4 @@ export class Post { @Column("geography") geography: string; - } diff --git a/test/integration/github-issues/39/entity/Post.ts b/test/integration/github-issues/39/entity/Post.ts index f5ad32b..52b18d8 100644 --- a/test/integration/github-issues/39/entity/Post.ts +++ b/test/integration/github-issues/39/entity/Post.ts @@ -18,9 +18,9 @@ export class Post { }) id: number; - @ManyToOne(type => User, userId => userId.posts) + @ManyToOne(type => User, user => user.posts) @JoinColumn({ name: "userId" }) - userId: User; + user: User; @Column("text", { nullable: true, diff --git a/test/integration/github-issues/39/entity/User.ts b/test/integration/github-issues/39/entity/User.ts index 6736995..8370780 100644 --- a/test/integration/github-issues/39/entity/User.ts +++ b/test/integration/github-issues/39/entity/User.ts @@ -1,26 +1,29 @@ -import {Index,Entity, PrimaryColumn, Column, OneToOne, OneToMany, ManyToOne, JoinColumn} from "typeorm"; -import {Post} from "./Post"; +import { + Index, + Entity, + PrimaryColumn, + Column, + OneToOne, + OneToMany, + ManyToOne, + JoinColumn +} from "typeorm"; +import { Post } from "./Post"; - -@Entity("User",{schema:"sch2"}) +@Entity("User", { schema: "sch2" }) export class User { + @Column("integer", { + primary: true, + name: "id" + }) + id: number; - @Column("integer",{ - primary:true, - name:"id" - }) - id:number; - - - @Column("text",{ - nullable:true, - name:"name" - }) - name:string; - - - - @OneToMany(type=>Post, posts=>posts.userId) - posts:Post[]; + @Column("text", { + nullable: true, + name: "name" + }) + name: string; + @OneToMany(type => Post, posts => posts.user) + posts: Post[]; }