From 1c94c16234941903bb84d4745df0c51e43e25394 Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Tue, 11 Feb 2014 14:59:31 +0100 Subject: [PATCH 1/4] Can cache empty collections I should be able to cache an "empty" collection. I have a some objects, where 90% of these have on-to-many relations with zero associated elements. This causes doctrine to run a query each time, instead of cache it as empty relation. --- lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php b/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php index e084405ed..eaca3d75e 100644 --- a/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php +++ b/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php @@ -543,7 +543,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister $list = $this->persister->loadOneToManyCollection($assoc, $sourceEntity, $coll); - if ($hasCache && ! empty($list)) { + if ($hasCache) { $persister->storeCollectionCache($key, $list); if ($this->cacheLogger) { From a5fbb20fbb58377fa876eb1ce8045541e0fbf01b Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Tue, 11 Feb 2014 15:08:49 +0100 Subject: [PATCH 2/4] Can cache many to many empty relations --- lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php b/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php index eaca3d75e..3589e31a5 100644 --- a/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php +++ b/lib/Doctrine/ORM/Cache/Persister/AbstractEntityPersister.php @@ -508,7 +508,7 @@ abstract class AbstractEntityPersister implements CachedEntityPersister $list = $this->persister->loadManyToManyCollection($assoc, $sourceEntity, $coll); - if ($hasCache && ! empty($list)) { + if ($hasCache) { $persister->storeCollectionCache($key, $list); if ($this->cacheLogger) { From 4a6d6e34f8a7a141f1c048a03e6b050ce5e8bfdc Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Tue, 11 Feb 2014 17:39:16 +0100 Subject: [PATCH 3/4] Test empty collections second level cache --- .../SecondLevelCacheAbstractTest.php | 7 ++-- .../SecondLevelCacheManyToManyTest.php | 29 +++++++++++++++ .../SecondLevelCacheOneToManyTest.php | 35 +++++++++++++++++-- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheAbstractTest.php b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheAbstractTest.php index 2866c146c..e4672b9f2 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheAbstractTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheAbstractTest.php @@ -121,7 +121,7 @@ abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase $this->_em->flush(); } - + protected function loadFixturesTravelersWithProfile() { $t1 = new Traveler("Test traveler 1"); @@ -139,7 +139,7 @@ abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase $this->travelersWithProfile[] = $t1; $this->travelersWithProfile[] = $t2; - + $this->_em->flush(); } @@ -165,6 +165,7 @@ abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase { $t1 = new Travel($this->travelers[0]); $t2 = new Travel($this->travelers[1]); + $t3 = new Travel($this->travelers[1]); $t1->addVisitedCity($this->cities[0]); $t1->addVisitedCity($this->cities[1]); @@ -175,9 +176,11 @@ abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase $this->_em->persist($t1); $this->_em->persist($t2); + $this->_em->persist($t3); $this->travels[] = $t1; $this->travels[] = $t2; + $this->travels[] = $t3; $this->_em->flush(); } diff --git a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php index ac3dfd4fc..490e0cf1a 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php @@ -214,4 +214,33 @@ class SecondLevelCacheManyToManyTest extends SecondLevelCacheAbstractTest $this->_em->persist($travel); $this->_em->flush(); } + + public function testManyToManyWithEmptyRelation() + { + $this->loadFixturesCountries(); + $this->loadFixturesStates(); + $this->loadFixturesCities(); + $this->loadFixturesTraveler(); + $this->loadFixturesTravels(); + $this->_em->clear(); + + $this->evictRegions(); + + $queryCount = $this->getCurrentQueryCount(); + + $entitiId = $this->travels[2]->getId(); //empty travel + $entity = $this->_em->find(Travel::CLASSNAME, $entitiId); + + $this->assertEquals(0, $entity->getVisitedCities()->count()); + $this->assertEquals($queryCount+2, $this->getCurrentQueryCount()); + + $this->_em->clear(); + + $entity = $this->_em->find(Travel::CLASSNAME, $entitiId); + + $queryCount = $this->getCurrentQueryCount(); + $this->assertEquals(0, $entity->getVisitedCities()->count()); + $this->assertEquals($queryCount, $this->getCurrentQueryCount()); + + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheOneToManyTest.php b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheOneToManyTest.php index 6d1fd700c..f8aff3790 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheOneToManyTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheOneToManyTest.php @@ -90,7 +90,7 @@ class SecondLevelCacheOneToManyTest extends SecondLevelCacheAbstractTest $s3 = $this->_em->find(State::CLASSNAME, $this->states[0]->getId()); $s4 = $this->_em->find(State::CLASSNAME, $this->states[1]->getId()); - + //trigger lazy load from cache $this->assertCount(2, $s3->getCities()); $this->assertCount(2, $s4->getCities()); @@ -133,12 +133,12 @@ class SecondLevelCacheOneToManyTest extends SecondLevelCacheAbstractTest //trigger lazy load from database $this->assertCount(2, $this->_em->find(State::CLASSNAME, $this->states[0]->getId())->getCities()); - + $this->assertTrue($this->cache->containsEntity(State::CLASSNAME, $this->states[0]->getId())); $this->assertTrue($this->cache->containsCollection(State::CLASSNAME, 'cities', $this->states[0]->getId())); $this->assertTrue($this->cache->containsEntity(City::CLASSNAME, $this->states[0]->getCities()->get(0)->getId())); $this->assertTrue($this->cache->containsEntity(City::CLASSNAME, $this->states[0]->getCities()->get(1)->getId())); - + $queryCount = $this->getCurrentQueryCount(); $stateId = $this->states[0]->getId(); $state = $this->_em->find(State::CLASSNAME, $stateId); @@ -284,6 +284,35 @@ class SecondLevelCacheOneToManyTest extends SecondLevelCacheAbstractTest $this->assertEquals(0, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(State::CLASSNAME, 'cities'))); } + public function testOneToManyWithEmptyRelation() + { + $this->loadFixturesCountries(); + $this->loadFixturesStates(); + $this->loadFixturesCities(); + + $this->secondLevelCacheLogger->clearStats(); + $this->cache->evictEntityRegion(City::CLASSNAME); + $this->cache->evictEntityRegion(State::CLASSNAME); + $this->cache->evictCollectionRegion(State::CLASSNAME, 'cities'); + $this->_em->clear(); + + $entitiId = $this->states[2]->getId(); // bavaria (cities count = 0) + $queryCount = $this->getCurrentQueryCount(); + $entity = $this->_em->find(State::CLASSNAME, $entitiId); + + $this->assertEquals(0, $entity->getCities()->count()); + $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount()); + + $this->_em->clear(); + + $queryCount = $this->getCurrentQueryCount(); + $entity = $this->_em->find(State::CLASSNAME, $entitiId); + + $this->assertEquals(0, $entity->getCities()->count()); + $this->assertEquals($queryCount, $this->getCurrentQueryCount()); + + } + public function testOneToManyCount() { $this->loadFixturesCountries(); From 94896ce55255dc15f0d15d4ad2d545bcae5441dc Mon Sep 17 00:00:00 2001 From: Asmir Mustafic Date: Wed, 12 Feb 2014 08:18:34 +0100 Subject: [PATCH 4/4] Typo fix on many-to-many assocaition cascade test --- .../Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php index 490e0cf1a..0db9e1cbc 100644 --- a/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/SecondLevelCacheManyToManyTest.php @@ -171,7 +171,7 @@ class SecondLevelCacheManyToManyTest extends SecondLevelCacheAbstractTest $this->_em->flush(); $this->_em->clear(); - $this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $travel->getId())); + $this->assertTrue($this->cache->containsEntity(Travel::CLASSNAME, $travel->getId())); $this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $traveler->getId())); $this->assertTrue($this->cache->containsEntity(City::CLASSNAME, $this->cities[0]->getId())); $this->assertTrue($this->cache->containsEntity(City::CLASSNAME, $this->cities[1]->getId()));