1
0
mirror of synced 2025-02-21 14:43:14 +03:00

[2.0] More work on the QueryBuilder and Expr classes.

This commit is contained in:
jwage 2009-07-10 17:53:48 +00:00
parent 312d347d2d
commit f608dd8a72
19 changed files with 433 additions and 81 deletions

View File

@ -1538,6 +1538,19 @@ abstract class AbstractPlatform
return 'H:i:s'; return 'H:i:s';
} }
public function modifyLimitQuery($query, $max, $first)
{
if ( ! is_null($first)) {
$query .= ' OFFSET ' . $first;
}
if ( ! is_null($max)) {
$query .= ' LIMIT ' . $max;
}
return $query;
}
/** /**
* Gets the SQL snippet used to declare a VARCHAR column type. * Gets the SQL snippet used to declare a VARCHAR column type.
* *

View File

@ -425,4 +425,92 @@ class MsSqlPlatform extends AbstractPlatform
{ {
return 'mssql'; return 'mssql';
} }
/**
* Adds an adapter-specific LIMIT clause to the SELECT statement.
*
* @param string $query
* @param mixed $limit
* @param mixed $offset
* @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html
* @return string
*/
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
{
if ($limit > 0) {
$count = intval($limit);
$offset = intval($offset);
if ($offset < 0) {
throw new Doctrine_Connection_Exception("LIMIT argument offset=$offset is not valid");
}
$orderby = stristr($query, 'ORDER BY');
if ($orderby !== false) {
// Ticket #1835: Fix for ORDER BY alias
// Ticket #2050: Fix for multiple ORDER BY clause
$order = str_ireplace('ORDER BY', '', $orderby);
$orders = explode(',', $order);
for ($i = 0; $i < count($orders); $i++) {
$sorts[$i] = (stripos($orders[$i], ' desc') !== false) ? 'desc' : 'asc';
$orders[$i] = trim(preg_replace('/\s+(ASC|DESC)$/i', '', $orders[$i]));
// find alias in query string
$helper_string = stristr($query, $orders[$i]);
$from_clause_pos = strpos($helper_string, ' FROM ');
$fields_string = substr($helper_string, 0, $from_clause_pos + 1);
$field_array = explode(',', $fields_string);
$field_array = array_shift($field_array);
$aux2 = spliti(' as ', $field_array);
$aliases[$i] = trim(end($aux2));
}
}
// Ticket #1259: Fix for limit-subquery in MSSQL
$selectRegExp = 'SELECT\s+';
$selectReplace = 'SELECT ';
if (preg_match('/^SELECT(\s+)DISTINCT/i', $query)) {
$selectRegExp .= 'DISTINCT\s+';
$selectReplace .= 'DISTINCT ';
}
$query = preg_replace('/^'.$selectRegExp.'/i', $selectReplace . 'TOP ' . ($count + $offset) . ' ', $query);
$query = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $query . ') AS ' . $this->quoteIdentifier('inner_tbl');
if ($orderby !== false) {
$query .= ' ORDER BY ';
for ($i = 0, $l = count($orders); $i < $l; $i++) {
if ($i > 0) { // not first order clause
$query .= ', ';
}
$query .= $this->quoteIdentifier('inner_tbl') . '.' . $aliases[$i] . ' ';
$query .= (stripos($sorts[$i], 'asc') !== false) ? 'DESC' : 'ASC';
}
}
$query .= ') AS ' . $this->quoteIdentifier('outer_tbl');
if ($orderby !== false) {
$query .= ' ORDER BY ';
for ($i = 0, $l = count($orders); $i < $l; $i++) {
if ($i > 0) { // not first order clause
$query .= ', ';
}
$query .= $this->quoteIdentifier('outer_tbl') . '.' . $aliases[$i] . ' ' . $sorts[$i];
}
}
}
return $query;
}
} }

View File

