1
0
mirror of synced 2024-12-13 14:56:01 +03:00
This commit is contained in:
zYne 2007-05-15 20:29:33 +00:00
parent 4289bdd9ab
commit 6a7130be55
3 changed files with 162 additions and 86 deletions

View File

@ -477,10 +477,11 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
$needsSubQuery = false;
$subquery = '';
$k = array_keys($this->_aliasMap);
$table = $this->_aliasMap[$k[0]]['table'];
$map = reset($this->_aliasMap);
$table = $map['table'];
$rootAlias = key($this->_aliasMap);
if( ! empty($this->parts['limit']) && $this->needsSubquery && $table->getAttribute(Doctrine::ATTR_QUERY_LIMIT) == Doctrine::LIMIT_RECORDS) {
if ( ! empty($this->parts['limit']) && $this->needsSubquery && $table->getAttribute(Doctrine::ATTR_QUERY_LIMIT) == Doctrine::LIMIT_RECORDS) {
$needsSubQuery = true;
$this->limitSubqueryUsed = true;
}
@ -491,7 +492,7 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
// build the basic query
$str = '';
if($this->isDistinct()) {
if ($this->isDistinct()) {
$str = 'DISTINCT ';
}
@ -512,26 +513,26 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
$modifyLimit = true;
if ( ! empty($this->parts["limit"]) || ! empty($this->parts["offset"])) {
if($needsSubQuery) {
if ($needsSubQuery) {
$subquery = $this->getLimitSubquery();
switch(strtolower($this->conn->getName())) {
switch (strtolower($this->conn->getName())) {
case 'mysql':
// mysql doesn't support LIMIT in subqueries
$list = $this->conn->execute($subquery, $params)->fetchAll(PDO::FETCH_COLUMN);
$subquery = implode(', ', $list);
break;
break;
case 'pgsql':
// pgsql needs special nested LIMIT subquery
$subquery = 'SELECT doctrine_subquery_alias.' . $table->getIdentifier(). ' FROM (' . $subquery . ') AS doctrine_subquery_alias';
break;
break;
}
$field = $this->aliasHandler->getShortAlias($table->getTableName()) . '.' . $table->getIdentifier();
$field = $this->aliasHandler->getShortAlias($rootAlias) . '.' . $table->getIdentifier();
// only append the subquery if it actually contains something
if($subquery !== '') {
if ($subquery !== '') {
array_unshift($this->parts['where'], $field. ' IN (' . $subquery . ')');
}
@ -569,11 +570,12 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
*/
public function getLimitSubquery()
{
$k = array_keys($this->tables);
$table = $this->tables[$k[0]];
$map = reset($this->_aliasMap);
$table = $map['table'];
$componentAlias = key($this->_aliasMap);
// get short alias
$alias = $this->aliasHandler->getShortAlias($table->getTableName());
$alias = $this->aliasHandler->getShortAlias($componentAlias);
$primaryKey = $alias . '.' . $table->getIdentifier();
// initialize the base of the subquery
@ -592,23 +594,20 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
}
}
$subquery .= ' FROM ' . $this->conn->quoteIdentifier($table->getTableName()) . ' ' . $alias;
$subquery .= ' FROM';
foreach ($this->parts['join'] as $parts) {
foreach ($parts as $part) {
// preserve LEFT JOINs only if needed
if (substr($part,0,9) === 'LEFT JOIN') {
$e = explode(' ', $part);
if ( ! in_array($e[3], $this->subqueryAliases) &&
! in_array($e[2], $this->subqueryAliases)) {
continue;
}
foreach ($this->parts['from'] as $part) {
// preserve LEFT JOINs only if needed
if (substr($part,0,9) === 'LEFT JOIN') {
$e = explode(' ', $part);
if ( ! in_array($e[3], $this->subqueryAliases) &&
! in_array($e[2], $this->subqueryAliases)) {
continue;
}
$subquery .= ' ' . $part;
}
$subquery .= ' ' . $part;
}
// all conditions must be preserved in subquery

View File

@ -1,11 +1,45 @@
<?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.phpdoctrine.com>.
*/
/**
* Doctrine_Query_IdentifierQuoting_TestCase
*
* This test case is used for testing DQL API quotes all identifiers properly
* if idenfitier quoting is turned on
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class Doctrine_Query_IdentifierQuoting_TestCase extends Doctrine_UnitTestCase {
public function prepareTables() { }
public function prepareData() { }
public function testQuerySupportsIdentifierQuoting() {
$this->connection->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true);
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->parseQuery('SELECT MAX(u.id), MIN(u.name) FROM User u');
@ -13,17 +47,15 @@ class Doctrine_Query_IdentifierQuoting_TestCase extends Doctrine_UnitTestCase {
}
public function testQuerySupportsIdentifierQuotingWithJoins() {
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->parseQuery('SELECT u.name FROM User u LEFT JOIN u.Phonenumber p');
$this->assertEqual($q->getQuery(), 'SELECT e.id AS e__id, e.name AS e__name FROM "entity" e LEFT JOIN "phonenumber" p ON e.id = p.entity_id WHERE (e.type = 0)');
}
public function testLimitSubqueryAlgorithmSupportsIdentifierQuoting() {
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->parseQuery('SELECT u.name FROM User u INNER JOIN u.Phonenumber p')->limit(5);

View File

@ -1,6 +1,41 @@
<?php
class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
public function prepareTables() {
/*
* $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.phpdoctrine.com>.
*/
/**
* Doctrine_Query_Limit_TestCase
*
* This test case is used for testing DQL LIMIT clause
*
* @package Doctrine
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @category Object Relational Mapping
* @link www.phpdoctrine.com
* @since 1.0
* @version $Revision$
*/
class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase
{
public function prepareTables()
{
$this->tables[] = "Photo";
$this->tables[] = "Tag";
$this->tables[] = "Phototag";
@ -8,8 +43,9 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
parent::prepareTables();
}
public function testLimitWithOneToOneLeftJoin() {
$q = new Doctrine_Query($this->connection);
public function testLimitWithOneToOneLeftJoin()
{
$q = new Doctrine_Query2();
$q->select('u.id, e.*')->from('User u, u.Email e')->limit(5);
$users = $q->execute();
@ -17,22 +53,25 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($q->getQuery(), "SELECT e.id AS e__id, e2.id AS e2__id, e2.address AS e2__address FROM entity e LEFT JOIN email e2 ON e.email_id = e2.id WHERE (e.type = 0) LIMIT 5");
}
public function testLimitWithOneToOneInnerJoin() {
$q = new Doctrine_Query($this->connection);
public function testLimitWithOneToOneInnerJoin()
{
$q = new Doctrine_Query2();
$q->select('u.id, e.*')->from('User u, u:Email e')->limit(5);
$users = $q->execute();
$this->assertEqual($users->count(), 5);
$this->assertEqual($q->getQuery(), "SELECT e.id AS e__id, e2.id AS e2__id, e2.address AS e2__address FROM entity e INNER JOIN email e2 ON e.email_id = e2.id WHERE (e.type = 0) LIMIT 5");
}
public function testLimitWithOneToManyLeftJoin() {
$this->query->select('u.id, p.*')->from('User u, u.Phonenumber p')->limit(5);
public function testLimitWithOneToManyLeftJoin()
{
$q = new Doctrine_Query2();
$q->select('u.id, p.*')->from('User u, u.Phonenumber p')->limit(5);
$sql = $this->query->getQuery();
$this->assertEqual($this->query->getQuery(),
$sql = $q->getQuery();
$this->assertEqual($q->getQuery(),
'SELECT e.id AS e__id, p.id AS p__id, p.phonenumber AS p__phonenumber, p.entity_id AS p__entity_id FROM entity e LEFT JOIN phonenumber p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM entity e2 WHERE (e2.type = 0) LIMIT 5) AND (e.type = 0)');
$users = $this->query->execute();
$users = $q->execute();
$count = $this->dbh->count();
$this->assertEqual($users->count(), 5);
$users[0]->Phonenumber[0];
@ -41,18 +80,19 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->query->offset(2);
$q->offset(2);
$users = $this->query->execute();
$users = $q->execute();
$count = $this->dbh->count();
$this->assertEqual($users->count(), 5);
$users[3]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count());
}
public function testLimitWithOneToManyLeftJoinAndCondition() {
$q = new Doctrine_Query($this->connection);
$q->from("User(name)")->where("User.Phonenumber.phonenumber LIKE '%123%'")->limit(5);
public function testLimitWithOneToManyLeftJoinAndCondition()
{
$q = new Doctrine_Query2();
$q->select('User.name')->from('User')->where("User.Phonenumber.phonenumber LIKE '%123%'")->limit(5);
$users = $q->execute();
@ -69,9 +109,10 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
}
public function testLimitWithOneToManyLeftJoinAndOrderBy() {
$q = new Doctrine_Query($this->connection);
$q->from("User(name)")->where("User.Phonenumber.phonenumber LIKE '%123%'")->orderby("User.Email.address")->limit(5);
public function testLimitWithOneToManyLeftJoinAndOrderBy()
{
$q = new Doctrine_Query2();
$q->select('User.name')->from('User')->where("User.Phonenumber.phonenumber LIKE '%123%'")->orderby('User.Email.address')->limit(5);
$users = $q->execute();
@ -85,36 +126,39 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($users->count(), 5);
}
public function testLimitWithOneToManyInnerJoin() {
$this->query->select('u.id, p.*')->from('User u INNER JOIN u.Phonenumber p');
$this->query->limit(5);
public function testLimitWithOneToManyInnerJoin()
{
$q = new Doctrine_Query2();
$q->select('u.id, p.*')->from('User u INNER JOIN u.Phonenumber p');
$q->limit(5);
$sql = $this->query->getQuery();
$sql = $q->getQuery();
$users = $this->query->execute();
$users = $q->execute();
$count = $this->dbh->count();
$this->assertEqual($users->count(), 5);
$users[0]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count());
$this->query->offset(2);
$q->offset(2);
$users = $this->query->execute();
$users = $q->execute();
$count = $this->dbh->count();
$this->assertEqual($users->count(), 5);
$users[3]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count());
$this->assertEqual($this->query->getQuery(),
$this->assertEqual($q->getQuery(),
'SELECT e.id AS e__id, p.id AS p__id, p.phonenumber AS p__phonenumber, p.entity_id AS p__entity_id FROM entity e INNER JOIN phonenumber p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM entity e2 INNER JOIN phonenumber p2 ON e2.id = p2.entity_id WHERE (e2.type = 0) LIMIT 5 OFFSET 2) AND (e.type = 0)');
}
public function testLimitWithPreparedQueries() {
$q = new Doctrine_Query();
public function testLimitWithPreparedQueries()
{
$q = new Doctrine_Query2();
$q->select('u.id, p.id')->from('User u LEFT JOIN u.Phonenumber p');
$q->where("u.name = ?");
$q->where('u.name = ?');
$q->limit(5);
$users = $q->execute(array('zYne'));
@ -126,10 +170,11 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($q->getQuery(),
'SELECT e.id AS e__id, p.id AS p__id FROM entity e LEFT JOIN phonenumber p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM entity e2 WHERE e2.name = ? AND (e2.type = 0) LIMIT 5) AND e.name = ? AND (e.type = 0)');
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->select('u.id, p.id')->from('User u LEFT JOIN u.Phonenumber p');
$q->where("User.name LIKE ? || User.name LIKE ?");
$q->where("u.name LIKE ? || u.name LIKE ?");
$q->limit(5);
$users = $q->execute(array('%zYne%', '%Arnold%'));
$this->assertEqual($users->count(), 2);
@ -140,26 +185,23 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($q->getQuery(),
"SELECT e.id AS e__id, p.id AS p__id FROM entity e LEFT JOIN phonenumber p ON e.id = p.entity_id WHERE e.id IN (SELECT DISTINCT e2.id FROM entity e2 WHERE (e2.name LIKE ? OR e2.name LIKE ?) AND (e2.type = 0) LIMIT 5) AND (e.name LIKE ? OR e.name LIKE ?) AND (e.type = 0)");
}
public function testConnectionFlushing() {
$q = new Doctrine_Query();
$q->from("User(id).Phonenumber(id)");
$q->where("User.name = ?");
public function testConnectionFlushing()
{
$q = new Doctrine_Query2();
$q->from('User.Phonenumber');
$q->where('User.name = ?');
$q->limit(5);
print $q;
$users = $q->execute(array('zYne'));
$this->assertEqual($users->count(), 1);
$this->connection->flush();
}
public function testLimitWithManyToManyColumnAggInheritanceLeftJoin() {
$q = new Doctrine_Query($this->connection);
$q->from("User.Group")->limit(5);
public function testLimitWithManyToManyColumnAggInheritanceLeftJoin()
{
$q = new Doctrine_Query2();
$q->from('User.Group')->limit(5);
$users = $q->execute();
@ -185,7 +227,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->from("User")->where("User.Group.id = ?")->orderby("User.id ASC")->limit(5);
@ -201,11 +243,12 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($users->count(), 3);
}
public function testLimitAttribute() {
public function testLimitAttribute()
{
$this->manager->setAttribute(Doctrine::ATTR_QUERY_LIMIT, Doctrine::LIMIT_ROWS);
$this->connection->clear();
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->from("User")->where("User.Group.id = ?")->orderby("User.id DESC")->limit(5);
$users = $q->execute(array(3));
@ -215,12 +258,14 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->manager->setAttribute(Doctrine::ATTR_QUERY_LIMIT, Doctrine::LIMIT_RECORDS);
}
public function testLimitWithManyToManyAndColumnAggregationInheritance() {
$q = new Doctrine_Query();
public function testLimitWithManyToManyAndColumnAggregationInheritance()
{
$q = new Doctrine_Query2();
$q->from('User u, u.Group g')->where('g.id > 1')->orderby('u.name DESC')->limit(10);
}
public function testLimitWithNormalManyToMany() {
public function testLimitWithNormalManyToMany()
{
$coll = new Doctrine_Collection($this->connection->getTable("Photo"));
$tag = new Tag();
$tag->tag = "Some tag";
@ -234,7 +279,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$coll[3]->name = "photo 4";
$this->connection->flush();
$q = new Doctrine_Query();
$q = new Doctrine_Query2();
$q->from("Photo")->where("Photo.Tag.id = ?")->orderby("Photo.id DESC")->limit(100);
$photos = $q->execute(array(1));