From 8c2aef3f147e95513703d929419c8b3de5c3106f Mon Sep 17 00:00:00 2001 From: "Fabio B. Silva" Date: Fri, 28 Feb 2014 21:27:03 -0500 Subject: [PATCH] [DDC-2943] Disable slc for pagination queries --- docs/en/reference/second-level-cache.rst | 7 ++ .../ORM/Tools/Pagination/Paginator.php | 3 + .../ORM/Functional/Ticket/DDC2943Test.php | 91 +++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2943Test.php diff --git a/docs/en/reference/second-level-cache.rst b/docs/en/reference/second-level-cache.rst index 42ef78d3e..d07cf0869 100644 --- a/docs/en/reference/second-level-cache.rst +++ b/docs/en/reference/second-level-cache.rst @@ -729,3 +729,10 @@ should be used in conjunction with distributed caching system such as memcached, Caches should be used with care when using a load-balancer if you don't share the cache. While using APC or any file based cache update occurred in a specific machine would not reflect to the cache in other machines. + + +Paginator +~~~~~~~~~ + +Count queries generated by ``Doctrine\ORM\Tools\Pagination\Paginator`` are not cached by second-level cache. +Although entities and query result are cached count queries will hit the database every time. diff --git a/lib/Doctrine/ORM/Tools/Pagination/Paginator.php b/lib/Doctrine/ORM/Tools/Pagination/Paginator.php index ecace32f6..087a17513 100755 --- a/lib/Doctrine/ORM/Tools/Pagination/Paginator.php +++ b/lib/Doctrine/ORM/Tools/Pagination/Paginator.php @@ -182,12 +182,14 @@ class Paginator implements \Countable, \IteratorAggregate $whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids)); $whereInQuery->setFirstResult(null)->setMaxResults(null); $whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids); + $whereInQuery->setCacheable($this->query->isCacheable()); $result = $whereInQuery->getResult($this->query->getHydrationMode()); } else { $result = $this->cloneQuery($this->query) ->setMaxResults($length) ->setFirstResult($offset) + ->setCacheable($this->query->isCacheable()) ->getResult($this->query->getHydrationMode()) ; } @@ -208,6 +210,7 @@ class Paginator implements \Countable, \IteratorAggregate $cloneQuery = clone $query; $cloneQuery->setParameters(clone $query->getParameters()); + $cloneQuery->setCacheable(false); foreach ($query->getHints() as $name => $value) { $cloneQuery->setHint($name, $value); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2943Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2943Test.php new file mode 100644 index 000000000..7ae6ef5f3 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2943Test.php @@ -0,0 +1,91 @@ +enableSecondLevelCache(); + $this->useModelSet('cache'); + parent::setUp(); + } + + private function loadFixtures() + { + $this->_em->persist(new Country("Brazil")); + $this->_em->persist(new Country("Canada")); + $this->_em->persist(new Country("Germany")); + $this->_em->persist(new Country("France")); + $this->_em->flush(); + $this->_em->clear(); + } + + public function testIssue() + { + $this->loadFixtures(); + + $region = $this->_em->getCache()->getEntityCacheRegion(Country::CLASSNAME); + $dql = 'SELECT c FROM Doctrine\Tests\Models\Cache\Country c'; + $query = $this->_em->createQuery($dql) + ->setCacheable(true) + ->setFirstResult(0) + ->setMaxResults(2); + + $this->assertPaginatorQueryPut(new Paginator(clone $query), $region->getName(), 4, 2); + + $this->_em->clear(); + $this->secondLevelCacheLogger->clearStats(); + + $this->assertPaginatorQueryHit(new Paginator(clone $query), $region->getName(), 4, 2); + } + + public function testIssueNonFetchJoin() + { + $this->loadFixtures(); + + $region = $this->_em->getCache()->getEntityCacheRegion(Country::CLASSNAME); + $dql = 'SELECT c FROM Doctrine\Tests\Models\Cache\Country c'; + $query = $this->_em->createQuery($dql) + ->setCacheable(true) + ->setFirstResult(0) + ->setMaxResults(2); + + $this->assertPaginatorQueryPut(new Paginator(clone $query, false), $region->getName(), 4, 2); + + $this->_em->clear(); + $this->secondLevelCacheLogger->clearStats(); + + $this->assertPaginatorQueryHit(new Paginator(clone $query, false), $region->getName(), 4, 2); + } + + public function assertPaginatorQueryPut(Paginator $paginator, $regionName, $count, $pageSize) + { + $this->assertCount($count, $paginator); + $this->assertCount($pageSize, $paginator->getIterator()); + + $this->assertEquals(0, $this->secondLevelCacheLogger->getRegionHitCount(Cache::DEFAULT_QUERY_REGION_NAME)); + $this->assertEquals(1, $this->secondLevelCacheLogger->getRegionPutCount(Cache::DEFAULT_QUERY_REGION_NAME)); + $this->assertEquals(0, $this->secondLevelCacheLogger->getRegionHitCount($regionName)); + $this->assertEquals($count, $this->secondLevelCacheLogger->getRegionPutCount($regionName)); + } + + public function assertPaginatorQueryHit(Paginator $paginator, $regionName, $count, $pageSize) + { + $this->assertCount($count, $paginator); + $this->assertCount($pageSize, $paginator->getIterator()); + + $this->assertEquals(1, $this->secondLevelCacheLogger->getRegionHitCount(Cache::DEFAULT_QUERY_REGION_NAME)); + $this->assertEquals(0, $this->secondLevelCacheLogger->getRegionPutCount(Cache::DEFAULT_QUERY_REGION_NAME)); + $this->assertEquals($pageSize, $this->secondLevelCacheLogger->getRegionHitCount($regionName)); + $this->assertEquals(0, $this->secondLevelCacheLogger->getRegionPutCount($regionName)); + } +}