Skip to content

Commit 7f2f426

Browse files
authored
Merge pull request #68: deduplicate indexes if FK outer key is PK
2 parents 24284c5 + 490efa4 commit 7f2f426

File tree

3 files changed

+77
-5
lines changed

3 files changed

+77
-5
lines changed

src/Generator/ForeignKeys.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ public function run(Registry $registry): Registry
1414
foreach ($registry as $entity) {
1515
foreach ($entity->getForeignKeys() as $fk) {
1616
$target = $registry->getEntity($fk->getTarget());
17+
$targetSchema = $registry->getTableSchema($target);
1718

18-
if (!$registry->getTableSchema($target)->hasIndex($fk->getOuterColumns())) {
19-
$registry->getTableSchema($target)->index($fk->getOuterColumns())->unique();
19+
$pkExists = \array_diff($fk->getOuterColumns(), $targetSchema->getPrimaryKeys()) === [];
20+
if (!$pkExists && !$targetSchema->hasIndex($fk->getOuterColumns())) {
21+
$targetSchema->index($fk->getOuterColumns())->unique();
2022
}
2123

2224
$registry->getTableSchema($entity)

tests/Schema/Fixtures/Author.php

+12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ public static function defineWithoutPK(): Entity
3737
return $entity;
3838
}
3939

40+
public static function defineWithUser(): Entity
41+
{
42+
$entity = self::define();
43+
44+
$entity->getFields()->set(
45+
'p_user_id',
46+
(new Field())->setType('int(11)')->setColumn('user_id')
47+
);
48+
49+
return $entity;
50+
}
51+
4052
public static function defineCompositePK(): Entity
4153
{
4254
$entity = self::define();

tests/Schema/Generator/ForeignKeysTest.php

+61-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Cycle\Schema\Tests\Generator;
66

77
use Cycle\Schema\Compiler;
8+
use Cycle\Schema\Definition\Field;
89
use Cycle\Schema\Definition\ForeignKey;
910
use Cycle\Schema\Generator\ForeignKeys;
1011
use Cycle\Schema\Generator\RenderTables;
@@ -18,7 +19,7 @@ abstract class ForeignKeysTest extends BaseTest
1819
{
1920
public function testTableSchemaShouldBeModified(): void
2021
{
21-
$author = Author::define();
22+
$author = Author::defineWithUser();
2223
$user = User::define();
2324
$plain = Plain::define();
2425

@@ -31,7 +32,7 @@ public function testTableSchemaShouldBeModified(): void
3132

3233
$fk = new ForeignKey();
3334
$fk->setTarget('user');
34-
$fk->setInnerColumns(['id']);
35+
$fk->setInnerColumns(['user_id']);
3536
$fk->setOuterColumns(['id']);
3637
$fk->setAction('CASCADE');
3738
$fk->createIndex(true);
@@ -46,10 +47,67 @@ public function testTableSchemaShouldBeModified(): void
4647

4748
$this->assertStringContainsString('authors', $expectedFk->getTable());
4849
$this->assertStringContainsString('users', $expectedFk->getForeignTable());
49-
$this->assertSame(['id'], $expectedFk->getColumns());
50+
$this->assertSame(['user_id'], $expectedFk->getColumns());
5051
$this->assertSame(['id'], $expectedFk->getForeignKeys());
5152
$this->assertSame('CASCADE', $expectedFk->getDeleteRule());
5253
$this->assertSame('CASCADE', $expectedFk->getUpdateRule());
5354
$this->assertTrue($expectedFk->hasIndex());
5455
}
56+
57+
public function testCreateIndex(): void
58+
{
59+
$author = Author::defineWithUser();
60+
$user = User::define();
61+
$user->getFields()->set('u_other_id', (new Field())->setType('integer')->setColumn('other_id'));
62+
$plain = Plain::define();
63+
64+
$registry = new Registry($this->dbal);
65+
$registry->register($author)->linkTable($author, 'default', 'authors');
66+
$registry->register($user)->linkTable($user, 'default', 'users');
67+
$registry->register($plain)->linkTable($plain, 'default', 'plain');
68+
69+
$this->assertSame([], $registry->getTableSchema($author)->getForeignKeys());
70+
71+
$fk = new ForeignKey();
72+
$fk->setTarget('user');
73+
$fk->setInnerColumns(['user_id']);
74+
$fk->setOuterColumns(['other_id']);
75+
$fk->setAction('CASCADE');
76+
$fk->createIndex(true);
77+
78+
$author->getForeignKeys()->set($fk);
79+
80+
$compiler = new Compiler();
81+
$compiler->compile($registry, [new RenderTables(), new ForeignKeys()]);
82+
83+
$this->assertCount(1, $registry->getTableSchema($user)->getIndexes());
84+
}
85+
86+
public function testShouldNotCreateIndexOnPk(): void
87+
{
88+
$author = Author::defineWithUser();
89+
$user = User::define();
90+
$plain = Plain::define();
91+
92+
$registry = new Registry($this->dbal);
93+
$registry->register($author)->linkTable($author, 'default', 'authors');
94+
$registry->register($user)->linkTable($user, 'default', 'users');
95+
$registry->register($plain)->linkTable($plain, 'default', 'plain');
96+
97+
$this->assertSame([], $registry->getTableSchema($author)->getForeignKeys());
98+
99+
$fk = new ForeignKey();
100+
$fk->setTarget('user');
101+
$fk->setInnerColumns(['user_id']);
102+
$fk->setOuterColumns(['id']);
103+
$fk->setAction('CASCADE');
104+
$fk->createIndex(true);
105+
106+
$author->getForeignKeys()->set($fk);
107+
108+
$compiler = new Compiler();
109+
$compiler->compile($registry, [new RenderTables(), new ForeignKeys()]);
110+
111+
$this->assertEmpty($registry->getTableSchema($user)->getIndexes());
112+
}
55113
}

0 commit comments

Comments
 (0)