1
0
mirror of synced 2025-01-09 18:47:10 +03:00

Merge branch 'hotfix/#1188-support-count-queries-with-parameters-in-removed-query-parts'

Close #1188
This commit is contained in:
Marco Pivetta 2014-11-27 18:16:22 +01:00
commit ec6781954a
2 changed files with 79 additions and 24 deletions

View File

@ -19,6 +19,7 @@
namespace Doctrine\ORM\Tools\Pagination;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\ResultSetMapping;
@ -118,31 +119,8 @@ class Paginator implements \Countable, \IteratorAggregate
public function count()
{
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 {
$data = $countQuery->getScalarResult();
$data = array_map('current', $data);
$this->count = array_sum($data);
$this->count = array_sum(array_map('current', $this->getCountQuery()->getScalarResult()));
} catch(NoResultException $e) {
$this->count = 0;
}
@ -252,4 +230,50 @@ class Paginator implements \Countable, \IteratorAggregate
$hints[] = $walkerClass;
$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;
}
}

View File

@ -11,6 +11,7 @@ use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsComment;
use Doctrine\ORM\Tools\Pagination\Paginator;
use ReflectionMethod;
/**
* @group DDC-1613
@ -150,6 +151,36 @@ class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertCount(1, $paginator->getIterator());
$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()
{