From 8bfde413742595fe621aadbbf1df80db9abd96c4 Mon Sep 17 00:00:00 2001 From: beberlei Date: Sat, 5 Dec 2009 15:48:54 +0000 Subject: [PATCH] [2.0] DDC-169 - Add ColumnDiff and further Comparator column stuff --- lib/Doctrine/DBAL/Schema/Column.php | 41 +++++++++++++- lib/Doctrine/DBAL/Schema/ColumnDiff.php | 55 +++++++++++++++++++ lib/Doctrine/DBAL/Schema/Comparator.php | 43 ++++++++------- lib/Doctrine/DBAL/Schema/TableDiff.php | 13 ++++- .../Tests/DBAL/Schema/ComparatorTest.php | 16 +++--- 5 files changed, 138 insertions(+), 30 deletions(-) create mode 100644 lib/Doctrine/DBAL/Schema/ColumnDiff.php diff --git a/lib/Doctrine/DBAL/Schema/Column.php b/lib/Doctrine/DBAL/Schema/Column.php index c0d98ad34..c2730d7c8 100644 --- a/lib/Doctrine/DBAL/Schema/Column.php +++ b/lib/Doctrine/DBAL/Schema/Column.php @@ -33,7 +33,7 @@ use Doctrine\DBAL\Schema\Visitor\Visitor; * @version $Revision$ * @author Benjamin Eberlei */ -class Column extends AbstractAsset +class Column extends AbstractAsset implements \ArrayAccess { /** * @var \Doctrine\DBAL\Types\Type @@ -288,4 +288,43 @@ class Column extends AbstractAsset { $visitor->accept($this); } + + /** + * @param string $option + * @return mixed + */ + public function offsetExists($option) + { + return (\property_exists($this, "_".$option) || $this->hasPlatformOption($option)); + } + + /** + * @param string $option + * @return mixed + */ + public function offsetGet($option) + { + $optionAccessor = "_".$option; + if(\property_exists($this, $optionAccessor)) { + return $this->$optionAccessor; + } else if($this->hasPlatformOption($option)) { + return $this->getPlatformOption($option); + } else { + return false; + } + } + + public function offsetSet($offset, $value) + { + throw new \BadMethodCallException( + "Setting column property ".$this->_name."::".$offset." through the ArrayAccess interface is not allowed." + ); + } + + public function offsetUnset($offset) + { + throw new \BadMethodCallException( + "Unsetting column property ".$this->_name."::".$offset." through the ArrayAccess interface is not allowed." + ); + } } \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Schema/ColumnDiff.php b/lib/Doctrine/DBAL/Schema/ColumnDiff.php new file mode 100644 index 000000000..29caab370 --- /dev/null +++ b/lib/Doctrine/DBAL/Schema/ColumnDiff.php @@ -0,0 +1,55 @@ +. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Represent the change of a column + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei + */ +class ColumnDiff +{ + /** + * @var Column + */ + public $column; + + /** + * @var array + */ + public $changedProperties = array(); + + public function __construct(Column $column, array $changedProperties = array()) + { + $this->column = $column; + $this->changedProperties = $changedProperties; + } + + public function hasChanged($propertyName) + { + return in_array($propertyName, $this->changedProperties); + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Schema/Comparator.php b/lib/Doctrine/DBAL/Schema/Comparator.php index ae91f9236..88206371c 100644 --- a/lib/Doctrine/DBAL/Schema/Comparator.php +++ b/lib/Doctrine/DBAL/Schema/Comparator.php @@ -142,7 +142,7 @@ class Comparator public function diffTable( Table $table1, Table $table2 ) { $changes = 0; - $tableDifferences = new TableDiff(); + $tableDifferences = new TableDiff($table1->getName()); $table1Columns = $table1->getColumns(); $table2Columns = $table2->getColumns(); @@ -164,8 +164,10 @@ class Comparator /* See if there are any changed fieldDefinitioninitions */ foreach ( $table1Columns as $columnName => $column ) { if ( $table2->hasColumn($columnName) ) { - if ( $this->diffColumn( $column, $table2->getColumn($columnName) ) ) { - $tableDifferences->changedColumns[$column->getName()] = $table2->getColumn($columnName); + $changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) ); + if (count($changedProperties) ) { + $columnDiff = new ColumnDiff($table2->getColumn($columnName), $changedProperties); + $tableDifferences->changedColumns[$column->getName()] = $columnDiff; $changes++; } } @@ -174,7 +176,7 @@ class Comparator // Try to find columns that only changed their name, rename operations maybe cheaper than add/drop foreach ($tableDifferences->addedColumns AS $addedColumnName => $addedColumn) { foreach ($tableDifferences->removedColumns AS $removedColumnName => $removedColumn) { - if ($this->diffColumn($addedColumn, $removedColumn) === false) { + if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) { $tableDifferences->renamedColumns[$removedColumn->getName()] = $addedColumn; unset($tableDifferences->addedColumns[$addedColumnName]); unset($tableDifferences->removedColumns[$removedColumnName]); @@ -286,56 +288,57 @@ class Comparator * @param Column $column1 * @param Column $column2 * - * @return bool + * @return array */ public function diffColumn( Column $column1, Column $column2 ) { + $changedProperties = array(); if ( $column1->getType() != $column2->getType() ) { - return true; + $changedProperties[] = 'type'; } if ($column1->getNotnull() != $column2->getNotnull()) { - return true; + $changedProperties[] = 'notnull'; } if ($column1->getDefault() != $column2->getDefault()) { - return true; + $changedProperties[] = 'default'; } if ($column1->getUnsigned() != $column2->getUnsigned()) { - return true; + $changedProperties[] = 'unsigned'; } if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) { if ($column1->getLength() != $column2->getLength()) { - return true; + $changedProperties[] = 'length'; } if ($column1->getFixed() != $column2->getFixed()) { - return true; + $changedProperties[] = 'fixed'; } } if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) { if ($column1->getPrecision() != $column2->getPrecision()) { - return true; + $changedProperties[] = 'precision'; } if ($column1->getScale() != $column2->getScale()) { - return true; + $changedProperties[] = 'scale'; } } foreach ($this->_checkColumnPlatformOptions AS $optionName) { - if ($column1->hasPlatformOption($optionName) != $column2->hasPlatformOption($optionName)) { - return true; - } - - if ($column1->getPlatformOption($optionName) != $column2->getPlatformOption($optionName)) { - return true; + if($column1->hasPlatformOption($optionName) && $column2->hasPlatformOption($optionName)) { + if ($column1->getPlatformOption($optionName) != $column2->getPlatformOption($optionName)) { + $changedProperties[] = $optionName; + } + } else if ($column1->hasPlatformOption($optionName) != $column2->hasPlatformOption($optionName)) { + $changedProperties[] = $optionName; } } - return false; + return $changedProperties; } /** diff --git a/lib/Doctrine/DBAL/Schema/TableDiff.php b/lib/Doctrine/DBAL/Schema/TableDiff.php index c8351c2e8..83e2cab9e 100644 --- a/lib/Doctrine/DBAL/Schema/TableDiff.php +++ b/lib/Doctrine/DBAL/Schema/TableDiff.php @@ -34,6 +34,16 @@ namespace Doctrine\DBAL\Schema; */ class TableDiff { + /** + * @var string + */ + public $name = null; + + /** + * @var string + */ + public $newName = false; + /** * All added fields * @@ -114,10 +124,11 @@ class TableDiff * @param array(string=>Index) $changedIndexes * @param array(string=>bool) $removedIndexes */ - function __construct( $addedColumns = array(), $changedColumns = array(), + function __construct( $tableName, $addedColumns = array(), $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), $changedIndexes = array(), $removedIndexes = array() ) { + $this->name = $tableName; $this->addedColumns = $addedColumns; $this->changedColumns = $changedColumns; $this->removedColumns = $removedColumns; diff --git a/tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php b/tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php index a8daf00b3..c806c4e27 100644 --- a/tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php +++ b/tests/Doctrine/Tests/DBAL/Schema/ComparatorTest.php @@ -152,7 +152,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff( array(), array(), + 'bugdb' => new TableDiff( 'bugdb', array(), array(), array ( 'integerfield1' => $missingColumn, ) @@ -182,7 +182,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff ( + 'bugdb' => new TableDiff ('bugdb', array ( 'integerfield2' => new Column('integerfield2', Type::getType('integer')), ) @@ -198,8 +198,8 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $column2 = new Column('charfield1', Type::getType('integer')); $c = new Comparator(); - $this->assertTrue($c->diffColumn($column1, $column2)); - $this->assertFalse($c->diffColumn($column1, $column1)); + $this->assertEquals(array('type'), $c->diffColumn($column1, $column2)); + $this->assertEquals(array(), $c->diffColumn($column1, $column1)); } public function testCompareRemovedIndex() @@ -231,7 +231,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff( array(), array(), array(), array(), array(), + 'bugdb' => new TableDiff( 'bugdb', array(), array(), array(), array(), array(), array ( 'primary' => true ) @@ -270,7 +270,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff( array(), array(), array(), + 'bugdb' => new TableDiff( 'bugdb', array(), array(), array(), array ( 'primary' => new Index('primary', array( @@ -320,7 +320,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff( array(), array(), array(), array(), + 'bugdb' => new TableDiff( 'bugdb', array(), array(), array(), array(), array ( 'primary' => new Index('primary', array( @@ -364,7 +364,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase $expected = new SchemaDiff ( array(), array ( - 'bugdb' => new TableDiff( array(), array(), array(), array(), + 'bugdb' => new TableDiff('bugdb', array(), array(), array(), array(), array ( 'primary' => new Index('primary', array('integerfield2', 'integerfield1'), true) )