Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

DDC-1385 - Add INDEX BY scalar variables on the top-level

  • Loading branch information...
commit 8466060797f0f9c85dd8f9d6b36906c4cbf2e8f7 1 parent ee924ff
@beberlei beberlei authored
View
18 lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php
@@ -66,12 +66,12 @@ protected function _hydrateAll()
}
/** @override */
- protected function _hydrateRow(array $data, array &$cache, array &$result)
+ protected function _hydrateRow(array $row, array &$cache, array &$result)
{
// 1) Initialize
$id = $this->_idTemplate; // initialize the id-memory
$nonemptyComponents = array();
- $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
+ $rowData = $this->_gatherRowData($row, $cache, $id, $nonemptyComponents);
// Extract scalar values. They're appended at the end.
if (isset($rowData['scalars'])) {
@@ -128,8 +128,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
if ( ! $indexExists || ! $indexIsValid) {
$element = $data;
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
- $field = $this->_rsm->indexByMap[$dqlAlias];
- $baseElement[$relationAlias][$element[$field]] = $element;
+ $baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
} else {
$baseElement[$relationAlias][] = $element;
}
@@ -167,6 +166,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
} else {
$result[] = null;
}
+ $resultKey = $this->_resultCounter;
++$this->_resultCounter;
continue;
}
@@ -179,8 +179,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
}
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
- $field = $this->_rsm->indexByMap[$dqlAlias];
- $resultKey = $rowData[$dqlAlias][$field];
+ $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
$result[$resultKey] = $element;
} else {
$resultKey = $this->_resultCounter;
@@ -204,7 +203,12 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
// Append scalar values to mixed result sets
if (isset($scalars)) {
if ( ! isset($resultKey) ) {
- $resultKey = $this->_resultCounter - 1;
+ // this only ever happens when no object is fetched (scalar result only)
+ if (isset($this->_rsm->indexByMap['scalars'])) {
+ $resultKey = $row[$this->_rsm->indexByMap['scalars']];
+ } else {
+ $resultKey = $this->_resultCounter - 1;
+ }
}
foreach ($scalars as $name => $value) {
View
17 lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
@@ -273,13 +273,13 @@ private function _getClassMetadata($className)
* @param array $cache The cache to use.
* @param array $result The result array to fill.
*/
- protected function _hydrateRow(array $data, array &$cache, array &$result)
+ protected function _hydrateRow(array $row, array &$cache, array &$result)
{
// Initialize
$id = $this->_idTemplate; // initialize the id-memory
$nonemptyComponents = array();
// Split the row data into chunks of class data.
- $rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
+ $rowData = $this->_gatherRowData($row, $cache, $id, $nonemptyComponents);
// Extract scalar values. They're appended at the end.
if (isset($rowData['scalars'])) {
@@ -352,8 +352,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
$element = $this->_getEntity($data, $dqlAlias);
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
- $field = $this->_rsm->indexByMap[$dqlAlias];
- $indexValue = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
+ $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]];
$reflFieldValue->hydrateSet($indexValue, $element);
$this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
} else {
@@ -421,6 +420,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
} else {
$result[] = null;
}
+ $resultKey = $this->_resultCounter;
++$this->_resultCounter;
continue;
}
@@ -433,8 +433,7 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
}
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
- $field = $this->_rsm->indexByMap[$dqlAlias];
- $resultKey = $rowData[$dqlAlias][$field];
+ $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateSet($resultKey, $element);
@@ -473,7 +472,11 @@ protected function _hydrateRow(array $data, array &$cache, array &$result)
// Append scalar values to mixed result sets
if (isset($scalars)) {
if ( ! isset($resultKey) ) {
- $resultKey = $this->_resultCounter - 1;
+ if (isset($this->_rsm->indexByMap['scalars'])) {
+ $resultKey = $row[$this->_rsm->indexByMap['scalars']];
+ } else {
+ $resultKey = $this->_resultCounter - 1;
+ }
}
foreach ($scalars as $name => $value) {
View
36 lib/Doctrine/ORM/Query/ResultSetMapping.php
@@ -157,7 +157,41 @@ public function setDiscriminatorColumn($alias, $discrColumn)
*/
public function addIndexBy($alias, $fieldName)
{
- $this->indexByMap[$alias] = $fieldName;
+ $found = false;
+ foreach ($this->fieldMappings AS $columnName => $columnFieldName) {
+ if ($columnFieldName === $fieldName && $this->columnOwnerMap[$columnName] == $alias) {
+ $this->addIndexByColumn($alias, $columnName);
+ $found = true;
+ break;
+ }
+ }
+ if (!$found) {
+ throw new \LogicException("Cannot add index by for dql alias " . $alias . " and field " .
+ $fieldName . " without calling addFieldResult() for them before.");
+ }
+ }
+
+ /**
+ * Set to index by a scalar result column name
+ *
+ * @param $resultColumnName
+ * @return void
+ */
+ public function addIndexByScalar($resultColumnName)
+ {
+ $this->indexByMap['scalars'] = $resultColumnName;
+ }
+
+ /**
+ * Sets a column to use for indexing an entity or joined entity result by the given alias name.
+ *
+ * @param $alias
+ * @param $resultColumnName
+ * @return void
+ */
+ public function addIndexByColumn($alias, $resultColumnName)
+ {
+ $this->indexByMap[$alias] = $resultColumnName;
}
/**
View
25 lib/Doctrine/ORM/Query/SqlWalker.php
@@ -71,6 +71,13 @@ class SqlWalker implements TreeWalker
/** Map from result variable names to their SQL column alias names. */
private $_scalarResultAliasMap = array();
+ /**
+ * Map from DQL-Alias + Field-Name to SQL Column Alias
+ *
+ * @var array
+ */
+ private $_scalarFields = array();
+
/** Map of all components/classes that appear in the DQL query. */
private $_queryComponents;
@@ -381,7 +388,7 @@ public function walkSelectStatement(AST\SelectStatement $AST)
} else if ($lockMode == LockMode::OPTIMISTIC) {
foreach ($this->_selectedClasses AS $class) {
if ( ! $class->isVersioned) {
- throw \Doctrine\ORM\OptimisticLockException::lockFailed();
+ throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name);
}
}
}
@@ -619,10 +626,17 @@ public function walkFromClause($fromClause)
}
if ($identificationVariableDecl->indexBy) {
- $this->_rsm->addIndexBy(
- $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
- $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->field
- );
+ $alias = $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable;
+ $field = $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->field;
+
+ if (isset($this->_scalarFields[$alias][$field])) {
+ $this->_rsm->addIndexByScalar($this->_scalarFields[$alias][$field]);
+ } else {
+ $this->_rsm->addIndexBy(
+ $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
+ $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->field
+ );
+ }
}
$sqlParts[] = $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE));
@@ -1010,6 +1024,7 @@ public function walkSelectExpression($selectExpression)
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
+ $this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
}
} else if ($expr instanceof AST\AggregateExpression) {
if ( ! $selectExpression->fieldIdentificationVariable) {
View
28 tests/Doctrine/Tests/ORM/Hydration/ObjectHydratorTest.php
@@ -1208,4 +1208,32 @@ public function testIndexByAndMixedResult()
$this->assertTrue(isset($result[2]));
$this->assertEquals(2, $result[2][0]->id);
}
+
+ /**
+ * @group DDC-1385
+ */
+ public function testIndexByScalarsOnly()
+ {
+ $rsm = new ResultSetMapping;
+ $rsm->addScalarResult('sclr0', 'nameUpper');
+ $rsm->addIndexByScalar('sclr0');
+
+ // Faked result set
+ $resultSet = array(
+ //row1
+ array(
+ 'sclr0' => 'ROMANB',
+ ),
+ array(
+ 'sclr0' => 'JWAGE',
+ ),
+ );
+
+ $stmt = new HydratorMockStatement($resultSet);
+ $hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
+
+ $result = $hydrator->hydrateAll($stmt, $rsm, array(Query::HINT_FORCE_PARTIAL_LOAD => true));
+
+ $this->assertEquals(array('ROMANB' => array('nameUpper' => 'ROMANB'), 'JWAGE' => array('nameUpper' => 'JWAGE')), $result);
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.