Commit 16d0c3e5 authored by Martin Hasoň's avatar Martin Hasoň

Improved foreign key definition parsing in SqliteSchemaManager

parent ff630e2a
...@@ -28,6 +28,7 @@ use Doctrine\DBAL\DBALException; ...@@ -28,6 +28,7 @@ use Doctrine\DBAL\DBALException;
* @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
*/ */
...@@ -121,15 +122,29 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -121,15 +122,29 @@ class SqliteSchemaManager extends AbstractSchemaManager
if ( ! empty($tableForeignKeys)) { 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 = $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'] : ''; $createSql = isset($createSql[0]['sql']) ? $createSql[0]['sql'] : '';
if (preg_match_all('#(?:CONSTRAINT\s+([^\s]+)\s+)?FOREIGN\s+KEY\s+\(#', $createSql, $match)) { 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]); $names = array_reverse($match[1]);
$deferrable = array_reverse($match[2]);
$deferred = array_reverse($match[3]);
} else { } else {
$names = array(); $names = $deferrable = $deferred = array();
} }
foreach ($tableForeignKeys as $key => $value) { foreach ($tableForeignKeys as $key => $value) {
$id = $value['id']; $id = $value['id'];
$tableForeignKeys[$key]['constraint_name'] = isset($names[$id]) && '' != $names[$id] ? $names[$id] : $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;
} }
} }
...@@ -293,7 +308,8 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -293,7 +308,8 @@ class SqliteSchemaManager extends AbstractSchemaManager
$list = array(); $list = array();
foreach ($tableForeignKeys as $key => $value) { foreach ($tableForeignKeys as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER); $value = array_change_key_case($value, CASE_LOWER);
if ( ! isset($list[$value['constraint_name']])) { $name = $value['constraint_name'];
if ( ! isset($list[$name])) {
if ( ! isset($value['on_delete']) || $value['on_delete'] == "RESTRICT") { if ( ! isset($value['on_delete']) || $value['on_delete'] == "RESTRICT") {
$value['on_delete'] = null; $value['on_delete'] = null;
} }
...@@ -301,17 +317,19 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -301,17 +317,19 @@ class SqliteSchemaManager extends AbstractSchemaManager
$value['on_update'] = null; $value['on_update'] = null;
} }
$list[$value['constraint_name']] = array( $list[$name] = array(
'name' => $value['constraint_name'], 'name' => $name,
'local' => array(), 'local' => array(),
'foreign' => array(), 'foreign' => array(),
'foreignTable' => $value['table'], 'foreignTable' => $value['table'],
'onDelete' => $value['on_delete'], 'onDelete' => $value['on_delete'],
'onUpdate' => $value['on_update'], 'onUpdate' => $value['on_update'],
'deferrable' => $value['deferrable'],
'deferred'=> $value['deferred'],
); );
} }
$list[$value['constraint_name']]['local'][] = $value['from']; $list[$name]['local'][] = $value['from'];
$list[$value['constraint_name']]['foreign'][] = $value['to']; $list[$name]['foreign'][] = $value['to'];
} }
$result = array(); $result = array();
...@@ -322,6 +340,8 @@ class SqliteSchemaManager extends AbstractSchemaManager ...@@ -322,6 +340,8 @@ class SqliteSchemaManager extends AbstractSchemaManager
array( array(
'onDelete' => $constraint['onDelete'], 'onDelete' => $constraint['onDelete'],
'onUpdate' => $constraint['onUpdate'], 'onUpdate' => $constraint['onUpdate'],
'deferrable' => $constraint['deferrable'],
'deferred'=> $constraint['deferred'],
) )
); );
} }
......
...@@ -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';
...@@ -45,4 +47,29 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase ...@@ -45,4 +47,29 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
return $table; 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'));
}
} }
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