@ -469,4 +469,38 @@ END;';
{ {
return 'oracle'; return 'oracle';
} }
/**
* Adds an driver-specific LIMIT clause to the query
*
* @param string $query query to modify
* @param integer $limit limit the number of rows
* @param integer $offset start reading from given offset
* @return string the modified query
*/
public function modifyLimitQuery($query, $limit = false, $offset = false, $isManip = false)
{
$limit = (int) $limit;
$offset = (int) $offset;
if (preg_match('/^\s*SELECT/i', $query)) {
if ( ! preg_match('/\sFROM\s/i', $query)) {
$query .= " FROM dual";
}
if ($limit > 0) {
$max = $offset + $limit;
$column = $column === null ? '*' : $this->quoteIdentifier($column);
if ($offset > 0) {
$min = $offset + 1;
$query = 'SELECT b.'.$column.' FROM ('.
'SELECT a.*, ROWNUM AS doctrine_rownum FROM ('
. $query . ') a '.
') b '.
'WHERE doctrine_rownum BETWEEN ' . $min . ' AND ' . $max;
} else {
$query = 'SELECT a.'.$column.' FROM (' . $query .') a WHERE ROWNUM <= ' . $max;
}
}
}
return $query;
}
} }

View File

@ -33,24 +33,34 @@ namespace Doctrine\ORM\Query;
*/ */
class Expr class Expr
{ {
public static function andx() public static function andx($x = null)
{ {
return new Expr\Andx(func_get_args()); return new Expr\Andx(func_get_args());
} }
public static function orx() public static function orx($x = null)
{ {
return new Expr\Orx(func_get_args()); return new Expr\Orx(func_get_args());
} }
public static function select() public static function select($select = null)
{ {
return new Expr\Select(func_get_args()); return new Expr\Select(func_get_args());
} }
public static function selectField($field, $alias = null) public static function orderBy($sort = null, $order = null)
{ {
return new Expr\SelectField($field, $alias); return new Expr\OrderBy($sort, $order);
}
public static function groupBy($groupBy = null)
{
return new Expr\GroupBy(func_get_args());
}
public static function having($having = null)
{
return new Expr\Having(func_get_args());
} }
public static function eq($x, $y) public static function eq($x, $y)
@ -105,7 +115,7 @@ class Expr
public static function countDistinct() public static function countDistinct()
{ {
return new Expr\CountDistinctFunction(func_get_args()); return 'COUNT(DISTINCT ' . implode(', ', func_get_args()) . ')';
} }
public static function exists($subquery) public static function exists($subquery)

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for building and clauses * Expression class for building DQL and parts
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com> * @author Guilherme Blanco <guilhermeblanco@gmail.com>

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Abstract class for building DQL expressions * Abstract base Expr class for building DQL parts
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com> * @author Guilherme Blanco <guilhermeblanco@gmail.com>
@ -68,7 +68,7 @@ abstract class Base
return count($this->_parts); return count($this->_parts);
} }
public function __tostring() public function __toString()
{ {
return $this->_preSeparator . implode($this->_separator, $this->_parts) . $this->_postSeparator; return $this->_preSeparator . implode($this->_separator, $this->_parts) . $this->_postSeparator;
} }

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for comparison statements * Expression class for DQL comparison expressions
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for building comparison clauses * Expression class for generating DQL functions
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL

View File

