fix sequence and join columns
This commit is contained in:
parent
7215c1a3b1
commit
a75c672ee7
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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}
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
111
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1843Test.php
Normal file
111
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1843Test.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user