From 5db68e15489d422b847ee1d9a2620c002cef11a3 Mon Sep 17 00:00:00 2001 From: Kononnable Date: Sat, 5 May 2018 23:57:18 +0200 Subject: [PATCH] composite primary keys support for many to many tables #30 --- src/drivers/AbstractDriver.ts | 35 +-- src/drivers/MssqlDriver.ts | 219 ++++++++++-------- src/drivers/MysqlDriver.ts | 219 ++++++++++-------- src/drivers/OracleDriver.ts | 219 ++++++++++-------- src/drivers/PostgresDriver.ts | 219 ++++++++++-------- .../entity/Post.ts | 18 ++ .../entity/PostAuthor.ts | 21 ++ 7 files changed, 544 insertions(+), 406 deletions(-) create mode 100644 test/integration/examples/sample4_2-many-to-many_composite_keys/entity/Post.ts create mode 100644 test/integration/examples/sample4_2-many-to-many_composite_keys/entity/PostAuthor.ts diff --git a/src/drivers/AbstractDriver.ts b/src/drivers/AbstractDriver.ts index 21bb8b0..95986c8 100644 --- a/src/drivers/AbstractDriver.ts +++ b/src/drivers/AbstractDriver.ts @@ -3,7 +3,6 @@ import { DatabaseModel } from "./../models/DatabaseModel"; import * as TomgUtils from "./../Utils"; import { RelationInfo } from "../models/RelationInfo"; import { ColumnInfo } from "../models/ColumnInfo"; -import { ManyToMany } from "typeorm"; import { WithWidthColumnType, WithPrecisionColumnType, @@ -74,40 +73,48 @@ export abstract class AbstractDriver { relations = entity.Columns.reduce((prev: RelationInfo[], curr) => { return prev.concat(curr.relations); }, relations); - //TODO: Composed keys - if (relations.length == 2) { + let namesOfRelatedTables = relations + .map(v => v.relatedTable) + .filter((v, i, s) => s.indexOf(v) == i); + if (namesOfRelatedTables.length == 2) { let relatedTable1 = dbModel.entities.filter( - v => v.EntityName == relations[0].relatedTable + v => v.EntityName == namesOfRelatedTables[0] )[0]; relatedTable1.Columns = relatedTable1.Columns.filter( - v => v.name.toLowerCase() != entity.EntityName.toLowerCase() + v => + !v.name + .toLowerCase() + .startsWith(entity.EntityName.toLowerCase()) ); let relatedTable2 = dbModel.entities.filter( - v => v.EntityName == relations[1].relatedTable + v => v.EntityName == namesOfRelatedTables[1] )[0]; relatedTable2.Columns = relatedTable2.Columns.filter( - v => v.name.toLowerCase() != entity.EntityName.toLowerCase() + v => + !v.name + .toLowerCase() + .startsWith(entity.EntityName.toLowerCase()) ); dbModel.entities = dbModel.entities.filter(ent => { return ent.EntityName != entity.EntityName; }); let column1 = new ColumnInfo(); - column1.name = relations[1].relatedTable; + column1.name = namesOfRelatedTables[1]; let col1Rel = new RelationInfo(); - col1Rel.relatedTable = relations[1].relatedTable; - col1Rel.relatedColumn = relations[1].relatedTable; + col1Rel.relatedTable = namesOfRelatedTables[1]; + col1Rel.relatedColumn = namesOfRelatedTables[1]; col1Rel.relationType = "ManyToMany"; col1Rel.isOwner = true; - col1Rel.ownerColumn = relations[0].relatedTable; + col1Rel.ownerColumn = namesOfRelatedTables[0]; column1.relations.push(col1Rel); relatedTable1.Columns.push(column1); let column2 = new ColumnInfo(); - column2.name = relations[0].relatedTable; + column2.name = namesOfRelatedTables[0]; let col2Rel = new RelationInfo(); - col2Rel.relatedTable = relations[0].relatedTable; - col2Rel.relatedColumn = relations[1].relatedTable; + col2Rel.relatedTable = namesOfRelatedTables[0]; + col2Rel.relatedColumn = namesOfRelatedTables[1]; col2Rel.relationType = "ManyToMany"; col2Rel.isOwner = false; column2.relations.push(col2Rel); diff --git a/src/drivers/MssqlDriver.ts b/src/drivers/MssqlDriver.ts index 705b59f..4f9605f 100644 --- a/src/drivers/MssqlDriver.ts +++ b/src/drivers/MssqlDriver.ts @@ -378,107 +378,130 @@ order by ); return; } - let ownerColumn = ownerEntity.Columns.find(column => { - return column.name == relationTmp.ownerColumnsNames[0]; - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return column.name == relationTmp.referencedColumnsNames[0]; - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 + for ( + let relationColumnIndex = 0; + relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex++ ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; + let ownerColumn = ownerEntity.Columns.find(column => { + return ( + column.name == + relationTmp.ownerColumnsNames[relationColumnIndex] + ); + }); + if (!ownerColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.ownerTable + }.${ownerColumn}.` + ); + return; } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; + let relatedColumn = referencedEntity.Columns.find(column => { + return ( + column.name == + relationTmp.referencedColumnsNames[relationColumnIndex] + ); + }); + if (!relatedColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.referencedTable + }.${relatedColumn}.` + ); + return; + } + let ownColumn: ColumnInfo = ownerColumn; + let isOneToMany: boolean; + isOneToMany = false; + let index = ownerEntity.Indexes.find(index => { + return ( + index.isUnique && + index.columns.some(col => { + return col.name == ownerColumn!.name; + }) + ); + }); + if (!index) { + isOneToMany = true; + } else { + isOneToMany = false; + } + let ownerRelation = new RelationInfo(); + let columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : ""); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length > 0 + ) { + for (let i = 2; i <= ownerEntity.Columns.length; i++) { + columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : "") + + i.toString(); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length == 0 + ) + break; + } + } + ownerRelation.actionOnDelete = relationTmp.actionOnDelete; + ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; + ownerRelation.isOwner = true; + ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); + ownerRelation.relatedTable = relationTmp.referencedTable; + ownerRelation.ownerTable = relationTmp.ownerTable; + ownerRelation.ownerColumn = columnName; + ownerRelation.relationType = isOneToMany + ? "ManyToOne" + : "OneToOne"; + ownerColumn.relations.push(ownerRelation); + if (isOneToMany) { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToMany"; + referencedEntity.Columns.push(col); + } else { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToOne"; - referencedEntity.Columns.push(col); + referencedEntity.Columns.push(col); + } } }); return entities; diff --git a/src/drivers/MysqlDriver.ts b/src/drivers/MysqlDriver.ts index 2cb8b55..6c7ab16 100644 --- a/src/drivers/MysqlDriver.ts +++ b/src/drivers/MysqlDriver.ts @@ -341,107 +341,130 @@ export class MysqlDriver extends AbstractDriver { ); return; } - let ownerColumn = ownerEntity.Columns.find(column => { - return column.name == relationTmp.ownerColumnsNames[0]; - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return column.name == relationTmp.referencedColumnsNames[0]; - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 + for ( + let relationColumnIndex = 0; + relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex++ ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; + let ownerColumn = ownerEntity.Columns.find(column => { + return ( + column.name == + relationTmp.ownerColumnsNames[relationColumnIndex] + ); + }); + if (!ownerColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.ownerTable + }.${ownerColumn}.` + ); + return; } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; + let relatedColumn = referencedEntity.Columns.find(column => { + return ( + column.name == + relationTmp.referencedColumnsNames[relationColumnIndex] + ); + }); + if (!relatedColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.referencedTable + }.${relatedColumn}.` + ); + return; + } + let ownColumn: ColumnInfo = ownerColumn; + let isOneToMany: boolean; + isOneToMany = false; + let index = ownerEntity.Indexes.find(index => { + return ( + index.isUnique && + index.columns.some(col => { + return col.name == ownerColumn!.name; + }) + ); + }); + if (!index) { + isOneToMany = true; + } else { + isOneToMany = false; + } + let ownerRelation = new RelationInfo(); + let columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : ""); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length > 0 + ) { + for (let i = 2; i <= ownerEntity.Columns.length; i++) { + columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : "") + + i.toString(); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length == 0 + ) + break; + } + } + ownerRelation.actionOnDelete = relationTmp.actionOnDelete; + ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; + ownerRelation.isOwner = true; + ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); + ownerRelation.relatedTable = relationTmp.referencedTable; + ownerRelation.ownerTable = relationTmp.ownerTable; + ownerRelation.ownerColumn = columnName; + ownerRelation.relationType = isOneToMany + ? "ManyToOne" + : "OneToOne"; + ownerColumn.relations.push(ownerRelation); + if (isOneToMany) { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToMany"; + referencedEntity.Columns.push(col); + } else { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToOne"; - referencedEntity.Columns.push(col); + referencedEntity.Columns.push(col); + } } }); return entities; diff --git a/src/drivers/OracleDriver.ts b/src/drivers/OracleDriver.ts index 06ed177..903dd53 100644 --- a/src/drivers/OracleDriver.ts +++ b/src/drivers/OracleDriver.ts @@ -307,107 +307,130 @@ export class OracleDriver extends AbstractDriver { ); return; } - let ownerColumn = ownerEntity.Columns.find(column => { - return column.name == relationTmp.ownerColumnsNames[0]; - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return column.name == relationTmp.referencedColumnsNames[0]; - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 + for ( + let relationColumnIndex = 0; + relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex++ ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; + let ownerColumn = ownerEntity.Columns.find(column => { + return ( + column.name == + relationTmp.ownerColumnsNames[relationColumnIndex] + ); + }); + if (!ownerColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.ownerTable + }.${ownerColumn}.` + ); + return; } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionOnDelete = relationTmp.actionOnDelete; - referencedRelation.actionOnUpdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; + let relatedColumn = referencedEntity.Columns.find(column => { + return ( + column.name == + relationTmp.referencedColumnsNames[relationColumnIndex] + ); + }); + if (!relatedColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.referencedTable + }.${relatedColumn}.` + ); + return; + } + let ownColumn: ColumnInfo = ownerColumn; + let isOneToMany: boolean; + isOneToMany = false; + let index = ownerEntity.Indexes.find(index => { + return ( + index.isUnique && + index.columns.some(col => { + return col.name == ownerColumn!.name; + }) + ); + }); + if (!index) { + isOneToMany = true; + } else { + isOneToMany = false; + } + let ownerRelation = new RelationInfo(); + let columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : ""); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length > 0 + ) { + for (let i = 2; i <= ownerEntity.Columns.length; i++) { + columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : "") + + i.toString(); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length == 0 + ) + break; + } + } + ownerRelation.actionOnDelete = relationTmp.actionOnDelete; + ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; + ownerRelation.isOwner = true; + ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); + ownerRelation.relatedTable = relationTmp.referencedTable; + ownerRelation.ownerTable = relationTmp.ownerTable; + ownerRelation.ownerColumn = columnName; + ownerRelation.relationType = isOneToMany + ? "ManyToOne" + : "OneToOne"; + ownerColumn.relations.push(ownerRelation); + if (isOneToMany) { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToMany"; + referencedEntity.Columns.push(col); + } else { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionOnDelete = + relationTmp.actionOnDelete; + referencedRelation.actionOnUpdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToOne"; - referencedEntity.Columns.push(col); + referencedEntity.Columns.push(col); + } } }); return entities; diff --git a/src/drivers/PostgresDriver.ts b/src/drivers/PostgresDriver.ts index cc34598..2ff41d7 100644 --- a/src/drivers/PostgresDriver.ts +++ b/src/drivers/PostgresDriver.ts @@ -470,107 +470,130 @@ export class PostgresDriver extends AbstractDriver { ); return; } - let ownerColumn = ownerEntity.Columns.find(column => { - return column.name == relationTmp.ownerColumnsNames[0]; - }); - if (!ownerColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.ownerTable - }.${ownerColumn}.` - ); - return; - } - let relatedColumn = referencedEntity.Columns.find(column => { - return column.name == relationTmp.referencedColumnsNames[0]; - }); - if (!relatedColumn) { - TomgUtils.LogError( - `Relation between tables ${relationTmp.ownerTable} and ${ - relationTmp.referencedTable - } didn't found entity column ${ - relationTmp.referencedTable - }.${relatedColumn}.` - ); - return; - } - let ownColumn: ColumnInfo = ownerColumn; - let isOneToMany: boolean; - isOneToMany = false; - let index = ownerEntity.Indexes.find(index => { - return ( - index.isUnique && - index.columns.some(col => { - return col.name == ownerColumn!.name; - }) - ); - }); - if (!index) { - isOneToMany = true; - } else { - isOneToMany = false; - } - let ownerRelation = new RelationInfo(); - let columnName = - ownerEntity.EntityName.toLowerCase() + (isOneToMany ? "s" : ""); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length > 0 + for ( + let relationColumnIndex = 0; + relationColumnIndex < relationTmp.ownerColumnsNames.length; + relationColumnIndex++ ) { - for (let i = 2; i <= ownerEntity.Columns.length; i++) { - columnName = - ownerEntity.EntityName.toLowerCase() + - (isOneToMany ? "s" : "") + - i.toString(); - if ( - referencedEntity.Columns.filter(filterVal => { - return filterVal.name == columnName; - }).length == 0 - ) - break; + let ownerColumn = ownerEntity.Columns.find(column => { + return ( + column.name == + relationTmp.ownerColumnsNames[relationColumnIndex] + ); + }); + if (!ownerColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.ownerTable + }.${ownerColumn}.` + ); + return; } - } - ownerRelation.actionOnDelete = relationTmp.actionOnDelete; - ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; - ownerRelation.isOwner = true; - ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); - ownerRelation.relatedTable = relationTmp.referencedTable; - ownerRelation.ownerTable = relationTmp.ownerTable; - ownerRelation.ownerColumn = columnName; - ownerRelation.relationType = isOneToMany ? "ManyToOne" : "OneToOne"; - ownerColumn.relations.push(ownerRelation); - if (isOneToMany) { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionondelete = relationTmp.actionOnDelete; - referencedRelation.actiononupdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToMany"; - referencedEntity.Columns.push(col); - } else { - let col = new ColumnInfo(); - col.name = columnName; - let referencedRelation = new RelationInfo(); - col.relations.push(referencedRelation); - referencedRelation.actionondelete = relationTmp.actionOnDelete; - referencedRelation.actiononupdate = relationTmp.actionOnUpdate; - referencedRelation.isOwner = false; - referencedRelation.relatedColumn = ownerColumn.name; - referencedRelation.relatedTable = relationTmp.ownerTable; - referencedRelation.ownerTable = relationTmp.referencedTable; - referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); - referencedRelation.relationType = "OneToOne"; + let relatedColumn = referencedEntity.Columns.find(column => { + return ( + column.name == + relationTmp.referencedColumnsNames[relationColumnIndex] + ); + }); + if (!relatedColumn) { + TomgUtils.LogError( + `Relation between tables ${ + relationTmp.ownerTable + } and ${ + relationTmp.referencedTable + } didn't found entity column ${ + relationTmp.referencedTable + }.${relatedColumn}.` + ); + return; + } + let ownColumn: ColumnInfo = ownerColumn; + let isOneToMany: boolean; + isOneToMany = false; + let index = ownerEntity.Indexes.find(index => { + return ( + index.isUnique && + index.columns.some(col => { + return col.name == ownerColumn!.name; + }) + ); + }); + if (!index) { + isOneToMany = true; + } else { + isOneToMany = false; + } + let ownerRelation = new RelationInfo(); + let columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : ""); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length > 0 + ) { + for (let i = 2; i <= ownerEntity.Columns.length; i++) { + columnName = + ownerEntity.EntityName.toLowerCase() + + (isOneToMany ? "s" : "") + + i.toString(); + if ( + referencedEntity.Columns.filter(filterVal => { + return filterVal.name == columnName; + }).length == 0 + ) + break; + } + } + ownerRelation.actionOnDelete = relationTmp.actionOnDelete; + ownerRelation.actionOnUpdate = relationTmp.actionOnUpdate; + ownerRelation.isOwner = true; + ownerRelation.relatedColumn = relatedColumn.name.toLowerCase(); + ownerRelation.relatedTable = relationTmp.referencedTable; + ownerRelation.ownerTable = relationTmp.ownerTable; + ownerRelation.ownerColumn = columnName; + ownerRelation.relationType = isOneToMany + ? "ManyToOne" + : "OneToOne"; + ownerColumn.relations.push(ownerRelation); + if (isOneToMany) { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionondelete = + relationTmp.actionOnDelete; + referencedRelation.actiononupdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToMany"; + referencedEntity.Columns.push(col); + } else { + let col = new ColumnInfo(); + col.name = columnName; + let referencedRelation = new RelationInfo(); + col.relations.push(referencedRelation); + referencedRelation.actionondelete = + relationTmp.actionOnDelete; + referencedRelation.actiononupdate = + relationTmp.actionOnUpdate; + referencedRelation.isOwner = false; + referencedRelation.relatedColumn = ownerColumn.name; + referencedRelation.relatedTable = relationTmp.ownerTable; + referencedRelation.ownerTable = relationTmp.referencedTable; + referencedRelation.ownerColumn = relatedColumn.name.toLowerCase(); + referencedRelation.relationType = "OneToOne"; - referencedEntity.Columns.push(col); + referencedEntity.Columns.push(col); + } } }); return entities; diff --git a/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/Post.ts b/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/Post.ts new file mode 100644 index 0000000..8f7e369 --- /dev/null +++ b/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/Post.ts @@ -0,0 +1,18 @@ +import { PrimaryColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; +import {PostAuthor} from "./PostAuthor"; + +@Entity("Post") +export class Post { + + @PrimaryColumn("int") + id: number; + + @PrimaryColumn() + type: string; + + // post has relation with details. not cascades here. means cannot be persisted, updated or removed + @ManyToMany(type => PostAuthor, author => author.Post) + @JoinTable() + PostAuthor: PostAuthor[]; + +} diff --git a/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/PostAuthor.ts b/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/PostAuthor.ts new file mode 100644 index 0000000..b807231 --- /dev/null +++ b/test/integration/examples/sample4_2-many-to-many_composite_keys/entity/PostAuthor.ts @@ -0,0 +1,21 @@ +import { PrimaryColumn, Column, Entity, OneToOne, OneToMany, ManyToOne, ManyToMany, JoinColumn, JoinTable } from "typeorm"; +import {Post} from "./Post"; + +@Entity("PostAuthor") +export class PostAuthor { + + + @PrimaryColumn("int") + id: number; + + @PrimaryColumn() + type: string; + + + @Column() + name: string; + + @ManyToMany(type => Post, post => post.PostAuthor) + Post: Post[]; + +}