@ -22,25 +22,17 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for building comparison clauses * Expression class for building DQL Group By parts
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://www.phpdoctrine.org * @link http://www.phpdoctrine.org
* @since 2.0 * @since 2.0
* @version $Revision$ * @version $Revision$
*/ */
class CountDistinctFunction class GroupBy extends Base
{ {
private $_arguments; protected $_preSeparator = '';
protected $_postSeparator = '';
public function __construct($arguments)
{
$this->_arguments = $arguments;
}
public function __toString()
{
return 'COUNT(DISTINCT ' . implode(', ', $this->_arguments) . ')';
}
} }

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for math statements * Expression class for DQL math statements
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* This class is used for representing field in a select statement * Expression class for building DQL Order By parts
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com> * @author Guilherme Blanco <guilhermeblanco@gmail.com>
@ -31,19 +31,35 @@ namespace Doctrine\ORM\Query\Expr;
* @since 2.0 * @since 2.0
* @version $Revision$ * @version $Revision$
*/ */
class SelectField class OrderBy
{ {
private $_field; protected $_preSeparator = '';
private $_alias; protected $_separator = ', ';
protected $_postSeparator = '';
protected $_allowedClasses = array();
public function __construct($field, $alias = null) private $_parts = array();
public function __construct($sort = null, $order = null)
{ {
$this->_field = $field; if ($sort) {
$this->_alias = $alias; $this->add($sort, $order);
}
} }
public function __toString() public function add($sort, $order = null)
{ {
return $this->_field . (($this->_alias !== null) ? ' AS ' . $this->_alias : ''); $order = ! $order ? 'ASC' : $order;
$this->_parts[] = $sort . ' '. $order;
}
public function count()
{
return count($this->_parts);
}
public function __tostring()
{
return $this->_preSeparator . implode($this->_separator, $this->_parts) . $this->_postSeparator;
} }
} }

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for building and clauses * Expression class for building DQL OR clauses
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com> * @author Guilherme Blanco <guilhermeblanco@gmail.com>

View File

