. */ namespace Doctrine\DBAL\Schema; /** * Compare to Schemas and return an instance of SchemaDiff * * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. * @license http://ez.no/licenses/new_bsd New BSD License * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org * @since 2.0 * @version $Revision$ * @author Benjamin Eberlei */ class Comparator { /** * @param Schema $fromSchema * @param Schema $toSchema * @return SchemaDiff */ static public function compareSchemas( Schema $fromSchema, Schema $toSchema ) { $c = new self(); return $c->compare($fromSchema, $toSchema); } /** * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. * * The returned diferences are returned in such a way that they contain the * operations to change the schema stored in $fromSchema to the schema that is * stored in $toSchema. * * @param Schema $fromSchema * @param Schema $toSchema * * @return SchemaDiff */ public function compare( Schema $fromSchema, Schema $toSchema ) { $diff = new SchemaDiff(); foreach ( $toSchema->getTables() as $tableName => $table ) { if ( !$fromSchema->hasTable($tableName) ) { $diff->newTables[$tableName] = $table; } else { $tableDifferences = $this->diffTable( $fromSchema->getTable($tableName), $table ); if ( $tableDifferences !== false ) { $diff->changedTables[$tableName] = $tableDifferences; } } } /* Check if there are tables removed */ foreach ( $fromSchema->getTables() as $tableName => $table ) { if ( !$toSchema->hasTable($tableName) ) { $diff->removedTables[$tableName] = $table; } } // Todo add code for sequence diff return $diff; } /** * Returns the difference between the tables $table1 and $table2. * * If there are no differences this method returns the boolean false. * * @param Table $table1 * @param Table $table2 * * @return bool|TableDiff */ private function diffTable( Table $table1, Table $table2 ) { $changes = 0; $tableDifferences = new TableDiff(); /* See if all the fields in table 1 exist in table 2 */ foreach ( $table2->getColumns() as $columnName => $column ) { if ( !$table1->hasColumn($columnName) ) { $tableDifferences->addedFields[$columnName] = $column; $changes++; } } /* See if there are any removed fields in table 2 */ foreach ( $table1->getColumns() as $columnName => $column ) { if ( !$table2->hasColumn($columnName) ) { $tableDifferences->removedFields[$columnName] = true; $changes++; } } /* See if there are any changed fieldDefinitioninitions */ foreach ( $table1->getColumns() as $columnName => $column ) { if ( $table2->hasColumn($columnName) ) { $fieldDifferences = $this->diffField( $column, $table2->getColumn($columnName) ); if ( $fieldDifferences ) { $tableDifferences->changedFields[$columnName] = $fieldDifferences; $changes++; } } } $table1Indexes = $table1->getIndexes(); $table2Indexes = $table2->getIndexes(); /* See if all the indexes in table 1 exist in table 2 */ foreach ( $table2Indexes as $indexName => $indexDefinition ) { if ( !isset( $table1Indexes[$indexName] ) ) { $tableDifferences->addedIndexes[$indexName] = $indexDefinition; $changes++; } } /* See if there are any removed indexes in table 2 */ foreach ( $table1Indexes as $indexName => $indexDefinition ) { if ( !isset( $table2Indexes[$indexName] ) ) { $tableDifferences->removedIndexes[$indexName] = true; $changes++; } } /* See if there are any changed indexDefinitions */ foreach ( $table1Indexes as $indexName => $indexDefinition ) { if ( isset( $table2Indexes[$indexName] ) ) { $indexDifferences = $this->diffIndex( $indexDefinition, $table2Indexes[$indexName] ); if ( $indexDifferences ) { $tableDifferences->changedIndexes[$indexName] = $indexDifferences; $changes++; } } } // Todo add code for foreign key differences return $changes ? $tableDifferences : false; } /** * Returns the difference between the fields $field1 and $field2. * * If there are differences this method returns $field2, otherwise the * boolean false. * * @param Column $column1 * @param Column $column2 * * @return bool|Column */ private function diffField( Column $column1, Column $column2 ) { if ( $column1->getType() != $column2->getType() ) { return $column2; } return false; } /** * Finds the difference between the indexes $index1 and $index2. * * Compares $index1 with $index2 and returns $index2 if there are any * differences or false in case there are no differences. * * @param Index $index1 * @param Index $index2 * @return bool|Index */ private function diffIndex( Index $index1, Index $index2 ) { if($index1->isPrimary() != $index2->isPrimary()) { return $index2; } if($index1->isUnique() != $index2->isUnique()) { return $index2; } // Check for removed index fields in $index2 $index1Columns = $index1->getColumns(); for($i = 0; $i < count($index1Columns); $i++) { $indexColumn = $index1Columns[$i]; if (!$index2->hasColumnAtPosition($indexColumn, $i)) { return $index2; } } // Check for new index fields in $index2 $index2Columns = $index2->getColumns(); for($i = 0; $i < count($index2Columns); $i++) { $indexColumn = $index2Columns[$i]; if (!$index1->hasColumnAtPosition($indexColumn, $i)) { return $index2; } } return false; } }