Commit 38bd0693 authored by Martin Hasoň's avatar Martin Hasoň

Added support for foreign keys and alter table in Sqlite platform

parent 95522656
......@@ -19,6 +19,8 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException;
/**
* SqliteSchemaManager
*
......@@ -61,6 +63,79 @@ class SqliteSchemaManager extends AbstractSchemaManager
$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+\(#', $createSql, $match)) {
$names = array_reverse($match[1]);
} else {
$names = array();
}
foreach ($tableForeignKeys as $key => $value) {
$id = $value['id'];
$tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && '' != $names[$id] ? $names[$id] : $id;
}
}
return $this->_getPortableTableForeignKeysList($tableForeignKeys);
}
protected function _getPortableTableDefinition($table)
{
return $table['name'];
......@@ -187,4 +262,62 @@ class SqliteSchemaManager extends AbstractSchemaManager
{
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);
if ( ! isset($list[$value['constraint_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[$value['constraint_name']] = array(
'name' => $value['constraint_name'],
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['table'],
'onDelete' => $value['on_delete'],
'onUpdate' => $value['on_update'],
);
}
$list[$value['constraint_name']]['local'][] = $value['from'];
$list[$value['constraint_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'],
)
);
}
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;
}
}
......@@ -17,14 +17,14 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
*/
protected $_sm;
protected function getPlatformName()
{
$class = get_class($this);
protected function getPlatformName()
{
$class = get_class($this);
$e = explode('\\', $class);
$testClass = end($e);
$dbms = strtolower(str_replace('SchemaManagerTest', null, $testClass));
return $dbms;
}
}
protected function setUp()
{
......@@ -376,7 +376,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->markTestSkipped('Alter Table is not supported by this platform.');
}
$this->createTestTable('alter_table');
$alterTable = $this->createTestTable('alter_table');
$this->createTestTable('alter_table_foreign');
$table = $this->_sm->listTableDetails('alter_table');
......@@ -387,6 +387,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertEquals(1, count($table->getIndexes()));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $alterTable;
$tableDiff->addedColumns['foo'] = new \Doctrine\DBAL\Schema\Column('foo', Type::getType('integer'));
$tableDiff->removedColumns['test'] = $table->getColumn('test');
......@@ -397,6 +398,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertTrue($table->hasColumn('foo'));
$tableDiff = new \Doctrine\DBAL\Schema\TableDiff("alter_table");
$tableDiff->fromTable = $table;
$tableDiff->addedIndexes[] = new \Doctrine\DBAL\Schema\Index('foo_idx', array('foo'));
$this->_sm->alterTable($tableDiff);
......@@ -409,6 +411,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertFalse($table->getIndex('foo_idx')->isUnique());
$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'));
$this->_sm->alterTable($tableDiff);
......@@ -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()));
$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'));
$fk = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(array('foreign_key_test'), 'alter_table_foreign', array('id'));
$tableDiff->addedForeignKeys[] = $fk;
......@@ -585,6 +589,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$table = $this->getTestTable($name, $options);
$this->_sm->dropAndCreateTable($table);
return $table;
}
protected function getTestTable($name, $options=array())
......
......@@ -28,12 +28,14 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->assertEquals(false, file_exists($path));
}
/**
* @expectedException \Doctrine\DBAL\DBALException
*/
public function testRenameTable()
{
$this->createTestTable('oldname');
$this->_sm->renameTable('oldname', 'newname');
$tables = $this->_sm->listTableNames();
$this->assertContains('newname', $tables);
$this->assertNotContains('oldname', $tables);
}
public function testAutoincrementDetection()
......@@ -43,4 +45,4 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
. 'auto-increment. So, while it does support a single identity column, we cannot with '
. 'certainty determine which it is.');
}
}
\ No newline at end of file
}
......@@ -205,7 +205,15 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
{
$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->fromTable = $table;
$tableDiff->newName = 'userlist';
$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'));
......@@ -309,7 +317,13 @@ abstract class AbstractPlatformTestCase extends \Doctrine\Tests\DbalTestCase
$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->fromTable = $table;
$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->changedColumns['changed'] = new \Doctrine\DBAL\Schema\ColumnDiff(
......
......@@ -105,9 +105,17 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
return 'CREATE UNIQUE INDEX index_name ON test (test, test2)';
}
/**
* @expectedException \Doctrine\DBAL\DBALException
*/
public function testGeneratesForeignKeyCreationSql()
{
parent::testGeneratesForeignKeyCreationSql();
}
public function getGenerateForeignKeySql()
{
$this->markTestSkipped('SQLite does not support ForeignKeys.');
return null;
}
public function testModifyLimitQuery()
......@@ -124,12 +132,12 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
public function getGenerateAlterTableSql()
{
$this->markTestSkipped('SQlite does not support ALTER Table.');
}
public function testGetAlterTableSqlDispatchEvent()
{
$this->markTestSkipped('SQlite does not support ALTER Table.');
return array(
"CREATE TABLE __temp__userlist (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 __temp__userlist (id, baz, bloo) SELECT id, bar, bloo FROM mytable",
"DROP TABLE mytable",
"ALTER TABLE __temp__userlist RENAME TO userlist",
);
}
/**
......@@ -146,11 +154,6 @@ class SqlitePlatformTest extends AbstractPlatformTestCase
'CREATE TABLE test ("like" INTEGER NOT NULL, PRIMARY KEY("like"))',
$createTableSQL[0]
);
$this->assertEquals(
'ALTER TABLE test ADD PRIMARY KEY ("like")',
$this->_platform->getCreatePrimaryKeySQL($table->getIndex('primary'), 'test')
);
}
protected function getQuotedColumnInPrimaryKeySQL()
......
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