Permalink
Browse files

[DDC-1685] Fix bug in OutputWalker when used on entities with Foreign…

… Key as Primary Key.
  • Loading branch information...
1 parent 2e79637 commit 3398d1e287ca9b857ceb80fa377f50e62956e24b @beberlei beberlei committed May 27, 2012
View
26 lib/Doctrine/ORM/Tools/Pagination/CountOutputWalker.php
@@ -87,18 +87,28 @@ public function walkSelectStatement(SelectStatement $AST)
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;
+ }
}
}
}
View
16 lib/Doctrine/ORM/Tools/Pagination/CountWalker.php
@@ -60,15 +60,21 @@ public function walkSelectStatement(SelectStatement $AST)
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(
View
27 lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryOutputWalker.php
@@ -98,19 +98,28 @@ public function walkSelectStatement(SelectStatement $AST)
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;
+ }
}
}
}
View
4 lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php
@@ -74,6 +74,10 @@ public function walkSelectStatement(SelectStatement $AST)
}
$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))
View
18 lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php
@@ -81,14 +81,18 @@ public function walkSelectStatement(SelectStatement $AST)
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);
View
64 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1685Test.php
@@ -0,0 +1,64 @@
+<?php
+namespace Doctrine\Tests\ORM\Functional\Ticket;
+
+use Doctrine\Tests\Models\DDC117\DDC117ArticleDetails;
+use Doctrine\Tests\Models\DDC117\DDC117Article;
+use Doctrine\ORM\Tools\Pagination\Paginator;
+
+/**
+ * @group DDC-1685
+ */
+class DDC1685Test extends \Doctrine\Tests\OrmFunctionalTestCase
+{
+ private $paginator;
+
+ protected function setUp()
+ {
+ $this->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);
+ }
+ }
+}
+

0 comments on commit 3398d1e

Please sign in to comment.