Skip to content

Commit

Permalink
Added real support to nested transactions for Mysql, Postgres, Sqlite.
Browse files Browse the repository at this point in the history
  • Loading branch information
jrbasso committed Apr 14, 2012
1 parent 2c9399a commit 2c1cf29
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 21 deletions.
9 changes: 9 additions & 0 deletions lib/Cake/Model/Datasource/Database/Mysql.php
Expand Up @@ -676,4 +676,13 @@ public function getSchemaName() {
return $this->config['database'];
}

/**
* Check if the server support nested transactions
*
* @return boolean
*/
protected function _supportNestedTransaction() {
return version_compare($this->getVersion(), '4.1', '>=');
}

}
9 changes: 9 additions & 0 deletions lib/Cake/Model/Datasource/Database/Postgres.php
Expand Up @@ -895,4 +895,13 @@ public function getSchemaName() {
return $this->config['schema'];
}

/**
* Check if the server support nested transactions
*
* @return boolean
*/
protected function _supportNestedTransaction() {
return version_compare($this->getVersion(), '8.0', '>=');
}

}
9 changes: 9 additions & 0 deletions lib/Cake/Model/Datasource/Database/Sqlite.php
Expand Up @@ -559,4 +559,13 @@ public function getSchemaName() {
return "main"; // Sqlite Datasource does not support multidb
}

/**
* Check if the server support nested transactions
*
* @return boolean
*/
protected function _supportNestedTransaction() {
return version_compare($this->getVersion(), '3.6.8', '>=');
}

}
111 changes: 90 additions & 21 deletions lib/Cake/Model/Datasource/DboSource.php
Expand Up @@ -2017,6 +2017,15 @@ public function truncate($table) {
return $this->execute('TRUNCATE TABLE ' . $this->fullTableName($table));
}

/**
* Check if the server support nested transactions
*
* @return boolean
*/
protected function _supportNestedTransaction() {
return false;
}

/**
* Begin a transaction
*
Expand All @@ -2025,15 +2034,33 @@ public function truncate($table) {
* or a transaction has not started).
*/
public function begin() {
if ($this->_transactionStarted || $this->_connection->beginTransaction()) {
if ($this->fullDebug && empty($this->_transactionNesting)) {
$this->logQuery('BEGIN');
if ($this->_transactionStarted) {
if ($this->_supportNestedTransaction()) {
return $this->_beginNested();
}
$this->_transactionStarted = true;
$this->_transactionNesting++;
return true;
return $this->_transactionStarted;
}
return false;

$this->_transactionNesting = 0;
if ($this->fullDebug) {
$this->logQuery('BEGIN');
}
return $this->_transactionStarted = $this->_connection->beginTransaction();
}

/**
* Begin a nested transaction
*
* @return boolean
*/
protected function _beginNested() {
$query = 'SAVEPOINT LEVEL' . ++$this->_transactionNesting;
if ($this->fullDebug) {
$this->logQuery($query);
}
$this->_connection->exec($query);
return true;
}

/**
Expand All @@ -2044,19 +2071,38 @@ public function begin() {
* or a transaction has not started).
*/
public function commit() {
if ($this->_transactionStarted) {
$this->_transactionNesting--;
if ($this->_transactionNesting <= 0) {
$this->_transactionStarted = false;
$this->_transactionNesting = 0;
if ($this->fullDebug) {
$this->logQuery('COMMIT');
}
return $this->_connection->commit();
if (!$this->_transactionStarted) {
return false;
}

if ($this->_transactionNesting === 0) {
if ($this->fullDebug) {
$this->logQuery('COMMIT');
}
return true;
$this->_transactionStarted = false;
return $this->_connection->commit();
}
return false;

if ($this->_supportNestedTransaction()) {
return $this->_commitNested();
}

$this->_transactionNesting--;
return true;
}

/**
* Commit a nested transaction
*
* @return boolean
*/
protected function _commitNested() {
$query = 'RELEASE SAVEPOINT LEVEL' . $this->_transactionNesting--;
if ($this->fullDebug) {
$this->logQuery($query);
}
$this->_connection->exec($query);
return true;
}

/**
Expand All @@ -2067,15 +2113,38 @@ public function commit() {
* or a transaction has not started).
*/
public function rollback() {
if ($this->_transactionStarted && $this->_connection->rollBack()) {
if (!$this->_transactionStarted) {
return false;
}

if ($this->_transactionNesting === 0) {
if ($this->fullDebug) {
$this->logQuery('ROLLBACK');
}
$this->_transactionStarted = false;
$this->_transactionNesting = 0;
return true;
return $this->_connection->rollBack();
}
return false;

if ($this->_supportNestedTransaction()) {
return $this->_rollbackNested();
}

$this->_transactionNesting--;
return true;
}

/**
* Rollback a nested transaction
*
* @return boolean
*/
protected function _rollbackNested() {
$query = 'ROLLBACK TO SAVEPOINT LEVEL' . $this->_transactionNesting--;
if ($this->fullDebug) {
$this->logQuery($query);
}
$this->_connection->exec($query);
return true;
}

/**
Expand Down

0 comments on commit 2c1cf29

Please sign in to comment.