1
0
mirror of synced 2024-12-13 06:46:03 +03:00

[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:
beberlei 2009-12-04 21:40:03 +00:00
parent 466e96b491
commit 556f8699ee
9 changed files with 232 additions and 34 deletions

View File

@ -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);
}
}

View File

@ -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));
}
/**

View File

@ -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;

View File

@ -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()) {

View File

@ -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());

View File

@ -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

View File

@ -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

View 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");
}
}

View File

@ -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++) {