Merge pull request #6417 from lcobucci/fix-expire-result-cache
Fix expire result cache
This commit is contained in:
commit
7bb02d0dbd
@ -20,6 +20,7 @@
|
|||||||
namespace Doctrine\ORM;
|
namespace Doctrine\ORM;
|
||||||
|
|
||||||
use Doctrine\DBAL\LockMode;
|
use Doctrine\DBAL\LockMode;
|
||||||
|
use Doctrine\ORM\Query\Exec\AbstractSqlExecutor;
|
||||||
use Doctrine\ORM\Query\Parser;
|
use Doctrine\ORM\Query\Parser;
|
||||||
use Doctrine\ORM\Query\ParserResult;
|
use Doctrine\ORM\Query\ParserResult;
|
||||||
use Doctrine\ORM\Query\QueryException;
|
use Doctrine\ORM\Query\QueryException;
|
||||||
@ -322,9 +323,27 @@ final class Query extends AbstractQuery
|
|||||||
|
|
||||||
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
|
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
|
||||||
|
|
||||||
|
$this->evictResultSetCache($executor, $sqlParams, $types);
|
||||||
|
|
||||||
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function evictResultSetCache(AbstractSqlExecutor $executor, array $sqlParams, array $types)
|
||||||
|
{
|
||||||
|
if (null === $this->_queryCacheProfile || ! $this->getExpireResultCache()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cacheDriver = $this->_queryCacheProfile->getResultCacheDriver();
|
||||||
|
$statements = (array) $executor->getSqlStatements(); // Type casted since it can either be a string or an array
|
||||||
|
|
||||||
|
foreach ($statements as $statement) {
|
||||||
|
$cacheKeys = $this->_queryCacheProfile->generateCacheKeys($statement, $sqlParams, $types);
|
||||||
|
|
||||||
|
$cacheDriver->delete(reset($cacheKeys));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evict entity cache region
|
* Evict entity cache region
|
||||||
*/
|
*/
|
||||||
|
95
tests/Doctrine/Tests/ORM/Functional/Ticket/GH2947Test.php
Normal file
95
tests/Doctrine/Tests/ORM/Functional/Ticket/GH2947Test.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||||
|
|
||||||
|
use Doctrine\Common\Cache\ArrayCache;
|
||||||
|
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group 2947
|
||||||
|
*/
|
||||||
|
class GH2947Test extends OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->resultCacheImpl = new ArrayCache();
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->_schemaTool->createSchema([$this->_em->getClassMetadata(GH2947Car::class)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIssue()
|
||||||
|
{
|
||||||
|
$this->createData();
|
||||||
|
$initialQueryCount = $this->getCurrentQueryCount();
|
||||||
|
|
||||||
|
$query = $this->createQuery();
|
||||||
|
self::assertEquals('BMW', (string) $query->getSingleResult());
|
||||||
|
self::assertEquals($initialQueryCount + 1, $this->getCurrentQueryCount());
|
||||||
|
|
||||||
|
$this->updateData();
|
||||||
|
self::assertEquals('BMW', (string) $query->getSingleResult());
|
||||||
|
self::assertEquals($initialQueryCount + 2, $this->getCurrentQueryCount());
|
||||||
|
|
||||||
|
$query->expireResultCache(true);
|
||||||
|
self::assertEquals('Dacia', (string) $query->getSingleResult());
|
||||||
|
self::assertEquals($initialQueryCount + 3, $this->getCurrentQueryCount());
|
||||||
|
|
||||||
|
$query->expireResultCache(false);
|
||||||
|
self::assertEquals('Dacia', (string) $query->getSingleResult());
|
||||||
|
self::assertEquals($initialQueryCount + 3, $this->getCurrentQueryCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createQuery()
|
||||||
|
{
|
||||||
|
return $this->_em->createQueryBuilder()
|
||||||
|
->select('car')
|
||||||
|
->from(GH2947Car::class, 'car')
|
||||||
|
->getQuery()
|
||||||
|
->useResultCache(true, 3600, 'foo-cache-id');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createData()
|
||||||
|
{
|
||||||
|
$this->_em->persist(new GH2947Car('BMW'));
|
||||||
|
$this->_em->flush();
|
||||||
|
$this->_em->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function updateData()
|
||||||
|
{
|
||||||
|
$this->_em->createQueryBuilder()
|
||||||
|
->update(GH2947Car::class, 'car')
|
||||||
|
->set('car.brand', ':newBrand')
|
||||||
|
->where('car.brand = :oldBrand')
|
||||||
|
->setParameter('newBrand', 'Dacia')
|
||||||
|
->setParameter('oldBrand', 'BMW')
|
||||||
|
->getQuery()
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="GH2947_car")
|
||||||
|
*/
|
||||||
|
class GH2947Car
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="string", length=25)
|
||||||
|
* @GeneratedValue(strategy="NONE")
|
||||||
|
*/
|
||||||
|
public $brand;
|
||||||
|
|
||||||
|
public function __construct(string $brand)
|
||||||
|
{
|
||||||
|
$this->brand = $brand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->brand;
|
||||||
|
}
|
||||||
|
}
|
@ -243,4 +243,37 @@ class QueryTest extends OrmTestCase
|
|||||||
$query->setHydrationCacheProfile(null);
|
$query->setHydrationCacheProfile(null);
|
||||||
$this->assertNull($query->getHydrationCacheProfile());
|
$this->assertNull($query->getHydrationCacheProfile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group 2947
|
||||||
|
*/
|
||||||
|
public function testResultCacheEviction()
|
||||||
|
{
|
||||||
|
$this->_em->getConfiguration()->setResultCacheImpl(new ArrayCache());
|
||||||
|
|
||||||
|
$query = $this->_em->createQuery("SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u")
|
||||||
|
->useResultCache(true);
|
||||||
|
|
||||||
|
/** @var DriverConnectionMock $driverConnectionMock */
|
||||||
|
$driverConnectionMock = $this->_em->getConnection()
|
||||||
|
->getWrappedConnection();
|
||||||
|
|
||||||
|
$driverConnectionMock->setStatementMock(new StatementArrayMock([['id_0' => 1]]));
|
||||||
|
|
||||||
|
// Performs the query and sets up the initial cache
|
||||||
|
self::assertCount(1, $query->getResult());
|
||||||
|
|
||||||
|
$driverConnectionMock->setStatementMock(new StatementArrayMock([['id_0' => 1], ['id_0' => 2]]));
|
||||||
|
|
||||||
|
// Retrieves cached data since expire flag is false and we have a cached result set
|
||||||
|
self::assertCount(1, $query->getResult());
|
||||||
|
|
||||||
|
// Performs the query and caches the result set since expire flag is true
|
||||||
|
self::assertCount(2, $query->expireResultCache(true)->getResult());
|
||||||
|
|
||||||
|
$driverConnectionMock->setStatementMock(new StatementArrayMock([['id_0' => 1]]));
|
||||||
|
|
||||||
|
// Retrieves cached data since expire flag is false and we have a cached result set
|
||||||
|
self::assertCount(2, $query->expireResultCache(false)->getResult());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
*/
|
*/
|
||||||
protected $_usedModelSets = [];
|
protected $_usedModelSets = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be configured by the test that uses result set cache
|
||||||
|
*
|
||||||
|
* @var \Doctrine\Common\Cache\Cache|null
|
||||||
|
*/
|
||||||
|
protected $resultCacheImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the database schema has already been created.
|
* Whether the database schema has already been created.
|
||||||
*
|
*
|
||||||
@ -699,6 +706,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
$config->setProxyDir(__DIR__ . '/Proxies');
|
$config->setProxyDir(__DIR__ . '/Proxies');
|
||||||
$config->setProxyNamespace('Doctrine\Tests\Proxies');
|
$config->setProxyNamespace('Doctrine\Tests\Proxies');
|
||||||
|
|
||||||
|
if (null !== $this->resultCacheImpl) {
|
||||||
|
$config->setResultCacheImpl($this->resultCacheImpl);
|
||||||
|
}
|
||||||
|
|
||||||
$enableSecondLevelCache = getenv('ENABLE_SECOND_LEVEL_CACHE');
|
$enableSecondLevelCache = getenv('ENABLE_SECOND_LEVEL_CACHE');
|
||||||
|
|
||||||
if ($this->isSecondLevelCacheEnabled || $enableSecondLevelCache) {
|
if ($this->isSecondLevelCacheEnabled || $enableSecondLevelCache) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user