Skip to content

Commit b17da07

Browse files
committed
Fixed schema comparison attempting to remove double foreign keys.
1 parent 2319596 commit b17da07

File tree

2 files changed

+192
-6
lines changed

2 files changed

+192
-6
lines changed

src/Schema/Comparator.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,17 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff
275275
foreach ($newForeignKeys as $newKey => $newForeignKey) {
276276
if ($this->diffForeignKey($oldForeignKey, $newForeignKey) === false) {
277277
unset($oldForeignKeys[$oldKey], $newForeignKeys[$newKey]);
278-
} else {
279-
if (strtolower($oldForeignKey->getName()) === strtolower($newForeignKey->getName())) {
280-
$droppedForeignKeys[$oldKey] = $oldForeignKey;
281-
$addedForeignKeys[$newKey] = $newForeignKey;
278+
continue 2;
279+
}
282280

283-
unset($oldForeignKeys[$oldKey], $newForeignKeys[$newKey]);
284-
}
281+
if (strtolower($oldForeignKey->getName()) !== strtolower($newForeignKey->getName())) {
282+
continue;
285283
}
284+
285+
$droppedForeignKeys[$oldKey] = $oldForeignKey;
286+
$addedForeignKeys[$newKey] = $newForeignKey;
287+
288+
unset($oldForeignKeys[$oldKey], $newForeignKeys[$newKey]);
286289
}
287290
}
288291

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\DBAL\Tests\Functional\Schema;
6+
7+
use Doctrine\DBAL\Platforms\DB2Platform;
8+
use Doctrine\DBAL\Platforms\OraclePlatform;
9+
use Doctrine\DBAL\Schema\AbstractSchemaManager;
10+
use Doctrine\DBAL\Schema\Column;
11+
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
12+
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
13+
use Doctrine\DBAL\Schema\Table;
14+
use Doctrine\DBAL\Tests\FunctionalTestCase;
15+
use Doctrine\DBAL\Types\Types;
16+
17+
class DoubleForeignKeyConstraintTest extends FunctionalTestCase
18+
{
19+
private AbstractSchemaManager $schemaManager;
20+
21+
protected function setUp(): void
22+
{
23+
$this->schemaManager = $this->connection->createSchemaManager();
24+
}
25+
26+
public function testDoubleForeignKeyConstraint(): void
27+
{
28+
$platform = $this->connection->getDatabasePlatform();
29+
if ($platform instanceof DB2Platform || $platform instanceof OraclePlatform) {
30+
self::markTestSkipped('DB2 and Oracle do not allow multiple FKs with the same columns.');
31+
}
32+
33+
$articles = Table::editor()
34+
->setUnquotedName('articles')
35+
->setColumns(
36+
Column::editor()
37+
->setUnquotedName('id')
38+
->setTypeName(Types::INTEGER)
39+
->create(),
40+
)
41+
->setPrimaryKeyConstraint(
42+
PrimaryKeyConstraint::editor()
43+
->setUnquotedColumnNames('id')
44+
->create(),
45+
)
46+
->create();
47+
48+
$orders = Table::editor()
49+
->setUnquotedName('orders')
50+
->setColumns(
51+
Column::editor()
52+
->setUnquotedName('id')
53+
->setTypeName(Types::INTEGER)
54+
->create(),
55+
Column::editor()
56+
->setUnquotedName('article_id')
57+
->setTypeName(Types::INTEGER)
58+
->create(),
59+
)
60+
->setForeignKeyConstraints(
61+
ForeignKeyConstraint::editor()
62+
->setUnquotedName('articles_fk')
63+
->setUnquotedReferencingColumnNames('article_id')
64+
->setUnquotedReferencedTableName('articles')
65+
->setUnquotedReferencedColumnNames('id')
66+
->create(),
67+
ForeignKeyConstraint::editor()
68+
->setUnquotedName('articles_fk_2')
69+
->setUnquotedReferencingColumnNames('article_id')
70+
->setUnquotedReferencedTableName('articles')
71+
->setUnquotedReferencedColumnNames('id')
72+
->create(),
73+
)
74+
->create();
75+
76+
$this->dropTableIfExists('orders');
77+
$this->dropTableIfExists('articles');
78+
79+
$this->connection->createSchemaManager()
80+
->createTable($articles);
81+
$this->connection->createSchemaManager()
82+
->createTable($orders);
83+
84+
$ordersActual = $this->schemaManager->introspectTable('orders');
85+
86+
self::assertTrue(
87+
$this->schemaManager->createComparator()
88+
->compareTables($ordersActual, $orders)
89+
->isEmpty(),
90+
);
91+
}
92+
93+
public function testDoubleForeignKeyConstraintComparedToSingle(): void
94+
{
95+
$platform = $this->connection->getDatabasePlatform();
96+
if ($platform instanceof DB2Platform || $platform instanceof OraclePlatform) {
97+
self::markTestSkipped('DB2 and Oracle do not allow multiple FKs with the same columns.');
98+
}
99+
100+
$articles = Table::editor()
101+
->setUnquotedName('articles')
102+
->setColumns(
103+
Column::editor()
104+
->setUnquotedName('id')
105+
->setTypeName(Types::INTEGER)
106+
->create(),
107+
)
108+
->setPrimaryKeyConstraint(
109+
PrimaryKeyConstraint::editor()
110+
->setUnquotedColumnNames('id')
111+
->create(),
112+
)
113+
->create();
114+
115+
$orders = Table::editor()
116+
->setUnquotedName('orders')
117+
->setColumns(
118+
Column::editor()
119+
->setUnquotedName('id')
120+
->setTypeName(Types::INTEGER)
121+
->create(),
122+
Column::editor()
123+
->setUnquotedName('article_id')
124+
->setTypeName(Types::INTEGER)
125+
->create(),
126+
)
127+
->setForeignKeyConstraints(
128+
ForeignKeyConstraint::editor()
129+
->setUnquotedName('articles_fk')
130+
->setUnquotedReferencingColumnNames('article_id')
131+
->setUnquotedReferencedTableName('articles')
132+
->setUnquotedReferencedColumnNames('id')
133+
->create(),
134+
ForeignKeyConstraint::editor()
135+
->setUnquotedName('articles_fk_2')
136+
->setUnquotedReferencingColumnNames('article_id')
137+
->setUnquotedReferencedTableName('articles')
138+
->setUnquotedReferencedColumnNames('id')
139+
->create(),
140+
)
141+
->create();
142+
143+
$ordersCompare = Table::editor()
144+
->setUnquotedName('orders')
145+
->setColumns(
146+
Column::editor()
147+
->setUnquotedName('id')
148+
->setTypeName(Types::INTEGER)
149+
->create(),
150+
Column::editor()
151+
->setUnquotedName('article_id')
152+
->setTypeName(Types::INTEGER)
153+
->create(),
154+
)
155+
->setForeignKeyConstraints(
156+
ForeignKeyConstraint::editor()
157+
->setUnquotedName('articles_fk')
158+
->setUnquotedReferencingColumnNames('article_id')
159+
->setUnquotedReferencedTableName('articles')
160+
->setUnquotedReferencedColumnNames('id')
161+
->create(),
162+
)
163+
->create();
164+
165+
$this->dropTableIfExists('orders');
166+
$this->dropTableIfExists('articles');
167+
168+
$this->connection->createSchemaManager()
169+
->createTable($articles);
170+
$this->connection->createSchemaManager()
171+
->createTable($orders);
172+
173+
$ordersActual = $this->schemaManager->introspectTable('orders');
174+
175+
$diff = $this->schemaManager->createComparator()
176+
->compareTables($ordersActual, $ordersCompare);
177+
178+
self::assertFalse($diff->isEmpty());
179+
self::assertCount(0, $diff->getAddedForeignKeys());
180+
self::assertCount(1, $diff->getDroppedForeignKeys());
181+
self::assertSame('articles_fk_2', $diff->getDroppedForeignKeys()[0]->getName());
182+
}
183+
}

0 commit comments

Comments
 (0)