1
0
mirror of synced 2025-01-18 06:21:40 +03:00

Merge pull request #890 from deeky666/DBAL-563

[DBAL-563] Add general IDENTITY generator type support for sequence emulating platforms
This commit is contained in:
Guilherme Blanco 2013-12-30 21:34:20 -08:00
commit a7b9140d2f
3 changed files with 97 additions and 62 deletions

View File

@ -448,17 +448,15 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
// Create & assign an appropriate ID generator instance
switch ($class->generatorType) {
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;
$fieldName = $class->identifier ? $class->getSingleIdentifierFieldName() : null;
if ($this->targetPlatform instanceof Platforms\PostgreSqlPlatform) {
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
$definition = array(
// Platforms that do not have native IDENTITY support need a sequence to emulate this behaviour.
if ($this->targetPlatform->usesSequenceEmulatedIdentityColumns()) {
$columnName = $class->getSingleIdentifierColumnName();
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
$sequenceName = $this->targetPlatform->getIdentitySequenceName($class->getTableName(), $columnName);
$definition = array(
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
);
@ -466,7 +464,11 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
$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')

View File

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

View File

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