[DDC-576] Fixed.
This commit is contained in:
parent
20c6259fa3
commit
561236bd56
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
@ -21,17 +19,17 @@
|
||||
|
||||
namespace Doctrine\DBAL\Driver\PDOMsSql;
|
||||
|
||||
use PDO, Doctrine\DBAL\Driver\Connection as DriverConnection;
|
||||
|
||||
/**
|
||||
* MsSql Connection implementation.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
class Connection extends \PDO implements \Doctrine\DBAL\Driver\Connection
|
||||
class Connection extends PDO implements DriverConnection
|
||||
{
|
||||
/**
|
||||
* Performs the rollback.
|
||||
*
|
||||
* @override
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
@ -39,9 +37,7 @@ class Connection extends \PDO implements \Doctrine\DBAL\Driver\Connection
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the commit.
|
||||
*
|
||||
* @override
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
@ -49,12 +45,21 @@ class Connection extends \PDO implements \Doctrine\DBAL\Driver\Connection
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins a database transaction.
|
||||
*
|
||||
* @override
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
$this->exec('BEGIN TRANSACTION');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lastInsertId($name = null)
|
||||
{
|
||||
$stmt = $this->query('SELECT SCOPE_IDENTITY()');
|
||||
$id = $stmt->fetchColumn();
|
||||
$stmt->closeCursor();
|
||||
return $id;
|
||||
}
|
||||
}
|
@ -21,23 +21,36 @@ namespace Doctrine\ORM\Id;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* Id generator that obtains IDs from special "identity" columns. These are columns
|
||||
* that automatically get a database-generated, auto-incremented identifier on INSERT.
|
||||
* This generator obtains the last insert id after such an insert.
|
||||
*/
|
||||
class IdentityGenerator extends AbstractIdGenerator
|
||||
{
|
||||
/** @var string The name of the sequence to pass to lastInsertId(), if any. */
|
||||
private $_seqName;
|
||||
|
||||
/**
|
||||
* Generates an ID for the given entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @return integer|float
|
||||
* @override
|
||||
* @param string $seqName The name of the sequence to pass to lastInsertId()
|
||||
* to obtain the last generated identifier within the current
|
||||
* database session/connection, if any.
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
public function __construct($seqName = null)
|
||||
{
|
||||
return $em->getConnection()->lastInsertId();
|
||||
$this->_seqName = $seqName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @override
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
return $em->getConnection()->lastInsertId($this->_seqName);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isPostInsertGenerator()
|
||||
{
|
||||
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
class SequenceIdentityGenerator extends IdentityGenerator
|
||||
{
|
||||
private $_sequenceName;
|
||||
|
||||
public function __construct($sequenceName)
|
||||
{
|
||||
$this->_sequenceName = $sequenceName;
|
||||
}
|
||||
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
return $em->getConnection()->lastInsertId($this->_sequenceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
* @override
|
||||
*/
|
||||
public function isPostInsertGenerator()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -19,8 +19,10 @@
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\ORM\ORMException,
|
||||
Doctrine\DBAL\Platforms\AbstractPlatform,
|
||||
use ReflectionException,
|
||||
Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\DBAL\Platforms,
|
||||
Doctrine\ORM\Events;
|
||||
|
||||
/**
|
||||
@ -53,7 +55,7 @@ class ClassMetadataFactory
|
||||
*
|
||||
* @param $driver The metadata driver to use.
|
||||
*/
|
||||
public function __construct(\Doctrine\ORM\EntityManager $em)
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
}
|
||||
@ -94,15 +96,15 @@ class ClassMetadataFactory
|
||||
if ( ! $this->_initialized) {
|
||||
$this->_initialize();
|
||||
}
|
||||
|
||||
|
||||
$metadata = array();
|
||||
foreach ($this->_driver->getAllClassNames() as $className) {
|
||||
$metadata[] = $this->getMetadataFor($className);
|
||||
}
|
||||
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lazy initialization of this stuff, especially the metadata driver,
|
||||
* since these are not needed at all when a metadata cache is active.
|
||||
@ -252,7 +254,7 @@ class ClassMetadataFactory
|
||||
// Invoke driver
|
||||
try {
|
||||
$this->_driver->loadMetadataForClass($className, $class);
|
||||
} catch(\ReflectionException $e) {
|
||||
} catch(ReflectionException $e) {
|
||||
throw MappingException::reflectionFailure($className, $e);
|
||||
}
|
||||
|
||||
@ -376,7 +378,13 @@ class ClassMetadataFactory
|
||||
// Create & assign an appropriate ID generator instance
|
||||
switch ($class->generatorType) {
|
||||
case ClassMetadata::GENERATOR_TYPE_IDENTITY:
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator());
|
||||
// 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->table['name'] . '_' . $class->columnNames[$class->identifier[0]] . '_seq' :
|
||||
null;
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($seqName));
|
||||
break;
|
||||
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
|
||||
// If there is no sequence definition yet, create a default definition
|
||||
|
@ -317,7 +317,7 @@ class ClassMetadataInfo
|
||||
* READ-ONLY: The ID generator used for generating IDs for this class.
|
||||
*
|
||||
* @var AbstractIdGenerator
|
||||
* @todo Remove
|
||||
* @todo Remove!
|
||||
*/
|
||||
public $idGenerator;
|
||||
|
||||
@ -335,6 +335,7 @@ class ClassMetadataInfo
|
||||
* </code>
|
||||
*
|
||||
* @var array
|
||||
* @todo Merge with tableGeneratorDefinition into generic generatorDefinition
|
||||
*/
|
||||
public $sequenceGeneratorDefinition;
|
||||
|
||||
@ -343,6 +344,7 @@ class ClassMetadataInfo
|
||||
* TABLE generation strategy.
|
||||
*
|
||||
* @var array
|
||||
* @todo Merge with tableGeneratorDefinition into generic generatorDefinition
|
||||
*/
|
||||
public $tableGeneratorDefinition;
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
<?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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user