diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 66f5e163b..8d33d3de5 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -762,7 +762,8 @@ abstract class AbstractPlatform public function getDecimalTypeDeclarationSql(array $columnDef) { $columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision'])) - ? 10 : $columnDef['precision']; + ? (( ! isset($columnDef['length']) || empty($columnDef['length'])) ? 10 : $columnDef['length']) + : $columnDef['precision']; $columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale'])) ? 0 : $columnDef['scale']; diff --git a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php index 29d6d7a07..34862550b 100644 --- a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -109,7 +109,7 @@ class MySqlSchemaManager extends AbstractSchemaManager $values = null; $scale = null; - + switch ($dbType) { case 'tinyint': $type = 'integer'; @@ -239,27 +239,24 @@ class MySqlSchemaManager extends AbstractSchemaManager 'unsigned' => (bool) $unsigned, 'fixed' => (bool) $fixed ); - if ($values !== null) { - $def['values'] = $values; - } + if ($scale !== null) { $def['scale'] = $scale; } - $values = isset($def['values']) ? $def['values'] : array(); + $values = ($values !== null) ? $values : array(); $column = array( 'name' => $tableColumn['Field'], 'values' => $values, 'primary' => (bool) (strtolower($tableColumn['Key']) == 'pri'), + 'unique' => (bool) (strtolower($tableColumn['Key']) == 'uni'), 'default' => $tableColumn['Default'], 'notnull' => (bool) ($tableColumn['Null'] != 'YES'), 'autoincrement' => (bool) (strpos($tableColumn['Extra'], 'auto_increment') !== false), ); - $column = array_merge($column, $def); - - return $column; + return array_merge($column, $def); } public function _getPortableTableForeignKeyDefinition($tableForeignKey) diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index 264a568a2..a0bf2ea82 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -628,11 +628,11 @@ final class ClassMetadata * @param string $fieldName The field name * @return boolean TRUE if the field is not null, FALSE otherwise. */ - public function isNotNull($fieldName) + public function isNullable($fieldName) { $mapping = $this->getFieldMapping($fieldName); if ($mapping !== false) { - return isset($mapping['nullable']) && $mapping['nullable'] == false; + return isset($mapping['nullable']) && $mapping['nullable'] == true; } return false; } diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index 96f28ea8d..38cd6f693 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -30,11 +30,13 @@ use Doctrine\Common\DoctrineException, * metadata mapping informations of a class which describes how a class should be mapped * to a relational database. * - * @author Roman Borschel - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @version $Revision$ - * @link www.doctrine-project.org - * @since 2.0 + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel */ class ClassMetadataFactory { diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 642619120..14e2824c7 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -169,8 +169,10 @@ class AnnotationDriver implements Driver $mapping['type'] = $columnAnnot->type; $mapping['length'] = $columnAnnot->length; + $mapping['fixed'] = $columnAnnot->fixed; $mapping['precision'] = $columnAnnot->precision; $mapping['scale'] = $columnAnnot->scale; + $mapping['unsigned'] = $columnAnnot->unsigned; $mapping['nullable'] = $columnAnnot->nullable; $mapping['options'] = $columnAnnot->options; $mapping['unique'] = $columnAnnot->unique; diff --git a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php index bcee0fc1f..692ce5636 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php +++ b/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php @@ -56,8 +56,10 @@ final class JoinColumns extends Annotation {} final class Column extends Annotation { public $type; public $length; + public $fixed = false; public $precision = 0; // The precision for a decimal (exact numeric) column (Applies only for decimal column) public $scale = 0; // The scale for a decimal (exact numeric) column (Applies only for decimal column) + public $unsigned = false; public $unique = false; public $nullable = false; public $default; diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php index acff179bf..aef30d2a0 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -125,6 +125,10 @@ class XmlDriver extends AbstractFileDriver $mapping['length'] = (int)$fieldMapping['length']; } + if (isset($fieldMapping['fixed'])) { + $mapping['fixed'] = (bool)$fieldMapping['fixed']; + } + if (isset($fieldMapping['precision'])) { $mapping['precision'] = (int)$fieldMapping['precision']; } @@ -133,6 +137,10 @@ class XmlDriver extends AbstractFileDriver $mapping['scale'] = (int)$fieldMapping['scale']; } + if (isset($fieldMapping['unsigned'])) { + $mapping['unsigned'] = (bool)$fieldMapping['unsigned']; + } + if (isset($fieldMapping['unique'])) { $mapping['unique'] = (bool)$fieldMapping['unique']; } diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index 8248ee370..53fe54ea9 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -128,6 +128,10 @@ class YamlDriver extends AbstractFileDriver $mapping['length'] = $fieldMapping['length']; } + if (isset($fieldMapping['fixed'])) { + $mapping['fixed'] = (bool)$fieldMapping['fixed']; + } + if (isset($fieldMapping['precision'])) { $mapping['precision'] = $fieldMapping['precision']; } @@ -136,6 +140,10 @@ class YamlDriver extends AbstractFileDriver $mapping['scale'] = $fieldMapping['scale']; } + if (isset($fieldMapping['unsigned'])) { + $mapping['unsigned'] = (bool)$fieldMapping['unsigned']; + } + if (isset($fieldMapping['unique'])) { $mapping['unique'] = (bool)$fieldMapping['unique']; } diff --git a/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php b/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php index 132dc0391..ddab5f68a 100644 --- a/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php +++ b/lib/Doctrine/ORM/Tools/Cli/Tasks/SchemaToolTask.php @@ -33,8 +33,13 @@ use Doctrine\Common\DoctrineException, * Specifies that the schema of the classes should be updated. * * - * @author robo - * @since 2.0 + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco + * @author Jonathan Wage + * @author Roman Borschel */ class SchemaToolTask extends AbstractTask { diff --git a/lib/Doctrine/ORM/Tools/SchemaTool.php b/lib/Doctrine/ORM/Tools/SchemaTool.php index 555058677..ac917031f 100644 --- a/lib/Doctrine/ORM/Tools/SchemaTool.php +++ b/lib/Doctrine/ORM/Tools/SchemaTool.php @@ -497,20 +497,95 @@ class SchemaTool $newClasses[] = $class; } else { $newFields = array(); + $updateFields = array(); + $dropIndexes = array(); $newJoinColumns = array(); $currentColumns = $sm->listTableColumns($tableName); - foreach ($class->fieldMappings as $fieldMapping) { + foreach ($class->fieldMappings as $fieldName => $fieldMapping) { $exists = false; foreach ($currentColumns as $index => $column) { if ($column['name'] == $fieldMapping['columnName']) { // Column exists, check for changes + $columnInfo = $column; + $columnChanged = false; + + echo $column['name'] . ' '; // 1. check for nullability change + $columnInfo['notnull'] = ( ! isset($columnInfo['notnull'])) + ? false : $columnInfo['notnull']; + $notnull = ! $class->isNullable($fieldName); + + if ($columnInfo['notnull'] != $notnull) { + $columnInfo['notnull'] = $notnull; + $columnChanged = true; + } + + unset($notnull); + // 2. check for uniqueness change - // 3. check for length change if type string - // 4. check for type change + $columnInfo['unique'] = ( ! isset($columnInfo['unique'])) + ? false : $columnInfo['unique']; + $unique = $class->isUniqueField($fieldName); + + if ($columnInfo['unique'] != $unique) { + // We need to call a special DROP INDEX if it was defined + if ($columnInfo['unique']) { + $dropIndexes[] = $column['name']; + } + + $columnInfo['unique'] = $unique; + $columnChanged = true; + } + + unset($unique); + + // 3. check for type change + $type = Type::getType($fieldMapping['type']); + + if ($columnInfo['type'] != $type) { + $columnInfo['type'] = $type; + $columnChanged = true; + } + + unset($type); + + // 4. check for length change + // 5. check for scale and precision change + /*if (isset($fieldMapping['scale'])) { + $columnInfo['length'] = $fieldMapping['precision']; + $columnInfo['scale'] = $fieldMapping['scale']; + } else { + $columnInfo['length'] = $fieldMapping['length']; + }*/ + + // 6. check for flexible and fixed length + $fieldMapping['fixed'] = ( ! isset($fieldMapping['fixed'])) + ? false : $fieldMapping['fixed']; + + if ($columnInfo['fixed'] != $fieldMapping['fixed']) { + $columnInfo['fixed'] = $fieldMapping['fixed']; + $columnChanged = true; + } + + // 7. check for unsigned change + $fieldMapping['unsigned'] = ( ! isset($fieldMapping['unsigned'])) + ? false : $fieldMapping['unsigned']; + + if ($columnInfo['unsigned'] != $fieldMapping['unsigned']) { + $columnInfo['unsigned'] = $fieldMapping['unsigned']; + $columnChanged = true; + } + + // Only add to column changed list if it was actually changed + if ($columnChanged) { + $updateFields[] = $columnInfo; + } + + //var_dump($columnInfo); + echo PHP_EOL . PHP_EOL; unset($currentColumns[$index]); $exists = true; @@ -550,6 +625,14 @@ class SchemaTool } } + // Drop indexes + if ($dropIndexes) { + foreach ($dropIndexes as $dropIndex) { + $sql[] = $this->_platform->getDropIndexSql($tableName, $dropIndex); + } + } + + // Create new columns if ($newFields || $newJoinColumns) { $changes = array(); @@ -565,6 +648,20 @@ class SchemaTool $sql[] = $this->_platform->getAlterTableSql($tableName, $changes); } + // Update existent columns + if ($updateFields) { + $changes = array(); + + foreach ($updateFields as $updateField) { + // Now we pick the Type instance + $changes['change'][$updateField['name']] = array( + 'definition' => $updateField + ); + } + + $sql[] = $this->_platform->getAlterTableSql($tableName, $changes); + } + // Drop any remaining columns if ($currentColumns) { $changes = array();