1
0
mirror of synced 2025-01-20 23:41:39 +03:00

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

This commit is contained in:
Benjamin Eberlei 2011-10-16 19:23:20 +02:00
parent ee924ffaba
commit 8466060797
5 changed files with 104 additions and 20 deletions

View File

@ -66,12 +66,12 @@ class ArrayHydrator extends AbstractHydrator
} }
/** @override */ /** @override */
protected function _hydrateRow(array $data, array &$cache, array &$result) protected function _hydrateRow(array $row, array &$cache, array &$result)
{ {
// 1) Initialize // 1) Initialize
$id = $this->_idTemplate; // initialize the id-memory $id = $this->_idTemplate; // initialize the id-memory
$nonemptyComponents = array(); $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. // Extract scalar values. They're appended at the end.
if (isset($rowData['scalars'])) { if (isset($rowData['scalars'])) {
@ -128,8 +128,7 @@ class ArrayHydrator extends AbstractHydrator
if ( ! $indexExists || ! $indexIsValid) { if ( ! $indexExists || ! $indexIsValid) {
$element = $data; $element = $data;
if (isset($this->_rsm->indexByMap[$dqlAlias])) { if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$field = $this->_rsm->indexByMap[$dqlAlias]; $baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
$baseElement[$relationAlias][$element[$field]] = $element;
} else { } else {
$baseElement[$relationAlias][] = $element; $baseElement[$relationAlias][] = $element;
} }
@ -167,6 +166,7 @@ class ArrayHydrator extends AbstractHydrator
} else { } else {
$result[] = null; $result[] = null;
} }
$resultKey = $this->_resultCounter;
++$this->_resultCounter; ++$this->_resultCounter;
continue; continue;
} }
@ -179,8 +179,7 @@ class ArrayHydrator extends AbstractHydrator
} }
if (isset($this->_rsm->indexByMap[$dqlAlias])) { if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$field = $this->_rsm->indexByMap[$dqlAlias]; $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
$resultKey = $rowData[$dqlAlias][$field];
$result[$resultKey] = $element; $result[$resultKey] = $element;
} else { } else {
$resultKey = $this->_resultCounter; $resultKey = $this->_resultCounter;
@ -204,8 +203,13 @@ class ArrayHydrator extends AbstractHydrator
// Append scalar values to mixed result sets // Append scalar values to mixed result sets
if (isset($scalars)) { if (isset($scalars)) {
if ( ! isset($resultKey) ) { 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; $resultKey = $this->_resultCounter - 1;
} }
}
foreach ($scalars as $name => $value) { foreach ($scalars as $name => $value) {
$result[$resultKey][$name] = $value; $result[$resultKey][$name] = $value;

View File

@ -273,13 +273,13 @@ class ObjectHydrator extends AbstractHydrator
* @param array $cache The cache to use. * @param array $cache The cache to use.
* @param array $result The result array to fill. * @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 // Initialize
$id = $this->_idTemplate; // initialize the id-memory $id = $this->_idTemplate; // initialize the id-memory
$nonemptyComponents = array(); $nonemptyComponents = array();
// Split the row data into chunks of class data. // 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. // Extract scalar values. They're appended at the end.
if (isset($rowData['scalars'])) { if (isset($rowData['scalars'])) {
@ -352,8 +352,7 @@ class ObjectHydrator extends AbstractHydrator
$element = $this->_getEntity($data, $dqlAlias); $element = $this->_getEntity($data, $dqlAlias);
if (isset($this->_rsm->indexByMap[$dqlAlias])) { if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$field = $this->_rsm->indexByMap[$dqlAlias]; $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]];
$indexValue = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
$reflFieldValue->hydrateSet($indexValue, $element); $reflFieldValue->hydrateSet($indexValue, $element);
$this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue; $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
} else { } else {
@ -421,6 +420,7 @@ class ObjectHydrator extends AbstractHydrator
} else { } else {
$result[] = null; $result[] = null;
} }
$resultKey = $this->_resultCounter;
++$this->_resultCounter; ++$this->_resultCounter;
continue; continue;
} }
@ -433,8 +433,7 @@ class ObjectHydrator extends AbstractHydrator
} }
if (isset($this->_rsm->indexByMap[$dqlAlias])) { if (isset($this->_rsm->indexByMap[$dqlAlias])) {
$field = $this->_rsm->indexByMap[$dqlAlias]; $resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
$resultKey = $rowData[$dqlAlias][$field];
if (isset($this->_hints['collection'])) { if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateSet($resultKey, $element); $this->_hints['collection']->hydrateSet($resultKey, $element);
@ -473,8 +472,12 @@ class ObjectHydrator extends AbstractHydrator
// Append scalar values to mixed result sets // Append scalar values to mixed result sets
if (isset($scalars)) { if (isset($scalars)) {
if ( ! isset($resultKey) ) { if ( ! isset($resultKey) ) {
if (isset($this->_rsm->indexByMap['scalars'])) {
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
} else {
$resultKey = $this->_resultCounter - 1; $resultKey = $this->_resultCounter - 1;
} }
}
foreach ($scalars as $name => $value) { foreach ($scalars as $name => $value) {
$result[$resultKey][$name] = $value; $result[$resultKey][$name] = $value;

View File

@ -157,7 +157,41 @@ class ResultSetMapping
*/ */
public function addIndexBy($alias, $fieldName) 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 File

@ -71,6 +71,13 @@ class SqlWalker implements TreeWalker
/** Map from result variable names to their SQL column alias names. */ /** Map from result variable names to their SQL column alias names. */
private $_scalarResultAliasMap = array(); 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. */ /** Map of all components/classes that appear in the DQL query. */
private $_queryComponents; private $_queryComponents;
@ -381,7 +388,7 @@ class SqlWalker implements TreeWalker
} else if ($lockMode == LockMode::OPTIMISTIC) { } else if ($lockMode == LockMode::OPTIMISTIC) {
foreach ($this->_selectedClasses AS $class) { foreach ($this->_selectedClasses AS $class) {
if ( ! $class->isVersioned) { if ( ! $class->isVersioned) {
throw \Doctrine\ORM\OptimisticLockException::lockFailed(); throw \Doctrine\ORM\OptimisticLockException::lockFailed($class->name);
} }
} }
} }
@ -619,11 +626,18 @@ class SqlWalker implements TreeWalker
} }
if ($identificationVariableDecl->indexBy) { if ($identificationVariableDecl->indexBy) {
$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( $this->_rsm->addIndexBy(
$identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable, $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->identificationVariable,
$identificationVariableDecl->indexBy->simpleStateFieldPathExpression->field $identificationVariableDecl->indexBy->simpleStateFieldPathExpression->field
); );
} }
}
$sqlParts[] = $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE)); $sqlParts[] = $this->_platform->appendLockHint($sql, $this->_query->getHint(Query::HINT_LOCK_MODE));
} }
@ -1010,6 +1024,7 @@ class SqlWalker implements TreeWalker
if ( ! $hidden) { if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias); $this->_rsm->addScalarResult($columnAlias, $resultAlias);
$this->_scalarFields[$dqlAlias][$fieldName] = $columnAlias;
} }
} else if ($expr instanceof AST\AggregateExpression) { } else if ($expr instanceof AST\AggregateExpression) {
if ( ! $selectExpression->fieldIdentificationVariable) { if ( ! $selectExpression->fieldIdentificationVariable) {

View File

@ -1208,4 +1208,32 @@ class ObjectHydratorTest extends HydrationTestCase
$this->assertTrue(isset($result[2])); $this->assertTrue(isset($result[2]));
$this->assertEquals(2, $result[2][0]->id); $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);
}
} }