Skip to content

Commit 0094f61

Browse files
tkvwpleerock
authored andcommitted
feat: add referenced table metadata to NamingStrategy to resolve foreign key name (#4274)
Feature allows to use foreignkey metadata to generate database foreignkey names. Closes #3847 and #1355
1 parent 3abe5b9 commit 0094f61

File tree

15 files changed

+101
-29
lines changed

15 files changed

+101
-29
lines changed

src/driver/cockroachdb/CockroachQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner
505505
// rename foreign key constraints
506506
newTable.foreignKeys.forEach(foreignKey => {
507507
// build new constraint name
508-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
508+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
509509

510510
// build queries
511511
upQueries.push(new Query(`ALTER TABLE ${this.escapePath(newTable)} RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -702,7 +702,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner
702702
// build new constraint name
703703
foreignKey.columnNames.splice(foreignKey.columnNames.indexOf(oldColumn.name), 1);
704704
foreignKey.columnNames.push(newColumn.name);
705-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames);
705+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
706706

707707
// build queries
708708
upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -1123,7 +1123,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner
11231123

11241124
// new FK may be passed without name. In this case we generate FK name manually.
11251125
if (!foreignKey.name)
1126-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames);
1126+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
11271127

11281128
const up = this.createForeignKeySql(table, foreignKey);
11291129
const down = this.dropForeignKeySql(table, foreignKey);
@@ -1618,7 +1618,7 @@ export class CockroachQueryRunner extends BaseQueryRunner implements QueryRunner
16181618
const foreignKeysSql = table.foreignKeys.map(fk => {
16191619
const columnNames = fk.columnNames.map(columnName => `"${columnName}"`).join(", ");
16201620
if (!fk.name)
1621-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
1621+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
16221622
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `"${columnName}"`).join(", ");
16231623

16241624
let constraint = `CONSTRAINT "${fk.name}" FOREIGN KEY (${columnNames}) REFERENCES ${this.escapePath(fk.referencedTableName)} (${referencedColumnNames})`;

src/driver/mysql/MysqlQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
408408
// build new constraint name
409409
const columnNames = foreignKey.columnNames.map(column => `\`${column}\``).join(", ");
410410
const referencedColumnNames = foreignKey.referencedColumnNames.map(column => `\`${column}\``).join(",");
411-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
411+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
412412

413413
// build queries
414414
let up = `ALTER TABLE ${this.escapePath(newTable)} DROP FOREIGN KEY \`${foreignKey.name}\`, ADD CONSTRAINT \`${newForeignKeyName}\` FOREIGN KEY (${columnNames}) ` +
@@ -599,7 +599,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
599599
foreignKey.columnNames.push(newColumn.name);
600600
const columnNames = foreignKey.columnNames.map(column => `\`${column}\``).join(", ");
601601
const referencedColumnNames = foreignKey.referencedColumnNames.map(column => `\`${column}\``).join(",");
602-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames);
602+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
603603

604604
// build queries
605605
let up = `ALTER TABLE ${this.escapePath(table)} DROP FOREIGN KEY \`${foreignKey.name}\`, ADD CONSTRAINT \`${newForeignKeyName}\` FOREIGN KEY (${columnNames}) ` +
@@ -1004,7 +1004,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
10041004

10051005
// new FK may be passed without name. In this case we generate FK name manually.
10061006
if (!foreignKey.name)
1007-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames);
1007+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
10081008

10091009
const up = this.createForeignKeySql(table, foreignKey);
10101010
const down = this.dropForeignKeySql(table, foreignKey);
@@ -1462,7 +1462,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
14621462
const foreignKeysSql = table.foreignKeys.map(fk => {
14631463
const columnNames = fk.columnNames.map(columnName => `\`${columnName}\``).join(", ");
14641464
if (!fk.name)
1465-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
1465+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
14661466
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `\`${columnName}\``).join(", ");
14671467

14681468
let constraint = `CONSTRAINT \`${fk.name}\` FOREIGN KEY (${columnNames}) REFERENCES ${this.escapePath(fk.referencedTableName)} (${referencedColumnNames})`;

src/driver/oracle/OracleQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
430430
// rename foreign key constraints
431431
newTable.foreignKeys.forEach(foreignKey => {
432432
// build new constraint name
433-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
433+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
434434

435435
// build queries
436436
upQueries.push(new Query(`ALTER TABLE "${newTable.name}" RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -613,7 +613,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
613613
// build new constraint name
614614
foreignKey.columnNames.splice(foreignKey.columnNames.indexOf(oldColumn.name), 1);
615615
foreignKey.columnNames.push(newColumn.name);
616-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames);
616+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
617617

618618
// build queries
619619
upQueries.push(new Query(`ALTER TABLE "${table.name}" RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -1004,7 +1004,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
10041004

10051005
// new FK may be passed without name. In this case we generate FK name manually.
10061006
if (!foreignKey.name)
1007-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames);
1007+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
10081008

10091009
const up = this.createForeignKeySql(table, foreignKey);
10101010
const down = this.dropForeignKeySql(table, foreignKey);
@@ -1351,7 +1351,7 @@ export class OracleQueryRunner extends BaseQueryRunner implements QueryRunner {
13511351
const foreignKeysSql = table.foreignKeys.map(fk => {
13521352
const columnNames = fk.columnNames.map(columnName => `"${columnName}"`).join(", ");
13531353
if (!fk.name)
1354-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
1354+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
13551355
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `"${columnName}"`).join(", ");
13561356
let constraint = `CONSTRAINT "${fk.name}" FOREIGN KEY (${columnNames}) REFERENCES "${fk.referencedTableName}" (${referencedColumnNames})`;
13571357
if (fk.onDelete && fk.onDelete !== "NO ACTION") // Oracle does not support NO ACTION, but we set NO ACTION by default in EntityMetadata

src/driver/postgres/PostgresQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
470470
// rename foreign key constraints
471471
newTable.foreignKeys.forEach(foreignKey => {
472472
// build new constraint name
473-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
473+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
474474

475475
// build queries
476476
upQueries.push(new Query(`ALTER TABLE ${this.escapePath(newTable)} RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -687,7 +687,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
687687
// build new constraint name
688688
foreignKey.columnNames.splice(foreignKey.columnNames.indexOf(oldColumn.name), 1);
689689
foreignKey.columnNames.push(newColumn.name);
690-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames);
690+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
691691

692692
// build queries
693693
upQueries.push(new Query(`ALTER TABLE ${this.escapePath(table)} RENAME CONSTRAINT "${foreignKey.name}" TO "${newForeignKeyName}"`));
@@ -1174,7 +1174,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
11741174

11751175
// new FK may be passed without name. In this case we generate FK name manually.
11761176
if (!foreignKey.name)
1177-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames);
1177+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
11781178

11791179
const up = this.createForeignKeySql(table, foreignKey);
11801180
const down = this.dropForeignKeySql(table, foreignKey);
@@ -1702,7 +1702,7 @@ export class PostgresQueryRunner extends BaseQueryRunner implements QueryRunner
17021702
const foreignKeysSql = table.foreignKeys.map(fk => {
17031703
const columnNames = fk.columnNames.map(columnName => `"${columnName}"`).join(", ");
17041704
if (!fk.name)
1705-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
1705+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
17061706
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `"${columnName}"`).join(", ");
17071707

17081708
let constraint = `CONSTRAINT "${fk.name}" FOREIGN KEY (${columnNames}) REFERENCES ${this.escapePath(fk.referencedTableName)} (${referencedColumnNames})`;

src/driver/sqlite-abstract/AbstractSqliteQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
304304

305305
// rename foreign key constraints
306306
newTable.foreignKeys.forEach(foreignKey => {
307-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
307+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
308308
});
309309

310310
// rename indices
@@ -384,7 +384,7 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
384384
changedTable.findColumnForeignKeys(changedColumnSet.oldColumn).forEach(fk => {
385385
fk.columnNames.splice(fk.columnNames.indexOf(changedColumnSet.oldColumn.name), 1);
386386
fk.columnNames.push(changedColumnSet.newColumn.name);
387-
fk.name = this.connection.namingStrategy.foreignKeyName(changedTable, fk.columnNames);
387+
fk.name = this.connection.namingStrategy.foreignKeyName(changedTable, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
388388
});
389389

390390
changedTable.findColumnIndices(changedColumnSet.oldColumn).forEach(index => {
@@ -848,7 +848,7 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
848848
const columnNames = ownForeignKeys.map(dbForeignKey => dbForeignKey["from"]);
849849
const referencedColumnNames = ownForeignKeys.map(dbForeignKey => dbForeignKey["to"]);
850850
// build foreign key name, because we can not get it directly.
851-
const fkName = this.connection.namingStrategy.foreignKeyName(table, columnNames);
851+
const fkName = this.connection.namingStrategy.foreignKeyName(table, columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
852852

853853
return new TableForeignKey({
854854
name: fkName,
@@ -975,7 +975,7 @@ export abstract class AbstractSqliteQueryRunner extends BaseQueryRunner implemen
975975
const foreignKeysSql = table.foreignKeys.map(fk => {
976976
const columnNames = fk.columnNames.map(columnName => `"${columnName}"`).join(", ");
977977
if (!fk.name)
978-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
978+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
979979
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `"${columnName}"`).join(", ");
980980

981981
let constraint = `CONSTRAINT "${fk.name}" FOREIGN KEY (${columnNames}) REFERENCES "${fk.referencedTableName}" (${referencedColumnNames})`;

src/driver/sqlserver/SqlServerQueryRunner.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
622622
// rename foreign key constraints
623623
newTable.foreignKeys.forEach(foreignKey => {
624624
// build new constraint name
625-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames);
625+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(newTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
626626

627627
// build queries
628628
upQueries.push(new Query(`EXEC sp_rename "${this.buildForeignKeyName(foreignKey.name!, schemaName, dbName)}", "${newForeignKeyName}"`));
@@ -823,7 +823,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
823823
// build new constraint name
824824
foreignKey.columnNames.splice(foreignKey.columnNames.indexOf(oldColumn.name), 1);
825825
foreignKey.columnNames.push(newColumn.name);
826-
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames);
826+
const newForeignKeyName = this.connection.namingStrategy.foreignKeyName(clonedTable, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
827827

828828
// build queries
829829
upQueries.push(new Query(`EXEC sp_rename "${this.buildForeignKeyName(foreignKey.name!, schemaName, dbName)}", "${newForeignKeyName}"`));
@@ -1240,7 +1240,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
12401240

12411241
// new FK may be passed without name. In this case we generate FK name manually.
12421242
if (!foreignKey.name)
1243-
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames);
1243+
foreignKey.name = this.connection.namingStrategy.foreignKeyName(table.name, foreignKey.columnNames, foreignKey.referencedTableName, foreignKey.referencedColumnNames);
12441244

12451245
const up = this.createForeignKeySql(table, foreignKey);
12461246
const down = this.dropForeignKeySql(table, foreignKey);
@@ -1816,7 +1816,7 @@ export class SqlServerQueryRunner extends BaseQueryRunner implements QueryRunner
18161816
const foreignKeysSql = table.foreignKeys.map(fk => {
18171817
const columnNames = fk.columnNames.map(columnName => `"${columnName}"`).join(", ");
18181818
if (!fk.name)
1819-
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames);
1819+
fk.name = this.connection.namingStrategy.foreignKeyName(table.name, fk.columnNames, fk.referencedTableName, fk.referencedColumnNames);
18201820
const referencedColumnNames = fk.referencedColumnNames.map(columnName => `"${columnName}"`).join(", ");
18211821

18221822
let constraint = `CONSTRAINT "${fk.name}" FOREIGN KEY (${columnNames}) REFERENCES ${this.escapePath(fk.referencedTableName)} (${referencedColumnNames})`;

src/metadata/ForeignKeyMetadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export class ForeignKeyMetadata {
106106
this.columnNames = this.columns.map(column => column.databaseName);
107107
this.referencedColumnNames = this.referencedColumns.map(column => column.databaseName);
108108
this.referencedTablePath = this.referencedEntityMetadata.tablePath;
109-
this.name = namingStrategy.foreignKeyName(this.entityMetadata.tablePath, this.columnNames);
109+
this.name = namingStrategy.foreignKeyName(this.entityMetadata.tablePath, this.columnNames, this.referencedTablePath, this.referencedColumnNames);
110110
}
111111

112112
}

src/naming-strategy/DefaultNamingStrategy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export class DefaultNamingStrategy implements NamingStrategyInterface {
7878
return "DF_" + RandomGenerator.sha1(key).substr(0, 27);
7979
}
8080

81-
foreignKeyName(tableOrName: Table|string, columnNames: string[]): string {
81+
foreignKeyName(tableOrName: Table|string, columnNames: string[], _referencedTablePath?: string, _referencedColumnNames?: string[]): string {
8282
// sort incoming column names to avoid issue when ["id", "name"] and ["name", "id"] arrays
8383
const clonedColumnNames = [...columnNames];
8484
clonedColumnNames.sort();

src/naming-strategy/NamingStrategyInterface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export interface NamingStrategyInterface {
6060
/**
6161
* Gets the name of the foreign key.
6262
*/
63-
foreignKeyName(tableOrName: Table|string, columnNames: string[]): string;
63+
foreignKeyName(tableOrName: Table|string, columnNames: string[], referencedTablePath?: string, referencedColumnNames?: string[]): string;
6464

6565
/**
6666
* Gets the name of the index - simple and compose index.

0 commit comments

Comments
 (0)