Here is the patch along the lines of setting the modes of the transaction. It doesn't have "force commit", but if the list decides that it's the right thing to do, I'll rework. I didn't test this - it's just a prototype. A patch for folks using MySQL is included as well.

--
Bojan
Index: include/apr_dbd.h
===================================================================
--- include/apr_dbd.h	(revision 398484)
+++ include/apr_dbd.h	(working copy)
@@ -153,6 +153,29 @@
                                          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_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 398484)
+++ 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,21 @@
      *  @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);
 };
 
 /* Export mutex lock/unlock for drivers that need it */
Index: dbd/apr_dbd_sqlite2.c
===================================================================
--- dbd/apr_dbd_sqlite2.c	(revision 398484)
+++ 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,18 @@
     return ret;
 }
 
+static int dbd_sqlite_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans->mode;
+}
+
+static int dbd_sqlite_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
 static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
 {
     apr_dbd_t *sql;
@@ -396,6 +410,8 @@
     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
 };
 #endif
Index: dbd/apr_dbd_sqlite3.c
===================================================================
--- dbd/apr_dbd_sqlite3.c	(revision 398484)
+++ 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,18 @@
     return ret;
 }
 
+static int dbd_sqlite3_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans->mode;
+}
+
+static int dbd_sqlite3_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                            int mode)
+{
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
 static apr_dbd_t *dbd_sqlite3_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql = NULL;
@@ -444,6 +458,8 @@
     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
 };
 #endif
Index: dbd/apr_dbd_oracle.c
===================================================================
--- dbd/apr_dbd_oracle.c	(revision 398484)
+++ 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,18 @@
     return ret;
 }
 
+static int dbd_oracle_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans->mode;
+}
+
+static int dbd_oracle_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                           int mode)
+{
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
 /* This doesn't work for BLOB because of NULLs, but it can fake it
  * if the BLOB is really a string
  */
@@ -1910,6 +1928,8 @@
     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
 };
 #endif
Index: dbd/apr_dbd_pgsql.c
===================================================================
--- dbd/apr_dbd_pgsql.c	(revision 398484)
+++ 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,18 @@
     return ret;
 }
 
+static int dbd_pgsql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans->mode;
+}
+
+static int dbd_pgsql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
 static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params)
 {
     apr_dbd_t *sql;
@@ -656,6 +670,8 @@
     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
 };
 #endif
Index: dbd/apr_dbd.c
===================================================================
--- dbd/apr_dbd.c	(revision 398484)
+++ dbd/apr_dbd.c	(working copy)
@@ -208,6 +208,19 @@
     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(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
                                         apr_dbd_t *handle)
 {
--- apr_dbd_mysql.c.orig	2006-05-01 11:11:06.000000000 +1000
+++ apr_dbd_mysql.c	2006-05-01 11:15:54.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,19 @@
     handle->trans = *trans;
     return (*trans)->errnum;
 }
+
+static int dbd_pgsql_transaction_mode_get(apr_dbd_transaction_t *trans)
+{
+    return trans->mode;
+}
+
+static int dbd_pgsql_transaction_mode_set(apr_dbd_transaction_t *trans,
+                                          int mode)
+{
+    return trans->mode = (mode ? APR_DBD_TRANSACTION_ROLLBACK
+                               : APR_DBD_TRANSACTION_COMMIT);
+}
+
 static apr_dbd_t *dbd_mysql_open(apr_pool_t *pool, const char *params)
 {
     static const char *const delims = " \r\n\t;|,";
@@ -674,7 +689,9 @@
     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,
 };
 
 #endif

Reply via email to