r-dbi / dbi3

DBI revisited
https://r-dbi.github.io/dbi3
37 stars 2 forks source link

Any way to know if a connection is already inside a transaction? #28

Open daattali opened 4 years ago

daattali commented 4 years ago

Ideally, every call to dbBegin() will be followed by exactly one call to either rollback or commit.

However, sometimes in complex situations where the transaction is happening throughout several functions, it might not be 100% certain that a rollback is called in case of an error. In that case, the next time I try to call dbBegin(), I'd like to clear any active transactions because if a previous transaction failed part-way through then I'm stuck and cannot start a new transaction.

To do this, it would be necessary to have a function such as DBI::isActiveTransaction() or similar

daattali commented 4 years ago

To show a concrete very simple example:

Suppose I have a global database connection con and two functions f1() and f2().

con <- DBI::dbConnect(...)

f1 <- function() {
  DBI::dbBegin(con)
  some_function_calls_that_result_an_in_error()
  DBI::dbCommit(con)
}

f2 <- function() {
  DBI::dbBegin(con)
  some_function_calls()
  DBI::dbCommit(con)
}

f1()
f2()

What would happen is that when I call f2(), it would fail because dbBegin() can't complete since a transaction is already in progress. The ideal solution here is to wrap the code in a try-catch and to roll back if an error occurs, I know that. But what if the transaction begins and ends in someone else's code where I have no control over it? It would be useful to have the ability to do

if (DBI::isTransactionActive(con)) DBI::dbRollback(con)
r2evans commented 4 years ago

(Up front, I'm guessing you already know this, and are asking for a stub for each driver to implement the actual method.)

It depends on the DBMS.

not sure about others ...

daattali commented 4 years ago

Thanks. Yeah, I was more wondering about a generic DBI function that works across the different implementations

krlmlr commented 3 years ago

I'd suggest to use dbWithTransaction() in your own code to ensure that transactions are finalized.

If you need to interact with code that you don't control, and this code behaves erratically regarding transactions, that's tough. Can you try(dbRollback()) unconditionally?

DBI knows if dbBegin() has been called or not, we could perhaps track and return this information even without changing all the drivers.

benscarlson commented 3 years ago

I just found this thread when I was also attempting to determine if there is an active transaction. I use RSQlite/DBI and would love to have isActiveTransaction() or something like that.

krlmlr commented 3 years ago

Thanks for the suggestions. I don't think this is a good fit for DBI at this time, please query the transaction status manually if you really need to.