1
0
mirror of synced 2025-02-03 05:49:25 +03:00

Merge branch 'fix/#6168-#6167-force-nextval-selection-on-the-master-server'

Close #6167
Close #6168
This commit is contained in:
Marco Pivetta 2017-06-21 06:04:34 +02:00
commit 07a9b10f36
No known key found for this signature in database
GPG Key ID: 4167D3337FD9D629
3 changed files with 83 additions and 20 deletions

View File

@ -76,7 +76,8 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
$conn = $em->getConnection(); $conn = $em->getConnection();
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName); $sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
$this->_nextValue = (int) $conn->fetchColumn($sql); // Using `query` to force usage of the master server in MasterSlaveConnection
$this->_nextValue = (int) $conn->query($sql)->fetchColumn();
$this->_maxValue = $this->_nextValue + $this->_allocationSize; $this->_maxValue = $this->_nextValue + $this->_allocationSize;
} }

View File

@ -1,7 +1,9 @@
<?php <?php
namespace Doctrine\Tests\Mocks; namespace Doctrine\Tests\Mocks;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement;
/** /**
* Mock class for Connection. * Mock class for Connection.
@ -13,6 +15,16 @@ class ConnectionMock extends Connection
*/ */
private $_fetchOneResult; private $_fetchOneResult;
/**
* @var \Exception|null
*/
private $_fetchOneException;
/**
* @var Statement|null
*/
private $_queryResult;
/** /**
* @var DatabasePlatformMock * @var DatabasePlatformMock
*/ */
@ -86,9 +98,21 @@ class ConnectionMock extends Connection
*/ */
public function fetchColumn($statement, array $params = [], $colnum = 0, array $types = []) public function fetchColumn($statement, array $params = [], $colnum = 0, array $types = [])
{ {
if (null !== $this->_fetchOneException) {
throw $this->_fetchOneException;
}
return $this->_fetchOneResult; return $this->_fetchOneResult;
} }
/**
* {@inheritdoc}
*/
public function query() : Statement
{
return $this->_queryResult;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -112,6 +136,16 @@ class ConnectionMock extends Connection
$this->_fetchOneResult = $fetchOneResult; $this->_fetchOneResult = $fetchOneResult;
} }
/**
* @param \Exception|null $exception
*
* @return void
*/
public function setFetchOneException(\Exception $exception = null)
{
$this->_fetchOneException = $exception;
}
/** /**
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
* *
@ -132,6 +166,14 @@ class ConnectionMock extends Connection
$this->_lastInsertId = $id; $this->_lastInsertId = $id;
} }
/**
* @param Statement $result
*/
public function setQueryResult(Statement $result)
{
$this->_queryResult = $result;
}
/** /**
* @return array * @return array
*/ */

View File

@ -2,38 +2,58 @@
namespace Doctrine\Tests\ORM\Id; namespace Doctrine\Tests\ORM\Id;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Id\SequenceGenerator; use Doctrine\ORM\Id\SequenceGenerator;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\StatementArrayMock;
use Doctrine\Tests\OrmTestCase; use Doctrine\Tests\OrmTestCase;
/**
* Description of SequenceGeneratorTest
*
* @author robo
*/
class SequenceGeneratorTest extends OrmTestCase class SequenceGeneratorTest extends OrmTestCase
{ {
private $_em; /**
private $_seqGen; * @var EntityManager
*/
private $entityManager;
protected function setUp() /**
* @var SequenceGenerator
*/
private $sequenceGenerator;
/**
* @var ConnectionMock
*/
private $connection;
protected function setUp() : void
{ {
$this->_em = $this->_getTestEntityManager(); parent::setUp();
$this->_seqGen = new SequenceGenerator('seq', 10);
$this->entityManager = $this->_getTestEntityManager();
$this->sequenceGenerator = new SequenceGenerator('seq', 10);
$this->connection = $this->entityManager->getConnection();
self::assertInstanceOf(ConnectionMock::class, $this->connection);
} }
public function testGeneration() public function testGeneration() : void
{ {
$this->connection->setFetchOneException(new \BadMethodCallException(
'Fetch* method used. Query method should be used instead, '
. 'as NEXTVAL should be run on a master server in master-slave setup.'
));
for ($i = 0; $i < 42; ++$i) { for ($i = 0; $i < 42; ++$i) {
if ($i % 10 == 0) { if ($i % 10 == 0) {
$this->_em->getConnection()->setFetchOneResult((int)($i / 10) * 10); $this->connection->setQueryResult(new StatementArrayMock([[(int)($i / 10) * 10]]));
}
$id = $this->_seqGen->generate($this->_em, null);
$this->assertEquals($i, $id);
$this->assertEquals((int)($i / 10) * 10 + 10, $this->_seqGen->getCurrentMaxValue());
$this->assertEquals($i + 1, $this->_seqGen->getNextValue());
} }
$id = $this->sequenceGenerator->generate($this->entityManager, null);
self::assertSame($i, $id);
self::assertSame((int)($i / 10) * 10 + 10, $this->sequenceGenerator->getCurrentMaxValue());
self::assertSame($i + 1, $this->sequenceGenerator->getNextValue());
}
} }
} }