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)
{