1
0
mirror of synced 2024-12-13 22:56:04 +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,8 +477,9 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
$needsSubQuery = false; $needsSubQuery = false;
$subquery = ''; $subquery = '';
$k = array_keys($this->_aliasMap); $map = reset($this->_aliasMap);
$table = $this->_aliasMap[$k[0]]['table']; $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; $needsSubQuery = true;
@ -528,7 +529,7 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
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 // only append the subquery if it actually contains something
if ($subquery !== '') { if ($subquery !== '') {
@ -569,11 +570,12 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
*/ */
public function getLimitSubquery() public function getLimitSubquery()
{ {
$k = array_keys($this->tables); $map = reset($this->_aliasMap);
$table = $this->tables[$k[0]]; $table = $map['table'];
$componentAlias = key($this->_aliasMap);
// get short alias // get short alias
$alias = $this->aliasHandler->getShortAlias($table->getTableName()); $alias = $this->aliasHandler->getShortAlias($componentAlias);
$primaryKey = $alias . '.' . $table->getIdentifier(); $primaryKey = $alias . '.' . $table->getIdentifier();
// initialize the base of the subquery // initialize the base of the subquery
@ -592,10 +594,9 @@ 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 ($this->parts['from'] as $part) {
foreach ($parts as $part) {
// preserve LEFT JOINs only if needed // preserve LEFT JOINs only if needed
if (substr($part,0,9) === 'LEFT JOIN') { if (substr($part,0,9) === 'LEFT JOIN') {
$e = explode(' ', $part); $e = explode(' ', $part);
@ -604,12 +605,10 @@ class Doctrine_Query2 extends Doctrine_Hydrate2 implements Countable
! in_array($e[2], $this->subqueryAliases)) { ! in_array($e[2], $this->subqueryAliases)) {
continue; continue;
} }
} }
$subquery .= ' ' . $part; $subquery .= ' ' . $part;
} }
}
// all conditions must be preserved in subquery // all conditions must be preserved in subquery
$subquery .= ( ! empty($this->parts['where']))? ' WHERE ' . implode(' AND ', $this->parts['where']) : ''; $subquery .= ( ! empty($this->parts['where']))? ' WHERE ' . implode(' AND ', $this->parts['where']) : '';

View File

@ -1,11 +1,45 @@
<?php <?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 { class Doctrine_Query_IdentifierQuoting_TestCase extends Doctrine_UnitTestCase {
public function prepareTables() { } public function prepareTables() { }
public function prepareData() { } public function prepareData() { }
public function testQuerySupportsIdentifierQuoting() { public function testQuerySupportsIdentifierQuoting() {
$this->connection->setAttribute(Doctrine::ATTR_QUOTE_IDENTIFIER, true); $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'); $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() { public function testQuerySupportsIdentifierQuotingWithJoins() {
$q = new Doctrine_Query(); $q = new Doctrine_Query2();
$q->parseQuery('SELECT u.name FROM User u LEFT JOIN u.Phonenumber p'); $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)'); $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() { 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); $q->parseQuery('SELECT u.name FROM User u INNER JOIN u.Phonenumber p')->limit(5);

View File

@ -1,6 +1,41 @@
<?php <?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[] = "Photo";
$this->tables[] = "Tag"; $this->tables[] = "Tag";
$this->tables[] = "Phototag"; $this->tables[] = "Phototag";
@ -8,8 +43,9 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
parent::prepareTables(); parent::prepareTables();
} }
public function testLimitWithOneToOneLeftJoin() { public function testLimitWithOneToOneLeftJoin()
$q = new Doctrine_Query($this->connection); {
$q = new Doctrine_Query2();
$q->select('u.id, e.*')->from('User u, u.Email e')->limit(5); $q->select('u.id, e.*')->from('User u, u.Email e')->limit(5);
$users = $q->execute(); $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"); $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() { public function testLimitWithOneToOneInnerJoin()
$q = new Doctrine_Query($this->connection); {
$q = new Doctrine_Query2();
$q->select('u.id, e.*')->from('User u, u:Email e')->limit(5); $q->select('u.id, e.*')->from('User u, u:Email e')->limit(5);
$users = $q->execute(); $users = $q->execute();
$this->assertEqual($users->count(), 5); $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"); $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() { public function testLimitWithOneToManyLeftJoin()
$this->query->select('u.id, p.*')->from('User u, u.Phonenumber p')->limit(5); {
$q = new Doctrine_Query2();
$q->select('u.id, p.*')->from('User u, u.Phonenumber p')->limit(5);
$sql = $this->query->getQuery(); $sql = $q->getQuery();
$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 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)'); '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(); $count = $this->dbh->count();
$this->assertEqual($users->count(), 5); $this->assertEqual($users->count(), 5);
$users[0]->Phonenumber[0]; $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(); $count = $this->dbh->count();
$this->assertEqual($users->count(), 5); $this->assertEqual($users->count(), 5);
$users[3]->Phonenumber[0]; $users[3]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count()); $this->assertEqual($count, $this->dbh->count());
} }
public function testLimitWithOneToManyLeftJoinAndCondition() { public function testLimitWithOneToManyLeftJoinAndCondition()
$q = new Doctrine_Query($this->connection); {
$q->from("User(name)")->where("User.Phonenumber.phonenumber LIKE '%123%'")->limit(5); $q = new Doctrine_Query2();
$q->select('User.name')->from('User')->where("User.Phonenumber.phonenumber LIKE '%123%'")->limit(5);
$users = $q->execute(); $users = $q->execute();
@ -69,9 +109,10 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
} }
public function testLimitWithOneToManyLeftJoinAndOrderBy() { 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); $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(); $users = $q->execute();
@ -85,36 +126,39 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($users->count(), 5); $this->assertEqual($users->count(), 5);
} }
public function testLimitWithOneToManyInnerJoin() { public function testLimitWithOneToManyInnerJoin()
$this->query->select('u.id, p.*')->from('User u INNER JOIN u.Phonenumber p'); {
$this->query->limit(5); $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(); $count = $this->dbh->count();
$this->assertEqual($users->count(), 5); $this->assertEqual($users->count(), 5);
$users[0]->Phonenumber[0]; $users[0]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count()); $this->assertEqual($count, $this->dbh->count());
$this->query->offset(2); $q->offset(2);
$users = $this->query->execute(); $users = $q->execute();
$count = $this->dbh->count(); $count = $this->dbh->count();
$this->assertEqual($users->count(), 5); $this->assertEqual($users->count(), 5);
$users[3]->Phonenumber[0]; $users[3]->Phonenumber[0];
$this->assertEqual($count, $this->dbh->count()); $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)'); '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() { public function testLimitWithPreparedQueries()
$q = new Doctrine_Query(); {
$q = new Doctrine_Query2();
$q->select('u.id, p.id')->from('User u LEFT JOIN u.Phonenumber p'); $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); $q->limit(5);
$users = $q->execute(array('zYne')); $users = $q->execute(array('zYne'));
@ -126,10 +170,11 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($q->getQuery(), $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)'); '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->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); $q->limit(5);
$users = $q->execute(array('%zYne%', '%Arnold%')); $users = $q->execute(array('%zYne%', '%Arnold%'));
$this->assertEqual($users->count(), 2); $this->assertEqual($users->count(), 2);
@ -140,26 +185,23 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$this->assertEqual($q->getQuery(), $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)"); "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_Query2();
public function testConnectionFlushing() { $q->from('User.Phonenumber');
$q = new Doctrine_Query(); $q->where('User.name = ?');
$q->from("User(id).Phonenumber(id)");
$q->where("User.name = ?");
$q->limit(5); $q->limit(5);
print $q;
$users = $q->execute(array('zYne')); $users = $q->execute(array('zYne'));
$this->assertEqual($users->count(), 1); $this->assertEqual($users->count(), 1);
$this->connection->flush(); $this->connection->flush();
} }
public function testLimitWithManyToManyColumnAggInheritanceLeftJoin()
{
public function testLimitWithManyToManyColumnAggInheritanceLeftJoin() { $q = new Doctrine_Query2();
$q = new Doctrine_Query($this->connection); $q->from('User.Group')->limit(5);
$q->from("User.Group")->limit(5);
$users = $q->execute(); $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); $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); $this->assertEqual($users->count(), 3);
} }
public function testLimitAttribute() { public function testLimitAttribute()
{
$this->manager->setAttribute(Doctrine::ATTR_QUERY_LIMIT, Doctrine::LIMIT_ROWS); $this->manager->setAttribute(Doctrine::ATTR_QUERY_LIMIT, Doctrine::LIMIT_ROWS);
$this->connection->clear(); $this->connection->clear();
$q = new Doctrine_Query(); $q = new Doctrine_Query2();
$q->from("User")->where("User.Group.id = ?")->orderby("User.id DESC")->limit(5); $q->from("User")->where("User.Group.id = ?")->orderby("User.id DESC")->limit(5);
$users = $q->execute(array(3)); $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); $this->manager->setAttribute(Doctrine::ATTR_QUERY_LIMIT, Doctrine::LIMIT_RECORDS);
} }
public function testLimitWithManyToManyAndColumnAggregationInheritance() { public function testLimitWithManyToManyAndColumnAggregationInheritance()
$q = new Doctrine_Query(); {
$q = new Doctrine_Query2();
$q->from('User u, u.Group g')->where('g.id > 1')->orderby('u.name DESC')->limit(10); $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")); $coll = new Doctrine_Collection($this->connection->getTable("Photo"));
$tag = new Tag(); $tag = new Tag();
$tag->tag = "Some tag"; $tag->tag = "Some tag";
@ -234,7 +279,7 @@ class Doctrine_Query_Limit_TestCase extends Doctrine_UnitTestCase {
$coll[3]->name = "photo 4"; $coll[3]->name = "photo 4";
$this->connection->flush(); $this->connection->flush();
$q = new Doctrine_Query(); $q = new Doctrine_Query2();
$q->from("Photo")->where("Photo.Tag.id = ?")->orderby("Photo.id DESC")->limit(100); $q->from("Photo")->where("Photo.Tag.id = ?")->orderby("Photo.id DESC")->limit(100);
$photos = $q->execute(array(1)); $photos = $q->execute(array(1));