I am having a difficult time understanding transactions in Postgres. I have a procedure that may encounter an exception. There are parts of the procedure where I might want
The problem is the EXCEPTION clause.
This is implemented in PL/pgSQL as a subtransaction (the same thing as a SAVEPOINT in SQL), which is rolled back when the exception block is reached.
You cannot COMMIT while a subtransaction is active.
See this comment in src/backend/executor/spi.c:
/*
* This restriction is required by PLs implemented on top of SPI. They
* use subtransactions to establish exception blocks that are supposed to
* be rolled back together if there is an error. Terminating the
* top-level transaction in such a block violates that idea. A future PL
* implementation might have different ideas about this, in which case
* this restriction would have to be refined or the check possibly be
* moved out of SPI into the PLs.
*/
if (IsSubTransaction())
ereport(ERROR,
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
errmsg("cannot commit while a subtransaction is active")));