From 64790d4d2e5608cdaede6eb6851894ebc45bc83f Mon Sep 17 00:00:00 2001 From: Arne Groskurth Date: Thu, 6 Dec 2018 22:08:03 +0100 Subject: [PATCH] Ensuring correct ALTER TABLE statement for creation of an AUTO INCREMENT column as new PRIMARY KEY --- lib/Doctrine/DBAL/Platforms/MySqlPlatform.php | 11 +++ ...imaryKeyWithNewAutoIncrementColumnTest.php | 69 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 tests/Doctrine/Tests/DBAL/Functional/Platform/NewPrimaryKeyWithNewAutoIncrementColumnTest.php diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 744aa08a4bd..059535640e1 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -599,6 +599,17 @@ public function getAlterTableSQL(TableDiff $diff) $keyColumns = array_unique(array_values($diff->addedIndexes['primary']->getColumns())); $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; unset($diff->addedIndexes['primary']); + } elseif (isset($diff->changedIndexes['primary'])) { + // Necessary in case the new primary key includes a new auto_increment column + foreach ($diff->changedIndexes['primary']->getColumns() as $columnName) { + if (isset($diff->addedColumns[$columnName]) && $diff->addedColumns[$columnName]->getAutoincrement()) { + $keyColumns = array_unique(array_values($diff->changedIndexes['primary']->getColumns())); + $queryParts[] = 'DROP PRIMARY KEY'; + $queryParts[] = 'ADD PRIMARY KEY (' . implode(', ', $keyColumns) . ')'; + unset($diff->changedIndexes['primary']); + break; + } + } } $sql = []; diff --git a/tests/Doctrine/Tests/DBAL/Functional/Platform/NewPrimaryKeyWithNewAutoIncrementColumnTest.php b/tests/Doctrine/Tests/DBAL/Functional/Platform/NewPrimaryKeyWithNewAutoIncrementColumnTest.php new file mode 100644 index 00000000000..ec387638c40 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Functional/Platform/NewPrimaryKeyWithNewAutoIncrementColumnTest.php @@ -0,0 +1,69 @@ +getPlatform()->getName(), ['mysql'])) { + return; + } + + $this->markTestSkipped('Restricted to MySQL.'); + } + + /** + * Ensures that the primary key is created within the same "alter table" statement that an auto-increment column + * is added to the table as part of the new primary key. + * + * Before the fix for this problem this resulted in a database error: (at least on mysql) + * SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definition; there can be only one auto + * column and it must be defined as a key + */ + public function testAlterPrimaryKeyToAutoIncrementColumn() + { + $schemaManager = $this->connection->getSchemaManager(); + $schema = $schemaManager->createSchema(); + + $table = $schema->createTable('dbal2807'); + $table->addColumn('initial_id', 'integer'); + $table->setPrimaryKey(['initial_id']); + + $schemaManager->dropAndCreateTable($table); + + $newSchema = clone $schema; + $newTable = $newSchema->getTable($table->getName()); + $newTable->addColumn('new_id', 'integer', ['autoincrement' => true]); + $newTable->dropPrimaryKey(); + $newTable->setPrimaryKey(['new_id']); + + $diff = (new Comparator())->compare($schema, $newSchema); + + foreach ($diff->toSql($this->getPlatform()) as $sql) { + $this->connection->exec($sql); + } + + $validationSchema = $schemaManager->createSchema(); + $validationTable = $validationSchema->getTable($table->getName()); + + $this->assertTrue($validationTable->hasColumn('new_id')); + $this->assertTrue($validationTable->getColumn('new_id')->getAutoincrement()); + $this->assertTrue($validationTable->hasPrimaryKey()); + $this->assertSame(['new_id'], $validationTable->getPrimaryKeyColumns()); + } + + private function getPlatform() + { + return $this->connection->getDatabasePlatform(); + } +}