Quoting Nick Kew <[EMAIL PROTECTED]>:

Erm, no.  It it doesn't exist, that reduces to resetting trans->errnum.

Ah, yes. Sorry. I meant we return APR_ENOTIMPL if the database cannot possibly support resetting of trans->errnum correctly (such as PGSQL). Otherwise, we just reset (i.e. SQLite, Oracle, MySQL).

This would obviously need to be called every time an error code is
returned by query/select, right?

If the application wants to handle the error (other than in the default
manner) then yes.

Right.

Well, it's something we can initialise and reset to.  It'll just give current
behaviour.  Could be relevant in cases like oracle, where (according to
your earlier post) it will commit even when there's an error, so that
gives us three behaviours that are clearly distinct.

Hmm, let's assume that apr_dbd_transaction_end in the underlying driver takes into account all three modes - it would still work only for the last query/select before the call to transaction end. All queries before that, for which reset was not executed, would not even touch the database (due to the trans->errnum check at the beginning of each function). So, reset needs to be called explicitly if something is to happen in query/select after a bad status code.

Given that, it would be more uniform to ask callers to reset the error code explicitly, even for the last query/select before end, if they are convinced that this transaction should in fact be committed. And once they do that, one commit mode is quite sufficient. Something like this:

Two explicit modes:

#define APR_DBD_TRANSACTION_COMMIT   0
#define APR_DBD_TRANSACTION_ROLLBACK 1

For:

apr_dbd_transaction_mode_get()
apr_dbd_transaction_mode_set()

And another functions call:

apr_dbd_transaction_recover()

The latter would attempt to recover the transaction from the error (if underlying database permits and it all works out). It would be used by caller if any of the query/select functions return bad status code and the caller is confident the transaction should proceed as normal.

This function would look something like this in the driver:

static int dbd_foo_transaction_recover(apr_dbd_transaction_t *trans) {
    int ret = -1;

    if (trans) {
      ret = foo_recover(...);
      if (ret == foo_success ) {
          trans->errnum = 0;
      }
    }

    return ret;
}

Databases that don't support such functionality (e.g. PostgreSQL) would simply return APR_ENOTIMPL.

--
Bojan

Reply via email to