@ -22,7 +22,7 @@
namespace Doctrine\ORM\Query\Expr; namespace Doctrine\ORM\Query\Expr;
/** /**
* Expression class for building DQL select clauses * Expression class for building DQL select statements
* *
* @author Jonathan H. Wage <jonwage@gmail.com> * @author Jonathan H. Wage <jonwage@gmail.com>
* @author Guilherme Blanco <guilhermeblanco@gmail.com> * @author Guilherme Blanco <guilhermeblanco@gmail.com>
@ -35,7 +35,4 @@ class Select extends Base
{ {
protected $_preSeparator = ''; protected $_preSeparator = '';
protected $_postSeparator = ''; protected $_postSeparator = '';
protected $_allowedClasses = array(
'Doctrine\ORM\Query\Expr\SelectField'
);
} }

View File

@ -134,6 +134,10 @@ class SqlWalker implements TreeWalker
$sql .= $AST->getHavingClause() ? $this->walkHavingClause($AST->getHavingClause()) : ''; $sql .= $AST->getHavingClause() ? $this->walkHavingClause($AST->getHavingClause()) : '';
$sql .= $AST->getOrderByClause() ? $this->walkOrderByClause($AST->getOrderByClause()) : ''; $sql .= $AST->getOrderByClause() ? $this->walkOrderByClause($AST->getOrderByClause()) : '';
$q = $this->getQuery();
$sql = $this->getConnection()->getDatabasePlatform()
->modifyLimitQuery($sql, $q->getMaxResults(), $q->getFirstResult());
return $sql; return $sql;
} }

View File

@ -49,41 +49,49 @@ class QueryBuilder
/** /**
* @var EntityManager $em Instance of an EntityManager to use for query * @var EntityManager $em Instance of an EntityManager to use for query
*/ */
protected $_em; private $_em;
/** /**
* @var array $dqlParts The array of DQL parts collected * @var array $dqlParts The array of DQL parts collected
*/ */
protected $_dqlParts = array( private $_dqlParts = array(
'select' => array(), 'select' => array(),
'from' => array(), 'from' => array(),
'where' => array(), 'where' => array(),
'groupBy' => array(), 'groupBy' => array(),
'having' => array(), 'having' => array(),
'orderBy' => array(), 'orderBy' => array()
'limit' => array(),
'offset' => array()
); );
/** /**
* @var integer $type The type of query this is. Can be select, update or delete * @var integer $type The type of query this is. Can be select, update or delete
*/ */
protected $_type = self::SELECT; private $_type = self::SELECT;
/** /**
* @var integer $state The state of the query object. Can be dirty or clean. * @var integer $state The state of the query object. Can be dirty or clean.
*/ */
protected $_state = self::STATE_CLEAN; private $_state = self::STATE_CLEAN;
/** /**
* @var string $dql The complete DQL string for this query * @var string $dql The complete DQL string for this query
*/ */
protected $_dql; private $_dql;
/** /**
* @var array $params Parameters of this query. * @var array $params Parameters of this query.
*/ */
protected $_params = array(); private $_params = array();
/**
* @var integer The first result to return (the "offset").
*/
private $_firstResult = null;
/**
* @var integer The maximum number of results to return (the "limit").
*/
private $_maxResults = null;
public function __construct(EntityManager $entityManager) public function __construct(EntityManager $entityManager)
{ {
@ -143,6 +151,8 @@ class QueryBuilder
$q = new Query($this->_em); $q = new Query($this->_em);
$q->setDql($this->getDql()); $q->setDql($this->getDql());
$q->setParameters($this->getParameters()); $q->setParameters($this->getParameters());
$q->setFirstResult($this->getFirstResult());
$q->setMaxResults($this->getMaxResults());
return $q; return $q;
} }
@ -224,7 +234,7 @@ class QueryBuilder
return $this; return $this;
} }
public function select($select) public function select($select = null)
{ {
$selects = func_get_args(); $selects = func_get_args();
$this->_type = self::SELECT; $this->_type = self::SELECT;
@ -349,12 +359,17 @@ class QueryBuilder
public function groupBy($groupBy) public function groupBy($groupBy)
{ {
return $this->add('groupBy', $groupBy, false); return $this->add('groupBy', Expr::groupBy($groupBy), false);
}
public function addGroupBy($groupBy)
{
return $this->add('groupBy', Expr::groupBy($groupBy), true);
} }
public function having($having) public function having($having)
{ {
return $this->add('having', $having, false); return $this->add('having', Expr::having($having), false);
} }
public function andHaving($having) public function andHaving($having)
@ -363,7 +378,7 @@ class QueryBuilder
$this->add('having', 'AND', true); $this->add('having', 'AND', true);
} }
return $this->add('having', $having, true); return $this->add('having', Expr::having($having), true);
} }
public function orHaving($having) public function orHaving($having)
@ -372,27 +387,63 @@ class QueryBuilder
$this->add('having', 'OR', true); $this->add('having', 'OR', true);
} }
return $this->add('having', $having, true); return $this->add('having', Expr::having($having), true);
} }
public function orderBy($sort, $order) public function orderBy($sort, $order)
{ {
return $this->add('orderBy', $sort . ' ' . $order, false); return $this->add('orderBy', Expr::orderBy($sort, $order), false);
} }
public function addOrderBy($sort, $order) public function addOrderBy($sort, $order)
{ {
return $this->add('orderBy', $sort . ' ' . $order, true); return $this->add('orderBy', Expr::orderBy($sort, $order), true);
} }
public function limit($limit) /**
* Sets the position of the first result to retrieve (the "offset").
*
* @param integer $firstResult The first result to return.
* @return Query This query object.
*/
public function setFirstResult($firstResult)
{ {
return $this->add('limit', $limit); $this->_firstResult = $firstResult;
return $this;
}
/**
* Gets the position of the first result the query object was set to retrieve (the "offset").
* Returns NULL if {@link setFirstResult} was not applied to this query.
*
* @return integer The position of the first result.
*/
public function getFirstResult()
{
return $this->_firstResult;
} }
public function offset($offset) /**
* Sets the maximum number of results to retrieve (the "limit").
*
* @param integer $maxResults
* @return Query This query object.
*/
public function setMaxResults($maxResults)
{ {
return $this->add('offset', $offset); $this->_maxResults = $maxResults;
return $this;
}
/**
* Gets the maximum number of results the query object was set to retrieve (the "limit").
* Returns NULL if {@link setMaxResults} was not applied to this query.
*
* @return integer Maximum number of results.
*/
public function getMaxResults()
{
return $this->_maxResults;
} }
/** /**
@ -414,9 +465,7 @@ class QueryBuilder
return 'DELETE' return 'DELETE'
. $this->_getReducedDqlQueryPart('from', array('pre' => ' ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('from', array('pre' => ' ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', ')) . $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', '));
. $this->_getReducedDqlQueryPart('limit', array('pre' => ' LIMIT ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('offset', array('pre' => ' OFFSET ', 'separator' => ' '));
} }
/** /**
@ -439,9 +488,7 @@ class QueryBuilder
. $this->_getReducedDqlQueryPart('from', array('pre' => ' ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('from', array('pre' => ' ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('set', array('pre' => ' SET ', 'separator' => ', ')) . $this->_getReducedDqlQueryPart('set', array('pre' => ' SET ', 'separator' => ', '))
. $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', ')) . $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', '));
. $this->_getReducedDqlQueryPart('limit', array('pre' => ' LIMIT ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('offset', array('pre' => ' OFFSET ', 'separator' => ' '));
} }
/** /**
@ -469,9 +516,7 @@ class QueryBuilder
. $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('where', array('pre' => ' WHERE ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('groupBy', array('pre' => ' GROUP BY ', 'separator' => ', ')) . $this->_getReducedDqlQueryPart('groupBy', array('pre' => ' GROUP BY ', 'separator' => ', '))
. $this->_getReducedDqlQueryPart('having', array('pre' => ' HAVING ', 'separator' => ' ')) . $this->_getReducedDqlQueryPart('having', array('pre' => ' HAVING ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', ')) . $this->_getReducedDqlQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', '));
. $this->_getReducedDqlQueryPart('limit', array('pre' => ' LIMIT ', 'separator' => ' '))
. $this->_getReducedDqlQueryPart('offset', array('pre' => ' OFFSET ', 'separator' => ' '));
} }
private function _getReducedDqlQueryPart($queryPartName, $options = array()) private function _getReducedDqlQueryPart($queryPartName, $options = array())

View File

@ -34,6 +34,7 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToOneSelfReferentialAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToOneSelfReferentialAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToManySelfReferentialAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\OneToManySelfReferentialAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManySelfReferentialAssociationTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Functional\ManyToManySelfReferentialAssociationTest');
$suite->addTestSuite('Doctrine\Tests\ORM\Functional\QueryBuilderTest');
return $suite; return $suite;
} }

View File

@ -0,0 +1,73 @@
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsArticle;
use Doctrine\ORM\QueryBuilder;
require_once __DIR__ . '/../../TestInit.php';
class QueryBuilderTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}
public function testExecute()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$results = $qb->execute();
$this->assertEquals('Doctrine\Common\Collections\Collection', get_class($results));
}
public function testSetMaxResultsAndSetFirstResultZero()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->setMaxResults(10)
->setFirstResult(0);
$this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ OFFSET 0 LIMIT 10', $qb->getQuery()->getSql());
}
public function testSetMaxResultsAndSetFirstResult()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->setMaxResults(10)
->setFirstResult(10);
$this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ OFFSET 10 LIMIT 10', $qb->getQuery()->getSql());
}
public function testRemoveSetMaxResultsAndSetFirstResult()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->setMaxResults(10)
->setFirstResult(0)
->setMaxResults(null)
->setFirstResult(null);
$this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_', $qb->getQuery()->getSql());
}
public function testOnlyFirstResult()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->setMaxResults(10);
$this->assertEquals('SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ LIMIT 10', $qb->getQuery()->getSql());
}
}

View File

@ -245,9 +245,48 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
public function testSelectExpr() public function testSelectExpr()
{ {
$selectExpr = Expr::select(); $selectExpr = Expr::select();
$selectExpr->add(Expr::selectField('u.id')); $selectExpr->add('u.id');
$selectExpr->add(Expr::selectField('u.username', 'my_test')); $selectExpr->add('u.username');
$this->assertEquals('u.id, u.username AS my_test', (string) $selectExpr); $this->assertEquals('u.id, u.username', (string) $selectExpr);
}
public function testExprBaseCount()
{
$selectExpr = Expr::select();
$selectExpr->add('u.id');
$selectExpr->add('u.username');
$this->assertEquals($selectExpr->count(), 2);
}
public function testOrderByCountExpr()
{
$orderByExpr = Expr::orderBy();
$orderByExpr->add('u.username', 'DESC');
$this->assertEquals($orderByExpr->count(), 1);
$this->assertEquals('u.username DESC', (string) $orderByExpr);
}
public function testOrderByOrder()
{
$orderByExpr = Expr::orderBy('u.username', 'DESC');
$this->assertEquals('u.username DESC', (string) $orderByExpr);
}
public function testOrderByDefaultOrderIsAsc()
{
$orderByExpr = Expr::orderBy('u.username');
$this->assertEquals('u.username ASC', (string) $orderByExpr);
}
/**
* @expectedException Doctrine\Common\DoctrineException
*/
public function testAddThrowsException()
{
$orExpr = Expr::orx();
$orExpr->add(Expr::quot(5, 2));
} }
} }

