Commit 63b7ef12 authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge pull request #220 from hason/sqlite_alter

[WIP] Added support for alter table, foreign keys and autoincrement detection to Sqlite platform and schema
parents aad1a946 a42b8ed1
...@@ -1833,6 +1833,10 @@ abstract class AbstractPlatform ...@@ -1833,6 +1833,10 @@ abstract class AbstractPlatform
$default = " DEFAULT ".$field['default']; $default = " DEFAULT ".$field['default'];
} else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { } else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) {
$default = " DEFAULT ".$this->getCurrentTimestampSQL(); $default = " DEFAULT ".$this->getCurrentTimestampSQL();
} else if ((string)$field['type'] == 'Time' && $field['default'] == $this->getCurrentTimeSQL()) {
$default = " DEFAULT ".$this->getCurrentTimeSQL();
} else if ((string)$field['type'] == 'Date' && $field['default'] == $this->getCurrentDateSQL()) {
$default = " DEFAULT ".$this->getCurrentDateSQL();
} else if ((string) $field['type'] == 'Boolean') { } else if ((string) $field['type'] == 'Boolean') {
$default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'";
} }
......
...@@ -44,11 +44,17 @@ class ColumnDiff ...@@ -44,11 +44,17 @@ class ColumnDiff
*/ */
public $changedProperties = array(); public $changedProperties = array();
public function __construct($oldColumnName, Column $column, array $changedProperties = array()) /**
* @var Column
*/
public $fromColumn;
public function __construct($oldColumnName, Column $column, array $changedProperties = array(), Column $fromColumn = null)
{ {
$this->oldColumnName = $oldColumnName; $this->oldColumnName = $oldColumnName;
$this->column = $column; $this->column = $column;
$this->changedProperties = $changedProperties; $this->changedProperties = $changedProperties;
$this->fromColumn = $fromColumn;
} }
public function hasChanged($propertyName) public function hasChanged($propertyName)
......
...@@ -58,6 +58,7 @@ class Comparator ...@@ -58,6 +58,7 @@ class Comparator
public function compare(Schema $fromSchema, Schema $toSchema) public function compare(Schema $fromSchema, Schema $toSchema)
{ {
$diff = new SchemaDiff(); $diff = new SchemaDiff();
$diff->fromSchema = $fromSchema;
$foreignKeysToTable = array(); $foreignKeysToTable = array();
...@@ -179,6 +180,7 @@ class Comparator ...@@ -179,6 +180,7 @@ class Comparator
{ {
$changes = 0; $changes = 0;
$tableDifferences = new TableDiff($table1->getName()); $tableDifferences = new TableDiff($table1->getName());
$tableDifferences->fromTable = $table1;
$table1Columns = $table1->getColumns(); $table1Columns = $table1->getColumns();
$table2Columns = $table2->getColumns(); $table2Columns = $table2->getColumns();
...@@ -203,6 +205,7 @@ class Comparator ...@@ -203,6 +205,7 @@ class Comparator
$changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) ); $changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) );
if (count($changedProperties) ) { if (count($changedProperties) ) {
$columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties);
$columnDiff->fromColumn = $column;
$tableDifferences->changedColumns[$column->getName()] = $columnDiff; $tableDifferences->changedColumns[$column->getName()] = $columnDiff;
$changes++; $changes++;
} }
......
...@@ -204,6 +204,16 @@ class Index extends AbstractAsset implements Constraint ...@@ -204,6 +204,16 @@ class Index extends AbstractAsset implements Constraint
return false; return false;
} }
/**
* Returns platform specific flags for indexes.
*
* @return array
*/
public function getFlags()
{
return array_keys($this->_flags);
}
/** /**
* Add Flag for an index that translates to platform specific handling. * Add Flag for an index that translates to platform specific handling.
* *
......
...@@ -34,6 +34,11 @@ use \Doctrine\DBAL\Platforms\AbstractPlatform; ...@@ -34,6 +34,11 @@ use \Doctrine\DBAL\Platforms\AbstractPlatform;
*/ */
class SchemaDiff class SchemaDiff
{ {
/**
* @var Schema
*/
public $fromSchema;
/** /**
* All added tables * All added tables
* *
...@@ -81,12 +86,14 @@ class SchemaDiff ...@@ -81,12 +86,14 @@ class SchemaDiff
* @param array(string=>Table) $newTables * @param array(string=>Table) $newTables
* @param array(string=>TableDiff) $changedTables * @param array(string=>TableDiff) $changedTables
* @param array(string=>bool) $removedTables * @param array(string=>bool) $removedTables
* @param Schema $fromSchema
*/ */
public function __construct($newTables = array(), $changedTables = array(), $removedTables = array()) public function __construct($newTables = array(), $changedTables = array(), $removedTables = array(), Schema $fromSchema = null)
{ {
$this->newTables = $newTables; $this->newTables = $newTables;
$this->changedTables = $changedTables; $this->changedTables = $changedTables;
$this->removedTables = $removedTables; $this->removedTables = $removedTables;
$this->fromSchema = $fromSchema;
} }
/** /**
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema; namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException;
/** /**
* SqliteSchemaManager * SqliteSchemaManager
* *
...@@ -26,6 +28,7 @@ namespace Doctrine\DBAL\Schema; ...@@ -26,6 +28,7 @@ namespace Doctrine\DBAL\Schema;
* @author Konsta Vesterinen <kvesteri@cc.hut.fi> * @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Martin Hasoň <martin.hason@gmail.com>
* @version $Revision$ * @version $Revision$
* @since 2.0 * @since 2.0
*/ */
...@@ -61,6 +64,93 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -61,6 +64,93 @@ class SqliteSchemaManager extends AbstractSchemaManager
$conn->close(); $conn->close();
} }
/**
* {@inheritdoc}
*/
public function renameTable($name, $newName)
{
$tableDiff = new TableDiff($name);
$tableDiff->fromTable = $this->listTableDetails($name);
$tableDiff->newName = $newName;
$this->alterTable($tableDiff);
}
/**
* {@inheritdoc}
*/
public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table);
$tableDiff->addedForeignKeys[] = $foreignKey;
$this->alterTable($tableDiff);
}
/**
* {@inheritdoc}
*/
public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
$tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table);
$tableDiff->changedForeignKeys[] = $foreignKey;
$this->alterTable($tableDiff);
}
/**
* {@inheritdoc}
*/
public function dropForeignKey($foreignKey, $table)
{
$tableDiff = $this->getTableDiffForAlterForeignKey($foreignKey, $table);
$tableDiff->removedForeignKeys[] = $foreignKey;
$this->alterTable($tableDiff);
}
/**
* {@inheritdoc}
*/
public function listTableForeignKeys($table, $database = null)
{
if (null === $database) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
if ( ! empty($tableForeignKeys)) {
$createSql = $this->_conn->fetchAll("SELECT sql FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = 'table' AND name = '$table'");
$createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : '';
if (preg_match_all('#
(?:CONSTRAINT\s+([^\s]+)\s+)?
(?:FOREIGN\s+KEY[^\)]+\)\s*)?
REFERENCES\s+[^\s]+\s+(?:\([^\)]+\))?
(?:
[^,]*?
(NOT\s+DEFERRABLE|DEFERRABLE)
(?:\s+INITIALLY\s+(DEFERRED|IMMEDIATE))?
)?#isx',
$createSql, $match)) {
$names = array_reverse($match[1]);
$deferrable = array_reverse($match[2]);
$deferred = array_reverse($match[3]);
} else {
$names = $deferrable = $deferred = array();
}
foreach ($tableForeignKeys as $key => $value) {
$id = $value['id'];
$tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && '' != $names[$id] ? $names[$id] : $id;
$tableForeignKeys[$key]['deferrable'] = isset($deferrable[$id]) && 'deferrable' == strtolower($deferrable[$id]) ? true : false;
$tableForeignKeys[$key]['deferred'] = isset($deferred[$id]) && 'deferred' == strtolower($deferred[$id]) ? true : false;
}
}
return $this->_getPortableTableForeignKeysList($tableForeignKeys);
}
protected function _getPortableTableDefinition($table) protected function _getPortableTableDefinition($table)
{ {
return $table['name']; return $table['name'];
...@@ -122,6 +212,31 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -122,6 +212,31 @@ class SqliteSchemaManager extends AbstractSchemaManager
); );
} }
protected function _getPortableTableColumnList($table, $database, $tableColumns)
{
$list = parent::_getPortableTableColumnList($table, $database, $tableColumns);
$autoincrementColumn = null;
$autoincrementCount = 0;
foreach ($tableColumns as $tableColumn) {
if ('1' == $tableColumn['pk']) {
$autoincrementCount++;
if (null === $autoincrementColumn && 'integer' == strtolower($tableColumn['type'])) {
$autoincrementColumn = $tableColumn['name'];
}
}
}
if (1 == $autoincrementCount && null !== $autoincrementColumn) {
foreach ($list as $column) {
if ($autoincrementColumn == $column->getName()) {
$column->setAutoincrement(true);
}
}
}
return $list;
}
protected function _getPortableTableColumnDefinition($tableColumn) protected function _getPortableTableColumnDefinition($tableColumn)
{ {
$e = explode('(', $tableColumn['type']); $e = explode('(', $tableColumn['type']);
...@@ -190,4 +305,67 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -190,4 +305,67 @@ class SqliteSchemaManager extends AbstractSchemaManager
{ {
return new View($view['name'], $view['sql']); return new View($view['name'], $view['sql']);
} }
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$list = array();
foreach ($tableForeignKeys as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER);
$name = $value['constraint_name'];
if ( ! isset($list[$name])) {
if ( ! isset($value['on_delete']) || $value['on_delete'] == "RESTRICT") {
$value['on_delete'] = null;
}
if ( ! isset($value['on_update']) || $value['on_update'] == "RESTRICT") {
$value['on_update'] = null;
}
$list[$name] = array(
'name' => $name,
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['table'],
'onDelete' => $value['on_delete'],
'onUpdate' => $value['on_update'],
'deferrable' => $value['deferrable'],
'deferred'=> $value['deferred'],
);
}
$list[$name]['local'][] = $value['from'];
$list[$name]['foreign'][] = $value['to'];
}
$result = array();
foreach($list as $constraint) {
$result[] = new ForeignKeyConstraint(
array_values($constraint['local']), $constraint['foreignTable'],
array_values($constraint['foreign']), $constraint['name'],
array(
'onDelete' => $constraint['onDelete'],
'onUpdate' => $constraint['onUpdate'],
'deferrable' => $constraint['deferrable'],
'deferred'=> $constraint['deferred'],
)
);
}
return $result;
}
private function getTableDiffForAlterForeignKey(ForeignKeyConstraint $foreignKey, $table)
{
if ( ! $table instanceof Table) {
$tableDetails = $this->tryMethod('listTableDetails', $table);
if (false === $table) {
throw new \DBALException(sprintf('Sqlite schema manager requires to modify foreign keys table definition "%s".', $table));
}
$table = $tableDetails;
}
$tableDiff = new TableDiff($table->getName());
$tableDiff->fromTable = $table;
return $tableDiff;
}
} }
...@@ -111,6 +111,11 @@ class TableDiff ...@@ -111,6 +111,11 @@ class TableDiff
*/ */
public $removedForeignKeys = array(); public $removedForeignKeys = array();
/**
* @var Table
*/
public $fromTable;
/** /**
* Constructs an TableDiff object. * Constructs an TableDiff object.
* *
...@@ -120,10 +125,11 @@ class TableDiff ...@@ -120,10 +125,11 @@ class TableDiff
* @param array(string=>Index) $addedIndexes * @param array(string=>Index) $addedIndexes
* @param array(string=>Index) $changedIndexes * @param array(string=>Index) $changedIndexes
* @param array(string=>bool) $removedIndexes * @param array(string=>bool) $removedIndexes
* @param Table $fromTable
*/ */
public function __construct($tableName, $addedColumns = array(), public function __construct($tableName, $addedColumns = array(),
$changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(),
$changedIndexes = array(), $removedIndexes = array()) $changedIndexes = array(), $removedIndexes = array(), Table $fromTable = null)
{ {
$this->name = $tableName; $this->name = $tableName;
$this->addedColumns = $addedColumns; $this->addedColumns = $addedColumns;
...@@ -132,5 +138,6 @@ class TableDiff ...@@ -132,5 +138,6 @@ class TableDiff
$this->addedIndexes = $addedIndexes; $this->addedIndexes = $addedIndexes;
$this->changedIndexes = $changedIndexes; $this->changedIndexes = $changedIndexes;
$this->removedIndexes = $removedIndexes; $this->removedIndexes = $removedIndexes;
$this->fromTable = $fromTable;
} }
} }
...@@ -376,7 +376,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -376,7 +376,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->markTestSkipped('Alter Table is not supported by this platform.'); $this->markTestSkipped('Alter Table is not supported by this platform.');
} }
$this->createTestTable('alter_table'); $alterTable = $this->createTestTable('alter_table');
$this->createTestTable('alter_table_foreign'); $this->createTestTable('alter_table_foreign');
$table = $this->_sm->listTableDetails('alter_table'); $table = $this->_sm->listTableDetails('alter_table');
...@@ -387,6 +387,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -387,6 +387,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertEquals(1, count($table->getIndexes())); $this->assertEquals(1, count($table->getIndexes()));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table"); $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $alterTable;
$tableDiff->addedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', Type::getType('integer')); $tableDiff->addedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', Type::getType('integer'));
$tableDiff->removedColumns['test'] = $table->getColumn('test'); $tableDiff->removedColumns['test'] = $table->getColumn('test');
...@@ -397,6 +398,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -397,6 +398,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertTrue($table->hasColumn('foo')); $this->assertTrue($table->hasColumn('foo'));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table"); $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $table;
$tableDiff->addedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo')); $tableDiff->addedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo'));
$this->_sm->alterTable($tableDiff); $this->_sm->alterTable($tableDiff);
...@@ -409,6 +411,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -409,6 +411,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertFalse($table->getIndex('foo_idx')->isUnique()); $this->assertFalse($table->getIndex('foo_idx')->isUnique());
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table"); $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $table;
$tableDiff->changedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test')); $tableDiff->changedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test'));
$this->_sm->alterTable($tableDiff); $this->_sm->alterTable($tableDiff);
...@@ -419,6 +422,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -419,6 +422,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertEquals(array('foo', 'foreign_key_test'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns())); $this->assertEquals(array('foo', 'foreign_key_test'), array_map('strtolower', $table->getIndex('foo_idx')->getColumns()));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table"); $tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $table;
$tableDiff->removedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test')); $tableDiff->removedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo', 'foreign_key_test'));
$fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('foreign_key_test'), 'alter_table_foreign', array('id')); $fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('foreign_key_test'), 'alter_table_foreign', array('id'));
$tableDiff->addedForeignKeys[] = $fk; $tableDiff->addedForeignKeys[] = $fk;
...@@ -585,6 +589,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -585,6 +589,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$table = $this->getTestTable($name, $options); $table = $this->getTestTable($name, $options);
$this->_sm->dropAndCreateTable($table); $this->_sm->dropAndCreateTable($table);
return $table;
} }
protected function getTestTable($name, $options=array()) protected function getTestTable($name, $options=array())
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
namespace Doctrine\Tests\DBAL\Functional\Schema; namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema; use Doctrine\DBAL\Schema;
require_once __DIR__ . '/../../../TestInit.php'; require_once __DIR__ . '/../../../TestInit.php';
...@@ -28,19 +30,46 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -28,19 +30,46 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(false, file_exists($path)); $this->assertEquals(false, file_exists($path));
} }
/**
* @expectedException \Doctrine\DBAL\DBALException
*/
public function testRenameTable() public function testRenameTable()
{ {
$this->createTestTable('oldname');
$this->_sm->renameTable('oldname', 'newname'); $this->_sm->renameTable('oldname', 'newname');
$tables = $this->_sm->listTableNames();
$this->assertContains('newname', $tables);
$this->assertNotContains('oldname', $tables);
} }
public function testAutoincrementDetection() public function createListTableColumns()
{ {
$this->markTestSkipped( $table = parent::createListTableColumns();
'There is currently no reliable way to determine whether an SQLite column is marked as ' $table->getColumn('id')->setAutoincrement(true);
. 'auto-increment. So, while it does support a single identity column, we cannot with '
. 'certainty determine which it is.'); return $table;
}
public function testListForeignKeysFromExistingDatabase()
{
$this->_conn->executeQuery(<<<EOS
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
page INTEGER CONSTRAINT FK_1 REFERENCES page (key) DEFERRABLE INITIALLY DEFERRED,
parent INTEGER REFERENCES user(id) ON DELETE CASCADE,
log INTEGER,
CONSTRAINT FK_3 FOREIGN KEY (log) REFERENCES log ON UPDATE SET NULL NOT DEFERRABLE
)
EOS
);
$expected = array(
new ForeignKeyConstraint(array('log'), 'log', array(null), 'FK_3',
array('onUpdate' => 'SET NULL', 'onDelete' => 'NO ACTION', 'deferrable' => false, 'deferred' => false)),
new ForeignKeyConstraint(array('parent'), 'user', array('id'), '1',
array('onUpdate' => 'NO ACTION', 'onDelete' => 'CASCADE', 'deferrable' => false, 'deferred' => false)),
new ForeignKeyConstraint(array('page'), 'page', array('key'), 'FK_1',
array('onUpdate' => 'NO ACTION', 'onDelete' => 'NO ACTION', 'deferrable' => true, 'deferred' => true)),
);
$this->assertEquals($expected, $this->_sm->listTableForeignKeys('user'));
} }
} }
...@@ -205,7 +205,15 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase ...@@ -205,7 +205,15 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{ {
$expectedSql = $this->getGenerateAlterTableSql(); $expectedSql = $this->getGenerateAlterTableSql();
$table = new Table('mytable');
$table->addColumn('id', 'integer', array('autoincrement' => true));
$table->addColumn('foo', 'integer');
$table->addColumn('bar', 'string');
$table->addColumn('bloo', 'boolean');
$table->setPrimaryKey(array('id'));
$tableDiff = new TableDiff('mytable'); $tableDiff = new TableDiff('mytable');
$tableDiff->fromTable = $table;
$tableDiff->newName = 'userlist'; $tableDiff->newName = 'userlist';
$tableDiff->addedColumns['quota'] = new \Doctrine\DBAL\Schema\Column('quota', \Doctrine\DBAL\Types\Type::getType('integer'), array('notnull' => false)); $tableDiff->addedColumns['quota'] = new \Doctrine\DBAL\Schema\Column('quota', \Doctrine\DBAL\Types\Type::getType('integer'), array('notnull' => false));
$tableDiff->removedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', \Doctrine\DBAL\Types\Type::getType('integer')); $tableDiff->removedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', \Doctrine\DBAL\Types\Type::getType('integer'));
...@@ -309,7 +317,13 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase ...@@ -309,7 +317,13 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
$this->_platform->setEventManager($eventManager); $this->_platform->setEventManager($eventManager);
$table = new Table('mytable');
$table->addColumn('removed', 'integer');
$table->addColumn('changed', 'integer');
$table->addColumn('renamed', 'integer');
$tableDiff = new TableDiff('mytable'); $tableDiff = new TableDiff('mytable');
$tableDiff->fromTable = $table;
$tableDiff->addedColumns['added'] = new \Doctrine\DBAL\Schema\Column('added', \Doctrine\DBAL\Types\Type::getType('integer'), array()); $tableDiff->addedColumns['added'] = new \Doctrine\DBAL\Schema\Column('added', \Doctrine\DBAL\Types\Type::getType('integer'), array());
$tableDiff->removedColumns['removed'] = new \Doctrine\DBAL\Schema\Column('removed', \Doctrine\DBAL\Types\Type::getType('integer'), array()); $tableDiff->removedColumns['removed'] = new \Doctrine\DBAL\Schema\Column('removed', \Doctrine\DBAL\Types\Type::getType('integer'), array());
$tableDiff->changedColumns['changed'] = new \Doctrine\DBAL\Schema\ColumnDiff( $tableDiff->changedColumns['changed'] = new \Doctrine\DBAL\Schema\ColumnDiff(
......
...@@ -2,8 +2,12 @@ ...@@ -2,8 +2,12 @@
namespace Doctrine\Tests\DBAL\Platforms; namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\DBALException;
require_once __DIR__ . '/../../TestInit.php'; require_once __DIR__ . '/../../TestInit.php';
...@@ -105,9 +109,25 @@ class SqlitePlatformTest extends AbstractPlatformTestCase ...@@ -105,9 +109,25 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
return 'CREATE UNIQUE INDEX index_name ON test (test, test2)'; return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
} }
/**
* @expectedException \Doctrine\DBAL\DBALException
*/
public function testGeneratesForeignKeyCreationSql()
{
parent::testGeneratesForeignKeyCreationSql();
}
/**
* @expectedException \Doctrine\DBAL\DBALException
*/
public function testGeneratesConstraintCreationSql()
{
parent::testGeneratesConstraintCreationSql();
}
public function getGenerateForeignKeySql() public function getGenerateForeignKeySql()
{ {
$this->markTestSkipped('SQLite does not support ForeignKeys.'); return null;
} }
public function testModifyLimitQuery() public function testModifyLimitQuery()
...@@ -124,12 +144,14 @@ class SqlitePlatformTest extends AbstractPlatformTestCase ...@@ -124,12 +144,14 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
public function getGenerateAlterTableSql() public function getGenerateAlterTableSql()
{ {
$this->markTestSkipped('SQlite does not support ALTER Table.'); return array(
} "CREATE TEMPORARY TABLE __temp__mytable AS SELECT id, bar, bloo FROM mytable",
"DROP TABLE mytable",
public function testGetAlterTableSqlDispatchEvent() "CREATE TABLE mytable (id INTEGER NOT NULL, baz VARCHAR(255) DEFAULT 'def' NOT NULL, bloo BOOLEAN DEFAULT '0' NOT NULL, quota INTEGER DEFAULT NULL, PRIMARY KEY(id))",
{ "INSERT INTO mytable (id, baz, bloo) SELECT id, bar, bloo FROM __temp__mytable",
$this->markTestSkipped('SQlite does not support ALTER Table.'); "DROP TABLE __temp__mytable",
"ALTER TABLE mytable RENAME TO userlist",
);
} }
/** /**
...@@ -146,11 +168,113 @@ class SqlitePlatformTest extends AbstractPlatformTestCase ...@@ -146,11 +168,113 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
'CREATE TABLE test ("like" INTEGER NOT NULL, PRIMARY KEY("like"))', 'CREATE TABLE test ("like" INTEGER NOT NULL, PRIMARY KEY("like"))',
$createTableSQL[0] $createTableSQL[0]
); );
}
$this->assertEquals( public function testAlterTableAddColumns()
'ALTER TABLE test ADD PRIMARY KEY ("like")', {
$this->_platform->getCreatePrimaryKeySQL($table->getIndex('primary'), 'test') $diff = new TableDiff('user');
$diff->addedColumns['foo'] = new Column('foo', Type::getType('string'));
$diff->addedColumns['count'] = new Column('count', Type::getType('integer'), array('notnull' => false, 'default' => 1));
$expected = array(
'ALTER TABLE user ADD COLUMN foo VARCHAR(255) NOT NULL',
'ALTER TABLE user ADD COLUMN count INTEGER DEFAULT 1',
); );
$this->assertEquals($expected, $this->_platform->getAlterTableSQL($diff));
}
public function testAlterTableAddComplexColumns()
{
$diff = new TableDiff('user');
$diff->addedColumns['time'] = new Column('time', Type::getType('date'), array('default' => 'CURRENT_DATE'));
try {
$this->_platform->getAlterTableSQL($diff);
$this->fail();
} catch (DBALException $e) {
}
$diff = new TableDiff('user');
$diff->addedColumns['id'] = new Column('id', Type::getType('integer'), array('autoincrement' => true));
try {
$this->_platform->getAlterTableSQL($diff);
$this->fail();
} catch (DBALException $e) {
}
}
public function testCreateTableWithDeferredForeignKeys()
{
$table = new Table('user');
$table->addColumn('id', 'integer');
$table->addColumn('article', 'integer');
$table->addColumn('post', 'integer');
$table->addColumn('parent', 'integer');
$table->setPrimaryKey(array('id'));
$table->addForeignKeyConstraint('article', array('article'), array('id'), array('deferrable' => true));
$table->addForeignKeyConstraint('post', array('post'), array('id'), array('deferred' => true));
$table->addForeignKeyConstraint('user', array('parent'), array('id'), array('deferrable' => true, 'deferred' => true));
$sql = array(
'CREATE TABLE user ('
. 'id INTEGER NOT NULL, article INTEGER NOT NULL, post INTEGER NOT NULL, parent INTEGER NOT NULL'
. ', PRIMARY KEY(id)'
. ', CONSTRAINT FK_8D93D64923A0E66 FOREIGN KEY (article) REFERENCES article (id) DEFERRABLE INITIALLY IMMEDIATE'
. ', CONSTRAINT FK_8D93D6495A8A6C8D FOREIGN KEY (post) REFERENCES post (id) NOT DEFERRABLE INITIALLY DEFERRED'
. ', CONSTRAINT FK_8D93D6493D8E604F FOREIGN KEY (parent) REFERENCES user (id) DEFERRABLE INITIALLY DEFERRED'
. ')',
'CREATE INDEX IDX_8D93D64923A0E66 ON user (article)',
'CREATE INDEX IDX_8D93D6495A8A6C8D ON user (post)',
'CREATE INDEX IDX_8D93D6493D8E604F ON user (parent)',
);
$this->assertEquals($sql, $this->_platform->getCreateTableSQL($table));
}
public function testAlterTable()
{
$table = new Table('user');
$table->addColumn('id', 'integer');
$table->addColumn('article', 'integer');
$table->addColumn('post', 'integer');
$table->addColumn('parent', 'integer');
$table->setPrimaryKey(array('id'));
$table->addForeignKeyConstraint('article', array('article'), array('id'), array('deferrable' => true));
$table->addForeignKeyConstraint('post', array('post'), array('id'), array('deferred' => true));
$table->addForeignKeyConstraint('user', array('parent'), array('id'), array('deferrable' => true, 'deferred' => true));
$table->addIndex(array('article', 'post'), 'index1');
$diff = new TableDiff('user');
$diff->fromTable = $table;
$diff->newName = 'client';
$diff->renamedColumns['id'] = new \Doctrine\DBAL\Schema\Column('key', \Doctrine\DBAL\Types\Type::getType('integer'), array());
$diff->renamedColumns['post'] = new \Doctrine\DBAL\Schema\Column('comment', \Doctrine\DBAL\Types\Type::getType('integer'), array());
$diff->removedColumns['parent'] = new \Doctrine\DBAL\Schema\Column('comment', \Doctrine\DBAL\Types\Type::getType('integer'), array());
$diff->removedIndexes['index1'] = $table->getIndex('index1');
$sql = array(
'DROP INDEX IDX_8D93D64923A0E66',
'DROP INDEX IDX_8D93D6495A8A6C8D',
'DROP INDEX IDX_8D93D6493D8E604F',
'DROP INDEX index1',
'CREATE TEMPORARY TABLE __temp__user AS SELECT id, article, post FROM user',
'DROP TABLE user',
'CREATE TABLE user ('
. '"key" INTEGER NOT NULL, article INTEGER NOT NULL, comment INTEGER NOT NULL'
. ', PRIMARY KEY("key")'
. ', CONSTRAINT FK_8D93D64923A0E66 FOREIGN KEY (article) REFERENCES article (id) DEFERRABLE INITIALLY IMMEDIATE'
. ', CONSTRAINT FK_8D93D6495A8A6C8D FOREIGN KEY (comment) REFERENCES post (id) NOT DEFERRABLE INITIALLY DEFERRED'
. ')',
'INSERT INTO user ("key", article, comment) SELECT id, article, post FROM __temp__user',
'DROP TABLE __temp__user',
'ALTER TABLE user RENAME TO client',
'CREATE INDEX IDX_8D93D64923A0E66 ON client (article)',
'CREATE INDEX IDX_8D93D6495A8A6C8D ON client (comment)',
);
$this->assertEquals($sql, $this->_platform->getAlterTableSQL($diff));
} }
protected function getQuotedColumnInPrimaryKeySQL() protected function getQuotedColumnInPrimaryKeySQL()
......
...@@ -29,6 +29,7 @@ use Doctrine\DBAL\Schema\Schema, ...@@ -29,6 +29,7 @@ use Doctrine\DBAL\Schema\Schema,
Doctrine\DBAL\Schema\Sequence, Doctrine\DBAL\Schema\Sequence,
Doctrine\DBAL\Schema\SchemaDiff, Doctrine\DBAL\Schema\SchemaDiff,
Doctrine\DBAL\Schema\TableDiff, Doctrine\DBAL\Schema\TableDiff,
Doctrine\DBAL\Schema\ColumnDiff,
Doctrine\DBAL\Schema\Comparator, Doctrine\DBAL\Schema\Comparator,
Doctrine\DBAL\Types\Type, Doctrine\DBAL\Types\Type,
Doctrine\DBAL\Schema\ForeignKeyConstraint; Doctrine\DBAL\Schema\ForeignKeyConstraint;
...@@ -61,7 +62,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -61,7 +62,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) ); ) );
$this->assertEquals(new SchemaDiff(), Comparator::compareSchemas( $schema1, $schema2 ) ); $expected = new SchemaDiff();
$expected->fromSchema = $schema1;
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
public function testCompareSame2() public function testCompareSame2()
...@@ -82,7 +85,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -82,7 +85,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
) )
), ),
) ); ) );
$this->assertEquals(new SchemaDiff(), Comparator::compareSchemas( $schema1, $schema2 ) );
$expected = new SchemaDiff();
$expected->fromSchema = $schema1;
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
public function testCompareMissingTable() public function testCompareMissingTable()
...@@ -94,7 +100,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -94,7 +100,7 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$schema1 = new Schema( array($table), array(), $schemaConfig ); $schema1 = new Schema( array($table), array(), $schemaConfig );
$schema2 = new Schema( array(), array(), $schemaConfig ); $schema2 = new Schema( array(), array(), $schemaConfig );
$expected = new SchemaDiff( array(), array(), array('bugdb' => $table) ); $expected = new SchemaDiff( array(), array(), array('bugdb' => $table), $schema1 );
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -108,7 +114,8 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -108,7 +114,8 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$schema1 = new Schema( array(), array(), $schemaConfig ); $schema1 = new Schema( array(), array(), $schemaConfig );
$schema2 = new Schema( array($table), array(), $schemaConfig ); $schema2 = new Schema( array($table), array(), $schemaConfig );
$expected = new SchemaDiff( array('bugdb' => $table), array(), array() ); $expected = new SchemaDiff( array('bugdb' => $table), array(), array(), $schema1 );
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -151,6 +158,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -151,6 +158,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
) )
) )
); );
$expected->fromSchema = $schema1;
$expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -181,6 +191,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -181,6 +191,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) )
); );
$expected->fromSchema = $schema1;
$expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -251,6 +264,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -251,6 +264,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) )
); );
$expected->fromSchema = $schema1;
$expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -295,6 +311,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -295,6 +311,9 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) )
); );
$expected->fromSchema = $schema1;
$expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) ); $this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ) );
} }
...@@ -346,8 +365,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -346,8 +365,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) )
); );
$actual = Comparator::compareSchemas( $schema1, $schema2 ); $expected->fromSchema = $schema1;
$this->assertEquals($expected, $actual); $expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ));
} }
public function testCompareChangedIndexFieldPositions() public function testCompareChangedIndexFieldPositions()
...@@ -384,8 +405,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -384,8 +405,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
), ),
) )
); );
$actual = Comparator::compareSchemas( $schema1, $schema2 ); $expected->fromSchema = $schema1;
$this->assertEquals($expected, $actual); $expected->changedTables['bugdb']->fromTable = $schema1->getTable('bugdb');
$this->assertEquals($expected, Comparator::compareSchemas( $schema1, $schema2 ));
} }
public function testCompareSequences() public function testCompareSequences()
...@@ -740,8 +763,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -740,8 +763,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$newSchema= new Schema(array(), array(), $config); $newSchema= new Schema(array(), array(), $config);
$newSchema->createTable('foo.bar'); $newSchema->createTable('foo.bar');
$c = new Comparator(); $expected = new SchemaDiff();
$this->assertEquals(new SchemaDiff(), $c->compare($oldSchema, $newSchema)); $expected->fromSchema = $oldSchema;
$this->assertEquals($expected, Comparator::compareSchemas($oldSchema, $newSchema));
} }
/** /**
...@@ -758,9 +783,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -758,9 +783,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$newSchema = new Schema(); $newSchema = new Schema();
$newSchema->createTable('bar'); $newSchema->createTable('bar');
$c = new Comparator(); $expected = new SchemaDiff();
$diff = $c->compare($oldSchema, $newSchema); $expected->fromSchema = $oldSchema;
$this->assertEquals(new SchemaDiff(), $c->compare($oldSchema, $newSchema));
$this->assertEquals($expected, Comparator::compareSchemas($oldSchema, $newSchema));
} }
/** /**
...@@ -776,10 +802,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -776,10 +802,10 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$newSchema = new Schema(); $newSchema = new Schema();
$newSchema->createTable('bar'); $newSchema->createTable('bar');
$c = new Comparator(); $expected = new SchemaDiff();
$diff = $c->compare($oldSchema, $newSchema); $expected->fromSchema = $oldSchema;
$this->assertEquals(new SchemaDiff(), $c->compare($oldSchema, $newSchema)); $this->assertEquals($expected, Comparator::compareSchemas($oldSchema, $newSchema));
} }
/** /**
...@@ -833,6 +859,27 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase ...@@ -833,6 +859,27 @@ class ComparatorTest extends \PHPUnit_Framework_TestCase
$this->assertCount(1, $diff->orphanedForeignKeys); $this->assertCount(1, $diff->orphanedForeignKeys);
} }
public function testCompareChangedColumn()
{
$oldSchema = new Schema();
$tableFoo = $oldSchema->createTable('foo');
$tableFoo->addColumn('id', 'integer');
$newSchema = new Schema();
$table = $newSchema->createTable('foo');
$table->addColumn('id', 'string');
$expected = new SchemaDiff();
$expected->fromSchema = $oldSchema;
$tableDiff = $expected->changedTables['foo'] = new TableDiff('foo');
$tableDiff->fromTable = $tableFoo;
$columnDiff = $tableDiff->changedColumns['id'] = new ColumnDiff('id', $table->getColumn('id'));
$columnDiff->fromColumn = $tableFoo->getColumn('id');
$columnDiff->changedProperties = array('type');
$this->assertEquals($expected, Comparator::compareSchemas($oldSchema, $newSchema));
}
/** /**
* @param SchemaDiff $diff * @param SchemaDiff $diff
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment