From 60eb755fe95d7b53d106e5f8b18748317d7d3bdd Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Tue, 8 Mar 2011 22:22:54 +0100 Subject: [PATCH] DDC-952, DDC-734 Add DQL query hint to switch associations from lazy to eager for deferred initialization optimizations. --- lib/Doctrine/ORM/UnitOfWork.php | 14 ++++++++- .../Tests/ORM/Functional/QueryTest.php | 30 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index 9f56416cb..45b2c612b 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -1936,6 +1936,18 @@ class UnitOfWork implements PropertyChangedListener $relatedIdHash = implode(' ', $associatedId); if (isset($this->identityMap[$targetClass->rootEntityName][$relatedIdHash])) { $newValue = $this->identityMap[$targetClass->rootEntityName][$relatedIdHash]; + + // if this is an uninitialized proxy, we are deferring eager loads, + // this association is marked as eager fetch, and its an uninitialized proxy (wtf!) + // then we cann append this entity for eager loading! + if (isset($hints['fetchEager'][$class->name][$field]) && + isset($hints['deferEagerLoad']) && + !$targetClass->isIdentifierComposite && + $newValue instanceof Proxy && + $newValue->__isInitialized__ === false) { + + $this->eagerLoadingEntities[$assoc['targetEntity']][] = $relatedIdHash; + } } else { if ($targetClass->subClasses) { // If it might be a subtype, it can not be lazy @@ -1943,7 +1955,7 @@ class UnitOfWork implements PropertyChangedListener ->loadOneToOneEntity($assoc, $entity, null, $associatedId); } else { // Deferred eager load only works for single identifier classes - if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) { + if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || isset($hints['eagerFetch'][$class->name][$field])) { if (isset($hints['deferEagerLoad']) && !$targetClass->isIdentifierComposite) { // TODO: Is there a faster approach? $this->eagerLoadingEntities[$assoc['targetEntity']][] = current($id); diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php index c753960f8..1519e1941 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php @@ -313,4 +313,34 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertTrue($result[0]->user instanceof \Doctrine\ORM\Proxy\Proxy); $this->assertFalse($result[0]->user->__isInitialized__); } + + /** + * @group DDC-952 + */ + public function testEnableFetchEagerMode() + { + for ($i = 0; $i < 10; $i++) { + $article = new CmsArticle; + $article->topic = "dr. dolittle"; + $article->text = "Once upon a time ..."; + $author = new CmsUser; + $author->name = "anonymous"; + $author->username = "anon".$i; + $author->status = "here"; + $article->user = $author; + $this->_em->persist($author); + $this->_em->persist($article); + } + $this->_em->flush(); + $this->_em->clear(); + + $articles = $this->_em->createQuery('select a from Doctrine\Tests\Models\CMS\CmsArticle a') + ->setHint('eagerFetch', array('Doctrine\Tests\Models\CMS\CmsArticle' => array('user' => true))) + ->getResult(); + + $this->assertEquals(10, count($articles)); + foreach ($articles AS $article) { + $this->assertNotInstanceOf('Doctrine\ORM\Proxy\Proxy', $article); + } + } } \ No newline at end of file