1
0
Fork 0
mirror of synced 2025-04-01 12:26:11 +03:00

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:
Guilherme Blanco 2014-04-24 04:47:13 +00:00
parent a3febd79de
commit 9692fc8c5b
4 changed files with 88 additions and 53 deletions

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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) ) {

View file

@ -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