diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 44dfb1315e4..c96c52b066f 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -102,9 +102,7 @@ - src/Connection.php - src/Schema/Comparator.php - src/SQLParserUtils.php + src/Schema/Table.php diff --git a/src/Schema/Exception/PrimaryKeyAlreadyExists.php b/src/Schema/Exception/PrimaryKeyAlreadyExists.php new file mode 100644 index 00000000000..70fd1f82436 --- /dev/null +++ b/src/Schema/Exception/PrimaryKeyAlreadyExists.php @@ -0,0 +1,21 @@ + keys are new names, values are old names */ protected array $renamedColumns = []; /** @var Index[] */ protected array $_indexes = []; + /** + * The keys of this array are the names of the indexes that were implicitly created as backing for foreign key + * constraints. The values are not used but must be non-null for {@link isset()} to work correctly. + * + * @var array + */ + private array $implicitIndexNames = []; + protected ?string $_primaryKeyName = null; /** @var UniqueConstraint[] */ @@ -606,36 +611,41 @@ protected function _addColumn(Column $column): void /** * Adds an index to the table. */ - protected function _addIndex(Index $indexCandidate): self + protected function _addIndex(Index $index): self { - $indexName = $indexCandidate->getName(); - $indexName = $this->normalizeIdentifier($indexName); - $replacedImplicitIndexes = []; + $indexName = $this->normalizeIdentifier($index->getName()); - foreach ($this->implicitIndexes as $name => $implicitIndex) { - if (! $implicitIndex->isFulfilledBy($indexCandidate) || ! isset($this->_indexes[$name])) { + $replacedImplicitIndexNames = []; + + foreach ($this->implicitIndexNames as $implicitIndexName => $_) { + if (! isset($this->_indexes[$implicitIndexName])) { + continue; + } + + if (! $this->_indexes[$implicitIndexName]->isFulfilledBy($index)) { continue; } - $replacedImplicitIndexes[] = $name; + $replacedImplicitIndexNames[$implicitIndexName] = true; } - if ( - (isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) || - ($this->_primaryKeyName !== null && $indexCandidate->isPrimary()) - ) { + if (isset($this->_indexes[$indexName]) && ! isset($replacedImplicitIndexNames[$indexName])) { throw IndexAlreadyExists::new($indexName, $this->_name); } - foreach ($replacedImplicitIndexes as $name) { - unset($this->_indexes[$name], $this->implicitIndexes[$name]); + if ($this->_primaryKeyName !== null && $index->isPrimary()) { + throw PrimaryKeyAlreadyExists::new($this->_name); + } + + foreach ($replacedImplicitIndexNames as $name => $_) { + unset($this->_indexes[$name], $this->implicitIndexNames[$name]); } - if ($indexCandidate->isPrimary()) { + if ($index->isPrimary()) { $this->_primaryKeyName = $indexName; } - $this->_indexes[$indexName] = $indexCandidate; + $this->_indexes[$indexName] = $index; return $this; } @@ -671,7 +681,7 @@ protected function _addUniqueConstraint(UniqueConstraint $constraint): self } } - $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; + $this->implicitIndexNames[$this->normalizeIdentifier($indexName)] = true; return $this; } @@ -709,7 +719,7 @@ protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint): s } $this->_addIndex($indexCandidate); - $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate; + $this->implicitIndexNames[$this->normalizeIdentifier($indexName)] = true; return $this; }