At 11:46 AM -0600 4/10/07, Dennis Cote wrote:
Samuel R. Neff wrote:
I personally would see value in supporting quasi-nested transactions where
they are nested in name only--increment decrement a counter and commit on
last commit, rollback entire transaction on first rollback.  This would have
the advantage that the library would support issuing multiple BEGIN
TRANSACTION statements without error. I often find in my code that I have library routines that want to run in a
transaction and can run in their own transaction or join an existing
transaction.  In SQLite I would need to have extra logic in place to detect
the transaction state and only run in a transaction if one is not already in
place.
I say "would" because the SQLite.NET [1] wrapper provides nested
transactions as a counter already, on top of the SQLite library (as long as
I use the connection.BeginTransaction() method and don't issue an explicit
BEGIN TRANSACTION call myself).

I do the same thing in my wrapper for the same reason. I think this is by far the most common case where users see a need for nested transactions. It decouples subroutines from their calling context. This form of nested transactions is exactly what several other database engines provide. It is simple to implement and does what the vast majority of users need.

I'm sure there are circumstances that can tolerate only some of the statements in a transaction being executed, but for most applications a transaction is *all or nothing*. They don't want to execute the first and last statement but skip the middle two. It seems to me any application that can tolerate some statements in a transaction not executing could factor those statements out into a separate transaction.

I think that the question of what would be a reasonable minimum to do now depends on what SQLite's current behaviour is when an individual SQL statement fails that is part of a larger transaction.

Remember that each SQL statement is conceptually an implicit child transaction of its own.

If a failing SQL statement causes the entire transaction to implicitly rollback, then what you describe about any rollback causing the whole thing to rollback would be consistent.

If a failing SQL statement just results in only that statement not leaving a trace and other uncommitted statements in a transaction are still applied subject to be committed, then an explicit rollback must not affect anything but the immediate child-most transaction, to be consistent.

Regardless, I like to think of SQL statement failures like exceptions, and each transaction level can optionally act like a try-catch-block; a failed statement throws an exception, and each transaction in turn is rolled back up to said try-catch block, and anything done prior to the block being entered is not rolled back automatically.

Now of course, users would then have to explicitly mark places, perhaps best as an extension to the "begin transaction" statement that indicates whether a failure within that transaction will auto-effect any of its parents; its like the "begin" doubles as a try-block. Or that may not be the best syntax, so alternatives could be tried.

I will also say for the record that partial rollbacks are useful. Having all layers rolling back unconditionally is like having a web browser program that exits if it has trouble loading a web page, rather than just saying sorry and moving on. Sometimes it is reasonable to only rollback the "load this page" transaction rather than the "main()" transaction. Users may want to try again, or try going to a different page.

-- Darren Duncan

-----------------------------------------------------------------------------
To unsubscribe, send email to [EMAIL PROTECTED]
-----------------------------------------------------------------------------

Reply via email to