Skip to content

Commit

Permalink
Add paginator query hint to force type conversion
Browse files Browse the repository at this point in the history
We're keeping a BC layer in the hydrator, which prevents type conversion
in scalar results.

This makes bypasses such layer in order to always convert the identifier
types when limiting the result set during a pagination.

The main goal here is to keep the conversion DB->PHP inside of the
hydrator components.
  • Loading branch information
lcobucci committed Nov 18, 2019
1 parent 3843eee commit 00ef1eb
Show file tree
Hide file tree
Showing 2 changed files with 17 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

0 comments on commit 00ef1eb

Please sign in to comment.