Skip to content

Commit

Permalink
Merge pull request #6852 from gigi/2.5
Browse files Browse the repository at this point in the history
Backport #6167 from 2.6 to 2.5.x branch
  • Loading branch information
lcobucci committed Nov 27, 2017
2 parents e874d93 + a23e909 commit 640d9af
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 28 deletions.
9 changes: 6 additions & 3 deletions lib/Doctrine/ORM/Id/SequenceGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ public function generate(EntityManager $em, $entity)
$conn = $em->getConnection();
$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;
}

Expand Down Expand Up @@ -108,10 +109,12 @@ public function getNextValue()
*/
public function serialize()
{
return serialize(array(
return serialize(
[
'allocationSize' => $this->_allocationSize,
'sequenceName' => $this->_sequenceName
));
]
);
}

/**
Expand Down
59 changes: 51 additions & 8 deletions tests/Doctrine/Tests/Mocks/ConnectionMock.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,29 @@

namespace Doctrine\Tests\Mocks;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\Statement;

/**
* Mock class for Connection.
*/
class ConnectionMock extends \Doctrine\DBAL\Connection
class ConnectionMock extends Connection
{
/**
* @var mixed
*/
private $_fetchOneResult;

/**
* @var \Exception|null
*/
private $_fetchOneException;

/**
* @var Statement|null
*/
private $_queryResult;

/**
* @var DatabasePlatformMock
*/
Expand All @@ -25,12 +38,12 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
/**
* @var array
*/
private $_inserts = array();
private $_inserts = [];

/**
* @var array
*/
private $_executeUpdates = array();
private $_executeUpdates = [];

/**
* @param array $params
Expand Down Expand Up @@ -59,17 +72,17 @@ public function getDatabasePlatform()
/**
* {@inheritdoc}
*/
public function insert($tableName, array $data, array $types = array())
public function insert($tableName, array $data, array $types = [])
{
$this->_inserts[$tableName][] = $data;
}

/**
* {@inheritdoc}
*/
public function executeUpdate($query, array $params = array(), array $types = array())
public function executeUpdate($query, array $params = [], array $types = [])
{
$this->_executeUpdates[] = array('query' => $query, 'params' => $params, 'types' => $types);
$this->_executeUpdates[] = ['query' => $query, 'params' => $params, 'types' => $types];
}

/**
Expand All @@ -83,11 +96,23 @@ public function lastInsertId($seqName = null)
/**
* {@inheritdoc}
*/
public function fetchColumn($statement, array $params = array(), $colnum = 0, array $types = array())
public function fetchColumn($statement, array $params = [], $colnum = 0, array $types = [])
{
if (null !== $this->_fetchOneException) {
throw $this->_fetchOneException;
}

return $this->_fetchOneResult;
}

/**
* {@inheritdoc}
*/
public function query()
{
return $this->_queryResult;
}

/**
* {@inheritdoc}
*/
Expand All @@ -111,6 +136,16 @@ public function setFetchOneResult($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
*
Expand All @@ -131,6 +166,14 @@ public function setLastInsertId($id)
$this->_lastInsertId = $id;
}

/**
* @param Statement $result
*/
public function setQueryResult(Statement $result)
{
$this->_queryResult = $result;
}

/**
* @return array
*/
Expand All @@ -152,7 +195,7 @@ public function getExecuteUpdates()
*/
public function reset()
{
$this->_inserts = array();
$this->_inserts = [];
$this->_lastInsertId = 0;
}
}
65 changes: 65 additions & 0 deletions tests/Doctrine/Tests/Mocks/StatementArrayMock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Doctrine\Tests\Mocks;


/**
* Simple statement mock that returns result based on array.
* Doesn't support fetch modes
*/
class StatementArrayMock extends StatementMock
{
/**
* @var array
*/
private $_result;

public function __construct($result)
{
$this->_result = $result;
}

public function getIterator()
{
return new \ArrayIterator($this->_result);
}

public function columnCount()
{
$row = reset($this->_result);
if ($row) {
return count($row);
} else {
return 0;
}
}

public function fetchAll($fetchMode = null, $fetchArgument = null, $ctorArgs = null)
{
return $this->_result;
}

public function fetch($fetchMode = null, $cursorOrientation = \PDO::FETCH_ORI_NEXT, $cursorOffset = 0)
{
$current = current($this->_result);
next($this->_result);

return $current;
}

public function fetchColumn($columnIndex = 0)
{
$current = current($this->_result);
if ($current) {
next($this->_result);
return reset($current);
} else {
return false;
}
}

public function rowCount()
{
return count($this->_result);
}
}
55 changes: 38 additions & 17 deletions tests/Doctrine/Tests/ORM/Id/SequenceGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,58 @@

namespace Doctrine\Tests\ORM\Id;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Id\SequenceGenerator;
use Doctrine\Tests\Mocks\ConnectionMock;
use Doctrine\Tests\Mocks\StatementArrayMock;
use Doctrine\Tests\OrmTestCase;

/**
* Description of SequenceGeneratorTest
*
* @author robo
*/
class SequenceGeneratorTest extends \Doctrine\Tests\OrmTestCase
class SequenceGeneratorTest extends OrmTestCase
{
private $_em;
private $_seqGen;
/**
* @var EntityManager
*/
private $entityManager;

/**
* @var SequenceGenerator
*/
private $sequenceGenerator;

/**
* @var ConnectionMock
*/
private $connection;

protected function setUp()
{
$this->_em = $this->_getTestEntityManager();
$this->_seqGen = new SequenceGenerator('seq', 10);
parent::setUp();

$this->entityManager = $this->_getTestEntityManager();
$this->sequenceGenerator = new SequenceGenerator('seq', 10);
$this->connection = $this->entityManager->getConnection();

self::assertInstanceOf('Doctrine\Tests\Mocks\ConnectionMock', $this->connection);
}

public function testGeneration()
{
for ($i=0; $i < 42; ++$i) {
$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) {
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());
}
}
}

0 comments on commit 640d9af

Please sign in to comment.