diff --git a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php index 1d478aaccc4..ffa310544ec 100644 --- a/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php +++ b/lib/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -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; } -} \ No newline at end of file +} diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php index acb3ca5b200..ac9fa8e082a 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php @@ -615,4 +615,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())); + } } diff --git a/tests/Doctrine/Tests/DBAL/Schema/MySqlSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Schema/MySqlSchemaManagerTest.php new file mode 100644 index 00000000000..e5033d68380 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Schema/MySqlSchemaManagerTest.php @@ -0,0 +1,76 @@ +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", + ) + ); + } +}