apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Bojan Smojver <bo...@rexursive.com>
Subject Transaction modes, explicit rollbacks etc.
Date Tue, 02 May 2006 04:45:38 GMT
So, we know by now that some databases will fail the whole transaction  
if any kind of error occurs, while some others won't. We also know  
that sometimes one option is the desired behaviour, while at other  
times the other option is what the caller wants - regardless of the  
underlying database. So, given that APR DBD is supposed to be database  
neutral, here is another solution for the same problem.

#define APR_DBD_TRANSACTION_COMMIT        0x00 /**< commit the transaction */
#define APR_DBD_TRANSACTION_ROLLBACK      0x01 /**< rollback the  
transaction */
#define APR_DBD_TRANSACTION_IGNORE_ERRORS 0x02 /**< ignore error conditions */

We then have our already known functions:

apr_dbd_transaction_mode_get()
apr_dbd_transaction_mode_set()

So, we can call (once only!):

apr_dbd_transaction_mode_set(driver, trans,
                              APR_DBD_TRANSACTION_COMMIT|
                              APR_DBD_TRANSACTION_IGNORE_ERRORS);

Then, inside the query/select functions we leave trans->errnum at zero  
in case any error occurs, but return the status to the caller. If the  
caller is intersted in the status, he/she can do something about it  
(such as call mode set with ROLLBACK and then call end, to rollback).  
Or, the caller can just continue with the next query/select. With  
IGNORE_ERRORS set, at no point will the transaction be in a bad state  
(i.e. this is how SQLite/Oracle/MySQL work). After all that, COMMIT is  
executed and whatever is good gets committed (so this is effectively  
COMMIT_ON_SUCCESS, but without the need to keep "recovering" the error  
status).

In case the IGNORE_ERRORS flag isn't set, the logic reverts to the  
current behaviour (i.e. the way PGSQL does things). Any error triggers  
a transaction error and the whole transaction will be rolled back for  
sure.

Here is the part we can now do with IGNORE_ERRORS that we could not do  
before - we can make PGSQL behave like other databases if we so wish.  
By setting IGNORE_ERRORS, we can insert SAVEPOINTS before every  
query/select inside PGSQL driver automatically (i.e. the caller  
doesn't have to do it). If an error occurs withing query/select, we  
simply roll back to the previous savepoint, keep trans->errnum always  
at zero and return the error code of the actual query. The caller can  
then decide what should be done with the whole thing. This brings us  
in line with transactional behaviour other databases.

In summary, we can pick the behaviour we want and users get  
savepoints/error recovery for free with PGSQL if they so wish.

Let me know what you think...

-- 
Bojan

Mime
View raw message