1
0
mirror of synced 2025-01-31 12:32:59 +03:00

The schema tool now doesn't add a foreign constraint when subclassess of a STI use the same field to map relations with entities of different classes

This commit is contained in:
Stefano Rodriguez 2012-09-08 05:00:31 +02:00 committed by Benjamin Eberlei
parent b1c69ebab9
commit 482da95352
4 changed files with 66 additions and 39 deletions

View File

@ -42,6 +42,7 @@ use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Stefano Rodriguez <stefano.rodriguez@fubles.com>
*/ */
class SchemaTool class SchemaTool
{ {
@ -142,6 +143,9 @@ class SchemaTool
$metadataSchemaConfig->setExplicitForeignKeyIndexes(false); $metadataSchemaConfig->setExplicitForeignKeyIndexes(false);
$schema = new Schema(array(), array(), $metadataSchemaConfig); $schema = new Schema(array(), array(), $metadataSchemaConfig);
$addedFks = array();
$blacklistedFks = array();
foreach ($classes as $class) { foreach ($classes as $class) {
if ($this->processingNotRequired($class, $processedClasses)) { if ($this->processingNotRequired($class, $processedClasses)) {
continue; continue;
@ -150,8 +154,8 @@ class SchemaTool
$table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform)); $table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform));
if ($class->isInheritanceTypeSingleTable()) { if ($class->isInheritanceTypeSingleTable()) {
$this->gatherColumns($class, $table); $columns = $this->gatherColumns($class, $table);
$this->gatherRelationsSql($class, $table, $schema); $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
// Add the discriminator column // Add the discriminator column
$this->addDiscriminatorColumnDefinition($class, $table); $this->addDiscriminatorColumnDefinition($class, $table);
@ -165,7 +169,7 @@ class SchemaTool
foreach ($class->subClasses as $subClassName) { foreach ($class->subClasses as $subClassName) {
$subClass = $this->em->getClassMetadata($subClassName); $subClass = $this->em->getClassMetadata($subClassName);
$this->gatherColumns($subClass, $table); $this->gatherColumns($subClass, $table);
$this->gatherRelationsSql($subClass, $table, $schema); $this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks);
$processedClasses[$subClassName] = true; $processedClasses[$subClassName] = true;
} }
} elseif ($class->isInheritanceTypeJoined()) { } elseif ($class->isInheritanceTypeJoined()) {
@ -182,7 +186,7 @@ class SchemaTool
} }
} }
$this->gatherRelationsSql($class, $table, $schema); $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
// Add the discriminator column only to the root table // Add the discriminator column only to the root table
if ($class->name == $class->rootEntityName) { if ($class->name == $class->rootEntityName) {
@ -211,7 +215,7 @@ class SchemaTool
throw ORMException::notSupported(); throw ORMException::notSupported();
} else { } else {
$this->gatherColumns($class, $table); $this->gatherColumns($class, $table);
$this->gatherRelationsSql($class, $table, $schema); $this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
} }
$pkColumns = array(); $pkColumns = array();
@ -432,9 +436,11 @@ class SchemaTool
* @param ClassMetadata $class * @param ClassMetadata $class
* @param \Doctrine\DBAL\Schema\Table $table * @param \Doctrine\DBAL\Schema\Table $table
* @param \Doctrine\DBAL\Schema\Schema $schema * @param \Doctrine\DBAL\Schema\Schema $schema
* @param array $addedFks
* @param array $blacklistedFks
* @return void * @return void
*/ */
private function gatherRelationsSql($class, Table $table, $schema) private function gatherRelationsSql($class, $table, $schema, &$addedFks, &$blacklistedFks)
{ {
foreach ($class->associationMappings as $mapping) { foreach ($class->associationMappings as $mapping) {
if (isset($mapping['inherited'])) { if (isset($mapping['inherited'])) {
@ -446,7 +452,7 @@ class SchemaTool
if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) { if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) {
$primaryKeyColumns = $uniqueConstraints = array(); // PK is unnecessary for this relation-type $primaryKeyColumns = $uniqueConstraints = array(); // PK is unnecessary for this relation-type
$this->_gatherRelationJoinColumns($mapping['joinColumns'], $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints); $this->_gatherRelationJoinColumns($mapping['joinColumns'], $table, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks);
foreach($uniqueConstraints as $indexName => $unique) { foreach($uniqueConstraints as $indexName => $unique) {
$table->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName); $table->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName);
@ -463,10 +469,10 @@ class SchemaTool
$primaryKeyColumns = $uniqueConstraints = array(); $primaryKeyColumns = $uniqueConstraints = array();
// Build first FK constraint (relation table => source table) // Build first FK constraint (relation table => source table)
$this->_gatherRelationJoinColumns($joinTable['joinColumns'], $theJoinTable, $class, $mapping, $primaryKeyColumns, $uniqueConstraints); $this->_gatherRelationJoinColumns($joinTable['joinColumns'], $theJoinTable, $class, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks);
// Build second FK constraint (relation table => target table) // Build second FK constraint (relation table => target table)
$this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints); $this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks);
$theJoinTable->setPrimaryKey($primaryKeyColumns); $theJoinTable->setPrimaryKey($primaryKeyColumns);
@ -522,8 +528,10 @@ class SchemaTool
* @param array $mapping * @param array $mapping
* @param array $primaryKeyColumns * @param array $primaryKeyColumns
* @param array $uniqueConstraints * @param array $uniqueConstraints
* @param array $addedFks
* @param array $blacklistedFks
*/ */
private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints) private function _gatherRelationJoinColumns($joinColumns, $theJoinTable, $class, $mapping, &$primaryKeyColumns, &$uniqueConstraints, &$addedFks, &$blacklistedFks)
{ {
$localColumns = array(); $localColumns = array();
$foreignColumns = array(); $foreignColumns = array();
@ -587,9 +595,27 @@ class SchemaTool
} }
} }
$theJoinTable->addForeignKeyConstraint( $compositeName = $theJoinTable->getName().'.'.implode('', $localColumns);
$foreignTableName, $localColumns, $foreignColumns, $fkOptions if (isset($addedFks[$compositeName])
); && ($foreignTableName != $addedFks[$compositeName]['foreignTableName']
|| 0 < count(array_diff($foreignColumns, $addedFks[$compositeName]['foreignColumns'])))
) {
foreach ($theJoinTable->getForeignKeys() as $fkName => $key) {
if (0 === count(array_diff($key->getLocalColumns(), $localColumns))
&& (($key->getForeignTableName() != $foreignTableName)
|| 0 < count(array_diff($key->getForeignColumns(), $foreignColumns)))
) {
$theJoinTable->removeForeignKey($fkName);
break;
}
}
$blacklistedFks[$compositeName] = true;
} elseif (!isset($blacklistedFks[$compositeName])) {
$addedFks[$compositeName] = array('foreignTableName' => $foreignTableName, 'foreignColumns' => $foreignColumns);
$theJoinTable->addUnnamedForeignKeyConstraint(
$foreignTableName, $localColumns, $foreignColumns, $fkOptions
);
}
} }
/** /**

View File

@ -8,15 +8,15 @@ namespace Doctrine\Tests\Models\SingleTableInheritanceType;
*/ */
class Structure class Structure
{ {
/** /**
* @Id * @Id
* @Column(type="integer") * @Column(type="integer")
* @GeneratedValue(strategy="AUTO") * @GeneratedValue(strategy="AUTO")
*/ */
protected $id; protected $id;
/** /**
* @Column(type="string", length=32, nullable=true) * @Column(type="string", length=32, nullable=true)
*/ */
protected $name; protected $name;
} }

