Skip to content

Commit

Permalink
[DDC-1657] Prevent autoincrement sequences from creating DROP SEQUENC…
Browse files Browse the repository at this point in the history
…E statements because of old/new schema missmatch.
  • Loading branch information
beberlei committed Jul 8, 2012
1 parent 78dbf28 commit 79e894b
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 4 deletions.
16 changes: 16 additions & 0 deletions lib/Doctrine/DBAL/Schema/Comparator.php
Expand Up @@ -110,7 +110,12 @@ public function compare(Schema $fromSchema, Schema $toSchema)
}

foreach ($fromSchema->getSequences() as $sequence) {
if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) {
continue;
}

$sequenceName = $sequence->getShortestName($fromSchema->getName());

if ( ! $toSchema->hasSequence($sequenceName)) {
$diff->removedSequences[] = $sequence;
}
Expand All @@ -119,6 +124,17 @@ public function compare(Schema $fromSchema, Schema $toSchema)
return $diff;
}

private function isAutoIncrementSequenceInSchema($schema, $sequence)
{
foreach ($schema->getTables() as $table) {
if ($sequence->isAutoIncrementsFor($table)) {
return true;
}
}

return false;
}

/**
*
* @param Sequence $sequence1
Expand Down
1 change: 1 addition & 0 deletions lib/Doctrine/DBAL/Schema/Schema.php
Expand Up @@ -87,6 +87,7 @@ public function __construct(array $tables=array(), array $sequences=array(), Sch
foreach ($tables as $table) {
$this->_addTable($table);
}

foreach ($sequences as $sequence) {
$this->_addSequence($sequence);
}
Expand Down
37 changes: 35 additions & 2 deletions lib/Doctrine/DBAL/Schema/Sequence.php
@@ -1,7 +1,5 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Expand Down Expand Up @@ -77,6 +75,41 @@ public function setInitialValue($initialValue)
$this->_initialValue = (is_numeric($initialValue))?$initialValue:1;
}

/**
* Check if this sequence is an autoincrement sequence for a given table.
*
* This is used inside the comparator to not report sequences as missing,
* when the "from" schema implicitly creates the sequences.
*
* @param Table $table
*
* @return bool
*/
public function isAutoIncrementsFor(Table $table)
{
if ( ! $table->hasPrimaryKey()) {
return false;
}

$pkColumns = $table->getPrimaryKey()->getColumns();

if (count($pkColumns) != 1) {
return false;
}

$column = $table->getColumn($pkColumns[0]);

if ( ! $column->getAutoincrement()) {
return false;
}

$sequenceName = $this->getShortestName($table->getNamespaceName());
$tableName = $table->getShortestName($table->getNamespaceName());
$tableSequenceName = sprintf('%s_%s_seq', $tableName, $pkColumns[0]);

return $tableSequenceName === $sequenceName;
}

/**
* @param Visitor $visitor
*/
Expand Down
8 changes: 8 additions & 0 deletions lib/Doctrine/DBAL/Schema/Table.php
Expand Up @@ -565,6 +565,14 @@ public function getPrimaryKey()
return $this->getIndex($this->_primaryKeyName);
}

public function getPrimaryKeyColumns()
{
if ( ! $this->hasPrimaryKey()) {
throw new DBALException("Table " . $this->getName() . " has no primary key.");
}
return $this->getPrimaryKey()->getColumns();
}

/**
* Check if this table has a primary key.
*
Expand Down
22 changes: 22 additions & 0 deletions tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php
Expand Up @@ -759,6 +759,28 @@ public function testFqnSchemaComparisionNoSchemaSame()
$this->assertEquals(new SchemaDiff(), $c->compare($oldSchema, $newSchema));
}

/**
* @group DDC-1657
*/
public function testAutoIncremenetSequences()
{
$oldSchema = new Schema();
$table = $oldSchema->createTable("foo");
$table->addColumn("id", "integer", array("autoincrement" => true));
$table->setPrimaryKey(array("id"));
$oldSchema->createSequence("foo_id_seq");

$newSchema = new Schema();
$table = $newSchema->createTable("foo");
$table->addColumn("id", "integer", array("autoincrement" => true));
$table->setPrimaryKey(array("id"));

$c = new Comparator();
$diff = $c->compare($oldSchema, $newSchema);

$this->assertCount(0, $diff->removedSequences);
}

/**
* @param SchemaDiff $diff
* @param int $newTableCount
Expand Down
28 changes: 28 additions & 0 deletions tests/Doctrine/Tests/DBAL/Schema/SequenceTest.php
@@ -0,0 +1,28 @@
<?php

namespace Doctrine\Tests\DBAL\Schema;

use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Sequence;

class SequenceTest extends \Doctrine\Tests\DbalTestCase
{
/**
* @group DDC-1657
*/
public function testIsAutoincrementFor()
{
$table = new Table("foo");
$table->addColumn("id", "integer", array("autoincrement" => true));
$table->setPrimaryKey(array("id"));

$sequence = new Sequence("foo_id_seq");
$sequence2 = new Sequence("bar_id_seq");
$sequence3 = new Sequence("other.foo_id_seq");

$this->assertTrue($sequence->isAutoIncrementsFor($table));
$this->assertFalse($sequence2->isAutoIncrementsFor($table));
$this->assertFalse($sequence3->isAutoIncrementsFor($table));
}
}

2 changes: 0 additions & 2 deletions tests/Doctrine/Tests/DBAL/Schema/TableTest.php
Expand Up @@ -2,8 +2,6 @@

namespace Doctrine\Tests\DBAL\Schema;

require_once __DIR__ . '/../../TestInit.php';

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableBuilder;
Expand Down

0 comments on commit 79e894b

Please sign in to comment.