Skip to content

Commit d9b04de

Browse files
committed
Add regression test for STI duplicate foreign key deduplication
When multiple STI child entities have a ManyToOne relation to the same target entity using the same join column, SchemaTool used to call addForeignKeyConstraint twice with the same constraint name, triggering a DBAL deprecation ("Overwriting an existing foreign key constraint"). The production fix landed in 3.6.x via #12477 ("Avoid adding the same foreign key twice for STI") but shipped without a regression test. This adds the missing coverage: the STI table must end up with exactly one foreign key when children share the same join column. See doctrine/dbal#7125
1 parent 7b5faaa commit d9b04de

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

tests/Tests/ORM/Tools/SchemaToolTest.php

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
use Doctrine\DBAL\Types\Types;
1919
use Doctrine\ORM\Mapping\ClassMetadata;
2020
use Doctrine\ORM\Mapping\Column;
21+
use Doctrine\ORM\Mapping\DiscriminatorColumn;
22+
use Doctrine\ORM\Mapping\DiscriminatorMap;
2123
use Doctrine\ORM\Mapping\Entity;
24+
use Doctrine\ORM\Mapping\GeneratedValue;
2225
use Doctrine\ORM\Mapping\Id;
2326
use Doctrine\ORM\Mapping\Index;
27+
use Doctrine\ORM\Mapping\InheritanceType;
2428
use Doctrine\ORM\Mapping\JoinColumn;
2529
use Doctrine\ORM\Mapping\ManyToOne;
2630
use Doctrine\ORM\Mapping\MappingException;
@@ -581,6 +585,41 @@ private static function columnIsIndexed(DbalTable $table, string $column): bool
581585

582586
return false;
583587
}
588+
589+
public function testSingleTableInheritanceWithSameForeignKeyInChildrenDoesNotTriggerDeprecation(): void
590+
{
591+
$em = $this->getTestEntityManager();
592+
$schemaTool = new SchemaTool($em);
593+
594+
$schema = $schemaTool->getSchemaFromMetadata([
595+
$em->getClassMetadata(STIBox::class),
596+
$em->getClassMetadata(STILocation::class),
597+
$em->getClassMetadata(STIBoxContainer::class),
598+
$em->getClassMetadata(STIPackedBoxContainer::class),
599+
]);
600+
601+
self::assertTrue($schema->hasTable('sti_location'));
602+
603+
$table = $schema->getTable('sti_location');
604+
605+
self::assertCount(1, $table->getForeignKeys());
606+
607+
$foreignKeys = $table->getForeignKeys();
608+
$foreignKey = current($foreignKeys);
609+
610+
if (! class_exists(ForeignKeyConstraintEditor::class)) {
611+
self::assertSame('sti_box', $foreignKey->getForeignTableName());
612+
self::assertSame(['box_id'], $foreignKey->getLocalColumns());
613+
614+
return;
615+
}
616+
617+
self::assertSame('sti_box', $foreignKey->getReferencedTableName()->toString());
618+
self::assertSame(['box_id'], array_map(
619+
static fn (UnqualifiedName $name) => $name->toString(),
620+
$foreignKey->getReferencingColumnNames(),
621+
));
622+
}
584623
}
585624

586625
#[Table(options: ['foo' => 'bar', 'baz' => ['key' => 'val']])]
@@ -816,3 +855,42 @@ class QuotedEntity
816855
#[Column(name: '`quoted-name`')]
817856
public string $name = '';
818857
}
858+
859+
#[Entity]
860+
#[Table(name: 'sti_box')]
861+
class STIBox
862+
{
863+
#[Id]
864+
#[Column(type: 'integer')]
865+
#[GeneratedValue]
866+
public int|null $id = null;
867+
}
868+
869+
#[Entity]
870+
#[Table(name: 'sti_location')]
871+
#[InheritanceType('SINGLE_TABLE')]
872+
#[DiscriminatorColumn(name: 'type', type: 'string')]
873+
#[DiscriminatorMap(['box_container' => STIBoxContainer::class, 'packed_box_container' => STIPackedBoxContainer::class])]
874+
abstract class STILocation
875+
{
876+
#[Id]
877+
#[Column(type: 'integer')]
878+
#[GeneratedValue]
879+
public int|null $id = null;
880+
}
881+
882+
#[Entity]
883+
class STIBoxContainer extends STILocation
884+
{
885+
#[ManyToOne(targetEntity: STIBox::class)]
886+
#[JoinColumn(name: 'box_id', referencedColumnName: 'id')]
887+
public STIBox|null $box = null;
888+
}
889+
890+
#[Entity]
891+
class STIPackedBoxContainer extends STILocation
892+
{
893+
#[ManyToOne(targetEntity: STIBox::class)]
894+
#[JoinColumn(name: 'box_id', referencedColumnName: 'id')]
895+
public STIBox|null $box = null;
896+
}

0 commit comments

Comments
 (0)