From 84a7fb7973e67b1cff0bd1bf60a5d8ba42040de5 Mon Sep 17 00:00:00 2001 From: zYne Date: Sat, 27 Jan 2007 10:28:25 +0000 Subject: [PATCH] Fixed DQL subquery handling --- lib/Doctrine/Query.php | 44 ++++++++++++++++++++++++++++---- lib/Doctrine/Query/Where.php | 4 ++- tests/Query/SubqueryTestCase.php | 5 +++- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/Doctrine/Query.php b/lib/Doctrine/Query.php index adb615877..385f022ce 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -59,6 +59,11 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { * @param boolean $limitSubqueryUsed */ private $limitSubqueryUsed = false; + /** + * @param boolean $isSubquery whether or not this query object is a subquery of another + * query object + */ + private $isSubquery; private $tableStack; @@ -88,7 +93,28 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { { return new Doctrine_Query(); } + /** + * isSubquery + * if $bool parameter is set this method sets the value of + * Doctrine_Query::$isSubquery. If this value is set to true + * the query object will not load the primary key fields of the selected + * components. + * + * If null is given as the first parameter this method retrieves the current + * value of Doctrine_Query::$isSubquery. + * + * @param boolean $bool whether or not this query acts as a subquery + * @return Doctrine_Query|bool + */ + public function isSubquery($bool = null) + { + if ($bool === null) { + return $this->isSubquery; + } + $this->isSubquery = (bool) $bool; + return $this; + } public function getTableStack() { return $this->tableStack; @@ -119,10 +145,15 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { if (isset($this->pendingFields[$componentAlias])) { $fields = $this->pendingFields[$componentAlias]; - if(in_array('*', $fields)) + if(in_array('*', $fields)) { $fields = $table->getColumnNames(); - else - $fields = array_unique(array_merge($table->getPrimaryKeys(), $fields)); + } else { + // only auto-add the primary key fields if this query object is not + // a subquery of another query object + if ( ! $this->isSubquery) { + $fields = array_unique(array_merge($table->getPrimaryKeys(), $fields)); + } + } } foreach ($fields as $name) { $name = $table->getColumnName($name); @@ -296,10 +327,13 @@ class Doctrine_Query extends Doctrine_Hydrate implements Countable { case Doctrine::FETCH_OFFSET: $this->limit = $table->getAttribute(Doctrine::ATTR_COLL_LIMIT); case Doctrine::FETCH_IMMEDIATE: - if( ! empty($names)) + if( ! empty($names)) { + // only auto-add the primary key fields if this query object is not + // a subquery of another query object $names = array_unique(array_merge($table->getPrimaryKeys(), $names)); - else + } else { $names = $table->getColumnNames(); + } break; case Doctrine::FETCH_LAZY_OFFSET: $this->limit = $table->getAttribute(Doctrine::ATTR_COLL_LIMIT); diff --git a/lib/Doctrine/Query/Where.php b/lib/Doctrine/Query/Where.php index d6894d52a..02c1fa932 100644 --- a/lib/Doctrine/Query/Where.php +++ b/lib/Doctrine/Query/Where.php @@ -132,9 +132,11 @@ class Doctrine_Query_Where extends Doctrine_Query_Condition $trimmed = Doctrine_Query::bracketTrim($value); if (substr($trimmed, 0, 4) == 'FROM' || substr($trimmed, 0, 6) == 'SELECT') { + // subquery found $q = new Doctrine_Query(); - $value = '(' . $q->parseQuery($trimmed)->getQuery() . ')'; + $value = '(' . $q->isSubquery(true)->parseQuery($trimmed)->getQuery() . ')'; + } elseif (substr($trimmed, 0, 4) == 'SQL:') { $value = '(' . substr($trimmed, 4) . ')'; } else { diff --git a/tests/Query/SubqueryTestCase.php b/tests/Query/SubqueryTestCase.php index 7f48c2510..ffd295f99 100644 --- a/tests/Query/SubqueryTestCase.php +++ b/tests/Query/SubqueryTestCase.php @@ -48,7 +48,10 @@ class Doctrine_Query_Subquery_TestCase extends Doctrine_UnitTestCase } public function testSubqueryAllowsSelectingOfAnyField() { - + $q = new Doctrine_Query(); + $q->from('User u')->where('u.id NOT IN (SELECT g.user_id FROM Groupuser g)'); + + $this->assertEqual($q->getQuery(), "SELECT e.id AS e__id, e.name AS e__name, e.loginname AS e__loginname, e.password AS e__password, e.type AS e__type, e.created AS e__created, e.updated AS e__updated, e.email_id AS e__email_id FROM entity e WHERE e.id NOT IN (SELECT g.user_id AS g__user_id FROM groupuser g) AND (e.type = 0)"); } } ?>