diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 81d2687495..9a9724574b 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -1825,6 +1825,8 @@ CommitTransaction(void) break; } + CallXactCallbacks(XACT_EVENT_PRE_COMMIT); + /* * The remaining actions cannot call any user-defined code, so it's safe * to start shutting down within-transaction services. But note that most @@ -2028,6 +2030,8 @@ PrepareTransaction(void) break; } + CallXactCallbacks(XACT_EVENT_PRE_PREPARE); + /* * The remaining actions cannot call any user-defined code, so it's safe * to start shutting down within-transaction services. But note that most @@ -4058,8 +4062,12 @@ CommitSubTransaction(void) elog(WARNING, "CommitSubTransaction while in %s state", TransStateAsString(s->state)); - /* Pre-commit processing goes here -- nothing to do at the moment */ + /* Pre-commit processing goes here */ + CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId, + s->parent->subTransactionId); + + /* Do the actual "commit", such as it is */ s->state = TRANS_COMMIT; /* Must CCI to ensure commands of subtransaction are seen as done */ diff --git a/src/include/access/xact.h b/src/include/access/xact.h index fcdff93272..8cadc54971 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -76,7 +76,9 @@ typedef enum { XACT_EVENT_COMMIT, XACT_EVENT_ABORT, - XACT_EVENT_PREPARE + XACT_EVENT_PREPARE, + XACT_EVENT_PRE_COMMIT, + XACT_EVENT_PRE_PREPARE } XactEvent; typedef void (*XactCallback) (XactEvent event, void *arg); @@ -85,7 +87,8 @@ typedef enum { SUBXACT_EVENT_START_SUB, SUBXACT_EVENT_COMMIT_SUB, - SUBXACT_EVENT_ABORT_SUB + SUBXACT_EVENT_ABORT_SUB, + SUBXACT_EVENT_PRE_COMMIT_SUB } SubXactEvent; typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid, diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 591a432f54..70e67d9eb7 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -6150,7 +6150,7 @@ plpgsql_xact_cb(XactEvent event, void *arg) * expect the regular abort recovery procedures to release everything of * interest. */ - if (event != XACT_EVENT_ABORT) + if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE) { /* Shouldn't be any econtext stack entries left at commit */ Assert(simple_econtext_stack == NULL); @@ -6159,7 +6159,7 @@ plpgsql_xact_cb(XactEvent event, void *arg) FreeExecutorState(simple_eval_estate); simple_eval_estate = NULL; } - else + else if (event == XACT_EVENT_ABORT) { simple_econtext_stack = NULL; simple_eval_estate = NULL; @@ -6178,19 +6178,19 @@ void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg) { - if (event == SUBXACT_EVENT_START_SUB) - return; - - while (simple_econtext_stack != NULL && - simple_econtext_stack->xact_subxid == mySubid) + if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB) { - SimpleEcontextStackEntry *next; + while (simple_econtext_stack != NULL && + simple_econtext_stack->xact_subxid == mySubid) + { + SimpleEcontextStackEntry *next; - FreeExprContext(simple_econtext_stack->stack_econtext, - (event == SUBXACT_EVENT_COMMIT_SUB)); - next = simple_econtext_stack->next; - pfree(simple_econtext_stack); - simple_econtext_stack = next; + FreeExprContext(simple_econtext_stack->stack_econtext, + (event == SUBXACT_EVENT_COMMIT_SUB)); + next = simple_econtext_stack->next; + pfree(simple_econtext_stack); + simple_econtext_stack = next; + } } }