-
-
Save doctrinebot/044a2dc627a11e5c3a9e to your computer and use it in GitHub Desktop.
Attachments to Doctrine Jira Issue DDC-736 - https://github.com/doctrine/doctrine2/issues/5249
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Doctrine\Tests\ORM\Functional\Ticket; | |
use Doctrine\Tests\Models\ECommerce\ECommerceCart; | |
use Doctrine\Tests\Models\ECommerce\ECommerceCustomer; | |
require_once __DIR__ . '/../../../TestInit.php'; | |
class DDC736Test extends \Doctrine\Tests\OrmFunctionalTestCase | |
{ | |
protected function setUp() | |
{ | |
$this->useModelSet('ecommerce'); | |
parent::setUp(); | |
} | |
/** | |
* @group DDC-736 | |
*/ | |
public function testFetchJoinInitializesPreviouslyUninitializedCollectionOfManagedEntity() | |
{ | |
//$this->_em->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger); | |
$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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php | |
index 3d3fb5f..c2ee213 100644 | |
--- a/lib/Doctrine/ORM/Query/Parser.php | |
+++ b/lib/Doctrine/ORM/Query/Parser.php | |
@@ -126,6 +126,16 @@ class Parser | |
private $_customOutputWalker; | |
/** | |
+ * @var array | |
+ */ | |
+ private $_identVariableOrder = array(); | |
+ | |
+ /** | |
+ * @var array | |
+ */ | |
+ private $_identVariableExpressions = array(); | |
+ | |
+ /** | |
* Creates a new query parser object. | |
* | |
* @param Query $query The Query to parse. | |
@@ -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; | |
} | |
/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php | |
index 3d3fb5f..9131f53 100644 | |
--- a/lib/Doctrine/ORM/Query/Parser.php | |
+++ b/lib/Doctrine/ORM/Query/Parser.php | |
@@ -126,6 +126,11 @@ class Parser | |
private $_customOutputWalker; | |
/** | |
+ * @var array | |
+ */ | |
+ private $_identVariableExpressions = array(); | |
+ | |
+ /** | |
* Creates a new query parser object. | |
* | |
* @param Query $query The Query to parse. | |
@@ -297,6 +302,21 @@ class Parser | |
} | |
} | |
+ // Fix order of identification variables. | |
+ // They have to appear in the select clause in the same order as the | |
+ // declarations (from ... x join ... y join ... z ...) appear in the query | |
+ // as the hydration process relies on that order for proper operation. | |
+ if (count($this->_identVariableExpressions) > 1) { | |
+ foreach ($this->_queryComponents as $dqlAlias => $comp) { | |
+ if (isset($this->_identVariableExpressions[$dqlAlias])) { | |
+ $expr = $this->_identVariableExpressions[$dqlAlias]; | |
+ $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 | |
@@ -1628,6 +1648,7 @@ class Parser | |
public function SelectExpression() | |
{ | |
$expression = null; | |
+ $identVariable = null; | |
$fieldAliasIdentificationVariable = null; | |
$peek = $this->_lexer->glimpse(); | |
@@ -1639,7 +1660,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 +1687,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 +1716,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/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php | |
index e43965e..979427a 100644 | |
--- a/lib/Doctrine/ORM/Query/SqlWalker.php | |
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php | |
@@ -382,7 +382,7 @@ class SqlWalker implements TreeWalker | |
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) { | |
$sql .= " " . $this->_platform->getWriteLockSQL(); | |
} else if ($lockMode == LockMode::OPTIMISTIC) { | |
- foreach ($this->_selectedClasses AS $class) { | |
+ foreach ($this->_selectedClasses as $class) { | |
if ( ! $class->isVersioned) { | |
throw \Doctrine\ORM\OptimisticLockException::lockFailed(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment