Skip to content

Commit 5a74880

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

File tree

2 files changed

+189
-6
lines changed

2 files changed

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

0 commit comments

Comments
 (0)