1
0
mirror of synced 2025-02-22 15:13:13 +03:00

[DDC-952] Make collection loading work with hydrators also.

This commit is contained in:
Benjamin Eberlei 2011-03-13 00:15:50 +01:00
parent 7c7106b1c1
commit 1bc4b62805
4 changed files with 36 additions and 33 deletions

View File

@ -404,6 +404,10 @@ class ObjectHydrator extends AbstractHydrator
$result[$key] = $element; $result[$key] = $element;
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key; $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
} }
if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateSet($key, $element);
}
} else { } else {
if ($this->_rsm->isMixed) { if ($this->_rsm->isMixed) {
$element = array(0 => $element); $element = array(0 => $element);
@ -411,6 +415,10 @@ class ObjectHydrator extends AbstractHydrator
$result[] = $element; $result[] = $element;
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter; $this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
++$this->_resultCounter; ++$this->_resultCounter;
if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateAdd($element);
}
} }
// Update result pointer // Update result pointer

View File

@ -721,19 +721,17 @@ class BasicEntityPersister
*/ */
private function loadArrayFromStatement($assoc, $stmt) private function loadArrayFromStatement($assoc, $stmt)
{ {
$entities = array(); $hints = array('deferEagerLoads' => true);
if (isset($assoc['indexBy'])) { if (isset($assoc['indexBy'])) {
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) { $rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.
$entity = $this->_createEntity($result); $rsm->addIndexBy('r', $assoc['indexBy']);
$entities[$this->_class->reflFields[$assoc['indexBy']]->getValue($entity)] = $entity;
}
} else { } else {
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) { $rsm = $this->_rsm;
$entities[] = $this->_createEntity($result);
} }
}
$stmt->closeCursor(); $hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
return $entities; return $hydrator->hydrateAll($stmt, $rsm, $hints);
} }
/** /**
@ -745,20 +743,17 @@ class BasicEntityPersister
*/ */
private function loadCollectionFromStatement($assoc, $stmt, $coll) private function loadCollectionFromStatement($assoc, $stmt, $coll)
{ {
$hints = array('deferEagerLoads' => true); $hints = array('deferEagerLoads' => true, 'collection' => $coll);
if (isset($assoc['indexBy'])) {
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$entity = $this->_createEntity($result, null, $hints);
$coll->hydrateSet($this->_class->reflFields[$assoc['indexBy']]->getValue($entity), $entity);
}
} else {
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$coll->hydrateAdd($this->_createEntity($result, null, $hints));
}
}
$stmt->closeCursor();
$this->_em->getUnitOfWork()->triggerEagerLoads(); if (isset($assoc['indexBy'])) {
$rsm = clone ($this->_rsm); // this is necessary because the "default rsm" should be changed.
$rsm->addIndexBy('r', $assoc['indexBy']);
} else {
$rsm = $this->_rsm;
}
$hydrator = $this->_em->newHydrator(Query::HYDRATE_OBJECT);
$hydrator->hydrateAll($stmt, $rsm, $hints);
} }
/** /**
@ -994,13 +989,13 @@ class BasicEntityPersister
$columnList .= $assocColumnSQL; $columnList .= $assocColumnSQL;
} }
if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER/* || !$assoc['isOwningSide']*/)) { if ($assoc['type'] & ClassMetadata::TO_ONE && ($assoc['fetch'] == ClassMetadata::FETCH_EAGER || !$assoc['isOwningSide'])) {
$eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']); $eagerEntity = $this->_em->getClassMetadata($assoc['targetEntity']);
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) { if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
continue; // now this is why you shouldn't use inheritance continue; // now this is why you shouldn't use inheritance
} }
$assocAlias = 'e' + ($eagerAliasCounter++); $assocAlias = 'e' . ($eagerAliasCounter++);
$this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField); $this->_rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
foreach ($eagerEntity->fieldNames AS $field) { foreach ($eagerEntity->fieldNames AS $field) {
@ -1009,13 +1004,13 @@ class BasicEntityPersister
} }
foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) { foreach ($eagerEntity->associationMappings as $assoc2Field => $assoc2) {
$assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity); $assoc2ColumnSQL = $this->_getSelectColumnAssociationSQL($assoc2Field, $assoc2, $eagerEntity, $assocAlias);
if ($assoc2ColumnSQL) { if ($assoc2ColumnSQL) {
if ($columnList) $columnList .= ', '; if ($columnList) $columnList .= ', ';
$columnList .= $assoc2ColumnSQL; $columnList .= $assoc2ColumnSQL;
} }
} }
$this->_selectJoinSql .= ' LEFT JOIN'; $this->_selectJoinSql .= ' LEFT JOIN'; // TODO: Inner join when all join columns are NOT nullable.
if ($assoc['isOwningSide']) { if ($assoc['isOwningSide']) {
$this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON '; $this->_selectJoinSql .= ' ' . $eagerEntity->table['name'] . ' ' . $this->_getSQLTableAlias($eagerEntity->name, $assocAlias) .' ON ';
@ -1042,7 +1037,7 @@ class BasicEntityPersister
return $this->_selectColumnListSql; return $this->_selectColumnListSql;
} }
protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class) protected function _getSelectColumnAssociationSQL($field, $assoc, ClassMetadata $class, $alias = 'r')
{ {
$columnList = ''; $columnList = '';
if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) { if ($assoc['isOwningSide'] && $assoc['type'] & ClassMetadata::TO_ONE) {
@ -1050,12 +1045,12 @@ class BasicEntityPersister
if ($columnList) $columnList .= ', '; if ($columnList) $columnList .= ', ';
$columnAlias = $srcColumn . $this->_sqlAliasCounter++; $columnAlias = $srcColumn . $this->_sqlAliasCounter++;
$columnList .= $this->_getSQLTableAlias($class->name) . ".$srcColumn AS $columnAlias"; $columnList .= $this->_getSQLTableAlias($class->name, ($alias == 'r' ? '' : $alias) ) . ".$srcColumn AS $columnAlias";
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias); $resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
if ( ! isset($this->_resultColumnNames[$resultColumnName])) { if ( ! isset($this->_resultColumnNames[$resultColumnName])) {
$this->_resultColumnNames[$resultColumnName] = $srcColumn; $this->_resultColumnNames[$resultColumnName] = $srcColumn;
} }
$this->_rsm->addMetaResult('r', $this->_platform->getSQLResultCasing($columnAlias), $srcColumn); $this->_rsm->addMetaResult($alias, $this->_platform->getSQLResultCasing($columnAlias), $srcColumn);
} }
} }
return $columnList; return $columnList;
@ -1195,8 +1190,8 @@ class BasicEntityPersister
return $this->_sqlTableAliases[$className]; return $this->_sqlTableAliases[$className];
} }
$tableAlias = 't' . $this->_sqlAliasCounter++; $tableAlias = 't' . $this->_sqlAliasCounter++;
$this->_sqlTableAliases[$className] = $tableAlias;
$this->_sqlTableAliases[$className] = $tableAlias;
return $tableAlias; return $tableAlias;
} }

View File

@ -172,10 +172,10 @@ class EntityRepositoryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$userId = $user->id; $userId = $user->id;
$this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $userId); $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId);
$this->setExpectedException('Doctrine\ORM\OptimisticLockException'); $this->setExpectedException('Doctrine\ORM\OptimisticLockException');
$this->_em->find('Doctrine\Tests\Models\Cms\CmsUser', $userId, \Doctrine\DBAL\LockMode::OPTIMISTIC); $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $userId, \Doctrine\DBAL\LockMode::OPTIMISTIC);
} }
/** /**

View File

@ -196,8 +196,8 @@ class ExtraLazyCollectionTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->assertEquals(2, count($someUsers)); $this->assertEquals(2, count($someUsers));
$this->assertEquals(2, count($otherUsers)); $this->assertEquals(2, count($otherUsers));
// +2 queries executed by slice, +4 are executed by EAGER fetching of User Address. // +2 queries executed by slice
$this->assertEquals($queryCount + 2 + 4, $this->getCurrentQueryCount()); $this->assertEquals($queryCount + 2, $this->getCurrentQueryCount(), "Slicing two parts should only execute two additional queries.");
} }
/** /**