Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 686f508

Browse files
authored
Merge pull request #7905 from lcobucci/7890-paginator-objecti
[Paginator] Fix type conversion during hydration of pagination limit subquery
2 parents 6a827d5 + 00ef1eb commit 686f508

3 files changed

Lines changed: 51 additions & 11 deletions

File tree

lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Doctrine\ORM\EntityManagerInterface;
2424
use Doctrine\ORM\Events;
2525
use Doctrine\ORM\Mapping\ClassMetadata;
26+
use Doctrine\ORM\Tools\Pagination\LimitSubqueryWalker;
2627
use PDO;
2728
use function array_map;
2829
use function in_array;
@@ -351,13 +352,11 @@ protected function gatherScalarRowData(&$data)
351352

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

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

424+
case isset($this->_rsm->scalarMappings[$key], $this->_hints[LimitSubqueryWalker::FORCE_DBAL_TYPE_CONVERSION]):
425+
return $this->_cache[$key] = [
426+
'fieldName' => $this->_rsm->scalarMappings[$key],
427+
'type' => Type::getType($this->_rsm->typeMappings[$key]),
428+
'dqlAlias' => '',
429+
];
425430
case (isset($this->_rsm->scalarMappings[$key])):
426431
return $this->_cache[$key] = [
427432
'isScalar' => true,

lib/Doctrine/ORM/Tools/Pagination/LimitSubqueryWalker.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@
3939
*/
4040
class LimitSubqueryWalker extends TreeWalkerAdapter
4141
{
42-
/**
43-
* ID type hint.
44-
*/
45-
const IDENTIFIER_TYPE = 'doctrine_paginator.id.type';
42+
public const IDENTIFIER_TYPE = 'doctrine_paginator.id.type';
43+
44+
public const FORCE_DBAL_TYPE_CONVERSION = 'doctrine_paginator.scalar_result.force_dbal_type_conversion';
4645

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

84+
$this->_getQuery()->setHint(self::FORCE_DBAL_TYPE_CONVERSION, true);
85+
8586
$pathExpression = new PathExpression(
8687
PathExpression::TYPE_STATE_FIELD | PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION,
8788
$rootAlias,

tests/Doctrine/Tests/ORM/Functional/PaginationTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@
22

33
namespace Doctrine\Tests\ORM\Functional;
44

5+
use Doctrine\DBAL\Types\Type as DBALType;
56
use Doctrine\ORM\Query;
67
use Doctrine\ORM\Tools\Pagination\Paginator;
8+
use Doctrine\Tests\DbalTypes\CustomIdObject;
9+
use Doctrine\Tests\DbalTypes\CustomIdObjectType;
710
use Doctrine\Tests\Models\CMS\CmsArticle;
811
use Doctrine\Tests\Models\CMS\CmsEmail;
912
use Doctrine\Tests\Models\CMS\CmsGroup;
1013
use Doctrine\Tests\Models\CMS\CmsUser;
1114
use Doctrine\Tests\Models\Company\CompanyManager;
15+
use Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent;
1216
use Doctrine\Tests\Models\Pagination\Company;
1317
use Doctrine\Tests\Models\Pagination\Department;
1418
use Doctrine\Tests\Models\Pagination\Logo;
1519
use Doctrine\Tests\Models\Pagination\User1;
1620
use Doctrine\Tests\OrmFunctionalTestCase;
1721
use ReflectionMethod;
22+
use function iterator_to_array;
1823

1924
/**
2025
* @group DDC-1613
@@ -26,6 +31,14 @@ protected function setUp()
2631
$this->useModelSet('cms');
2732
$this->useModelSet('pagination');
2833
$this->useModelSet('company');
34+
$this->useModelSet('custom_id_object_type');
35+
36+
if (DBALType::hasType(CustomIdObjectType::NAME)) {
37+
DBALType::overrideType(CustomIdObjectType::NAME, CustomIdObjectType::class);
38+
} else {
39+
DBALType::addType(CustomIdObjectType::NAME, CustomIdObjectType::class);
40+
}
41+
2942
parent::setUp();
3043
$this->populate();
3144
}
@@ -641,6 +654,27 @@ public function testQueryWalkerIsKept()
641654
$this->assertEquals(1, $paginator->count());
642655
}
643656

657+
/**
658+
* @group GH-7890
659+
*/
660+
public function testCustomIdTypeWithoutOutputWalker()
661+
{
662+
$this->_em->persist(new CustomIdObjectTypeParent(new CustomIdObject('foo')));
663+
$this->_em->flush();
664+
665+
$dql = 'SELECT p FROM Doctrine\Tests\Models\CustomType\CustomIdObjectTypeParent p';
666+
$query = $this->_em->createQuery($dql);
667+
668+
$paginator = new Paginator($query, true);
669+
$paginator->setUseOutputWalkers(false);
670+
671+
$matchedItems = iterator_to_array($paginator->getIterator());
672+
673+
self::assertCount(1, $matchedItems);
674+
self::assertInstanceOf(CustomIdObjectTypeParent::class, $matchedItems[0]);
675+
self::assertSame('foo', (string) $matchedItems[0]->id);
676+
}
677+
644678
public function testCountQueryStripsParametersInSelect()
645679
{
646680
$query = $this->_em->createQuery(

0 commit comments

Comments
 (0)