View File

@ -65,6 +65,15 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($qb->getType(), QueryBuilder::SELECT); $this->assertEquals($qb->getType(), QueryBuilder::SELECT);
} }
public function testEmptySelectSetsType()
{
$qb = QueryBuilder::create($this->_em)
->delete('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->select();
$this->assertEquals($qb->getType(), QueryBuilder::SELECT);
}
public function testDeleteSetsType() public function testDeleteSetsType()
{ {
$qb = QueryBuilder::create($this->_em) $qb = QueryBuilder::create($this->_em)
@ -210,9 +219,10 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$qb = QueryBuilder::create($this->_em) $qb = QueryBuilder::create($this->_em)
->select('u') ->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->groupBy('u.id'); ->groupBy('u.id')
->addGroupBy('u.username');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id, u.username');
} }
public function testHaving() public function testHaving()
@ -309,6 +319,29 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals($q->getParameters(), array('username' => 'jwage', 'username2' => 'jonwage')); $this->assertEquals($q->getParameters(), array('username' => 'jwage', 'username2' => 'jonwage'));
} }
public function testGetParameters()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id = :id');
$qb->setParameters(array('id' => 1));
$this->assertEquals(array('id' => 1, 'test' => 1), $qb->getParameters(array('test' => 1)));
}
public function testGetParameter()
{
$qb = QueryBuilder::create($this->_em)
->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id = :id');
$qb->setParameters(array('id' => 1));
$this->assertEquals(1, $qb->getParameter('id'));
}
public function testMultipleWhere() public function testMultipleWhere()
{ {
$qb = QueryBuilder::create($this->_em) $qb = QueryBuilder::create($this->_em)
@ -353,17 +386,24 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((u.id = :uid3) OR (u.id IN(1)))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((u.id = :uid3) OR (u.id IN(1)))');
} }
public function testLimit() public function testGetEntityManager()
{
$qb = QueryBuilder::create($this->_em);
$this->assertEquals($this->_em, $qb->getEntityManager());
}
public function testInitialStateIsClean()
{
$qb = QueryBuilder::create($this->_em);
$this->assertEquals(QueryBuilder::STATE_CLEAN, $qb->getState());
}
public function testAlteringQueryChangesStateToDirty()
{ {
/*
TODO: Limit fails. Is this not implemented in the DQL parser? Will look tomorrow.
$qb = QueryBuilder::create($this->_em) $qb = QueryBuilder::create($this->_em)
->select('u') ->select('u')
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u');
->limit(10)
->offset(0);
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u LIMIT 10'); $this->assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
*/
} }
} }