From 07c5c92e739bf7782422ce6deba17f59174889a0 Mon Sep 17 00:00:00 2001 From: zYne Date: Sat, 1 Sep 2007 17:28:11 +0000 Subject: [PATCH] deletes are no longer stacked in the end of transaction, now transactional integrity is always assured --- lib/Doctrine/Collection.php | 3 +- lib/Doctrine/Connection.php | 2 +- lib/Doctrine/Connection/UnitOfWork.php | 88 +++++++++++++++-- lib/Doctrine/Transaction.php | 132 ++++--------------------- 4 files changed, 104 insertions(+), 121 deletions(-) diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 8afd677da..f702b39c9 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -622,6 +622,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator $conn = $this->_table->getConnection(); } $conn->beginTransaction(); + $conn->transaction->addCollection($this); $this->processDiff(); @@ -631,7 +632,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator } $conn->commit(); - + return $this; } /** diff --git a/lib/Doctrine/Connection.php b/lib/Doctrine/Connection.php index f7b4ee16c..e4968671b 100644 --- a/lib/Doctrine/Connection.php +++ b/lib/Doctrine/Connection.php @@ -815,7 +815,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun */ public function exec($query, array $params = array()) { $this->connect(); - + print $query . print_r($params, true) . "
"; try { if ( ! empty($params)) { $stmt = $this->prepare($query); diff --git a/lib/Doctrine/Connection/UnitOfWork.php b/lib/Doctrine/Connection/UnitOfWork.php index b0547b6d0..2becf5ff3 100644 --- a/lib/Doctrine/Connection/UnitOfWork.php +++ b/lib/Doctrine/Connection/UnitOfWork.php @@ -183,7 +183,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module } else { $conn->transaction->addInvalid($record); } - + $state = $record->state(); $record->state(Doctrine_Record::STATE_LOCKED); @@ -261,18 +261,24 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module $record->getTable()->getRecordListener()->preDelete($event); + $state = $record->state(); + $record->state(Doctrine_Record::STATE_LOCKED); $this->deleteComposites($record); - - $record->state(Doctrine_Record::STATE_TDIRTY); if ( ! $event->skipOperation) { - $this->conn->transaction->addDelete($record); + $record->state(Doctrine_Record::STATE_TDIRTY); + + $this->deleteRecord($record); $record->state(Doctrine_Record::STATE_TCLEAN); + } else { + // return to original state + $record->state($state); } - + + $record->getTable()->getRecordListener()->postDelete($event); $record->postDelete($event); @@ -281,7 +287,77 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module return true; } + + public function deleteRecord(Doctrine_Record $record) + { + $ids = $record->identifier(); + $tmp = array(); + + foreach (array_keys($ids) as $id) { + $tmp[] = $id . ' = ? '; + } + + $params = array_values($ids); + $query = 'DELETE FROM ' + . $this->conn->quoteIdentifier($record->getTable()->getTableName()) + . ' WHERE ' . implode(' AND ', $tmp); + + + return $this->conn->exec($query, $params); + } + /** + * deleteMultiple + * deletes all records from the pending delete list + * + * @return void + */ + public function deleteMultiple(array $records) + { + + foreach ($this->delete as $name => $deletes) { + $record = false; + $ids = array(); + + if (is_array($deletes[count($deletes)-1]->getTable()->getIdentifier())) { + if (count($deletes) > 0) { + $query = 'DELETE FROM ' + . $this->conn->quoteIdentifier($deletes[0]->getTable()->getTableName()) + . ' WHERE '; + + $params = array(); + $cond = array(); + foreach ($deletes as $k => $record) { + $ids = $record->identifier(); + $tmp = array(); + foreach (array_keys($ids) as $id){ + $tmp[] = $id . ' = ? '; + } + $params = array_merge($params, array_values($ids)); + $cond[] = '(' . implode(' AND ', $tmp) . ')'; + } + $query .= implode(' OR ', $cond); + + $this->conn->execute($query, $params); + } + } else { + foreach ($deletes as $k => $record) { + $ids[] = $record->getIncremented(); + } + if ($record instanceof Doctrine_Record) { + $params = substr(str_repeat('?, ', count($ids)), 0, -2); + + $query = 'DELETE FROM ' + . $this->conn->quoteIdentifier($record->getTable()->getTableName()) + . ' WHERE ' + . $record->getTable()->getIdentifier() + . ' IN(' . $params . ')'; + + $this->conn->execute($query, $ids); + } + } + } + } /** * saveRelated * saves all related records to $record @@ -325,7 +401,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module * 3, 4 and 5, this method would first destroy the associations to 1 and 2 and then * save new associations to 4 and 5 * - * @throws PDOException if something went wrong at database level + * @throws Doctrine_Connection_Exception if something went wrong at database level * @param Doctrine_Record $record * @return void */ diff --git a/lib/Doctrine/Transaction.php b/lib/Doctrine/Transaction.php index 628285aef..8a72f82ee 100644 --- a/lib/Doctrine/Transaction.php +++ b/lib/Doctrine/Transaction.php @@ -54,11 +54,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module * @var array $invalid an array containing all invalid records within this transaction */ protected $invalid = array(); - /** - * @var array $delete two dimensional pending delete list, the records in - * this list will be deleted when transaction is committed - */ - protected $delete = array(); /** * @var array $savepoints an array containing all savepoints */ @@ -106,19 +101,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module } } - /** - * addDelete - * adds record into pending delete list - * - * @param Doctrine_Record $record a record to be added - * @return void - */ - public function addDelete(Doctrine_Record $record) - { - $name = $record->getTable()->getComponentName(); - $this->delete[$name][] = $record; - } - /** * addInvalid * adds record into invalid records list @@ -136,70 +118,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module return true; } - /** - * returns the pending delete list - * - * @return array - */ - public function getDeletes() - { - return $this->delete; - } - - /** - * bulkDelete - * deletes all records from the pending delete list - * - * @return void - */ - public function bulkDelete() - { - - foreach ($this->delete as $name => $deletes) { - $record = false; - $ids = array(); - - if (is_array($deletes[count($deletes)-1]->getTable()->getIdentifier())) { - if (count($deletes) > 0) { - $query = 'DELETE FROM ' - . $this->conn->quoteIdentifier($deletes[0]->getTable()->getTableName()) - . ' WHERE '; - - $params = array(); - $cond = array(); - foreach ($deletes as $k => $record) { - $ids = $record->identifier(); - $tmp = array(); - foreach (array_keys($ids) as $id){ - $tmp[] = $id . ' = ? '; - } - $params = array_merge($params, array_values($ids)); - $cond[] = '(' . implode(' AND ', $tmp) . ')'; - } - $query .= implode(' OR ', $cond); - - $this->conn->execute($query, $params); - } - } else { - foreach ($deletes as $k => $record) { - $ids[] = $record->getIncremented(); - } - if ($record instanceof Doctrine_Record) { - $params = substr(str_repeat('?, ', count($ids)), 0, -2); - - $query = 'DELETE FROM ' - . $this->conn->quoteIdentifier($record->getTable()->getTableName()) - . ' WHERE ' - . $record->getTable()->getIdentifier() - . ' IN(' . $params . ')'; - - $this->conn->execute($query, $ids); - } - } - - } - $this->delete = array(); - } /** * getTransactionLevel * get the current transaction nesting level @@ -311,40 +229,30 @@ class Doctrine_Transaction extends Doctrine_Connection_Module $listener->postSavepointCommit($event); } else { - if ($this->transactionLevel == 1) { - $event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT); - - $listener->preTransactionCommit($event); + if ($this->transactionLevel == 1) { + if ( ! empty($this->invalid)) { + $this->rollback(); - if ( ! $event->skipOperation) { - try { - $this->bulkDelete(); + $tmp = $this->invalid; + $this->invalid = array(); - } catch(Exception $e) { - $this->rollback(); - - throw new Doctrine_Transaction_Exception($e->getMessage()); - } - if ( ! empty($this->invalid)) { - $this->rollback(); - - $tmp = $this->invalid; - $this->invalid = array(); - - throw new Doctrine_Validator_Exception($tmp); - } - - // take snapshots of all collections used within this transaction - foreach ($this->_collections as $coll) { - $coll->takeSnapshot(); - } - $this->_collections = array(); - $this->conn->getDbh()->commit(); - - //$this->conn->unitOfWork->reset(); + throw new Doctrine_Validator_Exception($tmp); } + // take snapshots of all collections used within this transaction + foreach ($this->_collections as $coll) { + $coll->takeSnapshot(); + } + $this->_collections = array(); + + $event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT); + + $listener->preTransactionCommit($event); + if ( ! $event->skipOperation) { + $this->conn->getDbh()->commit(); + } $listener->postTransactionCommit($event); + } $this->transactionLevel--; @@ -395,8 +303,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module $listener->preTransactionRollback($event); if ( ! $event->skipOperation) { - $this->deteles = array(); - $this->transactionLevel = 0; try { $this->conn->getDbh()->rollback();