From cb6b4ebcdc3d935f5cb218199fce519055a9797f Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Tue, 24 Dec 2024 15:46:46 -0800 Subject: [PATCH 1/3] Do not index objects scoped to a table by name First, these keys are not used in the code. Second, they cause clashing between multiple unnamed unique constraints. --- src/Platforms/AbstractPlatform.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Platforms/AbstractPlatform.php b/src/Platforms/AbstractPlatform.php index 2c49c7d185..53679b8751 100644 --- a/src/Platforms/AbstractPlatform.php +++ b/src/Platforms/AbstractPlatform.php @@ -829,7 +829,7 @@ private function buildCreateTableSQL(Table $table, bool $createForeignKeys): arr foreach ($table->getIndexes() as $index) { if (! $index->isPrimary()) { - $options['indexes'][$index->getQuotedName($this)] = $index; + $options['indexes'][] = $index; continue; } @@ -839,7 +839,7 @@ private function buildCreateTableSQL(Table $table, bool $createForeignKeys): arr } foreach ($table->getUniqueConstraints() as $uniqueConstraint) { - $options['uniqueConstraints'][$uniqueConstraint->getQuotedName($this)] = $uniqueConstraint; + $options['uniqueConstraints'][] = $uniqueConstraint; } if ($createForeignKeys) { From baad09a1a37b86d7a0c1339f4809ab800e59d38e Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Wed, 25 Dec 2024 09:25:11 -0800 Subject: [PATCH 2/3] Use proper unnamed unique constraint DDL syntax --- src/Platforms/AbstractPlatform.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Platforms/AbstractPlatform.php b/src/Platforms/AbstractPlatform.php index 53679b8751..ea32cd4918 100644 --- a/src/Platforms/AbstractPlatform.php +++ b/src/Platforms/AbstractPlatform.php @@ -1170,8 +1170,13 @@ public function getCreateSchemaSQL(string $schemaName): string */ public function getCreateUniqueConstraintSQL(UniqueConstraint $constraint, string $tableName): string { - return 'ALTER TABLE ' . $tableName . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this) . ' UNIQUE' - . ' (' . implode(', ', $constraint->getQuotedColumns($this)) . ')'; + $sql = 'ALTER TABLE ' . $tableName . ' ADD'; + + if ($constraint->getName() !== '') { + $sql .= ' CONSTRAINT ' . $constraint->getQuotedName($this); + } + + return $sql . ' UNIQUE (' . implode(', ', $constraint->getQuotedColumns($this)) . ')'; } /** @@ -1546,9 +1551,10 @@ public function getUniqueConstraintDeclarationSQL(UniqueConstraint $constraint): throw new InvalidArgumentException('Incomplete definition. "columns" required.'); } - $chunks = ['CONSTRAINT']; + $chunks = []; if ($constraint->getName() !== '') { + $chunks[] = 'CONSTRAINT'; $chunks[] = $constraint->getQuotedName($this); } From 343f8a7422cbb01cfaf3c23b46fe0327bfa94660 Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Wed, 25 Dec 2024 09:21:06 -0800 Subject: [PATCH 3/3] Add unnamed constraint tests --- .../Schema/ForeignKeyConstraintTest.php | 49 +++++++++++++++++++ .../Schema/UniqueConstraintTest.php | 36 ++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 tests/Functional/Schema/ForeignKeyConstraintTest.php create mode 100644 tests/Functional/Schema/UniqueConstraintTest.php diff --git a/tests/Functional/Schema/ForeignKeyConstraintTest.php b/tests/Functional/Schema/ForeignKeyConstraintTest.php new file mode 100644 index 0000000000..49e57c299f --- /dev/null +++ b/tests/Functional/Schema/ForeignKeyConstraintTest.php @@ -0,0 +1,49 @@ +dropTableIfExists('users'); + $this->dropTableIfExists('roles'); + $this->dropTableIfExists('teams'); + + $roles = new Table('roles'); + $roles->addColumn('id', Types::INTEGER); + $roles->setPrimaryKey(['id']); + + $teams = new Table('teams'); + $teams->addColumn('id', Types::INTEGER); + $teams->setPrimaryKey(['id']); + + $users = new Table('users', [ + new Column('id', Type::getType(Types::INTEGER)), + new Column('role_id', Type::getType(Types::INTEGER)), + new Column('team_id', Type::getType(Types::INTEGER)), + ], [], [], [ + new ForeignKeyConstraint(['role_id'], 'roles', ['id']), + new ForeignKeyConstraint(['team_id'], 'teams', ['id']), + ]); + $users->setPrimaryKey(['id']); + + $sm = $this->connection->createSchemaManager(); + $sm->createTable($roles); + $sm->createTable($teams); + $sm->createTable($users); + + $table = $sm->introspectTable('users'); + + self::assertCount(2, $table->getForeignKeys()); + } +} diff --git a/tests/Functional/Schema/UniqueConstraintTest.php b/tests/Functional/Schema/UniqueConstraintTest.php new file mode 100644 index 0000000000..3c06427eb6 --- /dev/null +++ b/tests/Functional/Schema/UniqueConstraintTest.php @@ -0,0 +1,36 @@ +dropTableIfExists('users'); + + $users = new Table('users', [ + new Column('id', Type::getType(Types::INTEGER)), + new Column('username', Type::getType(Types::STRING), ['length' => 32]), + new Column('email', Type::getType(Types::STRING), ['length' => 255]), + ], [], [ + new UniqueConstraint('', ['username']), + new UniqueConstraint('', ['email']), + ], []); + + $sm = $this->connection->createSchemaManager(); + $sm->createTable($users); + + // we want to assert that the two empty names don't clash, but introspection of unique constraints is currently + // not supported. for now, we just assert that the table can be created without exceptions. + $this->expectNotToPerformAssertions(); + } +}