1
0
mirror of synced 2024-12-14 23:26:04 +03:00

deletes are no longer stacked in the end of transaction, now transactional integrity is always assured

This commit is contained in:
zYne 2007-09-01 17:28:11 +00:00
parent 5d0caba0aa
commit 07c5c92e73
4 changed files with 104 additions and 121 deletions

View File

@ -622,6 +622,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
$conn = $this->_table->getConnection(); $conn = $this->_table->getConnection();
} }
$conn->beginTransaction(); $conn->beginTransaction();
$conn->transaction->addCollection($this); $conn->transaction->addCollection($this);
$this->processDiff(); $this->processDiff();
@ -631,7 +632,7 @@ class Doctrine_Collection extends Doctrine_Access implements Countable, Iterator
} }
$conn->commit(); $conn->commit();
return $this; return $this;
} }
/** /**

View File

@ -815,7 +815,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
*/ */
public function exec($query, array $params = array()) { public function exec($query, array $params = array()) {
$this->connect(); $this->connect();
print $query . print_r($params, true) . "<br>";
try { try {
if ( ! empty($params)) { if ( ! empty($params)) {
$stmt = $this->prepare($query); $stmt = $this->prepare($query);

View File

@ -183,7 +183,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
} else { } else {
$conn->transaction->addInvalid($record); $conn->transaction->addInvalid($record);
} }
$state = $record->state(); $state = $record->state();
$record->state(Doctrine_Record::STATE_LOCKED); $record->state(Doctrine_Record::STATE_LOCKED);
@ -261,18 +261,24 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$record->getTable()->getRecordListener()->preDelete($event); $record->getTable()->getRecordListener()->preDelete($event);
$state = $record->state();
$record->state(Doctrine_Record::STATE_LOCKED); $record->state(Doctrine_Record::STATE_LOCKED);
$this->deleteComposites($record); $this->deleteComposites($record);
$record->state(Doctrine_Record::STATE_TDIRTY);
if ( ! $event->skipOperation) { if ( ! $event->skipOperation) {
$this->conn->transaction->addDelete($record); $record->state(Doctrine_Record::STATE_TDIRTY);
$this->deleteRecord($record);
$record->state(Doctrine_Record::STATE_TCLEAN); $record->state(Doctrine_Record::STATE_TCLEAN);
} else {
// return to original state
$record->state($state);
} }
$record->getTable()->getRecordListener()->postDelete($event); $record->getTable()->getRecordListener()->postDelete($event);
$record->postDelete($event); $record->postDelete($event);
@ -281,7 +287,77 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return true; 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 * saveRelated
* saves all related records to $record * 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 * 3, 4 and 5, this method would first destroy the associations to 1 and 2 and then
* save new associations to 4 and 5 * 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 * @param Doctrine_Record $record
* @return void * @return void
*/ */

View File

@ -54,11 +54,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
* @var array $invalid an array containing all invalid records within this transaction * @var array $invalid an array containing all invalid records within this transaction
*/ */
protected $invalid = array(); 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 * @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 * addInvalid
* adds record into invalid records list * adds record into invalid records list
@ -136,70 +118,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
return true; 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 * getTransactionLevel
* get the current transaction nesting level * get the current transaction nesting level
@ -311,40 +229,30 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
$listener->postSavepointCommit($event); $listener->postSavepointCommit($event);
} else { } else {
if ($this->transactionLevel == 1) { if ($this->transactionLevel == 1) {
$event = new Doctrine_Event($this, Doctrine_Event::TX_COMMIT); if ( ! empty($this->invalid)) {
$this->rollback();
$listener->preTransactionCommit($event);
if ( ! $event->skipOperation) { $tmp = $this->invalid;
try { $this->invalid = array();
$this->bulkDelete();
} catch(Exception $e) { throw new Doctrine_Validator_Exception($tmp);
$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();
} }
// 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); $listener->postTransactionCommit($event);
} }
$this->transactionLevel--; $this->transactionLevel--;
@ -395,8 +303,6 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
$listener->preTransactionRollback($event); $listener->preTransactionRollback($event);
if ( ! $event->skipOperation) { if ( ! $event->skipOperation) {
$this->deteles = array();
$this->transactionLevel = 0; $this->transactionLevel = 0;
try { try {
$this->conn->getDbh()->rollback(); $this->conn->getDbh()->rollback();