Skip to content

Commit

Permalink
DBAL 205 - Fixes problem with composite foreign key support in MySqlS…
Browse files Browse the repository at this point in the history
…chemaManager
  • Loading branch information
sbeining authored and beberlei committed Jan 21, 2012
1 parent 0ca0be8 commit e07f380
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 17 deletions.
52 changes: 35 additions & 17 deletions lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php
Expand Up @@ -170,26 +170,44 @@ protected function _getPortableTableColumnDefinition($tableColumn)
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") {
$tableForeignKey['delete_rule'] = null;
$list[$value['constraint_name']] = array(
'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(
(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'],
)
);
return $result;
}
}
}
Expand Up @@ -535,4 +535,28 @@ protected function assertHasTable($tables, $tableName)
}
$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()));
}
}
76 changes: 76 additions & 0 deletions tests/Doctrine/Tests/DBAL/Schema/MySqlSchemaManagerTest.php
@@ -0,0 +1,76 @@
<?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",
)
);
}
}

0 comments on commit e07f380

Please sign in to comment.