View File

@ -10,17 +10,17 @@ use Doctrine\Common\Collections\ArrayCollection;
*/ */
class User class User
{ {
/** /**
* @Id * @Id
* @Column(type="integer") * @Column(type="integer")
* @GeneratedValue(strategy="AUTO") * @GeneratedValue(strategy="AUTO")
*/ */
protected $id; protected $id;
/** /**
* @Column(type="string", length=32, nullable=true) * @Column(type="string", length=32, nullable=true)
*/ */
protected $name; protected $name;
/** /**
* @var ArrayCollection $followedUsers * @var ArrayCollection $followedUsers
@ -34,7 +34,8 @@ class User
*/ */
protected $followedStructures; protected $followedStructures;
public function __construct() { public function __construct()
{
$this->followedUsers = new ArrayCollection(); $this->followedUsers = new ArrayCollection();
$this->followedStructures = new ArrayCollection(); $this->followedStructures = new ArrayCollection();
} }
@ -52,7 +53,7 @@ class User
/** /**
* Add followedUsers * Add followedUsers
* *
* @param UserFollowedUser $followedUsers * @param UserFollowedUser $followedUsers
* @return User * @return User
*/ */
public function addFollowedUser(UserFollowedUser $followedUsers) public function addFollowedUser(UserFollowedUser $followedUsers)
@ -65,7 +66,7 @@ class User
/** /**
* Remove followedUsers * Remove followedUsers
* *
* @param UserFollowedUser $followedUsers * @param UserFollowedUser $followedUsers
* @return User * @return User
*/ */
public function removeFollowedUser(UserFollowedUser $followedUsers) public function removeFollowedUser(UserFollowedUser $followedUsers)
@ -88,7 +89,7 @@ class User
/** /**
* Add followedStructures * Add followedStructures
* *
* @param UserFollowedStructure $followedStructures * @param UserFollowedStructure $followedStructures
* @return User * @return User
*/ */
public function addFollowedStructure(UserFollowedStructure $followedStructures) public function addFollowedStructure(UserFollowedStructure $followedStructures)
@ -101,7 +102,7 @@ class User
/** /**
* Remove followedStructures * Remove followedStructures
* *
* @param UserFollowedStructure $followedStructures * @param UserFollowedStructure $followedStructures
* @return User * @return User
*/ */
public function removeFollowedStructure(UserFollowedStructure $followedStructures) public function removeFollowedStructure(UserFollowedStructure $followedStructures)

View File

@ -24,7 +24,7 @@ class UserFollowedStructure extends UserFollowedObject
/** /**
* Construct a UserFollowedStructure entity * Construct a UserFollowedStructure entity
* *
* @param User $user * @param User $user
* @param Structure $followedStructure * @param Structure $followedStructure
*/ */
public function __construct(User $user, Structure $followedStructure) public function __construct(User $user, Structure $followedStructure)