Skip to content

Commit 0c3251b

Browse files
committed
Introduce equals() in Index
1 parent 45d8ac6 commit 0c3251b

File tree

4 files changed

+166
-17
lines changed

4 files changed

+166
-17
lines changed

src/Schema/Comparator.php

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Doctrine\DBAL\Schema;
66

77
use Doctrine\DBAL\Platforms\AbstractPlatform;
8+
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
89

910
use function count;
1011
use function strtolower;
@@ -205,6 +206,7 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff
205206

206207
$oldIndexes = $oldTable->getIndexes();
207208
$newIndexes = $newTable->getIndexes();
209+
$folding = $this->platform->getUnquotedIdentifierFolding();
208210

209211
// See if all the indexes from the old table exist in the new one
210212
foreach ($newIndexes as $newIndexName => $newIndex) {
@@ -226,7 +228,7 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff
226228
// See if index has changed in the new table.
227229
$newIndex = $newTable->getIndex($oldIndexName);
228230

229-
if (! $this->diffIndex($oldIndex, $newIndex)) {
231+
if ($oldIndex->equals($newIndex, $folding)) {
230232
continue;
231233
}
232234

@@ -235,12 +237,11 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff
235237
}
236238

237239
if ($this->config->getDetectRenamedIndexes()) {
238-
$renamedIndexes = $this->detectRenamedIndexes($addedIndexes, $droppedIndexes);
240+
$renamedIndexes = $this->detectRenamedIndexes($addedIndexes, $droppedIndexes, $folding);
239241
}
240242

241243
$oldForeignKeys = $oldTable->getForeignKeys();
242244
$newForeignKeys = $newTable->getForeignKeys();
243-
$folding = $this->platform->getUnquotedIdentifierFolding();
244245

245246
foreach ($oldForeignKeys as $oldKey => $oldForeignKey) {
246247
foreach ($newForeignKeys as $newKey => $newForeignKey) {
@@ -350,14 +351,17 @@ private function primaryKeyConstraintsEqual(
350351
*
351352
* @return array<string,Index>
352353
*/
353-
private function detectRenamedIndexes(array &$addedIndexes, array &$removedIndexes): array
354-
{
354+
private function detectRenamedIndexes(
355+
array &$addedIndexes,
356+
array &$removedIndexes,
357+
UnquotedIdentifierFolding $folding,
358+
): array {
355359
$candidatesByName = [];
356360

357361
// Gather possible rename candidates by comparing each added and removed index based on semantics.
358362
foreach ($addedIndexes as $addedIndexName => $addedIndex) {
359363
foreach ($removedIndexes as $removedIndex) {
360-
if ($this->diffIndex($addedIndex, $removedIndex)) {
364+
if (! $addedIndex->equals($removedIndex, $folding)) {
361365
continue;
362366
}
363367

@@ -402,15 +406,4 @@ protected function columnsEqual(Column $column1, Column $column2): bool
402406
{
403407
return $this->platform->columnsEqual($column1, $column2);
404408
}
405-
406-
/**
407-
* Finds the difference between the indexes $index1 and $index2.
408-
*
409-
* Compares $index1 with $index2 and returns true if there are any
410-
* differences or false in case there are no differences.
411-
*/
412-
protected function diffIndex(Index $index1, Index $index2): bool
413-
{
414-
return ! ($index1->isFulfilledBy($index2) && $index2->isFulfilledBy($index1));
415-
}
416409
}

src/Schema/Index.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Doctrine\DBAL\Schema\Name\Parser\UnqualifiedNameParser;
1111
use Doctrine\DBAL\Schema\Name\Parsers;
1212
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
13+
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
1314

1415
use function count;
1516
use function strlen;
@@ -169,6 +170,36 @@ public function isFulfilledBy(Index $other): bool
169170
return $this->type === $other->type;
170171
}
171172

173+
/**
174+
* Returns whether this index is equal to the other.
175+
*/
176+
public function equals(self $other, UnquotedIdentifierFolding $folding): bool
177+
{
178+
if ($this === $other) {
179+
return true;
180+
}
181+
182+
if ($this->type !== $other->type) {
183+
return false;
184+
}
185+
186+
if (count($this->columns) !== count($other->columns)) {
187+
return false;
188+
}
189+
190+
for ($i = 0, $count = count($this->columns); $i < $count; $i++) {
191+
if (! $this->columns[$i]->equals($other->columns[$i], $folding)) {
192+
return false;
193+
}
194+
}
195+
196+
if ($this->isClustered !== $other->isClustered) {
197+
return false;
198+
}
199+
200+
return $this->predicate === $other->predicate;
201+
}
202+
172203
/**
173204
* Instantiates a new index editor.
174205
*/

src/Schema/Index/IndexedColumn.php

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

77
use Doctrine\DBAL\Schema\Exception\InvalidIndexDefinition;
88
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
9+
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
910

1011
final class IndexedColumn
1112
{
@@ -31,4 +32,20 @@ public function getLength(): ?int
3132
{
3233
return $this->length;
3334
}
35+
36+
/**
37+
* Returns whether this indexed column is equal to the other.
38+
*/
39+
public function equals(self $other, UnquotedIdentifierFolding $folding): bool
40+
{
41+
if ($this === $other) {
42+
return true;
43+
}
44+
45+
if (! $this->columnName->equals($other->columnName, $folding)) {
46+
return false;
47+
}
48+
49+
return $this->length === $other->length;
50+
}
3451
}

tests/Schema/IndexTest.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Doctrine\DBAL\Schema\Index\IndexedColumn;
1010
use Doctrine\DBAL\Schema\Index\IndexType;
1111
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
12+
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
1213
use PHPUnit\Framework\Attributes\DataProvider;
1314
use PHPUnit\Framework\Attributes\TestWith;
1415
use PHPUnit\Framework\TestCase;
@@ -167,4 +168,111 @@ public function testEmptyPredicate(): void
167168
$this->expectException(InvalidIndexDefinition::class);
168169
$editor->create();
169170
}
171+
172+
public function testEqualsToSelf(): void
173+
{
174+
$index = Index::editor()
175+
->setName(
176+
UnqualifiedName::unquoted('idx_user_id'),
177+
)
178+
->setColumnNames(
179+
UnqualifiedName::unquoted('user_id'),
180+
)
181+
->create();
182+
183+
self::assertTrue($index->equals($index, UnquotedIdentifierFolding::NONE));
184+
}
185+
186+
public function testEqualIndexes(): void
187+
{
188+
$index1 = Index::editor()
189+
->setName(
190+
UnqualifiedName::unquoted('idx_user_id'),
191+
)
192+
->setColumnNames(
193+
UnqualifiedName::unquoted('user_id'),
194+
)
195+
->create();
196+
197+
$index2 = Index::editor()
198+
->setName(
199+
UnqualifiedName::unquoted('idx_user_id'),
200+
)
201+
->setColumnNames(
202+
UnqualifiedName::unquoted('user_id'),
203+
)
204+
->create();
205+
206+
self::assertTrue($index1->equals($index2, UnquotedIdentifierFolding::NONE));
207+
self::assertTrue($index2->equals($index1, UnquotedIdentifierFolding::NONE));
208+
}
209+
210+
#[DataProvider('unequalIndexProvider')]
211+
public function testUnequalIndexes(Index $index1, Index $index2): void
212+
{
213+
self::assertFalse($index1->equals($index2, UnquotedIdentifierFolding::NONE));
214+
self::assertFalse($index2->equals($index1, UnquotedIdentifierFolding::NONE));
215+
}
216+
217+
/** @return iterable<array{Index, Index}> */
218+
public static function unequalIndexProvider(): iterable
219+
{
220+
$prototype = Index::editor()
221+
->setName(
222+
UnqualifiedName::unquoted('idx_user_id'),
223+
)
224+
->setColumnNames(
225+
UnqualifiedName::unquoted('user_id'),
226+
)
227+
->create();
228+
229+
yield [
230+
$prototype,
231+
$prototype->edit()
232+
->setType(IndexType::UNIQUE)
233+
->create(),
234+
];
235+
236+
yield [
237+
$prototype,
238+
$prototype->edit()
239+
->setColumnNames(
240+
UnqualifiedName::unquoted('user_id'),
241+
UnqualifiedName::unquoted('is_active'),
242+
)
243+
->create(),
244+
];
245+
246+
yield [
247+
$prototype,
248+
$prototype->edit()
249+
->setColumnNames(
250+
UnqualifiedName::unquoted('user_name'),
251+
)
252+
->create(),
253+
];
254+
255+
yield [
256+
$prototype,
257+
$prototype->edit()
258+
->setColumns(
259+
new IndexedColumn(UnqualifiedName::unquoted('user_id'), 1),
260+
)
261+
->create(),
262+
];
263+
264+
yield [
265+
$prototype,
266+
$prototype->edit()
267+
->setIsClustered(true)
268+
->create(),
269+
];
270+
271+
yield [
272+
$prototype,
273+
$prototype->edit()
274+
->setPredicate('is_active = 1')
275+
->create(),
276+
];
277+
}
170278
}

0 commit comments

Comments
 (0)