diff --git a/lib/Doctrine/DBAL/Schema/Table.php b/lib/Doctrine/DBAL/Schema/Table.php index 69109d21d5c..857caeb0859 100644 --- a/lib/Doctrine/DBAL/Schema/Table.php +++ b/lib/Doctrine/DBAL/Schema/Table.php @@ -42,6 +42,11 @@ class Table extends AbstractAsset */ protected $_columns = array(); + /** + * @var Index[] + */ + private $implicitIndexes = array(); + /** * @var Index[] */ @@ -491,11 +496,24 @@ protected function _addIndex(Index $indexCandidate) { $indexName = $indexCandidate->getName(); $indexName = $this->normalizeIdentifier($indexName); + $replacedImplicitIndexes = array(); - if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) { + foreach ($this->implicitIndexes as $name => $implicitIndex) { + if ($implicitIndex->isFullfilledBy($indexCandidate) && isset($this->_indexes[$name])) { + $replacedImplicitIndexes[] = $name; + } + } + + if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || + ($this->_primaryKeyName != false && $indexCandidate->isPrimary()) + ) { throw SchemaException::indexAlreadyExists($indexName, $this->_name); } + foreach ($replacedImplicitIndexes as $name) { + unset($this->_indexes[$name], $this->implicitIndexes[$name]); + } + if ($indexCandidate->isPrimary()) { $this->_primaryKeyName = $indexName; } @@ -541,7 +559,8 @@ protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint) } } - $this->addIndex($constraint->getColumns()); + $this->_addIndex($indexCandidate); + $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; } /** diff --git a/tests/Doctrine/Tests/DBAL/Schema/TableTest.php b/tests/Doctrine/Tests/DBAL/Schema/TableTest.php index 66b2cef96c0..3174ff9dbc4 100644 --- a/tests/Doctrine/Tests/DBAL/Schema/TableTest.php +++ b/tests/Doctrine/Tests/DBAL/Schema/TableTest.php @@ -491,6 +491,78 @@ public function testPrimaryKeyOverrulingUniqueIndexDoesNotDropUniqueIndex() $this->assertTrue($table->hasIndex('idx_unique')); } + public function testAddingFulfillingRegularIndexOverridesImplicitForeignKeyConstraintIndex() + { + $foreignTable = new Table('foreign'); + $foreignTable->addColumn('id', 'integer'); + + $localTable = new Table('local'); + $localTable->addColumn('id', 'integer'); + $localTable->addForeignKeyConstraint($foreignTable, array('id'), array('id')); + + $this->assertCount(1, $localTable->getIndexes()); + + $localTable->addIndex(array('id'), 'explicit_idx'); + + $this->assertCount(1, $localTable->getIndexes()); + $this->assertTrue($localTable->hasIndex('explicit_idx')); + } + + public function testAddingFulfillingUniqueIndexOverridesImplicitForeignKeyConstraintIndex() + { + $foreignTable = new Table('foreign'); + $foreignTable->addColumn('id', 'integer'); + + $localTable = new Table('local'); + $localTable->addColumn('id', 'integer'); + $localTable->addForeignKeyConstraint($foreignTable, array('id'), array('id')); + + $this->assertCount(1, $localTable->getIndexes()); + + $localTable->addUniqueIndex(array('id'), 'explicit_idx'); + + $this->assertCount(1, $localTable->getIndexes()); + $this->assertTrue($localTable->hasIndex('explicit_idx')); + } + + public function testAddingFulfillingPrimaryKeyOverridesImplicitForeignKeyConstraintIndex() + { + $foreignTable = new Table('foreign'); + $foreignTable->addColumn('id', 'integer'); + + $localTable = new Table('local'); + $localTable->addColumn('id', 'integer'); + $localTable->addForeignKeyConstraint($foreignTable, array('id'), array('id')); + + $this->assertCount(1, $localTable->getIndexes()); + + $localTable->setPrimaryKey(array('id'), 'explicit_idx'); + + $this->assertCount(1, $localTable->getIndexes()); + $this->assertTrue($localTable->hasIndex('explicit_idx')); + } + + public function testAddingFulfillingExplicitIndexOverridingImplicitForeignKeyConstraintIndexWithSameNameDoesNotThrowException() + { + $foreignTable = new Table('foreign'); + $foreignTable->addColumn('id', 'integer'); + + $localTable = new Table('local'); + $localTable->addColumn('id', 'integer'); + $localTable->addForeignKeyConstraint($foreignTable, array('id'), array('id')); + + $this->assertCount(1, $localTable->getIndexes()); + $this->assertTrue($localTable->hasIndex('IDX_8BD688E8BF396750')); + + $implicitIndex = $localTable->getIndex('IDX_8BD688E8BF396750'); + + $localTable->addIndex(array('id'), 'IDX_8BD688E8BF396750'); + + $this->assertCount(1, $localTable->getIndexes()); + $this->assertTrue($localTable->hasIndex('IDX_8BD688E8BF396750')); + $this->assertNotSame($implicitIndex, $localTable->getIndex('IDX_8BD688E8BF396750')); + } + /** * @group DBAL-64 */