From 6872f646d735fd6aa1c87317ebeffbe3274c1e08 Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Tue, 3 Jul 2012 23:03:13 -0430 Subject: [PATCH] Initial imlpementation for transactions and nested transactions --- .../Model/Datasource/Database/Connection.php | 63 ++++++++++++++++++- lib/Cake/Model/Datasource/Database/Driver.php | 25 ++++++++ .../Datasource/Database/Driver/Mysql.php | 18 +++--- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Connection.php b/lib/Cake/Model/Datasource/Database/Connection.php index 80134b1c4c3..f82efab4546 100644 --- a/lib/Cake/Model/Datasource/Database/Connection.php +++ b/lib/Cake/Model/Datasource/Database/Connection.php @@ -35,6 +35,21 @@ class Connection { **/ protected $_connected = false; +/** + * Contains how many nested transactions have been started + * + * @var int + **/ + protected $_transactionLevel = 0; + +/** + * Whether this connection can and should use savepoints for nested + * transactions + * + * @var boolean + **/ + protected $_useSavePoints = false; + /** * Constructor * @@ -215,7 +230,14 @@ public function delete($table, $conditions = array(), $types = array()) { * @return void **/ public function begin() { - + $this->connect(); + if (!$this->_transactionLevel) { + $this->_driver->beginTransaction(); + } + $this->_transactionLevel++; + if ($this->_transactionLevel > 1 && $this->useSavePoints()) { + $this->createSavePoint($this->_transactionLevel); + } } /** @@ -225,7 +247,7 @@ public function begin() { **/ public function commit() { - + } /** @@ -237,6 +259,43 @@ public function rollback() { } +/** + * Returns whether this connection is using savepoints for nested transactions + * If a boolean is passed as argument it will enable/disable the usage of savepoints + * only if driver the allows it. + * + * If you are trying to enable this feature, make sure you check the return value of this + * function to verify it was enabled successfuly + * + * ## Example: + * + * `$connection->useSavePoints(true)` Returns true if drivers supports save points, false otherwise + * `$connection->useSavePoints(false)` Disables usage of savepoints and returns false + * `$connection->useSavePoints()` Returns current status + * + * @return boolean true if enabled, false otherwise + **/ + public function useSavePoints($enable = null) { + if ($enable === null) { + return $this->_useSavePoints; + } + if ($enable === false) { + return $this->_useSavePoints = false; + } + + return $this->_useSavePoints = $this->_driver->supportsSavePoints(); + } + +/** + * Creates a new save point for nested transactions + * + * @return void + **/ + public function createSavePoint($name) { + $this->connect(); + $this->execute($this->_driver->savePointSQL($name)); + } + /** * Quotes value to be used safely in database query * diff --git a/lib/Cake/Model/Datasource/Database/Driver.php b/lib/Cake/Model/Datasource/Database/Driver.php index 6bd3fc66a7d..420fb5015e9 100644 --- a/lib/Cake/Model/Datasource/Database/Driver.php +++ b/lib/Cake/Model/Datasource/Database/Driver.php @@ -39,4 +39,29 @@ public abstract function enabled(); **/ public abstract function prepare($sql); +/** + * Starts a transaction + * + * @return boolean true on success, false otherwise + **/ + public abstract function beginTransaction(); + +/** + * Returns whether this driver supports save points for nested transactions + * + * @return boolean true if save points are supported, false otherwise + **/ + public function supportsSavePoints() { + true; + } + +/** + * Returns whether this driver supports save points for nested transactions + * + * @return boolean true if save points are supported, false otherwise + **/ + public function savePointSQL($name) { + return 'SAVEPOINT LEVEL ' . $name; + } + } diff --git a/lib/Cake/Model/Datasource/Database/Driver/Mysql.php b/lib/Cake/Model/Datasource/Database/Driver/Mysql.php index 1bfd6c0a29a..baaae8c250c 100644 --- a/lib/Cake/Model/Datasource/Database/Driver/Mysql.php +++ b/lib/Cake/Model/Datasource/Database/Driver/Mysql.php @@ -24,14 +24,7 @@ class Mysql extends \Cake\Model\Datasource\Database\Driver { ); /** - * PDO instance associated to this connection - * - * @var PDO - **/ - protected $_conenction; - -/** - * Establishes a conenction to the databse server + * Establishes a connection to the databse server * * @param array $config configuretion to be used for creating connection * @return boolean true on success @@ -91,4 +84,13 @@ public function prepare($sql) { return new Statement($statement, $this); } +/** + * Starts a transaction + * + * @return boolean true on success, false otherwise + **/ + public function beginTransaction() { + return $this->_connection->beginTransaction(); + } + }