Quoting Chris Darroch <[EMAIL PROTECTED]>:

So, like this:

    switch (trans->mode) {
        case APR_DBD_TRANSACTION_COMMIT:
            res = PQexec(trans->handle->conn, "COMMIT");
            break;
        case APR_DBD_TRANSACTION_COMMIT_ON_SUCCESS:
            if (trans->errnum) {
                trans->errnum = 0;
                res = PQexec(trans->handle->conn, "ROLLBACK");
            } else
                res = PQexec(trans->handle->conn, "COMMIT");
            break;
        case APR_DBD_TRANSACTION_ROLLBACK:
            res = PQexec(trans->handle->conn, "ROLLBACK");
            break;
    }

Right. That was my understanding of it as well.

Currently the API relies on all query/select call status codes to determine if the transaction as a whole is going to be success or failure - it doesn't determine that from the status code of apr_dbd_transaction_end (its status code is relevant to that function call only). In fact, once the transaction goes bad, subsequent calls to query/select don't actually execute anything within the database - they just return bad status code. In other words, by the time we reached transaction end, we must have been checking the error codes, otherwise we're screwed for sure and things will rollback anyway.

So, I would be in favour of keeping that logic - the caller needs to know *before* calling transaction end if there is a chance of the whole transaction succeeding or not. And mode can also be chosen explicitly if everything is OK. Something like:

- begin transaction
- all OK?
- if yes, start loop
- begin loop
- query/select
- all OK?
- if not, exit loop (no need to change mode here!)
- if yes, do nothing
- results as expected?
- if not, set mode rollback, exit loop (explicit rollback!)
- end loop
- end transaction
- all OK?
- if not, notify upstream or maybe retry

Put differently, the need for explicit rollback is really based on some unexpected result from query/select - not a bad status code. On bad status code there is nothing that can be done to save the transaction (bar savepoints, which the current logic probably won't even withstand, because we can't force transaction status code change using the API) - rollback is the only option.

That's why I was thinking that we only need two modes: COMMIT and ROLLBACK. SQL experts, please feel free to tear my argument to shreds :-)

--
Bojan

Reply via email to