Fixed issue if aliases were specific names, you would either get completely misleading results (dql alias: scalars) or a fatal error (dql alias: newObjects).
This commit is contained in:
parent
a3febd79de
commit
9692fc8c5b
4 changed files with 88 additions and 53 deletions
|
@ -247,7 +247,7 @@ abstract class AbstractHydrator
|
|||
*/
|
||||
protected function gatherRowData(array $data, array &$cache, array &$id, array &$nonemptyComponents)
|
||||
{
|
||||
$rowData = array();
|
||||
$rowData = array('data' => array());
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$cacheKeyInfo = $this->getColumnCacheInfo($key, $cache);
|
||||
|
@ -281,7 +281,7 @@ abstract class AbstractHydrator
|
|||
$fieldName = $cacheKeyInfo['fieldName'];
|
||||
|
||||
// Avoid double setting or null assignment
|
||||
if (isset($rowData[$dqlAlias][$fieldName]) || $value === null) {
|
||||
if (isset($rowData['data'][$dqlAlias][$fieldName]) || $value === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,7 @@ abstract class AbstractHydrator
|
|||
$nonemptyComponents[$dqlAlias] = true;
|
||||
}
|
||||
|
||||
$rowData[$dqlAlias][$fieldName] = $value;
|
||||
$rowData['data'][$dqlAlias][$fieldName] = $value;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -301,7 +301,7 @@ abstract class AbstractHydrator
|
|||
// in an inheritance hierarchy the same field could be defined several times.
|
||||
// We overwrite this value so long we don't have a non-null value, that value we keep.
|
||||
// Per definition it cannot be that a field is defined several times and has several values.
|
||||
if (isset($rowData[$dqlAlias][$fieldName]) && $value === null) {
|
||||
if (isset($rowData['data'][$dqlAlias][$fieldName]) && $value === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -315,7 +315,7 @@ abstract class AbstractHydrator
|
|||
$nonemptyComponents[$dqlAlias] = true;
|
||||
}
|
||||
|
||||
$rowData[$dqlAlias][$fieldName] = $value;
|
||||
$rowData['data'][$dqlAlias][$fieldName] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,30 +110,8 @@ class ArrayHydrator extends AbstractHydrator
|
|||
$nonemptyComponents = array();
|
||||
$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);
|
||||
|
||||
// Extract scalar values. They're appended at the end.
|
||||
if (isset($rowData['scalars'])) {
|
||||
$scalars = $rowData['scalars'];
|
||||
|
||||
unset($rowData['scalars']);
|
||||
|
||||
if (empty($rowData)) {
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract "new" object constructor arguments. They're appended at the end.
|
||||
if (isset($rowData['newObjects'])) {
|
||||
$newObjects = $rowData['newObjects'];
|
||||
|
||||
unset($rowData['newObjects']);
|
||||
|
||||
if (empty($rowData)) {
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Now hydrate the data found in the current row.
|
||||
foreach ($rowData as $dqlAlias => $data) {
|
||||
foreach ($rowData['data'] as $dqlAlias => $data) {
|
||||
$index = false;
|
||||
|
||||
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
|
||||
|
@ -232,8 +210,8 @@ class ArrayHydrator extends AbstractHydrator
|
|||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->_rsm->isMixed
|
||||
? array($entityKey => $rowData[$dqlAlias])
|
||||
: $rowData[$dqlAlias];
|
||||
? array($entityKey => $data)
|
||||
: $data;
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
|
@ -249,40 +227,39 @@ class ArrayHydrator extends AbstractHydrator
|
|||
} else {
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$resultKey = $index;
|
||||
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] =& $result[$index];
|
||||
++$this->_resultCounter;
|
||||
}*/
|
||||
}
|
||||
|
||||
$this->updateResultPointer($result, $index, $dqlAlias, false);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset($resultKey)) {
|
||||
$this->_resultCounter++;
|
||||
}
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
if (isset($rowData['scalars'])) {
|
||||
if ( ! isset($resultKey)) {
|
||||
// this only ever happens when no object is fetched (scalar result only)
|
||||
$resultKey = isset($this->_rsm->indexByMap['scalars'])
|
||||
? $row[$this->_rsm->indexByMap['scalars']]
|
||||
: $this->_resultCounter - 1;
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
foreach ($rowData['scalars'] as $name => $value) {
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Append new object to mixed result sets
|
||||
if (isset($newObjects)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
if (isset($rowData['newObjects'])) {
|
||||
if ( ! isset($resultKey)) {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
|
||||
$count = count($newObjects);
|
||||
$count = count($rowData['newObjects']);
|
||||
|
||||
foreach ($newObjects as $objIndex => $newObject) {
|
||||
foreach ($rowData['newObjects'] as $objIndex => $newObject) {
|
||||
$class = $newObject['class'];
|
||||
$args = $newObject['args'];
|
||||
$obj = $class->newInstanceArgs($args);
|
||||
|
|
|
@ -387,7 +387,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
}
|
||||
|
||||
// Hydrate the data chunks
|
||||
foreach ($rowData as $dqlAlias => $data) {
|
||||
foreach ($rowData['data'] as $dqlAlias => $data) {
|
||||
$entityName = $this->_rsm->aliasMap[$dqlAlias];
|
||||
|
||||
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
|
||||
|
@ -408,7 +408,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
$relationField = $this->_rsm->relationMap[$dqlAlias];
|
||||
$relation = $parentClass->associationMappings[$relationField];
|
||||
$reflField = $parentClass->reflFields[$relationField];
|
||||
|
||||
|
||||
// Get a reference to the parent object to which the joined element belongs.
|
||||
if ($this->_rsm->isMixed && isset($this->rootAliases[$parentAlias])) {
|
||||
$first = reset($this->resultPointers);
|
||||
|
@ -418,16 +418,13 @@ class ObjectHydrator extends AbstractHydrator
|
|||
} else {
|
||||
// Parent object of relation not found, mark as not-fetched again
|
||||
$element = $this->getEntity($data, $dqlAlias);
|
||||
|
||||
|
||||
// Update result pointer and provide initial fetch data for parent
|
||||
$this->resultPointers[$dqlAlias] = $element;
|
||||
$rowData[$parentAlias][$relationField] = $element;
|
||||
|
||||
$rowData['data'][$parentAlias][$relationField] = $element;
|
||||
|
||||
// Mark as not-fetched again
|
||||
unset($this->_hints['fetched'][$parentAlias][$relationField]);
|
||||
|
||||
////unset($rowData[$dqlAlias]);
|
||||
//$rowData[$dqlAlias] = $data;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -437,7 +434,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
|
||||
// PATH A: Collection-valued association
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
|
||||
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$collKey = $oid . $relationField;
|
||||
if (isset($this->initializedCollections[$collKey])) {
|
||||
|
@ -486,7 +483,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
} else {
|
||||
// PATH B: Single-valued association
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
|
||||
|
||||
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH]) || ($reflFieldValue instanceof Proxy && !$reflFieldValue->__isInitialized__)) {
|
||||
// we only need to take action if this value is null,
|
||||
// we refresh the entity or its an unitialized proxy.
|
||||
|
@ -584,6 +581,10 @@ class ObjectHydrator extends AbstractHydrator
|
|||
}
|
||||
}
|
||||
|
||||
if ( ! isset($resultKey) ) {
|
||||
$this->resultCounter++;
|
||||
}
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
|
|
|
@ -12,6 +12,8 @@ class ArrayHydratorTest extends HydrationTestCase
|
|||
return array(
|
||||
array(0),
|
||||
array('user'),
|
||||
array('scalars'),
|
||||
array('newObjects'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -53,6 +55,61 @@ class ArrayHydratorTest extends HydrationTestCase
|
|||
$this->assertEquals('jwage', $result[1]['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT PARTIAL scalars.{id, name}, UPPER(scalars.name) AS nameUpper
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser scalars
|
||||
*
|
||||
* @dataProvider provideDataForUserEntityResult
|
||||
*/
|
||||
public function testSimpleEntityWithScalarQuery($userEntityKey)
|
||||
{
|
||||
$alias = $userEntityKey ?: 'u';
|
||||
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', $alias);
|
||||
$rsm->addFieldResult($alias, 's__id', 'id');
|
||||
$rsm->addFieldResult($alias, 's__name', 'name');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
array(
|
||||
's__id' => '1',
|
||||
's__name' => 'romanb',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
's__id' => '2',
|
||||
's__name' => 'jwage',
|
||||
'sclr0' => 'JWAGE',
|
||||
)
|
||||
);
|
||||
|
||||
$stmt = new HydratorMockStatement($resultSet);
|
||||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
|
||||
$this->assertTrue(is_array($result));
|
||||
|
||||
$this->assertArrayHasKey('nameUpper', $result[0]);
|
||||
$this->assertArrayNotHasKey('id', $result[0]);
|
||||
$this->assertArrayNotHasKey('name', $result[0]);
|
||||
|
||||
$this->assertArrayHasKey(0, $result[0]);
|
||||
$this->assertArrayHasKey('id', $result[0][0]);
|
||||
$this->assertArrayHasKey('name', $result[0][0]);
|
||||
|
||||
$this->assertArrayHasKey('nameUpper', $result[1]);
|
||||
$this->assertArrayNotHasKey('id', $result[1]);
|
||||
$this->assertArrayNotHasKey('name', $result[1]);
|
||||
|
||||
$this->assertArrayHasKey(0, $result[1]);
|
||||
$this->assertArrayHasKey('id', $result[1][0]);
|
||||
$this->assertArrayHasKey('name', $result[1][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT PARTIAL u.{id, name} AS user
|
||||
* FROM Doctrine\Tests\Models\CMS\CmsUser u
|
||||
|
|
Loading…
Add table
Reference in a new issue