From 7ecc82fded2f671879e5a7901579254aec409147 Mon Sep 17 00:00:00 2001 From: zYne Date: Fri, 5 Oct 2007 21:18:40 +0000 Subject: [PATCH] removed deprecated attributes, added bound query part functionality, fixed remaining I18n issues --- lib/Doctrine.php | 21 +---- lib/Doctrine/Collection.php | 33 +++++--- lib/Doctrine/Configurable.php | 9 +- lib/Doctrine/I18n.php | 8 +- lib/Doctrine/Query.php | 22 +++-- lib/Doctrine/Table.php | 155 +++++++++++++++++++++------------- tests/I18nTestCase.php | 3 +- tests/QueryTestCase.php | 61 ++++++++++++- 8 files changed, 205 insertions(+), 107 deletions(-) diff --git a/lib/Doctrine.php b/lib/Doctrine.php index 83620521f..40bbdb9a9 100644 --- a/lib/Doctrine.php +++ b/lib/Doctrine.php @@ -169,27 +169,10 @@ final class Doctrine const ATTR_USE_NATIVE_ENUM = 117; const ATTR_DEFAULT_SEQUENCE = 133; - /** TODO: REMOVE THE FOLLOWING CONSTANTS AND UPDATE THE DOCS ! */ - - const ATTR_VLD = -1; - const ATTR_AUTO_LENGTH_VLD = -2; - const ATTR_AUTO_TYPE_VLD = -3; const ATTR_FETCHMODE = 118; - const ATTR_BATCH_SIZE = 119; - const ATTR_LOCKMODE = 120; const ATTR_NAME_PREFIX = 121; const ATTR_CREATE_TABLES = 122; const ATTR_COLL_LIMIT = 123; - const ATTR_ACCESSORS = 124; - const ATTR_ACCESSOR_PREFIX_GET = 125; - const ATTR_ACCESSOR_PREFIX_SET = 126; - - /** - * NESTED SET CONSTANTS - */ - const ATTR_NS_ROOT_COLUMN_NAME = 130; - const ATTR_NS_GAP_SIZE = 131; - const ATTR_NS_GAP_DECREASE_EXP = 132; const ATTR_CACHE = 150; const ATTR_CACHE_LIFESPAN = 151; @@ -512,7 +495,7 @@ final class Doctrine { $loadedModels = self::getLoadedModels(); - foreach ($loadedModels AS $name) { + foreach ($loadedModels as $name) { $model = new $name(); $table = $model->getTable(); @@ -669,4 +652,4 @@ final class Doctrine return true; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 24bdb3dcb..5ea30a391 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -72,7 +72,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator * * @param Doctrine_Table|string $table */ - public function __construct($table) + public function __construct($table, $keyColumn = null) { if ( ! ($table instanceof Doctrine_Table)) { $table = Doctrine_Manager::getInstance() @@ -80,9 +80,12 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator } $this->_table = $table; - $name = $table->getAttribute(Doctrine::ATTR_COLL_KEY); - if ($name !== null) { - $this->keyColumn = $name; + if ($keyColumn === null) { + $keyColumn = $table->getBoundQueryPart('indexBy'); + } + + if ($keyColumn !== null) { + $this->keyColumn = $keyColumn; } } /** @@ -152,12 +155,14 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $this->$name = $values; } - $this->_table = $connection->getTable($this->_table); + $this->_table = $connection->getTable($this->_table); + if ($keyColumn === null) { + $keyColumn = $table->getBoundQueryPart('indexBy'); + } - $name = $this->_table->getAttribute(Doctrine::ATTR_COLL_KEY); - if ($name !== null) { - $this->keyColumn = $name; + if ($keyColumn !== null) { + $this->keyColumn = $keyColumn; } } /** @@ -224,9 +229,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $this->reference = $record; $this->relation = $relation; - if ($relation instanceof Doctrine_Relation_ForeignKey - || $relation instanceof Doctrine_Relation_LocalKey - ) { + if ($relation instanceof Doctrine_Relation_ForeignKey || + $relation instanceof Doctrine_Relation_LocalKey) { $this->referenceField = $relation->getForeign(); @@ -318,6 +322,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $this->data[$key] = $record; } + if (isset($this->keyColumn)) { + + $record->set($this->keyColumn, $key); + } + return $record; } @@ -716,4 +725,4 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator { return Doctrine_Lib::getCollectionAsString($this); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Configurable.php b/lib/Doctrine/Configurable.php index baf3b7b36..cc309a73f 100644 --- a/lib/Doctrine/Configurable.php +++ b/lib/Doctrine/Configurable.php @@ -80,9 +80,6 @@ abstract class Doctrine_Configurable extends Doctrine_Object } switch ($attribute) { case Doctrine::ATTR_FETCHMODE: - case Doctrine::ATTR_COLL_LIMIT: - case Doctrine::ATTR_ACCESSOR_PREFIX_GET: - case Doctrine::ATTR_ACCESSOR_PREFIX_SET: throw new Doctrine_Exception('Deprecated attribute. See http://doctrine.pengus.net/doctrine/manual/new/?chapter=configuration'); case Doctrine::ATTR_LISTENER: $this->setEventListener($value); @@ -102,10 +99,6 @@ abstract class Doctrine_Configurable extends Doctrine_Object } } break; - case Doctrine::ATTR_VLD: - case Doctrine::ATTR_AUTO_LENGTH_VLD: - case Doctrine::ATTR_AUTO_TYPE_VLD: - throw new Doctrine_Exception('Deprecated attribute. See http://doctrine.pengus.net/doctrine/manual/new/?chapter=configuration#validation-attributes'); case Doctrine::ATTR_VALIDATE: case Doctrine::ATTR_QUERY_LIMIT: case Doctrine::ATTR_QUOTE_IDENTIFIER: @@ -348,4 +341,4 @@ abstract class Doctrine_Configurable extends Doctrine_Object { return $this->parent; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/I18n.php b/lib/Doctrine/I18n.php index 4e9f9c9e2..98ddbb2b5 100644 --- a/lib/Doctrine/I18n.php +++ b/lib/Doctrine/I18n.php @@ -83,6 +83,7 @@ class Doctrine_I18n extends Doctrine_Plugin foreach ($cols as $column => $definition) { if (in_array($column, $this->_options['fields'])) { $columns[$column] = $definition; + $table->removeColumn($column); } } @@ -101,7 +102,8 @@ class Doctrine_I18n extends Doctrine_Plugin $columns += $fk; - $options = array('className' => $this->_options['className']); + $options = array('className' => $this->_options['className'], + 'queryParts' => array('indexBy' => 'lang')); $builder = new Doctrine_Import_Builder(); @@ -111,7 +113,9 @@ class Doctrine_I18n extends Doctrine_Plugin eval($def); } $this->_options['pluginTable'] = $table->getConnection()->getTable($this->_options['className']); + + $this->_options['pluginTable']->bindQueryPart('indexBy', 'lang'); return true; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Query.php b/lib/Doctrine/Query.php index eb5ccb630..480488996 100644 --- a/lib/Doctrine/Query.php +++ b/lib/Doctrine/Query.php @@ -1503,15 +1503,27 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable } $parent = $prevPath; } + + $table = $this->_aliasMap[$componentAlias]['table']; + + $indexBy = null; + if (isset($mapWith)) { $e = explode('.', $mapWith); - $table = $this->_aliasMap[$componentAlias]['table']; - if ( ! $table->hasColumn($e[1])) { - throw new Doctrine_Query_Exception("Couldn't use key mapping. Column " . $e[1] . " does not exist."); + if (isset($e[1])) { + $indexBy = $e[1]; } + } elseif ($table->getBoundQueryPart('indexBy') !== null) { + $indexBy = $table->getBoundQueryPart('indexBy'); + } - $this->_aliasMap[$componentAlias]['map'] = $table->getColumnName($e[1]); + if ($indexBy !== null) { + if ( ! $table->hasColumn($indexBy)) { + throw new Doctrine_Query_Exception("Couldn't use key mapping. Column " . $indexBy . " does not exist."); + } + + $this->_aliasMap[$componentAlias]['map'] = $table->getColumnName($indexBy); } return $this->_aliasMap[$componentAlias]; } @@ -1677,4 +1689,4 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable $this->_dqlParts = array(); $this->_enumParams = array(); } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php index dd54964da..4337f03dd 100644 --- a/lib/Doctrine/Table.php +++ b/lib/Doctrine/Table.php @@ -127,22 +127,25 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable * * -- treeOptions the tree options * + * -- queryParts the bound query parts + * * -- versioning */ - protected $options = array('name' => null, - 'tableName' => null, - 'sequenceName' => null, - 'inheritanceMap' => array(), - 'enumMap' => array(), - 'type' => null, - 'charset' => null, - 'collation' => null, - 'treeImpl' => null, - 'treeOptions' => null, - 'indexes' => array(), - 'parents' => array(), - 'versioning' => null, - ); + protected $_options = array('name' => null, + 'tableName' => null, + 'sequenceName' => null, + 'inheritanceMap' => array(), + 'enumMap' => array(), + 'type' => null, + 'charset' => null, + 'collation' => null, + 'treeImpl' => null, + 'treeOptions' => null, + 'indexes' => array(), + 'parents' => array(), + 'queryParts' => array(), + 'versioning' => null, + ); /** * @var Doctrine_Tree $tree tree object associated with this table */ @@ -159,8 +162,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable * @var array $_filters an array containing all record filters attached to this table */ protected $_filters = array(); - - protected $_queryParts = array(); @@ -176,7 +177,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable $this->setParent($this->_conn); - $this->options['name'] = $name; + $this->_options['name'] = $name; $this->_parser = new Doctrine_Relation_Parser($this); if ( ! class_exists($name) || empty($name)) { @@ -203,18 +204,18 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable $names = array_reverse($names); // save parents array_pop($names); - $this->options['parents'] = $names; + $this->_options['parents'] = $names; // create database table if (method_exists($record, 'setTableDefinition')) { $record->setTableDefinition(); // get the declaring class of setTableDefinition method - $method = new ReflectionMethod($this->options['name'], 'setTableDefinition'); + $method = new ReflectionMethod($this->_options['name'], 'setTableDefinition'); $class = $method->getDeclaringClass(); } else { $class = new ReflectionClass($class); } - $this->options['declaringClass'] = $class; + $this->_options['declaringClass'] = $class; // set the table definition for the given tree implementation if ($this->isTree()) { @@ -223,8 +224,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable $this->columnCount = count($this->_columns); - if ( ! isset($this->options['tableName'])) { - $this->options['tableName'] = Doctrine::tableize($class->getName()); + if ( ! isset($this->_options['tableName'])) { + $this->_options['tableName'] = Doctrine::tableize($class->getName()); } switch (count($this->_identifier)) { @@ -262,12 +263,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable $found = true; if ($value) { - $this->options['sequenceName'] = $value; + $this->_options['sequenceName'] = $value; } else { if (($sequence = $this->getAttribute(Doctrine::ATTR_DEFAULT_SEQUENCE)) !== null) { - $this->options['sequenceName'] = $sequence; + $this->_options['sequenceName'] = $sequence; } else { - $this->options['sequenceName'] = $this->_conn->getSequenceName($this->options['tableName']); + $this->_options['sequenceName'] = $this->_conn->getSequenceName($this->_options['tableName']); } } break; @@ -415,8 +416,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable try { $this->_conn->beginTransaction(); - foreach ($this->options['index'] as $index => $definition) { - $this->_conn->export->createIndex($this->options['tableName'], $index, $definition); + foreach ($this->_options['index'] as $index => $definition) { + $this->_conn->export->createIndex($this->_options['tableName'], $index, $definition); } $this->_conn->commit(); } catch(Doctrine_Connection_Exception $e) { @@ -443,8 +444,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function __get($option) { - if (isset($this->options[$option])) { - return $this->options[$option]; + if (isset($this->_options[$option])) { + return $this->_options[$option]; } return null; } @@ -455,7 +456,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function __isset($option) { - return isset($this->options[$option]); + return isset($this->_options[$option]); } /** * getOptions @@ -465,7 +466,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function getOptions() { - return $this->options; + return $this->_options; } /** * addForeignKey @@ -476,7 +477,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function addForeignKey(array $definition) { - $this->options['foreignKeys'][] = $definition; + $this->_options['foreignKeys'][] = $definition; } /** * addCheckConstraint @@ -488,9 +489,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable public function addCheckConstraint($definition, $name) { if (is_string($name)) { - $this->options['checks'][$name] = $definition; + $this->_options['checks'][$name] = $definition; } else { - $this->options['checks'][] = $definition; + $this->_options['checks'][] = $definition; } return $this; @@ -504,7 +505,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function addIndex($index, array $definition) { - $this->options['indexes'][$index] = $definition; + $this->_options['indexes'][$index] = $definition; } /** * getIndex @@ -513,8 +514,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function getIndex($index) { - if (isset($this->options['indexes'][$index])) { - return $this->options['indexes'][$index]; + if (isset($this->_options['indexes'][$index])) { + return $this->_options['indexes'][$index]; } return false; @@ -536,7 +537,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable $args[2] = (array) $args[2]; } - $classes = array_merge($this->options['parents'], array($this->getComponentName())); + $classes = array_merge($this->_options['parents'], array($this->getComponentName())); $e = explode('.', $args[1]); @@ -644,7 +645,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable } break; } - $this->options[$name] = $value; + $this->_options[$name] = $value; } /** * getOption @@ -655,8 +656,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function getOption($name) { - if (isset($this->options[$name])) { - return $this->options[$name]; + if (isset($this->_options[$name])) { + return $this->_options[$name]; } return null; } @@ -820,7 +821,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function create(array $array = array()) { $this->_data = $array; - $record = new $this->options['name']($this, true); + $record = new $this->_options['name']($this, true); $this->_data = array(); return $record; } @@ -975,10 +976,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function getClassnameToReturn() { - if ( ! isset($this->options['subclasses'])) { - return $this->options['name']; + if ( ! isset($this->_options['subclasses'])) { + return $this->_options['name']; } - foreach ($this->options['subclasses'] as $subclass) { + foreach ($this->_options['subclasses'] as $subclass) { $table = $this->_conn->getTable($subclass); $inheritanceMap = $table->getOption('inheritanceMap'); $nomatch = false; @@ -992,7 +993,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable return $table->getComponentName(); } } - return $this->options['name']; + return $this->_options['name']; } /** @@ -1007,7 +1008,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable . ' WHERE ' . implode(' = ? && ', (array) $this->_identifier) . ' = ?'; $query = $this->applyInheritance($query); - $params = array_merge(array($id), array_values($this->options['inheritanceMap'])); + $params = array_merge(array($id), array_values($this->_options['inheritanceMap'])); $this->_data = $this->_conn->execute($query, $params)->fetch(PDO::FETCH_ASSOC); @@ -1023,9 +1024,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ final public function applyInheritance($where) { - if ( ! empty($this->options['inheritanceMap'])) { + if ( ! empty($this->_options['inheritanceMap'])) { $a = array(); - foreach ($this->options['inheritanceMap'] as $field => $value) { + foreach ($this->_options['inheritanceMap'] as $field => $value) { $a[] = $field . ' = ?'; } $i = implode(' AND ', $a); @@ -1040,7 +1041,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function count() { - $a = $this->_conn->execute('SELECT COUNT(1) FROM ' . $this->options['tableName'])->fetch(Doctrine::FETCH_NUM); + $a = $this->_conn->execute('SELECT COUNT(1) FROM ' . $this->_options['tableName'])->fetch(Doctrine::FETCH_NUM); return current($a); } /** @@ -1120,6 +1121,22 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { return $this->_columns; } + /** + * removeColumn + * removes given column + * + * @return boolean + */ + public function removeColumn($column) + { + if (isset($this->_columns[$column])) { + unset($this->_columns[$column]); + + return true; + } + + return false; + } /** * returns an array containing all the column names * @@ -1246,11 +1263,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable * @return mixed if tree return instance of Doctrine_Tree, otherwise returns false */ public function getTree() { - if (isset($this->options['treeImpl'])) { + if (isset($this->_options['treeImpl'])) { if ( ! $this->_tree) { - $options = isset($this->options['treeOptions']) ? $this->options['treeOptions'] : array(); + $options = isset($this->_options['treeOptions']) ? $this->_options['treeOptions'] : array(); $this->_tree = Doctrine_Tree::factory($this, - $this->options['treeImpl'], + $this->_options['treeImpl'], $options ); } @@ -1260,15 +1277,15 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable } public function getComponentName() { - return $this->options['name']; + return $this->_options['name']; } public function getTableName() { - return $this->options['tableName']; + return $this->_options['tableName']; } public function setTableName($tableName) { - $this->options['tableName'] = $tableName; + $this->_options['tableName'] = $tableName; } /** * determine if table acts as tree @@ -1276,7 +1293,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable * @return mixed if tree return true, otherwise returns false */ public function isTree() { - return ( ! is_null($this->options['treeImpl'])) ? true : false; + return ( ! is_null($this->_options['treeImpl'])) ? true : false; } public function getTemplate($template) @@ -1303,10 +1320,32 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable */ public function bindQueryParts(array $queryParts) { - $this->_queryParts = $queryParts; + $this->_options['queryParts'] = $queryParts; return $this; } + /** + * bindQueryPart + * binds given value to given query part + * + * @param string $queryPart + * @param mixed $value + * @return Doctrine_Record this object + */ + public function bindQueryPart($queryPart, $value) + { + $this->_options['queryParts'][$queryPart] = $value; + + return $this; + } + public function getBoundQueryPart($queryPart) + { + if ( ! isset($this->_options['queryParts'][$queryPart])) { + return null; + } + + return $this->_options['queryParts'][$queryPart]; + } public function unshiftFilter(Doctrine_Record_Filter $filter) { $filter->setTable($this); diff --git a/tests/I18nTestCase.php b/tests/I18nTestCase.php index 08af055b4..769755ff7 100644 --- a/tests/I18nTestCase.php +++ b/tests/I18nTestCase.php @@ -71,6 +71,7 @@ class Doctrine_I18n_TestCase extends Doctrine_UnitTestCase public function testTranslationTableIsInitializedProperly() { $i = new I18nTest(); + $i->id = 1; $i->Translation['EN']->name = 'some name'; $i->Translation['EN']->title = 'some title'; @@ -96,7 +97,7 @@ class Doctrine_I18n_TestCase extends Doctrine_UnitTestCase public function testDataFetching() { $i = Doctrine_Query::create()->from('I18nTest i')->innerJoin('i.Translation t INDEXBY t.lang')->orderby('t.lang')->fetchOne(array(), Doctrine::HYDRATE_ARRAY); - print_r($i); + $this->assertEqual($i['Translation']['EN']['name'], 'some name'); $this->assertEqual($i['Translation']['EN']['title'], 'some title'); $this->assertEqual($i['Translation']['EN']['lang'], 'EN'); diff --git a/tests/QueryTestCase.php b/tests/QueryTestCase.php index 6aed7b45a..fef9b017a 100644 --- a/tests/QueryTestCase.php +++ b/tests/QueryTestCase.php @@ -32,18 +32,75 @@ */ class Doctrine_Query_TestCase extends Doctrine_UnitTestCase { + public function testGetQueryHookResetsTheManuallyAddedDqlParts() { $q = new MyQuery(); - + $q->from('User u'); $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 = 4 AND (e.type = 0)'); - + // test consequent calls $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 = 4 AND (e.type = 0)'); } + + public function testParseClauseSupportsArithmeticOperators() + { + $q = new Doctrine_Query(); + + $str = $q->parseClause('2 + 3'); + + $this->assertEqual($str, '2 + 3'); + + $str = $q->parseClause('2 + 3 - 5 * 6'); + + $this->assertEqual($str, '2 + 3 - 5 * 6'); + } + public function testParseClauseSupportsArithmeticOperatorsWithFunctions() + { + $q = new Doctrine_Query(); + + $str = $q->parseClause('ACOS(2) + 3'); + + $this->assertEqual($str, 'ACOS(2) + 3'); + } + + public function testParseClauseSupportsArithmeticOperatorsWithParenthesis() + { + $q = new Doctrine_Query(); + + $str = $q->parseClause('(3 + 3)*3'); + + $this->assertEqual($str, '(3 + 3)*3'); + + $str = $q->parseClause('((3 + 3)*3 - 123) * 12 * (13 + 31)'); + + $this->assertEqual($str, '((3 + 3)*3 - 123) * 12 * (13 + 31)'); + } + + public function testParseClauseSupportsArithmeticOperatorsWithParenthesisAndFunctions() + { + $q = new Doctrine_Query(); + + $str = $q->parseClause('(3 + 3)*ACOS(3)'); + + $this->assertEqual($str, '(3 + 3)*ACOS(3)'); + + $str = $q->parseClause('((3 + 3)*3 - 123) * ACOS(12) * (13 + 31)'); + + $this->assertEqual($str, '((3 + 3)*3 - 123) * ACOS(12) * (13 + 31)'); + } + + public function testParseClauseSupportsComponentReferences() + { + $q = new Doctrine_Query(); + $q->from('User u')->leftJoin('u.Phonenumber p'); + $q->getQuery(); + + $this->assertEqual($q->parseClause("CONCAT('u.name', u.name)"), "CONCAT('u.name', e.name)"); + } } class MyQuery extends Doctrine_Query {