Quoting Bojan Smojver <[EMAIL PROTECTED]>:

Something like this:

Attached example patches.

--
Bojan
Index: include/apr_dbd.h
===================================================================
--- include/apr_dbd.h	(revision 398759)
+++ include/apr_dbd.h	(working copy)
@@ -153,6 +153,38 @@
                                          apr_pool_t *pool,
                                          apr_dbd_transaction_t *trans);
 
+#define APR_DBD_TRANSACTION_COMMIT   0  /**< commit the transaction */
+#define APR_DBD_TRANSACTION_ROLLBACK 1  /**< rollback the transaction */
+
+/** apr_dbd_transaction_mode_get: get the mode of transaction
+ *
+ *  @param driver - the driver
+ *  @param trans  - the transaction
+ *  @return mode of transaction
+ */
+APU_DECLARE(int) apr_dbd_transaction_mode_get(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans);
+
+/** apr_dbd_transaction_mode_set: set the mode of transaction
+ *
+ *  @param driver - the driver
+ *  @param trans  - the transaction
+ *  @param mode   - new mode of the transaction
+ *  @return new mode of transaction
+ */
+APU_DECLARE(int) apr_dbd_transaction_mode_set(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans,
+                                              int mode);
+
+/** apr_dbd_transaction_recover: recover transaction from an error condition
+ *
+ *  @param driver - the driver
+ *  @param trans  - the transaction
+ *  @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_transaction_recover(const apr_dbd_driver_t *driver,
+                                             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 398759)
+++ include/private/apr_dbd_internal.h	(working copy)
@@ -82,9 +82,9 @@
 
     /** transaction: start a transaction.  May be a no-op.
      *
-     *  @param pool - a pool to use for error messages (if any).
+     *  @param pool   - a pool to use for error messages (if any).
      *  @param handle - the connection
-     *  @param transaction - ptr to a transaction.  May be null on entry
+     *  @param trans  - ptr to a transaction.  May be null on entry
      *  @return 0 for success or error code
      */
     int (*start_transaction)(apr_pool_t *pool, apr_dbd_t *handle,
@@ -94,7 +94,7 @@
      *  (commit on success, rollback on error).
      *  May be a no-op.
      *
-     *  @param transaction - the transaction.
+     *  @param trans - the transaction.
      *  @return 0 for success or error code
      */
     int (*end_transaction)(apr_dbd_transaction_t *trans);
@@ -254,6 +254,28 @@
      *  @return param name, or NULL if col is out of bounds.
      */
     const char* (*get_name)(const apr_dbd_results_t *res, int col);
+
+    /** transaction_mode_get: get the mode of transaction
+     *
+     *  @param trans - the transaction.
+     *  @return mode of transaction
+     */
+    int (*transaction_mode_get)(apr_dbd_transaction_t *trans);
+
+    /** transaction_mode_set: get the mode of transaction
+     *
+     *  @param trans - the transaction.
+     *  @param mode  - new mode of the transaction
+     *  @return new mode of transaction
+     */
+    int (*transaction_mode_set)(apr_dbd_transaction_t *trans, int mode);
+
+    /** transaction_recover: recover transaction from an error condition
+     *
+     *  @param trans - the transaction.
+     *  @return 0 for success or error code
+     */
+    int (*transaction_recover)(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 398759)
+++ dbd/apr_dbd_sqlite2.c	(working copy)
@@ -29,6 +29,7 @@
 #include "apr_dbd_internal.h"
 
 struct apr_dbd_transaction_t {
+    int mode;
     int errnum;
     apr_dbd_t *handle;
 };
@@ -292,7 +293,8 @@
     int ret = -1;               /* no transaction is an error cond */
 
     if (trans) {
-        if (trans->errnum) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || trans->mode) {
             trans->errnum = 0;
             ret =
                 dbd_sqlite_query(trans->handle, &rows,
@@ -308,6 +310,36 @@
     return ret;
 }
 
+static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
+static int dbd_sqlite_transaction_recover(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+
+    if (trans) {
+        trans->errnum = 0;
+        ret = 0;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
 {
     apr_dbd_t *sql;
@@ -396,6 +428,9 @@
     dbd_sqlite_pvselect,
     dbd_sqlite_pquery,
     dbd_sqlite_pselect,
-    dbd_sqlite_get_name
+    dbd_sqlite_get_name,
+    dbd_sqlite_transaction_mode_get,
+    dbd_sqlite_transaction_mode_set,
+    dbd_sqlite_transaction_recover
 };
 #endif
Index: dbd/apr_dbd_sqlite3.c
===================================================================
--- dbd/apr_dbd_sqlite3.c	(revision 398759)
+++ dbd/apr_dbd_sqlite3.c	(working copy)
@@ -32,6 +32,7 @@
 #define MAX_RETRY_SLEEP 100000
 
 struct apr_dbd_transaction_t {
+    int mode;
     int errnum;
     apr_dbd_t *handle;
 };
@@ -355,7 +356,8 @@
     int nrows = 0;
 
     if (trans) {
-        if (trans->errnum) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || trans->mode) {
             trans->errnum = 0;
             ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK");
         } else {
@@ -367,6 +369,36 @@
     return ret;
 }
 
+static int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                            int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
+static int dbd_sqlite3_transaction_recover(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+
+    if (trans) {
+        trans->errnum = 0;
+        ret = 0;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql = NULL;
@@ -444,6 +476,9 @@
     dbd_sqlite3_pvselect,
     dbd_sqlite3_pquery,
     dbd_sqlite3_pselect,
-    dbd_sqlite3_get_name
+    dbd_sqlite3_get_name,
+    dbd_sqlite3_transaction_mode_get,
+    dbd_sqlite3_transaction_mode_set,
+    dbd_sqlite3_transaction_recover
 };
 #endif
Index: dbd/apr_dbd_oracle.c
===================================================================
--- dbd/apr_dbd_oracle.c	(revision 398759)
+++ dbd/apr_dbd_oracle.c	(working copy)
@@ -123,6 +123,7 @@
 static int dbd_oracle_end_transaction(apr_dbd_transaction_t *trans);
 
 struct apr_dbd_transaction_t {
+    int mode;
     enum { TRANS_NONE, TRANS_ERROR, TRANS_1, TRANS_2 } status;
     apr_dbd_t *handle;
     OCITrans *trans;
@@ -1664,7 +1665,12 @@
             status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT);
             break;
         default:
-            status = OCITransCommit(handle->svc, handle->err, OCI_DEFAULT);
+            /* rollback on explicit rollback request */
+            if (trans->mode) {
+                status = OCITransRollback(handle->svc, handle->err, OCI_DEFAULT);
+            } else {
+                status = OCITransCommit(handle->svc, handle->err, OCI_DEFAULT);
+            }
             break;
         }
 
@@ -1682,6 +1688,36 @@
     return ret;
 }
 
+static int dbd_oracle_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_oracle_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
+static int dbd_oracle_transaction_recover(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+
+    if (trans) {
+        trans->errnum = 0;
+        ret = 0;
+    }
+
+    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 +1946,9 @@
     dbd_oracle_pvselect,
     dbd_oracle_pquery,
     dbd_oracle_pselect,
-    dbd_oracle_get_name
+    dbd_oracle_get_name,
+    dbd_oracle_transaction_mode_get,
+    dbd_oracle_transaction_mode_set,
+    dbd_oracle_transaction_recover
 };
 #endif
Index: dbd/apr_dbd_pgsql.c
===================================================================
--- dbd/apr_dbd_pgsql.c	(revision 398759)
+++ dbd/apr_dbd_pgsql.c	(working copy)
@@ -31,6 +31,7 @@
 #define QUERY_MAX_ARGS 40
 
 struct apr_dbd_transaction_t {
+    int mode;
     int errnum;
     apr_dbd_t *handle;
 };
@@ -545,7 +546,8 @@
     PGresult *res;
     int ret = -1;                /* no transaction is an error cond */
     if (trans) {
-        if (trans->errnum) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || trans->mode) {
             trans->errnum = 0;
             res = PQexec(trans->handle->conn, "ROLLBACK");
         }
@@ -567,6 +569,36 @@
     return ret;
 }
 
+static int dbd_pgsql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_pgsql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
+static int dbd_pgsql_transaction_recover(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+
+    if (trans) {
+        trans->errnum = 0;
+        ret = 0;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql;
@@ -656,6 +688,9 @@
     dbd_pgsql_pvselect,
     dbd_pgsql_pquery,
     dbd_pgsql_pselect,
-    dbd_pgsql_get_name
+    dbd_pgsql_get_name,
+    dbd_pgsql_transaction_mode_get,
+    dbd_pgsql_transaction_mode_set,
+    dbd_pgsql_transaction_recover
 };
 #endif
Index: dbd/apr_dbd.c
===================================================================
--- dbd/apr_dbd.c	(revision 398759)
+++ dbd/apr_dbd.c	(working copy)
@@ -208,6 +208,25 @@
     return driver->end_transaction(trans);
 }
 
+APU_DECLARE(int) apr_dbd_transaction_mode_get(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans)
+{
+    return driver->transaction_mode_get(trans);
+}
+
+APU_DECLARE(int) apr_dbd_transaction_mode_set(const apr_dbd_driver_t *driver,
+                                              apr_dbd_transaction_t *trans,
+                                              int mode)
+{
+    return driver->transaction_mode_set(trans, mode);
+}
+
+APU_DECLARE(int) apr_dbd_transaction_recover(const apr_dbd_driver_t *driver,
+                                             apr_dbd_transaction_t *trans)
+{
+    return driver->transaction_recover(trans);
+}
+
 APU_DECLARE(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
                                         apr_dbd_t *handle)
 {
--- apr_dbd_mysql.c.orig	2006-05-02 11:35:04.000000000 +1000
+++ apr_dbd_mysql.c	2006-05-02 11:37:09.000000000 +1000
@@ -62,6 +62,7 @@
 };
 
 struct apr_dbd_transaction_t {
+    int mode;
     int errnum;
     apr_dbd_t *handle;
 };
@@ -506,7 +507,8 @@
 {
     int ret = -1;
     if (trans) {
-        if (trans->errnum) {
+        /* rollback on error or explicit rollback request */
+        if (trans->errnum || trans->mode) {
             trans->errnum = 0;
             ret = mysql_rollback(trans->handle->conn);
         }
@@ -536,6 +538,37 @@
     handle->trans = *trans;
     return (*trans)->errnum;
 }
+
+static int dbd_pgsql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode;
+}
+
+static int dbd_pgsql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    if (!trans)
+        return APR_DBD_TRANSACTION_COMMIT;
+
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
+static int dbd_pgsql_transaction_recover(apr_dbd_transaction_t *trans)
+{
+    int ret = -1;
+
+    if (trans) {
+        trans->errnum = 0;
+        ret = 0;
+    }
+
+    return ret;
+}
+
 static apr_dbd_t *dbd_mysql_open(apr_pool_t *pool, const char *params)
 {
     static const char *const delims = " \r\n\t;|,";
@@ -674,7 +707,10 @@
     dbd_mysql_pvselect,
     dbd_mysql_pquery,
     dbd_mysql_pselect,
-    dbd_mysql_get_name
+    dbd_mysql_get_name,
+    dbd_mysql_transaction_mode_get,
+    dbd_mysql_transaction_mode_set,
+    dbd_mysql_transaction_recover
 };
 
 #endif

Reply via email to