From e4280cf82e96b70068915ce2adf4beea50c67b79 Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 11 Nov 2010 21:12:09 +0100 Subject: [PATCH] DDC-736 - Fix ordering of identification variables in DQL parser to be by specification. --- lib/Doctrine/ORM/Query/Parser.php | 35 +++++++++++++++- .../ORM/Functional/Ticket/DDC736Test.php | 42 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC736Test.php diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index 3d3fb5f5e..c2ee2137e 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -125,6 +125,16 @@ class Parser */ private $_customOutputWalker; + /** + * @var array + */ + private $_identVariableOrder = array(); + + /** + * @var array + */ + private $_identVariableExpressions = array(); + /** * Creates a new query parser object. * @@ -297,6 +307,19 @@ class Parser } } + // fix order of identification variables + if ( count($this->_identVariableExpressions) > 1) { + $n = count($this->_identVariableOrder); + for ($i = 0; $i < $n; $i++) { + if (isset($this->_identVariableExpressions[$this->_identVariableOrder[$i]])) { + $expr = $this->_identVariableExpressions[$this->_identVariableOrder[$i]]; + $key = array_search($expr, $AST->selectClause->selectExpressions); + unset($AST->selectClause->selectExpressions[$key]); + $AST->selectClause->selectExpressions[] = $expr; + } + } + } + if ($this->_customOutputWalker) { $outputWalker = new $this->_customOutputWalker( $this->_query, $this->_parserResult, $this->_queryComponents @@ -1419,6 +1442,7 @@ class Parser $token = $this->_lexer->lookahead; $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + $this->_identVariableOrder[] = $aliasIdentificationVariable; $classMetadata = $this->_em->getClassMetadata($abstractSchemaName); // Building queryComponent @@ -1509,6 +1533,7 @@ class Parser $token = $this->_lexer->lookahead; $aliasIdentificationVariable = $this->AliasIdentificationVariable(); + $this->_identVariableOrder[] = $aliasIdentificationVariable; // Verify that the association exists. $parentClass = $this->_queryComponents[$joinPathExpression->identificationVariable]['metadata']; @@ -1628,6 +1653,7 @@ class Parser public function SelectExpression() { $expression = null; + $identVariable = null; $fieldAliasIdentificationVariable = null; $peek = $this->_lexer->glimpse(); @@ -1639,7 +1665,7 @@ class Parser $expression = $this->ScalarExpression(); } else { $supportsAlias = false; - $expression = $this->IdentificationVariable(); + $expression = $identVariable = $this->IdentificationVariable(); } } else if ($this->_lexer->lookahead['value'] == '(') { if ($peek['type'] == Lexer::T_SELECT) { @@ -1666,6 +1692,7 @@ class Parser } else if ($this->_lexer->lookahead['type'] == Lexer::T_PARTIAL) { $supportsAlias = false; $expression = $this->PartialObjectExpression(); + $identVariable = $expression->identificationVariable; } else if ($this->_lexer->lookahead['type'] == Lexer::T_INTEGER || $this->_lexer->lookahead['type'] == Lexer::T_FLOAT) { // Shortcut: ScalarExpression => SimpleArithmeticExpression @@ -1694,7 +1721,11 @@ class Parser } } - return new AST\SelectExpression($expression, $fieldAliasIdentificationVariable); + $expr = new AST\SelectExpression($expression, $fieldAliasIdentificationVariable); + if (!$supportsAlias) { + $this->_identVariableExpressions[$identVariable] = $expr; + } + return $expr; } /** diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC736Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC736Test.php new file mode 100644 index 000000000..e6138f87d --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC736Test.php @@ -0,0 +1,42 @@ +useModelSet('ecommerce'); + parent::setUp(); + } + + /** + * @group DDC-736 + */ + public function testFetchJoinInitializesPreviouslyUninitializedCollectionOfManagedEntity() + { + $cust = new ECommerceCustomer; + $cust->setName('roman'); + + $cart = new ECommerceCart; + $cart->setPayment('cash'); + $cart->setCustomer($cust); + + $this->_em->persist($cust); + $this->_em->persist($cart); + $this->_em->flush(); + $this->_em->clear(); + + $cart2 = $this->_em->createQuery("select c, ca from Doctrine\Tests\Models\ECommerce\ECommerceCart ca join ca.customer c") + ->getSingleResult(/*\Doctrine\ORM\Query::HYDRATE_ARRAY*/); + + $this->assertTrue($cart2 instanceof ECommerceCart); + $this->assertFalse($cart2->getCustomer() instanceof \Doctrine\ORM\Proxy\Proxy); + $this->assertTrue($cart2->getCustomer() instanceof ECommerceCustomer); + } +}