Commit 96ef7eca authored by romanb's avatar romanb

[2.0] More small internal perf. improvements.

parent eea43915
......@@ -39,7 +39,7 @@ use \PDO;
abstract class AbstractHydrator
{
/** The ResultSetMapping. */
protected $_resultSetMapping;
protected $_rsm;
/** @var EntityManager The EntityManager instance. */
protected $_em;
......@@ -74,7 +74,7 @@ abstract class AbstractHydrator
public function iterate($stmt, $resultSetMapping)
{
$this->_stmt = $stmt;
$this->_resultSetMapping = $resultSetMapping;
$this->_rsm = $resultSetMapping;
$this->_prepare();
return new IterableResult($this);
}
......@@ -89,7 +89,7 @@ abstract class AbstractHydrator
public function hydrateAll($stmt, $resultSetMapping)
{
$this->_stmt = $stmt;
$this->_resultSetMapping = $resultSetMapping;
$this->_rsm = $resultSetMapping;
$this->_prepare();
$result = $this->_hydrateAll();
$this->_cleanup();
......@@ -127,7 +127,7 @@ abstract class AbstractHydrator
*/
protected function _cleanup()
{
$this->_resultSetMapping = null;
$this->_rsm = null;
$this->_stmt->closeCursor();
$this->_stmt = null;
}
......@@ -174,26 +174,26 @@ abstract class AbstractHydrator
foreach ($data as $key => $value) {
// Parse each column name only once. Cache the results.
if ( ! isset($cache[$key])) {
if (isset($this->_resultSetMapping->ignoredColumns[$key])) {
if (isset($this->_rsm->ignoredColumns[$key])) {
$cache[$key] = false;
} else if (isset($this->_resultSetMapping->scalarMappings[$key])) {
$cache[$key]['fieldName'] = $this->_resultSetMapping->getScalarAlias($key);
} else if (isset($this->_rsm->scalarMappings[$key])) {
$cache[$key]['fieldName'] = $this->_rsm->getScalarAlias($key);
$cache[$key]['isScalar'] = true;
} else if (isset($this->_resultSetMapping->fieldMappings[$key])) {
$classMetadata = $this->_resultSetMapping->getOwningClass($key);
$fieldName = $this->_resultSetMapping->fieldMappings[$key];
} else if (isset($this->_rsm->fieldMappings[$key])) {
$classMetadata = $this->_rsm->getOwningClass($key);
$fieldName = $this->_rsm->fieldMappings[$key];
$classMetadata = $this->_lookupDeclaringClass($classMetadata, $fieldName);
$cache[$key]['fieldName'] = $fieldName;
$cache[$key]['isScalar'] = false;
$cache[$key]['type'] = Type::getType($classMetadata->getTypeOfField($fieldName));
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->columnOwnerMap[$key];
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
} else {
// Discriminator column
$cache[$key]['isDiscriminator'] = true;
$cache[$key]['isScalar'] = false;
$cache[$key]['fieldName'] = $key;
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->columnOwnerMap[$key];
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
}
}
......@@ -245,20 +245,20 @@ abstract class AbstractHydrator
foreach ($data as $key => $value) {
// Parse each column name only once. Cache the results.
if ( ! isset($cache[$key])) {
if (isset($this->_resultSetMapping->ignoredColumns[$key])) {
if (isset($this->_rsm->ignoredColumns[$key])) {
$cache[$key] = false;
continue;
} else if (isset($this->_resultSetMapping->scalarMappings[$key])) {
$cache[$key]['fieldName'] = $this->_resultSetMapping->scalarMappings[$key];
} else if (isset($this->_rsm->scalarMappings[$key])) {
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
$cache[$key]['isScalar'] = true;
} else {
$classMetadata = $this->_resultSetMapping->getOwningClass($key);
$fieldName = $this->_resultSetMapping->fieldMappings[$key];
$classMetadata = $this->_rsm->getOwningClass($key);
$fieldName = $this->_rsm->fieldMappings[$key];
$classMetadata = $this->_lookupDeclaringClass($classMetadata, $fieldName);
$cache[$key]['fieldName'] = $fieldName;
$cache[$key]['isScalar'] = false;
$cache[$key]['type'] = Type::getType($classMetadata->getTypeOfField($fieldName));
$cache[$key]['dqlAlias'] = $this->_resultSetMapping->columnOwnerMap[$key];
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
}
}
......@@ -283,8 +283,8 @@ abstract class AbstractHydrator
*/
protected function _getCustomIndexField($alias)
{
return isset($this->_resultSetMapping->indexByMap[$alias]) ?
$this->_resultSetMapping->indexByMap[$alias] : null;
return isset($this->_rsm->indexByMap[$alias]) ?
$this->_rsm->indexByMap[$alias] : null;
}
/**
......
......@@ -40,12 +40,12 @@ class ArrayHydrator extends AbstractHydrator
/** @override */
protected function _prepare()
{
$this->_isSimpleQuery = $this->_resultSetMapping->getEntityResultCount() <= 1;
$this->_isSimpleQuery = $this->_rsm->getEntityResultCount() <= 1;
$this->_identifierMap = array();
$this->_resultPointers = array();
$this->_idTemplate = array();
$this->_resultCounter = 0;
foreach ($this->_resultSetMapping->getAliasMap() as $dqlAlias => $class) {
foreach ($this->_rsm->getAliasMap() as $dqlAlias => $class) {
$this->_identifierMap[$dqlAlias] = array();
$this->_resultPointers[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
......@@ -88,17 +88,17 @@ class ArrayHydrator extends AbstractHydrator
foreach ($rowData as $dqlAlias => $data) {
$index = false;
if (isset($this->_resultSetMapping->parentAliasMap[$dqlAlias])) {
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
// It's a joined result
$parent = $this->_resultSetMapping->parentAliasMap[$dqlAlias];
$relation = $this->_resultSetMapping->relationMap[$dqlAlias];
$parent = $this->_rsm->parentAliasMap[$dqlAlias];
$relation = $this->_rsm->relationMap[$dqlAlias];
$relationAlias = $relation->getSourceFieldName();
$path = $parent . '.' . $dqlAlias;
// Get a reference to the right element in the result tree.
// This element will get the associated element attached.
if ($this->_resultSetMapping->isMixed && isset($this->_rootAliases[$parent])) {
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) {
$key = key(reset($this->_resultPointers));
// TODO: Exception if $key === null ?
$baseElement =& $this->_resultPointers[$parent][$key];
......@@ -155,14 +155,14 @@ class ArrayHydrator extends AbstractHydrator
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $rowData[$dqlAlias];
if ($field = $this->_getCustomIndexField($dqlAlias)) {
if ($this->_resultSetMapping->isMixed) {
if ($this->_rsm->isMixed) {
$result[] = array($element[$field] => $element);
++$this->_resultCounter;
} else {
$result[$element[$field]] = $element;
}
} else {
if ($this->_resultSetMapping->isMixed) {
if ($this->_rsm->isMixed) {
$result[] = array($element);
++$this->_resultCounter;
} else {
......
......@@ -33,55 +33,69 @@ use Doctrine\Common\Collections\Collection;
*/
class ObjectHydrator extends AbstractHydrator
{
/* TODO: Consider unifying _collections and _initializedRelations */
/** Collections initialized by the hydrator */
private $_collections = array();
/** Memory for initialized relations */
private $_initializedRelations = array();
/*
* These two properties maintain their values between hydration runs.
*/
private $_classMetadatas = array();
private $_rootAliases = array();
private $_discriminatorMap = array();
/*
* The following parts are reinitialized on every hydration run.
*/
private $_isSimpleQuery = false;
private $_allowPartialObjects = false;
private $_identifierMap = array();
private $_resultPointers = array();
private $_idTemplate = array();
private $_resultCounter = 0;
private $_discriminatorMap = array();
private $_rootAliases = array();
private $_fetchedAssociations = array();
/* TODO: Consider unifying _collections and _initializedRelations */
/** Collections initialized by the hydrator */
private $_collections = array();
/** Memory for initialized relations */
private $_initializedRelations = array();
/** @override */
protected function _prepare()
{
$this->_isSimpleQuery = count($this->_resultSetMapping->aliasMap) <= 1;
$this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1;
$this->_allowPartialObjects = $this->_em->getConfiguration()->getAllowPartialObjects();
$this->_identifierMap = array();
$this->_resultPointers = array();
$this->_idTemplate = array();
$this->_resultCounter = 0;
foreach ($this->_resultSetMapping->aliasMap as $dqlAlias => $class) {
$this->_fetchedAssociations = array();
foreach ($this->_rsm->aliasMap as $dqlAlias => $class) {
$this->_identifierMap[$dqlAlias] = array();
$this->_resultPointers[$dqlAlias] = array();
$this->_idTemplate[$dqlAlias] = '';
$this->_classMetadatas[$class->name] = $class;
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
$this->_discriminatorMap[$class->name][$class->discriminatorValue] = $class->name;
foreach (array_merge($class->parentClasses, $class->subClasses) as $className) {
$otherClass = $this->_em->getClassMetadata($className);
$value = $otherClass->discriminatorValue;
$this->_classMetadatas[$className] = $otherClass;
$this->_discriminatorMap[$class->name][$value] = $className;
if ( ! isset($this->_classMetadatas[$class->name])) {
$this->_classMetadatas[$class->name] = $class;
// Gather class descriptors and discriminator values of subclasses, if necessary
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined()) {
$this->_discriminatorMap[$class->name][$class->discriminatorValue] = $class->name;
foreach (array_merge($class->parentClasses, $class->subClasses) as $className) {
$otherClass = $this->_em->getClassMetadata($className);
$value = $otherClass->discriminatorValue;
$this->_classMetadatas[$className] = $otherClass;
$this->_discriminatorMap[$class->name][$value] = $className;
}
}
}
if (isset($this->_resultSetMapping->relationMap[$dqlAlias])) {
$assoc = $this->_resultSetMapping->relationMap[$dqlAlias];
$this->_fetchedAssociations[$assoc->getSourceEntityName()][$assoc->getSourceFieldName()] = true;
if ($mappedByField = $assoc->getMappedByFieldName()) {
$this->_fetchedAssociations[$assoc->getTargetEntityName()][$mappedByField] = true;
} else if ($inverseAssoc = $this->_em->getClassMetadata($assoc->getTargetEntityName())
->inverseMappings[$assoc->getSourceFieldName()]) {
$this->_fetchedAssociations[$assoc->getTargetEntityName()][
$inverseAssoc->getSourceFieldName()
// Remember which classes are "fetch joined"
if (isset($this->_rsm->relationMap[$dqlAlias])) {
$assoc = $this->_rsm->relationMap[$dqlAlias];
$this->_fetchedAssociations[$assoc->getSourceEntityName()][$assoc->sourceFieldName] = true;
if ($mappedByField = $assoc->mappedByFieldName) {
$this->_fetchedAssociations[$assoc->targetEntityName][$mappedByField] = true;
} else if ($inverseAssoc = $this->_em->getClassMetadata($assoc->targetEntityName)
->inverseMappings[$assoc->sourceFieldName]) {
$this->_fetchedAssociations[$assoc->targetEntityName][
$inverseAssoc->sourceFieldName
] = true;
}
}
......@@ -97,7 +111,7 @@ class ObjectHydrator extends AbstractHydrator
{
$s = microtime(true);
if ($this->_resultSetMapping->isMixed) {
if ($this->_rsm->isMixed) {
$result = array();
} else {
$result = new Collection;
......@@ -184,7 +198,7 @@ class ObjectHydrator extends AbstractHydrator
$classMetadata = $this->_classMetadatas[get_class($entity)];
$relation = $classMetadata->getAssociationMapping($name);
$relatedClass = $this->_em->getClassMetadata($relation->getTargetEntityName());
$relatedClass = $this->_em->getClassMetadata($relation->targetEntityName);
$coll = $this->getCollection($relatedClass);
$coll->setOwner($entity, $relation);
......@@ -226,8 +240,8 @@ class ObjectHydrator extends AbstractHydrator
private function getEntity(array $data, $className)
{
if (isset($this->_resultSetMapping->discriminatorColumns[$className])) {
$discrColumn = $this->_resultSetMapping->discriminatorColumns[$className];
if (isset($this->_rsm->discriminatorColumns[$className])) {
$discrColumn = $this->_rsm->discriminatorColumns[$className];
$className = $this->_discriminatorMap[$className][$data[$discrColumn]];
unset($data[$discrColumn]);
}
......@@ -241,15 +255,16 @@ class ObjectHydrator extends AbstractHydrator
if ($assoc->isLazilyFetched()) {
// Inject proxy
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
$this->_classMetadatas[$className]->setFieldValue($entity, $field, $proxy);
$this->_classMetadatas[$className]->reflFields[$field]->setValue($entity, $proxy);
} else {
//TODO: Schedule for eager fetching?
}
} else {
// Inject collection
$this->_classMetadatas[$className]->reflFields[$field]
->setValue($entity, new PersistentCollection($this->_em,
$this->_em->getClassMetadata($assoc->getTargetEntityName())
->setValue($entity, new PersistentCollection(
$this->_em,
$this->_em->getClassMetadata($assoc->targetEntityName)
));
}
}
......@@ -287,16 +302,16 @@ class ObjectHydrator extends AbstractHydrator
$this->_uow->setOriginalEntityProperty(spl_object_hash($entity1), $property, $entity2);
$relation = $classMetadata1->getAssociationMapping($property);
if ($relation->isOneToOne()) {
$targetClass = $this->_classMetadatas[$relation->getTargetEntityName()];
$targetClass = $this->_classMetadatas[$relation->targetEntityName];
if ($relation->isOwningSide()) {
// If there is an inverse mapping on the target class its bidirectional
if ($targetClass->hasInverseAssociationMapping($property)) {
$sourceProp = $targetClass->inverseMappings[$fieldName]->getSourceFieldName();
if (isset($targetClass->inverseMappings[$property])) {
$sourceProp = $targetClass->inverseMappings[$fieldName]->sourceFieldName;
$targetClass->reflFields[$sourceProp]->setValue($entity2, $entity1);
}
} else {
// For sure bidirectional, as there is no inverse side in unidirectional
$targetClass->reflFields[$relation->getMappedByFieldName()]->setValue($entity2, $entity1);
$targetClass->reflFields[$relation->mappedByFieldName]->setValue($entity2, $entity1);
}
}
}
......@@ -322,18 +337,18 @@ class ObjectHydrator extends AbstractHydrator
// Hydrate the entity data found in the current row.
foreach ($rowData as $dqlAlias => $data) {
$index = false;
$entityName = $this->_resultSetMapping->aliasMap[$dqlAlias]->name;
$entityName = $this->_rsm->aliasMap[$dqlAlias]->name;
if (isset($this->_resultSetMapping->parentAliasMap[$dqlAlias])) {
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
// It's a joined result
$parent = $this->_resultSetMapping->parentAliasMap[$dqlAlias];
$relation = $this->_resultSetMapping->relationMap[$dqlAlias];
$relationAlias = $relation->getSourceFieldName();
$parent = $this->_rsm->parentAliasMap[$dqlAlias];
$relation = $this->_rsm->relationMap[$dqlAlias];
$relationAlias = $relation->sourceFieldName;
// Get a reference to the right element in the result tree.
// This element will get the associated element attached.
if ($this->_resultSetMapping->isMixed && isset($this->_rootAliases[$parent])) {
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) {
$key = key(reset($this->_resultPointers));
// TODO: Exception if $key === null ?
$baseElement =& $this->_resultPointers[$parent][$key];
......@@ -363,12 +378,11 @@ class ObjectHydrator extends AbstractHydrator
// If it's a bi-directional many-to-many, also initialize the reverse collection.
if ($relation->isManyToMany()) {
if ($relation->isOwningSide()) {
$reverseAssoc = $this->_classMetadatas[$entityName]
->inverseMappings[$relationAlias];
$reverseAssoc = $this->_classMetadatas[$entityName]->inverseMappings[$relationAlias];
if ($reverseAssoc) {
$this->initRelatedCollection($element, $reverseAssoc->getSourceFieldName());
$this->initRelatedCollection($element, $reverseAssoc->sourceFieldName);
}
} else if ($mappedByField = $relation->getMappedByFieldName()) {
} else if ($mappedByField = $relation->mappedByFieldName) {
$this->initRelatedCollection($element, $mappedByField);
}
}
......@@ -421,7 +435,7 @@ class ObjectHydrator extends AbstractHydrator
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $this->getEntity($rowData[$dqlAlias], $entityName);
if ($field = $this->_getCustomIndexField($dqlAlias)) {
if ($this->_resultSetMapping->isMixed) {
if ($this->_rsm->isMixed) {
$result[] = array(
$this->_classMetadatas[$entityName]
->reflFields[$field]
......@@ -434,7 +448,7 @@ class ObjectHydrator extends AbstractHydrator
->getValue($element));
}
} else {
if ($this->_resultSetMapping->isMixed) {
if ($this->_rsm->isMixed) {
$result[] = array($element);
++$this->_resultCounter;
} else {
......
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Internal\Hydration;
......@@ -11,7 +26,7 @@ use \PDO;
/**
* Description of SingleScalarHydrator
*
* @author robo
* @author Roman Borschel <roman@code-factory.org>
*/
class SingleScalarHydrator extends AbstractHydrator
{
......
......@@ -24,6 +24,14 @@ namespace Doctrine\ORM\Mapping;
/**
* Base class for association mappings.
*
* <b>IMPORTANT NOTE:</b>
*
* The fields of this class are only public for 2 reasons:
* 1) To allow fast, internal READ access.
* 2) To drastically reduce the size of a serialized instance (private/protected members
* get the whole class name, namespace inclusive, prepended to every property in
* the serialized representation).
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
......@@ -47,18 +55,18 @@ abstract class AssociationMapping
'merge'
);
protected $_cascades = array();
protected $_isCascadeDelete;
protected $_isCascadeSave;
protected $_isCascadeRefresh;
protected $_isCascadeMerge;
public $cascades = array();
public $isCascadeDelete;
public $isCascadeSave;
public $isCascadeRefresh;
public $isCascadeMerge;
/**
* The fetch mode used for the association.
*
* @var integer
*/
protected $_fetchMode = self::FETCH_MANUAL;
public $fetchMode = self::FETCH_MANUAL;
/**
* Flag that indicates whether the class that defines this mapping is
......@@ -66,7 +74,7 @@ abstract class AssociationMapping
*
* @var boolean
*/
protected $_isOwningSide = true;
public $isOwningSide = true;
/**
* Whether the association is optional (0..X) or not (1..X).
......@@ -74,14 +82,14 @@ abstract class AssociationMapping
*
* @var boolean
*/
protected $_isOptional = true;
public $isOptional = true;
/**
* The name of the source Entity (the Entity that defines this mapping).
*
* @var string
*/
protected $_sourceEntityName;
public $sourceEntityName;
/**
* The name of the target Entity (the Enitity that is the target of the
......@@ -89,7 +97,7 @@ abstract class AssociationMapping
*
* @var string
*/
protected $_targetEntityName;
public $targetEntityName;
/**
* Identifies the field on the source class (the class this AssociationMapping
......@@ -98,7 +106,7 @@ abstract class AssociationMapping
*
* @var string
*/
protected $_sourceFieldName;
public $sourceFieldName;
/**
* Identifies the field on the owning side that controls the mapping for the
......@@ -106,14 +114,14 @@ abstract class AssociationMapping
*
* @var string
*/
protected $_mappedByFieldName;
public $mappedByFieldName;
/**
* The join table definition, if any.
*
* @var array
*/
protected $_joinTable = array();
public $joinTable = array();
//protected $_joinTableInsertSql;
......@@ -138,34 +146,38 @@ abstract class AssociationMapping
if ( ! isset($mapping['fieldName'])) {
throw MappingException::missingFieldName();
}
$this->_sourceFieldName = $mapping['fieldName'];
$this->sourceFieldName = $mapping['fieldName'];
if ( ! isset($mapping['sourceEntity'])) {
throw MappingException::missingSourceEntity($mapping['fieldName']);
}
$this->_sourceEntityName = $mapping['sourceEntity'];
$this->sourceEntityName = $mapping['sourceEntity'];
if ( ! isset($mapping['targetEntity'])) {
throw MappingException::missingTargetEntity($mapping['fieldName']);
}
$this->_targetEntityName = $mapping['targetEntity'];
$this->targetEntityName = $mapping['targetEntity'];
// Mandatory and optional attributes for either side
if ( ! isset($mapping['mappedBy'])) {
// Optional
if (isset($mapping['joinTable'])) {
$this->_joinTable = $mapping['joinTable'];
$this->joinTable = $mapping['joinTable'];
}
} else {
$this->_isOwningSide = false;
$this->_mappedByFieldName = $mapping['mappedBy'];
$this->isOwningSide = false;
$this->mappedByFieldName = $mapping['mappedBy'];
}
// Optional attributes for both sides
$this->_isOptional = isset($mapping['optional']) ?
$this->isOptional = isset($mapping['optional']) ?
(bool)$mapping['optional'] : true;
$this->_cascades = isset($mapping['cascade']) ?
$this->cascades = isset($mapping['cascade']) ?
(array)$mapping['cascade'] : array();
$this->isCascadeDelete = in_array('delete', $this->cascades);
$this->isCascadeSave = in_array('save', $this->cascades);
$this->isCascadeRefresh = in_array('refresh', $this->cascades);
$this->isCascadeMerge = in_array('merge', $this->cascades);
}
/**
......@@ -176,10 +188,7 @@ abstract class AssociationMapping
*/
public function isCascadeDelete()
{
if ($this->_isCascadeDelete === null) {
$this->_isCascadeDelete = in_array('delete', $this->_cascades);
}
return $this->_isCascadeDelete;
return $this->isCascadeDelete;
}
/**
......@@ -190,10 +199,7 @@ abstract class AssociationMapping
*/
public function isCascadeSave()
{
if ($this->_isCascadeSave === null) {
$this->_isCascadeSave = in_array('save', $this->_cascades);
}
return $this->_isCascadeSave;
return $this->isCascadeSave;
}
/**
......@@ -204,10 +210,7 @@ abstract class AssociationMapping
*/
public function isCascadeRefresh()
{
if ($this->_isCascadeRefresh === null) {
$this->_isCascadeRefresh = in_array('refresh', $this->_cascades);
}
return $this->_isCascadeRefresh;
return $this->isCascadeRefresh;
}
/**
......@@ -218,10 +221,7 @@ abstract class AssociationMapping
*/
public function isCascadeMerge()
{
if ($this->_isCascadeMerge === null) {
$this->_isCascadeMerge = in_array('merge', $this->_cascades);
}
return $this->_isCascadeMerge;
return $this->isCascadeMerge;
}
/**
......@@ -231,7 +231,7 @@ abstract class AssociationMapping
*/
public function isEagerlyFetched()
{
return $this->_fetchMode == self::FETCH_EAGER;
return $this->fetchMode == self::FETCH_EAGER;
}
/**
......@@ -241,7 +241,7 @@ abstract class AssociationMapping
*/
public function isLazilyFetched()
{
return $this->_fetchMode == self::FETCH_LAZY;
return $this->fetchMode == self::FETCH_LAZY;
}
/**
......@@ -251,7 +251,7 @@ abstract class AssociationMapping
*/
public function isManuallyFetched()
{
return $this->_fetchMode == self::FETCH_MANUAL;
return $this->fetchMode == self::FETCH_MANUAL;
}
/**
......@@ -261,7 +261,7 @@ abstract class AssociationMapping
*/
public function isOwningSide()
{
return $this->_isOwningSide;
return $this->isOwningSide;
}
/**
......@@ -271,7 +271,7 @@ abstract class AssociationMapping
*/
public function isInverseSide()
{
return ! $this->_isOwningSide;
return ! $this->isOwningSide;
}
/**
......@@ -282,7 +282,7 @@ abstract class AssociationMapping
*/
public function isOptional()
{
return $this->_isOptional;
return $this->isOptional;
}
/**
......@@ -292,7 +292,7 @@ abstract class AssociationMapping
*/
public function getSourceEntityName()
{
return $this->_sourceEntityName;
return $this->sourceEntityName;
}
/**
......@@ -302,7 +302,7 @@ abstract class AssociationMapping
*/
public function getTargetEntityName()
{
return $this->_targetEntityName;
return $this->targetEntityName;
}
/**
......@@ -312,7 +312,7 @@ abstract class AssociationMapping
*/
public function getJoinTable()
{
return $this->_joinTable;
return $this->joinTable;
}
/**
......@@ -322,7 +322,7 @@ abstract class AssociationMapping
*/
public function getSourceFieldName()
{
return $this->_sourceFieldName;
return $this->sourceFieldName;
}
/**
......@@ -334,7 +334,7 @@ abstract class AssociationMapping
*/
public function getMappedByFieldName()
{
return $this->_mappedByFieldName;
return $this->mappedByFieldName;
}
/**
......@@ -374,7 +374,7 @@ abstract class AssociationMapping
*/
public function usesJoinTable()
{
return (bool)$this->_joinTable;
return (bool)$this->joinTable;
}
/**
......
......@@ -36,8 +36,6 @@ use Doctrine\Common\DoctrineException;
* get the whole class name, namespace inclusive, prepended to every property in
* the serialized representation).
*
* !! Do NOT write/modify the public properties directly. Go through the public API. !!
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
......
......@@ -25,6 +25,14 @@ namespace Doctrine\ORM\Mapping;
* A many-to-many mapping describes the mapping between two collections of
* entities.
*
* <b>IMPORTANT NOTE:</b>
*
* The fields of this class are only public for 2 reasons:
* 1) To allow fast, internal READ access.
* 2) To drastically reduce the size of a serialized instance (private/protected members
* get the whole class name, namespace inclusive, prepended to every property in
* the serialized representation).
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
......@@ -33,27 +41,27 @@ class ManyToManyMapping extends AssociationMapping
/**
* The key columns of the source table.
*/
private $_sourceKeyColumns = array();
public $sourceKeyColumns = array();
/**
* The key columns of the target table.
*/
private $_targetKeyColumns = array();
public $targetKeyColumns = array();
/**
* Maps the columns in the source table to the columns in the relation table.
*/
private $_sourceToRelationKeyColumns = array();
public $sourceToRelationKeyColumns = array();
/**
* Maps the columns in the target table to the columns in the relation table.
*/
private $_targetToRelationKeyColumns = array();
public $targetToRelationKeyColumns = array();
/**
* The columns on the join table.
*/
private $_joinTableColumns = array();
public $joinTableColumns = array();
/**
* Initializes a new ManyToManyMapping.
......@@ -85,46 +93,46 @@ class ManyToManyMapping extends AssociationMapping
throw MappingException::invalidMapping($this->_sourceFieldName);
}
foreach ($mapping['joinTable']['joinColumns'] as $joinColumn) {
$this->_sourceToRelationKeyColumns[$joinColumn['referencedColumnName']] = $joinColumn['name'];
$this->_joinTableColumns[] = $joinColumn['name'];
$this->sourceToRelationKeyColumns[$joinColumn['referencedColumnName']] = $joinColumn['name'];
$this->joinTableColumns[] = $joinColumn['name'];
}
$this->_sourceKeyColumns = array_keys($this->_sourceToRelationKeyColumns);
$this->sourceKeyColumns = array_keys($this->sourceToRelationKeyColumns);
// owning side MUST specify inverseJoinColumns
if ( ! isset($mapping['joinTable']['inverseJoinColumns'])) {
throw MappingException::invalidMapping($this->_sourceFieldName);
}
foreach ($mapping['joinTable']['inverseJoinColumns'] as $inverseJoinColumn) {
$this->_targetToRelationKeyColumns[$inverseJoinColumn['referencedColumnName']] = $inverseJoinColumn['name'];
$this->_joinTableColumns[] = $inverseJoinColumn['name'];
$this->targetToRelationKeyColumns[$inverseJoinColumn['referencedColumnName']] = $inverseJoinColumn['name'];
$this->joinTableColumns[] = $inverseJoinColumn['name'];
}
$this->_targetKeyColumns = array_keys($this->_targetToRelationKeyColumns);
$this->targetKeyColumns = array_keys($this->targetToRelationKeyColumns);
}
}
public function getJoinTableColumns()
{
return $this->_joinTableColumns;
return $this->joinTableColumns;
}
public function getSourceToRelationKeyColumns()
{
return $this->_sourceToRelationKeyColumns;
return $this->sourceToRelationKeyColumns;
}
public function getTargetToRelationKeyColumns()
{
return $this->_targetToRelationKeyColumns;
return $this->targetToRelationKeyColumns;
}
public function getSourceKeyColumns()
{
return $this->_sourceKeyColumns;
return $this->sourceKeyColumns;
}
public function getTargetKeyColumns()
{
return $this->_targetKeyColumns;
return $this->targetKeyColumns;
}
public function lazyLoadFor($entity, $entityManager)
......
......@@ -29,6 +29,14 @@ namespace Doctrine\ORM\Mapping;
* In other words, the many-side MUST be the owning side and the one-side MUST be
* the inverse side.
*
* <b>IMPORTANT NOTE:</b>
*
* The fields of this class are only public for 2 reasons:
* 1) To allow fast, internal READ access.
* 2) To drastically reduce the size of a serialized instance (private/protected members
* get the whole class name, namespace inclusive, prepended to every property in
* the serialized representation).
*
* @author Roman Borschel <roman@code-factory.org>
* @since 2.0
*/
......@@ -51,7 +59,7 @@ class OneToManyMapping extends AssociationMapping
//protected $_sourceKeysToTargetForeignKeys;
/** Whether to delete orphaned elements (removed from the collection) */
private $_deleteOrphans = false;
public $deleteOrphans = false;
/**
* Initializes a new OneToManyMapping.
......@@ -79,7 +87,7 @@ class OneToManyMapping extends AssociationMapping
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
}
$this->_deleteOrphans = isset($mapping['deleteOrphans']) ?
$this->deleteOrphans = isset($mapping['deleteOrphans']) ?
(bool)$mapping['deleteOrphans'] : false;
}
......@@ -90,7 +98,7 @@ class OneToManyMapping extends AssociationMapping
*/
public function shouldDeleteOrphans()
{
return $this->_deleteOrphans;
return $this->deleteOrphans;
}
/**
......
......@@ -25,6 +25,14 @@ namespace Doctrine\ORM\Mapping;
* A one-to-one mapping describes a uni-directional mapping from one entity
* to another entity.
*
* <b>IMPORTANT NOTE:</b>
*
* The fields of this class are only public for 2 reasons:
* 1) To allow fast, internal READ access.
* 2) To drastically reduce the size of a serialized instance (private/protected members
* get the whole class name, namespace inclusive, prepended to every property in
* the serialized representation).
*
* @since 2.0
* @author Roman Borschel <roman@code-factory.org>
*/
......@@ -35,28 +43,28 @@ class OneToOneMapping extends AssociationMapping
* i.e. source.id (pk) => target.user_id (fk).
* Reverse mapping of _targetToSourceKeyColumns.
*/
private $_sourceToTargetKeyColumns = array();
public $sourceToTargetKeyColumns = array();
/**
* Maps the target primary/foreign key columns to the source foreign/primary key columns.
* i.e. target.user_id (fk) => source.id (pk).
* Reverse mapping of _sourceToTargetKeyColumns.
*/
private $_targetToSourceKeyColumns = array();
public $targetToSourceKeyColumns = array();
/**
* Whether to delete orphaned elements (when nulled out, i.e. $foo->other = null)
*
* @var boolean
*/
private $_deleteOrphans = false;
public $deleteOrphans = false;
/**
* The join column definitions.
*
* @var array
*/
private $_joinColumns = array();
public $joinColumns = array();
/**
* Creates a new OneToOneMapping.
......@@ -83,14 +91,14 @@ class OneToOneMapping extends AssociationMapping
if ( ! isset($mapping['joinColumns'])) {
throw MappingException::invalidMapping($this->_sourceFieldName);
}
$this->_joinColumns = $mapping['joinColumns'];
$this->joinColumns = $mapping['joinColumns'];
foreach ($mapping['joinColumns'] as $joinColumn) {
$this->_sourceToTargetKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
$this->sourceToTargetKeyColumns[$joinColumn['name']] = $joinColumn['referencedColumnName'];
}
$this->_targetToSourceKeyColumns = array_flip($this->_sourceToTargetKeyColumns);
$this->targetToSourceKeyColumns = array_flip($this->sourceToTargetKeyColumns);
}
$this->_deleteOrphans = isset($mapping['deleteOrphans']) ?
$this->deleteOrphans = isset($mapping['deleteOrphans']) ?
(bool)$mapping['deleteOrphans'] : false;
return $mapping;
......@@ -103,7 +111,7 @@ class OneToOneMapping extends AssociationMapping
*/
public function getJoinColumns()
{
return $this->_joinColumns;
return $this->joinColumns;
}
/**
......@@ -113,7 +121,7 @@ class OneToOneMapping extends AssociationMapping
*/
public function getSourceToTargetKeyColumns()
{
return $this->_sourceToTargetKeyColumns;
return $this->sourceToTargetKeyColumns;
}
/**
......@@ -123,7 +131,7 @@ class OneToOneMapping extends AssociationMapping
*/
public function getTargetToSourceKeyColumns()
{
return $this->_targetToSourceKeyColumns;
return $this->targetToSourceKeyColumns;
}
/**
......@@ -146,31 +154,31 @@ class OneToOneMapping extends AssociationMapping
*/
public function load($owningEntity, $targetEntity, $em)
{
$sourceClass = $em->getClassMetadata($this->_sourceEntityName);
$targetClass = $em->getClassMetadata($this->_targetEntityName);
$sourceClass = $em->getClassMetadata($this->sourceEntityName);
$targetClass = $em->getClassMetadata($this->targetEntityName);
$conditions = array();
if ($this->_isOwningSide) {
foreach ($this->_sourceToTargetKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
if ($this->isOwningSide) {
foreach ($this->sourceToTargetKeyColumns as $sourceKeyColumn => $targetKeyColumn) {
$conditions[$targetKeyColumn] = $sourceClass->getReflectionProperty(
$sourceClass->getFieldName($sourceKeyColumn))->getValue($owningEntity);
}
if ($targetClass->hasInverseAssociation($this->_sourceFieldName)) {
if ($targetClass->hasInverseAssociation($this->sourceFieldName)) {
$targetClass->setFieldValue(
$targetEntity,
$targetClass->inverseMappings[$this->_sourceFieldName]->getSourceFieldName(),
$owningEntity);
}
} else {
$owningAssoc = $em->getClassMetadata($this->_targetEntityName)->getAssociationMapping($this->_mappedByFieldName);
$owningAssoc = $em->getClassMetadata($this->targetEntityName)->getAssociationMapping($this->mappedByFieldName);
foreach ($owningAssoc->getTargetToSourceKeyColumns() as $targetKeyColumn => $sourceKeyColumn) {
$conditions[$sourceKeyColumn] = $sourceClass->getReflectionProperty(
$sourceClass->getFieldName($targetKeyColumn))->getValue($owningEntity);
}
$targetClass->setFieldValue($targetEntity, $this->_mappedByFieldName, $owningEntity);
$targetClass->setFieldValue($targetEntity, $this->mappedByFieldName, $owningEntity);
}
$em->getUnitOfWork()->getEntityPersister($this->_targetEntityName)->load($conditions, $targetEntity);
$em->getUnitOfWork()->getEntityPersister($this->targetEntityName)->load($conditions, $targetEntity);
}
}
\ No newline at end of file
......@@ -272,12 +272,11 @@ abstract class AbstractEntityPersister
$entity = $this->_em->getUnitOfWork()->createEntity($this->_entityName, $data);
} else {
foreach ($data as $field => $value) {
$this->_class->setFieldValue($entity, $field, $value);
$this->_class->reflFields[$field]->setValue($entity, $value);
}
$id = array();
if ($this->_class->isIdentifierComposite()) {
$identifierFieldNames = $this->_class->identifier;
foreach ($identifierFieldNames as $fieldName) {
foreach ($this->_class->identifier as $fieldName) {
$id[] = $data[$fieldName];
}
} else {
......@@ -292,15 +291,15 @@ abstract class AbstractEntityPersister
if ($assoc->isLazilyFetched()) {
// Inject proxy
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
$this->_class->setFieldValue($entity, $field, $proxy);
$this->_class->reflFields[$field]->setValue($entity, $proxy);
} else {
//TODO: Eager fetch?
}
} else {
// Inject collection
$this->_class->getReflectionProperty($field)
->setValue($entity, new PersistentCollection($this->_em,
$this->_em->getClassMetadata($assoc->getTargetEntityName())
$this->_class->reflFields[$field]->setValue(
$entity, new PersistentCollection($this->_em,
$this->_em->getClassMetadata($assoc->targetEntityName)
));
}
}
......@@ -318,8 +317,7 @@ abstract class AbstractEntityPersister
protected function _getSelectSingleEntitySql(array $criteria)
{
$columnList = '';
$columnNames = $this->_class->getColumnNames();
foreach ($columnNames as $column) {
foreach ($this->_class->columnNames as $column) {
if ($columnList != '') $columnList .= ', ';
$columnList .= $column;
}
......@@ -327,7 +325,7 @@ abstract class AbstractEntityPersister
$conditionSql = '';
foreach ($criteria as $field => $value) {
if ($conditionSql != '') $conditionSql .= ' AND ';
$conditionSql .= $this->_class->getColumnName($field) . ' = ?';
$conditionSql .= $this->_class->columnNames[$field] . ' = ?';
}
return 'SELECT ' . $columnList . ' FROM ' . $this->_class->getTableName()
......
......@@ -65,38 +65,75 @@ class ResultSetMapping
$this->aliasMap[$alias] = $class;
}
/**
*
* @param <type> $className
* @param <type> $alias
* @param <type> $discrColumn
*/
public function setDiscriminatorColumn($className, $alias, $discrColumn)
{
$this->discriminatorColumns[$className] = $discrColumn;
$this->columnOwnerMap[$discrColumn] = $alias;
}
/**
*
* @param string $className
* @return string
*/
public function getDiscriminatorColumn($className)
{
return isset($this->discriminatorColumns[$className]) ?
$this->discriminatorColumns[$className] : null;
}
/**
*
* @param string $alias
* @param string $fieldName
*/
public function addIndexBy($alias, $fieldName)
{
$this->indexByMap[$alias] = $fieldName;
}
/**
*
* @param string $alias
* @return boolean
*/
public function hasIndexBy($alias)
{
return isset($this->indexByMap[$alias]);
}
/**
*
* @param string $alias
* @return string
*/
public function getIndexByField($alias)
{
return $this->indexByMap[$alias];
}
/**
*
* @param string $columnName
* @return boolean
*/
public function isFieldResult($columnName)
{
return isset($this->fieldMappings[$columnName]);
}
/**
*
* @param <type> $alias
* @param <type> $columnName
* @param <type> $fieldName
*/
public function addFieldResult($alias, $columnName, $fieldName)
{
$this->fieldMappings[$columnName] = $fieldName;
......@@ -106,6 +143,13 @@ class ResultSetMapping
}
}
/**
*
* @param <type> $class
* @param <type> $alias
* @param <type> $parentAlias
* @param <type> $relation
*/
public function addJoinedEntityResult($class, $alias, $parentAlias, $relation)
{
$this->aliasMap[$alias] = $class;
......@@ -164,11 +208,21 @@ class ResultSetMapping
return $this->aliasMap[$this->columnOwnerMap[$columnName]];
}
/**
*
* @param string $alias
* @return AssociationMapping
*/
public function getRelation($alias)
{
return $this->relationMap[$alias];
}
/**
*
* @param string $alias
* @return boolean
*/
public function isRelation($alias)
{
return isset($this->relationMap[$alias]);
......@@ -186,50 +240,77 @@ class ResultSetMapping
/**
*
* @param <type> $alias
* @return <type>
* @param string $alias
* @return string
*/
public function getParentAlias($alias)
{
return $this->parentAliasMap[$alias];
}
/**
*
* @param string $alias
* @return boolean
*/
public function hasParentAlias($alias)
{
return isset($this->parentAliasMap[$alias]);
}
/**
* Gets the field name for a column name.
*
* @param <type> $className
* @param <type> $columnName
* @return <type>
* @param string $columnName
* @return string
*/
public function getFieldName($columnName)
{
return $this->fieldMappings[$columnName];
}
/**
*
* @return array
*/
public function getAliasMap()
{
return $this->aliasMap;
}
/**
*
* @return integer
*/
public function getEntityResultCount()
{
return count($this->aliasMap);
}
/**
*
* @return boolean
*/
public function isMixedResult()
{
return $this->isMixed;
}
/**
* Adds a column name that will be ignored during hydration.
*
* @param string $columnName
*/
public function addIgnoredColumn($columnName)
{
$this->ignoredColumns[$columnName] = true;
}
/**
*
* @param string $columnName
* @return boolean
*/
public function isIgnoredColumn($columnName)
{
return isset($this->ignoredColumns[$columnName]);
......
......@@ -144,9 +144,9 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
}
/**
* [romanb: 10000 rows => 3.4 seconds]
* [romanb: 10000 rows => 3.8 seconds]
*
* MAXIMUM TIME: 4 seconds
* MAXIMUM TIME: 5 seconds
*/
public function testSimpleQueryObjectHydrationPerformance()
{
......@@ -192,7 +192,7 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
$stmt = new HydratorMockStatement($resultSet);
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
$this->setMaxRunningTime(4);
$this->setMaxRunningTime(5);
$result = $hydrator->hydrateAll($stmt, $rsm);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment