Commit b2370d5e authored by Sascha Beining's avatar Sascha Beining Committed by Benjamin Eberlei

DBAL 205 - Fixes problem with composite foreign key support in MySqlSchemaManager

parent 7c336921
...@@ -170,26 +170,44 @@ class MySqlSchemaManager extends AbstractSchemaManager ...@@ -170,26 +170,44 @@ class MySqlSchemaManager extends AbstractSchemaManager
return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options);
} }
public function _getPortableTableForeignKeyDefinition($tableForeignKey) protected function _getPortableTableForeignKeysList($tableForeignKeys)
{ {
$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); $list = array();
foreach ($tableForeignKeys as $key => $value) {
$value = array_change_key_case($value, CASE_LOWER);
if (!isset($list[$value['constraint_name']])) {
if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") {
$value['delete_rule'] = null;
}
if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") {
$value['update_rule'] = null;
}
if (!isset($tableForeignKey['delete_rule']) || $tableForeignKey['delete_rule'] == "RESTRICT") { $list[$value['constraint_name']] = array(
$tableForeignKey['delete_rule'] = null; 'name' => $value['constraint_name'],
'local' => array(),
'foreign' => array(),
'foreignTable' => $value['referenced_table_name'],
'onDelete' => $value['delete_rule'],
'onUpdate' => $value['update_rule'],
);
}
$list[$value['constraint_name']]['local'][] = $value['column_name'];
$list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
} }
if (!isset($tableForeignKey['update_rule']) || $tableForeignKey['update_rule'] == "RESTRICT") {
$tableForeignKey['update_rule'] = null; $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 new ForeignKeyConstraint( return $result;
(array)$tableForeignKey['column_name'],
$tableForeignKey['referenced_table_name'],
(array)$tableForeignKey['referenced_column_name'],
$tableForeignKey['constraint_name'],
array(
'onUpdate' => $tableForeignKey['update_rule'],
'onDelete' => $tableForeignKey['delete_rule'],
)
);
} }
} }
\ No newline at end of file
...@@ -615,4 +615,28 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest ...@@ -615,4 +615,28 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
} }
$this->assertTrue($foundTable, "Could not find new table"); $this->assertTrue($foundTable, "Could not find new table");
} }
public function testListForeignKeysComposite()
{
if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
$this->markTestSkipped('Does not support foreign key constraints.');
}
$this->_sm->createTable($this->getTestTable('test_create_fk3'));
$this->_sm->createTable($this->getTestCompositeTable('test_create_fk4'));
$foreignKey = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
array('id', 'foreign_key_test'), 'test_create_fk4', array('id', 'other_id'), 'foreign_key_test_fk'
);
$this->_sm->createForeignKey($foreignKey, 'test_create_fk3');
$fkeys = $this->_sm->listTableForeignKeys('test_create_fk3');
$this->assertEquals(1, count($fkeys), "Table 'test_create_fk3' has to have one foreign key.");
$this->assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
$this->assertEquals(array('id', 'foreign_key_test'), array_map('strtolower', $fkeys[0]->getLocalColumns()));
$this->assertEquals(array('id', 'other_id'), array_map('strtolower', $fkeys[0]->getForeignColumns()));
}
} }
<?php
namespace Doctrine\Tests\DBAL\Schema;
require_once __DIR__ . '/../../TestInit.php';
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Events;
use Doctrine\DBAL\Schema\MySqlSchemaManager;
use Doctrine\Tests\DBAL\Mocks;
use Doctrine\Tests\TestUtil;
class MySqlSchemaManagerTest extends \PHPUnit_Framework_TestCase
{
/**
*
* @var \Doctrine\DBAL\Schema\AbstractSchemaManager
*/
private $manager;
public function setUp()
{
$eventManager = new EventManager();
$driverMock = $this->getMock('Doctrine\DBAL\Driver');
$platform = $this->getMock('Doctrine\DBAL\Platforms\MySqlPlatform');
$this->conn = $this->getMock(
'Doctrine\DBAL\Connection',
array('fetchAll'),
array(array('platform' => $platform), $driverMock, new Configuration(), $eventManager)
);
$this->manager = new MySqlSchemaManager($this->conn);
}
public function testCompositeForeignKeys()
{
$this->conn->expects($this->once())->method('fetchAll')->will($this->returnValue($this->getFKDefinition()));
$fkeys = $this->manager->listTableForeignKeys('dummy');
$this->assertEquals(1, count($fkeys), "Table has to have one foreign key.");
$this->assertInstanceOf('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
$this->assertEquals(array('column_1', 'column_2', 'column_3'), array_map('strtolower', $fkeys[0]->getLocalColumns()));
$this->assertEquals(array('column_1', 'column_2', 'column_3'), array_map('strtolower', $fkeys[0]->getForeignColumns()));
}
public function getFKDefinition()
{
return array(
array(
"CONSTRAINT_NAME" => "FK_C1B1712387FE737264DE5A5511B8B3E",
"COLUMN_NAME" => "column_1",
"REFERENCED_TABLE_NAME" => "dummy",
"REFERENCED_COLUMN_NAME" => "column_1",
"update_rule" => "RESTRICT",
"delete_rule" => "RESTRICT",
),
array(
"CONSTRAINT_NAME" => "FK_C1B1712387FE737264DE5A5511B8B3E",
"COLUMN_NAME" => "column_2",
"REFERENCED_TABLE_NAME" => "dummy",
"REFERENCED_COLUMN_NAME" => "column_2",
"update_rule" => "RESTRICT",
"delete_rule" => "RESTRICT",
),
array(
"CONSTRAINT_NAME" => "FK_C1B1712387FE737264DE5A5511B8B3E",
"COLUMN_NAME" => "column_3",
"REFERENCED_TABLE_NAME" => "dummy",
"REFERENCED_COLUMN_NAME" => "column_3",
"update_rule" => "RESTRICT",
"delete_rule" => "RESTRICT",
)
);
}
}
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