From 84515776597960a8f33172ae2a38b418c944fdbb Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Wed, 17 Sep 2014 14:39:16 -0400
Subject: [PATCH] Added transactions support

---
 program/lib/Roundcube/rcube_db.php      |   67 +++++++++++++++++++++-
 program/lib/Roundcube/rcube_db_oci8.php |   74 ++++++++++++++++++++++++
 2 files changed, 137 insertions(+), 4 deletions(-)

diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php
index 72cad01..5a2ad03 100644
--- a/program/lib/Roundcube/rcube_db.php
+++ b/program/lib/Roundcube/rcube_db.php
@@ -555,7 +555,9 @@
     public function affected_rows($result = null)
     {
         if ($result || ($result === null && ($result = $this->last_result))) {
-            return $result->rowCount();
+            if ($result !== true) {
+                return $result->rowCount();
+            }
         }
 
         return 0;
@@ -571,7 +573,7 @@
      */
     public function num_rows($result = null)
     {
-        if ($result || ($result === null && ($result = $this->last_result))) {
+        if (($result || ($result === null && ($result = $this->last_result))) && $result !== true) {
             // repeat query with SELECT COUNT(*) ...
             if (preg_match('/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/ims', $result->queryString, $m)) {
                 $query = $this->dbh->query('SELECT COUNT(*) FROM ' . $m[1], PDO::FETCH_NUM);
@@ -647,7 +649,9 @@
     protected function _fetch_row($result, $mode)
     {
         if ($result || ($result === null && ($result = $this->last_result))) {
-            return $result->fetch($mode);
+            if ($result !== true) {
+                return $result->fetch($mode);
+            }
         }
 
         return false;
@@ -717,6 +721,63 @@
     }
 
     /**
+     * Start transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function startTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('BEGIN TRANSACTION');
+
+        return $this->last_result = $this->dbh->beginTransaction();
+    }
+
+    /**
+     * Commit transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function endTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('COMMIT TRANSACTION');
+
+        return $this->last_result = $this->dbh->commit();
+    }
+
+    /**
+     * Rollback transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function rollbackTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('ROLLBACK TRANSACTION');
+
+        return $this->last_result = $this->dbh->rollBack();
+    }
+
+    /**
      * Formats input so it can be safely used in a query
      *
      * @param mixed  $input Value to quote
diff --git a/program/lib/Roundcube/rcube_db_oci8.php b/program/lib/Roundcube/rcube_db_oci8.php
index b9f63f3..a55ba04 100644
--- a/program/lib/Roundcube/rcube_db_oci8.php
+++ b/program/lib/Roundcube/rcube_db_oci8.php
@@ -110,8 +110,9 @@
 
         // prepare query
         $result = oci_parse($this->dbh, $query);
+        $mode   = $this->in_transaction ? OCI_NO_AUTO_COMMIT : OCI_COMMIT_ON_SUCCESS;
 
-        if (!@oci_execute($result, OCI_COMMIT_ON_SUCCESS)) { // OCI_NO_AUTO_COMMIT
+        if (!@oci_execute($result, $mode)) {
             $result = $this->handle_error($query, $result);
         }
 
@@ -459,4 +460,75 @@
 
         return !$this->db_error;
     }
+
+    /**
+     * Start transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function startTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('BEGIN TRANSACTION');
+
+        return $this->last_result = $this->in_transaction = true;
+    }
+
+    /**
+     * Commit transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function endTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('COMMIT TRANSACTION');
+
+        if ($result = @oci_commit($this->dbh)) {
+            $this->in_transaction = true;
+        }
+        else {
+            $this->handle_error('COMMIT');
+        }
+
+        return $this->last_result = $result;
+    }
+
+    /**
+     * Rollback transaction
+     *
+     * @return bool True on success, False on failure
+     */
+    public function rollbackTransaction()
+    {
+        $this->db_connect('w', true);
+
+        // check connection before proceeding
+        if (!$this->is_connected()) {
+            return $this->last_result = false;
+        }
+
+        $this->debug('ROLLBACK TRANSACTION');
+
+        if ($result = @oci_rollback($this->dbh)) {
+            $this->in_transaction = false;
+        }
+        else {
+            $this->handle_error('ROLLBACK');
+        }
+
+        return $this->last_result = $this->dbh->rollBack();
+    }
 }

--
Gitblit v1.9.1