1
0
mirror of synced 2025-01-31 12:32:59 +03:00
Sander Marechal edd5d14b06 Pagination using SQL walkers
A CountSqlWalker and LimitSubquerySqlWalker have been implemented. By
default the Paginator will use these SQL walkers. When a query already
uses custom SQL walkers, the Paginator will fall back to the existing
TreeWalker implementations. Improvements:

* Support for more complex DQL queries using named mixed results with
  GROUP BY and HAVING. For example:

  SELECT g, u, COUNT(u.id) AS userCount
      FROM Entity\Group g LEFT JOIN g.users u
      GROUP BY g.id
      HAVING userCount > 0

* Support for entities with composite primary keys in the CountSqlWalker
  and LimitSubquerySqlWalker. Only the WhereInWalker still needs to be
  updated for full composite primary key support. But someone smarter
  than me needs to look at that and figure out how to build a WHERE IN
  query that can select rows based on multiple columns.
2012-03-06 16:24:44 +01:00

155 lines
4.9 KiB
PHP

<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Query;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\Tests\Models\CMS\CmsAddress;
use Doctrine\Tests\Models\CMS\CmsGroup;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\Tests\Models\CMS\CmsComment;
use Doctrine\ORM\Tools\Pagination\Paginator;
/**
* @group DDC-1613
*/
class PaginationTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
$this->populate();
}
public function testCountSimpleWithoutJoin()
{
$dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query);
$paginator->setUseSqlWalkers(false);
$this->assertEquals(3, count($paginator));
}
public function testCountWithFetchJoin()
{
$dql = "SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query);
$paginator->setUseSqlWalkers(false);
$this->assertEquals(3, count($paginator));
}
public function testCountComplexWithSqlWalker()
{
$dql = "SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g.id HAVING userCount > 0";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query);
$paginator->setUseSqlWalkers(true);
$this->assertEquals(9, count($paginator));
}
public function testIterateSimpleWithoutJoinFetchJoinHandlingOff()
{
$dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query, false);
$paginator->setUseSqlWalkers(false);
$data = array();
foreach ($paginator as $user) {
$data[] = $user;
}
$this->assertEquals(3, count($data));
}
public function testIterateSimpleWithoutJoinFetchJoinHandlingOn()
{
$dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query, true);
$paginator->setUseSqlWalkers(false);
$data = array();
foreach ($paginator as $user) {
$data[] = $user;
}
$this->assertEquals(3, count($data));
}
public function testIterateWithFetchJoin()
{
$dql = "SELECT u,g FROM Doctrine\Tests\Models\CMS\CmsUser u JOIN u.groups g";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query, true);
$paginator->setUseSqlWalkers(false);
$data = array();
foreach ($paginator as $user) {
$data[] = $user;
}
$this->assertEquals(3, count($data));
}
public function testIterateComplexWithSqlWalker()
{
$dql = "SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g.id HAVING userCount > 0";
$query = $this->_em->createQuery($dql);
$paginator = new Paginator($query);
$paginator->setUseSqlWalkers(true);
$data = array();
foreach ($paginator as $user) {
$data[] = $user;
}
$this->assertEquals(9, count($data));
}
public function testDetectSqlWalker()
{
// This query works using the SQL walkers but causes an exception using the TreeWalker
$dql = "SELECT g, COUNT(u.id) AS userCount FROM Doctrine\Tests\Models\CMS\CmsGroup g LEFT JOIN g.users u GROUP BY g.id HAVING userCount > 0";
$query = $this->_em->createQuery($dql);
// If the Paginator detects the custom SQL walker it should fall back to using the
// Tree walkers for pagination, which leads to an exception. If the query works, the SQL walkers were used
$query->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, 'Doctrine\ORM\Query\SqlWalker');
$paginator = new Paginator($query);
try {
count($paginator);
$this->fail('Paginator did not detect custom SQL walker');
} catch (\PHPUnit_Framework_Error_Notice $e) {
$this->assertEquals('Undefined index: userCount', $e->getMessage());
}
}
public function populate()
{
for ($i = 0; $i < 3; $i++) {
$user = new CmsUser();
$user->name = "Name$i";
$user->username = "username$i";
$user->status = "active";
$this->_em->persist($user);
for ($j = 0; $j < 3; $j++) {;
$group = new CmsGroup();
$group->name = "group$j";
$user->addGroup($group);
$this->_em->persist($group);
}
}
$this->_em->flush();
}
}