Skip to content

Commit 91430e6

Browse files
committed
Replace FK overwrite deprecation with exception
Removed the deprecation warning triggered when overwriting an existing foreign key constraint, and replaced it with a ForeignKeyAlreadyExists exception to enforce correct behavior.
1 parent c01a43f commit 91430e6

File tree

5 files changed

+54
-29
lines changed

5 files changed

+54
-29
lines changed

UPGRADE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ awareness about deprecated code.
88

99
# Upgrade to 5.0
1010

11+
## BC BREAK: changes in `Table` class
12+
13+
The `Table` class no longer accepts `foreignKeyConstraints`
14+
with duplicate names.
15+
1116
## BC BREAK: changes in `TableDiff` constructor
1217

1318
The `TableDiff` class constructor no longer accepts `droppedForeignKeys`

src/Platforms/SQLitePlatform.php

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use Doctrine\DBAL\Types;
2828

2929
use function array_merge;
30+
use function assert;
3031
use function count;
3132
use function explode;
3233
use function implode;
@@ -861,23 +862,8 @@ private function getForeignKeysInAlteredTable(TableDiff $diff): array
861862
{
862863
$oldTable = $diff->getOldTable();
863864
$foreignKeys = $oldTable->getForeignKeys();
865+
$nameMap = $this->getDiffColumnNameMap($diff);
864866
$keysByName = [];
865-
foreach ($foreignKeys as $key => $foreignKey) {
866-
$constraintName = $foreignKey->getObjectName();
867-
868-
if ($constraintName === null) {
869-
continue;
870-
}
871-
872-
$constraintKey = strtolower(
873-
$constraintName->getIdentifier()
874-
->getValue(),
875-
);
876-
877-
$keysByName[$constraintKey] = $key;
878-
}
879-
880-
$nameMap = $this->getDiffColumnNameMap($diff);
881867

882868
foreach ($foreignKeys as $key => $constraint) {
883869
$changed = false;
@@ -900,6 +886,17 @@ private function getForeignKeysInAlteredTable(TableDiff $diff): array
900886
$changed = true;
901887
}
902888

889+
$constraintName = $constraint->getObjectName();
890+
891+
if ($constraintName !== null) {
892+
$constraintKey = strtolower(
893+
$constraintName->getIdentifier()
894+
->getValue(),
895+
);
896+
897+
$keysByName[$constraintKey] = $key;
898+
}
899+
903900
if (! $changed) {
904901
continue;
905902
}
@@ -921,7 +918,8 @@ private function getForeignKeysInAlteredTable(TableDiff $diff): array
921918
->getValue(),
922919
);
923920

924-
unset($foreignKeys[$keysByName[$constraintKey]]);
921+
assert(isset($keysByName[$constraintKey]));
922+
unset($foreignKeys[$keysByName[$constraintKey]], $keysByName[$constraintKey]);
925923
}
926924

927925
foreach ($diff->getAddedForeignKeys() as $constraint) {
@@ -933,11 +931,10 @@ private function getForeignKeysInAlteredTable(TableDiff $diff): array
933931
->getValue(),
934932
);
935933

936-
if (isset($keysByName[$constraintKey])) {
937-
$foreignKeys[$keysByName[$constraintKey]] = $constraint;
938-
} else {
939-
$foreignKeys[] = $constraint;
940-
}
934+
assert(! isset($keysByName[$constraintKey]));
935+
$foreignKeys[] = $constraint;
936+
937+
$keysByName[$constraintKey] = count($foreignKeys) - 1;
941938
} else {
942939
$foreignKeys[] = $constraint;
943940
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\DBAL\Schema\Exception;
6+
7+
use Doctrine\DBAL\Schema\Name\OptionallyQualifiedName;
8+
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
9+
use Doctrine\DBAL\Schema\SchemaException;
10+
use LogicException;
11+
12+
use function sprintf;
13+
14+
final class ForeignKeyAlreadyExists extends LogicException implements SchemaException
15+
{
16+
public static function new(OptionallyQualifiedName $tableName, UnqualifiedName $foreignKeyName): self
17+
{
18+
return new self(
19+
sprintf(
20+
'A foreign key constraint named %s already exists on table %s.',
21+
$foreignKeyName->toString(),
22+
$tableName->toString(),
23+
),
24+
);
25+
}
26+
}

src/Schema/Table.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Doctrine\DBAL\Schema\Exception\ColumnAlreadyExists;
88
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
9+
use Doctrine\DBAL\Schema\Exception\ForeignKeyAlreadyExists;
910
use Doctrine\DBAL\Schema\Exception\ForeignKeyDoesNotExist;
1011
use Doctrine\DBAL\Schema\Exception\IndexAlreadyExists;
1112
use Doctrine\DBAL\Schema\Exception\IndexDoesNotExist;
@@ -839,12 +840,7 @@ private function _addForeignKeyConstraint(ForeignKeyConstraint $constraint): sel
839840
}
840841

841842
if (isset($this->foreignKeyConstraints[$key])) {
842-
Deprecation::trigger(
843-
'doctrine/dbal',
844-
'https://github.com/doctrine/dbal/pull/7125',
845-
'Overwriting an existing foreign key constraint ("%s") is deprecated.',
846-
$key,
847-
);
843+
throw ForeignKeyAlreadyExists::new($this->name, UnqualifiedName::unquoted($key));
848844
}
849845

850846
$this->foreignKeyConstraints[$key] = $constraint;

tests/Schema/TableTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Doctrine\DBAL\Platforms\MySQLPlatform;
99
use Doctrine\DBAL\Platforms\SQLitePlatform;
1010
use Doctrine\DBAL\Schema\Column;
11+
use Doctrine\DBAL\Schema\Exception\ForeignKeyAlreadyExists;
1112
use Doctrine\DBAL\Schema\Exception\IndexDoesNotExist;
1213
use Doctrine\DBAL\Schema\Exception\InvalidForeignKeyConstraintDefinition;
1314
use Doctrine\DBAL\Schema\Exception\InvalidIndexDefinition;
@@ -1797,7 +1798,7 @@ public function testOverwritingForeignKeyConstraint(): void
17971798

17981799
$table->addForeignKeyConstraint('bar', ['id'], ['id']);
17991800

1800-
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7125');
1801+
$this->expectException(ForeignKeyAlreadyExists::class);
18011802
$table->addForeignKeyConstraint('baz', ['id'], ['id']);
18021803
}
18031804
}

0 commit comments

Comments
 (0)