Hackers,
Here is a patch covering the syntax change. This changes the current
subtransaction-initiating command to SUBBEGIN instead of BEGIN;
similarly SUBCOMMIT and SUBABORT.
I did not add a SUBROLLBACK command ... rather I want to use the
standard syntax "SAVEPOINT <foo>" and "ROLLBACK TO <foo>" and keep our
nonstandard syntax small.
Note that with this patch it is possible to start a subtransaction when
not in a transaction block. This makes the new commands to behave
almost exactly like toplevel BEGIN/COMMIT (the difference is not visible
to the user: the server is in nesting level 2 rather than 1, but the
outer level will automatically commit or roll back).
This also means that a single COMMIT will commit the whole transaction
tree:
BEGIN;
create table foo (a int);
SUBBEGIN;
insert into foo values (1);
SUBBEGIN;
insert into foo values (2);
COMMIT;
Also a single ABORT/ROLLBACK aborts the whole thing.
Included in this patch is the ability to "ignore errors" in a subcommit,
so this works:
begin;
subbegin;
drop table foo;
-- error: table does not exist
subcommit ignore errors;
create table foo (...);
commit;
The point is that this can be executed in a dumb script without worrying
about whether the subtransaction will cause an error or not.
I'm not sure if the grammar modifications are good. I thought about
using two Sconst and comparing them to "ignore errors" ... right now,
"ignore" and "errors" are in the unreserved keywords list and I get no
errors/warnings from bison, but please check this.
I had to add a new transaction block state to support rolling back a
whole transaction tree. Also I moved the TransactionState declaration
to xact.c because it has no business being in the xact.h header file
that I can see.
I made some changes to SPI so that it forbids to close a subtransaction
that the _SPI_connection did not open, by saving the nesting level at
SPI_connect() time and checking when SPI_execute is called. I had
thought that it would be easy to return to that nesting level if the
function errored out, but I was quite wrong (because the SPI code stops
executing immediately as soon as an error is encountered). Now I don't
know how to do that at all. I also thought about adding something to
the sigsetjmp() block but I don't have a clue how to handle this.
Regression tests pass; I had to change the transaction test to adopt the
new syntax. I also added a couple of tests to verify the new
functionality.
--
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"La experiencia nos dice que el hombre peló millones de veces las patatas,
pero era forzoso admitir la posibilidad de que en un caso entre millones,
las patatas pelarían al hombre" (Ijon Tichy)