commit
c38d273c1f
@ -66,12 +66,12 @@ class ArrayHydrator extends AbstractHydrator
|
||||
}
|
||||
|
||||
/** @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 @@ class ArrayHydrator extends AbstractHydrator
|
||||
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 @@ class ArrayHydrator extends AbstractHydrator
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
@ -174,26 +174,23 @@ class ArrayHydrator extends AbstractHydrator
|
||||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $rowData[$dqlAlias];
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element[$field] => $element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$element[$field]] = $element;
|
||||
}
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[] = $element;
|
||||
}
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
}
|
||||
end($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = key($result);
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter;
|
||||
$result[] = $element;
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
} else {
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] =& $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@ -205,8 +202,17 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
// 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) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,13 +273,13 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* @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 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$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 {
|
||||
@ -418,6 +417,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
@ -425,35 +425,31 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// check for existing result from the iterations before
|
||||
if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
}
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$key = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($key => $element);
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$key] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
|
||||
}
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateSet($key, $element);
|
||||
$this->_hints['collection']->hydrateSet($resultKey, $element);
|
||||
}
|
||||
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
}
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateAdd($element);
|
||||
}
|
||||
|
||||
$result[] = $element;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $element;
|
||||
|
||||
@ -461,6 +457,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Update result pointer
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$this->_resultPointers[$dqlAlias] = $result[$index];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] = $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@ -471,8 +468,16 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,7 +157,41 @@ class ResultSetMapping
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
@ -375,7 +382,7 @@ class SqlWalker implements TreeWalker
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -610,10 +617,17 @@ class SqlWalker implements TreeWalker
|
||||
}
|
||||
|
||||
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));
|
||||
@ -996,6 +1010,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
if ( ! $hidden) {
|
||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||
$this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
|
||||
}
|
||||
} else if ($expr instanceof AST\AggregateExpression) {
|
||||
if ( ! $selectExpression->fieldIdentificationVariable) {
|
||||
|
@ -256,20 +256,20 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
$this->assertTrue(is_array($result[2]));
|
||||
|
||||
// test the scalar values
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
$this->assertEquals('ROMANB', $result[1]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']['phonenumbers']));
|
||||
$this->assertEquals(2, count($result[1][0]['phonenumbers']));
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']['phonenumbers']));
|
||||
$this->assertEquals(1, count($result[2][0]['phonenumbers']));
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[0]['1']['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[1]['2']['phonenumbers']['91']));
|
||||
$this->assertTrue(isset($result[1][0]['phonenumbers']['42']));
|
||||
$this->assertTrue(isset($result[1][0]['phonenumbers']['43']));
|
||||
$this->assertTrue(isset($result[2][0]['phonenumbers']['91']));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -817,4 +817,43 @@ class ArrayHydratorTest extends HydrationTestCase
|
||||
$this->assertEquals(array('id' => 2, 'status' => 'developer'), $result[2][0]);
|
||||
$this->assertNull($result[3][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1385
|
||||
*/
|
||||
public function testIndexByAndMixedResult()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
$rsm->addIndexBy('u', 'id');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'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(isset($result[1]));
|
||||
$this->assertEquals(1, $result[1][0]['id']);
|
||||
$this->assertTrue(isset($result[2]));
|
||||
$this->assertEquals(2, $result[2][0]['id']);
|
||||
}
|
||||
}
|
@ -352,24 +352,24 @@ class ObjectHydratorTest extends HydrationTestCase
|
||||
|
||||
$this->assertEquals(2, count($result));
|
||||
$this->assertTrue(is_array($result));
|
||||
$this->assertTrue(is_array($result[0]));
|
||||
$this->assertTrue(is_array($result[1]));
|
||||
$this->assertTrue(is_array($result[2]));
|
||||
|
||||
// test the scalar values
|
||||
$this->assertEquals('ROMANB', $result[0]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[1]['nameUpper']);
|
||||
$this->assertEquals('ROMANB', $result[1]['nameUpper']);
|
||||
$this->assertEquals('JWAGE', $result[2]['nameUpper']);
|
||||
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[0]['1']);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[1]['2']);
|
||||
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $result[0]['1']->phonenumbers);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[1][0]);
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsUser', $result[2][0]);
|
||||
$this->assertInstanceOf('Doctrine\ORM\PersistentCollection', $result[1][0]->phonenumbers);
|
||||
// first user => 2 phonenumbers. notice the custom indexing by user id
|
||||
$this->assertEquals(2, count($result[0]['1']->phonenumbers));
|
||||
$this->assertEquals(2, count($result[1][0]->phonenumbers));
|
||||
// second user => 1 phonenumber. notice the custom indexing by user id
|
||||
$this->assertEquals(1, count($result[1]['2']->phonenumbers));
|
||||
$this->assertEquals(1, count($result[2][0]->phonenumbers));
|
||||
// test the custom indexing of the phonenumbers
|
||||
$this->assertTrue(isset($result[0]['1']->phonenumbers['42']));
|
||||
$this->assertTrue(isset($result[0]['1']->phonenumbers['43']));
|
||||
$this->assertTrue(isset($result[1]['2']->phonenumbers['91']));
|
||||
$this->assertTrue(isset($result[1][0]->phonenumbers['42']));
|
||||
$this->assertTrue(isset($result[1][0]->phonenumbers['43']));
|
||||
$this->assertTrue(isset($result[2][0]->phonenumbers['91']));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1169,4 +1169,71 @@ class ObjectHydratorTest extends HydrationTestCase
|
||||
$this->assertInstanceOf('Doctrine\Tests\Models\CMS\CmsAddress', $result[0][0]->address);
|
||||
$this->assertNull($result[1][0]->address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1385
|
||||
*/
|
||||
public function testIndexByAndMixedResult()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
$rsm->addFieldResult('u', 'u__id', 'id');
|
||||
$rsm->addFieldResult('u', 'u__status', 'status');
|
||||
$rsm->addScalarResult('sclr0', 'nameUpper');
|
||||
$rsm->addIndexBy('u', 'id');
|
||||
|
||||
// Faked result set
|
||||
$resultSet = array(
|
||||
//row1
|
||||
array(
|
||||
'u__id' => '1',
|
||||
'u__status' => 'developer',
|
||||
'sclr0' => 'ROMANB',
|
||||
),
|
||||
array(
|
||||
'u__id' => '2',
|
||||
'u__status' => 'developer',
|
||||
'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(2, count($result));
|
||||
$this->assertTrue(isset($result[1]));
|
||||
$this->assertEquals(1, $result[1][0]->id);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user