diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php
index e97d4d7e6..360fc8705 100644
--- a/lib/Doctrine/Collection.php
+++ b/lib/Doctrine/Collection.php
@@ -20,8 +20,9 @@
*/
Doctrine::autoload('Doctrine_Access');
/**
- * Doctrine_Collection
- * Collection of Doctrine_Record objects.
+ * A Doctrine_Collection represents a collection of record objects.
+ * A collection object is strongly typed in the sense that it can only contain
+ * records of a specific type or one it's subtypes.
*
* @package Doctrine
* @subpackage Collection
@@ -34,57 +35,74 @@ Doctrine::autoload('Doctrine_Access');
class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable
{
/**
- * @var array $data an array containing the records of this collection
+ * An array containing the records of this collection.
+ *
+ * @var array
*/
protected $data = array();
+ /**
+ * The mapper object used to map the records of this collection to the database.
+ *
+ * @var Doctrine_Mapper
+ */
protected $_mapper;
/**
- * @var array $_snapshot a snapshot of the fetched data
+ * A snapshot of the fetched data.
+ *
+ * @var array
*/
protected $_snapshot = array();
/**
- * @var Doctrine_Record $reference collection can belong to a record
+ * This record this collection is attached to, if any.
+ *
+ * @var Doctrine_Record
*/
protected $reference;
/**
- * @var string $referenceField the reference field of the collection
+ * The reference field of the collection.
+ *
+ * @var string $referenceField
*/
protected $referenceField;
/**
- * @var Doctrine_Relation the record this collection is related to, if any
+ * The relation this collection is related to, if any.
+ *
+ * @var Doctrine_Relation
*/
protected $relation;
/**
- * @var string $keyColumn the name of the column that is used for collection key mapping
+ * The name of the column that is used for collection key mapping.
+ *
+ * @var string
*/
protected $keyColumn;
/**
- * @var Doctrine_Null $null used for extremely fast null value testing
+ * Helper variable. Used for fast null value testing.
+ *
+ * @var Doctrine_Null
*/
protected static $null;
-
/**
- * constructor
+ * Constructor.
+ * Creates a new collection that will hold instances of the type that is
+ * specified through the mapper. That means if the mapper is a mapper for
+ * the entity "User", then the resulting collection will be a collection of
+ * user objects.
*
- * @param Doctrine_Table|string $table
+ * @param Doctrine_Mapper|string $mapper The mapper used by the collection.
+ * @param string $keyColumn The field name that will be used as the key
+ * in the collection.
*/
public function __construct($mapper, $keyColumn = null)
{
- if ($mapper instanceof Doctrine_Table) {
- try {
- throw new Exception();
- } catch (Exception $e) {
- echo $e->getTraceAsString();
- }
- }
if (is_string($mapper)) {
$mapper = Doctrine_Manager::getInstance()->getMapper($mapper);
}
@@ -105,7 +123,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
/**
* initNullObject
- * initializes the null object for this collection
+ * Initializes the null object for this collection.
*
* @return void
*/
@@ -116,7 +134,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
/**
* getTable
- * returns the table this collection belongs to
+ * Returns the table of the mapper of the collection.
*
* @return Doctrine_Table
*/
@@ -124,6 +142,17 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
{
return $this->_mapper->getTable();
}
+
+ /**
+ * getMapper
+ * Returns the mapper of this collection.
+ *
+ * @return Doctrine_Mapper
+ */
+ public function getMapper()
+ {
+ return $this->_mapper;
+ }
/**
* setData
@@ -137,7 +166,10 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
/**
- * this method is automatically called when this Doctrine_Collection is serialized
+ * Serializes the collection.
+ * This method is automatically called when this Doctrine_Collection is serialized.
+ *
+ * Part of the implementation of the Serializable interface.
*
* @return array
*/
@@ -158,15 +190,17 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
/**
- * unseralize
- * this method is automatically called everytime a Doctrine_Collection object is unserialized
+ * Reconstitutes the collection object from it's serialized form.
+ * This method is automatically called everytime a Doctrine_Collection object is unserialized.
+ *
+ * Part of the implementation of the Serializable interface.
*
* @return void
*/
public function unserialize($serialized)
{
- $manager = Doctrine_Manager::getInstance();
- $connection = $manager->getCurrentConnection();
+ $manager = Doctrine_Manager::getInstance();
+ $connection = $manager->getCurrentConnection();
$array = unserialize($serialized);
@@ -196,7 +230,6 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
public function setKeyColumn($column)
{
$this->keyColumn = $column;
-
return $this;
}
@@ -243,6 +276,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
{
return end($this->data);
}
+
/**
* returns the last record in the collection
*
@@ -252,6 +286,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
{
return end($this->data);
}
+
/**
* returns the current key
*
@@ -261,6 +296,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
{
return key($this->data);
}
+
/**
* setReference
* sets a reference pointer
@@ -269,18 +305,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function setReference(Doctrine_Record $record, Doctrine_Relation $relation)
{
- /*try {
- throw new Exception();
- } catch (Exception $e) {
- echo "relation set on collection: " . get_class($relation) . "
";
- echo $e->getTraceAsString() . "
";
- }*/
$this->reference = $record;
$this->relation = $relation;
if ($relation instanceof Doctrine_Relation_ForeignKey ||
$relation instanceof Doctrine_Relation_LocalKey) {
-
$this->referenceField = $relation->getForeignFieldName();
$value = $record->get($relation->getLocalFieldName());
foreach ($this->data as $record) {
@@ -331,6 +360,9 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
return isset($this->data[$key]);
}
+ /**
+ *
+ */
public function search(Doctrine_Record $record)
{
return array_search($record, $this->data, true);
@@ -367,6 +399,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
$record->set($this->referenceField, $this->reference, false);
}
}
+
if ($key === null) {
$this->data[] = $record;
} else {
@@ -374,7 +407,6 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
if (isset($this->keyColumn)) {
-
$record->set($this->keyColumn, $key);
}
@@ -385,7 +417,9 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
/**
- * @return array an array containing all primary keys
+ * Returns the primary keys of all records in the collection.
+ *
+ * @return array An array containing all primary keys.
*/
public function getPrimaryKeys()
{
@@ -412,11 +446,11 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
/**
- * count
- * this class implements interface countable
- * returns the number of records in this collection
+ * Returns the number of records in this collection.
*
- * @return integer
+ * Implementation of the Countable interface.
+ *
+ * @return integer The number of records in the collection.
*/
public function count()
{
@@ -434,7 +468,6 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
if (isset($this->referenceField)) {
$record->set($this->referenceField, $this->reference, false);
}
-
$this->data[$key] = $record;
}
@@ -455,7 +488,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
$record->set($this->referenceField, $this->reference, false);
}
}
- /**
+ /*
* for some weird reason in_array cannot be used here (php bug ?)
*
* if used it results in fatal error : [ nesting level too deep ]
@@ -495,7 +528,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
public function loadRelated($name = null)
{
$list = array();
- $query = new Doctrine_Query($this->_mapper->getConnection());
+ $query = new Doctrine_Query($this->_mapper->getConnection());
if ( ! isset($name)) {
foreach ($this->data as $record) {
@@ -510,7 +543,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
return $query;
}
- $rel = $this->_mapper->getTable()->getRelation($name);
+ $rel = $this->_mapper->getTable()->getRelation($name);
if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) {
foreach ($this->data as $record) {
@@ -525,9 +558,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
}
}
- $dql = $rel->getRelationDql(count($list), 'collection');
-
- $coll = $query->query($dql, $list);
+ $dql = $rel->getRelationDql(count($list), 'collection');
+ $coll = $query->query($dql, $list);
$this->populateRelated($name, $coll);
}
@@ -618,7 +650,6 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
public function takeSnapshot()
{
$this->_snapshot = $this->data;
-
return $this;
}
@@ -647,7 +678,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function processDiff()
{
- foreach (array_udiff($this->_snapshot, $this->data, array($this, "compareRecords")) as $record) {
+ foreach (array_udiff($this->_snapshot, $this->data, array($this, "_compareRecords")) as $record) {
$record->delete();
}
return $this;
@@ -663,9 +694,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
{
$data = array();
foreach ($this as $key => $record) {
-
$key = $prefixKey ? get_class($record) . '_' .$key:$key;
-
$data[$key] = $record->toArray($deep, $prefixKey);
}
@@ -758,7 +787,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function getDeleteDiff()
{
- return array_udiff($this->_snapshot, $this->data, array($this, "compareRecords"));
+ return array_udiff($this->_snapshot, $this->data, array($this, "_compareRecords"));
}
/**
@@ -768,14 +797,14 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
*/
public function getInsertDiff()
{
- return array_udiff($this->data, $this->_snapshot, array($this, "compareRecords"));
+ return array_udiff($this->data, $this->_snapshot, array($this, "_compareRecords"));
}
/**
- * compareRecords
- * Compares two records. To be used on _snapshot diffs using array_udiff
+ * _compareRecords
+ * Compares two records. To be used on _snapshot diffs using array_udiff.
*/
- protected function compareRecords($a, $b)
+ protected function _compareRecords($a, $b)
{
if ($a->getOid() == $b->getOid()) {
return 0;
@@ -786,8 +815,8 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
/**
* save
- * saves all records of this collection and processes the
- * difference of the last snapshot and the current data
+ * Saves all records of this collection and processes the
+ * difference of the last snapshot and the current data.
*
* @param Doctrine_Connection $conn optional connection parameter
* @return Doctrine_Collection
diff --git a/lib/Doctrine/Connection.php b/lib/Doctrine/Connection.php
index 92dfa65e6..8053901d9 100644
--- a/lib/Doctrine/Connection.php
+++ b/lib/Doctrine/Connection.php
@@ -60,6 +60,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/
protected $dbh;
+ /**
+ *
+ */
protected $_tableFactory;
/**
@@ -169,6 +172,12 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
'Sqlite',
'Firebird'
);
+
+ /**
+ * The query count. Represents the number of executed database queries by the connection.
+ *
+ * @var integer
+ */
protected $_count = 0;
/**
@@ -184,9 +193,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
throw new Doctrine_Connection_Exception('First argument should be an instance of PDO or implement Doctrine_Adapter_Interface');
}
$this->dbh = $adapter;
-
$this->isConnected = true;
-
} else if (is_array($adapter)) {
$this->pendingAttributes[Doctrine::ATTR_DRIVER_NAME] = $adapter['scheme'];
@@ -235,7 +242,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/
public function getAttribute($attribute)
{
-
if ($attribute >= 100) {
if ( ! isset($this->attributes[$attribute])) {
return parent::getAttribute($attribute);
@@ -353,14 +359,13 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
}
/**
- * returns the database handler of which this connection uses
+ * returns the database handler which this connection uses
*
* @return PDO the database handler
*/
public function getDbh()
{
$this->connect();
-
return $this->dbh;
}
@@ -372,13 +377,11 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/
public function connect()
{
-
if ($this->isConnected) {
return false;
}
$event = new Doctrine_Event($this, Doctrine_Event::CONN_CONNECT);
-
$this->getListener()->preConnect($event);
$e = explode(':', $this->options['dsn']);
@@ -515,21 +518,19 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*
* @throws Doctrine_Connection_Exception if something went wrong at the database level
* @param string $table The table to delete data from
- * @param array $identifier An associateve array containing identifier column-value pairs.
+ * @param array $identifier An associateve array containing identifier fieldname-value pairs.
* @return integer The number of affected rows
*/
public function delete(Doctrine_Table $table, array $identifier)
{
- $tmp = array();
-
+ $criteria = array();
foreach (array_keys($identifier) as $id) {
- $tmp[] = $table->getColumnName($id) . ' = ?';
+ $criteria[] = $table->getColumnName($id) . ' = ?';
}
$query = 'DELETE FROM '
. $this->quoteIdentifier($table->getTableName())
- . ' WHERE ' . implode(' AND ', $tmp);
-
+ . ' WHERE ' . implode(' AND ', $criteria);
return $this->exec($query, array_values($identifier));
}
@@ -573,7 +574,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* Inserts a table row with specified data.
*
* @param string $table The table to insert data into.
- * @param array $values An associateve array containing column-value pairs.
+ * @param array $fields An associateve array containing fieldname-value pairs.
* @return mixed boolean false if empty value array was given,
* otherwise returns the number of affected rows
*/
@@ -606,53 +607,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$query .= implode(', ', $a) . ')';
// prepare and execute the statement
-
+
return $this->exec($query, array_values($fields));
- }
-
- /**
- * @todo DESCRIBE WHAT THIS METHOD DOES, PLEASE!
- */
- public function processSingleInsert(Doctrine_Record $record)
- {
- $fields = $record->getPrepared();
- if (empty($fields)) {
- return false;
- }
-
- $table = $record->getTable();
- $identifier = (array) $table->getIdentifier();
-
- $seq = $record->getTable()->getOption('sequenceName');
-
- if ( ! empty($seq)) {
- $id = $this->sequence->nextId($seq);
- $seqName = $table->getIdentifier();
- $fields[$seqName] = $id;
-
- $record->assignIdentifier($id);
- }
-
- $this->insert($table, $fields);
-
- if (empty($seq) && count($identifier) == 1 && $identifier[0] == $table->getIdentifier() &&
- $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
-
- if (strtolower($this->getName()) == 'pgsql') {
- $seq = $table->getTableName() . '_' . $identifier[0];
- }
-
- $id = $this->sequence->lastInsertId($seq);
-
- if ( ! $id) {
- throw new Doctrine_Connection_Exception("Couldn't get last insert identifier.");
- }
-
- $record->assignIdentifier($id);
- } else {
- $record->assignIdentifier(true);
- }
- }
+ }
/**
* Set the charset on the current connection
@@ -661,11 +618,11 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/
public function setCharset($charset)
{
-
+ return true;
}
/**
- * Quote a string so it can be safely used as a table or column name
+ * Quote a string so it can be safely used as a table or column name.
*
* Delimiting style depends on which database driver is being used.
*
@@ -1032,7 +989,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
public function rethrowException(Exception $e, $invoker)
{
$event = new Doctrine_Event($this, Doctrine_Event::CONN_ERROR);
-
$this->getListener()->preError($event);
$name = 'Doctrine_Connection_' . $this->driverName . '_Exception';
@@ -1079,7 +1035,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
}
/**
- * Gets a mapper for the specified domain class that is used map instances of
+ * Gets a mapper for the specified domain class that is used to map instances of
* the class between the relational database and their object representation.
*
* @return Doctrine_Mapper_Abstract The mapper object.
@@ -1092,9 +1048,9 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$customMapperClass = $className . 'Mapper';
if (class_exists($customMapperClass, $this->getAttribute(Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES)) &&
- in_array('Doctrine_Mapper', class_parents($customMapperClass))) {
+ in_array('Doctrine_Mapper_Abstract', class_parents($customMapperClass))) {
$table = $this->getTable($className);
- $mapper = new $customMapperClass($className, $this);
+ $mapper = new $customMapperClass($className, $table);
} else {
// instantiate correct mapper type
$table = $this->getTable($className);
@@ -1250,7 +1206,6 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
public function close()
{
$event = new Doctrine_Event($this, Doctrine_Event::CONN_CLOSE);
-
$this->getAttribute(Doctrine::ATTR_LISTENER)->preClose($event);
$this->clear();
diff --git a/lib/Doctrine/Connection/UnitOfWork.php b/lib/Doctrine/Connection/UnitOfWork.php
index 09eac4d7f..3e9dd8ad3 100644
--- a/lib/Doctrine/Connection/UnitOfWork.php
+++ b/lib/Doctrine/Connection/UnitOfWork.php
@@ -73,7 +73,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
{
$tree = array();
foreach ($tables as $k => $table) {
- if ( ! ($table instanceof Doctrine_Mapper)) {
+ if ( ! ($table instanceof Doctrine_Mapper_Abstract)) {
$table = $this->conn->getMapper($table);
}
$nm = $table->getComponentName();
@@ -281,7 +281,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* @return boolean true on success, false on failure
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
*/
- public function delete(Doctrine_Record $record)
+ /*public function delete(Doctrine_Record $record)
{
if ( ! $this->_autoflush) {
return true;
@@ -331,7 +331,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$this->conn->commit();
return true;
- }
+ }*/
/**
* @todo Description. See also the todo for deleteMultiple().
@@ -356,6 +356,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}*/
/**
+ * DOESNT SEEM TO BE USED ANYWHERE.
+ *
* deleteMultiple
* deletes all records from the pending delete list
*
@@ -364,7 +366,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* queries itself and sometimes it leaves the sql construction to Connection.
* This should be changed.
*/
- public function deleteMultiple(array $records)
+ /*public function deleteMultiple(array $records)
{
foreach ($this->delete as $name => $deletes) {
$record = false;
@@ -414,7 +416,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
}
}
- }
+ }*/
/**
* saveRelated
@@ -498,7 +500,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
* @throws PDOException if something went wrong at database level
* @return void
*/
- public function deleteComposites(Doctrine_Record $record)
+ /*public function deleteComposites(Doctrine_Record $record)
{
foreach ($record->getTable()->getRelations() as $fk) {
if ($fk->isComposite()) {
@@ -509,7 +511,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
}
}
- }
+ }*/
/**
* saveAll
@@ -554,22 +556,19 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
//echo "
flushin all.
";
// get the flush tree
$tree = $this->buildFlushTree($this->conn->getMappers());
- //foreach ($tree as $name) echo $name . "
";
// save all records
foreach ($tree as $name) {
$mapper = $this->conn->getMapper($name);
-
foreach ($mapper->getRepository() as $record) {
//echo $record->getOid() . "
";
- $mapper->save($record);
+ $mapper->saveSingleRecord($record);
}
}
// save all associations
foreach ($tree as $name) {
$mapper = $this->conn->getMapper($name);
-
foreach ($mapper->getRepository() as $record) {
$mapper->saveAssociations($record);
}
diff --git a/lib/Doctrine/Hydrator.php b/lib/Doctrine/Hydrator.php
index 3651ad9ba..dedc099b3 100644
--- a/lib/Doctrine/Hydrator.php
+++ b/lib/Doctrine/Hydrator.php
@@ -106,6 +106,7 @@ 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['table']->getRecordListener();
$identifierMap[$dqlAlias] = array();
@@ -229,6 +230,11 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$driver->flush();
+ // re-enable lazy loading
+ foreach ($this->_queryComponents as $dqlAlias => $data) {
+ $data['mapper']->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, true);
+ }
+
//$e = microtime(true);
//echo 'Hydration took: ' . ($e - $s) . ' for '.count($result).' records
';
@@ -290,8 +296,9 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
$e = explode('__', $key);
$last = strtolower(array_pop($e));
$cache[$key]['dqlAlias'] = $this->_tableAliases[strtolower(implode('__', $e))];
- $table = $this->_queryComponents[$cache[$key]['dqlAlias']]['table'];
- $fieldName = $table->getFieldName($last);
+ $mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
+ $table = $mapper->getTable();
+ $fieldName = $mapper->getFieldName($last);
$cache[$key]['fieldName'] = $fieldName;
if ($table->isIdentifier($fieldName)) {
$cache[$key]['isIdentifier'] = true;
@@ -306,8 +313,7 @@ class Doctrine_Hydrator extends Doctrine_Hydrator_Abstract
}
}
- $map = $this->_queryComponents[$cache[$key]['dqlAlias']];
- $mapper = $map['mapper'];
+ $mapper = $this->_queryComponents[$cache[$key]['dqlAlias']]['mapper'];
$dqlAlias = $cache[$key]['dqlAlias'];
$fieldName = $cache[$key]['fieldName'];
diff --git a/lib/Doctrine/Hydrator/ArrayDriver.php b/lib/Doctrine/Hydrator/ArrayDriver.php
index 106170a00..f0ec5f233 100644
--- a/lib/Doctrine/Hydrator/ArrayDriver.php
+++ b/lib/Doctrine/Hydrator/ArrayDriver.php
@@ -37,18 +37,22 @@ class Doctrine_Hydrator_ArrayDriver
{
return array();
}
+
public function getElement(array $data, $component)
{
return $data;
}
+
public function isIdentifiable(array $data, Doctrine_Table $table)
{
return ( ! empty($data));
}
+
public function registerCollection($coll)
{
}
+
public function initRelated(array &$data, $name)
{
if ( ! isset($data[$name])) {
@@ -56,10 +60,12 @@ class Doctrine_Hydrator_ArrayDriver
}
return true;
}
+
public function getNullPointer()
{
return null;
}
+
public function getLastKey(&$data)
{
end($data);
diff --git a/lib/Doctrine/Hydrator/RecordDriver.php b/lib/Doctrine/Hydrator/RecordDriver.php
index c77e03c6d..31e7ee3d7 100644
--- a/lib/Doctrine/Hydrator/RecordDriver.php
+++ b/lib/Doctrine/Hydrator/RecordDriver.php
@@ -20,8 +20,8 @@
*/
/**
- * Doctrine_Hydrate_Record
- * defines a record fetching strategy for Doctrine_Hydrate
+ * Doctrine_Hydrate_RecordDriver
+ * Hydration strategy used for creating collections of entity objects.
*
* @package Doctrine
* @subpackage Hydrate
@@ -30,14 +30,13 @@
* @since 1.0
* @version $Revision$
* @author Konsta Vesterinen
+ * @author Roman Borschel
*/
class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
{
protected $_collections = array();
-
protected $_records = array();
-
- protected $_tables = array();
+ protected $_mappers = array();
public function getElementCollection($component)
{
@@ -105,13 +104,12 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
public function getElement(array $data, $component)
{
- if ( ! isset($this->_tables[$component])) {
- $this->_tables[$component] = Doctrine_Manager::getInstance()->getMapper($component);
- $this->_tables[$component]->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
+ if ( ! isset($this->_mappers[$component])) {
+ $this->_mappers[$component] = Doctrine_Manager::getInstance()->getMapper($component);
}
- $this->_tables[$component]->setData($data);
- $record = $this->_tables[$component]->getRecord();
+ $component = $this->_getClassnameToReturn($data, $component);
+ $record = $this->_mappers[$component]->getRecord($data);
if ( ! isset($this->_records[$record->getOid()]) ) {
$record->clearRelated();
@@ -127,8 +125,38 @@ class Doctrine_Hydrator_RecordDriver extends Doctrine_Locator_Injectable
foreach ($this->_collections as $key => $coll) {
$coll->takeSnapshot();
}
- foreach ($this->_tables as $table) {
- $table->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, true);
+ }
+
+ /**
+ * Check the dataset for a discriminator column, to determine the correct
+ * class to instantiate. If no discriminator column is found, the given
+ * classname will be returned.
+ *
+ * @todo this function could use reflection to check the first time it runs
+ * if the subclassing option is not set.
+ *
+ * @return string The name of the class to instantiate.
+ *
+ */
+ protected function _getClassnameToReturn(array $data, $className)
+ {
+ $subClasses = $this->_mappers[$className]->getTable()->getOption('subclasses');
+ if ( ! isset($subClasses)) {
+ return $className;
}
+
+ foreach ($subClasses as $subclass) {
+ if ( ! isset($this->_mappers[$subclass])) {
+ $this->_mappers[$subclass] = Doctrine_Manager::getInstance()->getMapper($subclass);
+ }
+ $mapper = $this->_mappers[$subclass];
+ $inheritanceMap = $mapper->getDiscriminatorColumn();
+ foreach ($inheritanceMap as $key => $value) {
+ if (isset($data[$key]) && $data[$key] == $value) {
+ return $mapper->getComponentName();
+ }
+ }
+ }
+ return $className;
}
}
diff --git a/lib/Doctrine/Manager.php b/lib/Doctrine/Manager.php
index da56ae8b4..f2c315fe2 100644
--- a/lib/Doctrine/Manager.php
+++ b/lib/Doctrine/Manager.php
@@ -255,7 +255,7 @@ class Doctrine_Manager extends Doctrine_Configurable implements Countable, Itera
}
$driverName = $adapter->getAttribute(Doctrine::ATTR_DRIVER_NAME);
- } elseif (is_array($adapter)) {
+ } else if (is_array($adapter)) {
if ( ! isset($adapter[0])) {
throw new Doctrine_Manager_Exception('Empty data source name given.');
}
diff --git a/lib/Doctrine/Mapper.php b/lib/Doctrine/Mapper/Abstract.php
similarity index 80%
rename from lib/Doctrine/Mapper.php
rename to lib/Doctrine/Mapper/Abstract.php
index bcdd2da6b..515ee8179 100644
--- a/lib/Doctrine/Mapper.php
+++ b/lib/Doctrine/Mapper/Abstract.php
@@ -31,7 +31,8 @@
* @link www.phpdoctrine.org
* @since 1.0
*/
-class Doctrine_Mapper extends Doctrine_Configurable implements Countable
+abstract class Doctrine_Mapper_Abstract extends Doctrine_Configurable
+ implements Countable
{
/**
* @var Doctrine_Table Metadata container that represents the database table this
@@ -48,13 +49,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
* The names of all the fields that are available on entities created by this mapper.
*/
protected $_fieldNames = array();
-
- /**
- * Temporary data which is then loaded into Doctrine_Record::$_data.
- *
- * @var array $data
- */
- protected $_data = array();
/**
* The Doctrine_Connection object that the database connection of this mapper.
@@ -372,10 +366,9 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
*
* @return Doctrine_Record
*/
- public function getRecord()
+ public function getRecord(array $data)
{
- if ( ! empty($this->_data)) {
-
+ if ( ! empty($data)) {
$identifierFieldNames = $this->_table->getIdentifier();
if ( ! is_array($identifierFieldNames)) {
@@ -384,18 +377,19 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
$found = false;
foreach ($identifierFieldNames as $fieldName) {
- if ( ! isset($this->_data[$fieldName])) {
+ if ( ! isset($data[$fieldName])) {
// primary key column not found return new record
$found = true;
break;
}
- $id[] = $this->_data[$fieldName];
+ $id[] = $data[$fieldName];
}
if ($found) {
- $recordName = $this->getClassnameToReturn();
- $record = new $recordName($this, true);
- $this->_data = array();
+ //$recordName = $this->getClassnameToReturn();
+ //$record = new $recordName($this, true);
+ $record = new $this->_domainClassName($this, true, $data);
+ $data = array();
return $record;
}
@@ -404,16 +398,18 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
if (isset($this->_identityMap[$id])) {
$record = $this->_identityMap[$id];
- $record->hydrate($this->_data);
+ $record->hydrate($data);
} else {
- $recordName = $this->getClassnameToReturn();
- $record = new $recordName($this);
+ //$recordName = $this->getClassnameToReturn();
+ //$record = new $recordName($this);
+ $record = new $this->_domainClassName($this, false, $data);
$this->_identityMap[$id] = $record;
}
- $this->_data = array();
+ $data = array();
} else {
- $recordName = $this->getClassnameToReturn();
- $record = new $recordName($this, true);
+ //$recordName = $this->getClassnameToReturn();
+ //$record = new $recordName($this, true);
+ $record = new $this->_domainClassName($this, true, $data);
}
return $record;
@@ -435,7 +431,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
* @return string The name of the class to create
*
*/
- public function getClassnameToReturn()
+ /*public function getClassnameToReturn()
{
$subClasses = $this->_table->getOption('subclasses');
if ( ! isset($subClasses)) {
@@ -457,7 +453,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
}
}
return $this->_domainClassName;
- }
+ }*/
/**
* @param $id database row id
@@ -472,15 +468,15 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
. ' WHERE ' . implode(' = ? && ', $identifierColumnNames) . ' = ?';
$query = $this->applyInheritance($query);
- $params = array_merge(array($id), array_values($this->getDiscriminatorColumn($this->_domainClassName)));
+ $params = array_merge(array($id), array_values($this->getDiscriminatorColumn()));
- $this->_data = $this->_conn->execute($query, $params)->fetch(PDO::FETCH_ASSOC);
+ $data = $this->_conn->execute($query, $params)->fetch(PDO::FETCH_ASSOC);
- if ($this->_data === false) {
+ if ($data === false) {
return false;
}
}
- return $this->getRecord();
+ return $this->getRecord($data);
}
/**
@@ -490,7 +486,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
*/
final public function applyInheritance($where)
{
- $inheritanceMap = $this->getDiscriminatorColumn($this->_domainClassName);
+ $inheritanceMap = $this->getDiscriminatorColumn();
if ( ! empty($inheritanceMap)) {
$a = array();
foreach ($inheritanceMap as $field => $value) {
@@ -523,30 +519,6 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
return $graph;
}
- /**
- * setData
- * doctrine uses this function internally
- * users are strongly discouraged to use this function
- *
- * @param array $data internal data
- * @return void
- */
- public function setData(array $data)
- {
- $this->_data = $data;
- }
-
- /**
- * returns internal data, used by Doctrine_Record instances
- * when retrieving data from database
- *
- * @return array
- */
- public function getData()
- {
- return $this->_data;
- }
-
/**
* prepareValue
* this method performs special data preparation depending on
@@ -728,12 +700,18 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
}
/**
+ * Saves an entity and all it's related entities.
*
+ * @param Doctrine_Record $record The entity to save.
+ * @param Doctrine_Connection $conn The connection to use. Will default to the mapper's
+ * connection.
+ * @throws Doctrine_Mapper_Exception If the mapper is unable to save the given record.
*/
- public function saveGraph(Doctrine_Record $record, Doctrine_Connection $conn = null)
+ public function save(Doctrine_Record $record, Doctrine_Connection $conn = null)
{
- if ($this->_domainClassName != get_class($record)) {
- echo "mismatch: " . $this->_domainClassName . " <-> " . get_class($record) . "
";
+ if ( ! ($record instanceof $this->_domainClassName)) {
+ throw new Doctrine_Mapper_Exception("Mapper of type " . $this->_domainClassName . "
+ can't save instances of type" . get_class($record) . ".");
}
if ($conn === null) {
@@ -798,9 +776,8 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
// save the MANY-TO-MANY associations
$this->saveAssociations($record);
-
+ // reset state
$record->state($state);
-
$conn->commit();
} catch (Exception $e) {
// save() calls can be nested recursively and exceptions bubble up, so check
@@ -815,14 +792,64 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
return true;
}
+ /**
+ * Inserts a single entity into the database, without any related entities.
+ *
+ * @param Doctrine_Record $record The entity to insert.
+ */
+ protected function insertSingleRecord(Doctrine_Record $record)
+ {
+ $fields = $record->getPrepared();
+ if (empty($fields)) {
+ return false;
+ }
+
+ $table = $record->getTable();
+ $identifier = (array) $table->getIdentifier();
+
+ $seq = $table->getOption('sequenceName');
+ if ( ! empty($seq)) {
+ $id = $this->_conn->sequence->nextId($seq);
+ $seqName = $table->getIdentifier();
+ $fields[$seqName] = $id;
+ $record->assignIdentifier($id);
+ }
+
+ $this->_conn->insert($table, $fields);
+
+ if (empty($seq) && count($identifier) == 1 && $identifier[0] == $table->getIdentifier() &&
+ $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
+
+ if (strtolower($this->getName()) == 'pgsql') {
+ $seq = $table->getTableName() . '_' . $identifier[0];
+ }
+
+ $id = $this->_conn->sequence->lastInsertId($seq);
+
+ if ( ! $id) {
+ throw new Doctrine_Connection_Exception("Couldn't get last insert identifier.");
+ }
+
+ $record->assignIdentifier($id);
+ } else {
+ $record->assignIdentifier(true);
+ }
+ }
+
+ protected function _fireEvent($type, $callback, $invoker)
+ {
+
+ }
+
/**
* saves the given record
*
* @param Doctrine_Record $record
* @return void
*/
- public function save(Doctrine_Record $record)
+ public function saveSingleRecord(Doctrine_Record $record)
{
+ //$this->_fireEvent(Doctrine_Event::RECORD_SAVE, 'preSave', $record);
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
$record->preSave($event);
$this->getRecordListener()->preSave($event);
@@ -925,7 +952,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
$assocRecord->set($assocTable->getFieldName($rel->getForeign()), $r);
$assocRecord->set($assocTable->getFieldName($rel->getLocal()), $record);
- $this->save($assocRecord);
+ $this->saveSingleRecord($assocRecord);
}
}
}
@@ -938,7 +965,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
* @return boolean whether or not the update was successful
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
*/
- public function update(Doctrine_Record $record)
+ protected function update(Doctrine_Record $record)
{
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE);
$record->preUpdate($event);
@@ -946,10 +973,7 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
$this->getRecordListener()->preUpdate($event);
if ( ! $event->skipOperation) {
- $identifier = $record->identifier();
- $array = $record->getPrepared();
- $this->_conn->update($table, $array, $identifier);
- $record->assignIdentifier(true);
+ $this->_doUpdate($record);
}
$this->getRecordListener()->postUpdate($event);
@@ -958,22 +982,29 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
return true;
}
+ protected function _doUpdate(Doctrine_Record $record)
+ {
+ $identifier = $record->identifier();
+ $array = $record->getPrepared();
+ $this->_conn->update($this->_table, $array, $identifier);
+ $record->assignIdentifier(true);
+ }
+
/**
* inserts a record into database
*
* @param Doctrine_Record $record record to be inserted
* @return boolean
- * @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
*/
- public function insert(Doctrine_Record $record)
- {
+ protected function insert(Doctrine_Record $record)
+ {
// trigger event
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_INSERT);
$record->preInsert($event);
$this->getRecordListener()->preInsert($event);
if ( ! $event->skipOperation) {
- $this->_conn->processSingleInsert($record);
+ $this->_doInsert($record);
}
// trigger event
@@ -984,9 +1015,95 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
return true;
}
- public function delete(Doctrine_Record $record)
+ protected function _doInsert(Doctrine_Record $record)
{
+ $this->insertSingleRecord($record);
+ }
+
+ /**
+ * deletes given record and all the related composites
+ * this operation is isolated by a transaction
+ *
+ * this event can be listened by the onPreDelete and onDelete listeners
+ *
+ * @return boolean true on success, false on failure
+ * @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
+ */
+ public function delete(Doctrine_Record $record, Doctrine_Connection $conn = null)
+ {
+ if ( ! $record->exists()) {
+ return false;
+ }
+ if ( ! ($record instanceof $this->_domainClassName)) {
+ throw new Doctrine_Mapper_Exception("Mapper of type " . $this->_domainClassName . "
+ can't save instances of type" . get_class($record) . ".");
+ }
+
+ if ($conn == null) {
+ $conn = $this->_conn;
+ }
+
+ $event = new Doctrine_Event($record, Doctrine_Event::RECORD_DELETE);
+ $record->preDelete($event);
+ $this->getRecordListener()->preDelete($event);
+
+ $table = $this->_table;
+
+ $state = $record->state();
+ $record->state(Doctrine_Record::STATE_LOCKED);
+
+ if ( ! $event->skipOperation) {
+ $this->_doDelete($record, $conn);
+ } else {
+ // return to original state
+ $record->state($state);
+ }
+
+ $this->getRecordListener()->postDelete($event);
+ $record->postDelete($event);
+
+ return true;
+ }
+
+ protected function _doDelete(Doctrine_Record $record, Doctrine_Connection $conn)
+ {
+ try {
+ $conn->beginInternalTransaction();
+ $this->deleteComposites($record);
+
+ $record->state(Doctrine_Record::STATE_TDIRTY);
+
+ $conn->delete($this->_table, $record->identifier());
+ $record->state(Doctrine_Record::STATE_TCLEAN);
+
+ $this->removeRecord($record);
+ $conn->commit();
+ } catch (Exception $e) {
+ $conn->rollback();
+ throw $e;
+ }
+
+ }
+
+ /**
+ * deletes all related composites
+ * this method is always called internally when a record is deleted
+ *
+ * @throws PDOException if something went wrong at database level
+ * @return void
+ */
+ protected function deleteComposites(Doctrine_Record $record)
+ {
+ foreach ($this->_table->getRelations() as $fk) {
+ if ($fk->isComposite()) {
+ $obj = $record->get($fk->getAlias());
+ if ($obj instanceof Doctrine_Record &&
+ $obj->state() != Doctrine_Record::STATE_LOCKED) {
+ $obj->delete($this->_conn);
+ }
+ }
+ }
}
public function executeQuery(Doctrine_Query $query)
@@ -998,15 +1115,10 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
{
return $this->_table;
}
-
- public function getCustomJoins()
+
+ public function getFieldName($columnName)
{
- return array();
- }
-
- public function getDiscriminatorColumn($domainClassName)
- {
- return array();
+ return $this->_table->getFieldName($columnName);
}
public function getFieldNames()
@@ -1014,15 +1126,14 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
if ($this->_fieldNames) {
return $this->_fieldNames;
}
-
$this->_fieldNames = $this->_table->getFieldNames();
- return $this->_table->getFieldNames();
+ return $this->_fieldNames;
}
- /*public function free()
+ public function getOwningTable($fieldName)
{
- unset($this->_table);
- }*/
+ return $this->_table;
+ }
public function getIdentityMap()
{
@@ -1034,4 +1145,31 @@ class Doctrine_Mapper extends Doctrine_Configurable implements Countable
var_dump($this->_invokedMethods);
}
+
+ /*public function addToWhere($componentAlias, array &$sqlWhereParts, Doctrine_Query $query)
+ {
+
+ }
+
+ public function addToFrom($sqlString, Doctrine_Query $query)
+ {
+
+ }*/
+
+ /* Hooks used during SQL query construction to manipulate the query. */
+
+ public function getCustomJoins()
+ {
+ return array();
+ }
+
+ public function getCustomFields()
+ {
+ return array();
+ }
+
+ public function getDiscriminatorColumn()
+ {
+ return array();
+ }
}
diff --git a/lib/Doctrine/Mapper/Joined.php b/lib/Doctrine/Mapper/Joined.php
index 5c02fb47c..06a03799e 100644
--- a/lib/Doctrine/Mapper/Joined.php
+++ b/lib/Doctrine/Mapper/Joined.php
@@ -1,7 +1,8 @@
_table;
@@ -19,19 +20,39 @@ class Doctrine_Mapper_Joined extends Doctrine_Mapper
$classes = $table->getOption('joinedParents');
array_unshift($classes, $component);
-
- foreach (array_reverse($classes) as $k => $parent) {
- if ($k === 0) {
- $rootRecord = new $parent();
- $rootRecord->merge($dataSet[$parent]);
- parent::insert($rootRecord);
- $record->assignIdentifier($rootRecord->identifier());
- } else {
- foreach ((array) $rootRecord->identifier() as $id => $value) {
- $dataSet[$parent][$id] = $value;
+
+ try {
+ $this->_conn->beginInternalTransaction();
+ $identifier = null;
+ foreach (array_reverse($classes) as $k => $parent) {
+ $parentTable = $this->_conn->getTable($parent);
+ if ($k == 0) {
+ $identifierType = $parentTable->getIdentifierType();
+ if ($identifierType == Doctrine::IDENTIFIER_AUTOINC) {
+ $this->_conn->insert($parentTable, $dataSet[$parent]);
+ $identifier = $this->_conn->sequence->lastInsertId();
+ } else if ($identifierType == Doctrine::IDENTIFIER_SEQUENCE) {
+ $seq = $record->getTable()->getOption('sequenceName');
+ if ( ! empty($seq)) {
+ $identifier = $this->_conn->sequence->nextId($seq);
+ $dataSet[$parent][$parentTable->getIdentifier()] = $identifier;
+ $this->_conn->insert($parentTable, $dataSet[$parent]);
+ }
+ } else {
+ throw new Doctrine_Mapper_Exception("Unsupported identifier type '$identifierType'.");
+ }
+ $record->assignIdentifier($identifier);
+ } else {
+ foreach ((array) $record->identifier() as $id => $value) {
+ $dataSet[$parent][$id] = $value;
+ }
+ $this->_conn->insert($parentTable, $dataSet[$parent]);
}
- $this->_conn->insert($this->_conn->getTable($parent), $dataSet[$parent]);
}
+ $this->_conn->commit();
+ } catch (Exception $e) {
+ $this->_conn->rollback();
+ throw $e;
}
return true;
@@ -44,39 +65,58 @@ class Doctrine_Mapper_Joined extends Doctrine_Mapper
* @return boolean whether or not the update was successful
* @todo Move to Doctrine_Table (which will become Doctrine_Mapper).
*/
- public function update(Doctrine_Record $record)
+ protected function _doUpdate(Doctrine_Record $record)
{
- $event = new Doctrine_Event($record, Doctrine_Event::RECORD_UPDATE);
- $record->preUpdate($event);
$table = $this->_table;
- $this->getRecordListener()->preUpdate($event);
+ $identifier = $record->identifier();
+ $dataSet = $this->_formatDataSet($record);
+ $component = $table->getComponentName();
+ $classes = $table->getOption('joinedParents');
+ array_unshift($classes, $component);
- if ( ! $event->skipOperation) {
- $identifier = $record->identifier();
- $dataSet = $this->_formatDataSet($record);
- $component = $table->getComponentName();
- $classes = $table->getOption('joinedParents');
- array_unshift($classes, $component);
-
- foreach ($record as $field => $value) {
- if ($value instanceof Doctrine_Record) {
- if ( ! $value->exists()) {
- $value->save();
- }
- $record->set($field, $value->getIncremented());
+ foreach ($record as $field => $value) {
+ if ($value instanceof Doctrine_Record) {
+ if ( ! $value->exists()) {
+ $value->save();
}
+ $record->set($field, $value->getIncremented());
}
+ }
- foreach (array_reverse($classes) as $class) {
- $parentTable = $this->_conn->getTable($class);
- $this->_conn->update($parentTable, $dataSet[$class], $identifier);
- }
-
- $record->assignIdentifier(true);
+ foreach (array_reverse($classes) as $class) {
+ $parentTable = $this->_conn->getTable($class);
+ $this->_conn->update($parentTable, $dataSet[$class], $identifier);
}
- $this->getRecordListener()->postUpdate($event);
- $record->postUpdate($event);
+ $record->assignIdentifier(true);
+
+ return true;
+ }
+
+
+ protected function _doDelete(Doctrine_Record $record, Doctrine_Connection $conn)
+ {
+ try {
+ $table = $this->_table;
+ $conn->beginInternalTransaction();
+ $this->deleteComposites($record);
+
+ $record->state(Doctrine_Record::STATE_TDIRTY);
+
+ foreach ($table->getOption('joinedParents') as $parent) {
+ $parentTable = $conn->getTable($parent);
+ $conn->delete($parentTable, $record->identifier());
+ }
+
+ $conn->delete($table, $record->identifier());
+ $record->state(Doctrine_Record::STATE_TCLEAN);
+
+ $this->removeRecord($record);
+ $conn->commit();
+ } catch (Exception $e) {
+ $conn->rollback();
+ throw $e;
+ }
return true;
}
@@ -87,13 +127,33 @@ class Doctrine_Mapper_Joined extends Doctrine_Mapper
*/
public function getCustomJoins()
{
- return $this->_table->getOption('joinedParents');
+ $customJoins = array();
+ foreach ($this->_table->getOption('joinedParents') as $parentClass) {
+ $customJoins[$parentClass] = 'INNER';
+ }
+ foreach ((array)$this->_table->getOption('subclasses') as $subClass) {
+ if ($subClass != $this->_domainClassName) {
+ $customJoins[$subClass] = 'LEFT';
+ }
+ }
+ return $customJoins;
+ }
+
+ public function getCustomFields()
+ {
+ $fields = array();
+ if ($this->_table->getOption('subclasses')) {
+ foreach ($this->_table->getOption('subclasses') as $subClass) {
+ $fields = array_merge($this->_conn->getTable($subClass)->getFieldNames(), $fields);
+ }
+ }
+ return array_unique($fields);
}
/**
*
*/
- public function getDiscriminatorColumn($domainClassName)
+ public function getDiscriminatorColumn()
{
$joinedParents = $this->_table->getOption('joinedParents');
if (count($joinedParents) <= 0) {
@@ -101,7 +161,7 @@ class Doctrine_Mapper_Joined extends Doctrine_Mapper
} else {
$inheritanceMap = $this->_conn->getTable(array_pop($joinedParents))->getOption('inheritanceMap');
}
- return isset($inheritanceMap[$domainClassName]) ? $inheritanceMap[$domainClassName] : array();
+ return isset($inheritanceMap[$this->_domainClassName]) ? $inheritanceMap[$this->_domainClassName] : array();
}
/**
@@ -115,14 +175,67 @@ class Doctrine_Mapper_Joined extends Doctrine_Mapper
$fieldNames = $this->_table->getFieldNames();
foreach ($this->_table->getOption('joinedParents') as $parent) {
- $fieldNames = array_merge($this->_conn->getTable($parent)->getFieldNames(),
- $fieldNames);
+ $parentTable = $this->_conn->getTable($parent);
+ $fieldNames = array_merge($parentTable->getFieldNames(), $fieldNames);
}
- $this->_fieldNames = $fieldNames;
+ $this->_fieldNames = array_unique($fieldNames);
return $fieldNames;
}
+ public function getFieldName($columnName)
+ {
+ if (isset($this->_columnNameFieldNameMap[$columnName])) {
+ return $this->_columnNameFieldNameMap[$columnName];
+ }
+
+ if ($this->_table->hasColumn($columnName)) {
+ $this->_columnNameFieldNameMap[$columnName] = $this->_table->getFieldName($columnName);
+ return $this->_columnNameFieldNameMap[$columnName];
+ }
+
+ foreach ($this->_table->getOption('joinedParents') as $parentClass) {
+ $parentTable = $this->_conn->getTable($parentClass);
+ if ($parentTable->hasColumn($columnName)) {
+ $this->_columnNameFieldNameMap[$columnName] = $parentTable->getFieldName($columnName);
+ return $this->_columnNameFieldNameMap[$columnName];
+ }
+ }
+
+ foreach ((array)$this->_table->getOption('subclasses') as $subClass) {
+ $subTable = $this->_conn->getTable($subClass);
+ if ($subTable->hasColumn($columnName)) {
+ $this->_columnNameFieldNameMap[$columnName] = $subTable->getFieldName($columnName);
+ return $this->_columnNameFieldNameMap[$columnName];
+ }
+ }
+
+ throw new Doctrine_Mapper_Exception("No field name found for column name '$columnName'.");
+ }
+
+ public function getOwningTable($fieldName)
+ {
+ if ($this->_table->hasField($fieldName)) {
+ return $this->_table;
+ }
+
+ foreach ($this->_table->getOption('joinedParents') as $parentClass) {
+ $parentTable = $this->_conn->getTable($parentClass);
+ if ($parentTable->hasField($fieldName)) {
+ return $parentTable;
+ }
+ }
+
+ foreach ((array)$this->_table->getOption('subclasses') as $subClass) {
+ $subTable = $this->_conn->getTable($subClass);
+ if ($subTable->hasField($fieldName)) {
+ return $subTable;
+ }
+ }
+
+ throw new Doctrine_Mapper_Exception("Unable to find owner of field '$fieldName'.");
+ }
+
/**
*
*/
diff --git a/lib/Doctrine/Mapper/SingleTable.php b/lib/Doctrine/Mapper/SingleTable.php
index fb77d84cd..5ab32d4b6 100644
--- a/lib/Doctrine/Mapper/SingleTable.php
+++ b/lib/Doctrine/Mapper/SingleTable.php
@@ -1,15 +1,63 @@
_table->getOption('inheritanceMap');
- return isset($inheritanceMap[$domainClassName]) ? $inheritanceMap[$domainClassName] : array();
+ return isset($inheritanceMap[$this->_domainClassName]) ? $inheritanceMap[$this->_domainClassName] : array();
}
-
-
+ /*public function addToWhere($componentAlias, array &$sqlWhereParts, Doctrine_Query $query)
+ {
+ $array = array();
+ $componentParts = $query->getQueryComponent($componentAlias);
+ $sqlTableAlias = $query->getSqlTableAlias($componentAlias);
+ $array[$sqlTableAlias][] = $this->getDiscriminatorColumn();
+
+ // apply inheritance maps
+ $str = '';
+ $c = array();
+
+ $index = 0;
+ foreach ($array as $tableAlias => $maps) {
+ $a = array();
+
+ // don't use table aliases if the query isn't a select query
+ if ($query->getType() !== Doctrine_Query::SELECT) {
+ $tableAlias = '';
+ } else {
+ $tableAlias .= '.';
+ }
+
+ foreach ($maps as $map) {
+ $b = array();
+ foreach ($map as $field => $value) {
+ $identifier = $this->_conn->quoteIdentifier($tableAlias . $field);
+
+ if ($index > 0) {
+ $b[] = '(' . $identifier . ' = ' . $this->_conn->quote($value)
+ . ' OR ' . $identifier . ' IS NULL)';
+ } else {
+ $b[] = $identifier . ' = ' . $this->_conn->quote($value);
+ }
+ }
+
+ if ( ! empty($b)) {
+ $a[] = implode(' AND ', $b);
+ }
+ }
+
+ if ( ! empty($a)) {
+ $c[] = implode(' AND ', $a);
+ }
+ $index++;
+ }
+
+ $str .= implode(' AND ', $c);
+
+ return $str;
+ }*/
}
diff --git a/lib/Doctrine/Mapper/TablePerClass.php b/lib/Doctrine/Mapper/TablePerClass.php
index ab34412b8..d4851fbba 100644
--- a/lib/Doctrine/Mapper/TablePerClass.php
+++ b/lib/Doctrine/Mapper/TablePerClass.php
@@ -1,6 +1,6 @@
_state === self::STATE_LOCKED) {
- throw new Doctrine_Query_Exception('This query object is locked. No query parts can be manipulated.');
- }
-
- // sanity check
- if ($queryPart === '' || $queryPart === null) {
- throw new Doctrine_Query_Exception('Empty ' . $queryPartName . ' part given.');
- }
-
- // add query part to the dql part array
- if ($append) {
- $this->_dqlParts[$queryPartName][] = $queryPart;
- } else {
- $this->_dqlParts[$queryPartName] = array($queryPart);
- }
-
- if ($this->_state === self::STATE_DIRECT) {
- $parser = $this->_getParser($queryPartName);
-
- $sql = $parser->parse($queryPart);
-
- if (isset($sql)) {
- if ($append) {
- $this->addSqlQueryPart($queryPartName, $sql);
- } else {
- $this->setSqlQueryPart($queryPartName, $sql);
- }
- }
- }
-
- $this->_state = Doctrine_Query::STATE_DIRTY;
-
- return $this;
- }*/
-
+
/**
* getDqlPart
* returns a specific DQL query part.
@@ -480,8 +432,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
*/
public function processPendingFields($componentAlias)
{
- $tableAlias = $this->getTableAlias($componentAlias);
- $table = $this->_queryComponents[$componentAlias]['table'];
+ $tableAlias = $this->getSqlTableAlias($componentAlias);
+ $baseTable = $this->_queryComponents[$componentAlias]['table'];
+ $mapper = $this->_queryComponents[$componentAlias]['mapper'];
if ( ! isset($this->_pendingFields[$componentAlias])) {
return;
@@ -489,41 +442,39 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$fields = $this->_pendingFields[$componentAlias];
-
// check for wildcards
if (in_array('*', $fields)) {
- //echo "
";Doctrine::dump($table->getColumnNames()); echo "
";
- $fields = $table->getFieldNames();
+ $fields = $mapper->getFieldNames();
} else {
// only auto-add the primary key fields if this query object is not
// a subquery of another query object
if ( ! $this->_isSubquery) {
- $fields = array_unique(array_merge((array) $table->getIdentifier(), $fields));
+ $fields = array_unique(array_merge((array) $baseTable->getIdentifier(), $fields));
}
}
+ $fields = array_unique(array_merge($fields, $mapper->getCustomFields()));
+
$sql = array();
foreach ($fields as $fieldName) {
- $columnName = $table->getColumnName($fieldName);
- if (($owner = $table->getColumnOwner($columnName)) !== null &&
- $owner !== $table->getComponentName()) {
- $parent = $this->_conn->getTable($owner);
- $columnName = $parent->getColumnName($fieldName);
- $parentAlias = $this->getTableAlias($componentAlias . '.' . $parent->getComponentName());
- $sql[] = $this->_conn->quoteIdentifier($parentAlias . '.' . $columnName)
- . ' AS '
- . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
+ $table = $mapper->getOwningTable($fieldName);
+ if ($table !== $baseTable) {
+ $tableAlias = $this->getSqlTableAlias($componentAlias . '.' . $table->getComponentName());
} else {
- $columnName = $table->getColumnName($fieldName);
- $sql[] = $this->_conn->quoteIdentifier($tableAlias . '.' . $columnName)
- . ' AS '
- . $this->_conn->quoteIdentifier($tableAlias . '__' . $columnName);
+ $tableAlias = $this->getSqlTableAlias($componentAlias);
+ }
+
+ $columnName = $table->getColumnName($fieldName);
+ $columnName = $table->getColumnName($fieldName);
+ $sql[] = $this->_conn->quoteIdentifier($tableAlias . '.' . $columnName)
+ . ' AS '
+ . $this->_conn->quoteIdentifier($this->getSqlTableAlias($componentAlias) . '__' . $columnName);
+
+ if ( ! in_array($tableAlias, $this->_neededTables)) {
+ $this->_neededTables[] = $tableAlias;
}
}
-
- $this->_neededTables[] = $tableAlias;
- //Doctrine::dump(implode(', ', $sql));
- //echo "
";
+
return implode(', ', $sql);
}
@@ -617,7 +568,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
// check for DISTINCT keyword
if ($first === 'DISTINCT') {
$this->_sqlParts['distinct'] = true;
-
$refs[0] = substr($refs[0], ++$pos);
}
@@ -632,7 +582,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$terms = $this->_tokenizer->sqlExplode($reference, ' ');
- $pos = strpos($terms[0], '(');
+ $pos = strpos($terms[0], '(');
if (count($terms) > 1 || $pos !== false) {
$expression = array_shift($terms);
@@ -647,7 +597,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$tableAlias = $this->getTableAlias($componentAlias);
- $index = count($this->_aggregateAliasMap);
+ $index = count($this->_aggregateAliasMap);
$sqlAlias = $this->_conn->quoteIdentifier($tableAlias . '__' . $index);
@@ -670,7 +620,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$componentAlias = key($this->_queryComponents);
$field = $e[0];
}
-
$this->_pendingFields[$componentAlias][] = $field;
}
}
@@ -1156,7 +1105,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
}
// append discriminator column conditions (if any)
- $string = $this->_createDiscriminatorSql();
+ $string = $this->_createDiscriminatorConditionSql();
+ //echo "orig:$string
";
if ( ! empty($string)) {
if (substr($string, 0, 1) === '(' && substr($string, -1) === ')') {
$this->_sqlParts['where'][] = $string;
@@ -1482,23 +1432,21 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$componentAlias = $prevPath;
}
- // if the current alias already exists, skip it
+ // if the current alias already exists, it's user error
if (isset($this->_queryComponents[$componentAlias])) {
- continue;
+ throw new Doctrine_Query_Exception("Duplicate alias '$componentAlias' in query.");
}
if ( ! isset($table)) {
// process the root of the path
-
$table = $this->loadRoot($name, $componentAlias);
} else {
$join = ($delimeter == ':') ? 'INNER JOIN ' : 'LEFT JOIN ';
- //echo "!!!!!!" . $prevPath . "!!!!!
";
$relation = $table->getRelation($name);
$localTable = $table;
- $table = $relation->getTable();
- //echo "
" . $table->getComponentName() . "------" . $relation->getForeignComponentName() . "
";
+ $table = $relation->getTable();
+ //echo "
" . $table->getComponentName() . "------" . $relation->getForeignComponentName() . "
";
$this->_queryComponents[$componentAlias] = array(
'table' => $table,
'mapper' => $this->_conn->getMapper($relation->getForeignComponentName()),
@@ -1536,7 +1484,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
}
$assocPath = $prevPath . '.' . $asf->getComponentName();
- //var_dump($name); echo "hrrrr";
//echo "
" . $asf->getComponentName() . "---2---" . $relation->getForeignComponentName() . "
";
$this->_queryComponents[$assocPath] = array(
'parent' => $prevPath,
@@ -1592,7 +1539,6 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
}
}
} else {
-
$queryPart = $join . $foreignSql;
if ( ! $overrideJoin) {
@@ -1632,8 +1578,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
if (isset($e[1])) {
$indexBy = $e[1];
}
- } else if ($mapper->getBoundQueryPart('indexBy') !== null) {
- $indexBy = $mapper->getBoundQueryPart('indexBy');
+ } else if ($table->getBoundQueryPart('indexBy') !== null) {
+ $indexBy = $table->getBoundQueryPart('indexBy');
}
if ($indexBy !== null) {
@@ -1733,7 +1679,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable, Seria
$q .= ' FROM ' . $this->_buildSqlFromPart();
// append discriminator column conditions (if any)
- $string = $this->_createDiscriminatorSql();
+ $string = $this->_createDiscriminatorConditionSql();
if ( ! empty($string)) {
$where[] = $string;
}
diff --git a/lib/Doctrine/Query/Abstract.php b/lib/Doctrine/Query/Abstract.php
index b154c3a84..7c45067d8 100644
--- a/lib/Doctrine/Query/Abstract.php
+++ b/lib/Doctrine/Query/Abstract.php
@@ -532,11 +532,11 @@ abstract class Doctrine_Query_Abstract
$tableAlias = $this->getSqlTableAlias($componentAlias, $table->getTableName());
$customJoins = $this->_conn->getMapper($componentName)->getCustomJoins();
$sql = '';
- foreach ($customJoins as $componentName) {
+ foreach ($customJoins as $componentName => $joinType) {
$joinedTable = $this->_conn->getTable($componentName);
$joinedAlias = $componentAlias . '.' . $componentName;
$joinedTableAlias = $this->getSqlTableAlias($joinedAlias, $joinedTable->getTableName());
- $sql .= ' LEFT JOIN ' . $this->_conn->quoteIdentifier($joinedTable->getTableName())
+ $sql .= " $joinType JOIN " . $this->_conn->quoteIdentifier($joinedTable->getTableName())
. ' ' . $this->_conn->quoteIdentifier($joinedTableAlias) . ' ON ';
foreach ($table->getIdentifierColumnNames() as $column) {
@@ -556,23 +556,16 @@ abstract class Doctrine_Query_Abstract
*
* @return string The created SQL snippet.
*/
- protected function _createDiscriminatorSql()
- {
+ protected function _createDiscriminatorConditionSql()
+ {
$array = array();
foreach ($this->_queryComponents as $componentAlias => $data) {
- $tableAlias = $this->getSqlTableAlias($componentAlias);
- //echo $data['table']->getComponentName() . " -- ";
- /*if (!isset($data['mapper'])) {
- //echo $data['table']->getComponentName();
- echo $this->getDql();
- }*/
- /*if ($data['mapper']->getComponentName() != $data['table']->getComponentName()) {
- //echo $this->getDql() . "
";
- }*/
- //echo $data['mapper']->getComponentName() . "_
";
- //var_dump($data['mapper']->getDiscriminatorColumn($data['mapper']->getComponentName()));
-
- $array[$tableAlias][] = $data['mapper']->getDiscriminatorColumn($data['mapper']->getComponentName());
+ $sqlTableAlias = $this->getSqlTableAlias($componentAlias);
+ if ( ! $data['mapper'] instanceof Doctrine_Mapper_SingleTable) {
+ $array[$sqlTableAlias][] = array();
+ } else {
+ $array[$sqlTableAlias][] = $data['mapper']->getDiscriminatorColumn();
+ }
}
//var_dump($array);
// apply inheritance maps
diff --git a/lib/Doctrine/RawSql.php b/lib/Doctrine/RawSql.php
index bda9c8650..fb1d3798f 100644
--- a/lib/Doctrine/RawSql.php
+++ b/lib/Doctrine/RawSql.php
@@ -238,7 +238,7 @@ class Doctrine_RawSql extends Doctrine_Query_Abstract
}
}
- $string = $this->_createDiscriminatorSql();
+ $string = $this->_createDiscriminatorConditionSql();
if ( ! empty($string)) {
$this->_sqlParts['where'][] = $string;
}
diff --git a/lib/Doctrine/Record.php b/lib/Doctrine/Record.php
index 04b9c7546..0969a4578 100644
--- a/lib/Doctrine/Record.php
+++ b/lib/Doctrine/Record.php
@@ -146,7 +146,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* open connections
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
*/
- public function __construct($mapper = null, $isNewEntry = false)
+ public function __construct($mapper = null, $isNewEntry = false, array $data = array())
{
//echo get_class($this) . "
";
if (isset($mapper) && $mapper instanceof Doctrine_Table) {
@@ -155,18 +155,10 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
//$this->_mapper = Doctrine_Manager::getInstance()->getMapper(get_class($this));
$exists = ! $isNewEntry;
return;
- } else if (isset($mapper) && $mapper instanceof Doctrine_Mapper) {
+ } else if (isset($mapper) && $mapper instanceof Doctrine_Mapper_Abstract) {
//echo "two
";
$class = get_class($this);
$this->_mapper = Doctrine_Manager::getInstance()->getMapper($class);
- if ($class != $this->_mapper->getComponentName()) {
- try {
- throw new Exception("ddd");
- } catch (Exception $e) {
- echo "MISMATCH: " . get_class($this) . "---" . $mapper->getComponentName();
- echo $e->getTraceAsString() . "
";
- }
- }
$this->_table = $this->_mapper->getTable();
$exists = ! $isNewEntry;
} else {
@@ -182,7 +174,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
self::$_index++;
// get the data array
- $this->_data = $this->_mapper->getData();
+ $this->_data = $data;
// get the column count
$count = count($this->_data);
@@ -202,7 +194,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->assignDefaultValues();
} else {
$this->_state = Doctrine_Record::STATE_CLEAN;
-
+ // @TODO table->getColumnCount is not correct in CTI
if ($count < $this->_table->getColumnCount()) {
$this->_state = Doctrine_Record::STATE_PROXY;
}
@@ -213,7 +205,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$repository->add($this);
$this->construct();
-
}
/**
@@ -256,11 +247,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
{
return $this->_oid;
}
-
- public function oid()
- {
- return $this->_oid;
- }
/**
* isValid
@@ -534,22 +520,22 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
/**
- * serialize
- * this method is automatically called when this Doctrine_Record is serialized
+ * Serializes the entity.
+ * This method is automatically called when the entity is serialized.
+ *
+ * Part of the implementation of the Serializable interface.
*
* @return array
*/
public function serialize()
{
$event = new Doctrine_Event($this, Doctrine_Event::RECORD_SERIALIZE);
-
$this->preSerialize($event);
$vars = get_object_vars($this);
unset($vars['_references']);
unset($vars['_mapper']);
- //unset($vars['_table']);
unset($vars['_errorStack']);
unset($vars['_filter']);
unset($vars['_node']);
@@ -586,8 +572,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
/**
- * unseralize
- * this method is automatically called everytime a Doctrine_Record object is unserialized
+ * Reconstructs the entity from it's serialized form.
+ * This method is automatically called everytime the entity is unserialized.
*
* @param string $serialized Doctrine_Record as serialized string
* @throws Doctrine_Record_Exception if the cleanData operation fails somehow
@@ -634,6 +620,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->_mapper->getRepository()->add($this);
$this->cleanData($this->_data);
$this->prepareIdentifiers($this->exists());
+
$this->postUnserialize($event);
}
@@ -676,7 +663,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
if ($err) {
- throw new Doctrine_Record_Exception('Unknown record state ' . $state);
+ throw new Doctrine_Record_Exception("Unknown record state '$state'.");
}
}
@@ -863,12 +850,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
if ( ! isset($this->_references[$fieldName]) && $load) {
$rel = $this->_table->getRelation($fieldName);
$this->_references[$fieldName] = $rel->fetchRelatedFor($this);
- /*if (count($this->_references[$fieldName]) > 0) {
- echo $this->_references[$fieldName][0]->state() . "
";
- }*/
}
return $this->_references[$fieldName];
-
} catch (Doctrine_Table_Exception $e) {
//echo $e->getTraceAsString();
//echo "
";
@@ -937,12 +920,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->_modified[] = $fieldName;
switch ($this->_state) {
case Doctrine_Record::STATE_CLEAN:
- /*try {
- throw new Exception();
- } catch (Exception $e) {
- echo $e->getTraceAsString() . "
";
- }
- echo "setting dirty ...
";*/
$this->_state = Doctrine_Record::STATE_DIRTY;
break;
case Doctrine_Record::STATE_TCLEAN:
@@ -1004,7 +981,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
}
}
-
} else if ($rel instanceof Doctrine_Relation_Association) {
// join table relation found
if ( ! ($value instanceof Doctrine_Collection)) {
@@ -1070,7 +1046,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*/
public function save(Doctrine_Connection $conn = null)
{
- $this->_mapper->saveGraph($this, $conn);
+ $this->_mapper->save($this, $conn);
}
/**
@@ -1209,7 +1185,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
}
//$map = $this->_table->getOption('inheritanceMap');
- $map = $this->_mapper->getDiscriminatorColumn($this->_domainClassName);
+ $map = $this->_mapper->getDiscriminatorColumn();
foreach ($map as $k => $v) {
$old = $this->get($k, false);
if ((string) $old !== (string) $v || $old === null) {
@@ -1225,6 +1201,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* count
* this class implements countable interface
*
+ * Implementation of the Countable interface.
+ *
* @return integer the number of columns in this record
*/
public function count()
@@ -1436,10 +1414,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*/
public function delete(Doctrine_Connection $conn = null)
{
- if ($conn == null) {
- $conn = $this->_mapper->getConnection();
- }
- return $conn->unitOfWork->delete($this);
+ return $this->_mapper->delete($this, $conn);
}
/**
diff --git a/lib/Doctrine/Relation/Association.php b/lib/Doctrine/Relation/Association.php
index 3b778afc3..2b3ea6b98 100644
--- a/lib/Doctrine/Relation/Association.php
+++ b/lib/Doctrine/Relation/Association.php
@@ -107,7 +107,10 @@ class Doctrine_Relation_Association extends Doctrine_Relation
public function fetchRelatedFor(Doctrine_Record $record)
{
$id = $record->getIncremented();
+ //var_dump($id);
+ //echo "
";
if (empty($id) || ! $this->_foreignMapper->getAttribute(Doctrine::ATTR_LOAD_REFERENCES)) {
+ //echo "here" . $this->_foreignMapper->getAttribute(Doctrine::ATTR_LOAD_REFERENCES);
$coll = new Doctrine_Collection($this->getForeignComponentName());
} else {
$query = Doctrine_Query::create()->parseQuery($this->getRelationDql(1));
diff --git a/lib/Doctrine/Sequence/Mysql.php b/lib/Doctrine/Sequence/Mysql.php
index 088b22afe..c2e3ae100 100644
--- a/lib/Doctrine/Sequence/Mysql.php
+++ b/lib/Doctrine/Sequence/Mysql.php
@@ -47,10 +47,8 @@ class Doctrine_Sequence_Mysql extends Doctrine_Sequence
$query = 'INSERT INTO ' . $sequenceName . ' (' . $seqcolName . ') VALUES (NULL)';
try {
-
$this->conn->exec($query);
-
- } catch(Doctrine_Connection_Exception $e) {
+ } catch (Doctrine_Connection_Exception $e) {
if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
try {
$this->conn->export->createSequence($seqName);
diff --git a/lib/Doctrine/Sequence/Pgsql.php b/lib/Doctrine/Sequence/Pgsql.php
index c5ea04482..73e4ea7a1 100644
--- a/lib/Doctrine/Sequence/Pgsql.php
+++ b/lib/Doctrine/Sequence/Pgsql.php
@@ -47,7 +47,7 @@ class Doctrine_Sequence_Pgsql extends Doctrine_Sequence
$query = "SELECT NEXTVAL('" . $sequenceName . "')";
try {
$result = (int) $this->conn->fetchOne($query);
- } catch(Doctrine_Connection_Exception $e) {
+ } catch (Doctrine_Connection_Exception $e) {
if ($onDemand && $e->getPortableCode() == Doctrine::ERR_NOSUCHTABLE) {
try {
@@ -70,6 +70,7 @@ class Doctrine_Sequence_Pgsql extends Doctrine_Sequence
* @param string name of the table into which a new row was inserted
* @param string name of the field into which a new row was inserted
* @return integer the autoincremented id
+ * @todo Why not use $this->conn->getDbh()->lastInsertId($sequenceName) ?
*/
public function lastInsertId($table = null, $field = null)
{
diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php
index ce6a7addd..50d1f1727 100644
--- a/lib/Doctrine/Table.php
+++ b/lib/Doctrine/Table.php
@@ -437,6 +437,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Serializable
$fieldName = $parts[0];
}
$name = strtolower($parts[0]);
+
+ if (isset($this->_columnNames[$fieldName])) {
+ return;
+ }
+
if ($prepend) {
$this->_columnNames = array_merge(array($fieldName => $name), $this->_columnNames);
$this->_fieldNames = array_merge(array($name => $fieldName), $this->_fieldNames);
@@ -493,6 +498,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Serializable
if (isset($options['default'])) {
$this->hasDefaultValues = true;
}
+
+ $this->columnCount++;
}
/**
@@ -633,11 +640,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Serializable
{
return $this->columnCount;
}
-
- public function setColumnCount($count)
- {
- $this->columnCount = $count;
- }
/**
* returns all columns and their definitions
diff --git a/lib/Doctrine/Table/Factory.php b/lib/Doctrine/Table/Factory.php
index 3ad5edee1..6dfdbcfd6 100644
--- a/lib/Doctrine/Table/Factory.php
+++ b/lib/Doctrine/Table/Factory.php
@@ -200,11 +200,9 @@ class Doctrine_Table_Factory
$table->setOption('declaringClass', $class);
// set the table definition for the given tree implementation
- if ($table->isTree()) {
+ /*if ($table->isTree()) {
$table->getTree()->setTableDefinition();
- }
-
- $table->setColumnCount(count($table->getColumns()));
+ }*/
$tableName = $table->getOption('tableName');
if ( ! isset($tableName)) {
@@ -217,9 +215,9 @@ class Doctrine_Table_Factory
$record->setUp();
// if tree, set up tree relations
- if ($table->isTree()) {
+ /*if ($table->isTree()) {
$table->getTree()->setUp();
- }
+ }*/
return $table;
}
@@ -304,8 +302,6 @@ class Doctrine_Table_Factory
$table->setIdentifier('id');
$table->setIdentifierType(Doctrine::IDENTIFIER_AUTOINC);
}
- $currentCount = $table->getColumnCount();
- $table->setColumnCount(++$currentCount);
break;
case 1:
foreach ($table->getIdentifier() as $pk) {
diff --git a/lib/Doctrine/Table/Repository.php b/lib/Doctrine/Table/Repository.php
index 785811f6f..9659447d8 100644
--- a/lib/Doctrine/Table/Repository.php
+++ b/lib/Doctrine/Table/Repository.php
@@ -51,9 +51,9 @@ class Doctrine_Table_Repository implements Countable, IteratorAggregate
*
* @param Doctrine_Table $table
*/
- public function __construct(Doctrine_Mapper $table)
+ public function __construct(Doctrine_Mapper_Abstract $mapper)
{
- $this->table = $table;
+ $this->table = $mapper;
}
/**
diff --git a/lib/Doctrine/Transaction.php b/lib/Doctrine/Transaction.php
index 5a55e001f..fe1f3ce23 100644
--- a/lib/Doctrine/Transaction.php
+++ b/lib/Doctrine/Transaction.php
@@ -326,11 +326,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
public function rollback($savepoint = null)
{
if ($this->_nestingLevel == 0) {
- /*try {
- throw new Doctrine_Transaction_Exception("Rollback failed. There is no active transaction.");
- } catch (Exception $e) {
- echo $e->getTraceAsString() . "
";
- }*/
throw new Doctrine_Transaction_Exception("Rollback failed. There is no active transaction.");
}
diff --git a/lib/Doctrine/Tree/NestedSet.php b/lib/Doctrine/Tree/NestedSet.php
index 5e30f42af..d0424b162 100644
--- a/lib/Doctrine/Tree/NestedSet.php
+++ b/lib/Doctrine/Tree/NestedSet.php
@@ -319,39 +319,4 @@ class Doctrine_Tree_NestedSet extends Doctrine_Tree implements Doctrine_Tree_Int
$this->_baseQuery = $this->_createBaseQuery();
}
- /**
- * Enter description here...
- *
- * @param unknown_type $graph
- */
- /*
- public function computeLevels($tree)
- {
- $right = array();
- $isArray = is_array($tree);
- $rootColumnName = $this->getAttribute('rootColumnName');
-
- for ($i = 0, $count = count($tree); $i < $count; $i++) {
- if ($rootColumnName && $i > 0 && $tree[$i][$rootColumnName] != $tree[$i-1][$rootColumnName]) {
- $right = array();
- }
-
- if (count($right) > 0) {
- while (count($right) > 0 && $right[count($right)-1] < $tree[$i]['rgt']) {
- //echo count($right);
- array_pop($right);
- }
- }
-
- if ($isArray) {
- $tree[$i]['level'] = count($right);
- } else {
- $tree[$i]->getNode()->setLevel(count($right));
- }
-
- $right[] = $tree[$i]['rgt'];
- }
- return $tree;
- }
- */
}
\ No newline at end of file
diff --git a/tests/ConnectionTestCase.php b/tests/ConnectionTestCase.php
index 71cf1bb8a..2efccbd6c 100644
--- a/tests/ConnectionTestCase.php
+++ b/tests/ConnectionTestCase.php
@@ -151,9 +151,9 @@ class Doctrine_Connection_TestCase extends Doctrine_UnitTestCase
public function testDelete()
{
- $user = $this->connection->create('User');
- $this->connection->unitOfWork->delete($user);
- $this->assertEqual($user->state(),Doctrine_Record::STATE_TCLEAN);
+ //$user = $this->connection->create('User');
+ //$this->connection->unitOfWork->delete($user);
+ //$this->assertEqual($user->state(),Doctrine_Record::STATE_TCLEAN);
}
public function testGetTable()
diff --git a/tests/Inheritance/JoinedTestCase.php b/tests/Inheritance/JoinedTestCase.php
index 345928972..56bf8854b 100644
--- a/tests/Inheritance/JoinedTestCase.php
+++ b/tests/Inheritance/JoinedTestCase.php
@@ -140,6 +140,40 @@ class Doctrine_Inheritance_Joined_TestCase extends Doctrine_UnitTestCase
$this->assertEqual('Billy the Kid', $superManager->gosutitle);
$this->assertEqual(4, $superManager->type);
}
+
+ public function testDqlQueryJoinsTransparentlyAcrossParents()
+ {
+ $this->_createManager();
+ $this->conn->getMapper('CTI_Manager')->clear();
+
+ $query = $this->conn->createQuery();
+ $query->parseQuery("SELECT m.* FROM CTI_Manager m");
+ $manager = $query->execute()->getFirst();
+
+ $this->assertTrue($manager instanceof CTI_Manager);
+ $this->assertEqual(1, $manager->id);
+ $this->assertEqual(80000, $manager->salary);
+ $this->assertEqual('John Smith', $manager->name);
+ $this->assertEqual(2, $manager->type);
+ }
+
+ public function testQueryingBaseClassOuterJoinsSubClassesAndReturnsSubclassInstances()
+ {
+ $this->_createManager();
+ $this->conn->getMapper('CTI_Manager')->clear();
+ $this->conn->getMapper('CTI_User')->clear();
+
+ $query = $this->conn->createQuery();
+ $query->parseQuery("SELECT u.* FROM CTI_User u");
+ //echo $query->getSql();
+ $user = $query->execute()->getFirst();
+
+ $this->assertTrue($user instanceof CTI_Manager);
+ $this->assertEqual(1, $user->id);
+ $this->assertEqual(80000, $user->salary);
+ $this->assertEqual('John Smith', $user->name);
+ $this->assertEqual(2, $user->type);
+ }
}
@@ -152,7 +186,15 @@ class CTI_User extends Doctrine_Record
'CTI_Manager' => array('type' => 2),
'CTI_Customer' => array('type' => 3),
'CTI_SuperManager' => array('type' => 4))
- );
+ );/*
+ $class->setInheritanceType(Doctrine::INHERITANCETYPE_JOINED, array(
+ 'discriminatorColumn' => 'type',
+ 'map' => array(1 => 'CTI_User', 2 => 'CTI_Manager', 3 => 'CTI_Customer',
+ 4 => 'CTI_SuperManager')
+ ));
+ $class->setDiscriminatorValue(1);
+ $class->setInheritanceOption('fetchType', 'explicit');
+ */
$this->setTableName('cti_user');
$this->hasColumn('cti_id as id', 'integer', 4, array('primary' => true, 'autoincrement' => true));
$this->hasColumn('cti_foo as foo', 'integer', 4);
diff --git a/tests/Inheritance/SingleTableTestCase.php b/tests/Inheritance/SingleTableTestCase.php
index 2c797ad50..c8461d7ac 100644
--- a/tests/Inheritance/SingleTableTestCase.php
+++ b/tests/Inheritance/SingleTableTestCase.php
@@ -58,6 +58,16 @@ class Doctrine_Inheritance_SingleTable_TestCase extends Doctrine_UnitTestCase
$this->fail("Saving record in single table inheritance failed: " . $e->getMessage());
}
}
+
+ public function testQuery()
+ {
+ //$this->_createManager();
+ $query = $this->conn->createQuery();
+ $query->select("m.*")->from("STI_Manager m");
+ //echo $query->getSql();
+ //$managers = $query->execute();
+
+ }
}
diff --git a/tests/Query/JoinCondition2TestCase.php b/tests/Query/JoinCondition2TestCase.php
index ca6367d07..5101d139a 100755
--- a/tests/Query/JoinCondition2TestCase.php
+++ b/tests/Query/JoinCondition2TestCase.php
@@ -74,7 +74,7 @@ class Doctrine_Query_JoinCondition2_TestCase extends Doctrine_UnitTestCase
// Should only find zYne
$this->assertEqual($rs->count(), 1);
-
+
// Grab the number of runned queries
$queryCount = $this->connection->count();
diff --git a/tests/Query/MultiJoin2TestCase.php b/tests/Query/MultiJoin2TestCase.php
index 7341c5db8..43d22805b 100644
--- a/tests/Query/MultiJoin2TestCase.php
+++ b/tests/Query/MultiJoin2TestCase.php
@@ -85,7 +85,7 @@ class Doctrine_Query_MultiJoin2_TestCase extends Doctrine_UnitTestCase
->execute();
// Test that accessing a loaded (but empty) relation doesnt trigger an extra query
$this->assertEqual($queryCount + 1, $this->connection->count());
-
+ $this->assertEqual(0, count($categories[0]->subCategories));
$categories[0]->subCategories;
$this->assertEqual($queryCount + 1, $this->connection->count());
} catch (Doctrine_Exception $e) {
diff --git a/tests/QueryTestCase.php b/tests/QueryTestCase.php
index 46527698c..dbdb42ed5 100644
--- a/tests/QueryTestCase.php
+++ b/tests/QueryTestCase.php
@@ -101,6 +101,27 @@ class Doctrine_Query_TestCase extends Doctrine_UnitTestCase
//Doctrine::dump($q->getCachedForm(array('foo' => 'bar')));
$this->assertEqual($q->parseClause("CONCAT('u.name', u.name)"), "'u.name' || e.name");
}
+
+ public function testUsingDuplicateClassAliasThrowsException()
+ {
+ $q = new Doctrine_Query();
+ $q->from('User u')->leftJoin('u.Phonenumber u');
+ try {
+ $q->getSqlQuery();
+ $this->fail();
+ } catch (Doctrine_Query_Exception $e) {
+ $this->pass();
+ }
+
+ $q = new Doctrine_Query();
+ $q->parseDqlQuery('FROM User u, u.Phonenumber u');
+ try {
+ $q->getSqlQuery();
+ $this->fail();
+ } catch (Doctrine_Query_Exception $e) {
+ $this->pass();
+ }
+ }
}
class MyQuery extends Doctrine_Query
{