diff --git a/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php b/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php index 1434433a0..098934e30 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php @@ -87,18 +87,28 @@ class CountOutputWalker extends SqlWalker throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } - $rootClass = $from[0]->rangeVariableDeclaration->abstractSchemaName; - $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; - - // Get the identity properties from the metadata - $rootIdentifier = $this->queryComponents[$rootAlias]['metadata']->identifier; + $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $this->queryComponents[$rootAlias]['metadata']; + $rootIdentifier = $rootClass->identifier; // For every identifier, find out the SQL alias by combing through the ResultSetMapping $sqlIdentifier = array(); foreach ($rootIdentifier as $property) { - foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; + if (isset($rootClass->fieldMappings[$property])) { + foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + + if (isset($rootClass->associationMappings[$property])) { + $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; + + foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } } } } diff --git a/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php b/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php index 07d9f579a..0fc7e7585 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/CountWalker.php @@ -60,15 +60,21 @@ class CountWalker extends TreeWalkerAdapter if (count($rootComponents) > 1) { throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } - $root = reset($rootComponents); - $parentName = key($root); - $parent = current($root); + $root = reset($rootComponents); + $parentName = key($root); + $parent = current($root); + $identifierFieldName = $parent['metadata']->getSingleIdentifierFieldName(); + + $pathType = PathExpression::TYPE_STATE_FIELD; + if (isset($parent['metadata']->associationMappings[$identifierFieldName])) { + $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; + } $pathExpression = new PathExpression( PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, - $parent['metadata']->getSingleIdentifierFieldName() + $identifierFieldName ); - $pathExpression->type = PathExpression::TYPE_STATE_FIELD; + $pathExpression->type = $pathType; $distinct = $this->_getQuery()->getHint(self::HINT_DISTINCT); $AST->selectClause->selectExpressions = array( diff --git a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php index 22654925a..2c79a5acc 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php @@ -98,19 +98,28 @@ class LimitSubqueryOutputWalker extends SqlWalker throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } - $rootClass = $from[0]->rangeVariableDeclaration->abstractSchemaName; - $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; - - // Get the identity properties from the metadata - $metadata = $this->queryComponents[$rootAlias]['metadata']; - $rootIdentifier = $metadata->identifier; + $rootAlias = $from[0]->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $this->queryComponents[$rootAlias]['metadata']; + $rootIdentifier = $rootClass->identifier; // For every identifier, find out the SQL alias by combing through the ResultSetMapping $sqlIdentifier = array(); foreach ($rootIdentifier as $property) { - foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { - if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { - $sqlIdentifier[$property] = $alias; + if (isset($rootClass->fieldMappings[$property])) { + foreach (array_keys($this->rsm->fieldMappings, $property) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } + } + } + + if (isset($rootClass->associationMappings[$property])) { + $joinColumn = $rootClass->associationMappings[$property]['joinColumns'][0]['name']; + + foreach (array_keys($this->rsm->metaMappings, $joinColumn) as $alias) { + if ($this->rsm->columnOwnerMap[$alias] == $rootAlias) { + $sqlIdentifier[$property] = $alias; + } } } } diff --git a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php index 12fa11043..86ee5dd97 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php @@ -74,6 +74,10 @@ class LimitSubqueryWalker extends TreeWalkerAdapter } $identifier = $parent['metadata']->getSingleIdentifierFieldName(); + if (isset($parent['metadata']->associationMappings[$identifier])) { + throw new \RuntimeException("Paginating an entity with foreign key as identifier only works when using the Output Walkers. Call Paginator#setUseOutputWalkers(true) before iterating the paginator."); + } + $this->_getQuery()->setHint( self::IDENTIFIER_TYPE, Type::getType($parent['metadata']->getTypeOfField($identifier)) diff --git a/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php b/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php index de1a222ea..9b919e601 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php @@ -81,14 +81,18 @@ class WhereInWalker extends TreeWalkerAdapter if (count($rootComponents) > 1) { throw new \RuntimeException("Cannot count query which selects two FROM components, cannot make distinction"); } - $root = reset($rootComponents); - $parentName = key($root); - $parent = current($root); + $root = reset($rootComponents); + $parentName = key($root); + $parent = current($root); + $identifierFieldName = $parent['metadata']->getSingleIdentifierFieldName(); - $pathExpression = new PathExpression( - PathExpression::TYPE_STATE_FIELD, $parentName, $parent['metadata']->getSingleIdentifierFieldName() - ); - $pathExpression->type = PathExpression::TYPE_STATE_FIELD; + $pathType = PathExpression::TYPE_STATE_FIELD; + if (isset($parent['metadata']->associationMappings[$identifierFieldName])) { + $pathType = PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION; + } + + $pathExpression = new PathExpression(PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION, $parentName, $identifierFieldName); + $pathExpression->type = $pathType; $count = $this->_getQuery()->getHint(self::HINT_PAGINATOR_ID_COUNT); diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1685Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1685Test.php new file mode 100644 index 000000000..ee4c64a19 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1685Test.php @@ -0,0 +1,64 @@ +useModelSet('ddc117'); + parent::setUp(); + + $this->_em->createQuery('DELETE FROM Doctrine\Tests\Models\DDC117\DDC117ArticleDetails ad')->execute(); + + $article = new DDC117Article("Foo"); + $this->_em->persist($article); + $this->_em->flush(); + + $articleDetails = new DDC117ArticleDetails($article, "Very long text"); + $this->_em->persist($articleDetails); + $this->_em->flush(); + + $dql = "SELECT ad FROM Doctrine\Tests\Models\DDC117\DDC117ArticleDetails ad"; + $query = $this->_em->createQuery($dql); + + $this->paginator = new Paginator($query); + } + + public function testPaginateCount() + { + $this->assertEquals(1, count($this->paginator)); + } + + public function testPaginateIterate() + { + foreach ($this->paginator as $ad) { + $this->assertInstanceOf('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails', $ad); + } + } + + public function testPaginateCountNoOutputWalkers() + { + $this->paginator->setUseOutputWalkers(false); + $this->assertEquals(1, count($this->paginator)); + } + + public function testPaginateIterateNoOutputWalkers() + { + $this->paginator->setUseOutputWalkers(false); + + $this->setExpectedException('RuntimeException', 'Paginating an entity with foreign key as identifier only works when using the Output Walkers. Call Paginator#setUseOutputWalkers(true) before iterating the paginator.'); + foreach ($this->paginator as $ad) { + $this->assertInstanceOf('Doctrine\Tests\Models\DDC117\DDC117ArticleDetails', $ad); + } + } +} +