From ebe933810e0f25097c0067525c1b219b35495f5f Mon Sep 17 00:00:00 2001 From: Guilherme Blanco Date: Mon, 3 Oct 2011 02:07:07 -0300 Subject: [PATCH] Implemented HIDDEN support in DQL. Fixes DDC-1363. --- .../ORM/Query/AST/SelectExpression.php | 6 +- lib/Doctrine/ORM/Query/Lexer.php | 67 ++++++++++--------- lib/Doctrine/ORM/Query/Parser.php | 15 ++++- lib/Doctrine/ORM/Query/SqlWalker.php | 35 +++++++--- lib/Doctrine/ORM/Tools/EntityGenerator.php | 3 + .../Tests/ORM/Functional/QueryTest.php | 30 +++++++++ 6 files changed, 110 insertions(+), 46 deletions(-) diff --git a/lib/Doctrine/ORM/Query/AST/SelectExpression.php b/lib/Doctrine/ORM/Query/AST/SelectExpression.php index f1793f0c4..623a325bb 100644 --- a/lib/Doctrine/ORM/Query/AST/SelectExpression.php +++ b/lib/Doctrine/ORM/Query/AST/SelectExpression.php @@ -23,7 +23,7 @@ namespace Doctrine\ORM\Query\AST; /** * SelectExpression ::= IdentificationVariable ["." "*"] | StateFieldPathExpression | - * (AggregateExpression | "(" Subselect ")") [["AS"] FieldAliasIdentificationVariable] + * (AggregateExpression | "(" Subselect ")") [["AS"] ["HIDDEN"] FieldAliasIdentificationVariable] * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org @@ -36,11 +36,13 @@ namespace Doctrine\ORM\Query\AST; class SelectExpression extends Node { public $expression; + public $hiddenAliasResultVariable; public $fieldIdentificationVariable; - public function __construct($expression, $fieldIdentificationVariable) + public function __construct($expression, $hiddenAliasResultVariable, $fieldIdentificationVariable) { $this->expression = $expression; + $this->hiddenAliasResultVariable = $hiddenAliasResultVariable; $this->fieldIdentificationVariable = $fieldIdentificationVariable; } diff --git a/lib/Doctrine/ORM/Query/Lexer.php b/lib/Doctrine/ORM/Query/Lexer.php index 9d20689cf..00fcffd8c 100644 --- a/lib/Doctrine/ORM/Query/Lexer.php +++ b/lib/Doctrine/ORM/Query/Lexer.php @@ -76,39 +76,40 @@ class Lexer extends \Doctrine\Common\Lexer const T_FROM = 122; const T_GROUP = 123; const T_HAVING = 124; - const T_IN = 125; - const T_INDEX = 126; - const T_INNER = 127; - const T_INSTANCE = 128; - const T_IS = 129; - const T_JOIN = 130; - const T_LEADING = 131; - const T_LEFT = 132; - const T_LIKE = 133; - const T_MAX = 134; - const T_MEMBER = 135; - const T_MIN = 136; - const T_NOT = 137; - const T_NULL = 138; - const T_NULLIF = 139; - const T_OF = 140; - const T_OR = 141; - const T_ORDER = 142; - const T_OUTER = 143; - const T_SELECT = 144; - const T_SET = 145; - const T_SIZE = 146; - const T_SOME = 147; - const T_SUM = 148; - const T_THEN = 149; - const T_TRAILING = 150; - const T_TRUE = 151; - const T_UPDATE = 152; - const T_WHEN = 153; - const T_WHERE = 154; - const T_WITH = 155; - const T_PARTIAL = 156; - const T_MOD = 157; + const T_HIDDEN = 125; + const T_IN = 126; + const T_INDEX = 127; + const T_INNER = 128; + const T_INSTANCE = 129; + const T_IS = 130; + const T_JOIN = 131; + const T_LEADING = 132; + const T_LEFT = 133; + const T_LIKE = 134; + const T_MAX = 135; + const T_MEMBER = 136; + const T_MIN = 137; + const T_NOT = 138; + const T_NULL = 139; + const T_NULLIF = 140; + const T_OF = 141; + const T_OR = 142; + const T_ORDER = 143; + const T_OUTER = 144; + const T_SELECT = 145; + const T_SET = 146; + const T_SIZE = 147; + const T_SOME = 148; + const T_SUM = 149; + const T_THEN = 150; + const T_TRAILING = 151; + const T_TRUE = 152; + const T_UPDATE = 153; + const T_WHEN = 154; + const T_WHERE = 155; + const T_WITH = 156; + const T_PARTIAL = 157; + const T_MOD = 158; /** * Creates a new query scanner object. diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index d5b57a00d..35294a0ea 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -1831,7 +1831,7 @@ class Parser /** * SelectExpression ::= * IdentificationVariable | StateFieldPathExpression | - * (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable] + * (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] ["HIDDEN"] AliasResultVariable] * * @return Doctrine\ORM\Query\AST\SelectExpression */ @@ -1839,6 +1839,7 @@ class Parser { $expression = null; $identVariable = null; + $hiddenAliasResultVariable = false; $fieldAliasIdentificationVariable = null; $peek = $this->_lexer->glimpse(); @@ -1900,6 +1901,12 @@ class Parser if ($this->_lexer->isNextToken(Lexer::T_AS)) { $this->match(Lexer::T_AS); } + + if ($this->_lexer->isNextToken(Lexer::T_HIDDEN)) { + $this->match(Lexer::T_HIDDEN); + + $hiddenAliasResultVariable = true; + } if ($this->_lexer->isNextToken(Lexer::T_IDENTIFIER)) { $token = $this->_lexer->lookahead; @@ -1914,10 +1921,12 @@ class Parser } } - $expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable); - if (!$supportsAlias) { + $expr = new AST\SelectExpression($expression, $hiddenAliasResultVariable, $fieldAliasIdentificationVariable); + + if ( ! $supportsAlias) { $this->_identVariableExpressions[$identVariable] = $expr; } + return $expr; } diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 0f1c79542..9a929c6d6 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -975,8 +975,9 @@ class SqlWalker implements TreeWalker */ public function walkSelectExpression($selectExpression) { - $sql = ''; - $expr = $selectExpression->expression; + $sql = ''; + $expr = $selectExpression->expression; + $hidden = $selectExpression->hiddenAliasResultVariable; if ($expr instanceof AST\PathExpression) { if ($expr->type !== AST\PathExpression::TYPE_STATE_FIELD) { @@ -1006,7 +1007,10 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSQLColumnAlias($columnName); $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else if ($expr instanceof AST\AggregateExpression) { if ( ! $selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; @@ -1019,7 +1023,10 @@ class SqlWalker implements TreeWalker $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else if ($expr instanceof AST\Subselect) { if ( ! $selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; @@ -1032,7 +1039,10 @@ class SqlWalker implements TreeWalker $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else if ($expr instanceof AST\Functions\FunctionNode) { if ( ! $selectExpression->fieldIdentificationVariable) { $resultAlias = $this->_scalarResultCounter++; @@ -1045,7 +1055,10 @@ class SqlWalker implements TreeWalker $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else if ( $expr instanceof AST\SimpleArithmeticExpression || $expr instanceof AST\ArithmeticTerm || @@ -1070,7 +1083,10 @@ class SqlWalker implements TreeWalker $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else if ( $expr instanceof AST\NullIfExpression || $expr instanceof AST\CoalesceExpression || @@ -1090,7 +1106,10 @@ class SqlWalker implements TreeWalker $this->_scalarResultAliasMap[$resultAlias] = $columnAlias; $columnAlias = $this->_platform->getSQLResultCasing($columnAlias); - $this->_rsm->addScalarResult($columnAlias, $resultAlias); + + if ( ! $hidden) { + $this->_rsm->addScalarResult($columnAlias, $resultAlias); + } } else { // IdentificationVariable or PartialObjectExpression if ($expr instanceof AST\PartialObjectExpression) { diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php index e53505f98..cc08d944f 100644 --- a/lib/Doctrine/ORM/Tools/EntityGenerator.php +++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -399,14 +399,17 @@ public function () } $collections = array(); + foreach ($metadata->associationMappings AS $mapping) { if ($mapping['type'] & ClassMetadataInfo::TO_MANY) { $collections[] = '$this->'.$mapping['fieldName'].' = new \Doctrine\Common\Collections\ArrayCollection();'; } } + if ($collections) { return $this->_prefixCodeWithSpaces(str_replace("", implode("\n", $collections), self::$_constructorMethodTemplate)); } + return ''; } diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php index 993ce1642..596d929f6 100644 --- a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php @@ -533,4 +533,34 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertEquals(2, count($users)); } + + public function testQueryWithHiddenAsSelectExpression() + { + $userA = new CmsUser; + $userA->name = 'Benjamin'; + $userA->username = 'beberlei'; + $userA->status = 'developer'; + $this->_em->persist($userA); + + $userB = new CmsUser; + $userB->name = 'Roman'; + $userB->username = 'romanb'; + $userB->status = 'developer'; + $this->_em->persist($userB); + + $userC = new CmsUser; + $userC->name = 'Jonathan'; + $userC->username = 'jwage'; + $userC->status = 'developer'; + $this->_em->persist($userC); + + $this->_em->flush(); + $this->_em->clear(); + + $query = $this->_em->createQuery("SELECT u, (SELECT COUNT(u2.id) FROM Doctrine\Tests\Models\CMS\CmsUser u2) AS HIDDEN total FROM Doctrine\Tests\Models\CMS\CmsUser u"); + $users = $query->execute(); + + $this->assertEquals(3, count($users)); + $this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $users[0]); + } } \ No newline at end of file