diff --git a/lib/Doctrine/DBAL/Schema/Comparator.php b/lib/Doctrine/DBAL/Schema/Comparator.php index 03b800e396d..16582f7a79e 100644 --- a/lib/Doctrine/DBAL/Schema/Comparator.php +++ b/lib/Doctrine/DBAL/Schema/Comparator.php @@ -12,6 +12,7 @@ use function array_unique; use function assert; use function count; +use function strcasecmp; use function strtolower; /** @@ -259,7 +260,10 @@ public function diffTable(Table $table1, Table $table2) if ($this->diffForeignKey($constraint1, $constraint2) === false) { unset($fromFkeys[$key1], $toFkeys[$key2]); } else { - if (strtolower($constraint1->getName()) === strtolower($constraint2->getName())) { + $name1 = $constraint1->getName(); + $name2 = $constraint2->getName(); + + if ($name1 !== null && $name2 !== null && strcasecmp($name1, $name2) === 0) { $tableDifferences->changedForeignKeys[] = $constraint2; $changes++; unset($fromFkeys[$key1], $toFkeys[$key2]); @@ -349,8 +353,20 @@ private function detectIndexRenamings(TableDiff $tableDifferences) : void [$removedIndex, $addedIndex] = $candidateIndexes[0]; - $removedIndexName = strtolower($removedIndex->getName()); - $addedIndexName = strtolower($addedIndex->getName()); + $removedIndexName = $removedIndex->getName(); + + if ($removedIndexName === null) { + continue; + } + + $addedIndexName = $addedIndex->getName(); + + if ($addedIndexName === null) { + continue; + } + + $removedIndexName = strtolower($removedIndexName); + $addedIndexName = strtolower($addedIndexName); if (isset($tableDifferences->renamedIndexes[$removedIndexName])) { continue; diff --git a/lib/Doctrine/DBAL/Schema/SchemaException.php b/lib/Doctrine/DBAL/Schema/SchemaException.php index 72c38870f12..cd0fa483c3d 100644 --- a/lib/Doctrine/DBAL/Schema/SchemaException.php +++ b/lib/Doctrine/DBAL/Schema/SchemaException.php @@ -116,6 +116,17 @@ public static function namedForeignKeyRequired(Table $localTable, ForeignKeyCons ); } + public static function namedIndexRequired(Table $table, Index $index) : self + { + return new self( + sprintf( + 'The performed schema operation on %s requires a named index, but the given index on (%s) is currently unnamed.', + $table->getName(), + implode(', ', $index->getColumns()) + ) + ); + } + public static function alterTableChangeNotSupported(string $changeName) : self { return new self( diff --git a/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php b/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php index 8f3a2a822ef..d36947a55cf 100644 --- a/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php +++ b/lib/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php @@ -4,6 +4,7 @@ use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\SchemaException; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; @@ -57,6 +58,8 @@ public function acceptSequence(Sequence $sequence) : void /** * {@inheritdoc} + * + * @throws SchemaException */ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) : void { @@ -64,7 +67,8 @@ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkCons // RemoveNamespacedAssets#acceptTable call. Removing Foreign keys that // point to nowhere. if (! $this->schema->hasTable($fkConstraint->getForeignTableName())) { - $localTable->removeForeignKey($fkConstraint->getName()); + $this->removeForeignKey($localTable, $fkConstraint); + return; } @@ -73,6 +77,20 @@ public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkCons return; } - $localTable->removeForeignKey($fkConstraint->getName()); + $this->removeForeignKey($localTable, $fkConstraint); + } + + /** + * @throws SchemaException + */ + private function removeForeignKey(Table $table, ForeignKeyConstraint $constraint) : void + { + $name = $constraint->getName(); + + if ($name === null) { + throw SchemaException::namedForeignKeyRequired($table, $constraint); + } + + $table->removeForeignKey($name); } } diff --git a/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php index aaeb3060e4b..069ae52e9b1 100644 --- a/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php +++ b/lib/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Schema\ForeignKeyConstraint; use Doctrine\DBAL\Schema\Index; use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\SchemaException; use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\Visitor\Visitor; @@ -62,6 +63,8 @@ public function __construct(array $excludedTables = [], string $tenantColumnName /** * {@inheritdoc} + * + * @throws SchemaException */ public function acceptTable(Table $table) : void { @@ -82,9 +85,15 @@ public function acceptTable(Table $table) : void $table->dropPrimaryKey(); $table->setPrimaryKey($indexColumns); } else { - $table->dropIndex($clusteredIndex->getName()); - $table->addIndex($indexColumns, $clusteredIndex->getName()); - $table->getIndex($clusteredIndex->getName())->addFlag('clustered'); + $name = $clusteredIndex->getName(); + + if ($name === null) { + throw SchemaException::namedIndexRequired($table, $clusteredIndex); + } + + $table->dropIndex($name); + $table->addIndex($indexColumns, $name); + $table->getIndex($name)->addFlag('clustered'); } }