[subxacts] Aborting a function - Mailing list pgsql-hackers
From | Alvaro Herrera |
---|---|
Subject | [subxacts] Aborting a function |
Date | |
Msg-id | 20040708194226.GA10855@dcc.uchile.cl Whole thread Raw |
Responses |
Re: [subxacts] Aborting a function
Re: [subxacts] Aborting a function |
List | pgsql-hackers |
[Note: my ISP is having problems with email, so probably a duplicate of this will be published as soon as their SMTP starts working again] There's a point that hasn't been raised in discussion of subtransactions here and it's what to do when a function aborts. If I have a plpgsql function that goes like subbegin; ... do work ...; subcommit; and then the "work" causes a subtransaction abort, what should happen? Currently the system remains inside the subtransaction that the function created --- the "subcommit" is never executed and thus the subtransaction is never closed. This is wrong. (We could talk about exception support in plpgsql or other language handlers but I don't think this is going to happen for 7.5.) I think the right thing to do is close all subtransactions that the function may have created, abort the (sub)transaction that created the function itself, and return control to the application in an aborted state. Furthermore, suppose a function is called which creates subtransactions, and inside that function there's another function which creates more subtransactions, and inside one of those inner subtransactions there is an error. In this case, the right thing to do is abort all subtransactions created in the second function, and all subtransactions created in the first function, and then return control to the application, in an aborted state. As a simple example, consider this: create function crashme2() returns int strict language plpgsql as ' begin subbegin; select foo; -- aborts the transaction -- did not close the subxact end;'; create function crashme5() returns int strict language plpgsql as 'begin subbegin; perform crashme2(); subabort; end; '; begin; subbegin; select crashme5(); subabort; subcommit; -- WARNING: there is no subxact in progress commit; The point here is to observe that the transaction is taken back to the correct nesting level after the function aborts. The server reacts with the following error report: alvherre=# select crashme5(); ERROR: no existe la columna "foo" CONTEXT: SQL query "SELECT foo" PL/pgSQL function "crashme2" line 1 at SQL statement SQL query "SELECT crashme2()" PL/pgSQL function "crashme5" line 1 at perform This is working with a patch I'm testing now, modelled after an idea of Bruce. It works by setting an "abort level" when the function is going to be called, and unsetting it when the function is done executing. If there is a transaction abort, the unset won't happen, and the aborting code will see the marker defined, close all the levels up to the marker, and then put that transaction in aborted state. I have tested it using functions in the targetlist (modifying ExecEvalFunc) and as rangevars (ExecInitFunctionScan and ExecEndFunctionScan). Maybe ExecEvalOper needs to do the same, if an operator can be defined as dependant on a function which uses subxacts. Comments, opinions please? -- Alvaro Herrera (<alvherre[a]dcc.uchile.cl>) "Use it up, wear it out, make it do, or do without"
pgsql-hackers by date: