From b35253a4c30a7d769559f5e23f04700b6883e05b Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 10 Mar 2022 10:24:05 +0100 Subject: [PATCH 1/2] Enforce primary keys as they are required to be performant in MySQL clusters Signed-off-by: Joas Schilling --- lib/private/DB/MigrationService.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/private/DB/MigrationService.php b/lib/private/DB/MigrationService.php index 6ad74a5859168..e7361cb4cab5e 100644 --- a/lib/private/DB/MigrationService.php +++ b/lib/private/DB/MigrationService.php @@ -634,6 +634,8 @@ public function ensureOracleConstraints(Schema $sourceSchema, Schema $targetSche if ($isUsingDefaultName && \strlen($table->getName()) - $prefixLength >= 23) { throw new \InvalidArgumentException('Primary index name on "' . $table->getName() . '" is too long.'); } + } elseif (!$primaryKey instanceof Index) { + throw new \InvalidArgumentException('Table "' . $table->getName() . '" has no primary key and therefor will not behave sane in clustered setups.'); } } From 1970d3dc9ab599e67ad1a0393fc5707ec283cf08 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 10 Mar 2022 14:04:04 +0100 Subject: [PATCH 2/2] Add a test for primary keys Signed-off-by: Joas Schilling --- tests/lib/DB/MigrationsTest.php | 44 ++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/tests/lib/DB/MigrationsTest.php b/tests/lib/DB/MigrationsTest.php index 507f3d0e228f9..f22de8c5e6ec1 100644 --- a/tests/lib/DB/MigrationsTest.php +++ b/tests/lib/DB/MigrationsTest.php @@ -246,6 +246,8 @@ public function testEnsureOracleConstraintsValid() { ->method('getName') ->willReturn(\str_repeat('a', 30)); + $primaryKey = $this->createMock(Index::class); + $table->expects($this->once()) ->method('getColumns') ->willReturn([$column]); @@ -257,7 +259,7 @@ public function testEnsureOracleConstraintsValid() { ->willReturn([$foreignKey]); $table->expects($this->once()) ->method('getPrimaryKey') - ->willReturn(null); + ->willReturn($primaryKey); $schema = $this->createMock(Schema::class); $schema->expects($this->once()) @@ -607,6 +609,46 @@ public function testEnsureOracleConstraintsTooLongForeignKeyName() { } + public function testEnsureOracleConstraintsNoPrimaryKey() { + $this->expectException(\InvalidArgumentException::class); + + $table = $this->createMock(Table::class); + $table->expects($this->atLeastOnce()) + ->method('getName') + ->willReturn(\str_repeat('a', 30)); + $table->expects($this->once()) + ->method('getColumns') + ->willReturn([]); + $table->expects($this->once()) + ->method('getIndexes') + ->willReturn([]); + $table->expects($this->once()) + ->method('getForeignKeys') + ->willReturn([]); + $table->expects($this->once()) + ->method('getPrimaryKey') + ->willReturn(null); + + $schema = $this->createMock(Schema::class); + $schema->expects($this->once()) + ->method('getTables') + ->willReturn([$table]); + $schema->expects($this->once()) + ->method('getSequences') + ->willReturn([]); + + $sourceSchema = $this->createMock(Schema::class); + $sourceSchema->expects($this->any()) + ->method('getTable') + ->willThrowException(new SchemaException()); + $sourceSchema->expects($this->any()) + ->method('hasSequence') + ->willReturn(false); + + self::invokePrivate($this->migrationService, 'ensureOracleConstraints', [$sourceSchema, $schema, 3]); + } + + public function testEnsureOracleConstraintsTooLongSequenceName() { $this->expectException(\InvalidArgumentException::class);