Skip to content

Commit fdaf448

Browse files
committed
Invent pre-commit/pre-prepare/pre-subcommit events for xact callbacks.
Currently it's only possible for loadable modules to get control during post-commit cleanup of a transaction. That doesn't work too well if they want to do something that could throw an error; for example, an FDW might need to issue a remote commit, which could well fail. To improve matters, extend the existing APIs for XactCallback and SubXactCallback functions to provide new pre-commit events for this purpose. The release notes will need to mention that existing callback functions should be checked to make sure they don't do something unwanted when one of the new event types occurs. In the examples within our source tree, contrib/sepgsql was fine but plpgsql had been a bit too cute.
1 parent 4765dd7 commit fdaf448

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

src/backend/access/transam/xact.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,8 @@ CommitTransaction(void)
18251825
break;
18261826
}
18271827

1828+
CallXactCallbacks(XACT_EVENT_PRE_COMMIT);
1829+
18281830
/*
18291831
* The remaining actions cannot call any user-defined code, so it's safe
18301832
* to start shutting down within-transaction services. But note that most
@@ -2028,6 +2030,8 @@ PrepareTransaction(void)
20282030
break;
20292031
}
20302032

2033+
CallXactCallbacks(XACT_EVENT_PRE_PREPARE);
2034+
20312035
/*
20322036
* The remaining actions cannot call any user-defined code, so it's safe
20332037
* to start shutting down within-transaction services. But note that most
@@ -4058,8 +4062,12 @@ CommitSubTransaction(void)
40584062
elog(WARNING, "CommitSubTransaction while in %s state",
40594063
TransStateAsString(s->state));
40604064

4061-
/* Pre-commit processing goes here -- nothing to do at the moment */
4065+
/* Pre-commit processing goes here */
4066+
4067+
CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
4068+
s->parent->subTransactionId);
40624069

4070+
/* Do the actual "commit", such as it is */
40634071
s->state = TRANS_COMMIT;
40644072

40654073
/* Must CCI to ensure commands of subtransaction are seen as done */

src/include/access/xact.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ typedef enum
7676
{
7777
XACT_EVENT_COMMIT,
7878
XACT_EVENT_ABORT,
79-
XACT_EVENT_PREPARE
79+
XACT_EVENT_PREPARE,
80+
XACT_EVENT_PRE_COMMIT,
81+
XACT_EVENT_PRE_PREPARE
8082
} XactEvent;
8183

8284
typedef void (*XactCallback) (XactEvent event, void *arg);
@@ -85,7 +87,8 @@ typedef enum
8587
{
8688
SUBXACT_EVENT_START_SUB,
8789
SUBXACT_EVENT_COMMIT_SUB,
88-
SUBXACT_EVENT_ABORT_SUB
90+
SUBXACT_EVENT_ABORT_SUB,
91+
SUBXACT_EVENT_PRE_COMMIT_SUB
8992
} SubXactEvent;
9093

9194
typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,

src/pl/plpgsql/src/pl_exec.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6150,7 +6150,7 @@ plpgsql_xact_cb(XactEvent event, void *arg)
61506150
* expect the regular abort recovery procedures to release everything of
61516151
* interest.
61526152
*/
6153-
if (event != XACT_EVENT_ABORT)
6153+
if (event == XACT_EVENT_COMMIT || event == XACT_EVENT_PREPARE)
61546154
{
61556155
/* Shouldn't be any econtext stack entries left at commit */
61566156
Assert(simple_econtext_stack == NULL);
@@ -6159,7 +6159,7 @@ plpgsql_xact_cb(XactEvent event, void *arg)
61596159
FreeExecutorState(simple_eval_estate);
61606160
simple_eval_estate = NULL;
61616161
}
6162-
else
6162+
else if (event == XACT_EVENT_ABORT)
61636163
{
61646164
simple_econtext_stack = NULL;
61656165
simple_eval_estate = NULL;
@@ -6178,19 +6178,19 @@ void
61786178
plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
61796179
SubTransactionId parentSubid, void *arg)
61806180
{
6181-
if (event == SUBXACT_EVENT_START_SUB)
6182-
return;
6183-
6184-
while (simple_econtext_stack != NULL &&
6185-
simple_econtext_stack->xact_subxid == mySubid)
6181+
if (event == SUBXACT_EVENT_COMMIT_SUB || event == SUBXACT_EVENT_ABORT_SUB)
61866182
{
6187-
SimpleEcontextStackEntry *next;
6183+
while (simple_econtext_stack != NULL &&
6184+
simple_econtext_stack->xact_subxid == mySubid)
6185+
{
6186+
SimpleEcontextStackEntry *next;
61886187

6189-
FreeExprContext(simple_econtext_stack->stack_econtext,
6190-
(event == SUBXACT_EVENT_COMMIT_SUB));
6191-
next = simple_econtext_stack->next;
6192-
pfree(simple_econtext_stack);
6193-
simple_econtext_stack = next;
6188+
FreeExprContext(simple_econtext_stack->stack_econtext,
6189+
(event == SUBXACT_EVENT_COMMIT_SUB));
6190+
next = simple_econtext_stack->next;
6191+
pfree(simple_econtext_stack);
6192+
simple_econtext_stack = next;
6193+
}
61946194
}
61956195
}
61966196

0 commit comments

Comments
 (0)