Commit c5bc8641 authored by romanb's avatar romanb

refactorings, a bug fix (#786) and improved performance for the hydration of...

refactorings, a bug fix (#786) and improved performance for the hydration of results from polymorphic queries.
parent ff91185d
......@@ -207,7 +207,6 @@ final class Doctrine
const ATTR_DEFAULT_PARAM_NAMESPACE = 156;
const ATTR_QUERY_CACHE = 157;
const ATTR_QUERY_CACHE_LIFESPAN = 158;
const ATTR_AUTOLOAD_TABLE_CLASSES = 160;
const ATTR_MODEL_LOADING = 161;
const ATTR_LOCK = 162;
const ATTR_HYDRATE = 163;
......
......@@ -46,9 +46,7 @@ class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
* Test if a cache is available for the given id and (if yes) return it (false else).
*
* @param string $id cache id
* @param boolean $testCacheValidity if set to false, the cache validity won't be tested
......@@ -56,11 +54,7 @@ class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
*/
public function fetch($id, $testCacheValidity = true)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
return $tmp[0];
}
return false;
return apc_fetch($id);
}
/**
......@@ -71,11 +65,7 @@ class Doctrine_Cache_Apc extends Doctrine_Cache_Driver
*/
public function contains($id)
{
$tmp = apc_fetch($id);
if (is_array($tmp)) {
return $tmp[1];
}
return false;
return apc_fetch($id) === false ? false : true;
}
/**
......
......@@ -38,9 +38,7 @@ class Doctrine_Cache_Array implements Countable, Doctrine_Cache_Interface
protected $data;
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
* Test if a cache is available for the given id and (if yes) return it (false else).
*
* @param string $id cache id
* @param boolean $testCacheValidity if set to false, the cache validity won't be tested
......
......@@ -67,9 +67,7 @@ class Doctrine_Cache_Db extends Doctrine_Cache_Driver implements Countable
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
* Test if a cache is available for the given id and (if yes) return it (false else).
*
* @param string $id cache id
* @param boolean $testCacheValidity if set to false, the cache validity won't be tested
......
......@@ -33,7 +33,7 @@
interface Doctrine_Cache_Interface
{
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
* Test if a cache entry is available for the given id and (if yes) return it (false else).
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
*
......
......@@ -72,9 +72,7 @@ class Doctrine_Cache_Memcache extends Doctrine_Cache_Driver
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
* Test if a cache is available for the given id and (if yes) return it (false else).
*
* @param string $id cache id
* @param boolean $testCacheValidity if set to false, the cache validity won't be tested
......
......@@ -39,7 +39,7 @@ class Doctrine_Cache_Xcache extends Doctrine_Cache_Driver
*/
public function __construct($options = array())
{
if ( !extension_loaded('xcache') ) {
if ( ! extension_loaded('xcache')) {
throw new Doctrine_Cache_Exception('In order to use Xcache driver, the xcache extension must be loaded.');
}
......@@ -47,9 +47,7 @@ class Doctrine_Cache_Xcache extends Doctrine_Cache_Driver
}
/**
* Test if a cache is available for the given id and (if yes) return it (false else)
*
* Note : return value is always "string" (unserialization is done by the core not by the backend)
* Test if a cache entry is available for the given id and (if yes) return it (false else).
*
* @param string $id cache id
* @param boolean $testCacheValidity if set to false, the cache validity won't be tested
......
......@@ -20,7 +20,7 @@
*/
/**
* A ClassMetadata instance holds all the information (metadata) of an entity and it's relations.
* A <tt>ClassMetadata</tt> instance holds all the information (metadata) of an entity and it's relations.
* These informations are used for the proper object-relational mapping of the class.
*
* @package Doctrine
......@@ -479,7 +479,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
}
/**
* getColumnAlias
* getFieldName
*
* returns a column alias for a column name
* if no alias can be found the column name is returned.
......@@ -687,8 +687,8 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
/**
* Gets the type of the identifier (primary key) used by the mapped class. The type
* can be either "Doctrine::IDENTIFIER_NATURAL", "Doctrine::IDENTIFIER_AUTOINCREMENT",
* "Doctrine::IDENTIFIER_SEQUENCE" or "Doctrine::IDENTIFIER_COMPOSITE".
* can be either <tt>Doctrine::IDENTIFIER_NATURAL</tt>, <tt>Doctrine::IDENTIFIER_AUTOINCREMENT</tt>,
* <tt>Doctrine::IDENTIFIER_SEQUENCE</tt> or <tt>Doctrine::IDENTIFIER_COMPOSITE</tt>.
*
* @return integer
*/
......@@ -1255,7 +1255,6 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* for the class.
*
* @return array
* @todo Move somewhere else ... somehow this seems wrong here. Exporting is a separate task.
*/
public function getExportableFormat($parseForeignKeys = true)
{
......@@ -1448,14 +1447,14 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
}
/**
* loadTemplate
* loadBehavior
*
* @param string $template
* @todo Unify under 'Behaviors'.
*/
public function loadTemplate($template, array $options = array())
public function loadBehavior($behavior, array $options = array())
{
$this->actAs($template, $options);
$this->actAs($behavior, $options);
}
/**
......@@ -1472,6 +1471,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
*
* @param object Doctrine_Record_Filter $filter
* @return object $this
* @todo Remove filters, if possible.
*/
public function unshiftFilter(Doctrine_Record_Filter $filter)
{
......@@ -1519,6 +1519,7 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
* getFilters
*
* @return array $filters
* @todo Remove filters, if possible.
*/
public function getFilters()
{
......@@ -1755,6 +1756,11 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return false;
}
public function isDiscriminatorColumn($columnName)
{
return $columnName === $this->_inheritanceOptions['discriminatorColumn'];
}
/**
* hasOne
* binds One-to-One aggregate relation
......@@ -1786,7 +1792,6 @@ class Doctrine_ClassMetadata extends Doctrine_Configurable implements Serializab
return $this;
}
/**
......
......@@ -479,16 +479,13 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
* @param integer $key
* @param Doctrine_Record $record
* @return void
* @internal Can't type-hint the second parameter to Doctrine_Record because we need
* to adhere to the Doctrine_Access::set() signature.
*/
public function set($key, $record)
{
if ( ! $record instanceOf Doctrine_Record) {
try {
throw new Exception();
} catch (Exception $e) {
echo $e->getTraceAsString() . "<br/><br/>";
}
throw new Doctrine_Record_Exception('Value variable in set is not an instance of Doctrine_Record');
throw new Doctrine_Collection_Exception('Value variable in set is not an instance of Doctrine_Record');
}
if (isset($this->referenceField)) {
......
......@@ -141,7 +141,6 @@ abstract class Doctrine_Configurable extends Doctrine_Locator_Injectable
case Doctrine::ATTR_RECORD_LISTENER:
case Doctrine::ATTR_THROW_EXCEPTIONS:
case Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE:
case Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES:
case Doctrine::ATTR_MODEL_LOADING:
break;
......
......@@ -1277,7 +1277,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/
public function clear()
{
$this->unitOfWork->detachAllManagedEntities();
$this->unitOfWork->detachAll();
foreach ($this->_mappers as $mapper) {
$mapper->clear(); // clear identity map of each mapper
}
......@@ -1289,6 +1289,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*
* @return void
* @todo package:orm
* @deprecated
*/
public function evictTables()
{
......
......@@ -43,7 +43,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
/**
* The identity map that holds references to all managed entities that have
* an identity.
* an identity. The entities are grouped by their class name.
*/
protected $_identityMap = array();
......@@ -246,7 +246,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* Adds an entity to the pool of managed entities.
*
*/
public function addManagedEntity(Doctrine_Record $entity)
public function manage(Doctrine_Record $entity)
{
$oid = $entity->getOid();
if ( ! isset($this->_managedEntities[$oid])) {
......@@ -257,14 +257,15 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
/**
* get
* @param integer $oid
* Gets a managed entity by it's object id (oid).
*
* @param integer $oid The object id.
* @throws Doctrine_Table_Repository_Exception
*/
public function getManagedEntity($oid)
public function getByOid($oid)
{
if ( ! isset($this->_managedEntities[$oid])) {
throw new Doctrine_Connection_UnitOfWork_Exception("Unknown object identifier '$oid'.");
throw new Doctrine_Connection_Exception("Unknown object identifier '$oid'.");
}
return $this->_managedEntities[$oid];
}
......@@ -273,7 +274,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* @param integer $oid object identifier
* @return boolean whether ot not the operation was successful
*/
public function detachManagedEntity(Doctrine_Record $entity)
public function detach(Doctrine_Record $entity)
{
$oid = $entity->getOid();
if ( ! isset($this->_managedEntities[$oid])) {
......@@ -284,35 +285,42 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
/**
* @return integer number of records evicted
* Detaches all currently managed entities.
*
* @return integer The number of detached entities.
*/
public function detachAllManagedEntities()
public function detachAll()
{
$evicted = 0;
foreach ($this->_managedEntities as $entity) {
if ($this->detachManagedEntity($entity)) {
$evicted++;
}
}
return $evicted;
$numDetached = count($this->_managedEntities);
$this->_managedEntities = array();
return $numDetached;
}
/**
* contains
* @param integer $oid object identifier
* Checks whether an entity is managed.
*
* @param Doctrine_Record $entity The entity to check.
* @return boolean TRUE if the entity is currently managed by doctrine, FALSE otherwise.
*/
public function isManagedEntity($oid)
public function isManaged(Doctrine_Record $entity)
{
return isset($this->_managedEntities[$oid]);
return isset($this->_managedEntities[$entity->getOid()]);
}
/**
* Adds an entity to the identity map.
* Registers an entity in the identity map.
*
* @return boolean TRUE if the registration was successful, FALSE if the identity of
* the entity in question is already managed.
* @throws Doctrine_Connection_Exception If the entity has no (database) identity.
*/
public function addToIdentityMap(Doctrine_Record $entity)
public function registerIdentity(Doctrine_Record $entity)
{
$id = implode(' ', $entity->identifier());
if ( ! $id) {
throw new Doctrine_Connection_Exception("Entity with oid '" . $entity->getOid()
. "' has no database identity and therefore can't be added to the identity map.");
}
$className = $entity->getClassMetadata()->getRootClassName();
if (isset($this->_identityMap[$className][$id])) {
return false;
......@@ -321,4 +329,25 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return true;
}
public function unregisterIdentity(Doctrine_Record $entity)
{
$id = implode(' ', $entity->identifier());
if ( ! $id) {
throw new Doctrine_Connection_Exception("Entity with oid '" . $entity->getOid()
. "' has no database identity and therefore can't be removed from the identity map.");
}
$className = $entity->getClassMetadata()->getRootClassName();
if (isset($this->_identityMap[$className][$id])) {
unset($this->_identityMap[$className][$id]);
return true;
}
return false;
}
public function containsIdentity(Doctrine_Record $entity)
{
}
}
......@@ -24,7 +24,7 @@
* a database result set.
*
* @package Doctrine
* @subpackage Hydrate
* @subpackage Hydrator
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.phpdoctrine.org
* @since 1.0
......@@ -104,10 +104,11 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
}
// Initialize
foreach ($this->_queryComponents as $dqlAlias => $data) {
$data['mapper']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
$componentName = $data['mapper']->getComponentName();
$listeners[$componentName] = $data['mapper']->getRecordListener();
foreach ($this->_queryComponents as $dqlAlias => $component) {
// disable lazy-loading of related elements during hydration
$component['mapper']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
$componentName = $component['mapper']->getComponentName();
$listeners[$componentName] = $component['mapper']->getRecordListener();
$identifierMap[$dqlAlias] = array();
$prev[$dqlAlias] = array();
$id[$dqlAlias] = '';
......@@ -290,28 +291,38 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
protected function _gatherRowData(&$data, &$cache, &$id, &$nonemptyComponents)
{
$rowData = array();
//$className = null;
foreach ($data as $key => $value) {
// Parse each column name only once. Cache the results.
if ( ! isset($cache[$key])) {
// cache general information like the column name <-> field name mapping
$e = explode('__', $key);
$last = strtolower(array_pop($e));
$columnName = strtolower(array_pop($e));
$cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
$mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$table = $mapper->getTable();
$fieldName = $mapper->getFieldName($last);
$classMetadata = $mapper->getClassMetadata();
$fieldName = $mapper->getFieldName($columnName);
$cache[$key]['fieldName'] = $fieldName;
// determine the class name
/*if ( ! $className) {
if ($classMetadata->isDiscriminatorColumn($columnName)) {
$className = $this->_getClassnameToReturn();
} else if ( ! $className) {
$className = $classMetadata->getClassName();
}
}*/
// cache identifier information
if ($table->isIdentifier($fieldName)) {
if ($classMetadata->isIdentifier($fieldName)) {
$cache[$key]['isIdentifier'] = true;
} else {
$cache[$key]['isIdentifier'] = false;
}
// cache type information
$type = $table->getTypeOfColumn($last);
$type = $classMetadata->getTypeOfColumn($columnName);
if ($type == 'integer' || $type == 'string') {
$cache[$key]['isSimpleType'] = true;
} else {
......
......@@ -52,10 +52,10 @@ class Doctrine_Hydrator_ArrayDriver
/**
*
*/
public function isIdentifiable(array $data, Doctrine_Table $table)
/*public function isIdentifiable(array $data, Doctrine_Table $table)
{
return ( ! empty($data));
}
}*/
/**
*
......
......@@ -35,7 +35,6 @@
class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
{
protected $_collections = array();
protected $_records = array();
protected $_mappers = array();
public function getElementCollection($component)
......@@ -79,7 +78,7 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
* @param Doctrine_Table $table
* @return boolean
*/
public function isIdentifiable(array $row, Doctrine_Table $table)
/*public function isIdentifiable(array $row, Doctrine_Table $table)
{
$primaryKeys = $table->getIdentifierColumnNames();
......@@ -95,26 +94,21 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
}
}
return true;
}
}*/
public function getNullPointer()
{
return self::$_null;
}
public function getElement(array $data, $component)
public function getElement(array $data, $className)
{
$component = $this->_getClassnameToReturn($data, $component);
if ( ! isset($this->_mappers[$component])) {
$this->_mappers[$component] = Doctrine_Manager::getInstance()->getMapper($component);
$className = $this->_getClassnameToReturn($data, $className);
if ( ! isset($this->_mappers[$className])) {
$this->_mappers[$className] = Doctrine_Manager::getInstance()->getMapper($className);
}
$record = $this->_mappers[$component]->getRecord($data);
if ( ! isset($this->_records[$record->getOid()]) ) {
$record->clearRelated();
$this->_records[$record->getOid()] = $record;
}
$record = $this->_mappers[$className]->getRecord($data);
return $record;
}
......@@ -125,6 +119,8 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
foreach ($this->_collections as $key => $coll) {
$coll->takeSnapshot();
}
$this->_collections = array();
$this->_mappers = array();
}
/**
......@@ -141,18 +137,17 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
$this->_mappers[$className] = Doctrine_Manager::getInstance()->getMapper($className);
}
$discCol = $this->_mappers[$className]->getTable()->getInheritanceOption('discriminatorColumn');
$discCol = $this->_mappers[$className]->getClassMetadata()->getInheritanceOption('discriminatorColumn');
if ( ! $discCol) {
return $className;
}
$discMap = $this->_mappers[$className]->getTable()->getInheritanceOption('discriminatorMap');
foreach ($discMap as $value => $class) {
if (isset($data[$discCol]) && $data[$discCol] == $value) {
return $class;
}
}
$discMap = $this->_mappers[$className]->getClassMetadata()->getInheritanceOption('discriminatorMap');
return $className;
if (isset($data[$discCol], $discMap[$data[$discCol]])) {
return $discMap[$data[$discCol]];
} else {
return $className;
}
}
}
......@@ -110,8 +110,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera
Doctrine::ATTR_PORTABILITY => Doctrine::PORTABILITY_ALL,
Doctrine::ATTR_EXPORT => Doctrine::EXPORT_ALL,
Doctrine::ATTR_DECIMAL_PLACES => 2,
Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE => 'doctrine',
Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES => true,
Doctrine::ATTR_DEFAULT_PARAM_NAMESPACE => 'doctrine'
);
foreach ($attributes as $attribute => $value) {
$old = $this->getAttribute($attribute);
......
......@@ -62,12 +62,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
*/
protected $_identityMap = array();
/**
* @var Doctrine_Table_Repository $repository record repository
* @todo Move to UnifOfWork together with identity map.
*/
//protected $_repository;
/**
* Constructs a new mapper.
......@@ -90,7 +84,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
$this->_conn = $classMetadata->getConnection();
$this->_classMetadata = $classMetadata;
$this->setParent($this->_conn);
//$this->_repository = new Doctrine_Table_Repository($this);
if ($classMetadata->getInheritanceType() == Doctrine::INHERITANCETYPE_JOINED) {
$this->_mappingStrategy = new Doctrine_Mapper_JoinedStrategy($this);
} else {
......@@ -143,17 +136,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
return Doctrine_Query::create($this->_conn)->from($this->getComponentName() . $alias);
}
/**
* getRepository
*
* @return Doctrine_Table_Repository
* @todo refactor
*/
/*public function getRepository()
{
return $this->_repository;
}*/
/**
* sets the connection for this class
*
......@@ -195,7 +177,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
public function detach(Doctrine_Record $entity)
{
return $this->_conn->unitOfWork->detachManagedEntity($entity);
return $this->_conn->unitOfWork->detach($entity);
}
/**
......@@ -323,7 +305,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
*/
public function manage(Doctrine_Record $record)
{
return $this->_conn->unitOfWork->addManagedEntity($record);
return $this->_conn->unitOfWork->manage($record);
}
/**
......@@ -977,6 +959,13 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
$this->_mappingStrategy = null;
}
public function getMappingStrategy()
{
return $this->_mappingStrategy;
}
public function getFieldName($columnName)
{
return $this->_mappingStrategy->getFieldName($columnName);
......
<?php
/*
* $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.phpdoctrine.org>.
*/
/**
* The default strategy maps a single instance to a single database table, as is
* the case in Single Table Inheritance & Concrete Table Inheritance.
* The default mapping strategy maps a single entity instance to a single database table,
* as is the case in Single Table Inheritance & Concrete Table Inheritance.
*
* @since 1.0
* @author Roman Borschel <roman@code-factory.org>
* @package Doctrine
* @subpackage DefaultStrategy
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$
* @link www.phpdoctrine.org
* @since 1.0
*/
class Doctrine_Mapper_DefaultStrategy extends Doctrine_Mapper_Strategy
{
/**
* Deletes an entity.
*/
......
<?php
/*
* $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.phpdoctrine.org>.
*/
/**
* The joined mapping strategy maps a single entity instance to several tables in the
* database as it is defined by <b>Class Table Inheritance</b>.
*
* @author Roman Borschel <roman@code-factory.org>
* @package Doctrine
* @subpackage DefaultStrategy
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$
* @link www.phpdoctrine.org
* @since 1.0
*/
class Doctrine_Mapper_JoinedStrategy extends Doctrine_Mapper_Strategy
{
protected $_columnNameFieldNameMap = array();
......
<?php
/*
* $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.phpdoctrine.org>.
*/
/**
* Base class for all mapping strategies used by mappers.
*
* @author Roman Borschel <roman@code-factory.org>
* @package Doctrine
* @subpackage Strategy
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @version $Revision$
* @link www.phpdoctrine.org
* @since 1.0
*/
abstract class Doctrine_Mapper_Strategy
{
protected $_mapper;
......
......@@ -730,12 +730,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$id = array_values($id);
if ($deep) {
$query = $this->_mapper->createQuery();
foreach (array_keys($this->_references) as $name) {
$query->leftJoin(get_class($this) . '.' . $name);
}
$query->where(implode(' = ? AND ', $this->_table->getIdentifierColumnNames()) . ' = ?');
$this->clearRelated();
$record = $query->fetchOne($id);
} else {
// Use FETCH_ARRAY to avoid clearing object relations
......@@ -1900,7 +1900,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* Note: The entity is no longer useable after free() has been called. Any operations
* done with the entity afterwards can lead to unpredictable results.
*/
public function free()
public function free($deep = false)
{
if ($this->_state != self::STATE_LOCKED) {
$this->_mapper->detach($this);
......
......@@ -8,6 +8,7 @@ require_once 'lib/DoctrineTestInit.php';
// Suites
require_once 'Orm/Component/AllTests.php';
require_once 'Orm/Ticket/AllTests.php';
require_once 'Orm/UnitOfWorkTestCase.php';
class Orm_AllTests
{
......@@ -20,6 +21,7 @@ class Orm_AllTests
{
$suite = new Doctrine_OrmTestSuite('Doctrine Orm');
$suite->addTestSuite('Orm_UnitOfWorkTestCase');
$suite->addTest(Orm_Component_AllTests::suite());
$suite->addTest(Orm_Ticket_AllTests::suite());
......
......@@ -44,7 +44,7 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
$this->user = new ForumUser();
}
public function testAccessorOverridePerformance() {
/*public function testAccessorOverridePerformance() {
$this->user->username;
$start = microtime(true);
for ($i = 0; $i < 1; $i++) {
......@@ -52,7 +52,7 @@ class Orm_Component_AccessTest extends Doctrine_OrmTestCase
}
$end = microtime(true);
echo ($end - $start) . " seconds" . PHP_EOL;
}
}*/
/**
* @test
......
......@@ -825,12 +825,12 @@ class Doctrine_Record_TestCase extends Doctrine_UnitTestCase
$user = $this->objTable->find(5);
$this->assertEqual($user->Group->count(), 2);
$this->assertEqual($user->Group[0]->identifier(), $group1->identifier());
$this->assertEqual($user->Group[1]->identifier(), $group2->identifier());
$this->assertEqual($user->Group[0]->identifier(), $group2->identifier());
$this->assertEqual($user->Group[1]->identifier(), $group1->identifier());
$user->unlink('Group');
$user->save();
unset($user);
$user->free();
$user = $this->objTable->find(5);
$this->assertEqual($user->Group->count(), 0);
......
......@@ -13,6 +13,8 @@
*/
class Doctrine_Ticket_428_TestCase extends Doctrine_UnitTestCase
{
private $_albums;
public function prepareTables()
{
$this->tables = array('Album', 'Song');
......@@ -36,10 +38,15 @@ class Doctrine_Ticket_428_TestCase extends Doctrine_UnitTestCase
$albums[0]->Song[3]->title = 'Michelle';
$albums->save();
$this->assertEqual(count($albums[0]->Song), 4);
$this->_albums = $albums;
}
public function testAggregateValueMappingSupportsLeftJoins()
{
foreach ($this->_albums as $album) {
$album->clearRelated();
}
$q = new Doctrine_Query();
$q->select('a.name, COUNT(s.id) count')->from('Album a')->leftJoin('a.Song s')->groupby('a.id');
......
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