diff --git a/lib/Doctrine/ORM/Tools/Pagination/Paginator.php b/lib/Doctrine/ORM/Tools/Pagination/Paginator.php index cdfa35d89b9..7145496fae6 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/Paginator.php +++ b/lib/Doctrine/ORM/Tools/Pagination/Paginator.php @@ -160,9 +160,10 @@ public function getIterator() $this->appendTreeWalker($whereInQuery, WhereInWalker::class); $whereInQuery->setHint(WhereInWalker::HINT_PAGINATOR_ID_COUNT, count($ids)); $whereInQuery->setFirstResult(0)->setMaxResults(null); - $whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $ids); $whereInQuery->setCacheable($this->query->isCacheable()); - $whereInQuery->useQueryCache(false); + + $databaseIds = $this->convertWhereInIdentifiersToDatabaseValue($ids); + $whereInQuery->setParameter(WhereInWalker::PAGINATOR_ID_ALIAS, $databaseIds); $result = $whereInQuery->getResult($this->query->getHydrationMode()); } else { @@ -265,4 +266,17 @@ private function unbindUnusedQueryParams(Query $query): void $query->setParameters($parameters); } + + private function convertWhereInIdentifiersToDatabaseValue(array $identifiers): array + { + $query = $this->cloneQuery($this->query); + $query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, RootTypeWalker::class); + + $type = $query->getSQL(); + $connection = $this->query->getEntityManager()->getConnection(); + + return array_map(static function ($id) use ($connection, $type) { + return $connection->convertToDatabaseValue($id, $type); + }, $identifiers); + } } diff --git a/lib/Doctrine/ORM/Tools/Pagination/RootTypeWalker.php b/lib/Doctrine/ORM/Tools/Pagination/RootTypeWalker.php new file mode 100644 index 00000000000..7662fff086c --- /dev/null +++ b/lib/Doctrine/ORM/Tools/Pagination/RootTypeWalker.php @@ -0,0 +1,48 @@ + root entity id type resolution can be cached in the query cache. + */ +class RootTypeWalker extends SqlWalker +{ + public function walkSelectStatement(AST\SelectStatement $AST): string + { + // Get the root entity and alias from the AST fromClause + $from = $AST->fromClause->identificationVariableDeclarations; + + if (count($from) > 1) { + throw new RuntimeException('Can only process queries that select only one FROM component'); + } + + $fromRoot = reset($from); + $rootAlias = $fromRoot->rangeVariableDeclaration->aliasIdentificationVariable; + $rootClass = $this->getMetadataForDqlAlias($rootAlias); + $identifierFieldName = $rootClass->getSingleIdentifierFieldName(); + + return PersisterHelper::getTypeOfField( + $identifierFieldName, + $rootClass, + $this->getQuery() + ->getEntityManager() + )[0]; + } +} diff --git a/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php b/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php index 669bff9d7a2..fc694788abe 100644 --- a/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php +++ b/lib/Doctrine/ORM/Tools/Pagination/WhereInWalker.php @@ -17,13 +17,9 @@ use Doctrine\ORM\Query\AST\SimpleArithmeticExpression; use Doctrine\ORM\Query\AST\WhereClause; use Doctrine\ORM\Query\TreeWalkerAdapter; -use Doctrine\ORM\Utility\PersisterHelper; use RuntimeException; -use function array_map; -use function assert; use function count; -use function is_array; use function reset; /** @@ -80,15 +76,6 @@ public function walkSelectStatement(SelectStatement $AST) $arithmeticExpression, [new InputParameter(':' . self::PAGINATOR_ID_ALIAS)] ); - - $this->convertWhereInIdentifiersToDatabaseValue( - PersisterHelper::getTypeOfField( - $identifierFieldName, - $rootClass, - $this->_getQuery() - ->getEntityManager() - )[0] - ); } else { $expression = new NullComparisonExpression($pathExpression); } @@ -130,24 +117,4 @@ public function walkSelectStatement(SelectStatement $AST) ); } } - - private function convertWhereInIdentifiersToDatabaseValue(string $type): void - { - $query = $this->_getQuery(); - $identifiersParameter = $query->getParameter(self::PAGINATOR_ID_ALIAS); - - assert($identifiersParameter !== null); - - $identifiers = $identifiersParameter->getValue(); - - assert(is_array($identifiers)); - - $connection = $this->_getQuery() - ->getEntityManager() - ->getConnection(); - - $query->setParameter(self::PAGINATOR_ID_ALIAS, array_map(static function ($id) use ($connection, $type) { - return $connection->convertToDatabaseValue($id, $type); - }, $identifiers)); - } }