1
0
mirror of synced 2024-12-13 06:46:03 +03:00

[2.0] DDC-169 - AbstractPlatform::getAlterTableSql() now accepts only a TableDiff instance as argument across all platforms.

This commit is contained in:
beberlei 2009-12-06 09:47:54 +00:00
parent 4736f5ee50
commit dd6abf751f
10 changed files with 172 additions and 313 deletions

View File

@ -26,7 +26,8 @@ use Doctrine\DBAL\DBALException,
Doctrine\DBAL\Types,
Doctrine\DBAL\Schema\Table,
Doctrine\DBAL\Schema\Index,
Doctrine\DBAL\Schema\ForeignKeyConstraint;
Doctrine\DBAL\Schema\ForeignKeyConstraint,
Doctrine\DBAL\Schema\TableDiff;
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
@ -785,14 +786,10 @@ abstract class AbstractPlatform
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSql($name, array $changes, $check = false)
public function getAlterTableSql(TableDiff $diff)
{
throw DBALException::notSupported(__METHOD__);
}

View File

@ -21,6 +21,8 @@
namespace Doctrine\DBAL\Platforms;
use \Doctrine\DBAL\Schema\TableDiff;
use Doctrine\Common\DoctrineException;
/**
@ -93,91 +95,41 @@ class MsSqlPlatform extends AbstractPlatform
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param string $name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSql($name, array $changes, $check = false)
public function getAlterTableSql(TableDiff $diff)
{
foreach ($changes as $changeName => $change) {
switch ($changeName) {
case 'add':
case 'remove':
case 'change':
case 'rename':
case 'name':
break;
default:
throw \Doctrine\Common\DoctrineException::alterTableChangeNotSupported($changeName);
}
$queryParts = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
$query = '';
if ( ! empty($changes['name'])) {
$change_name = $changes['name'];
$query .= 'RENAME TO ' . $change_name;
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
if ( ! empty($changes['add']) && is_array($changes['add'])) {
foreach ($changes['add'] as $fieldName => $field) {
if ($query) {
$query .= ', ';
}
$query .= 'ADD ' . $this->getColumnDeclarationSql($fieldName, $field);
}
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP ' . $column->getName();
}
if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $fieldName => $field) {
if ($query) {
$query .= ', ';
}
$query .= 'DROP COLUMN ' . $fieldName;
}
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
$rename = array();
if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
foreach ($changes['rename'] as $fieldName => $field) {
$rename[$field['name']] = $fieldName;
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
. $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
if ( ! empty($changes['change']) && is_array($changes['change'])) {
foreach ($changes['change'] as $fieldName => $field) {
if ($query) {
$query.= ', ';
}
if (isset($rename[$fieldName])) {
$oldFieldName = $rename[$fieldName];
unset($rename[$fieldName]);
} else {
$oldFieldName = $fieldName;
}
$query .= 'CHANGE ' . $oldFieldName . ' '
. $this->getColumnDeclarationSql($fieldName, $field['definition']);
}
}
if ( ! empty($rename) && is_array($rename)) {
foreach ($rename as $renameName => $renamedField) {
if ($query) {
$query.= ', ';
}
$field = $changes['rename'][$renamedField];
$query .= 'CHANGE ' . $renamedField . ' '
. $this->getColumnDeclarationSql($field['name'], $field['definition']);
}
}
if ( ! $query) {
if (count($queryParts) == 0) {
return false;
}
return array('ALTER TABLE ' . $name . ' ' . $query);
return array('ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts));
}
/**

View File

@ -21,7 +21,8 @@
namespace Doctrine\DBAL\Platforms;
use Doctrine\Common\DoctrineException;
use Doctrine\Common\DoctrineException,
Doctrine\DBAL\Schema\TableDiff;
/**
* The MySqlPlatform provides the behavior, features and SQL dialect of the
@ -592,91 +593,38 @@ class MySqlPlatform extends AbstractPlatform
* @return boolean
* @override
*/
public function getAlterTableSql($name, array $changes, $check = false)
public function getAlterTableSql(TableDiff $diff)
{
if ( ! $name) {
throw DoctrineException::missingTableName();
$queryParts = array();
if ($diff->newName !== false) {
$queryParts[] = 'RENAME TO ' . $diff->newName;
}
foreach ($changes as $changeName => $change) {
switch ($changeName) {
case 'add':
case 'remove':
case 'change':
case 'rename':
case 'name':
break;
default:
throw \Doctrine\Common\DoctrineException::alterTableChangeNotSupported($changeName);
}
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD ' . $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
if ($check) {
return true;
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP ' . $column->getName();
}
$query = '';
if ( ! empty($changes['name'])) {
$query .= 'RENAME TO ' . $changes['name'];
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
if ( ! empty($changes['add']) && is_array($changes['add'])) {
foreach ($changes['add'] as $fieldName => $field) {
if ($query) {
$query.= ', ';
}
$query.= 'ADD ' . $this->getColumnDeclarationSql($fieldName, $field);
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'CHANGE ' . $oldColumnName . ' '
. $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $fieldName => $field) {
if ($query) {
$query .= ', ';
}
$query .= 'DROP ' . $fieldName;
}
}
$rename = array();
if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
foreach ($changes['rename'] as $fieldName => $field) {
$rename[$field['name']] = $fieldName;
}
}
if ( ! empty($changes['change']) && is_array($changes['change'])) {
foreach ($changes['change'] as $fieldName => $field) {
if ($query) {
$query.= ', ';
}
if (isset($rename[$fieldName])) {
$oldFieldName = $rename[$fieldName];
unset($rename[$fieldName]);
} else {
$oldFieldName = $fieldName;
}
$query .= 'CHANGE ' . $oldFieldName . ' '
. $this->getColumnDeclarationSql($fieldName, $field['definition']);
}
}
if ( ! empty($rename) && is_array($rename)) {
foreach ($rename as $renameName => $renamedField) {
if ($query) {
$query.= ', ';
}
$field = $changes['rename'][$renamedField];
$query .= 'CHANGE ' . $renamedField . ' '
. $this->getColumnDeclarationSql($field['name'], $field['definition']);
}
}
if ( ! $query) {
if (count($queryParts) == 0) {
return false;
}
return array('ALTER TABLE ' . $name . ' ' . $query);
return array('ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts));
}
/**

View File

@ -21,6 +21,8 @@
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
/**
* OraclePlatform.
*
@ -466,69 +468,48 @@ END;';
*
* The method returns an array of sql statements, since some platforms need several statements.
*
* @param string $name name of the table that is intended to be changed.
* @param string $diff->name name of the table that is intended to be changed.
* @param array $changes associative array that contains the details of each type *
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return array
*/
public function getAlterTableSql($name, array $changes, $check = false)
public function getAlterTableSql(TableDiff $diff)
{
if ( ! $name) {
throw DoctrineException::missingTableName();
$sql = array();
$fields = array();
foreach ($diff->addedColumns AS $column) {
$fields[] = $this->getColumnDeclarationSql($column->getName(), $column->toArray());
}
foreach ($changes as $changeName => $change) {
switch ($changeName) {
case 'add':
case 'remove':
case 'change':
case 'name':
case 'rename':
break;
default:
throw \Doctrine\Common\DoctrineException::alterTableChangeNotSupported($changeName);
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')';
}
if ($check) {
return false;
$fields = array();
foreach ($diff->changedColumns AS $columnDiff) {
$column = $columnDiff->column;
$fields[] = $column->getName(). ' ' . $this->getColumnDeclarationSql('', $column->toArray());
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')';
}
if ( ! empty($changes['add']) && is_array($changes['add'])) {
$fields = array();
foreach ($changes['add'] as $fieldName => $field) {
$fields[] = $this->getColumnDeclarationSql($fieldName, $field);
}
$sql[] = 'ALTER TABLE ' . $name . ' ADD (' . implode(', ', $fields) . ')';
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getName();
}
if ( ! empty($changes['change']) && is_array($changes['change'])) {
$fields = array();
foreach ($changes['change'] as $fieldName => $field) {
$fields[] = $fieldName. ' ' . $this->getColumnDeclarationSql('', $field['definition']);
}
$sql[] = 'ALTER TABLE ' . $name . ' MODIFY (' . implode(', ', $fields) . ')';
$fields = array();
foreach ($diff->removedColumns AS $column) {
$fields[] = $column->getName();
}
if (count($fields)) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' DROP COLUMN ' . implode(', ', $fields);
}
if ( ! empty($changes['rename']) && is_array($changes['rename'])) {
foreach ($changes['rename'] as $fieldName => $field) {
$sql[] = 'ALTER TABLE ' . $name . ' RENAME COLUMN ' . $fieldName
. ' TO ' . $field['name'];
}
}
if ( ! empty($changes['remove']) && is_array($changes['remove'])) {
$fields = array();
foreach ($changes['remove'] as $fieldName => $field) {
$fields[] = $fieldName;
}
$sql[] = 'ALTER TABLE ' . $name . ' DROP COLUMN ' . implode(', ', $fields);
}
if ( ! empty($changes['name'])) {
$changeName = $changes['name'];
$sql[] = 'ALTER TABLE ' . $name . ' RENAME TO ' . $changeName;
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
return $sql;

View File

@ -21,6 +21,8 @@
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\TableDiff;
/**
* PostgreSqlPlatform.
*
@ -489,70 +491,47 @@ class PostgreSqlPlatform extends AbstractPlatform
* @return array
* @override
*/
public function getAlterTableSql($name, array $changes, $check = false)
public function getAlterTableSql(TableDiff $diff)
{
foreach ($changes as $changeName => $change) {
switch ($changeName) {
case 'add':
case 'remove':
case 'change':
case 'name':
case 'rename':
break;
default:
throw DoctrineException::alterTableChangeNotSupported($changeName);
}
}
if ($check) {
return true;
}
$sql = array();
if (isset($changes['add']) && is_array($changes['add'])) {
foreach ($changes['add'] as $fieldName => $field) {
$query = 'ADD ' . $this->getColumnDeclarationSql($fieldName, $field);
$sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
foreach ($diff->addedColumns as $column) {
$query = 'ADD ' . $this->getColumnDeclarationSql($column->getName(), $column->toArray());
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
foreach ($diff->removedColumns as $column) {
$query = 'DROP ' . $column->getName();
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
foreach ($diff->changedColumns AS $columnDiff) {
$oldColumnName = $columnDiff->oldColumnName;
$column = $columnDiff->column;
if ($columnDiff->hasChanged('type')) {
$type = $column->getType();
// here was a server version check before, but DBAL API does not support this anymore.
$query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this);
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('default')) {
$query = 'ALTER ' . $oldColumnName . ' SET DEFAULT ' . $column->getDefault();
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
if ($columnDiff->hasChanged('notnull')) {
$query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL';
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query;
}
}
if (isset($changes['remove']) && is_array($changes['remove'])) {
foreach ($changes['remove'] as $fieldName => $field) {
$query = 'DROP ' . $fieldName;
$sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
}
foreach ($diff->renamedColumns as $oldColumnName => $column) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getName();
}
if (isset($changes['change']) && is_array($changes['change'])) {
foreach ($changes['change'] as $fieldName => $field) {
if (isset($field['definition']['type']) && $field['definition']['type'] instanceof \Doctrine\DBAL\Types\Type) {
$type = $field['definition']['type'];
// here was a server version check before, but DBAL API does not support this anymore.
$query = 'ALTER ' . $fieldName . ' TYPE ' . $type->getSqlDeclaration($field['definition'], $this);
$sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
}
if (isset($field['definition']['default'])) {
$query = 'ALTER ' . $fieldName . ' SET DEFAULT ' . $field['definition']['default'];
$sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
}
if (isset($field['definition']['notnull']) && is_bool($field['definition']['notnull'])) {
$query = 'ALTER ' . $fieldName . ' ' . ($field['definition']['notnull'] ? 'SET' : 'DROP') . ' NOT NULL';
$sql[] = 'ALTER TABLE ' . $name . ' ' . $query;
}
}
}
if (isset($changes['rename']) && is_array($changes['rename'])) {
foreach ($changes['rename'] as $fieldName => $field) {
$sql[] = 'ALTER TABLE ' . $name . ' RENAME COLUMN ' . $fieldName . ' TO ' . $field['name'];
}
}
if (isset($changes['name'])) {
$sql[] = 'ALTER TABLE ' . $name . ' RENAME TO ' . $changes['name'];
if ($diff->newName !== false) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName;
}
return $sql;

View File

@ -33,7 +33,7 @@ use Doctrine\DBAL\Schema\Visitor\Visitor;
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class Column extends AbstractAsset implements \ArrayAccess
class Column extends AbstractAsset
{
/**
* @var \Doctrine\DBAL\Types\Type
@ -290,41 +290,20 @@ class Column extends AbstractAsset implements \ArrayAccess
}
/**
* @param string $option
* @return mixed
* @return array
*/
public function offsetExists($option)
public function toArray()
{
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."
);
return array_merge(array(
'name' => $this->_name,
'type' => $this->_type,
'default' => $this->_default,
'notnull' => $this->_notnull,
'length' => $this->_length,
'precision' => $this->_precision,
'scale' => $this->_scale,
'fixed' => $this->_fixed,
'unsigned' => $this->_unsigned,
), $this->_platformOptions);
}
}

View File

@ -32,6 +32,8 @@ namespace Doctrine\DBAL\Schema;
*/
class ColumnDiff
{
public $oldColumnName;
/**
* @var Column
*/
@ -42,8 +44,9 @@ class ColumnDiff
*/
public $changedProperties = array();
public function __construct(Column $column, array $changedProperties = array())
public function __construct($oldColumnName, Column $column, array $changedProperties = array())
{
$this->oldColumnName = $oldColumnName;
$this->column = $column;
$this->changedProperties = $changedProperties;
}

View File

@ -161,12 +161,11 @@ class Comparator
$changes++;
}
}
/* See if there are any changed fieldDefinitioninitions */
foreach ( $table1Columns as $columnName => $column ) {
if ( $table2->hasColumn($columnName) ) {
$changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) );
if (count($changedProperties) ) {
$columnDiff = new ColumnDiff($table2->getColumn($columnName), $changedProperties);
$columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties);
$tableDifferences->changedColumns[$column->getName()] = $columnDiff;
$changes++;
}

View File

@ -95,18 +95,13 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{
$expectedSql = $this->getGenerateAlterTableSql();
$changes = array(
'name' => 'userlist',
'add' => array(
'quota' => array(
'type' => \Doctrine\DBAL\Types\Type::getType('integer'),
'notnull' => false,
)
));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff('mytable');
$tableDiff->newName = 'userlist';
$tableDiff->addedColumns['quota'] = new \Doctrine\DBAL\Schema\Column('quota', \Doctrine\DBAL\Types\Type::getType('integer'), array('notnull' => false));
$sql = $this->_platform->getAlterTableSql('mytable', $changes);
$sql = $this->_platform->getAlterTableSql($tableDiff);
$this->assertEquals(count($sql), count($expectedSql), "Expecting the same number of sql queries for alter table failed.");
$this->assertEquals(count($expectedSql), count($sql), "Expecting the same number of sql queries for alter table failed.");
for ($i = 0; $i < count($expectedSql); $i++) {
$this->assertEquals($expectedSql[$i], $sql[$i], $i."th query of alter table does not match.");
}

View File

@ -13,22 +13,10 @@ class ColumnTest extends \PHPUnit_Framework_TestCase
{
public function testGet()
{
$options = array(
'length' => 200,
'precision' => 5,
'scale' => 2,
'unsigned' => true,
'notnull' => false,
'fixed' => true,
'default' => 'baz',
'platformOptions' => array('foo' => 'bar'),
);
$string = Type::getType('string');
$column = new Column("foo", $string, $options);
$column = $this->createColumn();
$this->assertEquals("foo", $column->getName());
$this->assertSame($string, $column->getType());
$this->assertSame(Type::getType('string'), $column->getType());
$this->assertEquals(200, $column->getLength());
$this->assertEquals(5, $column->getPrecision());
@ -43,4 +31,42 @@ class ColumnTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('bar', $column->getPlatformOption('foo'));
$this->assertFalse($column->hasPlatformOption('bar'));
}
public function testToArray()
{
$expected = array(
'name' => 'foo',
'type' => Type::getType('string'),
'default' => 'baz',
'notnull' => false,
'length' => 200,
'precision' => 5,
'scale' => 2,
'fixed' => true,
'unsigned' => true,
'foo' => 'bar',
);
$this->assertEquals($expected, $this->createColumn()->toArray());
}
/**
* @return Column
*/
public function createColumn()
{
$options = array(
'length' => 200,
'precision' => 5,
'scale' => 2,
'unsigned' => true,
'notnull' => false,
'fixed' => true,
'default' => 'baz',
'platformOptions' => array('foo' => 'bar'),
);
$string = Type::getType('string');
return new Column("foo", $string, $options);
}
}