Skip to content

Commit

Permalink
Merge pull request #3311 from arnegroskurth/alter-pk-with-ai
Browse files Browse the repository at this point in the history
Fix: Ensuring correct ALTER TABLE statement for creation of an AUTO INCREMENT column as new PRIMARY KEY
  • Loading branch information
morozov committed Dec 7, 2018
2 parents 4b4d44f + 64790d4 commit f0e93fb
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
11 changes: 11 additions & 0 deletions lib/Doctrine/DBAL/Platforms/MySqlPlatform.php
Expand Up @@ -612,6 +612,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 = [];
Expand Down
@@ -0,0 +1,69 @@
<?php

namespace Doctrine\Tests\DBAL\Functional\Platform;

use Doctrine\DBAL\Schema\Comparator;
use Doctrine\Tests\DbalFunctionalTestCase;
use function in_array;

final class NewPrimaryKeyWithNewAutoIncrementColumnTest extends DbalFunctionalTestCase
{
/**
* {@inheritDoc}
*/
protected function setUp()
{
parent::setUp();

if (in_array($this->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();
}
}

0 comments on commit f0e93fb

Please sign in to comment.