On 24.08.2012 18:55, Tyler Romeo wrote:
So, how would you solve the use case I described? What I need to do is to perform some checks before calling WikiPage::doEdit, and make sure the
result of
the check is still valid when the actual save occurs.
SAVEPOINTs are basically nested transactions.
Yes. I'd like to use them.
MediaWiki's current behaviour is calling begin() when a transaction is open silently commits the old transaction and starts a new one.
This SUCKS.
Can you describe the use case in more detail?
So, in wikidata, we have global constraints, e.g. the requirement that only one data item can have a sitelink to a given wikipedage (there's a 1:1 relationship between wikipedia pages and data items). Before saving the item page, this constraint needs to be checked, just before calling WikiPage::doEdit(). And we also want to check for edit conflicts (comparing the base revision - note that we are not using EditPage).
Anyway, wee need to do some checks before we call WikiPage::doEdit. And make sure the database doesn't change before the actual save is done. So our checks should be in the same transaction as the actual save.
But WikiPage::doEdit already opens a transaction. So we can no open a surrounding transactiopn bracket - because nested transactions are not supported.
This could be solved be the "counting" or the "safepoint" solution, the latter being somewhat nicer. But we need to st least *one* of them, as far as I can tell.
The current situation is that code always has to know whether it is safe to call some function X from inside a transaction, and conversely, any function needs to decide on whether it expects to be called from within an existing transaction, or if it should open its own.
These things can often not really be known in advance. This has caused trouble in the past (caused by transactions being committed prematurely, because another transaction started). I'm sure it will cause more pain in the future.
So I'm proposing to implement support for nested transactions, either by just counting (and, on rollback, roll back all open transactions). Or by using savepoints.
-- daniel