Re: How to do transactions, especially nested Lassi Kortela 18 Sep 2019 08:26 UTC
> I just didn't want to require the user throwing and catching an exception > just to abort the transaction. This possibility didn't occur to me. I understand your aversion to it :) > Perhaps we can specify a specific exception type to throw which will just > return from the with-transaction but not propagate the exception to user > code? That would probably be the better API, in hindsight. Any other type > of exception will be re-raised, just not this one. This is the approach I meant. IIRC many DB APIs in other languages do this. > Alternatively, we could have a specific procedure that aborts the current > transaction and calls the continuation of the with-transaction call. > This could be implemented using the mechanism I just described without > exposing that it's actually an exception. That would be even less ugly > at the cost of adding another procedure to the API. This is probably a good idea as well. IIRC many DB APIs have a "rollback" procedure that probably just raises a magic exception. >> There are probably some exotic situations where you'd want to use those >> Postgres savepoints at the DB engine side to rollback only part of a >> transaction. I don't know anything about that; I'll let you decide. > > Well, I think you just described that yourself: if a library wants to > abort its own transaction, it should not roll back the entire user > transaction. That's the idea behind nested transactions: it's an > abstraction. It's somewhat leaky due to the isolation levels not being > changeable, but other than that I think it's best to make use of > savepoints when available. You're right. This didn't occur to me. > The real question is: what should we do with nested with-transaction > calls for engines that don't support them? We could raise an exception, > but that would make such library code unusable. Alternatively, we could > just ignore the nesting but that would change the semantics when the > library tries to do a rollback; it would either do nothing (which is > undesirable) or it would abort the user transaction completely (which is > probably not what was intended either). As with the URL stuff in Schemeweb, I'm glad we have your experience on board. This is much harder than it seemed at first :) No good ideas from me at this time... > Note that this is not a specific Postgres feature. MySQL has savepoints > as well: https://dev.mysql.com/doc/refman/5.7/en/savepoint.html > And so does SQLite: https://sqlite.org/lang_savepoint.html It's nice to know that they're widely supported. > Perhaps we should treat databases that don't support this as second-class > and raise an exception when you try to roll back a nested transaction? > That way, the "happy path" will always work. Not sure this is great > design, though. Raising an exception when trying to make a nested > transaction could also work, but that means some library code is > completely unusable in certain databases (how many databases don't have > these, anyway?). Hard to say. I agree with your assessment that this is likely to effectively throw other databases into the bin for Schemers :) Eventually it'd be nice to download SQL-wielding Scheme libraries from a package repository, and most of those could be expected to fail on exotic DBs because of the nested transaction thing.