[2.0] DDC-125 - Query Hints are now included in both QueryCache and ResultCache - QueryCache now also uses firstResult and maxResults for the cache key - ResultCache was fixed to use "getSql()" instead of "getDql()"
This commit is contained in:
parent
ca23555c3e
commit
04832e2789
@ -488,7 +488,7 @@ abstract class AbstractQuery
|
|||||||
|
|
||||||
// Check result cache
|
// Check result cache
|
||||||
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
|
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
|
||||||
$id = $this->getResultCacheId($params);
|
$id = $this->_getResultCacheId($params);
|
||||||
$cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id);
|
$cached = $this->_expireResultCache ? false : $cacheDriver->fetch($id);
|
||||||
|
|
||||||
if ($cached === false) {
|
if ($cached === false) {
|
||||||
@ -541,12 +541,14 @@ abstract class AbstractQuery
|
|||||||
* @param array $params
|
* @param array $params
|
||||||
* @return string $id
|
* @return string $id
|
||||||
*/
|
*/
|
||||||
public function getResultCacheId(array $params)
|
protected function _getResultCacheId(array $params)
|
||||||
{
|
{
|
||||||
if ($this->_resultCacheId) {
|
if ($this->_resultCacheId) {
|
||||||
return $this->_resultCacheId;
|
return $this->_resultCacheId;
|
||||||
} else {
|
} else {
|
||||||
return md5($this->getDql() . var_export($params, true));
|
$sql = $this->getSql();
|
||||||
|
ksort($this->_hints);
|
||||||
|
return md5(implode(";", (array)$sql) . var_export($params, true) . var_export($this->_hints, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,11 +173,7 @@ final class Query extends AbstractQuery
|
|||||||
{
|
{
|
||||||
// Check query cache
|
// Check query cache
|
||||||
if ($queryCache = $this->getQueryCacheDriver()) {
|
if ($queryCache = $this->getQueryCacheDriver()) {
|
||||||
// Calculate hash for dql query.
|
$hash = $this->_getQueryCacheId();
|
||||||
// TODO: Probably need to include query hints in hash calculation, because query hints
|
|
||||||
// can have influence on the SQL.
|
|
||||||
// TODO: Include _maxResults and _firstResult in hash calculation
|
|
||||||
$hash = md5($this->getDql() . 'DOCTRINE_QUERY_CACHE_SALT');
|
|
||||||
$cached = ($this->_expireQueryCache) ? false : $queryCache->fetch($hash);
|
$cached = ($this->_expireQueryCache) ? false : $queryCache->fetch($hash);
|
||||||
|
|
||||||
if ($cached === false) {
|
if ($cached === false) {
|
||||||
@ -438,4 +434,21 @@ final class Query extends AbstractQuery
|
|||||||
$this->setHint(self::HINT_INTERNAL_ITERATION, true);
|
$this->setHint(self::HINT_INTERNAL_ITERATION, true);
|
||||||
return parent::iterate($params, $hydrationMode);
|
return parent::iterate($params, $hydrationMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a cache id for the query cache - reusing the Result-Cache-Id generator.
|
||||||
|
*
|
||||||
|
* The query cache
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function _getQueryCacheId()
|
||||||
|
{
|
||||||
|
ksort($this->_hints);
|
||||||
|
|
||||||
|
return md5(
|
||||||
|
$this->getDql() . var_export($this->_hints, true) .
|
||||||
|
'firstResult='.$this->_firstResult.'&maxResult='.$this->_maxResults.'DOCTRINE_QUERY_CACHE_SALT'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
@ -19,38 +19,101 @@ class QueryCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testQueryCache()
|
public function testQueryCache_DependsOnHints()
|
||||||
|
{
|
||||||
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
|
|
||||||
|
$cache = new ArrayCache();
|
||||||
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
|
$query->getResult();
|
||||||
|
$this->assertEquals(1, count($cache->getIds()));
|
||||||
|
|
||||||
|
$query->setHint('foo', 'bar');
|
||||||
|
|
||||||
|
$query->getResult();
|
||||||
|
$this->assertEquals(2, count($cache->getIds()));
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <type> $query
|
||||||
|
* @depends testQueryCache_DependsOnHints
|
||||||
|
*/
|
||||||
|
public function testQueryCache_DependsOnFirstResult($query)
|
||||||
|
{
|
||||||
|
$cache = $query->getQueryCacheDriver();
|
||||||
|
$cacheCount = count($cache->getIds());
|
||||||
|
|
||||||
|
$query->setFirstResult(10);
|
||||||
|
|
||||||
|
$query->getResult();
|
||||||
|
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <type> $query
|
||||||
|
* @depends testQueryCache_DependsOnHints
|
||||||
|
*/
|
||||||
|
public function testQueryCache_DependsOnMaxResults($query)
|
||||||
|
{
|
||||||
|
$cache = $query->getQueryCacheDriver();
|
||||||
|
$cacheCount = count($cache->getIds());
|
||||||
|
|
||||||
|
$query->setMaxResults(10);
|
||||||
|
|
||||||
|
$query->getResult();
|
||||||
|
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testQueryCache_NoHitSaveParserResult()
|
||||||
{
|
{
|
||||||
$this->_em->getConfiguration()->setQueryCacheImpl(null);
|
$this->_em->getConfiguration()->setQueryCacheImpl(null);
|
||||||
|
|
||||||
$user = new CmsUser;
|
|
||||||
$user->name = 'Roman';
|
|
||||||
$user->username = 'romanb';
|
|
||||||
$user->status = 'dev';
|
|
||||||
$this->_em->persist($user);
|
|
||||||
$this->_em->flush();
|
|
||||||
|
|
||||||
|
|
||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
$cache = new ArrayCache;
|
|
||||||
|
$cache = $this->getMock('Doctrine\Common\Cache\AbstractCache', array('_doFetch', '_doContains', '_doSave', '_doDelete', 'getIds'));
|
||||||
|
$cache->expects($this->at(0))
|
||||||
|
->method('_doFetch')
|
||||||
|
->with($this->isType('string'))
|
||||||
|
->will($this->returnValue(false));
|
||||||
|
$cache->expects($this->at(1))
|
||||||
|
->method('_doSave')
|
||||||
|
->with($this->isType('string'), $this->isInstanceOf('Doctrine\ORM\Query\ParserResult'), $this->equalTo(null));
|
||||||
|
|
||||||
$query->setQueryCacheDriver($cache);
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
$users = $query->getResult();
|
$users = $query->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
$this->assertTrue($cache->contains(md5('select ux from Doctrine\Tests\Models\CMS\CmsUser uxDOCTRINE_QUERY_CACHE_SALT')));
|
public function testQueryCache_HitDoesNotSaveParserResult()
|
||||||
$this->assertEquals(1, count($users));
|
{
|
||||||
$this->assertEquals('Roman', $users[0]->name);
|
$this->_em->getConfiguration()->setQueryCacheImpl(null);
|
||||||
|
|
||||||
$this->_em->clear();
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
|
|
||||||
$query2 = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$sqlExecMock = $this->getMock('Doctrine\ORM\Query\Exec\AbstractSqlExecutor', array('execute'));
|
||||||
$query2->setQueryCacheDriver($cache);
|
$sqlExecMock->expects($this->once())
|
||||||
|
->method('execute')
|
||||||
|
->will($this->returnValue( 10 ));
|
||||||
|
|
||||||
$users = $query2->getResult();
|
$parserResultMock = $this->getMock('Doctrine\ORM\Query\ParserResult');
|
||||||
|
$parserResultMock->expects($this->once())
|
||||||
|
->method('getSqlExecutor')
|
||||||
|
->will($this->returnValue($sqlExecMock));
|
||||||
|
|
||||||
$this->assertTrue($cache->contains(md5('select ux from Doctrine\Tests\Models\CMS\CmsUser uxDOCTRINE_QUERY_CACHE_SALT')));
|
$cache = $this->getMock('Doctrine\Common\Cache\AbstractCache', array('_doFetch', '_doContains', '_doSave', '_doDelete', 'getIds'));
|
||||||
$this->assertEquals(1, count($users));
|
$cache->expects($this->once())
|
||||||
$this->assertEquals('Roman', $users[0]->name);
|
->method('_doFetch')
|
||||||
|
->with($this->isType('string'))
|
||||||
|
->will($this->returnValue($parserResultMock));
|
||||||
|
$cache->expects($this->never())
|
||||||
|
->method('_doSave');
|
||||||
|
|
||||||
|
$query->setQueryCacheDriver($cache);
|
||||||
|
|
||||||
|
$users = $query->getResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,23 +30,27 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
|
|
||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
$cache = new ArrayCache;
|
|
||||||
$query->setResultCacheDriver($cache);
|
$cache = new ArrayCache();
|
||||||
|
|
||||||
|
$query->setResultCacheDriver($cache)->setResultCacheId('my_cache_id');
|
||||||
|
|
||||||
|
$this->assertFalse($cache->contains('my_cache_id'));
|
||||||
|
|
||||||
$users = $query->getResult();
|
$users = $query->getResult();
|
||||||
|
|
||||||
$this->assertTrue($cache->contains($query->getResultCacheId(array())));
|
$this->assertTrue($cache->contains('my_cache_id'));
|
||||||
$this->assertEquals(1, count($users));
|
$this->assertEquals(1, count($users));
|
||||||
$this->assertEquals('Roman', $users[0]->name);
|
$this->assertEquals('Roman', $users[0]->name);
|
||||||
|
|
||||||
$this->_em->clear();
|
$this->_em->clear();
|
||||||
|
|
||||||
$query2 = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query2 = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
$query2->setResultCacheDriver($cache);
|
$query2->setResultCacheDriver($cache)->setResultCacheId('my_cache_id');
|
||||||
|
|
||||||
$users = $query2->getResult();
|
$users = $query2->getResult();
|
||||||
|
|
||||||
$this->assertTrue($cache->contains($query->getResultCacheId(array())));
|
$this->assertTrue($cache->contains('my_cache_id'));
|
||||||
$this->assertEquals(1, count($users));
|
$this->assertEquals(1, count($users));
|
||||||
$this->assertEquals('Roman', $users[0]->name);
|
$this->assertEquals('Roman', $users[0]->name);
|
||||||
}
|
}
|
||||||
@ -58,6 +62,9 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
$query = $this->_em->createQuery('select ux from Doctrine\Tests\Models\CMS\CmsUser ux');
|
||||||
$query->setResultCacheDriver($cache);
|
$query->setResultCacheDriver($cache);
|
||||||
$query->setResultCacheId('testing_result_cache_id');
|
$query->setResultCacheId('testing_result_cache_id');
|
||||||
|
|
||||||
|
$this->assertFalse($cache->contains('testing_result_cache_id'));
|
||||||
|
|
||||||
$users = $query->getResult();
|
$users = $query->getResult();
|
||||||
|
|
||||||
$this->assertTrue($cache->contains('testing_result_cache_id'));
|
$this->assertTrue($cache->contains('testing_result_cache_id'));
|
||||||
@ -77,4 +84,51 @@ class ResultCacheTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->_em->getConfiguration()->setResultCacheImpl(null);
|
$this->_em->getConfiguration()->setResultCacheImpl(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testNativeQueryResultCaching()
|
||||||
|
{
|
||||||
|
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
|
||||||
|
$rsm->addScalarResult('id', 'u');
|
||||||
|
$query = $this->_em->createNativeQuery('select u.id FROM cms_users u WHERE u.id = ?', $rsm);
|
||||||
|
$query->setParameter(1, 10);
|
||||||
|
|
||||||
|
$cache = new ArrayCache();
|
||||||
|
$query->setResultCacheDriver($cache)->useResultCache(true);
|
||||||
|
|
||||||
|
$this->assertEquals(0, count($cache->getIds()));
|
||||||
|
$query->getResult();
|
||||||
|
$this->assertEquals(1, count($cache->getIds()));
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <type> $query
|
||||||
|
* @depends testNativeQueryResultCaching
|
||||||
|
*/
|
||||||
|
public function testResultCacheDependsOnQueryHints($query)
|
||||||
|
{
|
||||||
|
$cache = $query->getResultCacheDriver();
|
||||||
|
$cacheCount = count($cache->getIds());
|
||||||
|
|
||||||
|
$query->setHint('foo', 'bar');
|
||||||
|
$query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <type> $query
|
||||||
|
* @depends testNativeQueryResultCaching
|
||||||
|
*/
|
||||||
|
public function testResultCacheDependsOnParameters($query)
|
||||||
|
{
|
||||||
|
$cache = $query->getResultCacheDriver();
|
||||||
|
$cacheCount = count($cache->getIds());
|
||||||
|
|
||||||
|
$query->setParameter(1, 50);
|
||||||
|
$query->getResult();
|
||||||
|
|
||||||
|
$this->assertEquals($cacheCount + 1, count($cache->getIds()));
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user