1
0
mirror of synced 2025-02-20 06:03:15 +03:00

fix sequence and join columns

This commit is contained in:
Fabio B. Silva 2012-06-05 17:10:44 -03:00
parent 7215c1a3b1
commit a75c672ee7
11 changed files with 229 additions and 28 deletions

View File

@ -648,23 +648,40 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
// For PostgreSQL IDENTITY (SERIAL) we need a sequence name. It defaults to
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
// Not pretty but necessary and the simplest solution that currently works.
$seqName = $this->targetPlatform instanceof Platforms\PostgreSQLPlatform ?
$class->getTableName() . '_' . $class->columnNames[$class->identifier[0]] . '_seq' :
null;
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($seqName));
$sequenceName = null;
if($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
$fieldName = $class->getSingleIdentifierFieldName();
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
$definition = array(
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
);
if ($quoted) {
$definition['quoted'] = true;
}
$sequenceName = $this->em->getQuoteStrategy()->getSequenceName($definition, $class);
}
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($sequenceName));
break;
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
// If there is no sequence definition yet, create a default definition
$definition = $class->sequenceGeneratorDefinition;
if ( ! $definition) {
$sequenceName = $class->getTableName() . '_' . $class->getSingleIdentifierColumnName() . '_seq';
$definition['sequenceName'] = $this->targetPlatform->fixSchemaElementName($sequenceName);
$definition['allocationSize'] = 1;
$definition['initialValue'] = 1;
$fieldName = $class->getSingleIdentifierFieldName();
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
$definition['sequenceName'] = $this->targetPlatform->fixSchemaElementName($sequenceName);
$definition['allocationSize'] = 1;
$definition['initialValue'] = 1;
if ($quoted) {
$definition['quoted'] = true;
}
$class->setSequenceGeneratorDefinition($definition);
}
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
$definition['sequenceName'],
$this->em->getQuoteStrategy()->getSequenceName($definition, $class),
$definition['allocationSize']
);
$class->setIdGenerator($sequenceGenerator);

View File

@ -2567,9 +2567,10 @@ class ClassMetadataInfo implements ClassMetadata
* The definition must have the following structure:
* <code>
* array(
* 'sequenceName' => 'name',
* 'sequenceName' => 'name',
* 'allocationSize' => 20,
* 'initialValue' => 1
* 'initialValue' => 1
* 'quoted' => 1
* )
* </code>
*
@ -2577,6 +2578,11 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function setSequenceGeneratorDefinition(array $definition)
{
if (isset($definition['name']) && $definition['name'] == '`') {
$definition['name'] = trim($definition['name'], '`');
$definition['quoted'] = true;
}
$this->sequenceGeneratorDefinition = $definition;
}

View File

@ -49,6 +49,37 @@ class DefaultQuoteStrategy extends QuoteStrategy
: $class->table['name'];
}
/**
* {@inheritdoc}
*/
public function getSequenceName(array $definition, ClassMetadata $class)
{
return isset($definition['quoted'])
? $this->platform->quoteSingleIdentifier($definition['sequenceName'])
: $definition['sequenceName'];
}
/**
* {@inheritdoc}
*/
public function getJoinColumnName($columnName, array $association, ClassMetadata $class)
{
if( !isset($association['joinColumns'])) {
return $columnName;
}
foreach ($association['joinColumns'] as $joinColumn) {
if($joinColumn['name'] === $columnName) {
if (isset($joinColumn['quoted'])) {
return $this->platform->quoteIdentifier($columnName);
}
return $columnName;
}
}
return $columnName;
}
/**
* {@inheritdoc}
*/

View File

