Merge branch 'hotfix/#1188-support-count-queries-with-parameters-in-removed-query-parts'
Close #1188
This commit is contained in:
commit
ec6781954a
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
namespace Doctrine\ORM\Tools\Pagination;
|
namespace Doctrine\ORM\Tools\Pagination;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Query\Parser;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
use Doctrine\ORM\Query\ResultSetMapping;
|
use Doctrine\ORM\Query\ResultSetMapping;
|
||||||
@ -118,31 +119,8 @@ class Paginator implements \Countable, \IteratorAggregate
|
|||||||
public function count()
|
public function count()
|
||||||
{
|
{
|
||||||
if ($this->count === null) {
|
if ($this->count === null) {
|
||||||
/* @var $countQuery Query */
|
|
||||||
$countQuery = $this->cloneQuery($this->query);
|
|
||||||
|
|
||||||
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
|
|
||||||
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->useOutputWalker($countQuery)) {
|
|
||||||
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
|
|
||||||
|
|
||||||
$rsm = new ResultSetMapping();
|
|
||||||
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
|
|
||||||
|
|
||||||
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
|
|
||||||
$countQuery->setResultSetMapping($rsm);
|
|
||||||
} else {
|
|
||||||
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
|
|
||||||
}
|
|
||||||
|
|
||||||
$countQuery->setFirstResult(null)->setMaxResults(null);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $countQuery->getScalarResult();
|
$this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult()));
|
||||||
$data = array_map('current', $data);
|
|
||||||
$this->count = array_sum($data);
|
|
||||||
} catch(NoResultException $e) {
|
} catch(NoResultException $e) {
|
||||||
$this->count = 0;
|
$this->count = 0;
|
||||||
}
|
}
|
||||||
@ -252,4 +230,50 @@ class Paginator implements \Countable, \IteratorAggregate
|
|||||||
$hints[] = $walkerClass;
|
$hints[] = $walkerClass;
|
||||||
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
|
$query->setHint(Query::HINT_CUSTOM_TREE_WALKERS, $hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Query prepared to count.
|
||||||
|
*
|
||||||
|
* @return Query
|
||||||
|
*/
|
||||||
|
private function getCountQuery()
|
||||||
|
{
|
||||||
|
/* @var $countQuery Query */
|
||||||
|
$countQuery = $this->cloneQuery($this->query);
|
||||||
|
|
||||||
|
if ( ! $countQuery->hasHint(CountWalker::HINT_DISTINCT)) {
|
||||||
|
$countQuery->setHint(CountWalker::HINT_DISTINCT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->useOutputWalker($countQuery)) {
|
||||||
|
$platform = $countQuery->getEntityManager()->getConnection()->getDatabasePlatform(); // law of demeter win
|
||||||
|
|
||||||
|
$rsm = new ResultSetMapping();
|
||||||
|
$rsm->addScalarResult($platform->getSQLResultCasing('dctrn_count'), 'count');
|
||||||
|
|
||||||
|
$countQuery->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Tools\Pagination\CountOutputWalker');
|
||||||
|
$countQuery->setResultSetMapping($rsm);
|
||||||
|
} else {
|
||||||
|
$this->appendTreeWalker($countQuery, 'Doctrine\ORM\Tools\Pagination\CountWalker');
|
||||||
|
}
|
||||||
|
|
||||||
|
$countQuery->setFirstResult(null)->setMaxResults(null);
|
||||||
|
|
||||||
|
$parser = new Parser($countQuery);
|
||||||
|
$parameterMappings = $parser->parse()->getParameterMappings();
|
||||||
|
/* @var $parameters \Doctrine\Common\Collections\Collection|\Doctrine\ORM\Query\Parameter[] */
|
||||||
|
$parameters = $countQuery->getParameters();
|
||||||
|
|
||||||
|
foreach ($parameters as $key => $parameter) {
|
||||||
|
$parameterName = $parameter->getName();
|
||||||
|
|
||||||
|
if( ! (isset($parameterMappings[$parameterName]) || array_key_exists($parameterName, $parameterMappings))) {
|
||||||
|
unset($parameters[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$countQuery->setParameters($parameters);
|
||||||
|
|
||||||
|
return $countQuery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use Doctrine\Tests\Models\CMS\CmsGroup;
|
|||||||
use Doctrine\Tests\Models\CMS\CmsArticle;
|
use Doctrine\Tests\Models\CMS\CmsArticle;
|
||||||
use Doctrine\Tests\Models\CMS\CmsComment;
|
use Doctrine\Tests\Models\CMS\CmsComment;
|
||||||
use Doctrine\ORM\Tools\Pagination\Paginator;
|
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||||
|
use ReflectionMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group DDC-1613
|
* @group DDC-1613
|
||||||
@ -151,6 +152,36 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals(1, $paginator->count());
|
$this->assertEquals(1, $paginator->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCountQueryStripsParametersInSelect()
|
||||||
|
{
|
||||||
|
$query = $this->_em->createQuery(
|
||||||
|
'SELECT u, (CASE WHEN u.id < :vipMaxId THEN 1 ELSE 0 END) AS hidden promotedFirst
|
||||||
|
FROM Doctrine\\Tests\\Models\\CMS\\CmsUser u
|
||||||
|
WHERE u.id < :id or 1=1'
|
||||||
|
);
|
||||||
|
$query->setParameter('vipMaxId', 10);
|
||||||
|
$query->setParameter('id', 100);
|
||||||
|
$query->setFirstResult(null)->setMaxResults(null);
|
||||||
|
|
||||||
|
$paginator = new Paginator($query);
|
||||||
|
|
||||||
|
$getCountQuery = new ReflectionMethod($paginator, 'getCountQuery');
|
||||||
|
|
||||||
|
$getCountQuery->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertCount(2, $getCountQuery->invoke($paginator)->getParameters());
|
||||||
|
$this->assertCount(3, $paginator);
|
||||||
|
|
||||||
|
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Query\SqlWalker');
|
||||||
|
|
||||||
|
$paginator = new Paginator($query);
|
||||||
|
|
||||||
|
// if select part of query is replaced with count(...) paginator should remove
|
||||||
|
// parameters from query object not used in new query.
|
||||||
|
$this->assertCount(1, $getCountQuery->invoke($paginator)->getParameters());
|
||||||
|
$this->assertCount(3, $paginator);
|
||||||
|
}
|
||||||
|
|
||||||
public function populate()
|
public function populate()
|
||||||
{
|
{
|
||||||
for ($i = 0; $i < 3; $i++) {
|
for ($i = 0; $i < 3; $i++) {
|
||||||
|
Loading…
Reference in New Issue
Block a user