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