This was never compiled, let alone tested. It is here as a prototype for Ronen's suggestion.

--
Bojan
Index: include/apr_dbd.h
===================================================================
--- include/apr_dbd.h	(revision 397754)
+++ include/apr_dbd.h	(working copy)
@@ -153,6 +153,18 @@
                                          apr_pool_t *pool,
                                          apr_dbd_transaction_t *trans);
 
+/** apr_dbd_transaction_rollback: rollback a transaction
+ *  May be a no-op.
+ *
+ *  @param driver - the driver
+ *  @param handle - the db connection
+ *  @param transaction - the transaction.
+ *  @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_transaction_rollback(const apr_dbd_driver_t *driver,
+                                              apr_pool_t *pool,
+                                              apr_dbd_transaction_t *trans);
+
 /** apr_dbd_query: execute an SQL query that doesn't return a result set
  *
  *  @param driver - the driver
Index: include/private/apr_dbd_internal.h
===================================================================
--- include/private/apr_dbd_internal.h	(revision 397754)
+++ include/private/apr_dbd_internal.h	(working copy)
@@ -254,6 +254,14 @@
      *  @return param name, or NULL if col is out of bounds.
      */
     const char* (*get_name)(const apr_dbd_results_t *res, int col);
+
+    /** rollback_transaction: rollback a transaction
+     *  May be a no-op.
+     *
+     *  @param transaction - the transaction.
+     *  @return 0 for success or error code
+     */
+    int (*rollback_transaction)(apr_dbd_transaction_t *trans);
 };
 
 /* Export mutex lock/unlock for drivers that need it */
Index: dbd/apr_dbd_sqlite2.c
===================================================================
--- dbd/apr_dbd_sqlite2.c	(revision 397754)
+++ dbd/apr_dbd_sqlite2.c	(working copy)
@@ -308,6 +308,19 @@
     return ret;
 }
 
+static int dbd_sqlite_rollback_transaction(apr_dbd_transaction_t * trans)
+{
+    int rows;
+    int ret = -1;               /* no transaction is an error cond */
+
+    if (trans) {
+        ret = dbd_sqlite_query(trans->handle, &rows, "ROLLBACK TRANSACTION");
+        trans->handle->trans = NULL;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
 {
     apr_dbd_t *sql;
@@ -396,6 +409,7 @@
     dbd_sqlite_pvselect,
     dbd_sqlite_pquery,
     dbd_sqlite_pselect,
-    dbd_sqlite_get_name
+    dbd_sqlite_get_name,
+    dbd_sqlite_rollback_transaction
 };
 #endif
Index: dbd/apr_dbd_sqlite3.c
===================================================================
--- dbd/apr_dbd_sqlite3.c	(revision 397754)
+++ dbd/apr_dbd_sqlite3.c	(working copy)
@@ -368,6 +368,19 @@
     return ret;
 }
 
+static int dbd_sqlite3_rollback_transaction(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+    int nrows = 0;
+
+    if (trans) {
+        ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK;");
+        trans->handle->trans = NULL;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql = NULL;
@@ -445,6 +458,7 @@
     dbd_sqlite3_pvselect,
     dbd_sqlite3_pquery,
     dbd_sqlite3_pselect,
-    dbd_sqlite3_get_name
+    dbd_sqlite3_get_name,
+    dbd_sqlite3_rollback_transaction
 };
 #endif
Index: dbd/apr_dbd_oracle.c
===================================================================
--- dbd/apr_dbd_oracle.c	(revision 397754)
+++ dbd/apr_dbd_oracle.c	(working copy)
@@ -1682,6 +1682,28 @@
     return ret;
 }
 
+static int dbd_oracle_rollback_transaction(apr_dbd_transaction_t *trans)
+{
+    int ret = 1;             /* no transaction is an error cond */
+    sword status;
+    apr_dbd_t *handle = trans->handle;
+    if (trans) {
+        status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT);
+
+        handle->trans = NULL;
+
+        switch (status) {
+        case OCI_SUCCESS:
+            ret = 0;
+            break;
+        default:
+            ret = 3;
+            break;
+        }
+    }
+    return ret;
+}
+
 /* This doesn't work for BLOB because of NULLs, but it can fake it
  * if the BLOB is really a string
  */
@@ -1910,6 +1932,7 @@
     dbd_oracle_pvselect,
     dbd_oracle_pquery,
     dbd_oracle_pselect,
-    dbd_oracle_get_name
+    dbd_oracle_get_name,
+    dbd_oracle_end_transaction
 };
 #endif
Index: dbd/apr_dbd_pgsql.c
===================================================================
--- dbd/apr_dbd_pgsql.c	(revision 397754)
+++ dbd/apr_dbd_pgsql.c	(working copy)
@@ -567,6 +567,27 @@
     return ret;
 }
 
+static int dbd_pgsql_rollback_transaction(apr_dbd_transaction_t *trans)
+{
+    PGresult *res;
+    int ret = -1;                /* no transaction is an error cond */
+    if (trans) {
+        res = PQexec(trans->handle->conn, "ROLLBACK");
+        if (res) {
+            ret = PQresultStatus(res);
+            if (dbd_pgsql_is_success(ret)) {
+                ret = 0;
+            }
+            PQclear(res);
+        }
+        else {
+            ret = PGRES_FATAL_ERROR;
+        }
+        trans->handle->trans = NULL;
+    }
+    return ret;
+}
+
 static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql;
@@ -656,6 +677,7 @@
     dbd_pgsql_pvselect,
     dbd_pgsql_pquery,
     dbd_pgsql_pselect,
-    dbd_pgsql_get_name
+    dbd_pgsql_get_name,
+    dbd_pgsql_rollback_transaction
 };
 #endif
Index: dbd/apr_dbd.c
===================================================================
--- dbd/apr_dbd.c	(revision 397754)
+++ dbd/apr_dbd.c	(working copy)
@@ -200,6 +200,7 @@
     }
     return ret;
 }
+
 APU_DECLARE(int) apr_dbd_transaction_end(const apr_dbd_driver_t *driver,
                                          apr_pool_t *pool,
                                          apr_dbd_transaction_t *trans)
@@ -208,6 +209,14 @@
     return driver->end_transaction(trans);
 }
 
+APU_DECLARE(int) apr_dbd_transaction_rollback(const apr_dbd_driver_t *driver,
+                                              apr_pool_t *pool,
+                                              apr_dbd_transaction_t *trans)
+{
+    apr_pool_cleanup_kill(pool, trans, CLEANUP_CAST driver->end_transaction);
+    return driver->rollback_transaction(trans);
+}
+
 APU_DECLARE(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
                                         apr_dbd_t *handle)
 {

Reply via email to