@ -60,14 +60,33 @@ abstract class QuoteStrategy
*/
abstract public function getTableName(ClassMetadata $class);
/**
* Gets the (possibly quoted) sequence name for safe use in an SQL statement.
*
* @param array $definition
* @param ClassMetadata $class
* @return string
*/
abstract public function getSequenceName(array $definition, ClassMetadata $class);
/**
* Gets the (possibly quoted) name of the join table.
*
* @param array $association
* @param ClassMetadata $class
* @return string
*/
abstract public function getJoinTableName(array $association, ClassMetadata $class);
/**
* Gets the (possibly quoted) join column name.
*
* @param array $association
* @param ClassMetadata $class
* @return string
*/
abstract public function getJoinColumnName($columnName, array $association, ClassMetadata $class);
/**
* Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
*

View File

@ -1080,10 +1080,11 @@ class BasicEntityPersister
foreach ($assoc['targetToSourceKeyColumns'] as $srcColumn) {
if ($columnList) $columnList .= ', ';
$quotedColumn = $this->quoteStrategy->getJoinColumnName($srcColumn, $assoc, $this->_class);
$resultColumnName = $this->getSQLColumnAlias($srcColumn);
$columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) )
. '.' . $srcColumn . ' AS ' . $resultColumnName;
$this->_rsm->addMetaResult($alias, $resultColumnName, $srcColumn, isset($assoc['id']) && $assoc['id'] === true);
. '.' . $quotedColumn . ' AS ' . $resultColumnName;
$this->_rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, isset($assoc['id']) && $assoc['id'] === true);
}
}
@ -1191,7 +1192,7 @@ class BasicEntityPersister
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) {
$columns[] = $sourceCol;
$columns[] = $this->quoteStrategy->getJoinColumnName($sourceCol, $assoc, $this->_class);
}
}
} else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) {

View File

@ -217,12 +217,12 @@ class SchemaTool
$pkColumns = array();
foreach ($class->identifier as $identifierField) {
if (isset($class->fieldMappings[$identifierField])) {
$pkColumns[] = $class->getColumnName($identifierField);
$pkColumns[] = $this->quoteStrategy->getColumnName($identifierField, $class);
} else if (isset($class->associationMappings[$identifierField])) {
/* @var $assoc \Doctrine\ORM\Mapping\OneToOne */
$assoc = $class->associationMappings[$identifierField];
foreach ($assoc['joinColumns'] as $joinColumn) {
$pkColumns[] = $joinColumn['name'];
$pkColumns[] = $this->quoteStrategy->getJoinColumnName($joinColumn['name'], $assoc, $class);
}
}
}
@ -252,11 +252,11 @@ class SchemaTool
$processedClasses[$class->name] = true;
if ($class->isIdGeneratorSequence() && $class->name == $class->rootEntityName) {
$seqDef = $class->sequenceGeneratorDefinition;
if (!$schema->hasSequence($seqDef['sequenceName'])) {
$seqDef = $class->sequenceGeneratorDefinition;
$quotedName = $this->quoteStrategy->getSequenceName($seqDef, $class);
if ( ! $schema->hasSequence($quotedName)) {
$schema->createSequence(
$seqDef['sequenceName'],
$quotedName,
$seqDef['allocationSize'],
$seqDef['initialValue']
);
@ -523,9 +523,10 @@ class SchemaTool
);
}
$primaryKeyColumns[] = $columnName;
$localColumns[] = $columnName;
$foreignColumns[] = $joinColumn['referencedColumnName'];
$primaryKeyColumns[] = $columnName;
$localColumns[] = $columnName;
$foreignColumns[] = $joinColumn['referencedColumnName'];
$quotedColumnName = $this->quoteStrategy->getJoinColumnName($columnName, $mapping, $class);
if ( ! $theJoinTable->hasColumn($joinColumn['name'])) {
// Only add the column to the table if it does not exist already.
@ -551,7 +552,7 @@ class SchemaTool
$columnOptions['precision'] = $fieldMapping['precision'];
}
$theJoinTable->addColumn($columnName, $fieldMapping['type'], $columnOptions);
$theJoinTable->addColumn($quotedColumnName, $fieldMapping['type'], $columnOptions);
}
if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) {

View File

@ -21,9 +21,20 @@ class Group
*/
public $name;
/**
* @ManyToOne(targetEntity="Group", cascade={"persist"})
* @JoinColumn(name="`parent-id`", referencedColumnName="`group-id`")
*/
public $parent;
/**
* @ManyToMany(targetEntity="User", mappedBy="groups")
*/
public $users;
public function __construct($name = null, Group $parent = null)
{
$this->name = $name;
$this->parent = $parent;
}
}

View File

@ -25,8 +25,8 @@ class DDC1151Test extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals("CREATE INDEX IDX_88A3259AC5AD08A ON ddc1151user_ddc1151group (ddc1151user_id)", $sql[2]);
$this->assertEquals("CREATE INDEX IDX_88A32597357E0B1 ON ddc1151user_ddc1151group (ddc1151group_id)", $sql[3]);
$this->assertEquals("CREATE TABLE \"Group\" (id INT NOT NULL, PRIMARY KEY(id))", $sql[4]);
$this->assertEquals("CREATE SEQUENCE User_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[5]);
$this->assertEquals("CREATE SEQUENCE Group_id_seq INCREMENT BY 1 MINVALUE 1 START 1", $sql[6]);
$this->assertEquals("CREATE SEQUENCE \"User_id_seq\" INCREMENT BY 1 MINVALUE 1 START 1", $sql[5]);
$this->assertEquals("CREATE SEQUENCE \"Group_id_seq\" INCREMENT BY 1 MINVALUE 1 START 1", $sql[6]);
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A3259AC5AD08A FOREIGN KEY (ddc1151user_id) REFERENCES \"User\" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[7]);
$this->assertEquals("ALTER TABLE ddc1151user_ddc1151group ADD CONSTRAINT FK_88A32597357E0B1 FOREIGN KEY (ddc1151group_id) REFERENCES \"Group\" (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE", $sql[8]);
}

