Commit 36c2e76a authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge branch 'master' of github.com:doctrine/dbal

parents d6e2d6fc 0985b38b
......@@ -33,7 +33,6 @@ use PDO, Closure, Exception,
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
......@@ -1093,4 +1092,14 @@ class Connection implements DriverConnection
}
}
}
/**
* Create a new instance of a SQL query builder.
*
* @return Query\QueryBuilder
*/
public function createQueryBuilder()
{
return new Query\QueryBuilder($this);
}
}
\ No newline at end of file
......@@ -24,7 +24,7 @@ namespace Doctrine\DBAL\Query\Expression;
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @since 2.1
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
......@@ -111,10 +111,20 @@ class CompositeExpression implements \Countable
*/
public function __toString()
{
if ($this->count() === 1) {
if (count($this->parts) === 1) {
return (string) $this->parts[0];
}
return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')';
}
/**
* Return type of this composite expression (AND/OR)
*
* @return string
*/
public function getType()
{
return $this->type;
}
}
\ No newline at end of file
......@@ -26,8 +26,7 @@ use Doctrine\DBAL\Connection;
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @since 2.1
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
......
......@@ -24,11 +24,17 @@ use Doctrine\DBAL\Query\Expression\CompositeExpression,
/**
* QueryBuilder class is responsible to dynamically create SQL queries.
*
* Important: Verify that every feature you use will work with your database vendor.
* SQL Query Builder does not attempt to validate the generated SQL at all.
*
* The query builder does no validation whatsoever if certain features even work with the
* underlying database vendor. Limit queries and joins are NOT applied to UPDATE and DELETE statements
* even if some vendors such as MySQL support it.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @since 2.1
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
......@@ -49,7 +55,7 @@ class QueryBuilder
private $connection = null;
/**
* @var array The array of DQL parts collected.
* @var array The array of SQL parts collected.
*/
private $sqlParts = array(
'select' => array(),
......@@ -96,6 +102,13 @@ class QueryBuilder
* @var integer The maximum number of results to retrieve.
*/
private $maxResults = null;
/**
* The counter of bound parameters used with {@see bindValue)
*
* @var int
*/
private $boundCounter = 0;
/**
* Initializes a new <tt>QueryBuilder</tt>.
......@@ -157,18 +170,35 @@ class QueryBuilder
{
return $this->state;
}
/**
* Execute this query using the bound parameters and their types.
*
* Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate}
* for insert, update and delete statements.
*
* @return mixed
*/
public function execute()
{
if ($this->type == self::SELECT) {
return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes);
} else {
return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes);
}
}
/**
* Get the complete DQL string formed by the current specifications of this QueryBuilder.
* Get the complete SQL string formed by the current specifications of this QueryBuilder.
*
* <code>
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u')
* echo $qb->getDql(); // SELECT u FROM User u
* echo $qb->getSQL(); // SELECT u FROM User u
* </code>
*
* @return string The DQL query string.
* @return string The sql query string.
*/
public function getSQL()
{
......@@ -280,6 +310,7 @@ class QueryBuilder
*/
public function setFirstResult($firstResult)
{
$this->state = self::STATE_DIRTY;
$this->firstResult = $firstResult;
return $this;
}
......@@ -303,6 +334,7 @@ class QueryBuilder
*/
public function setMaxResults($maxResults)
{
$this->state = self::STATE_DIRTY;
$this->maxResults = $maxResults;
return $this;
}
......@@ -331,18 +363,22 @@ class QueryBuilder
*/
public function add($sqlPartName, $sqlPart, $append = false)
{
$isArray = is_array($sqlPart);
$isMultiple = is_array($this->sqlParts[$sqlPartName]);
if ($isMultiple && ! is_array($sqlPart)) {
if ($isMultiple && !$isArray) {
$sqlPart = array($sqlPart);
}
$this->state = self::STATE_DIRTY;
if ($append) {
$key = key($sqlPart);
if (is_array($sqlPart[$key])) {
if ($sqlPartName == "orderBy" || $sqlPartName == "groupBy" || $sqlPartName == "select" || $sqlPartName == "set") {
foreach ($sqlPart AS $part) {
$this->sqlParts[$sqlPartName][] = $part;
}
} else if ($isArray && is_array($sqlPart[key($sqlPart)])) {
$key = key($sqlPart);
$this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key];
} else if ($isMultiple) {
$this->sqlParts[$sqlPartName][] = $sqlPart;
......@@ -414,7 +450,7 @@ class QueryBuilder
/**
* Turns the query being built into a bulk delete query that ranges over
* a certain entity type.
* a certain table.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -423,8 +459,8 @@ class QueryBuilder
* ->setParameter(':user_id', 1);
* </code>
*
* @param string $delete The class/type whose instances are subject to the deletion.
* @param string $alias The class/type alias used in the constructed query.
* @param string $delete The table whose rows are subject to the deletion.
* @param string $alias The table alias used in the constructed query.
* @return QueryBuilder This QueryBuilder instance.
*/
public function delete($delete = null, $alias = null)
......@@ -443,7 +479,7 @@ class QueryBuilder
/**
* Turns the query being built into a bulk update query that ranges over
* a certain entity type.
* a certain table
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -452,8 +488,8 @@ class QueryBuilder
* ->where('u.id = ?');
* </code>
*
* @param string $update The class/type whose instances are subject to the update.
* @param string $alias The class/type alias used in the constructed query.
* @param string $update The table whose rows are subject to the update.
* @param string $alias The table alias used in the constructed query.
* @return QueryBuilder This QueryBuilder instance.
*/
public function update($update = null, $alias = null)
......@@ -471,7 +507,7 @@ class QueryBuilder
}
/**
* Create and add a query root corresponding to the entity identified by the
* Create and add a query root corresponding to the table identified by the
* given alias, forming a cartesian product with any existing query roots.
*
* <code>
......@@ -480,8 +516,8 @@ class QueryBuilder
* ->from('users', 'u')
* </code>
*
* @param string $from The class name.
* @param string $alias The alias of the class.
* @param string $from The table
* @param string $alias The alias of the table
* @return QueryBuilder This QueryBuilder instance.
*/
public function from($from, $alias)
......@@ -493,11 +529,7 @@ class QueryBuilder
}
/**
* Creates and adds a join over an entity association to the query.
*
* The entities in the joined association will be fetched as part of the query
* result if the alias used for the joined association is placed in the select
* expressions.
* Creates and adds a join to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -518,11 +550,7 @@ class QueryBuilder
}
/**
* Creates and adds a join over an entity association to the query.
*
* The entities in the joined association will be fetched as part of the query
* result if the alias used for the joined association is placed in the select
* expressions.
* Creates and adds a join to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -550,11 +578,7 @@ class QueryBuilder
}
/**
* Creates and adds a left join over an entity association to the query.
*
* The entities in the joined association will be fetched as part of the query
* result if the alias used for the joined association is placed in the select
* expressions.
* Creates and adds a left join to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -580,9 +604,37 @@ class QueryBuilder
)
), true);
}
/**
* Creates and adds a right join to the query.
*
* <code>
* $qb = $conn->createQueryBuilder()
* ->select('u.name')
* ->from('users', 'u')
* ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1');
* </code>
*
* @param string $fromAlias The alias that points to a from clause
* @param string $join The table name to join
* @param string $alias The alias of the join table
* @param string $condition The condition for the join
* @return QueryBuilder This QueryBuilder instance.
*/
public function rightJoin($fromAlias, $join, $alias, $condition = null)
{
return $this->add('join', array(
$fromAlias => array(
'joinType' => 'right',
'joinTable' => $join,
'joinAlias' => $alias,
'joinCondition' => $condition
)
), true);
}
/**
* Sets a new value for a field in a bulk update query.
* Sets a new value for a column in a bulk update query.
*
* <code>
* $qb = $conn->createQueryBuilder()
......@@ -591,13 +643,13 @@ class QueryBuilder
* ->where('u.id = ?');
* </code>
*
* @param string $key The key/field to set.
* @param string $key The column to set.
* @param string $value The value, expression, placeholder, etc.
* @return QueryBuilder This QueryBuilder instance.
*/
public function set($key, $value)
{
return $this->add('set', $this->expr()->eq($key, '=', $value), true);
return $this->add('set', $key .' = ' . $value, true);
}
/**
......@@ -627,8 +679,8 @@ class QueryBuilder
*/
public function where($predicates)
{
if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression)) {
$predicates = $this->expr()->andX(func_get_args());
if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression) ) {
$predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
return $this->add('where', $predicates);
......@@ -659,7 +711,7 @@ class QueryBuilder
$where->addMultiple($args);
} else {
array_unshift($args, $where);
$where = $this->expr()->andX($args);
$where = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
}
return $this->add('where', $where, true);
......@@ -690,7 +742,7 @@ class QueryBuilder
$where->addMultiple($args);
} else {
array_unshift($args, $where);
$where = $this->expr()->orX($args);
$where = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
}
return $this->add('where', $where, true);
......@@ -757,7 +809,7 @@ class QueryBuilder
public function having($having)
{
if ( ! (func_num_args() == 1 && $having instanceof CompositeExpression)) {
$having = $this->expr()->andX(func_get_args());
$having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args());
}
return $this->add('having', $having);
......@@ -775,11 +827,11 @@ class QueryBuilder
$having = $this->getQueryPart('having');
$args = func_get_args();
if ($having instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) {
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) {
$having->addMultiple($args);
} else {
array_unshift($args, $having);
$having = $this->expr()->andX($args);
$having = new CompositeExpression(CompositeExpression::TYPE_AND, $args);
}
return $this->add('having', $having);
......@@ -797,11 +849,11 @@ class QueryBuilder
$having = $this->getQueryPart('having');
$args = func_get_args();
if ($having instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) {
if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) {
$having->addMultiple($args);
} else {
array_unshift($args, $having);
$having = $this->expr()->orX($args);
$having = new CompositeExpression(CompositeExpression::TYPE_OR, $args);
}
return $this->add('having', $having);
......@@ -817,10 +869,7 @@ class QueryBuilder
*/
public function orderBy($sort, $order = null)
{
return $this->add('orderBy', array(
'sort' => $sort,
'order' => ! $order ? 'ASC' : $order
), false);
return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false);
}
/**
......@@ -832,10 +881,7 @@ class QueryBuilder
*/
public function addOrderBy($sort, $order = null)
{
return $this->add('orderBy', array(
'sort' => $sort,
'order' => ! $order ? 'ASC' : $order
), true);
return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true);
}
/**
......@@ -860,7 +906,7 @@ class QueryBuilder
}
/**
* Reset DQL parts
* Reset SQL parts
*
* @param array $queryPartNames
* @return QueryBuilder
......@@ -879,7 +925,7 @@ class QueryBuilder
}
/**
* Reset single DQL part
* Reset single SQL part
*
* @param string $queryPartName
* @return QueryBuilder
......@@ -926,7 +972,7 @@ class QueryBuilder
. ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '')
. ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : '');
return ($this->maxResults === null)
return ($this->maxResults === null && $this->firstResult == null)
? $query
: $this->connection->getDatabasePlatform()->modifyLimitQuery($query, $this->maxResults, $this->firstResult);
}
......@@ -938,7 +984,10 @@ class QueryBuilder
*/
private function getSQLForUpdate()
{
$query = 'UPDATE ';
$table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : '');
$query = 'UPDATE ' . $table
. ' SET ' . implode(", ", $this->sqlParts['set'])
. ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '');
return $query;
}
......@@ -950,7 +999,8 @@ class QueryBuilder
*/
private function getSQLForDelete()
{
$query = 'DELETE ';
$table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : '');
$query = 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '');
return $query;
}
......@@ -965,4 +1015,70 @@ class QueryBuilder
{
return $this->getSQL();
}
/**
* Create a new named parameter and bind the value $value to it.
*
* This method provides a shortcut for PDOStatement::bindValue
* when using prepared statements.
*
* The parameter $value specifies the value that you want to bind. If
* $placeholder is not provided bindValue() will automatically create a
* placeholder for you. An automatic placeholder will be of the name
* ':dcValue1', ':dcValue2' etc.
*
* For more information see {@link http://php.net/pdostatement-bindparam}
*
* Example:
* <code>
* $value = 2;
* $q->eq( 'id', $q->bindValue( $value ) );
* $stmt = $q->executeQuery(); // executed with 'id = 2'
* </code>
*
* @license New BSD License
* @link http://www.zetacomponents.org
* @param mixed $value
* @param mixed $type
* @param string $placeHolder the name to bind with. The string must start with a colon ':'.
* @return string the placeholder name used.
*/
public function createNamedParameter( $value, $type = \PDO::PARAM_STR, $placeHolder = null )
{
if ( $placeHolder === null ) {
$this->boundCounter++;
$placeHolder = ":dcValue" . $this->boundCounter;
}
$this->setParameter(substr($placeHolder, 1), $value, $type);
return $placeHolder;
}
/**
* Create a new positional parameter and bind the given value to it.
*
* Attention: If you are using positional parameters with the query builder you have
* to be very careful to bind all parameters in the order they appear in the SQL
* statement , otherwise they get bound in the wrong order which can lead to serious
* bugs in your code.
*
* Example:
* <code>
* $qb = $conn->createQueryBuilder();
* $qb->select('u.*')
* ->from('users', 'u')
* ->where('u.username = ' . $qb->createPositionalParameter('Foo', PDO::PARAM_STR))
* ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', PDO::PARAM_STR))
* </code>
*
* @param mixed $value
* @param mixed $type
* @return string
*/
public function createPositionalParameter($value, $type = \PDO::PARAM_STR)
{
$this->boundCounter++;
$this->setParameter($this->boundCounter, $value, $type);
return "?";
}
}
\ No newline at end of file
......@@ -6,6 +6,9 @@ use Doctrine\DBAL\Query\Expression\CompositeExpression;
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DBAL-12
*/
class CompositeExpressionTest extends \Doctrine\Tests\DbalTestCase
{
public function testCount()
......
......@@ -7,6 +7,9 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder,
require_once __DIR__ . '/../../../TestInit.php';
/**
* @group DBAL-12
*/
class ExpressionBuilderTest extends \Doctrine\Tests\DbalTestCase
{
protected $expr;
......
......@@ -7,6 +7,9 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder,
require_once __DIR__ . '/../../TestInit.php';
/**
* @group DBAL-12
*/
class QueryBuilderTest extends \Doctrine\Tests\DbalTestCase
{
protected $conn;
......@@ -44,7 +47,7 @@ class QueryBuilderTest extends \Doctrine\Tests\DbalTestCase
$this->assertEquals("SELECT u.id FROM users u WHERE u.nickname = ?", (string) $qb);
}
public function testSelectWithJoin()
public function testSelectWithLeftJoin()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
......@@ -55,4 +58,494 @@ class QueryBuilderTest extends \Doctrine\Tests\DbalTestCase
$this->assertEquals('SELECT u.*, p.* FROM users u LEFT JOIN phones p ON p.user_id = u.id', (string) $qb);
}
public function testSelectWithJoin()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->Join('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
$this->assertEquals('SELECT u.*, p.* FROM users u INNER JOIN phones p ON p.user_id = u.id', (string) $qb);
}
public function testSelectWithInnerJoin()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->innerJoin('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
$this->assertEquals('SELECT u.*, p.* FROM users u INNER JOIN phones p ON p.user_id = u.id', (string) $qb);
}
public function testSelectWithRightJoin()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->rightJoin('u', 'phones', 'p', $expr->eq('p.user_id', 'u.id'));
$this->assertEquals('SELECT u.*, p.* FROM users u RIGHT JOIN phones p ON p.user_id = u.id', (string) $qb);
}
public function testSelectWithAndWhereConditions()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->where('u.username = ?')
->andWhere('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) AND (u.name = ?)', (string) $qb);
}
public function testSelectWithOrWhereConditions()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->where('u.username = ?')
->orWhere('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) OR (u.name = ?)', (string) $qb);
}
public function testSelectWithOrOrWhereConditions()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->orWhere('u.username = ?')
->orWhere('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u WHERE (u.username = ?) OR (u.name = ?)', (string) $qb);
}
public function testSelectWithAndOrWhereConditions()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->where('u.username = ?')
->andWhere('u.username = ?')
->orWhere('u.name = ?')
->andWhere('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u WHERE (((u.username = ?) AND (u.username = ?)) OR (u.name = ?)) AND (u.name = ?)', (string) $qb);
}
public function testSelectGroupBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id', (string) $qb);
}
public function testSelectEmptyGroupBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->groupBy(array())
->from('users', 'u');
$this->assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testSelectEmptyAddGroupBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->addGroupBy(array())
->from('users', 'u');
$this->assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testSelectAddGroupBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->addGroupBy('u.foo');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id, u.foo', (string) $qb);
}
public function testSelectAddGroupBys()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->addGroupBy('u.foo', 'u.bar');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id, u.foo, u.bar', (string) $qb);
}
public function testSelectHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->having('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING u.name = ?', (string) $qb);
}
public function testSelectAndHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->andHaving('u.name = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING u.name = ?', (string) $qb);
}
public function testSelectHavingAndHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->having('u.name = ?')
->andHaving('u.username = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) AND (u.username = ?)', (string) $qb);
}
public function testSelectHavingOrHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->having('u.name = ?')
->orHaving('u.username = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) OR (u.username = ?)', (string) $qb);
}
public function testSelectOrHavingOrHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->orHaving('u.name = ?')
->orHaving('u.username = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING (u.name = ?) OR (u.username = ?)', (string) $qb);
}
public function testSelectHavingAndOrHaving()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->groupBy('u.id')
->having('u.name = ?')
->orHaving('u.username = ?')
->andHaving('u.username = ?');
$this->assertEquals('SELECT u.*, p.* FROM users u GROUP BY u.id HAVING ((u.name = ?) OR (u.username = ?)) AND (u.username = ?)', (string) $qb);
}
public function testSelectOrderBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->orderBy('u.name');
$this->assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC', (string) $qb);
}
public function testSelectAddOrderBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->orderBy('u.name')
->addOrderBy('u.username', 'DESC');
$this->assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC, u.username DESC', (string) $qb);
}
public function testSelectAddAddOrderBy()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*', 'p.*')
->from('users', 'u')
->addOrderBy('u.name')
->addOrderBy('u.username', 'DESC');
$this->assertEquals('SELECT u.*, p.* FROM users u ORDER BY u.name ASC, u.username DESC', (string) $qb);
}
public function testEmptySelect()
{
$qb = new QueryBuilder($this->conn);
$qb2 = $qb->select();
$this->assertSame($qb, $qb2);
$this->assertEquals(QueryBuilder::SELECT, $qb->getType());
}
public function testSelectAddSelect()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*')
->addSelect('p.*')
->from('users', 'u');
$this->assertEquals('SELECT u.*, p.* FROM users u', (string) $qb);
}
public function testEmptyAddSelect()
{
$qb = new QueryBuilder($this->conn);
$qb2 = $qb->addSelect();
$this->assertSame($qb, $qb2);
$this->assertEquals(QueryBuilder::SELECT, $qb->getType());
}
public function testSelectMultipleFrom()
{
$qb = new QueryBuilder($this->conn);
$expr = $qb->expr();
$qb->select('u.*')
->addSelect('p.*')
->from('users', 'u')
->from('phonenumbers', 'p');
$this->assertEquals('SELECT u.*, p.* FROM users u, phonenumbers p', (string) $qb);
}
public function testUpdate()
{
$qb = new QueryBuilder($this->conn);
$qb->update('users', 'u')
->set('u.foo', '?')
->set('u.bar', '?');
$this->assertEquals(QueryBuilder::UPDATE, $qb->getType());
$this->assertEquals('UPDATE users u SET u.foo = ?, u.bar = ?', (string) $qb);
}
public function testUpdateWithoutAlias()
{
$qb = new QueryBuilder($this->conn);
$qb->update('users')
->set('foo', '?')
->set('bar', '?');
$this->assertEquals('UPDATE users SET foo = ?, bar = ?', (string) $qb);
}
public function testUpdateWhere()
{
$qb = new QueryBuilder($this->conn);
$qb->update('users', 'u')
->set('u.foo', '?')
->where('u.foo = ?');
$this->assertEquals('UPDATE users u SET u.foo = ? WHERE u.foo = ?', (string) $qb);
}
public function testEmptyUpdate()
{
$qb = new QueryBuilder($this->conn);
$qb2 = $qb->update();
$this->assertEquals(QueryBuilder::UPDATE, $qb->getType());
$this->assertSame($qb2, $qb);
}
public function testDelete()
{
$qb = new QueryBuilder($this->conn);
$qb->delete('users', 'u');
$this->assertEquals(QueryBuilder::DELETE, $qb->getType());
$this->assertEquals('DELETE FROM users u', (string) $qb);
}
public function testDeleteWithoutAlias()
{
$qb = new QueryBuilder($this->conn);
$qb->delete('users');
$this->assertEquals(QueryBuilder::DELETE, $qb->getType());
$this->assertEquals('DELETE FROM users', (string) $qb);
}
public function testDeleteWhere()
{
$qb = new QueryBuilder($this->conn);
$qb->delete('users', 'u')
->where('u.foo = ?');
$this->assertEquals('DELETE FROM users u WHERE u.foo = ?', (string) $qb);
}
public function testEmptyDelete()
{
$qb = new QueryBuilder($this->conn);
$qb2 = $qb->delete();
$this->assertEquals(QueryBuilder::DELETE, $qb->getType());
$this->assertSame($qb2, $qb);
}
public function testGetConnection()
{
$qb = new QueryBuilder($this->conn);
$this->assertSame($this->conn, $qb->getConnection());
}
public function testGetState()
{
$qb = new QueryBuilder($this->conn);
$this->assertEquals(QueryBuilder::STATE_CLEAN, $qb->getState());
$qb->select('u.*')->from('users', 'u');
$this->assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
$sql1 = $qb->getSQL();
$this->assertEquals(QueryBuilder::STATE_CLEAN, $qb->getState());
$this->assertEquals($sql1, $qb->getSQL());
}
public function testSetMaxResults()
{
$qb = new QueryBuilder($this->conn);
$qb->setMaxResults(10);
$this->assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
$this->assertEQuals(10, $qb->getMaxResults());
}
public function testSetFirstResult()
{
$qb = new QueryBuilder($this->conn);
$qb->setFirstResult(10);
$this->assertEquals(QueryBuilder::STATE_DIRTY, $qb->getState());
$this->assertEQuals(10, $qb->getFirstResult());
}
public function testResetQueryPart()
{
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')->from('users', 'u')->where('u.name = ?');
$this->assertEquals('SELECT u.* FROM users u WHERE u.name = ?', (string)$qb);
$qb->resetQueryPart('where');
$this->assertEquals('SELECT u.* FROM users u', (string)$qb);
}
public function testResetQueryParts()
{
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')->from('users', 'u')->where('u.name = ?')->orderBy('u.name');
$this->assertEquals('SELECT u.* FROM users u WHERE u.name = ? ORDER BY u.name ASC', (string)$qb);
$qb->resetQueryParts(array('where', 'orderBy'));
$this->assertEquals('SELECT u.* FROM users u', (string)$qb);
}
public function testCreateNamedParameter()
{
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')->from('users', 'u')->where(
$qb->expr()->eq('u.name', $qb->createNamedParameter(10, \PDO::PARAM_INT))
);
$this->assertEquals('SELECT u.* FROM users u WHERE u.name = :dcValue1', (string)$qb);
$this->assertEquals(10, $qb->getParameter('dcValue1'));
}
public function testCreateNamedParameterCustomPlaceholder()
{
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')->from('users', 'u')->where(
$qb->expr()->eq('u.name', $qb->createNamedParameter(10, \PDO::PARAM_INT, ':test'))
);
$this->assertEquals('SELECT u.* FROM users u WHERE u.name = :test', (string)$qb);
$this->assertEquals(10, $qb->getParameter('test'));
}
public function testCreatePositionalParameter()
{
$qb = new QueryBuilder($this->conn);
$qb->select('u.*')->from('users', 'u')->where(
$qb->expr()->eq('u.name', $qb->createPositionalParameter(10, \PDO::PARAM_INT))
);
$this->assertEquals('SELECT u.* FROM users u WHERE u.name = ?', (string)$qb);
$this->assertEquals(10, $qb->getParameter(1));
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment