Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
daattali opened this issue Jun 13, 2020 · 6 comments
Open

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

daattali opened this issue Jun 13, 2020 · 6 comments

Comments

@daattali
Copy link

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
Copy link
Author

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
Copy link

r2evans commented Jul 2, 2020

(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.

  • SQL Server, if select @@TRANCOUNT is greater than 0 then you are in a transaction;
  • Postgres, if select txid_current() is the same when repeated, then you are in a transaction;
  • SQLite: I think RSQLite would need to add sqlite3_get_autocommit to the C functions it uses, since that's the (a?) canary for autocommit/in-transaction.

not sure about others ...

@daattali
Copy link
Author

daattali commented Jul 2, 2020

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

@krlmlr
Copy link
Member

krlmlr commented Sep 28, 2020

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
Copy link

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
Copy link
Member

krlmlr commented Dec 27, 2020

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.

@krlmlr krlmlr closed this as completed Dec 27, 2020
@krlmlr krlmlr transferred this issue from r-dbi/DBI Nov 1, 2021
@krlmlr krlmlr reopened this Nov 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants