1
0
mirror of synced 2025-01-18 22:41:43 +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 Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Stefano Rodriguez <stefano.rodriguez@fubles.com>
*/
class SchemaTool
{
@ -142,6 +143,9 @@ class SchemaTool
$metadataSchemaConfig->setExplicitForeignKeyIndexes(false);
$schema = new Schema(array(), array(), $metadataSchemaConfig);
$addedFks = array();
$blacklistedFks = array();
foreach ($classes as $class) {
if ($this->processingNotRequired($class, $processedClasses)) {
continue;
@ -150,8 +154,8 @@ class SchemaTool
$table = $schema->createTable($this->quoteStrategy->getTableName($class, $this->platform));
if ($class->isInheritanceTypeSingleTable()) {
$this->gatherColumns($class, $table);
$this->gatherRelationsSql($class, $table, $schema);
$columns = $this->gatherColumns($class, $table);
$this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
// Add the discriminator column
$this->addDiscriminatorColumnDefinition($class, $table);
@ -165,7 +169,7 @@ class SchemaTool
foreach ($class->subClasses as $subClassName) {
$subClass = $this->em->getClassMetadata($subClassName);
$this->gatherColumns($subClass, $table);
$this->gatherRelationsSql($subClass, $table, $schema);
$this->gatherRelationsSql($subClass, $table, $schema, $addedFks, $blacklistedFks);
$processedClasses[$subClassName] = true;
}
} 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
if ($class->name == $class->rootEntityName) {
@ -211,7 +215,7 @@ class SchemaTool
throw ORMException::notSupported();
} else {
$this->gatherColumns($class, $table);
$this->gatherRelationsSql($class, $table, $schema);
$this->gatherRelationsSql($class, $table, $schema, $addedFks, $blacklistedFks);
}
$pkColumns = array();
@ -432,9 +436,11 @@ class SchemaTool
* @param ClassMetadata $class
* @param \Doctrine\DBAL\Schema\Table $table
* @param \Doctrine\DBAL\Schema\Schema $schema
* @param array $addedFks
* @param array $blacklistedFks
* @return void
*/
private function gatherRelationsSql($class, Table $table, $schema)
private function gatherRelationsSql($class, $table, $schema, &$addedFks, &$blacklistedFks)
{
foreach ($class->associationMappings as $mapping) {
if (isset($mapping['inherited'])) {
@ -446,7 +452,7 @@ class SchemaTool
if ($mapping['type'] & ClassMetadata::TO_ONE && $mapping['isOwningSide']) {
$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) {
$table->addUniqueIndex($unique['columns'], is_numeric($indexName) ? null : $indexName);
@ -463,10 +469,10 @@ class SchemaTool
$primaryKeyColumns = $uniqueConstraints = array();
// 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)
$this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints);
$this->_gatherRelationJoinColumns($joinTable['inverseJoinColumns'], $theJoinTable, $foreignClass, $mapping, $primaryKeyColumns, $uniqueConstraints, $addedFks, $blacklistedFks);
$theJoinTable->setPrimaryKey($primaryKeyColumns);
@ -522,8 +528,10 @@ class SchemaTool
* @param array $mapping
* @param array $primaryKeyColumns
* @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();
$foreignColumns = array();
@ -587,9 +595,27 @@ class SchemaTool
}
}
$theJoinTable->addForeignKeyConstraint(
$foreignTableName, $localColumns, $foreignColumns, $fkOptions
);
$compositeName = $theJoinTable->getName().'.'.implode('', $localColumns);
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
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @Column(type="string", length=32, nullable=true)
*/
protected $name;
/**
* @Column(type="string", length=32, nullable=true)
*/
protected $name;
}

View File

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

View File

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