1
0
mirror of synced 2025-02-02 05:21:44 +03:00

Fixed where componentes (ie. MEMBER OF) that that are sensitive to parenthesis presence. Made OR and AND expressions smarter. Fixed related unit tests.

This commit is contained in:
Guilherme Blanco 2011-05-07 20:14:04 -03:00
parent bffca232e2
commit b025b2b343
8 changed files with 80 additions and 27 deletions

View File

@ -32,9 +32,9 @@ namespace Doctrine\ORM\Query\Expr;
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
class Andx extends Base class Andx extends Composite
{ {
protected $_separator = ') AND ('; protected $_separator = ' AND ';
protected $_allowedClasses = array( protected $_allowedClasses = array(
'Doctrine\ORM\Query\Expr\Comparison', 'Doctrine\ORM\Query\Expr\Comparison',
'Doctrine\ORM\Query\Expr\Func', 'Doctrine\ORM\Query\Expr\Func',

View File

@ -39,7 +39,7 @@ abstract class Base
protected $_postSeparator = ')'; protected $_postSeparator = ')';
protected $_allowedClasses = array(); protected $_allowedClasses = array();
private $_parts = array(); protected $_parts = array();
public function __construct($args = array()) public function __construct($args = array())
{ {

View File

@ -0,0 +1,53 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query\Expr;
/**
* Expression class for building DQL and parts
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Composite extends Base
{
public function __toString()
{
if ($this->count() === 1) {
return (string) $this->_parts[0];
}
$components = array();
foreach ($this->_parts as $part) {
$components[] = (is_object($part) && $part instanceof self && $part->count() > 1)
? $this->_preSeparator . ((string) $part) . $this->_postSeparator
: ((string) $part);
}
return implode($this->_separator, $components);
}
}

View File

@ -32,9 +32,9 @@ namespace Doctrine\ORM\Query\Expr;
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
class Orx extends Base class Orx extends Composite
{ {
protected $_separator = ') OR ('; protected $_separator = ' OR ';
protected $_allowedClasses = array( protected $_allowedClasses = array(
'Doctrine\ORM\Query\Expr\Andx', 'Doctrine\ORM\Query\Expr\Andx',
'Doctrine\ORM\Query\Expr\Comparison', 'Doctrine\ORM\Query\Expr\Comparison',

View File

@ -629,7 +629,7 @@ class QueryBuilder
*/ */
public function where($predicates) public function where($predicates)
{ {
if ( ! (func_num_args() == 1 && ($predicates instanceof Expr\Andx || $predicates instanceof Expr\Orx))) { if ( ! (func_num_args() == 1 && $predicates instanceof Expr\Composite)) {
$predicates = new Expr\Andx(func_get_args()); $predicates = new Expr\Andx(func_get_args());
} }

@ -1 +1 @@
Subproject commit 076a03f8f40b6e08f0ae2f4ee2678474e64b6f59 Subproject commit ba63ae0f0b6b62a2a8617f01386698730ff2b713

View File

@ -111,20 +111,20 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
public function testAndExpr() public function testAndExpr()
{ {
$this->assertEquals('(1 = 1) AND (2 = 2)', (string) $this->_expr->andx((string) $this->_expr->eq(1, 1), (string) $this->_expr->eq(2, 2))); $this->assertEquals('1 = 1 AND 2 = 2', (string) $this->_expr->andx((string) $this->_expr->eq(1, 1), (string) $this->_expr->eq(2, 2)));
} }
public function testIntelligentParenthesisPreventionAndExpr() public function testIntelligentParenthesisPreventionAndExpr()
{ {
$this->assertEquals( $this->assertEquals(
'(1 = 1) AND (2 = 2)', '1 = 1 AND 2 = 2',
(string) $this->_expr->andx($this->_expr->orx($this->_expr->andx($this->_expr->eq(1, 1))), (string) $this->_expr->eq(2, 2)) (string) $this->_expr->andx($this->_expr->orx($this->_expr->andx($this->_expr->eq(1, 1))), (string) $this->_expr->eq(2, 2))
); );
} }
public function testOrExpr() public function testOrExpr()
{ {
$this->assertEquals('(1 = 1) OR (2 = 2)', (string) $this->_expr->orx((string) $this->_expr->eq(1, 1), (string) $this->_expr->eq(2, 2))); $this->assertEquals('1 = 1 OR 2 = 2', (string) $this->_expr->orx((string) $this->_expr->eq(1, 1), (string) $this->_expr->eq(2, 2)));
} }
public function testAbsExpr() public function testAbsExpr()
@ -296,7 +296,7 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
$orExpr->add($andExpr); $orExpr->add($andExpr);
$orExpr->add($this->_expr->eq(1, 1)); $orExpr->add($this->_expr->eq(1, 1));
$this->assertEquals('((1 = 1) AND (1 < 5)) OR (1 = 1)', (string) $orExpr); $this->assertEquals('(1 = 1 AND 1 < 5) OR 1 = 1', (string) $orExpr);
} }
public function testOrxExpr() public function testOrxExpr()
@ -305,7 +305,7 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
$orExpr->add($this->_expr->eq(1, 1)); $orExpr->add($this->_expr->eq(1, 1));
$orExpr->add($this->_expr->lt(1, 5)); $orExpr->add($this->_expr->lt(1, 5));
$this->assertEquals('(1 = 1) OR (1 < 5)', (string) $orExpr); $this->assertEquals('1 = 1 OR 1 < 5', (string) $orExpr);
} }
public function testOrderByCountExpr() public function testOrderByCountExpr()

View File

@ -162,7 +162,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->andWhere('u.id = :uid2'); ->andWhere('u.id = :uid2');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) AND (u.id = :uid2)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid AND u.id = :uid2');
} }
public function testOrWhere() public function testOrWhere()
@ -173,7 +173,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->orWhere('u.id = :uid2'); ->orWhere('u.id = :uid2');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) OR (u.id = :uid2)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid OR u.id = :uid2');
} }
public function testComplexAndWhereOrWhereNesting() public function testComplexAndWhereOrWhereNesting()
@ -187,7 +187,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->orWhere('u.name = :name1', 'u.name = :name2') ->orWhere('u.name = :name1', 'u.name = :name2')
->andWhere('u.name <> :noname'); ->andWhere('u.name <> :noname');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE ((((u.id = :uid) OR (u.id = :uid2)) AND (u.id = :uid3)) OR (u.name = :name1) OR (u.name = :name2)) AND (u.name <> :noname)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (((u.id = :uid OR u.id = :uid2) AND u.id = :uid3) OR u.name = :name1 OR u.name = :name2) AND u.name <> :noname');
} }
public function testAndWhereIn() public function testAndWhereIn()
@ -198,7 +198,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->andWhere($qb->expr()->in('u.id', array(1, 2, 3))); ->andWhere($qb->expr()->in('u.id', array(1, 2, 3)));
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) AND (u.id IN(1, 2, 3))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid AND u.id IN(1, 2, 3)');
} }
public function testOrWhereIn() public function testOrWhereIn()
@ -209,7 +209,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->orWhere($qb->expr()->in('u.id', array(1, 2, 3))); ->orWhere($qb->expr()->in('u.id', array(1, 2, 3)));
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) OR (u.id IN(1, 2, 3))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid OR u.id IN(1, 2, 3)');
} }
public function testAndWhereNotIn() public function testAndWhereNotIn()
@ -220,7 +220,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->andWhere($qb->expr()->notIn('u.id', array(1, 2, 3))); ->andWhere($qb->expr()->notIn('u.id', array(1, 2, 3)));
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) AND (u.id NOT IN(1, 2, 3))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid AND u.id NOT IN(1, 2, 3)');
} }
public function testOrWhereNotIn() public function testOrWhereNotIn()
@ -231,7 +231,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->where('u.id = :uid') ->where('u.id = :uid')
->orWhere($qb->expr()->notIn('u.id', array(1, 2, 3))); ->orWhere($qb->expr()->notIn('u.id', array(1, 2, 3)));
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) OR (u.id NOT IN(1, 2, 3))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid OR u.id NOT IN(1, 2, 3)');
} }
public function testGroupBy() public function testGroupBy()
@ -265,7 +265,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->having('COUNT(u.id) > 1') ->having('COUNT(u.id) > 1')
->andHaving('COUNT(u.id) < 1'); ->andHaving('COUNT(u.id) < 1');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id HAVING (COUNT(u.id) > 1) AND (COUNT(u.id) < 1)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id HAVING COUNT(u.id) > 1 AND COUNT(u.id) < 1');
} }
public function testOrHaving() public function testOrHaving()
@ -278,7 +278,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->andHaving('COUNT(u.id) < 1') ->andHaving('COUNT(u.id) < 1')
->orHaving('COUNT(u.id) > 1'); ->orHaving('COUNT(u.id) > 1');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id HAVING ((COUNT(u.id) > 1) AND (COUNT(u.id) < 1)) OR (COUNT(u.id) > 1)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u GROUP BY u.id HAVING (COUNT(u.id) > 1 AND COUNT(u.id) < 1) OR COUNT(u.id) > 1');
} }
public function testOrderBy() public function testOrderBy()
@ -375,7 +375,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where('u.id = :uid', 'u.id = :uid2'); ->where('u.id = :uid', 'u.id = :uid2');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) AND (u.id = :uid2)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid AND u.id = :uid2');
} }
public function testMultipleAndWhere() public function testMultipleAndWhere()
@ -385,7 +385,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->andWhere('u.id = :uid', 'u.id = :uid2'); ->andWhere('u.id = :uid', 'u.id = :uid2');
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) AND (u.id = :uid2)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid AND u.id = :uid2');
} }
public function testMultipleOrWhere() public function testMultipleOrWhere()
@ -395,7 +395,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->orWhere('u.id = :uid', $qb->expr()->eq('u.id', ':uid2')); ->orWhere('u.id = :uid', $qb->expr()->eq('u.id', ':uid2'));
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid) OR (u.id = :uid2)'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid OR u.id = :uid2');
} }
public function testComplexWhere() public function testComplexWhere()
@ -409,7 +409,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where($orExpr); ->where($orExpr);
$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 testWhereInWithStringLiterals() public function testWhereInWithStringLiterals()
@ -453,7 +453,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
->from('Doctrine\Tests\Models\CMS\CmsUser', 'u') ->from('Doctrine\Tests\Models\CMS\CmsUser', 'u')
->where($orExpr); ->where($orExpr);
$this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.id = :uid3) OR (NOT(u.id IN(1)))'); $this->assertValidQueryBuilder($qb, 'SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = :uid3 OR NOT(u.id IN(1))');
} }
public function testSomeAllAny() public function testSomeAllAny()
@ -490,7 +490,7 @@ class QueryBuilderTest extends \Doctrine\Tests\OrmTestCase
$q2 = $qb->getQuery(); $q2 = $qb->getQuery();
$this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE (u.name = :name) AND (u.id = :id)', $q2->getDql()); $this->assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.name = :name AND u.id = :id', $q2->getDql());
$this->assertTrue($q1 !== $q2); // two different, independent queries $this->assertTrue($q1 !== $q2); // two different, independent queries
$this->assertEquals(2, count($q2->getParameters())); $this->assertEquals(2, count($q2->getParameters()));
$this->assertEquals(1, count($q1->getParameters())); // $q1 unaffected $this->assertEquals(1, count($q1->getParameters())); // $q1 unaffected