diff --git a/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php b/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php
index edb39afc6..6b5e5c4f1 100644
--- a/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php
+++ b/lib/Doctrine/ORM/Persisters/Entity/AbstractEntityInheritancePersister.php
@@ -66,7 +66,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
$sql = $this->getSQLTableAlias($class->name, $tableAlias) . '.'
. $this->quoteStrategy->getColumnName($field, $class, $this->platform);
- $this->rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
+ $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
$type = Type::getType($class->getTypeOfField($field));
@@ -88,7 +88,7 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
{
$columnAlias = $this->getSQLColumnAlias($joinColumnName);
- $this->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type);
+ $this->currentPersisterContext->rsm->addMetaResult('r', $columnAlias, $joinColumnName, false, $type);
return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
}
diff --git a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
index c53e817c1..a3f35f440 100644
--- a/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
+++ b/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php
@@ -134,15 +134,6 @@ class BasicEntityPersister implements EntityPersister
*/
protected $queuedInserts = array();
- /**
- * ResultSetMapping that is used for all queries. Is generated lazily once per request.
- *
- * TODO: Evaluate Caching in combination with the other cached SQL snippets.
- *
- * @var Query\ResultSetMapping
- */
- protected $rsm;
-
/**
* The map of column names to DBAL mapping types of all prepared columns used
* when INSERTing or UPDATEing an entity.
@@ -172,36 +163,6 @@ class BasicEntityPersister implements EntityPersister
*/
private $insertSql;
- /**
- * The SELECT column list SQL fragment used for querying entities by this persister.
- * This SQL fragment is only generated once per request, if at all.
- *
- * @var string
- */
- protected $selectColumnListSql;
-
- /**
- * The JOIN SQL fragment used to eagerly load all many-to-one and one-to-one
- * associations configured as FETCH_EAGER, as well as all inverse one-to-one associations.
- *
- * @var string
- */
- protected $selectJoinSql;
-
- /**
- * Counter for creating unique SQL table and column aliases.
- *
- * @var integer
- */
- protected $sqlAliasCounter = 0;
-
- /**
- * Map from class names (FQCN) to the corresponding generated SQL table aliases.
- *
- * @var array
- */
- protected $sqlTableAliases = array();
-
/**
* The quote strategy.
*
@@ -216,6 +177,21 @@ class BasicEntityPersister implements EntityPersister
*/
private $identifierFlattener;
+ /**
+ * @var CachedPersisterContext
+ */
+ protected $currentPersisterContext;
+
+ /**
+ * @var CachedPersisterContext
+ */
+ private $limitsHandlingContext;
+
+ /**
+ * @var CachedPersisterContext
+ */
+ private $noLimitsContext;
+
/**
* Initializes a new BasicEntityPersister that uses the given EntityManager
* and persists instances of the class described by the given ClassMetadata descriptor.
@@ -225,12 +201,22 @@ class BasicEntityPersister implements EntityPersister
*/
public function __construct(EntityManagerInterface $em, ClassMetadata $class)
{
- $this->em = $em;
- $this->class = $class;
- $this->conn = $em->getConnection();
- $this->platform = $this->conn->getDatabasePlatform();
- $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy();
- $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory());
+ $this->em = $em;
+ $this->class = $class;
+ $this->conn = $em->getConnection();
+ $this->platform = $this->conn->getDatabasePlatform();
+ $this->quoteStrategy = $em->getConfiguration()->getQuoteStrategy();
+ $this->identifierFlattener = new IdentifierFlattener($em->getUnitOfWork(), $em->getMetadataFactory());
+ $this->noLimitsContext = $this->currentPersisterContext = new CachedPersisterContext(
+ $class,
+ new Query\ResultSetMapping(),
+ false
+ );
+ $this->limitsHandlingContext = new CachedPersisterContext(
+ $class,
+ new Query\ResultSetMapping(),
+ true
+ );
}
/**
@@ -246,7 +232,7 @@ class BasicEntityPersister implements EntityPersister
*/
public function getResultSetMapping()
{
- return $this->rsm;
+ return $this->currentPersisterContext->rsm;
}
/**
@@ -710,6 +696,8 @@ class BasicEntityPersister implements EntityPersister
*/
public function load(array $criteria, $entity = null, $assoc = null, array $hints = array(), $lockMode = null, $limit = null, array $orderBy = null)
{
+ $this->switchPersisterContext(null, $limit);
+
$sql = $this->getSelectSQL($criteria, $assoc, $lockMode, $limit, null, $orderBy);
list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->conn->executeQuery($sql, $params, $types);
@@ -719,8 +707,8 @@ class BasicEntityPersister implements EntityPersister
$hints[Query::HINT_REFRESH_ENTITY] = $entity;
}
- $hydrator = $this->em->newHydrator($this->selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
- $entities = $hydrator->hydrateAll($stmt, $this->rsm, $hints);
+ $hydrator = $this->em->newHydrator($this->currentPersisterContext->selectJoinSql ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
+ $entities = $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, $hints);
return $entities ? $entities[0] : null;
}
@@ -809,7 +797,7 @@ class BasicEntityPersister implements EntityPersister
$stmt = $this->conn->executeQuery($sql, $params, $types);
$hydrator = $this->em->newHydrator(Query::HYDRATE_OBJECT);
- $hydrator->hydrateAll($stmt, $this->rsm, array(Query::HINT_REFRESH => true));
+ $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, array(Query::HINT_REFRESH => true));
}
/**
@@ -839,9 +827,9 @@ class BasicEntityPersister implements EntityPersister
list($params, $types) = $this->expandCriteriaParameters($criteria);
$stmt = $this->conn->executeQuery($query, $params, $types);
- $hydrator = $this->em->newHydrator(($this->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
+ $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
- return $hydrator->hydrateAll($stmt, $this->rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
+ return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -880,13 +868,15 @@ class BasicEntityPersister implements EntityPersister
*/
public function loadAll(array $criteria = array(), array $orderBy = null, $limit = null, $offset = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$sql = $this->getSelectSQL($criteria, null, null, $limit, $offset, $orderBy);
list($params, $types) = $this->expandParameters($criteria);
$stmt = $this->conn->executeQuery($sql, $params, $types);
- $hydrator = $this->em->newHydrator(($this->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
+ $hydrator = $this->em->newHydrator(($this->currentPersisterContext->selectJoinSql) ? Query::HYDRATE_OBJECT : Query::HYDRATE_SIMPLEOBJECT);
- return $hydrator->hydrateAll($stmt, $this->rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
+ return $hydrator->hydrateAll($stmt, $this->currentPersisterContext->rsm, array(UnitOfWork::HINT_DEFEREAGERLOAD => true));
}
/**
@@ -894,6 +884,8 @@ class BasicEntityPersister implements EntityPersister
*/
public function getManyToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$stmt = $this->getManyToManyStatement($assoc, $sourceEntity, $offset, $limit);
return $this->loadArrayFromStatement($assoc, $stmt);
@@ -909,11 +901,11 @@ class BasicEntityPersister implements EntityPersister
*/
private function loadArrayFromStatement($assoc, $stmt)
{
- $rsm = $this->rsm;
+ $rsm = $this->currentPersisterContext->rsm;
$hints = array(UnitOfWork::HINT_DEFEREAGERLOAD => true);
if (isset($assoc['indexBy'])) {
- $rsm = clone ($this->rsm); // this is necessary because the "default rsm" should be changed.
+ $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed.
$rsm->addIndexBy('r', $assoc['indexBy']);
}
@@ -931,14 +923,14 @@ class BasicEntityPersister implements EntityPersister
*/
private function loadCollectionFromStatement($assoc, $stmt, $coll)
{
- $rsm = $this->rsm;
+ $rsm = $this->currentPersisterContext->rsm;
$hints = array(
UnitOfWork::HINT_DEFEREAGERLOAD => true,
'collection' => $coll
);
if (isset($assoc['indexBy'])) {
- $rsm = clone ($this->rsm); // this is necessary because the "default rsm" should be changed.
+ $rsm = clone ($this->currentPersisterContext->rsm); // this is necessary because the "default rsm" should be changed.
$rsm->addIndexBy('r', $assoc['indexBy']);
}
@@ -967,6 +959,8 @@ class BasicEntityPersister implements EntityPersister
*/
private function getManyToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$sourceClass = $this->em->getClassMetadata($assoc['sourceEntity']);
$class = $sourceClass;
$association = $assoc;
@@ -1032,6 +1026,8 @@ class BasicEntityPersister implements EntityPersister
*/
public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$lockSql = '';
$joinSql = '';
$orderBySql = '';
@@ -1075,7 +1071,7 @@ class BasicEntityPersister implements EntityPersister
$select = 'SELECT ' . $columnList;
$from = ' FROM ' . $tableName . ' '. $tableAlias;
- $join = $this->selectJoinSql . $joinSql;
+ $join = $this->currentPersisterContext->selectJoinSql . $joinSql;
$where = ($conditionSql ? ' WHERE ' . $conditionSql : '');
$lock = $this->platform->appendLockHint($from, $lockMode);
$query = $select
@@ -1184,20 +1180,19 @@ class BasicEntityPersister implements EntityPersister
*/
protected function getSelectColumnsSQL()
{
- if ($this->selectColumnListSql !== null) {
- return $this->selectColumnListSql;
+ if ($this->currentPersisterContext->selectColumnListSql !== null) {
+ return $this->currentPersisterContext->selectColumnListSql;
}
$columnList = array();
- $this->rsm = new Query\ResultSetMapping();
- $this->rsm->addEntityResult($this->class->name, 'r'); // r for root
+ $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r'); // r for root
// Add regular columns to select list
foreach ($this->class->fieldNames as $field) {
$columnList[] = $this->getSelectColumnSQL($field, $this->class);
}
- $this->selectJoinSql = '';
+ $this->currentPersisterContext->selectJoinSql = '';
$eagerAliasCounter = 0;
foreach ($this->class->associationMappings as $assocField => $assoc) {
@@ -1214,6 +1209,10 @@ class BasicEntityPersister implements EntityPersister
continue;
}
+ if ((($assoc['type'] & ClassMetadata::TO_MANY) > 0) && $this->currentPersisterContext->handlesLimits) {
+ continue;
+ }
+
$eagerEntity = $this->em->getClassMetadata($assoc['targetEntity']);
if ($eagerEntity->inheritanceType != ClassMetadata::INHERITANCE_TYPE_NONE) {
@@ -1221,7 +1220,7 @@ class BasicEntityPersister implements EntityPersister
}
$assocAlias = 'e' . ($eagerAliasCounter++);
- $this->rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
+ $this->currentPersisterContext->rsm->addJoinedEntityResult($assoc['targetEntity'], $assocAlias, 'r', $assocField);
foreach ($eagerEntity->fieldNames as $field) {
$columnList[] = $this->getSelectColumnSQL($field, $eagerEntity, $assocAlias);
@@ -1241,7 +1240,7 @@ class BasicEntityPersister implements EntityPersister
$joinCondition = array();
if (isset($assoc['indexBy'])) {
- $this->rsm->addIndexBy($assocAlias, $assoc['indexBy']);
+ $this->currentPersisterContext->rsm->addIndexBy($assocAlias, $assoc['indexBy']);
}
if ( ! $assoc['isOwningSide']) {
@@ -1254,7 +1253,7 @@ class BasicEntityPersister implements EntityPersister
if ($assoc['isOwningSide']) {
$tableAlias = $this->getSQLTableAlias($association['targetEntity'], $assocAlias);
- $this->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']);
+ $this->currentPersisterContext->selectJoinSql .= ' ' . $this->getJoinSQLForJoinColumns($association['joinColumns']);
foreach ($association['joinColumns'] as $joinColumn) {
$sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
@@ -1270,7 +1269,7 @@ class BasicEntityPersister implements EntityPersister
} else {
- $this->selectJoinSql .= ' LEFT JOIN';
+ $this->currentPersisterContext->selectJoinSql .= ' LEFT JOIN';
foreach ($association['joinColumns'] as $joinColumn) {
$sourceCol = $this->quoteStrategy->getJoinColumnName($joinColumn, $this->class, $this->platform);
@@ -1281,13 +1280,13 @@ class BasicEntityPersister implements EntityPersister
}
}
- $this->selectJoinSql .= ' ' . $joinTableName . ' ' . $joinTableAlias . ' ON ';
- $this->selectJoinSql .= implode(' AND ', $joinCondition);
+ $this->currentPersisterContext->selectJoinSql .= ' ' . $joinTableName . ' ' . $joinTableAlias . ' ON ';
+ $this->currentPersisterContext->selectJoinSql .= implode(' AND ', $joinCondition);
}
- $this->selectColumnListSql = implode(', ', $columnList);
+ $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
- return $this->selectColumnListSql;
+ return $this->currentPersisterContext->selectColumnListSql;
}
/**
@@ -1318,7 +1317,7 @@ class BasicEntityPersister implements EntityPersister
. '.' . $quotedColumn . ' AS ' . $resultColumnName;
$type = PersisterHelper::getTypeOfColumn($joinColumn['referencedColumnName'], $targetClass, $this->em);
- $this->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
+ $this->currentPersisterContext->rsm->addMetaResult($alias, $resultColumnName, $quotedColumn, $isIdentifier, $type);
}
return implode(', ', $columnList);
@@ -1456,7 +1455,7 @@ class BasicEntityPersister implements EntityPersister
$sql = $tableAlias . '.' . $columnName;
$columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]);
- $this->rsm->addFieldResult($alias, $columnAlias, $field);
+ $this->currentPersisterContext->rsm->addFieldResult($alias, $columnAlias, $field);
if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
$type = Type::getType($class->getTypeOfField($field));
@@ -1482,13 +1481,13 @@ class BasicEntityPersister implements EntityPersister
$className .= '#' . $assocName;
}
- if (isset($this->sqlTableAliases[$className])) {
- return $this->sqlTableAliases[$className];
+ if (isset($this->currentPersisterContext->sqlTableAliases[$className])) {
+ return $this->currentPersisterContext->sqlTableAliases[$className];
}
- $tableAlias = 't' . $this->sqlAliasCounter++;
+ $tableAlias = 't' . $this->currentPersisterContext->sqlAliasCounter++;
- $this->sqlTableAliases[$className] = $tableAlias;
+ $this->currentPersisterContext->sqlTableAliases[$className] = $tableAlias;
return $tableAlias;
}
@@ -1690,6 +1689,8 @@ class BasicEntityPersister implements EntityPersister
*/
public function getOneToManyCollection(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$stmt = $this->getOneToManyStatement($assoc, $sourceEntity, $offset, $limit);
return $this->loadArrayFromStatement($assoc, $stmt);
@@ -1717,6 +1718,8 @@ class BasicEntityPersister implements EntityPersister
*/
private function getOneToManyStatement(array $assoc, $sourceEntity, $offset = null, $limit = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$criteria = array();
$parameters = array();
$owningAssoc = $this->class->associationMappings[$assoc['mappedBy']];
@@ -1930,7 +1933,7 @@ class BasicEntityPersister implements EntityPersister
*/
public function getSQLColumnAlias($columnName)
{
- return $this->quoteStrategy->getColumnAlias($columnName, $this->sqlAliasCounter++, $this->platform);
+ return $this->quoteStrategy->getColumnAlias($columnName, $this->currentPersisterContext->sqlAliasCounter++, $this->platform);
}
/**
@@ -1954,4 +1957,23 @@ class BasicEntityPersister implements EntityPersister
$sql = implode(' AND ', $filterClauses);
return $sql ? "(" . $sql . ")" : ""; // Wrap again to avoid "X or Y and FilterConditionSQL"
}
+
+ /**
+ * Switches persister context according to current query offset/limits
+ *
+ * This is due to the fact that to-many associations cannot be fetch-joined when a limit is involved
+ *
+ * @param null|int $offset
+ * @param null|int $limit
+ */
+ protected function switchPersisterContext($offset, $limit)
+ {
+ if (null === $offset && null === $limit) {
+ $this->currentPersisterContext = $this->noLimitsContext;
+
+ return;
+ }
+
+ $this->currentPersisterContext = $this->limitsHandlingContext;
+ }
}
diff --git a/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php b/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php
new file mode 100644
index 000000000..81fde938b
--- /dev/null
+++ b/lib/Doctrine/ORM/Persisters/Entity/CachedPersisterContext.php
@@ -0,0 +1,102 @@
+.
+ */
+
+namespace Doctrine\ORM\Persisters\Entity;
+use Doctrine\Common\Persistence\Mapping\ClassMetadata;
+use Doctrine\ORM\Query\ResultSetMapping;
+
+/**
+ * A swappable persister context to use as a container for the current
+ * generated query/resultSetMapping/type binding information.
+ *
+ * This class is a utility class to be used only by the persister API
+ *
+ * This object is highly mutable due to performance reasons. Same reasoning
+ * behind its properties being public.
+ *
+ * @author Marco Pivetta
+ */
+class CachedPersisterContext
+{
+ /**
+ * Metadata object that describes the mapping of the mapped entity class.
+ *
+ * @var \Doctrine\ORM\Mapping\ClassMetadata
+ */
+ public $class;
+
+ /**
+ * ResultSetMapping that is used for all queries. Is generated lazily once per request.
+ *
+ * @var \Doctrine\ORM\Query\ResultSetMapping
+ */
+ public $rsm;
+
+ /**
+ * The SELECT column list SQL fragment used for querying entities by this persister.
+ * This SQL fragment is only generated once per request, if at all.
+ *
+ * @var string|null
+ */
+ public $selectColumnListSql;
+
+ /**
+ * The JOIN SQL fragment used to eagerly load all many-to-one and one-to-one
+ * associations configured as FETCH_EAGER, as well as all inverse one-to-one associations.
+ *
+ * @var string
+ */
+ public $selectJoinSql;
+
+ /**
+ * Counter for creating unique SQL table and column aliases.
+ *
+ * @var integer
+ */
+ public $sqlAliasCounter = 0;
+
+ /**
+ * Map from class names (FQCN) to the corresponding generated SQL table aliases.
+ *
+ * @var array
+ */
+ public $sqlTableAliases = array();
+
+ /**
+ * Whether this persistent context is considering limit operations applied to the selection queries
+ *
+ * @var bool
+ */
+ public $handlesLimits;
+
+ /**
+ * @param ClassMetadata $class
+ * @param ResultSetMapping $rsm
+ * @param bool $handlesLimits
+ */
+ public function __construct(
+ ClassMetadata $class,
+ ResultSetMapping $rsm,
+ $handlesLimits
+ ) {
+ $this->class = $class;
+ $this->rsm = $rsm;
+ $this->handlesLimits = (bool) $handlesLimits;
+ }
+}
diff --git a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
index 019d987d5..a5bd84348 100644
--- a/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
+++ b/lib/Doctrine/ORM/Persisters/Entity/JoinedSubclassPersister.php
@@ -299,6 +299,8 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
*/
public function getSelectSQL($criteria, $assoc = null, $lockMode = null, $limit = null, $offset = null, array $orderBy = null)
{
+ $this->switchPersisterContext($offset, $limit);
+
$baseTableAlias = $this->getSQLTableAlias($this->class->name);
$joinSql = $this->getJoinSql($baseTableAlias);
@@ -420,19 +422,18 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
protected function getSelectColumnsSQL()
{
// Create the column list fragment only once
- if ($this->selectColumnListSql !== null) {
- return $this->selectColumnListSql;
+ if ($this->currentPersisterContext->selectColumnListSql !== null) {
+ return $this->currentPersisterContext->selectColumnListSql;
}
$columnList = array();
- $this->rsm = new ResultSetMapping();
$discrColumn = $this->class->discriminatorColumn['name'];
$baseTableAlias = $this->getSQLTableAlias($this->class->name);
$resultColumnName = $this->platform->getSQLResultCasing($discrColumn);
- $this->rsm->addEntityResult($this->class->name, 'r');
- $this->rsm->setDiscriminatorColumn('r', $resultColumnName);
- $this->rsm->addMetaResult('r', $resultColumnName, $discrColumn);
+ $this->currentPersisterContext->rsm->addEntityResult($this->class->name, 'r');
+ $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName);
+ $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn);
// Add regular columns
foreach ($this->class->fieldMappings as $fieldName => $mapping) {
@@ -523,9 +524,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
}
- $this->selectColumnListSql = implode(', ', $columnList);
+ $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
- return $this->selectColumnListSql;
+ return $this->currentPersisterContext->selectColumnListSql;
}
/**
diff --git a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php
index 23ebdf2d2..f9e4d5573 100644
--- a/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php
+++ b/lib/Doctrine/ORM/Persisters/Entity/SingleTablePersister.php
@@ -48,8 +48,8 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
*/
protected function getSelectColumnsSQL()
{
- if ($this->selectColumnListSql !== null) {
- return $this->selectColumnListSql;
+ if ($this->currentPersisterContext->selectColumnListSql !== null) {
+ return $this->currentPersisterContext->selectColumnListSql;
}
$columnList[] = parent::getSelectColumnsSQL();
@@ -63,8 +63,8 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
$resultColumnName = $this->platform->getSQLResultCasing($discrColumn);
- $this->rsm->setDiscriminatorColumn('r', $resultColumnName);
- $this->rsm->addMetaResult('r', $resultColumnName, $discrColumn);
+ $this->currentPersisterContext->rsm->setDiscriminatorColumn('r', $resultColumnName);
+ $this->currentPersisterContext->rsm->addMetaResult('r', $resultColumnName, $discrColumn);
// Append subclass columns
foreach ($this->class->subClasses as $subClassName) {
@@ -106,9 +106,9 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
}
- $this->selectColumnListSql = implode(', ', $columnList);
+ $this->currentPersisterContext->selectColumnListSql = implode(', ', $columnList);
- return $this->selectColumnListSql;
+ return $this->currentPersisterContext->selectColumnListSql;
}
/**
diff --git a/tests/Doctrine/Tests/Models/DDC3346/DDC3346Article.php b/tests/Doctrine/Tests/Models/DDC3346/DDC3346Article.php
new file mode 100644
index 000000000..dc8a876c5
--- /dev/null
+++ b/tests/Doctrine/Tests/Models/DDC3346/DDC3346Article.php
@@ -0,0 +1,27 @@
+useModelSet('ddc3346');
+
+ parent::setUp();
+
+ $this->loadAuthorFixture();
+ }
+
+ public function testFindOneWithEagerFetchWillNotHydrateLimitedCollection()
+ {
+ /* @var DDC3346Author $author */
+ $author = $this->_em->getRepository(DDC3346Author::CLASSNAME)->findOneBy(
+ array('username' => 'bwoogy')
+ );
+
+ $this->assertCount(2, $author->articles);
+ }
+
+ public function testFindLimitedWithEagerFetchWillNotHydrateLimitedCollection()
+ {
+ /* @var DDC3346Author[] $authors */
+ $authors = $this->_em->getRepository(DDC3346Author::CLASSNAME)->findBy(
+ array('username' => 'bwoogy'),
+ null,
+ 1
+ );
+
+ $this->assertCount(1, $authors);
+ $this->assertCount(2, $authors[0]->articles);
+ }
+
+ public function testFindWithEagerFetchAndOffsetWillNotHydrateLimitedCollection()
+ {
+ /* @var DDC3346Author[] $authors */
+ $authors = $this->_em->getRepository(DDC3346Author::CLASSNAME)->findBy(
+ array('username' => 'bwoogy'),
+ null,
+ null,
+ 0 // using an explicitly defined offset
+ );
+
+ $this->assertCount(1, $authors);
+ $this->assertCount(2, $authors[0]->articles);
+ }
+
+ private function loadAuthorFixture()
+ {
+ $user = new DDC3346Author();
+ $article1 = new DDC3346Article();
+ $article2 = new DDC3346Article();
+
+ $user->username = 'bwoogy';
+ $article1->user = $user;
+ $article2->user = $user;
+ $user->articles[] = $article1;
+ $user->articles[] = $article2;
+
+ $this->_em->persist($user);
+ $this->_em->persist($article1);
+ $this->_em->persist($article2);
+ $this->_em->flush();
+ $this->_em->clear();
+ }
+}
diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
index cfced6d61..f73ac54fc 100644
--- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php
+++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php
@@ -193,6 +193,10 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\DDC2504\DDC2504ChildClass',
'Doctrine\Tests\Models\DDC2504\DDC2504OtherClass',
),
+ 'ddc3346' => array(
+ 'Doctrine\Tests\Models\DDC3346\DDC3346Author',
+ 'Doctrine\Tests\Models\DDC3346\DDC3346Article',
+ ),
'quote' => array(
'Doctrine\Tests\Models\Quote\Address',
'Doctrine\Tests\Models\Quote\Group',
@@ -399,6 +403,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$conn->executeUpdate('DELETE FROM cache_country');
}
+ if (isset($this->_usedModelSets['ddc3346'])) {
+ $conn->executeUpdate('DELETE FROM ddc3346_articles');
+ $conn->executeUpdate('DELETE FROM ddc3346_users');
+ }
+
if (isset($this->_usedModelSets['quote'])) {
$conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-address"));
$conn->executeUpdate('DELETE FROM ' . $platform->quoteIdentifier("quote-group"));