add general IDENTITY generator type support for sequence emulating platforms
This commit is contained in:
parent
7360231b4b
commit
337857dc8a
@ -448,16 +448,14 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
|||||||
// Create & assign an appropriate ID generator instance
|
// Create & assign an appropriate ID generator instance
|
||||||
switch ($class->generatorType) {
|
switch ($class->generatorType) {
|
||||||
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
|
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
|
||||||
// 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.
|
|
||||||
$sequenceName = null;
|
$sequenceName = null;
|
||||||
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
|
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
|
||||||
|
|
||||||
if ($this->targetPlatform instanceof Platforms\PostgreSqlPlatform) {
|
// Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
|
||||||
|
if ($this->targetPlatform->usesSequenceEmulatedIdentityColumns()) {
|
||||||
$columnName = $class->getSingleIdentifierColumnName();
|
$columnName = $class->getSingleIdentifierColumnName();
|
||||||
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
||||||
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
|
$sequenceName = $this->targetPlatform->getIdentitySequenceName($class->getTableName(), $columnName);
|
||||||
$definition = array(
|
$definition = array(
|
||||||
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
|
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
|
||||||
);
|
);
|
||||||
@ -466,7 +464,11 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
|
|||||||
$definition['quoted'] = true;
|
$definition['quoted'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
|
$sequenceName = $this
|
||||||
|
->em
|
||||||
|
->getConfiguration()
|
||||||
|
->getQuoteStrategy()
|
||||||
|
->getSequenceName($definition, $class, $this->targetPlatform);
|
||||||
}
|
}
|
||||||
|
|
||||||
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint')
|
$generator = ($fieldName && $class->fieldMappings[$fieldName]['type'] === 'bigint')
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Doctrine\Tests\ORM\Functional;
|
|
||||||
|
|
||||||
use Doctrine\ORM\Event\PreUpdateEventArgs;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../TestInit.php';
|
|
||||||
|
|
||||||
class PostgreSQLIdentityStrategyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|
||||||
{
|
|
||||||
protected function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != 'postgresql') {
|
|
||||||
$this->markTestSkipped('This test is special to the PostgreSQL IDENTITY key generation strategy.');
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
$this->_schemaTool->createSchema(array(
|
|
||||||
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\PostgreSQLIdentityEntity'),
|
|
||||||
));
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Swallow all exceptions. We do not test the schema tool here.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function tearDown() {
|
|
||||||
parent::tearDown();
|
|
||||||
// drop sequence manually due to dependency
|
|
||||||
$this->_em->getConnection()->exec('DROP SEQUENCE postgresqlidentityentity_id_seq CASCADE');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testPreSavePostSaveCallbacksAreInvoked()
|
|
||||||
{
|
|
||||||
$entity = new PostgreSQLIdentityEntity();
|
|
||||||
$entity->setValue('hello');
|
|
||||||
$this->_em->persist($entity);
|
|
||||||
$this->_em->flush();
|
|
||||||
$this->assertTrue(is_numeric($entity->getId()));
|
|
||||||
$this->assertTrue($entity->getId() > 0);
|
|
||||||
$this->assertTrue($this->_em->contains($entity));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @Entity */
|
|
||||||
class PostgreSQLIdentityEntity {
|
|
||||||
/** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
|
|
||||||
private $id;
|
|
||||||
/** @Column(type="string") */
|
|
||||||
private $value;
|
|
||||||
public function getId() {return $this->id;}
|
|
||||||
public function getValue() {return $this->value;}
|
|
||||||
public function setValue($value) {$this->value = $value;}
|
|
||||||
}
|
|
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Sequence;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
class SequenceEmulatedIdentityStrategyTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
if ( ! $this->_em->getConnection()->getDatabasePlatform()->usesSequenceEmulatedIdentityColumns()) {
|
||||||
|
$this->markTestSkipped(
|
||||||
|
'This test is special to platforms emulating IDENTITY key generation strategy through sequences.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$this->_schemaTool->createSchema(
|
||||||
|
array($this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\SequenceEmulatedIdentityEntity'))
|
||||||
|
);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Swallow all exceptions. We do not test the schema tool here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function tearDown()
|
||||||
|
{
|
||||||
|
parent::tearDown();
|
||||||
|
|
||||||
|
$connection = $this->_em->getConnection();
|
||||||
|
$platform = $connection->getDatabasePlatform();
|
||||||
|
|
||||||
|
// drop sequence manually due to dependency
|
||||||
|
$connection->exec(
|
||||||
|
$platform->getDropSequenceSQL(
|
||||||
|
new Sequence($platform->getIdentitySequenceName('seq_identity', 'id'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPreSavePostSaveCallbacksAreInvoked()
|
||||||
|
{
|
||||||
|
$entity = new SequenceEmulatedIdentityEntity();
|
||||||
|
$entity->setValue('hello');
|
||||||
|
$this->_em->persist($entity);
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->assertTrue(is_numeric($entity->getId()));
|
||||||
|
$this->assertTrue($entity->getId() > 0);
|
||||||
|
$this->assertTrue($this->_em->contains($entity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @Entity @Table(name="seq_identity") */
|
||||||
|
class SequenceEmulatedIdentityEntity
|
||||||
|
{
|
||||||
|
/** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/** @Column(type="string") */
|
||||||
|
private $value;
|
||||||
|
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setValue($value)
|
||||||
|
{
|
||||||
|
$this->value = $value;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user