[2.0] DDC-186 - Fixed DatabaseDriver to work with new Schema abstraction, added functional test-cases for database to yaml convertion.
This commit is contained in:
parent
466e96b491
commit
556f8699ee
@ -44,6 +44,16 @@ use Doctrine\DBAL\DBALException,
|
||||
*/
|
||||
abstract class AbstractPlatform
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
const CREATE_INDEXES = 1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
const CREATE_FOREIGNKEYS = 2;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
@ -530,29 +540,34 @@ abstract class AbstractPlatform
|
||||
* on this platform.
|
||||
*
|
||||
* @param string $table The name of the table.
|
||||
* @param array $columns The column definitions for the table.
|
||||
* @param array $options The table constraints.
|
||||
* @param int $createFlags
|
||||
* @return array The sequence of SQL statements.
|
||||
*/
|
||||
public function getCreateTableSql(Table $table)
|
||||
public function getCreateTableSql(Table $table, $createFlags=self::CREATE_INDEXES)
|
||||
{
|
||||
if (!is_int($createFlags)) {
|
||||
throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSql() has to be integer.");
|
||||
}
|
||||
|
||||
$tableName = $table->getName();
|
||||
$options = $table->getOptions();
|
||||
$options['uniqueConstraints'] = array();
|
||||
$options['indexes'] = array();
|
||||
$options['primary'] = array();
|
||||
|
||||
foreach($table->getIndexes() AS $index) {
|
||||
/* @var $index Index */
|
||||
if($index->isPrimary()) {
|
||||
$options['primary'] = $index->getColumns();
|
||||
} else {
|
||||
$options['indexes'][$index->getName()] = $index;
|
||||
if (($createFlags&self::CREATE_INDEXES) > 0) {
|
||||
foreach ($table->getIndexes() AS $index) {
|
||||
/* @var $index Index */
|
||||
if ($index->isPrimary()) {
|
||||
$options['primary'] = $index->getColumns();
|
||||
} else {
|
||||
$options['indexes'][$index->getName()] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$columns = array();
|
||||
foreach($table->getColumns() AS $column) {
|
||||
foreach ($table->getColumns() AS $column) {
|
||||
/* @var \Doctrine\DBAL\Schema\Column $column */
|
||||
$columnData = array();
|
||||
$columnData['name'] = $column->getName();
|
||||
@ -580,16 +595,23 @@ abstract class AbstractPlatform
|
||||
$columns[$columnData['name']] = $columnData;
|
||||
}
|
||||
|
||||
if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) {
|
||||
$options['foreignKeys'] = array();
|
||||
foreach ($table->getForeignKeys() AS $fkConstraint) {
|
||||
$options['foreignKeys'][] = $fkConstraint;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_getCreateTableSql($tableName, $columns, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param string $tableName
|
||||
* @param array $columns
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected function _getCreateTableSql($table, array $columns, array $options = array())
|
||||
protected function _getCreateTableSql($tableName, array $columns, array $options = array())
|
||||
{
|
||||
$columnListSql = $this->getColumnDeclarationListSql($columns);
|
||||
|
||||
@ -609,7 +631,7 @@ abstract class AbstractPlatform
|
||||
}
|
||||
}
|
||||
|
||||
$query = 'CREATE TABLE ' . $table . ' (' . $columnListSql;
|
||||
$query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql;
|
||||
|
||||
$check = $this->getCheckDeclarationSql($columns);
|
||||
if ( ! empty($check)) {
|
||||
@ -621,7 +643,7 @@ abstract class AbstractPlatform
|
||||
|
||||
if (isset($options['foreignKeys'])) {
|
||||
foreach ((array) $options['foreignKeys'] AS $definition) {
|
||||
$sql[] = $this->getCreateForeignKeySql($definition, $name);
|
||||
$sql[] = $this->getCreateForeignKeySql($definition, $tableName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ namespace Doctrine\DBAL\Schema;
|
||||
use \Doctrine\DBAL\Types;
|
||||
use \Doctrine\Common\DoctrineException;
|
||||
use \Doctrine\DBAL\DBALException;
|
||||
use \Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
/**
|
||||
* Base class for schema managers. Schema managers are used to inspect and/or
|
||||
@ -65,6 +66,16 @@ abstract class AbstractSchemaManager
|
||||
$this->_platform = $this->_conn->getDatabasePlatform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return associated platform.
|
||||
*
|
||||
* @return \Doctrine\DBAL\Platform\AbstractPlatform
|
||||
*/
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return $this->_platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try any method on the schema manager. Normally a method throws an
|
||||
* exception when your DBMS doesn't support it or if an error occurs.
|
||||
@ -410,10 +421,12 @@ abstract class AbstractSchemaManager
|
||||
* Create a new table.
|
||||
*
|
||||
* @param Table $table
|
||||
* @param int $createFlags
|
||||
*/
|
||||
public function createTable(Table $table)
|
||||
{
|
||||
$this->_execSql($this->_platform->getCreateTableSql($table));
|
||||
$createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
|
||||
$this->_execSql($this->_platform->getCreateTableSql($table, $createFlags));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,35 +68,42 @@ class DatabaseDriver implements Driver
|
||||
$metadata->primaryTable['name'] = $tableName;
|
||||
|
||||
$columns = $this->_sm->listTableColumns($tableName);
|
||||
try {
|
||||
|
||||
if($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$foreignKeys = $this->_sm->listTableForeignKeys($tableName);
|
||||
} catch (\Doctrine\Common\DoctrineException $e) {
|
||||
} else {
|
||||
$foreignKeys = array();
|
||||
}
|
||||
|
||||
$indexes = $this->_sm->listTableIndexes($tableName);
|
||||
|
||||
$ids = array();
|
||||
$fieldMappings = array();
|
||||
foreach ($columns as $column) {
|
||||
// Skip columns that are foreign keys
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
if ($column['name'] == $foreignKey['local']) {
|
||||
if (in_array($column->getName(), $foreignKey->getColumns())) {
|
||||
continue(2);
|
||||
}
|
||||
}
|
||||
|
||||
$fieldMapping = array();
|
||||
if ($column['primary']) {
|
||||
if (in_array($column->getName(), $indexes['primary']->getColumns())) {
|
||||
$fieldMapping['id'] = true;
|
||||
}
|
||||
|
||||
$fieldMapping['fieldName'] = Inflector::camelize($column['name']);
|
||||
$fieldMapping['columnName'] = $column['name'];
|
||||
$fieldMapping['type'] = strtolower((string) $column['type']);
|
||||
$fieldMapping['length'] = $column['length'];
|
||||
$fieldMapping['unsigned'] = $column['unsigned'];
|
||||
$fieldMapping['fixed'] = $column['fixed'];
|
||||
$fieldMapping['notnull'] = $column['notnull'];
|
||||
$fieldMapping['default'] = $column['default'];
|
||||
$fieldMapping['fieldName'] = Inflector::camelize($column->getName());
|
||||
$fieldMapping['columnName'] = $column->getName();
|
||||
$fieldMapping['type'] = strtolower((string) $column->getType());
|
||||
|
||||
if ($column->getType() instanceof \Doctrine\DBAL\Types\StringType) {
|
||||
$fieldMapping['length'] = $column->getLength();
|
||||
$fieldMapping['fixed'] = $column->getFixed();
|
||||
} else if ($column->getType() instanceof \Doctrine\DBAL\Types\IntegerType) {
|
||||
$fieldMapping['unsigned'] = $column->getUnsigned();
|
||||
}
|
||||
$fieldMapping['notnull'] = $column->getNotNull();
|
||||
$fieldMapping['default'] = $column->getDefault();
|
||||
|
||||
if (isset($fieldMapping['id'])) {
|
||||
$ids[] = $fieldMapping;
|
||||
@ -120,13 +127,27 @@ class DatabaseDriver implements Driver
|
||||
}
|
||||
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
if (count($foreignKey->getColumns()) != 1) {
|
||||
throw new MappingException(
|
||||
"Cannot generate mapping for table '".$tableName."' with foreign keys with multiple local columns."
|
||||
);
|
||||
}
|
||||
$localColumn = current($foreignKey->getColumns());
|
||||
|
||||
if (count($foreignKey->getForeignColumns()) != 1) {
|
||||
throw new MappingException(
|
||||
"Cannot generate mapping for table '".$tableName."' with foreign keys with multiple foreign columns."
|
||||
);
|
||||
}
|
||||
$foreignColumn = current($foreignKey->getForeignColumns());
|
||||
|
||||
$associationMapping = array();
|
||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', $foreignKey['local']));
|
||||
$associationMapping['columnName'] = $foreignKey['local'];
|
||||
$associationMapping['targetEntity'] = Inflector::classify($foreignKey['table']);
|
||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', $localColumn));
|
||||
$associationMapping['columnName'] = $localColumn;
|
||||
$associationMapping['targetEntity'] = Inflector::classify($foreignKey->getForeignTableName());
|
||||
$associationMapping['joinColumns'][] = array(
|
||||
'name' => $foreignKey['local'],
|
||||
'referencedColumnName' => $foreignKey['foreign']
|
||||
'name' => $localColumn,
|
||||
'referencedColumnName' => $foreignColumn
|
||||
);
|
||||
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
@ -156,7 +177,7 @@ class DatabaseDriver implements Driver
|
||||
{
|
||||
$tables = array();
|
||||
foreach ($this->_sm->listTables() as $table) {
|
||||
$tables[] = $table;
|
||||
$tables[] = $table->getName();
|
||||
}
|
||||
|
||||
return $tables;
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
namespace Doctrine\Tests\DBAL\Functional\Schema;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Types\Type,
|
||||
Doctrine\DBAL\Schema\AbstractSchemaManager;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
@ -197,6 +198,31 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
|
||||
$this->assertFalse($tableIndexes['test']->isPrimary());
|
||||
}
|
||||
|
||||
public function testCreateTableWithForeignKeys()
|
||||
{
|
||||
if(!$this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$this->markTestSkipped('Platform does not support foreign keys.');
|
||||
}
|
||||
|
||||
$tableB = $this->getTestTable('test_foreign');
|
||||
|
||||
$this->_sm->dropAndCreateTable($tableB);
|
||||
|
||||
$tableA = $this->getTestTable('test_create_fk');
|
||||
$tableA->addForeignKeyConstraint('test_foreign', array('foreign_key_test'), array('id'));
|
||||
|
||||
$this->_sm->dropAndCreateTable($tableA);
|
||||
|
||||
$fkConstraints = $this->_sm->listTableForeignKeys('test_create_fk');
|
||||
$this->assertEquals(1, count($fkConstraints));
|
||||
|
||||
$fkConstraint = current($fkConstraints);
|
||||
$fkConstraint->setCaseMode("lower");
|
||||
$this->assertEquals('test_foreign', $fkConstraint->getForeignTableName());
|
||||
$this->assertEquals(array('foreign_key_test'), $fkConstraint->getColumns());
|
||||
$this->assertEquals(array('id'), $fkConstraint->getForeignColumns());
|
||||
}
|
||||
|
||||
public function testListForeignKeys()
|
||||
{
|
||||
if(!$this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
|
@ -45,6 +45,7 @@ class AllTests
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\MappedSuperclassTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\EntityRepositoryTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\IdentityMapTest');
|
||||
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\DatabaseDriverTest');
|
||||
|
||||
$suite->addTest(Locking\AllTests::suite());
|
||||
$suite->addTest(SchemaTool\AllTests::suite());
|
||||
|
@ -0,0 +1,26 @@
|
||||
DbdriverBaz:
|
||||
type: entity
|
||||
table: dbdriver_baz
|
||||
fields:
|
||||
id:
|
||||
id: true
|
||||
type: integer
|
||||
unsigned: false
|
||||
notnull: true
|
||||
default: null
|
||||
generator:
|
||||
strategy: AUTO
|
||||
oneToOne:
|
||||
bar:
|
||||
targetEntity: DbdriverBar
|
||||
cascade:
|
||||
remove: false
|
||||
persist: false
|
||||
refresh: false
|
||||
merge: false
|
||||
detach: false
|
||||
mappedBy: null
|
||||
joinColumns:
|
||||
bar_id:
|
||||
referencedColumnName: id
|
||||
orphanRemoval: false
|
@ -0,0 +1,17 @@
|
||||
DbdriverFoo:
|
||||
type: entity
|
||||
table: dbdriver_foo
|
||||
fields:
|
||||
id:
|
||||
id: true
|
||||
type: integer
|
||||
unsigned: false
|
||||
notnull: true
|
||||
default: null
|
||||
generator:
|
||||
strategy: AUTO
|
||||
bar:
|
||||
type: string(200)
|
||||
fixed: false
|
||||
notnull: true
|
||||
default: null
|
68
tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php
Normal file
68
tests/Doctrine/Tests/ORM/Functional/DatabaseDriverTest.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
use Doctrine\ORM\Tools\Export\ClassMetadataExporter;
|
||||
|
||||
class DatabaseDriverTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
protected $_sm = null;
|
||||
|
||||
public function testCreateSimpleYamlFromDatabase()
|
||||
{
|
||||
$table = new \Doctrine\DBAL\Schema\Table("dbdriver_foo");
|
||||
$table->createColumn('id', 'integer');
|
||||
$table->setPrimaryKey(array('id'));
|
||||
$table->createColumn('bar', 'string', array('length' => 200));
|
||||
|
||||
$this->_sm = $this->_em->getConnection()->getSchemaManager();
|
||||
$this->_sm->dropAndCreateTable($table);
|
||||
|
||||
$this->assertClassMetadataYamlEqualsFile(__DIR__."/DatabaseDriver/simpleYaml.yml", "DbdriverFoo");
|
||||
}
|
||||
|
||||
protected function assertClassMetadataYamlEqualsFile($file, $className)
|
||||
{
|
||||
$cm = new ClassMetadataExporter();
|
||||
$cm->addMappingSource($this->_sm, 'database');
|
||||
$exporter = $cm->getExporter('yaml');
|
||||
$metadatas = $cm->getMetadatasForMappingSources();
|
||||
|
||||
$output = false;
|
||||
foreach ($metadatas AS $metadata) {
|
||||
if ($metadata->name == $className) {
|
||||
$output = $exporter->exportClassMetadata($metadata);
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue($output!==false, "No class matching the name '".$className."' was found!");
|
||||
$this->assertEquals(strtolower(trim(file_get_contents($file))), strtolower(trim($output)));
|
||||
}
|
||||
|
||||
public function testCreateYamlWithForeignKeyFromDatabase()
|
||||
{
|
||||
if (!$this->_em->getConnection()->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$this->markTestSkipped('Platform does not support foreign keys.');
|
||||
}
|
||||
|
||||
$tableB = new \Doctrine\DBAL\Schema\Table("dbdriver_bar");
|
||||
$tableB->createColumn('id', 'integer');
|
||||
$tableB->setPrimaryKey(array('id'));
|
||||
|
||||
$sm = $this->_em->getConnection()->getSchemaManager();
|
||||
$sm->dropAndCreateTable($tableB);
|
||||
|
||||
$tableA = new \Doctrine\DBAL\Schema\Table("dbdriver_baz");
|
||||
$tableA->createColumn('id', 'integer');
|
||||
$tableA->setPrimaryKey(array('id'));
|
||||
$tableA->createColumn('bar_id', 'integer');
|
||||
$tableA->addForeignKeyConstraint('dbdriver_bar', array('bar_id'), array('id'));
|
||||
|
||||
$this->_sm = $this->_em->getConnection()->getSchemaManager();
|
||||
$this->_sm->dropAndCreateTable($tableA);
|
||||
|
||||
$this->assertClassMetadataYamlEqualsFile(__DIR__."/DatabaseDriver/fkYaml.yml", "DbdriverBaz");
|
||||
}
|
||||
}
|
@ -209,6 +209,10 @@ class OrmFunctionalTestCase extends OrmTestCase
|
||||
|
||||
protected function onNotSuccessfulTest(\Exception $e)
|
||||
{
|
||||
if ($e instanceof \PHPUnit_Framework_ExpectationFailedException) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if($this->_sqlLoggerStack->queries !== null && count($this->_sqlLoggerStack->queries)) {
|
||||
$queries = "";
|
||||
for($i = 0; $i < count($this->_sqlLoggerStack->queries); $i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user