View File

@ -21,7 +21,7 @@ class DDC1360Test extends OrmFunctionalTestCase
$this->assertEquals(array(
'CREATE TABLE "user"."user" (id INT NOT NULL, PRIMARY KEY(id))',
'CREATE SEQUENCE "user".user_id_seq INCREMENT BY 1 MINVALUE 1 START 1',
'CREATE SEQUENCE "user"."user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1',
), $sql);
}
}

View File

@ -0,0 +1,111 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
use Doctrine\Tests\Models\Quote\Group;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DDC-1843
*/
class DDC1843Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
const CLASS_NAME = '\Doctrine\Tests\Models\Quote\Group';
protected function setUp()
{
$this->markTestIncomplete();
parent::setUp();
$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
try {
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(self::CLASS_NAME),
));
} catch(\Exception $e) {
$this->fail($e->getMessage());
}
}
public function testCreateRetreaveUpdateDelete()
{
$e1 = new Group('Parent Bar 1');
$e2 = new Group('Parent Foo 2');
$this->_em->persist($e1);
$this->_em->persist($e2);
$this->_em->flush();
$e3 = new Group('Bar 3', $e1);
$e4 = new Group('Foo 4', $e2);
// Create
$this->_em->persist($e3);
$this->_em->persist($e4);
$this->_em->flush();
$this->_em->clear();
$e1Id = $e1->id;
$e2Id = $e2->id;
$e3Id = $e3->id;
$e4Id = $e4->id;
// Retreave
$e1 = $this->_em->find(self::CLASS_NAME, $e1Id);
$e2 = $this->_em->find(self::CLASS_NAME, $e2Id);
$e3 = $this->_em->find(self::CLASS_NAME, $e3Id);
$e4 = $this->_em->find(self::CLASS_NAME, $e4Id);
$this->assertInstanceOf(self::CLASS_NAME, $e1);
$this->assertInstanceOf(self::CLASS_NAME, $e2);
$this->assertInstanceOf(self::CLASS_NAME, $e3);
$this->assertInstanceOf(self::CLASS_NAME, $e4);
$this->assertEquals($e1Id, $e1->id);
$this->assertEquals($e2Id, $e2->id);
$this->assertEquals($e3Id, $e3->id);
$this->assertEquals($e4Id, $e4->id);
return;
$this->assertEquals('Bar 1', $e1->value);
$this->assertEquals('Foo 1', $e2->value);
$e1->value = 'Bar 2';
$e2->value = 'Foo 2';
// Update
$this->_em->persist($e1);
$this->_em->persist($e2);
$this->_em->flush();
$this->assertEquals('Bar 2', $e1->value);
$this->assertEquals('Foo 2', $e2->value);
$this->assertInstanceOf(self::CLASS_NAME, $e1);
$this->assertInstanceOf(self::CLASS_NAME, $e2);
$this->assertEquals($e1Id, $e1->id);
$this->assertEquals($e2Id, $e2->id);
$this->assertEquals('Bar 2', $e1->value);
$this->assertEquals('Foo 2', $e2->value);
// Delete
$this->_em->remove($e1);
$this->_em->remove($e2);
$this->_em->flush();
$e1 = $this->_em->find(self::CLASS_NAME, $e1Id);
$e2 = $this->_em->find(self::CLASS_NAME, $e2Id);
$this->assertNull($e1);
$this->assertNull($e2);
}
}

View File

@ -272,13 +272,17 @@ class ClassMetadataFactoryTest extends \Doctrine\Tests\OrmTestCase
// User Class Metadata
// User Group Metadata
$this->assertTrue($groupMetadata->fieldMappings['id']['quoted']);
$this->assertTrue($groupMetadata->fieldMappings['name']['quoted']);
$this->assertEquals('user-id', $userMetadata->fieldMappings['id']['columnName']);
$this->assertEquals('user-name', $userMetadata->fieldMappings['name']['columnName']);
$user = $groupMetadata->associationMappings['parent'];
$this->assertTrue($user['joinColumns'][0]['quoted']);
$this->assertEquals('parent-id', $user['joinColumns'][0]['name']);
$this->assertEquals('group-id', $user['joinColumns'][0]['referencedColumnName']);
// Address Class Metadata