diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2023-07-24 14:44:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-24 14:44:37 +0200 |
commit | 7548e62181832dca36fa1a6ad4ec715d71fe83e6 (patch) | |
tree | 7e117e97a4f2cce7c2a5612002c61249c5536df6 | |
parent | 0411cc64aaaaa42ae23b4d5e216f16d481f20819 (diff) | |
parent | b80692d323ed2bedec5593fa7ae94fdd02d7186c (diff) | |
download | nextcloud-server-7548e62181832dca36fa1a6ad4ec715d71fe83e6.tar.gz nextcloud-server-7548e62181832dca36fa1a6ad4ec715d71fe83e6.zip |
Merge pull request #39506 from nextcloud/techdebt/39488/ensure-index-name-uniqueness
feat(db): Ensure that index names are unique across the database
-rw-r--r-- | lib/private/DB/MigrationService.php | 55 | ||||
-rw-r--r-- | tests/lib/DB/MigrationsTest.php | 4 |
2 files changed, 57 insertions, 2 deletions
diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index 3afe2f689f9..71d7b51d149 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -448,6 +448,7 @@ class MigrationService { if ($toSchema instanceof SchemaWrapper) { $targetSchema = $toSchema->getWrappedSchema(); + $this->ensureUniqueNamesConstraints($targetSchema); if ($this->checkOracle) { $beforeSchema = $this->connection->createSchema(); $this->ensureOracleConstraints($beforeSchema, $targetSchema, strlen($this->connection->getPrefix())); @@ -525,6 +526,7 @@ class MigrationService { if ($toSchema instanceof SchemaWrapper) { $targetSchema = $toSchema->getWrappedSchema(); + $this->ensureUniqueNamesConstraints($targetSchema); if ($this->checkOracle) { $sourceSchema = $this->connection->createSchema(); $this->ensureOracleConstraints($sourceSchema, $targetSchema, strlen($this->connection->getPrefix())); @@ -659,6 +661,59 @@ class MigrationService { } } + /** + * Naming constraints: + * - Index, sequence and primary key names must be unique within a Postgres Schema + * + * @param Schema $targetSchema + */ + public function ensureUniqueNamesConstraints(Schema $targetSchema): void { + $constraintNames = []; + + $sequences = $targetSchema->getSequences(); + + foreach ($targetSchema->getTables() as $table) { + foreach ($table->getIndexes() as $thing) { + $indexName = strtolower($thing->getName()); + if ($indexName === 'primary' || $thing->isPrimary()) { + continue; + } + + if (isset($constraintNames[$thing->getName()])) { + throw new \InvalidArgumentException('Index name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".'); + } + $constraintNames[$thing->getName()] = $table->getName(); + } + + foreach ($table->getForeignKeys() as $thing) { + if (isset($constraintNames[$thing->getName()])) { + throw new \InvalidArgumentException('Foreign key name "' . $thing->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".'); + } + $constraintNames[$thing->getName()] = $table->getName(); + } + + $primaryKey = $table->getPrimaryKey(); + if ($primaryKey instanceof Index) { + $indexName = strtolower($primaryKey->getName()); + if ($indexName === 'primary') { + continue; + } + + if (isset($constraintNames[$indexName])) { + throw new \InvalidArgumentException('Primary index name "' . $indexName . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".'); + } + $constraintNames[$indexName] = $table->getName(); + } + } + + foreach ($sequences as $sequence) { + if (isset($constraintNames[$sequence->getName()])) { + throw new \InvalidArgumentException('Sequence name "' . $sequence->getName() . '" for table "' . $table->getName() . '" collides with the constraint on table "' . $constraintNames[$thing->getName()] . '".'); + } + $constraintNames[$sequence->getName()] = 'sequence'; + } + } + private function ensureMigrationsAreLoaded() { if (empty($this->migrations)) { $this->migrations = $this->findMigrations(); diff --git a/tests/lib/DB/MigrationsTest.php b/tests/lib/DB/MigrationsTest.php index b7d49b565ac..d982a47623b 100644 --- a/tests/lib/DB/MigrationsTest.php +++ b/tests/lib/DB/MigrationsTest.php @@ -101,10 +101,10 @@ class MigrationsTest extends \Test\TestCase { ->method('migrateToSchema'); $wrappedSchema = $this->createMock(Schema::class); - $wrappedSchema->expects($this->once()) + $wrappedSchema->expects($this->exactly(2)) ->method('getTables') ->willReturn([]); - $wrappedSchema->expects($this->once()) + $wrappedSchema->expects($this->exactly(2)) ->method('getSequences') ->willReturn([]); |