deletes are no longer stacked in the end of transaction, now transactional integrity is always assured
This commit is contained in:
parent
5d0caba0aa
commit
07c5c92e73
@ -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;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user