Skip to content

Commit

Permalink
Merge pull request #7905 from lcobucci/7890-paginator-objecti
Browse files Browse the repository at this point in the history
[Paginator] Fix type conversion during hydration of pagination limit subquery
  • Loading branch information
lcobucci authored Nov 18, 2019
2 parents 6a827d5 + 00ef1eb commit 686f508
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 11 deletions.
19 changes: 12 additions & 7 deletions lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker;
use PDO;
use function array_map;
use function in_array;
Expand Down Expand Up @@ -351,13 +352,11 @@ protected function gatherScalarRowData(&$data)

// WARNING: BC break! We know this is the desired behavior to type convert values, but this
// erroneous behavior exists since 2.0 and we're forced to keep compatibility.
if ( ! isset($cacheKeyInfo['isScalar'])) {
$dqlAlias = $cacheKeyInfo['dqlAlias'];
$type = $cacheKeyInfo['type'];
$fieldName = $dqlAlias . '_' . $fieldName;
$value = $type
? $type->convertToPHPValue($value, $this->_platform)
: $value;
if (! isset($cacheKeyInfo['isScalar'])) {
$type = $cacheKeyInfo['type'];
$value = $type ? $type->convertToPHPValue($value, $this->_platform) : $value;

$fieldName = $cacheKeyInfo['dqlAlias'] . '_' . $fieldName;
}

$rowData[$fieldName] = $value;
Expand Down Expand Up @@ -422,6 +421,12 @@ protected function hydrateColumnInfo($key)
'class' => new \ReflectionClass($mapping['className']),
];

case isset($this->_rsm->scalarMappings[$key], $this->_hints[LimitSubqueryWalker::FORCE_DBAL_TYPE_CONVERSION]):
return $this->_cache[$key] = [
'fieldName' => $this->_rsm->scalarMappings[$key],
'type' => Type::getType($this->_rsm->typeMappings[$key]),
'dqlAlias' => '',
];
case (isset($this->_rsm->scalarMappings[$key])):
return $this->_cache[$key] = [
'isScalar' => true,
Expand Down
9 changes: 5 additions & 4 deletions lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@
*/
class LimitSubqueryWalker extends TreeWalkerAdapter
{
/**
* ID type hint.
*/
const IDENTIFIER_TYPE = 'doctrine_paginator.id.type';
public const IDENTIFIER_TYPE = 'doctrine_paginator.id.type';

public const FORCE_DBAL_TYPE_CONVERSION = 'doctrine_paginator.scalar_result.force_dbal_type_conversion';

/**
* Counter for generating unique order column aliases.
Expand Down Expand Up @@ -82,6 +81,8 @@ public function walkSelectStatement(SelectStatement $AST)
Type::getType($rootClass->fieldMappings[$identifier]['type'])
);

$this->_getQuery()->setHint(self::FORCE_DBAL_TYPE_CONVERSION, true);

$pathExpression = new PathExpression(
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
$rootAlias,
Expand Down
34 changes: 34 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/PaginationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\DBAL\Types\Type as DBALType;
use Doctrine\ORM\Query;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\Tests\DbalTypes\CustomIdObject;
use Doctrine\Tests\DbalTypes\CustomIdObjectType;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsEmail;
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\Company\CompanyManager;
use Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent;
use Doctrine\Tests\Models\Pagination\Company;
use Doctrine\Tests\Models\Pagination\Department;
use Doctrine\Tests\Models\Pagination\Logo;
use Doctrine\Tests\Models\Pagination\User1;
use Doctrine\Tests\OrmFunctionalTestCase;
use ReflectionMethod;
use function iterator_to_array;

/**
* @group DDC-1613
Expand All @@ -26,6 +31,14 @@ protected function setUp()
$this->useModelSet('cms');
$this->useModelSet('pagination');
$this->useModelSet('company');
$this->useModelSet('custom_id_object_type');

if (DBALType::hasType(CustomIdObjectType::NAME)) {
DBALType::overrideType(CustomIdObjectType::NAME, CustomIdObjectType::class);
} else {
DBALType::addType(CustomIdObjectType::NAME, CustomIdObjectType::class);
}

parent::setUp();
$this->populate();
}
Expand Down Expand Up @@ -641,6 +654,27 @@ public function testQueryWalkerIsKept()
$this->assertEquals(1, $paginator->count());
}

/**
* @group GH-7890
*/
public function testCustomIdTypeWithoutOutputWalker()
{
$this->_em->persist(new CustomIdObjectTypeParent(new CustomIdObject('foo')));
$this->_em->flush();

$dql = 'SELECT p FROM Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent p';
$query = $this->_em->createQuery($dql);

$paginator = new Paginator($query, true);
$paginator->setUseOutputWalkers(false);

$matchedItems = iterator_to_array($paginator->getIterator());

self::assertCount(1, $matchedItems);
self::assertInstanceOf(CustomIdObjectTypeParent::class, $matchedItems[0]);
self::assertSame('foo', (string) $matchedItems[0]->id);
}

public function testCountQueryStripsParametersInSelect()
{
$query = $this->_em->createQuery(
Expand Down

0 comments on commit 686f508

Please sign in to comment.