Skip to content
Browse files

Improved foreign key definition parsing in SqliteSchemaManager

  • Loading branch information...
1 parent ff630e2 commit 16d0c3e52aaa4ce5fcd7fa77db3d2e92626227b0 @hason hason committed Nov 18, 2012
View
34 lib/Doctrine/DBAL/Schema/SqliteSchemaManager.php
@@ -28,6 +28,7 @@
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library)
* @author Jonathan H. Wage <jonwage@gmail.com>
+ * @author Martin Hasoň <martin.hason@gmail.com>
* @version $Revision$
* @since 2.0
*/
@@ -121,15 +122,29 @@ public function listTableForeignKeys($table, $database = null)
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)) {
+ 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 = array();
+ $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;
}
}
@@ -293,25 +308,28 @@ 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']])) {
+ $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[$value['constraint_name']] = array(
- 'name' => $value['constraint_name'],
+ $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[$value['constraint_name']]['local'][] = $value['from'];
- $list[$value['constraint_name']]['foreign'][] = $value['to'];
+ $list[$name]['local'][] = $value['from'];
+ $list[$name]['foreign'][] = $value['to'];
}
$result = array();
@@ -322,6 +340,8 @@ protected function _getPortableTableForeignKeysList($tableForeignKeys)
array(
'onDelete' => $constraint['onDelete'],
'onUpdate' => $constraint['onUpdate'],
+ 'deferrable' => $constraint['deferrable'],
+ 'deferred'=> $constraint['deferred'],
)
);
}
View
27 tests/Doctrine/Tests/DBAL/Functional/Schema/SqliteSchemaManagerTest.php
@@ -2,6 +2,8 @@
namespace Doctrine\Tests\DBAL\Functional\Schema;
+use Doctrine\DBAL\Schema\ForeignKeyConstraint;
+
use Doctrine\DBAL\Schema;
require_once __DIR__ . '/../../../TestInit.php';
@@ -45,4 +47,29 @@ public function createListTableColumns()
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'));
+ }
}

0 comments on commit 16d0c3e

Please sign in to comment.
Something went wrong with that request. Please try again.