]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/xact.c
Clean up the rather historically encumbered interface to now() and
[postgresql] / src / backend / access / transam / xact.c
1 /*-------------------------------------------------------------------------
2  *
3  * xact.c
4  *        top level transaction system support routines
5  *
6  * See src/backend/access/transam/README for more information.
7  *
8  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.209 2005/06/29 22:51:53 tgl Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17
18 #include "postgres.h"
19
20 #include <time.h>
21 #include <unistd.h>
22
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/twophase.h"
26 #include "access/xact.h"
27 #include "catalog/heap.h"
28 #include "catalog/index.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
36 #include "storage/fd.h"
37 #include "storage/proc.h"
38 #include "storage/procarray.h"
39 #include "storage/smgr.h"
40 #include "utils/flatfiles.h"
41 #include "utils/guc.h"
42 #include "utils/inval.h"
43 #include "utils/memutils.h"
44 #include "utils/portal.h"
45 #include "utils/relcache.h"
46 #include "utils/resowner.h"
47 #include "pgstat.h"
48
49
50 /*
51  *      User-tweakable parameters
52  */
53 int                     DefaultXactIsoLevel = XACT_READ_COMMITTED;
54 int                     XactIsoLevel;
55
56 bool            DefaultXactReadOnly = false;
57 bool            XactReadOnly;
58
59 int                     CommitDelay = 0;        /* precommit delay in microseconds */
60 int                     CommitSiblings = 5; /* # concurrent xacts needed to sleep */
61
62
63 /*
64  *      transaction states - transaction state from server perspective
65  */
66 typedef enum TransState
67 {
68         TRANS_DEFAULT,
69         TRANS_START,
70         TRANS_INPROGRESS,
71         TRANS_COMMIT,
72         TRANS_ABORT,
73         TRANS_PREPARE
74 } TransState;
75
76 /*
77  *      transaction block states - transaction state of client queries
78  *
79  * Note: the subtransaction states are used only for non-topmost
80  * transactions; the others appear only in the topmost transaction.
81  */
82 typedef enum TBlockState
83 {
84         /* not-in-transaction-block states */
85         TBLOCK_DEFAULT,                         /* idle */
86         TBLOCK_STARTED,                         /* running single-query transaction */
87
88         /* transaction block states */
89         TBLOCK_BEGIN,                           /* starting transaction block */
90         TBLOCK_INPROGRESS,                      /* live transaction */
91         TBLOCK_END,                                     /* COMMIT received */
92         TBLOCK_ABORT,                           /* failed xact, awaiting ROLLBACK */
93         TBLOCK_ABORT_END,                       /* failed xact, ROLLBACK received */
94         TBLOCK_ABORT_PENDING,           /* live xact, ROLLBACK received */
95         TBLOCK_PREPARE,                         /* live xact, PREPARE received */
96
97         /* subtransaction states */
98         TBLOCK_SUBBEGIN,                        /* starting a subtransaction */
99         TBLOCK_SUBINPROGRESS,           /* live subtransaction */
100         TBLOCK_SUBEND,                          /* RELEASE received */
101         TBLOCK_SUBABORT,                        /* failed subxact, awaiting ROLLBACK */
102         TBLOCK_SUBABORT_END,            /* failed subxact, ROLLBACK received */
103         TBLOCK_SUBABORT_PENDING,        /* live subxact, ROLLBACK received */
104         TBLOCK_SUBRESTART,                      /* live subxact, ROLLBACK TO received */
105         TBLOCK_SUBABORT_RESTART         /* failed subxact, ROLLBACK TO received */
106 } TBlockState;
107
108 /*
109  *      transaction state structure
110  */
111 typedef struct TransactionStateData
112 {
113         TransactionId transactionId;            /* my XID, or Invalid if none */
114         SubTransactionId subTransactionId;      /* my subxact ID */
115         char       *name;                       /* savepoint name, if any */
116         int                     savepointLevel; /* savepoint level */
117         TransState      state;                  /* low-level state */
118         TBlockState blockState;         /* high-level state */
119         int                     nestingLevel;   /* nest depth */
120         MemoryContext curTransactionContext;            /* my xact-lifetime
121                                                                                                  * context */
122         ResourceOwner curTransactionOwner;      /* my query resources */
123         List       *childXids;          /* subcommitted child XIDs */
124         Oid                     currentUser;    /* subxact start current_user */
125         bool            prevXactReadOnly;               /* entry-time xact r/o state */
126         struct TransactionStateData *parent;            /* back link to parent */
127 } TransactionStateData;
128
129 typedef TransactionStateData *TransactionState;
130
131 /*
132  * childXids is currently implemented as an integer List, relying on the
133  * assumption that TransactionIds are no wider than int.  We use these
134  * macros to provide some isolation in case that changes in the future.
135  */
136 #define lfirst_xid(lc)                          ((TransactionId) lfirst_int(lc))
137 #define lappend_xid(list, datum)        lappend_int(list, (int) (datum))
138
139 /*
140  * CurrentTransactionState always points to the current transaction state
141  * block.  It will point to TopTransactionStateData when not in a
142  * transaction at all, or when in a top-level transaction.
143  */
144 static TransactionStateData TopTransactionStateData = {
145         0,                                                      /* transaction id */
146         0,                                                      /* subtransaction id */
147         NULL,                                           /* savepoint name */
148         0,                                                      /* savepoint level */
149         TRANS_DEFAULT,                          /* transaction state */
150         TBLOCK_DEFAULT,                         /* transaction block state from the client
151                                                                  * perspective */
152         0,                                                      /* nesting level */
153         NULL,                                           /* cur transaction context */
154         NULL,                                           /* cur transaction resource owner */
155         NIL,                                            /* subcommitted child Xids */
156         0,                                                      /* entry-time current userid */
157         false,                                          /* entry-time xact r/o state */
158         NULL                                            /* link to parent state block */
159 };
160
161 static TransactionState CurrentTransactionState = &TopTransactionStateData;
162
163 /*
164  * The subtransaction ID and command ID assignment counters are global
165  * to a whole transaction, so we do not keep them in the state stack.
166  */
167 static SubTransactionId currentSubTransactionId;
168 static CommandId currentCommandId;
169
170 /*
171  * This is the value of now(), ie, the transaction start time.
172  * This does not change as we enter and exit subtransactions, so we don't
173  * keep it inside the TransactionState stack.
174  */
175 static TimestampTz xactStartTimestamp;
176
177 /*
178  * GID to be used for preparing the current transaction.  This is also
179  * global to a whole transaction, so we don't keep it in the state stack.
180  */
181 static char *prepareGID;
182
183
184 /*
185  * List of add-on start- and end-of-xact callbacks
186  */
187 typedef struct XactCallbackItem
188 {
189         struct XactCallbackItem *next;
190         XactCallback callback;
191         void       *arg;
192 } XactCallbackItem;
193
194 static XactCallbackItem *Xact_callbacks = NULL;
195
196 /*
197  * List of add-on start- and end-of-subxact callbacks
198  */
199 typedef struct SubXactCallbackItem
200 {
201         struct SubXactCallbackItem *next;
202         SubXactCallback callback;
203         void       *arg;
204 } SubXactCallbackItem;
205
206 static SubXactCallbackItem *SubXact_callbacks = NULL;
207
208
209 /* local function prototypes */
210 static void AssignSubTransactionId(TransactionState s);
211 static void AbortTransaction(void);
212 static void AtAbort_Memory(void);
213 static void AtCleanup_Memory(void);
214 static void AtAbort_ResourceOwner(void);
215 static void AtCommit_LocalCache(void);
216 static void AtCommit_Memory(void);
217 static void AtStart_Cache(void);
218 static void AtStart_Memory(void);
219 static void AtStart_ResourceOwner(void);
220 static void CallXactCallbacks(XactEvent event);
221 static void CallSubXactCallbacks(SubXactEvent event,
222                                                                  SubTransactionId mySubid,
223                                                                  SubTransactionId parentSubid);
224 static void CleanupTransaction(void);
225 static void CommitTransaction(void);
226 static void RecordTransactionAbort(void);
227 static void StartTransaction(void);
228
229 static void RecordSubTransactionCommit(void);
230 static void StartSubTransaction(void);
231 static void CommitSubTransaction(void);
232 static void AbortSubTransaction(void);
233 static void CleanupSubTransaction(void);
234 static void PushTransaction(void);
235 static void PopTransaction(void);
236
237 static void AtSubAbort_Memory(void);
238 static void AtSubCleanup_Memory(void);
239 static void AtSubAbort_ResourceOwner(void);
240 static void AtSubCommit_Memory(void);
241 static void AtSubStart_Memory(void);
242 static void AtSubStart_ResourceOwner(void);
243
244 static void ShowTransactionState(const char *str);
245 static void ShowTransactionStateRec(TransactionState state);
246 static const char *BlockStateAsString(TBlockState blockState);
247 static const char *TransStateAsString(TransState state);
248
249
250 /* ----------------------------------------------------------------
251  *      transaction state accessors
252  * ----------------------------------------------------------------
253  */
254
255 /*
256  *      IsTransactionState
257  *
258  *      This returns true if we are currently running a query
259  *      within an executing transaction.
260  */
261 bool
262 IsTransactionState(void)
263 {
264         TransactionState s = CurrentTransactionState;
265
266         switch (s->state)
267         {
268                 case TRANS_DEFAULT:
269                         return false;
270                 case TRANS_START:
271                         return true;
272                 case TRANS_INPROGRESS:
273                         return true;
274                 case TRANS_COMMIT:
275                         return true;
276                 case TRANS_ABORT:
277                         return true;
278                 case TRANS_PREPARE:
279                         return true;
280         }
281
282         /*
283          * Shouldn't get here, but lint is not happy without this...
284          */
285         return false;
286 }
287
288 /*
289  *      IsAbortedTransactionBlockState
290  *
291  *      This returns true if we are currently running a query
292  *      within an aborted transaction block.
293  */
294 bool
295 IsAbortedTransactionBlockState(void)
296 {
297         TransactionState s = CurrentTransactionState;
298
299         if (s->blockState == TBLOCK_ABORT ||
300                 s->blockState == TBLOCK_SUBABORT)
301                 return true;
302
303         return false;
304 }
305
306
307 /*
308  *      GetTopTransactionId
309  *
310  * Get the ID of the main transaction, even if we are currently inside
311  * a subtransaction.
312  */
313 TransactionId
314 GetTopTransactionId(void)
315 {
316         return TopTransactionStateData.transactionId;
317 }
318
319
320 /*
321  *      GetCurrentTransactionId
322  *
323  * We do not assign XIDs to subtransactions until/unless this is called.
324  * When we do assign an XID to a subtransaction, recursively make sure
325  * its parent has one as well (this maintains the invariant that a child
326  * transaction has an XID following its parent's).
327  */
328 TransactionId
329 GetCurrentTransactionId(void)
330 {
331         TransactionState s = CurrentTransactionState;
332
333         if (!TransactionIdIsValid(s->transactionId))
334                 AssignSubTransactionId(s);
335
336         return s->transactionId;
337 }
338
339 static void
340 AssignSubTransactionId(TransactionState s)
341 {
342         ResourceOwner currentOwner;
343
344         Assert(s->parent != NULL);
345         Assert(s->state == TRANS_INPROGRESS);
346         if (!TransactionIdIsValid(s->parent->transactionId))
347                 AssignSubTransactionId(s->parent);
348
349         /*
350          * Generate a new Xid and record it in PG_PROC and pg_subtrans.
351          *
352          * NB: we must make the subtrans entry BEFORE the Xid appears anywhere
353          * in shared storage other than PG_PROC; because if there's no room for
354          * it in PG_PROC, the subtrans entry is needed to ensure that other
355          * backends see the Xid as "running".  See GetNewTransactionId.
356          */
357         s->transactionId = GetNewTransactionId(true);
358
359         SubTransSetParent(s->transactionId, s->parent->transactionId);
360
361         /*
362          * Acquire lock on the transaction XID.  (We assume this cannot block.)
363          * We have to be sure that the lock is assigned to the transaction's
364          * ResourceOwner.
365          */
366         currentOwner = CurrentResourceOwner;
367         PG_TRY();
368         {
369                 CurrentResourceOwner = s->curTransactionOwner;
370
371                 XactLockTableInsert(s->transactionId);
372         }
373         PG_CATCH();
374         {
375                 /* Ensure CurrentResourceOwner is restored on error */
376                 CurrentResourceOwner = currentOwner;
377                 PG_RE_THROW();
378         }
379         PG_END_TRY();
380         CurrentResourceOwner = currentOwner;
381 }
382
383
384 /*
385  *      GetCurrentTransactionIdIfAny
386  *
387  * Unlike GetCurrentTransactionId, this will return InvalidTransactionId
388  * if we are currently not in a transaction, or in a transaction or
389  * subtransaction that has not yet assigned itself an XID.
390  */
391 TransactionId
392 GetCurrentTransactionIdIfAny(void)
393 {
394         TransactionState s = CurrentTransactionState;
395
396         return s->transactionId;
397 }
398
399
400 /*
401  *      GetCurrentSubTransactionId
402  */
403 SubTransactionId
404 GetCurrentSubTransactionId(void)
405 {
406         TransactionState s = CurrentTransactionState;
407
408         return s->subTransactionId;
409 }
410
411
412 /*
413  *      GetCurrentCommandId
414  */
415 CommandId
416 GetCurrentCommandId(void)
417 {
418         /* this is global to a transaction, not subtransaction-local */
419         return currentCommandId;
420 }
421
422 /*
423  *      GetCurrentTransactionStartTimestamp
424  */
425 TimestampTz
426 GetCurrentTransactionStartTimestamp(void)
427 {
428         return xactStartTimestamp;
429 }
430
431 /*
432  *      GetCurrentTransactionNestLevel
433  *
434  * Note: this will return zero when not inside any transaction, one when
435  * inside a top-level transaction, etc.
436  */
437 int
438 GetCurrentTransactionNestLevel(void)
439 {
440         TransactionState s = CurrentTransactionState;
441
442         return s->nestingLevel;
443 }
444
445
446 /*
447  *      TransactionIdIsCurrentTransactionId
448  */
449 bool
450 TransactionIdIsCurrentTransactionId(TransactionId xid)
451 {
452         TransactionState s;
453
454         /*
455          * We always say that BootstrapTransactionId is "not my transaction ID"
456          * even when it is (ie, during bootstrap).  Along with the fact that
457          * transam.c always treats BootstrapTransactionId as already committed,
458          * this causes the tqual.c routines to see all tuples as committed,
459          * which is what we need during bootstrap.  (Bootstrap mode only inserts
460          * tuples, it never updates or deletes them, so all tuples can be presumed
461          * good immediately.)
462          */
463         if (xid == BootstrapTransactionId)
464                 return false;
465
466         /*
467          * We will return true for the Xid of the current subtransaction, any
468          * of its subcommitted children, any of its parents, or any of their
469          * previously subcommitted children.  However, a transaction being
470          * aborted is no longer "current", even though it may still have an
471          * entry on the state stack.
472          */
473         for (s = CurrentTransactionState; s != NULL; s = s->parent)
474         {
475                 ListCell   *cell;
476
477                 if (s->state == TRANS_ABORT)
478                         continue;
479                 if (!TransactionIdIsValid(s->transactionId))
480                         continue;                       /* it can't have any child XIDs either */
481                 if (TransactionIdEquals(xid, s->transactionId))
482                         return true;
483                 foreach(cell, s->childXids)
484                 {
485                         if (TransactionIdEquals(xid, lfirst_xid(cell)))
486                                 return true;
487                 }
488         }
489
490         return false;
491 }
492
493
494 /*
495  *      CommandCounterIncrement
496  */
497 void
498 CommandCounterIncrement(void)
499 {
500         currentCommandId += 1;
501         if (currentCommandId == FirstCommandId) /* check for overflow */
502         {
503                 currentCommandId -= 1;
504                 ereport(ERROR,
505                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
506                                  errmsg("cannot have more than 2^32-1 commands in a transaction")));
507         }
508
509         /* Propagate new command ID into static snapshots, if set */
510         if (SerializableSnapshot)
511                 SerializableSnapshot->curcid = currentCommandId;
512         if (LatestSnapshot)
513                 LatestSnapshot->curcid = currentCommandId;
514
515         /*
516          * make cache changes visible to me.
517          */
518         AtCommit_LocalCache();
519         AtStart_Cache();
520 }
521
522
523 /* ----------------------------------------------------------------
524  *                                              StartTransaction stuff
525  * ----------------------------------------------------------------
526  */
527
528 /*
529  *      AtStart_Cache
530  */
531 static void
532 AtStart_Cache(void)
533 {
534         AcceptInvalidationMessages();
535 }
536
537 /*
538  *      AtStart_Memory
539  */
540 static void
541 AtStart_Memory(void)
542 {
543         TransactionState s = CurrentTransactionState;
544
545         /*
546          * We shouldn't have a transaction context already.
547          */
548         Assert(TopTransactionContext == NULL);
549
550         /*
551          * Create a toplevel context for the transaction.
552          */
553         TopTransactionContext =
554                 AllocSetContextCreate(TopMemoryContext,
555                                                           "TopTransactionContext",
556                                                           ALLOCSET_DEFAULT_MINSIZE,
557                                                           ALLOCSET_DEFAULT_INITSIZE,
558                                                           ALLOCSET_DEFAULT_MAXSIZE);
559
560         /*
561          * In a top-level transaction, CurTransactionContext is the same as
562          * TopTransactionContext.
563          */
564         CurTransactionContext = TopTransactionContext;
565         s->curTransactionContext = CurTransactionContext;
566
567         /* Make the CurTransactionContext active. */
568         MemoryContextSwitchTo(CurTransactionContext);
569 }
570
571 /*
572  *      AtStart_ResourceOwner
573  */
574 static void
575 AtStart_ResourceOwner(void)
576 {
577         TransactionState s = CurrentTransactionState;
578
579         /*
580          * We shouldn't have a transaction resource owner already.
581          */
582         Assert(TopTransactionResourceOwner == NULL);
583
584         /*
585          * Create a toplevel resource owner for the transaction.
586          */
587         s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
588
589         TopTransactionResourceOwner = s->curTransactionOwner;
590         CurTransactionResourceOwner = s->curTransactionOwner;
591         CurrentResourceOwner = s->curTransactionOwner;
592 }
593
594 /* ----------------------------------------------------------------
595  *                                              StartSubTransaction stuff
596  * ----------------------------------------------------------------
597  */
598
599 /*
600  * AtSubStart_Memory
601  */
602 static void
603 AtSubStart_Memory(void)
604 {
605         TransactionState s = CurrentTransactionState;
606
607         Assert(CurTransactionContext != NULL);
608
609         /*
610          * Create a CurTransactionContext, which will be used to hold data
611          * that survives subtransaction commit but disappears on
612          * subtransaction abort. We make it a child of the immediate parent's
613          * CurTransactionContext.
614          */
615         CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
616                                                                                                   "CurTransactionContext",
617                                                                                                 ALLOCSET_DEFAULT_MINSIZE,
618                                                                                            ALLOCSET_DEFAULT_INITSIZE,
619                                                                                            ALLOCSET_DEFAULT_MAXSIZE);
620         s->curTransactionContext = CurTransactionContext;
621
622         /* Make the CurTransactionContext active. */
623         MemoryContextSwitchTo(CurTransactionContext);
624 }
625
626 /*
627  * AtSubStart_ResourceOwner
628  */
629 static void
630 AtSubStart_ResourceOwner(void)
631 {
632         TransactionState s = CurrentTransactionState;
633
634         Assert(s->parent != NULL);
635
636         /*
637          * Create a resource owner for the subtransaction.      We make it a child
638          * of the immediate parent's resource owner.
639          */
640         s->curTransactionOwner =
641                 ResourceOwnerCreate(s->parent->curTransactionOwner,
642                                                         "SubTransaction");
643
644         CurTransactionResourceOwner = s->curTransactionOwner;
645         CurrentResourceOwner = s->curTransactionOwner;
646 }
647
648 /* ----------------------------------------------------------------
649  *                                              CommitTransaction stuff
650  * ----------------------------------------------------------------
651  */
652
653 /*
654  *      RecordTransactionCommit
655  */
656 void
657 RecordTransactionCommit(void)
658 {
659         int                     nrels;
660         RelFileNode *rels;
661         int                     nchildren;
662         TransactionId *children;
663
664         /* Get data needed for commit record */
665         nrels = smgrGetPendingDeletes(true, &rels);
666         nchildren = xactGetCommittedChildren(&children);
667
668         /*
669          * If we made neither any XLOG entries nor any temp-rel updates, and
670          * have no files to be deleted, we can omit recording the transaction
671          * commit at all.  (This test includes the effects of subtransactions,
672          * so the presence of committed subxacts need not alone force a
673          * write.)
674          */
675         if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
676         {
677                 TransactionId xid = GetCurrentTransactionId();
678                 bool            madeTCentries;
679                 XLogRecPtr      recptr;
680
681                 /* Tell bufmgr and smgr to prepare for commit */
682                 BufmgrCommit();
683
684                 START_CRIT_SECTION();
685
686                 /*
687                  * If our transaction made any transaction-controlled XLOG
688                  * entries, we need to lock out checkpoint start between writing
689                  * our XLOG record and updating pg_clog.  Otherwise it is possible
690                  * for the checkpoint to set REDO after the XLOG record but fail
691                  * to flush the pg_clog update to disk, leading to loss of the
692                  * transaction commit if we crash a little later.  Slightly klugy
693                  * fix for problem discovered 2004-08-10.
694                  *
695                  * (If it made no transaction-controlled XLOG entries, its XID
696                  * appears nowhere in permanent storage, so no one else will ever
697                  * care if it committed; so it doesn't matter if we lose the
698                  * commit flag.)
699                  *
700                  * Note we only need a shared lock.
701                  */
702                 madeTCentries = (MyLastRecPtr.xrecoff != 0);
703                 if (madeTCentries)
704                         LWLockAcquire(CheckpointStartLock, LW_SHARED);
705
706                 /*
707                  * We only need to log the commit in XLOG if the transaction made
708                  * any transaction-controlled XLOG entries or will delete files.
709                  */
710                 if (madeTCentries || nrels > 0)
711                 {
712                         XLogRecData rdata[3];
713                         int                     lastrdata = 0;
714                         xl_xact_commit xlrec;
715
716                         xlrec.xtime = time(NULL);
717                         xlrec.nrels = nrels;
718                         xlrec.nsubxacts = nchildren;
719                         rdata[0].data = (char *) (&xlrec);
720                         rdata[0].len = MinSizeOfXactCommit;
721                         rdata[0].buffer = InvalidBuffer;
722                         /* dump rels to delete */
723                         if (nrels > 0)
724                         {
725                                 rdata[0].next = &(rdata[1]);
726                                 rdata[1].data = (char *) rels;
727                                 rdata[1].len = nrels * sizeof(RelFileNode);
728                                 rdata[1].buffer = InvalidBuffer;
729                                 lastrdata = 1;
730                         }
731                         /* dump committed child Xids */
732                         if (nchildren > 0)
733                         {
734                                 rdata[lastrdata].next = &(rdata[2]);
735                                 rdata[2].data = (char *) children;
736                                 rdata[2].len = nchildren * sizeof(TransactionId);
737                                 rdata[2].buffer = InvalidBuffer;
738                                 lastrdata = 2;
739                         }
740                         rdata[lastrdata].next = NULL;
741
742                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
743                 }
744                 else
745                 {
746                         /* Just flush through last record written by me */
747                         recptr = ProcLastRecEnd;
748                 }
749
750                 /*
751                  * We must flush our XLOG entries to disk if we made any XLOG
752                  * entries, whether in or out of transaction control.  For
753                  * example, if we reported a nextval() result to the client, this
754                  * ensures that any XLOG record generated by nextval will hit the
755                  * disk before we report the transaction committed.
756                  *
757                  * Note: if we generated a commit record above, MyXactMadeXLogEntry
758                  * will certainly be set now.
759                  */
760                 if (MyXactMadeXLogEntry)
761                 {
762                         /*
763                          * Sleep before flush! So we can flush more than one commit
764                          * records per single fsync.  (The idea is some other backend
765                          * may do the XLogFlush while we're sleeping.  This needs work
766                          * still, because on most Unixen, the minimum select() delay
767                          * is 10msec or more, which is way too long.)
768                          *
769                          * We do not sleep if enableFsync is not turned on, nor if there
770                          * are fewer than CommitSiblings other backends with active
771                          * transactions.
772                          */
773                         if (CommitDelay > 0 && enableFsync &&
774                                 CountActiveBackends() >= CommitSiblings)
775                                 pg_usleep(CommitDelay);
776
777                         XLogFlush(recptr);
778                 }
779
780                 /*
781                  * We must mark the transaction committed in clog if its XID
782                  * appears either in permanent rels or in local temporary rels. We
783                  * test this by seeing if we made transaction-controlled entries
784                  * *OR* local-rel tuple updates.  Note that if we made only the
785                  * latter, we have not emitted an XLOG record for our commit, and
786                  * so in the event of a crash the clog update might be lost.  This
787                  * is okay because no one else will ever care whether we
788                  * committed.
789                  */
790                 if (madeTCentries || MyXactMadeTempRelUpdate)
791                 {
792                         TransactionIdCommit(xid);
793                         /* to avoid race conditions, the parent must commit first */
794                         TransactionIdCommitTree(nchildren, children);
795                 }
796
797                 /* Unlock checkpoint lock if we acquired it */
798                 if (madeTCentries)
799                         LWLockRelease(CheckpointStartLock);
800
801                 END_CRIT_SECTION();
802         }
803
804         /* Break the chain of back-links in the XLOG records I output */
805         MyLastRecPtr.xrecoff = 0;
806         MyXactMadeXLogEntry = false;
807         MyXactMadeTempRelUpdate = false;
808
809         /* And clean up local data */
810         if (rels)
811                 pfree(rels);
812         if (children)
813                 pfree(children);
814 }
815
816
817 /*
818  *      AtCommit_LocalCache
819  */
820 static void
821 AtCommit_LocalCache(void)
822 {
823         /*
824          * Make catalog changes visible to me for the next command.
825          */
826         CommandEndInvalidationMessages();
827 }
828
829 /*
830  *      AtCommit_Memory
831  */
832 static void
833 AtCommit_Memory(void)
834 {
835         /*
836          * Now that we're "out" of a transaction, have the system allocate
837          * things in the top memory context instead of per-transaction
838          * contexts.
839          */
840         MemoryContextSwitchTo(TopMemoryContext);
841
842         /*
843          * Release all transaction-local memory.
844          */
845         Assert(TopTransactionContext != NULL);
846         MemoryContextDelete(TopTransactionContext);
847         TopTransactionContext = NULL;
848         CurTransactionContext = NULL;
849         CurrentTransactionState->curTransactionContext = NULL;
850 }
851
852 /* ----------------------------------------------------------------
853  *                                              CommitSubTransaction stuff
854  * ----------------------------------------------------------------
855  */
856
857 /*
858  * AtSubCommit_Memory
859  */
860 static void
861 AtSubCommit_Memory(void)
862 {
863         TransactionState s = CurrentTransactionState;
864
865         Assert(s->parent != NULL);
866
867         /* Return to parent transaction level's memory context. */
868         CurTransactionContext = s->parent->curTransactionContext;
869         MemoryContextSwitchTo(CurTransactionContext);
870
871         /*
872          * Ordinarily we cannot throw away the child's CurTransactionContext,
873          * since the data it contains will be needed at upper commit.  However,
874          * if there isn't actually anything in it, we can throw it away.  This
875          * avoids a small memory leak in the common case of "trivial" subxacts.
876          */
877         if (MemoryContextIsEmpty(s->curTransactionContext))
878         {
879                 MemoryContextDelete(s->curTransactionContext);
880                 s->curTransactionContext = NULL;
881         }
882 }
883
884 /*
885  * AtSubCommit_childXids
886  *
887  * Pass my own XID and my child XIDs up to my parent as committed children.
888  */
889 static void
890 AtSubCommit_childXids(void)
891 {
892         TransactionState s = CurrentTransactionState;
893         MemoryContext old_cxt;
894
895         Assert(s->parent != NULL);
896
897         /*
898          * We keep the child-XID lists in TopTransactionContext; this avoids
899          * setting up child-transaction contexts for what might be just a few
900          * bytes of grandchild XIDs.
901          */
902         old_cxt = MemoryContextSwitchTo(TopTransactionContext);
903
904         s->parent->childXids = lappend_xid(s->parent->childXids,
905                                                                            s->transactionId);
906
907         if (s->childXids != NIL)
908         {
909                 s->parent->childXids = list_concat(s->parent->childXids,
910                                                                                    s->childXids);
911                 /*
912                  * list_concat doesn't free the list header for the second list;
913                  * do so here to avoid memory leakage (kluge)
914                  */
915                 pfree(s->childXids);
916                 s->childXids = NIL;
917         }
918
919         MemoryContextSwitchTo(old_cxt);
920 }
921
922 /*
923  * RecordSubTransactionCommit
924  */
925 static void
926 RecordSubTransactionCommit(void)
927 {
928         /*
929          * We do not log the subcommit in XLOG; it doesn't matter until the
930          * top-level transaction commits.
931          *
932          * We must mark the subtransaction subcommitted in clog if its XID
933          * appears either in permanent rels or in local temporary rels. We
934          * test this by seeing if we made transaction-controlled entries *OR*
935          * local-rel tuple updates.  (The test here actually covers the entire
936          * transaction tree so far, so it may mark subtransactions that don't
937          * really need it, but it's probably not worth being tenser. Note that
938          * if a prior subtransaction dirtied these variables, then
939          * RecordTransactionCommit will have to do the full pushup anyway...)
940          */
941         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
942         {
943                 TransactionId xid = GetCurrentTransactionId();
944
945                 /* XXX does this really need to be a critical section? */
946                 START_CRIT_SECTION();
947
948                 /* Record subtransaction subcommit */
949                 TransactionIdSubCommit(xid);
950
951                 END_CRIT_SECTION();
952         }
953 }
954
955 /* ----------------------------------------------------------------
956  *                                              AbortTransaction stuff
957  * ----------------------------------------------------------------
958  */
959
960 /*
961  *      RecordTransactionAbort
962  */
963 static void
964 RecordTransactionAbort(void)
965 {
966         int                     nrels;
967         RelFileNode *rels;
968         int                     nchildren;
969         TransactionId *children;
970
971         /* Get data needed for abort record */
972         nrels = smgrGetPendingDeletes(false, &rels);
973         nchildren = xactGetCommittedChildren(&children);
974
975         /*
976          * If we made neither any transaction-controlled XLOG entries nor any
977          * temp-rel updates, and are not going to delete any files, we can
978          * omit recording the transaction abort at all.  No one will ever care
979          * that it aborted.  (These tests cover our whole transaction tree.)
980          */
981         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
982         {
983                 TransactionId xid = GetCurrentTransactionId();
984
985                 /*
986                  * Catch the scenario where we aborted partway through
987                  * RecordTransactionCommit ...
988                  */
989                 if (TransactionIdDidCommit(xid))
990                         elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
991
992                 START_CRIT_SECTION();
993
994                 /*
995                  * We only need to log the abort in XLOG if the transaction made
996                  * any transaction-controlled XLOG entries or will delete files.
997                  * (If it made no transaction-controlled XLOG entries, its XID
998                  * appears nowhere in permanent storage, so no one else will ever
999                  * care if it committed.)
1000                  *
1001                  * We do not flush XLOG to disk unless deleting files, since the
1002                  * default assumption after a crash would be that we aborted,
1003                  * anyway. For the same reason, we don't need to worry about
1004                  * interlocking against checkpoint start.
1005                  */
1006                 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1007                 {
1008                         XLogRecData rdata[3];
1009                         int                     lastrdata = 0;
1010                         xl_xact_abort xlrec;
1011                         XLogRecPtr      recptr;
1012
1013                         xlrec.xtime = time(NULL);
1014                         xlrec.nrels = nrels;
1015                         xlrec.nsubxacts = nchildren;
1016                         rdata[0].data = (char *) (&xlrec);
1017                         rdata[0].len = MinSizeOfXactAbort;
1018                         rdata[0].buffer = InvalidBuffer;
1019                         /* dump rels to delete */
1020                         if (nrels > 0)
1021                         {
1022                                 rdata[0].next = &(rdata[1]);
1023                                 rdata[1].data = (char *) rels;
1024                                 rdata[1].len = nrels * sizeof(RelFileNode);
1025                                 rdata[1].buffer = InvalidBuffer;
1026                                 lastrdata = 1;
1027                         }
1028                         /* dump committed child Xids */
1029                         if (nchildren > 0)
1030                         {
1031                                 rdata[lastrdata].next = &(rdata[2]);
1032                                 rdata[2].data = (char *) children;
1033                                 rdata[2].len = nchildren * sizeof(TransactionId);
1034                                 rdata[2].buffer = InvalidBuffer;
1035                                 lastrdata = 2;
1036                         }
1037                         rdata[lastrdata].next = NULL;
1038
1039                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1040
1041                         /* Must flush if we are deleting files... */
1042                         if (nrels > 0)
1043                                 XLogFlush(recptr);
1044                 }
1045
1046                 /*
1047                  * Mark the transaction aborted in clog.  This is not absolutely
1048                  * necessary but we may as well do it while we are here.
1049                  *
1050                  * The ordering here isn't critical but it seems best to mark the
1051                  * parent first.  This assures an atomic transition of all the
1052                  * subtransactions to aborted state from the point of view of
1053                  * concurrent TransactionIdDidAbort calls.
1054                  */
1055                 TransactionIdAbort(xid);
1056                 TransactionIdAbortTree(nchildren, children);
1057
1058                 END_CRIT_SECTION();
1059         }
1060
1061         /* Break the chain of back-links in the XLOG records I output */
1062         MyLastRecPtr.xrecoff = 0;
1063         MyXactMadeXLogEntry = false;
1064         MyXactMadeTempRelUpdate = false;
1065
1066         /* And clean up local data */
1067         if (rels)
1068                 pfree(rels);
1069         if (children)
1070                 pfree(children);
1071 }
1072
1073 /*
1074  *      AtAbort_Memory
1075  */
1076 static void
1077 AtAbort_Memory(void)
1078 {
1079         /*
1080          * Make sure we are in a valid context (not a child of
1081          * TopTransactionContext...).  Note that it is possible for this code
1082          * to be called when we aren't in a transaction at all; go directly to
1083          * TopMemoryContext in that case.
1084          */
1085         if (TopTransactionContext != NULL)
1086         {
1087                 MemoryContextSwitchTo(TopTransactionContext);
1088
1089                 /*
1090                  * We do not want to destroy the transaction's global state yet,
1091                  * so we can't free any memory here.
1092                  */
1093         }
1094         else
1095                 MemoryContextSwitchTo(TopMemoryContext);
1096 }
1097
1098 /*
1099  * AtSubAbort_Memory
1100  */
1101 static void
1102 AtSubAbort_Memory(void)
1103 {
1104         Assert(TopTransactionContext != NULL);
1105
1106         MemoryContextSwitchTo(TopTransactionContext);
1107 }
1108
1109
1110 /*
1111  *      AtAbort_ResourceOwner
1112  */
1113 static void
1114 AtAbort_ResourceOwner(void)
1115 {
1116         /*
1117          * Make sure we have a valid ResourceOwner, if possible (else it
1118          * will be NULL, which is OK)
1119          */
1120         CurrentResourceOwner = TopTransactionResourceOwner;
1121 }
1122
1123 /*
1124  * AtSubAbort_ResourceOwner
1125  */
1126 static void
1127 AtSubAbort_ResourceOwner(void)
1128 {
1129         TransactionState s = CurrentTransactionState;
1130
1131         /* Make sure we have a valid ResourceOwner */
1132         CurrentResourceOwner = s->curTransactionOwner;
1133 }
1134
1135
1136 /*
1137  * AtSubAbort_childXids
1138  */
1139 static void
1140 AtSubAbort_childXids(void)
1141 {
1142         TransactionState s = CurrentTransactionState;
1143
1144         /*
1145          * We keep the child-XID lists in TopTransactionContext (see
1146          * AtSubCommit_childXids).  This means we'd better free the list
1147          * explicitly at abort to avoid leakage.
1148          */
1149         list_free(s->childXids);
1150         s->childXids = NIL;
1151 }
1152
1153 /*
1154  * RecordSubTransactionAbort
1155  */
1156 static void
1157 RecordSubTransactionAbort(void)
1158 {
1159         int                     nrels;
1160         RelFileNode *rels;
1161         TransactionId xid = GetCurrentTransactionId();
1162         int                     nchildren;
1163         TransactionId *children;
1164
1165         /* Get data needed for abort record */
1166         nrels = smgrGetPendingDeletes(false, &rels);
1167         nchildren = xactGetCommittedChildren(&children);
1168
1169         /*
1170          * If we made neither any transaction-controlled XLOG entries nor any
1171          * temp-rel updates, and are not going to delete any files, we can
1172          * omit recording the transaction abort at all.  No one will ever care
1173          * that it aborted.  (These tests cover our whole transaction tree,
1174          * and therefore may mark subxacts that don't really need it, but it's
1175          * probably not worth being tenser.)
1176          *
1177          * In this case we needn't worry about marking subcommitted children as
1178          * aborted, because they didn't mark themselves as subcommitted in the
1179          * first place; see the optimization in RecordSubTransactionCommit.
1180          */
1181         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
1182         {
1183                 START_CRIT_SECTION();
1184
1185                 /*
1186                  * We only need to log the abort in XLOG if the transaction made
1187                  * any transaction-controlled XLOG entries or will delete files.
1188                  */
1189                 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
1190                 {
1191                         XLogRecData rdata[3];
1192                         int                     lastrdata = 0;
1193                         xl_xact_abort xlrec;
1194                         XLogRecPtr      recptr;
1195
1196                         xlrec.xtime = time(NULL);
1197                         xlrec.nrels = nrels;
1198                         xlrec.nsubxacts = nchildren;
1199                         rdata[0].data = (char *) (&xlrec);
1200                         rdata[0].len = MinSizeOfXactAbort;
1201                         rdata[0].buffer = InvalidBuffer;
1202                         /* dump rels to delete */
1203                         if (nrels > 0)
1204                         {
1205                                 rdata[0].next = &(rdata[1]);
1206                                 rdata[1].data = (char *) rels;
1207                                 rdata[1].len = nrels * sizeof(RelFileNode);
1208                                 rdata[1].buffer = InvalidBuffer;
1209                                 lastrdata = 1;
1210                         }
1211                         /* dump committed child Xids */
1212                         if (nchildren > 0)
1213                         {
1214                                 rdata[lastrdata].next = &(rdata[2]);
1215                                 rdata[2].data = (char *) children;
1216                                 rdata[2].len = nchildren * sizeof(TransactionId);
1217                                 rdata[2].buffer = InvalidBuffer;
1218                                 lastrdata = 2;
1219                         }
1220                         rdata[lastrdata].next = NULL;
1221
1222                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1223
1224                         /* Must flush if we are deleting files... */
1225                         if (nrels > 0)
1226                                 XLogFlush(recptr);
1227                 }
1228
1229                 /*
1230                  * Mark the transaction aborted in clog.  This is not absolutely
1231                  * necessary but XactLockTableWait makes use of it to avoid waiting
1232                  * for already-aborted subtransactions.
1233                  */
1234                 TransactionIdAbort(xid);
1235                 TransactionIdAbortTree(nchildren, children);
1236
1237                 END_CRIT_SECTION();
1238         }
1239
1240         /*
1241          * We can immediately remove failed XIDs from PGPROC's cache of
1242          * running child XIDs. It's easiest to do it here while we have the
1243          * child XID array at hand, even though in the main-transaction case
1244          * the equivalent work happens just after return from
1245          * RecordTransactionAbort.
1246          */
1247         XidCacheRemoveRunningXids(xid, nchildren, children);
1248
1249         /* And clean up local data */
1250         if (rels)
1251                 pfree(rels);
1252         if (children)
1253                 pfree(children);
1254 }
1255
1256 /* ----------------------------------------------------------------
1257  *                                              CleanupTransaction stuff
1258  * ----------------------------------------------------------------
1259  */
1260
1261 /*
1262  *      AtCleanup_Memory
1263  */
1264 static void
1265 AtCleanup_Memory(void)
1266 {
1267         /*
1268          * Now that we're "out" of a transaction, have the system allocate
1269          * things in the top memory context instead of per-transaction
1270          * contexts.
1271          */
1272         MemoryContextSwitchTo(TopMemoryContext);
1273
1274         Assert(CurrentTransactionState->parent == NULL);
1275
1276         /*
1277          * Release all transaction-local memory.
1278          */
1279         if (TopTransactionContext != NULL)
1280                 MemoryContextDelete(TopTransactionContext);
1281         TopTransactionContext = NULL;
1282         CurTransactionContext = NULL;
1283         CurrentTransactionState->curTransactionContext = NULL;
1284 }
1285
1286
1287 /* ----------------------------------------------------------------
1288  *                                              CleanupSubTransaction stuff
1289  * ----------------------------------------------------------------
1290  */
1291
1292 /*
1293  * AtSubCleanup_Memory
1294  */
1295 static void
1296 AtSubCleanup_Memory(void)
1297 {
1298         TransactionState s = CurrentTransactionState;
1299
1300         Assert(s->parent != NULL);
1301
1302         /* Make sure we're not in an about-to-be-deleted context */
1303         MemoryContextSwitchTo(s->parent->curTransactionContext);
1304         CurTransactionContext = s->parent->curTransactionContext;
1305
1306         /*
1307          * Delete the subxact local memory contexts. Its CurTransactionContext
1308          * can go too (note this also kills CurTransactionContexts from any
1309          * children of the subxact).
1310          */
1311         if (s->curTransactionContext)
1312                 MemoryContextDelete(s->curTransactionContext);
1313         s->curTransactionContext = NULL;
1314 }
1315
1316 /* ----------------------------------------------------------------
1317  *                                              interface routines
1318  * ----------------------------------------------------------------
1319  */
1320
1321 /*
1322  *      StartTransaction
1323  */
1324 static void
1325 StartTransaction(void)
1326 {
1327         TransactionState s;
1328
1329         /*
1330          * Let's just make sure the state stack is empty
1331          */
1332         s = &TopTransactionStateData;
1333         CurrentTransactionState = s;
1334
1335         /*
1336          * check the current transaction state
1337          */
1338         if (s->state != TRANS_DEFAULT)
1339                 elog(WARNING, "StartTransaction while in %s state",
1340                          TransStateAsString(s->state));
1341
1342         /*
1343          * set the current transaction state information appropriately during
1344          * start processing
1345          */
1346         s->state = TRANS_START;
1347         s->transactionId = InvalidTransactionId; /* until assigned */
1348
1349         /*
1350          * Make sure we've freed any old snapshot, and reset xact state
1351          * variables
1352          */
1353         FreeXactSnapshot();
1354         XactIsoLevel = DefaultXactIsoLevel;
1355         XactReadOnly = DefaultXactReadOnly;
1356
1357         /*
1358          * reinitialize within-transaction counters
1359          */
1360         s->subTransactionId = TopSubTransactionId;
1361         currentSubTransactionId = TopSubTransactionId;
1362         currentCommandId = FirstCommandId;
1363
1364         /*
1365          * must initialize resource-management stuff first
1366          */
1367         AtStart_Memory();
1368         AtStart_ResourceOwner();
1369
1370         /*
1371          * generate a new transaction id
1372          */
1373         s->transactionId = GetNewTransactionId(false);
1374
1375         XactLockTableInsert(s->transactionId);
1376
1377         /*
1378          * set now()
1379          */
1380         xactStartTimestamp = GetCurrentTimestamp();
1381
1382         /*
1383          * initialize current transaction state fields
1384          */
1385         s->nestingLevel = 1;
1386         s->childXids = NIL;
1387
1388         /*
1389          * You might expect to see "s->currentUser = GetUserId();" here, but
1390          * you won't because it doesn't work during startup; the userid isn't
1391          * set yet during a backend's first transaction start.  We only use
1392          * the currentUser field in sub-transaction state structs.
1393          *
1394          * prevXactReadOnly is also valid only in sub-transactions.
1395          */
1396
1397         /*
1398          * initialize other subsystems for new transaction
1399          */
1400         AtStart_Inval();
1401         AtStart_Cache();
1402         AfterTriggerBeginXact();
1403
1404         /*
1405          * done with start processing, set current transaction state to "in
1406          * progress"
1407          */
1408         s->state = TRANS_INPROGRESS;
1409
1410         ShowTransactionState("StartTransaction");
1411 }
1412
1413
1414 /*
1415  *      CommitTransaction
1416  *
1417  * NB: if you change this routine, better look at PrepareTransaction too!
1418  */
1419 static void
1420 CommitTransaction(void)
1421 {
1422         TransactionState s = CurrentTransactionState;
1423
1424         ShowTransactionState("CommitTransaction");
1425
1426         /*
1427          * check the current transaction state
1428          */
1429         if (s->state != TRANS_INPROGRESS)
1430                 elog(WARNING, "CommitTransaction while in %s state",
1431                          TransStateAsString(s->state));
1432         Assert(s->parent == NULL);
1433
1434         /*
1435          * Do pre-commit processing (most of this stuff requires database
1436          * access, and in fact could still cause an error...)
1437          *
1438          * It is possible for CommitHoldablePortals to invoke functions that
1439          * queue deferred triggers, and it's also possible that triggers create
1440          * holdable cursors.  So we have to loop until there's nothing left to
1441          * do.
1442          */
1443         for (;;)
1444         {
1445                 /*
1446                  * Fire all currently pending deferred triggers.
1447                  */
1448                 AfterTriggerFireDeferred();
1449
1450                 /*
1451                  * Convert any open holdable cursors into static portals.  If there
1452                  * weren't any, we are done ... otherwise loop back to check if they
1453                  * queued deferred triggers.  Lather, rinse, repeat.
1454                  */
1455                 if (!CommitHoldablePortals())
1456                         break;
1457         }
1458
1459         /* Now we can shut down the deferred-trigger manager */
1460         AfterTriggerEndXact(true);
1461
1462         /* Close any open regular cursors */
1463         AtCommit_Portals();
1464
1465         /*
1466          * Let ON COMMIT management do its thing (must happen after closing
1467          * cursors, to avoid dangling-reference problems)
1468          */
1469         PreCommit_on_commit_actions();
1470
1471         /* close large objects before lower-level cleanup */
1472         AtEOXact_LargeObject(true);
1473
1474         /* NOTIFY commit must come before lower-level cleanup */
1475         AtCommit_Notify();
1476
1477         /*
1478          * Update flat files if we changed pg_database, pg_authid or
1479          * pg_auth_members.  This should be the last step before commit.
1480          */
1481         AtEOXact_UpdateFlatFiles(true);
1482
1483         /* Prevent cancel/die interrupt while cleaning up */
1484         HOLD_INTERRUPTS();
1485
1486         /*
1487          * set the current transaction state information appropriately during
1488          * the abort processing
1489          */
1490         s->state = TRANS_COMMIT;
1491
1492         /*
1493          * Here is where we really truly commit.
1494          */
1495         RecordTransactionCommit();
1496
1497         /*----------
1498          * Let others know about no transaction in progress by me. Note that
1499          * this must be done _before_ releasing locks we hold and _after_
1500          * RecordTransactionCommit.
1501          *
1502          * LWLockAcquire(ProcArrayLock) is required; consider this example:
1503          *              UPDATE with xid 0 is blocked by xid 1's UPDATE.
1504          *              xid 1 is doing commit while xid 2 gets snapshot.
1505          * If xid 2's GetSnapshotData sees xid 1 as running then it must see
1506          * xid 0 as running as well, or it will be able to see two tuple versions
1507          * - one deleted by xid 1 and one inserted by xid 0.  See notes in
1508          * GetSnapshotData.
1509          *
1510          * Note: MyProc may be null during bootstrap.
1511          *----------
1512          */
1513         if (MyProc != NULL)
1514         {
1515                 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1516                 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1517                 MyProc->xid = InvalidTransactionId;
1518                 MyProc->xmin = InvalidTransactionId;
1519
1520                 /* Clear the subtransaction-XID cache too while holding the lock */
1521                 MyProc->subxids.nxids = 0;
1522                 MyProc->subxids.overflowed = false;
1523
1524                 LWLockRelease(ProcArrayLock);
1525         }
1526
1527         /*
1528          * This is all post-commit cleanup.  Note that if an error is raised
1529          * here, it's too late to abort the transaction.  This should be just
1530          * noncritical resource releasing.
1531          *
1532          * The ordering of operations is not entirely random.  The idea is:
1533          * release resources visible to other backends (eg, files, buffer
1534          * pins); then release locks; then release backend-local resources. We
1535          * want to release locks at the point where any backend waiting for us
1536          * will see our transaction as being fully cleaned up.
1537          *
1538          * Resources that can be associated with individual queries are handled
1539          * by the ResourceOwner mechanism.      The other calls here are for
1540          * backend-wide state.
1541          */
1542
1543         CallXactCallbacks(XACT_EVENT_COMMIT);
1544
1545         ResourceOwnerRelease(TopTransactionResourceOwner,
1546                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
1547                                                  true, true);
1548
1549         /* Check we've released all buffer pins */
1550         AtEOXact_Buffers(true);
1551
1552         /*
1553          * Make catalog changes visible to all backends.  This has to happen
1554          * after relcache references are dropped (see comments for
1555          * AtEOXact_RelationCache), but before locks are released (if anyone
1556          * is waiting for lock on a relation we've modified, we want them to
1557          * know about the catalog change before they start using the
1558          * relation).
1559          */
1560         AtEOXact_Inval(true);
1561
1562         /*
1563          * Likewise, dropping of files deleted during the transaction is best done
1564          * after releasing relcache and buffer pins.  (This is not strictly
1565          * necessary during commit, since such pins should have been released
1566          * already, but this ordering is definitely critical during abort.)
1567          */
1568         smgrDoPendingDeletes(true);
1569
1570         AtEOXact_MultiXact();
1571
1572         ResourceOwnerRelease(TopTransactionResourceOwner,
1573                                                  RESOURCE_RELEASE_LOCKS,
1574                                                  true, true);
1575         ResourceOwnerRelease(TopTransactionResourceOwner,
1576                                                  RESOURCE_RELEASE_AFTER_LOCKS,
1577                                                  true, true);
1578
1579         AtEOXact_GUC(true, false);
1580         AtEOXact_SPI(true);
1581         AtEOXact_on_commit_actions(true);
1582         AtEOXact_Namespace(true);
1583         /* smgrcommit already done */
1584         AtEOXact_Files();
1585         pgstat_count_xact_commit();
1586
1587         CurrentResourceOwner = NULL;
1588         ResourceOwnerDelete(TopTransactionResourceOwner);
1589         s->curTransactionOwner = NULL;
1590         CurTransactionResourceOwner = NULL;
1591         TopTransactionResourceOwner = NULL;
1592
1593         AtCommit_Memory();
1594
1595         s->transactionId = InvalidTransactionId;
1596         s->subTransactionId = InvalidSubTransactionId;
1597         s->nestingLevel = 0;
1598         s->childXids = NIL;
1599
1600         /*
1601          * done with commit processing, set current transaction state back to
1602          * default
1603          */
1604         s->state = TRANS_DEFAULT;
1605
1606         RESUME_INTERRUPTS();
1607 }
1608
1609
1610 /*
1611  *      PrepareTransaction
1612  *
1613  * NB: if you change this routine, better look at CommitTransaction too!
1614  */
1615 static void
1616 PrepareTransaction(void)
1617 {
1618         TransactionState        s = CurrentTransactionState;
1619         TransactionId           xid = GetCurrentTransactionId();
1620         GlobalTransaction       gxact;
1621         TimestampTz                     prepared_at;
1622
1623         ShowTransactionState("PrepareTransaction");
1624
1625         /*
1626          * check the current transaction state
1627          */
1628         if (s->state != TRANS_INPROGRESS)
1629                 elog(WARNING, "PrepareTransaction while in %s state",
1630                          TransStateAsString(s->state));
1631         Assert(s->parent == NULL);
1632
1633         /*
1634          * Do pre-commit processing (most of this stuff requires database
1635          * access, and in fact could still cause an error...)
1636          *
1637          * It is possible for PrepareHoldablePortals to invoke functions that
1638          * queue deferred triggers, and it's also possible that triggers create
1639          * holdable cursors.  So we have to loop until there's nothing left to
1640          * do.
1641          */
1642         for (;;)
1643         {
1644                 /*
1645                  * Fire all currently pending deferred triggers.
1646                  */
1647                 AfterTriggerFireDeferred();
1648
1649                 /*
1650                  * Convert any open holdable cursors into static portals.  If there
1651                  * weren't any, we are done ... otherwise loop back to check if they
1652                  * queued deferred triggers.  Lather, rinse, repeat.
1653                  */
1654                 if (!PrepareHoldablePortals())
1655                         break;
1656         }
1657
1658         /* Now we can shut down the deferred-trigger manager */
1659         AfterTriggerEndXact(true);
1660
1661         /* Close any open regular cursors */
1662         AtCommit_Portals();
1663
1664         /*
1665          * Let ON COMMIT management do its thing (must happen after closing
1666          * cursors, to avoid dangling-reference problems)
1667          */
1668         PreCommit_on_commit_actions();
1669
1670         /* close large objects before lower-level cleanup */
1671         AtEOXact_LargeObject(true);
1672
1673         /* NOTIFY and flatfiles will be handled below */
1674
1675         /* Prevent cancel/die interrupt while cleaning up */
1676         HOLD_INTERRUPTS();
1677
1678         /*
1679          * set the current transaction state information appropriately during
1680          * the processing
1681          */
1682         s->state = TRANS_PREPARE;
1683
1684         prepared_at = GetCurrentTimestamp();
1685
1686         /* Tell bufmgr and smgr to prepare for commit */
1687         BufmgrCommit();
1688
1689         /*
1690          * Reserve the GID for this transaction. This could fail if the
1691          * requested GID is invalid or already in use.
1692          */
1693         gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1694                                                         GetUserId(), MyDatabaseId);
1695         prepareGID = NULL;
1696
1697         /*
1698          * Collect data for the 2PC state file.  Note that in general, no actual
1699          * state change should happen in the called modules during this step,
1700          * since it's still possible to fail before commit, and in that case we
1701          * want transaction abort to be able to clean up.  (In particular, the
1702          * AtPrepare routines may error out if they find cases they cannot
1703          * handle.)  State cleanup should happen in the PostPrepare routines
1704          * below.  However, some modules can go ahead and clear state here
1705          * because they wouldn't do anything with it during abort anyway.
1706          *
1707          * Note: because the 2PC state file records will be replayed in the same
1708          * order they are made, the order of these calls has to match the order
1709          * in which we want things to happen during COMMIT PREPARED or
1710          * ROLLBACK PREPARED; in particular, pay attention to whether things
1711          * should happen before or after releasing the transaction's locks.
1712          */
1713         StartPrepare(gxact);
1714
1715         AtPrepare_Notify();
1716         AtPrepare_UpdateFlatFiles();
1717         AtPrepare_Inval();
1718         AtPrepare_Locks();
1719
1720         /*
1721          * Here is where we really truly prepare.
1722          *
1723          * We have to record transaction prepares even if we didn't
1724          * make any updates, because the transaction manager might
1725          * get confused if we lose a global transaction.
1726          */
1727         EndPrepare(gxact);
1728
1729         /*
1730          * Now we clean up backend-internal state and release internal
1731          * resources.
1732          */
1733
1734         /* Break the chain of back-links in the XLOG records I output */
1735         MyLastRecPtr.xrecoff = 0;
1736         MyXactMadeXLogEntry = false;
1737         MyXactMadeTempRelUpdate = false;
1738
1739         /*
1740          * Let others know about no transaction in progress by me.  This has
1741          * to be done *after* the prepared transaction has been marked valid,
1742          * else someone may think it is unlocked and recyclable.
1743          */
1744
1745         /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1746         LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1747         MyProc->xid = InvalidTransactionId;
1748         MyProc->xmin = InvalidTransactionId;
1749
1750         /* Clear the subtransaction-XID cache too while holding the lock */
1751         MyProc->subxids.nxids = 0;
1752         MyProc->subxids.overflowed = false;
1753
1754         LWLockRelease(ProcArrayLock);
1755
1756         /*
1757          * This is all post-transaction cleanup.  Note that if an error is raised
1758          * here, it's too late to abort the transaction.  This should be just
1759          * noncritical resource releasing.  See notes in CommitTransaction.
1760          */
1761
1762         CallXactCallbacks(XACT_EVENT_PREPARE);
1763
1764         ResourceOwnerRelease(TopTransactionResourceOwner,
1765                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
1766                                                  true, true);
1767
1768         /* Check we've released all buffer pins */
1769         AtEOXact_Buffers(true);
1770
1771         /* notify and flatfiles don't need a postprepare call */
1772
1773         PostPrepare_Inval();
1774
1775         PostPrepare_smgr();
1776
1777         AtEOXact_MultiXact();
1778
1779         PostPrepare_Locks(xid);
1780
1781         ResourceOwnerRelease(TopTransactionResourceOwner,
1782                                                  RESOURCE_RELEASE_LOCKS,
1783                                                  true, true);
1784         ResourceOwnerRelease(TopTransactionResourceOwner,
1785                                                  RESOURCE_RELEASE_AFTER_LOCKS,
1786                                                  true, true);
1787
1788         /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1789         AtEOXact_GUC(true, false);
1790         AtEOXact_SPI(true);
1791         AtEOXact_on_commit_actions(true);
1792         AtEOXact_Namespace(true);
1793         /* smgrcommit already done */
1794         AtEOXact_Files();
1795
1796         CurrentResourceOwner = NULL;
1797         ResourceOwnerDelete(TopTransactionResourceOwner);
1798         s->curTransactionOwner = NULL;
1799         CurTransactionResourceOwner = NULL;
1800         TopTransactionResourceOwner = NULL;
1801
1802         AtCommit_Memory();
1803
1804         s->transactionId = InvalidTransactionId;
1805         s->subTransactionId = InvalidSubTransactionId;
1806         s->nestingLevel = 0;
1807         s->childXids = NIL;
1808
1809         /*
1810          * done with 1st phase commit processing, set current transaction
1811          * state back to default
1812          */
1813         s->state = TRANS_DEFAULT;
1814
1815         RESUME_INTERRUPTS();
1816 }
1817
1818
1819 /*
1820  *      AbortTransaction
1821  */
1822 static void
1823 AbortTransaction(void)
1824 {
1825         TransactionState s = CurrentTransactionState;
1826
1827         /* Prevent cancel/die interrupt while cleaning up */
1828         HOLD_INTERRUPTS();
1829
1830         /*
1831          * Release any LW locks we might be holding as quickly as possible.
1832          * (Regular locks, however, must be held till we finish aborting.)
1833          * Releasing LW locks is critical since we might try to grab them
1834          * again while cleaning up!
1835          */
1836         LWLockReleaseAll();
1837
1838         /* Clean up buffer I/O and buffer context locks, too */
1839         AbortBufferIO();
1840         UnlockBuffers();
1841
1842         /*
1843          * Also clean up any open wait for lock, since the lock manager will
1844          * choke if we try to wait for another lock before doing this.
1845          */
1846         LockWaitCancel();
1847
1848         /*
1849          * check the current transaction state
1850          */
1851         if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
1852                 elog(WARNING, "AbortTransaction while in %s state",
1853                          TransStateAsString(s->state));
1854         Assert(s->parent == NULL);
1855
1856         /*
1857          * set the current transaction state information appropriately during
1858          * the abort processing
1859          */
1860         s->state = TRANS_ABORT;
1861
1862         /* Make sure we have a valid memory context and resource owner */
1863         AtAbort_Memory();
1864         AtAbort_ResourceOwner();
1865
1866         /*
1867          * Reset user id which might have been changed transiently.  We cannot
1868          * use s->currentUser, but must get the session userid from
1869          * miscinit.c.
1870          *
1871          * (Note: it is not necessary to restore session authorization here
1872          * because that can only be changed via GUC, and GUC will take care of
1873          * rolling it back if need be.  However, an error within a SECURITY
1874          * DEFINER function could send control here with the wrong current
1875          * userid.)
1876          */
1877         SetUserId(GetSessionUserId());
1878
1879         /*
1880          * do abort processing
1881          */
1882         AfterTriggerEndXact(false);
1883         AtAbort_Portals();
1884         AtEOXact_LargeObject(false);    /* 'false' means it's abort */
1885         AtAbort_Notify();
1886         AtEOXact_UpdateFlatFiles(false);
1887
1888         /*
1889          * Advertise the fact that we aborted in pg_clog (assuming that we
1890          * got as far as assigning an XID to advertise).
1891          */
1892         if (TransactionIdIsValid(s->transactionId))
1893                 RecordTransactionAbort();
1894
1895         /*
1896          * Let others know about no transaction in progress by me. Note that
1897          * this must be done _before_ releasing locks we hold and _after_
1898          * RecordTransactionAbort.
1899          */
1900         if (MyProc != NULL)
1901         {
1902                 /* Lock ProcArrayLock because that's what GetSnapshotData uses. */
1903                 LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1904                 MyProc->xid = InvalidTransactionId;
1905                 MyProc->xmin = InvalidTransactionId;
1906
1907                 /* Clear the subtransaction-XID cache too while holding the lock */
1908                 MyProc->subxids.nxids = 0;
1909                 MyProc->subxids.overflowed = false;
1910
1911                 LWLockRelease(ProcArrayLock);
1912         }
1913
1914         /*
1915          * Post-abort cleanup.  See notes in CommitTransaction() concerning
1916          * ordering.
1917          */
1918
1919         CallXactCallbacks(XACT_EVENT_ABORT);
1920
1921         ResourceOwnerRelease(TopTransactionResourceOwner,
1922                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
1923                                                  false, true);
1924         AtEOXact_Buffers(false);
1925         AtEOXact_Inval(false);
1926         smgrDoPendingDeletes(false);
1927         AtEOXact_MultiXact();
1928         ResourceOwnerRelease(TopTransactionResourceOwner,
1929                                                  RESOURCE_RELEASE_LOCKS,
1930                                                  false, true);
1931         ResourceOwnerRelease(TopTransactionResourceOwner,
1932                                                  RESOURCE_RELEASE_AFTER_LOCKS,
1933                                                  false, true);
1934
1935         AtEOXact_GUC(false, false);
1936         AtEOXact_SPI(false);
1937         AtEOXact_on_commit_actions(false);
1938         AtEOXact_Namespace(false);
1939         smgrabort();
1940         AtEOXact_Files();
1941         pgstat_count_xact_rollback();
1942
1943         /*
1944          * State remains TRANS_ABORT until CleanupTransaction().
1945          */
1946         RESUME_INTERRUPTS();
1947 }
1948
1949 /*
1950  *      CleanupTransaction
1951  */
1952 static void
1953 CleanupTransaction(void)
1954 {
1955         TransactionState s = CurrentTransactionState;
1956
1957         /*
1958          * State should still be TRANS_ABORT from AbortTransaction().
1959          */
1960         if (s->state != TRANS_ABORT)
1961                 elog(FATAL, "CleanupTransaction: unexpected state %s",
1962                          TransStateAsString(s->state));
1963
1964         /*
1965          * do abort cleanup processing
1966          */
1967         AtCleanup_Portals();            /* now safe to release portal memory */
1968
1969         CurrentResourceOwner = NULL;    /* and resource owner */
1970         if (TopTransactionResourceOwner)
1971                 ResourceOwnerDelete(TopTransactionResourceOwner);
1972         s->curTransactionOwner = NULL;
1973         CurTransactionResourceOwner = NULL;
1974         TopTransactionResourceOwner = NULL;
1975
1976         AtCleanup_Memory();                     /* and transaction memory */
1977
1978         s->transactionId = InvalidTransactionId;
1979         s->subTransactionId = InvalidSubTransactionId;
1980         s->nestingLevel = 0;
1981         s->childXids = NIL;
1982
1983         /*
1984          * done with abort processing, set current transaction state back to
1985          * default
1986          */
1987         s->state = TRANS_DEFAULT;
1988 }
1989
1990 /*
1991  *      StartTransactionCommand
1992  */
1993 void
1994 StartTransactionCommand(void)
1995 {
1996         TransactionState s = CurrentTransactionState;
1997
1998         switch (s->blockState)
1999         {
2000                         /*
2001                          * if we aren't in a transaction block, we just do our usual
2002                          * start transaction.
2003                          */
2004                 case TBLOCK_DEFAULT:
2005                         StartTransaction();
2006                         s->blockState = TBLOCK_STARTED;
2007                         break;
2008
2009                         /*
2010                          * We are somewhere in a transaction block or subtransaction
2011                          * and about to start a new command.  For now we do nothing,
2012                          * but someday we may do command-local resource initialization.
2013                          * (Note that any needed CommandCounterIncrement was done by
2014                          * the previous CommitTransactionCommand.)
2015                          */
2016                 case TBLOCK_INPROGRESS:
2017                 case TBLOCK_SUBINPROGRESS:
2018                         break;
2019
2020                         /*
2021                          * Here we are in a failed transaction block (one of
2022                          * the commands caused an abort) so we do nothing but remain in
2023                          * the abort state.  Eventually we will get a ROLLBACK command
2024                          * which will get us out of this state.  (It is up to other
2025                          * code to ensure that no commands other than ROLLBACK will be
2026                          * processed in these states.)
2027                          */
2028                 case TBLOCK_ABORT:
2029                 case TBLOCK_SUBABORT:
2030                         break;
2031
2032                         /* These cases are invalid. */
2033                 case TBLOCK_STARTED:
2034                 case TBLOCK_BEGIN:
2035                 case TBLOCK_SUBBEGIN:
2036                 case TBLOCK_END:
2037                 case TBLOCK_SUBEND:
2038                 case TBLOCK_ABORT_END:
2039                 case TBLOCK_SUBABORT_END:
2040                 case TBLOCK_ABORT_PENDING:
2041                 case TBLOCK_SUBABORT_PENDING:
2042                 case TBLOCK_SUBRESTART:
2043                 case TBLOCK_SUBABORT_RESTART:
2044                 case TBLOCK_PREPARE:
2045                         elog(ERROR, "StartTransactionCommand: unexpected state %s",
2046                                  BlockStateAsString(s->blockState));
2047                         break;
2048         }
2049
2050         /*
2051          * We must switch to CurTransactionContext before returning. This is
2052          * already done if we called StartTransaction, otherwise not.
2053          */
2054         Assert(CurTransactionContext != NULL);
2055         MemoryContextSwitchTo(CurTransactionContext);
2056 }
2057
2058 /*
2059  *      CommitTransactionCommand
2060  */
2061 void
2062 CommitTransactionCommand(void)
2063 {
2064         TransactionState s = CurrentTransactionState;
2065
2066         switch (s->blockState)
2067         {
2068                         /*
2069                          * This shouldn't happen, because it means the previous
2070                          * StartTransactionCommand didn't set the STARTED state
2071                          * appropriately.
2072                          */
2073                 case TBLOCK_DEFAULT:
2074                         elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2075                                  BlockStateAsString(s->blockState));
2076                         break;
2077
2078                         /*
2079                          * If we aren't in a transaction block, just do our usual
2080                          * transaction commit, and return to the idle state.
2081                          */
2082                 case TBLOCK_STARTED:
2083                         CommitTransaction();
2084                         s->blockState = TBLOCK_DEFAULT;
2085                         break;
2086
2087                         /*
2088                          * We are completing a "BEGIN TRANSACTION" command, so we
2089                          * change to the "transaction block in progress" state and
2090                          * return.  (We assume the BEGIN did nothing to the database,
2091                          * so we need no CommandCounterIncrement.)
2092                          */
2093                 case TBLOCK_BEGIN:
2094                         s->blockState = TBLOCK_INPROGRESS;
2095                         break;
2096
2097                         /*
2098                          * This is the case when we have finished executing a command
2099                          * someplace within a transaction block.  We increment the
2100                          * command counter and return.
2101                          */
2102                 case TBLOCK_INPROGRESS:
2103                 case TBLOCK_SUBINPROGRESS:
2104                         CommandCounterIncrement();
2105                         break;
2106
2107                         /*
2108                          * We are completing a "COMMIT" command.  Do it and return to
2109                          * the idle state.
2110                          */
2111                 case TBLOCK_END:
2112                         CommitTransaction();
2113                         s->blockState = TBLOCK_DEFAULT;
2114                         break;
2115
2116                         /*
2117                          * Here we are in the middle of a transaction block but one of
2118                          * the commands caused an abort so we do nothing but remain in
2119                          * the abort state.  Eventually we will get a ROLLBACK comand.
2120                          */
2121                 case TBLOCK_ABORT:
2122                 case TBLOCK_SUBABORT:
2123                         break;
2124
2125                         /*
2126                          * Here we were in an aborted transaction block and we just
2127                          * got the ROLLBACK command from the user, so clean up the
2128                          * already-aborted transaction and return to the idle state.
2129                          */
2130                 case TBLOCK_ABORT_END:
2131                         CleanupTransaction();
2132                         s->blockState = TBLOCK_DEFAULT;
2133                         break;
2134
2135                         /*
2136                          * Here we were in a perfectly good transaction block but the
2137                          * user told us to ROLLBACK anyway.  We have to abort the
2138                          * transaction and then clean up.
2139                          */
2140                 case TBLOCK_ABORT_PENDING:
2141                         AbortTransaction();
2142                         CleanupTransaction();
2143                         s->blockState = TBLOCK_DEFAULT;
2144                         break;
2145
2146                         /*
2147                          * We are completing a "PREPARE TRANSACTION" command.  Do it and
2148                          * return to the idle state.
2149                          */
2150                 case TBLOCK_PREPARE:
2151                         PrepareTransaction();
2152                         s->blockState = TBLOCK_DEFAULT;
2153                         break;
2154
2155                         /*
2156                          * We were just issued a SAVEPOINT inside a transaction block.
2157                          * Start a subtransaction.      (DefineSavepoint already did
2158                          * PushTransaction, so as to have someplace to put the
2159                          * SUBBEGIN state.)
2160                          */
2161                 case TBLOCK_SUBBEGIN:
2162                         StartSubTransaction();
2163                         s->blockState = TBLOCK_SUBINPROGRESS;
2164                         break;
2165
2166                         /*
2167                          * We were issued a COMMIT or RELEASE command, so we end the
2168                          * current subtransaction and return to the parent transaction.
2169                          * The parent might be ended too, so repeat till we are all the
2170                          * way out or find an INPROGRESS transaction.
2171                          */
2172                 case TBLOCK_SUBEND:
2173                         do
2174                         {
2175                                 CommitSubTransaction();
2176                                 s = CurrentTransactionState;    /* changed by pop */
2177                         } while (s->blockState == TBLOCK_SUBEND);
2178                         /* If we had a COMMIT command, finish off the main xact too */
2179                         if (s->blockState == TBLOCK_END)
2180                         {
2181                                 Assert(s->parent == NULL);
2182                                 CommitTransaction();
2183                                 s->blockState = TBLOCK_DEFAULT;
2184                         }
2185                         else if (s->blockState == TBLOCK_PREPARE)
2186                         {
2187                                 Assert(s->parent == NULL);
2188                                 PrepareTransaction();
2189                                 s->blockState = TBLOCK_DEFAULT;
2190                         }
2191                         else
2192                         {
2193                                 Assert(s->blockState == TBLOCK_INPROGRESS ||
2194                                            s->blockState == TBLOCK_SUBINPROGRESS);
2195                         }
2196                         break;
2197
2198                         /*
2199                          * The current already-failed subtransaction is ending due to a
2200                          * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2201                          * examine the parent (which could be in any of several states).
2202                          */
2203                 case TBLOCK_SUBABORT_END:
2204                         CleanupSubTransaction();
2205                         CommitTransactionCommand();
2206                         break;
2207
2208                         /*
2209                          * As above, but it's not dead yet, so abort first.
2210                          */
2211                 case TBLOCK_SUBABORT_PENDING:
2212                         AbortSubTransaction();
2213                         CleanupSubTransaction();
2214                         CommitTransactionCommand();
2215                         break;
2216
2217                         /*
2218                          * The current subtransaction is the target of a ROLLBACK TO
2219                          * command.  Abort and pop it, then start a new subtransaction
2220                          * with the same name.
2221                          */
2222                 case TBLOCK_SUBRESTART:
2223                         {
2224                                 char       *name;
2225                                 int                     savepointLevel;
2226
2227                                 /* save name and keep Cleanup from freeing it */
2228                                 name = s->name;
2229                                 s->name = NULL;
2230                                 savepointLevel = s->savepointLevel;
2231
2232                                 AbortSubTransaction();
2233                                 CleanupSubTransaction();
2234
2235                                 DefineSavepoint(NULL);
2236                                 s = CurrentTransactionState;    /* changed by push */
2237                                 s->name = name;
2238                                 s->savepointLevel = savepointLevel;
2239
2240                                 /* This is the same as TBLOCK_SUBBEGIN case */
2241                                 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2242                                 StartSubTransaction();
2243                                 s->blockState = TBLOCK_SUBINPROGRESS;
2244                         }
2245                         break;
2246
2247                         /*
2248                          * Same as above, but the subtransaction had already failed,
2249                          * so we don't need AbortSubTransaction.
2250                          */
2251                 case TBLOCK_SUBABORT_RESTART:
2252                         {
2253                                 char       *name;
2254                                 int                     savepointLevel;
2255
2256                                 /* save name and keep Cleanup from freeing it */
2257                                 name = s->name;
2258                                 s->name = NULL;
2259                                 savepointLevel = s->savepointLevel;
2260
2261                                 CleanupSubTransaction();
2262
2263                                 DefineSavepoint(NULL);
2264                                 s = CurrentTransactionState;    /* changed by push */
2265                                 s->name = name;
2266                                 s->savepointLevel = savepointLevel;
2267
2268                                 /* This is the same as TBLOCK_SUBBEGIN case */
2269                                 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2270                                 StartSubTransaction();
2271                                 s->blockState = TBLOCK_SUBINPROGRESS;
2272                         }
2273                         break;
2274         }
2275 }
2276
2277 /*
2278  *      AbortCurrentTransaction
2279  */
2280 void
2281 AbortCurrentTransaction(void)
2282 {
2283         TransactionState s = CurrentTransactionState;
2284
2285         switch (s->blockState)
2286         {
2287                 case TBLOCK_DEFAULT:
2288                         if (s->state == TRANS_DEFAULT)
2289                         {
2290                                 /* we are idle, so nothing to do */
2291                         }
2292                         else
2293                         {
2294                                 /*
2295                                  * We can get here after an error during transaction start
2296                                  * (state will be TRANS_START).  Need to clean up the
2297                                  * incompletely started transaction.  First, adjust the
2298                                  * low-level state to suppress warning message from
2299                                  * AbortTransaction.
2300                                  */
2301                                 if (s->state == TRANS_START)
2302                                         s->state = TRANS_INPROGRESS;
2303                                 AbortTransaction();
2304                                 CleanupTransaction();
2305                         }
2306                         break;
2307
2308                         /*
2309                          * if we aren't in a transaction block, we just do the basic
2310                          * abort & cleanup transaction.
2311                          */
2312                 case TBLOCK_STARTED:
2313                         AbortTransaction();
2314                         CleanupTransaction();
2315                         s->blockState = TBLOCK_DEFAULT;
2316                         break;
2317
2318                         /*
2319                          * If we are in TBLOCK_BEGIN it means something screwed up
2320                          * right after reading "BEGIN TRANSACTION".  We assume that
2321                          * the user will interpret the error as meaning the BEGIN
2322                          * failed to get him into a transaction block, so we should
2323                          * abort and return to idle state.
2324                          */
2325                 case TBLOCK_BEGIN:
2326                         AbortTransaction();
2327                         CleanupTransaction();
2328                         s->blockState = TBLOCK_DEFAULT;
2329                         break;
2330
2331                         /*
2332                          * We are somewhere in a transaction block and we've gotten a
2333                          * failure, so we abort the transaction and set up the persistent
2334                          * ABORT state.  We will stay in ABORT until we get a ROLLBACK.
2335                          */
2336                 case TBLOCK_INPROGRESS:
2337                         AbortTransaction();
2338                         s->blockState = TBLOCK_ABORT;
2339                         /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2340                         break;
2341
2342                         /*
2343                          * Here, we failed while trying to COMMIT.  Clean up the
2344                          * transaction and return to idle state (we do not want to
2345                          * stay in the transaction).
2346                          */
2347                 case TBLOCK_END:
2348                         AbortTransaction();
2349                         CleanupTransaction();
2350                         s->blockState = TBLOCK_DEFAULT;
2351                         break;
2352
2353                         /*
2354                          * Here, we are already in an aborted transaction state and
2355                          * are waiting for a ROLLBACK, but for some reason we failed
2356                          * again!  So we just remain in the abort state.
2357                          */
2358                 case TBLOCK_ABORT:
2359                 case TBLOCK_SUBABORT:
2360                         break;
2361
2362                         /*
2363                          * We are in a failed transaction and we got the ROLLBACK command.
2364                          * We have already aborted, we just need to cleanup and go to
2365                          * idle state.
2366                          */
2367                 case TBLOCK_ABORT_END:
2368                         CleanupTransaction();
2369                         s->blockState = TBLOCK_DEFAULT;
2370                         break;
2371
2372                         /*
2373                          * We are in a live transaction and we got a ROLLBACK command.
2374                          * Abort, cleanup, go to idle state.
2375                          */
2376                 case TBLOCK_ABORT_PENDING:
2377                         AbortTransaction();
2378                         CleanupTransaction();
2379                         s->blockState = TBLOCK_DEFAULT;
2380                         break;
2381
2382                         /*
2383                          * Here, we failed while trying to PREPARE.  Clean up the
2384                          * transaction and return to idle state (we do not want to
2385                          * stay in the transaction).
2386                          */
2387                 case TBLOCK_PREPARE:
2388                         AbortTransaction();
2389                         CleanupTransaction();
2390                         s->blockState = TBLOCK_DEFAULT;
2391                         break;
2392
2393                         /*
2394                          * We got an error inside a subtransaction.  Abort just the
2395                          * subtransaction, and go to the persistent SUBABORT state
2396                          * until we get ROLLBACK.
2397                          */
2398                 case TBLOCK_SUBINPROGRESS:
2399                         AbortSubTransaction();
2400                         s->blockState = TBLOCK_SUBABORT;
2401                         break;
2402
2403                         /*
2404                          * If we failed while trying to create a subtransaction, clean up
2405                          * the broken subtransaction and abort the parent.  The same
2406                          * applies if we get a failure while ending a subtransaction.
2407                          */
2408                 case TBLOCK_SUBBEGIN:
2409                 case TBLOCK_SUBEND:
2410                 case TBLOCK_SUBABORT_PENDING:
2411                 case TBLOCK_SUBRESTART:
2412                         AbortSubTransaction();
2413                         CleanupSubTransaction();
2414                         AbortCurrentTransaction();
2415                         break;
2416
2417                         /*
2418                          * Same as above, except the Abort() was already done.
2419                          */
2420                 case TBLOCK_SUBABORT_END:
2421                 case TBLOCK_SUBABORT_RESTART:
2422                         CleanupSubTransaction();
2423                         AbortCurrentTransaction();
2424                         break;
2425         }
2426 }
2427
2428 /*
2429  *      PreventTransactionChain
2430  *
2431  *      This routine is to be called by statements that must not run inside
2432  *      a transaction block, typically because they have non-rollback-able
2433  *      side effects or do internal commits.
2434  *
2435  *      If we have already started a transaction block, issue an error; also issue
2436  *      an error if we appear to be running inside a user-defined function (which
2437  *      could issue more commands and possibly cause a failure after the statement
2438  *      completes).  Subtransactions are verboten too.
2439  *
2440  *      stmtNode: pointer to parameter block for statement; this is used in
2441  *      a very klugy way to determine whether we are inside a function.
2442  *      stmtType: statement type name for error messages.
2443  */
2444 void
2445 PreventTransactionChain(void *stmtNode, const char *stmtType)
2446 {
2447         /*
2448          * xact block already started?
2449          */
2450         if (IsTransactionBlock())
2451                 ereport(ERROR,
2452                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2453                 /* translator: %s represents an SQL statement name */
2454                                  errmsg("%s cannot run inside a transaction block",
2455                                                 stmtType)));
2456
2457         /*
2458          * subtransaction?
2459          */
2460         if (IsSubTransaction())
2461                 ereport(ERROR,
2462                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2463                 /* translator: %s represents an SQL statement name */
2464                                  errmsg("%s cannot run inside a subtransaction",
2465                                                 stmtType)));
2466
2467         /*
2468          * Are we inside a function call?  If the statement's parameter block
2469          * was allocated in QueryContext, assume it is an interactive command.
2470          * Otherwise assume it is coming from a function.
2471          */
2472         if (!MemoryContextContains(QueryContext, stmtNode))
2473                 ereport(ERROR,
2474                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2475                 /* translator: %s represents an SQL statement name */
2476                          errmsg("%s cannot be executed from a function", stmtType)));
2477
2478         /* If we got past IsTransactionBlock test, should be in default state */
2479         if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2480                 CurrentTransactionState->blockState != TBLOCK_STARTED)
2481                 elog(FATAL, "cannot prevent transaction chain");
2482         /* all okay */
2483 }
2484
2485 /*
2486  *      RequireTransactionChain
2487  *
2488  *      This routine is to be called by statements that must run inside
2489  *      a transaction block, because they have no effects that persist past
2490  *      transaction end (and so calling them outside a transaction block
2491  *      is presumably an error).  DECLARE CURSOR is an example.
2492  *
2493  *      If we appear to be running inside a user-defined function, we do not
2494  *      issue an error, since the function could issue more commands that make
2495  *      use of the current statement's results.  Likewise subtransactions.
2496  *      Thus this is an inverse for PreventTransactionChain.
2497  *
2498  *      stmtNode: pointer to parameter block for statement; this is used in
2499  *      a very klugy way to determine whether we are inside a function.
2500  *      stmtType: statement type name for error messages.
2501  */
2502 void
2503 RequireTransactionChain(void *stmtNode, const char *stmtType)
2504 {
2505         /*
2506          * xact block already started?
2507          */
2508         if (IsTransactionBlock())
2509                 return;
2510
2511         /*
2512          * subtransaction?
2513          */
2514         if (IsSubTransaction())
2515                 return;
2516
2517         /*
2518          * Are we inside a function call?  If the statement's parameter block
2519          * was allocated in QueryContext, assume it is an interactive command.
2520          * Otherwise assume it is coming from a function.
2521          */
2522         if (!MemoryContextContains(QueryContext, stmtNode))
2523                 return;
2524         ereport(ERROR,
2525                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2526         /* translator: %s represents an SQL statement name */
2527                          errmsg("%s may only be used in transaction blocks",
2528                                         stmtType)));
2529 }
2530
2531 /*
2532  *      IsInTransactionChain
2533  *
2534  *      This routine is for statements that need to behave differently inside
2535  *      a transaction block than when running as single commands.  ANALYZE is
2536  *      currently the only example.
2537  *
2538  *      stmtNode: pointer to parameter block for statement; this is used in
2539  *      a very klugy way to determine whether we are inside a function.
2540  */
2541 bool
2542 IsInTransactionChain(void *stmtNode)
2543 {
2544         /*
2545          * Return true on same conditions that would make
2546          * PreventTransactionChain error out
2547          */
2548         if (IsTransactionBlock())
2549                 return true;
2550
2551         if (IsSubTransaction())
2552                 return true;
2553
2554         if (!MemoryContextContains(QueryContext, stmtNode))
2555                 return true;
2556
2557         if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2558                 CurrentTransactionState->blockState != TBLOCK_STARTED)
2559                 return true;
2560
2561         return false;
2562 }
2563
2564
2565 /*
2566  * Register or deregister callback functions for start- and end-of-xact
2567  * operations.
2568  *
2569  * These functions are intended for use by dynamically loaded modules.
2570  * For built-in modules we generally just hardwire the appropriate calls
2571  * (mainly because it's easier to control the order that way, where needed).
2572  *
2573  * At transaction end, the callback occurs post-commit or post-abort, so the
2574  * callback functions can only do noncritical cleanup.
2575  */
2576 void
2577 RegisterXactCallback(XactCallback callback, void *arg)
2578 {
2579         XactCallbackItem *item;
2580
2581         item = (XactCallbackItem *)
2582                 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2583         item->callback = callback;
2584         item->arg = arg;
2585         item->next = Xact_callbacks;
2586         Xact_callbacks = item;
2587 }
2588
2589 void
2590 UnregisterXactCallback(XactCallback callback, void *arg)
2591 {
2592         XactCallbackItem *item;
2593         XactCallbackItem *prev;
2594
2595         prev = NULL;
2596         for (item = Xact_callbacks; item; prev = item, item = item->next)
2597         {
2598                 if (item->callback == callback && item->arg == arg)
2599                 {
2600                         if (prev)
2601                                 prev->next = item->next;
2602                         else
2603                                 Xact_callbacks = item->next;
2604                         pfree(item);
2605                         break;
2606                 }
2607         }
2608 }
2609
2610 static void
2611 CallXactCallbacks(XactEvent event)
2612 {
2613         XactCallbackItem *item;
2614
2615         for (item = Xact_callbacks; item; item = item->next)
2616                 (*item->callback) (event, item->arg);
2617 }
2618
2619
2620 /*
2621  * Register or deregister callback functions for start- and end-of-subxact
2622  * operations.
2623  *
2624  * Pretty much same as above, but for subtransaction events.
2625  *
2626  * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2627  * so the callback functions can only do noncritical cleanup.  At
2628  * subtransaction start, the callback is called when the subtransaction has
2629  * finished initializing.
2630  */
2631 void
2632 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2633 {
2634         SubXactCallbackItem *item;
2635
2636         item = (SubXactCallbackItem *)
2637                 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2638         item->callback = callback;
2639         item->arg = arg;
2640         item->next = SubXact_callbacks;
2641         SubXact_callbacks = item;
2642 }
2643
2644 void
2645 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2646 {
2647         SubXactCallbackItem *item;
2648         SubXactCallbackItem *prev;
2649
2650         prev = NULL;
2651         for (item = SubXact_callbacks; item; prev = item, item = item->next)
2652         {
2653                 if (item->callback == callback && item->arg == arg)
2654                 {
2655                         if (prev)
2656                                 prev->next = item->next;
2657                         else
2658                                 SubXact_callbacks = item->next;
2659                         pfree(item);
2660                         break;
2661                 }
2662         }
2663 }
2664
2665 static void
2666 CallSubXactCallbacks(SubXactEvent event,
2667                                          SubTransactionId mySubid,
2668                                          SubTransactionId parentSubid)
2669 {
2670         SubXactCallbackItem *item;
2671
2672         for (item = SubXact_callbacks; item; item = item->next)
2673                 (*item->callback) (event, mySubid, parentSubid, item->arg);
2674 }
2675
2676
2677 /* ----------------------------------------------------------------
2678  *                                         transaction block support
2679  * ----------------------------------------------------------------
2680  */
2681
2682 /*
2683  *      BeginTransactionBlock
2684  *              This executes a BEGIN command.
2685  */
2686 void
2687 BeginTransactionBlock(void)
2688 {
2689         TransactionState s = CurrentTransactionState;
2690
2691         switch (s->blockState)
2692         {
2693                         /*
2694                          * We are not inside a transaction block, so allow one to
2695                          * begin.
2696                          */
2697                 case TBLOCK_STARTED:
2698                         s->blockState = TBLOCK_BEGIN;
2699                         break;
2700
2701                         /*
2702                          * Already a transaction block in progress.
2703                          */
2704                 case TBLOCK_INPROGRESS:
2705                 case TBLOCK_SUBINPROGRESS:
2706                 case TBLOCK_ABORT:
2707                 case TBLOCK_SUBABORT:
2708                         ereport(WARNING,
2709                                         (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2710                                   errmsg("there is already a transaction in progress")));
2711                         break;
2712
2713                         /* These cases are invalid. */
2714                 case TBLOCK_DEFAULT:
2715                 case TBLOCK_BEGIN:
2716                 case TBLOCK_SUBBEGIN:
2717                 case TBLOCK_END:
2718                 case TBLOCK_SUBEND:
2719                 case TBLOCK_ABORT_END:
2720                 case TBLOCK_SUBABORT_END:
2721                 case TBLOCK_ABORT_PENDING:
2722                 case TBLOCK_SUBABORT_PENDING:
2723                 case TBLOCK_SUBRESTART:
2724                 case TBLOCK_SUBABORT_RESTART:
2725                 case TBLOCK_PREPARE:
2726                         elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2727                                  BlockStateAsString(s->blockState));
2728                         break;
2729         }
2730 }
2731
2732 /*
2733  *      PrepareTransactionBlock
2734  *              This executes a PREPARE command.
2735  *
2736  * Since PREPARE may actually do a ROLLBACK, the result indicates what
2737  * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2738  *
2739  * Note that we don't actually do anything here except change blockState.
2740  * The real work will be done in the upcoming PrepareTransaction().
2741  * We do it this way because it's not convenient to change memory context,
2742  * resource owner, etc while executing inside a Portal.
2743  */
2744 bool
2745 PrepareTransactionBlock(char *gid)
2746 {
2747         TransactionState s;
2748         bool result;
2749
2750         /* Set up to commit the current transaction */
2751         result = EndTransactionBlock();
2752
2753         /* If successful, change outer tblock state to PREPARE */
2754         if (result)
2755         {
2756                 s = CurrentTransactionState;
2757
2758                 while (s->parent != NULL)
2759                         s = s->parent;
2760
2761                 if (s->blockState == TBLOCK_END)
2762                 {
2763                         /* Save GID where PrepareTransaction can find it again */
2764                         prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2765
2766                         s->blockState = TBLOCK_PREPARE;
2767                 }
2768                 else
2769                 {
2770                         /*
2771                          * ignore case where we are not in a transaction;
2772                          * EndTransactionBlock already issued a warning.
2773                          */
2774                         Assert(s->blockState == TBLOCK_STARTED);
2775                         /* Don't send back a PREPARE result tag... */
2776                         result = false;
2777                 }
2778         }
2779
2780         return result;
2781 }
2782
2783 /*
2784  *      EndTransactionBlock
2785  *              This executes a COMMIT command.
2786  *
2787  * Since COMMIT may actually do a ROLLBACK, the result indicates what
2788  * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2789  *
2790  * Note that we don't actually do anything here except change blockState.
2791  * The real work will be done in the upcoming CommitTransactionCommand().
2792  * We do it this way because it's not convenient to change memory context,
2793  * resource owner, etc while executing inside a Portal.
2794  */
2795 bool
2796 EndTransactionBlock(void)
2797 {
2798         TransactionState s = CurrentTransactionState;
2799         bool            result = false;
2800
2801         switch (s->blockState)
2802         {
2803                         /*
2804                          * We are in a transaction block, so tell CommitTransactionCommand
2805                          * to COMMIT.
2806                          */
2807                 case TBLOCK_INPROGRESS:
2808                         s->blockState = TBLOCK_END;
2809                         result = true;
2810                         break;
2811
2812                         /*
2813                          * We are in a failed transaction block.  Tell
2814                          * CommitTransactionCommand it's time to exit the block.
2815                          */
2816                 case TBLOCK_ABORT:
2817                         s->blockState = TBLOCK_ABORT_END;
2818                         break;
2819
2820                         /*
2821                          * We are in a live subtransaction block.  Set up to subcommit
2822                          * all open subtransactions and then commit the main transaction.
2823                          */
2824                 case TBLOCK_SUBINPROGRESS:
2825                         while (s->parent != NULL)
2826                         {
2827                                 if (s->blockState == TBLOCK_SUBINPROGRESS)
2828                                         s->blockState = TBLOCK_SUBEND;
2829                                 else
2830                                         elog(FATAL, "EndTransactionBlock: unexpected state %s",
2831                                                  BlockStateAsString(s->blockState));
2832                                 s = s->parent;
2833                         }
2834                         if (s->blockState == TBLOCK_INPROGRESS)
2835                                 s->blockState = TBLOCK_END;
2836                         else
2837                                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2838                                          BlockStateAsString(s->blockState));
2839                         result = true;
2840                         break;
2841
2842                         /*
2843                          * Here we are inside an aborted subtransaction.  Treat the
2844                          * COMMIT as ROLLBACK: set up to abort everything and exit
2845                          * the main transaction.
2846                          */
2847                 case TBLOCK_SUBABORT:
2848                         while (s->parent != NULL)
2849                         {
2850                                 if (s->blockState == TBLOCK_SUBINPROGRESS)
2851                                         s->blockState = TBLOCK_SUBABORT_PENDING;
2852                                 else if (s->blockState == TBLOCK_SUBABORT)
2853                                         s->blockState = TBLOCK_SUBABORT_END;
2854                                 else
2855                                         elog(FATAL, "EndTransactionBlock: unexpected state %s",
2856                                                  BlockStateAsString(s->blockState));
2857                                 s = s->parent;
2858                         }
2859                         if (s->blockState == TBLOCK_INPROGRESS)
2860                                 s->blockState = TBLOCK_ABORT_PENDING;
2861                         else if (s->blockState == TBLOCK_ABORT)
2862                                 s->blockState = TBLOCK_ABORT_END;
2863                         else
2864                                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
2865                                          BlockStateAsString(s->blockState));
2866                         break;
2867
2868                         /*
2869                          * The user issued COMMIT when not inside a transaction.  Issue a
2870                          * WARNING, staying in TBLOCK_STARTED state.  The upcoming call to
2871                          * CommitTransactionCommand() will then close the transaction and
2872                          * put us back into the default state.
2873                          */
2874                 case TBLOCK_STARTED:
2875                         ereport(WARNING,
2876                                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2877                                          errmsg("there is no transaction in progress")));
2878                         result = true;
2879                         break;
2880
2881                         /* These cases are invalid. */
2882                 case TBLOCK_DEFAULT:
2883                 case TBLOCK_BEGIN:
2884                 case TBLOCK_SUBBEGIN:
2885                 case TBLOCK_END:
2886                 case TBLOCK_SUBEND:
2887                 case TBLOCK_ABORT_END:
2888                 case TBLOCK_SUBABORT_END:
2889                 case TBLOCK_ABORT_PENDING:
2890                 case TBLOCK_SUBABORT_PENDING:
2891                 case TBLOCK_SUBRESTART:
2892                 case TBLOCK_SUBABORT_RESTART:
2893                 case TBLOCK_PREPARE:
2894                         elog(FATAL, "EndTransactionBlock: unexpected state %s",
2895                                  BlockStateAsString(s->blockState));
2896                         break;
2897         }
2898
2899         return result;
2900 }
2901
2902 /*
2903  *      UserAbortTransactionBlock
2904  *              This executes a ROLLBACK command.
2905  *
2906  * As above, we don't actually do anything here except change blockState.
2907  */
2908 void
2909 UserAbortTransactionBlock(void)
2910 {
2911         TransactionState s = CurrentTransactionState;
2912
2913         switch (s->blockState)
2914         {
2915                         /*
2916                          * We are inside a transaction block and we got a ROLLBACK
2917                          * command from the user, so tell CommitTransactionCommand
2918                          * to abort and exit the transaction block.
2919                          */
2920                 case TBLOCK_INPROGRESS:
2921                         s->blockState = TBLOCK_ABORT_PENDING;
2922                         break;
2923
2924                         /*
2925                          * We are inside a failed transaction block and we got a ROLLBACK
2926                          * command from the user.  Abort processing is already done,
2927                          * so CommitTransactionCommand just has to cleanup and go back
2928                          * to idle state.
2929                          */
2930                 case TBLOCK_ABORT:
2931                         s->blockState = TBLOCK_ABORT_END;
2932                         break;
2933
2934                         /*
2935                          * We are inside a subtransaction.  Mark everything
2936                          * up to top level as exitable.
2937                          */
2938                 case TBLOCK_SUBINPROGRESS:
2939                 case TBLOCK_SUBABORT:
2940                         while (s->parent != NULL)
2941                         {
2942                                 if (s->blockState == TBLOCK_SUBINPROGRESS)
2943                                         s->blockState = TBLOCK_SUBABORT_PENDING;
2944                                 else if (s->blockState == TBLOCK_SUBABORT)
2945                                         s->blockState = TBLOCK_SUBABORT_END;
2946                                 else
2947                                         elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2948                                                  BlockStateAsString(s->blockState));
2949                                 s = s->parent;
2950                         }
2951                         if (s->blockState == TBLOCK_INPROGRESS)
2952                                 s->blockState = TBLOCK_ABORT_PENDING;
2953                         else if (s->blockState == TBLOCK_ABORT)
2954                                 s->blockState = TBLOCK_ABORT_END;
2955                         else
2956                                 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2957                                          BlockStateAsString(s->blockState));
2958                         break;
2959
2960                         /*
2961                          * The user issued ABORT when not inside a transaction. Issue
2962                          * a WARNING and go to abort state.  The upcoming call to
2963                          * CommitTransactionCommand() will then put us back into the
2964                          * default state.
2965                          */
2966                 case TBLOCK_STARTED:
2967                         ereport(WARNING,
2968                                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2969                                          errmsg("there is no transaction in progress")));
2970                         s->blockState = TBLOCK_ABORT_PENDING;
2971                         break;
2972
2973                         /* These cases are invalid. */
2974                 case TBLOCK_DEFAULT:
2975                 case TBLOCK_BEGIN:
2976                 case TBLOCK_SUBBEGIN:
2977                 case TBLOCK_END:
2978                 case TBLOCK_SUBEND:
2979                 case TBLOCK_ABORT_END:
2980                 case TBLOCK_SUBABORT_END:
2981                 case TBLOCK_ABORT_PENDING:
2982                 case TBLOCK_SUBABORT_PENDING:
2983                 case TBLOCK_SUBRESTART:
2984                 case TBLOCK_SUBABORT_RESTART:
2985                 case TBLOCK_PREPARE:
2986                         elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2987                                  BlockStateAsString(s->blockState));
2988                         break;
2989         }
2990 }
2991
2992 /*
2993  * DefineSavepoint
2994  *              This executes a SAVEPOINT command.
2995  */
2996 void
2997 DefineSavepoint(char *name)
2998 {
2999         TransactionState s = CurrentTransactionState;
3000
3001         switch (s->blockState)
3002         {
3003                 case TBLOCK_INPROGRESS:
3004                 case TBLOCK_SUBINPROGRESS:
3005                         /* Normal subtransaction start */
3006                         PushTransaction();
3007                         s = CurrentTransactionState;            /* changed by push */
3008
3009                         /*
3010                          * Savepoint names, like the TransactionState block itself,
3011                          * live in TopTransactionContext.
3012                          */
3013                         if (name)
3014                                 s->name = MemoryContextStrdup(TopTransactionContext, name);
3015                         break;
3016
3017                         /* These cases are invalid. */
3018                 case TBLOCK_DEFAULT:
3019                 case TBLOCK_STARTED:
3020                 case TBLOCK_BEGIN:
3021                 case TBLOCK_SUBBEGIN:
3022                 case TBLOCK_END:
3023                 case TBLOCK_SUBEND:
3024                 case TBLOCK_ABORT:
3025                 case TBLOCK_SUBABORT:
3026                 case TBLOCK_ABORT_END:
3027                 case TBLOCK_SUBABORT_END:
3028                 case TBLOCK_ABORT_PENDING:
3029                 case TBLOCK_SUBABORT_PENDING:
3030                 case TBLOCK_SUBRESTART:
3031                 case TBLOCK_SUBABORT_RESTART:
3032                 case TBLOCK_PREPARE:
3033                         elog(FATAL, "DefineSavepoint: unexpected state %s",
3034                                  BlockStateAsString(s->blockState));
3035                         break;
3036         }
3037 }
3038
3039 /*
3040  * ReleaseSavepoint
3041  *              This executes a RELEASE command.
3042  *
3043  * As above, we don't actually do anything here except change blockState.
3044  */
3045 void
3046 ReleaseSavepoint(List *options)
3047 {
3048         TransactionState s = CurrentTransactionState;
3049         TransactionState target,
3050                                 xact;
3051         ListCell   *cell;
3052         char       *name = NULL;
3053
3054         switch (s->blockState)
3055         {
3056                         /*
3057                          * We can't rollback to a savepoint if there is no savepoint
3058                          * defined.
3059                          */
3060                 case TBLOCK_INPROGRESS:
3061                         ereport(ERROR,
3062                                         (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3063                                          errmsg("no such savepoint")));
3064                         break;
3065
3066                         /*
3067                          * We are in a non-aborted subtransaction.      This is the only
3068                          * valid case.
3069                          */
3070                 case TBLOCK_SUBINPROGRESS:
3071                         break;
3072
3073                         /* These cases are invalid. */
3074                 case TBLOCK_DEFAULT:
3075                 case TBLOCK_STARTED:
3076                 case TBLOCK_BEGIN:
3077                 case TBLOCK_SUBBEGIN:
3078                 case TBLOCK_END:
3079                 case TBLOCK_SUBEND:
3080                 case TBLOCK_ABORT:
3081                 case TBLOCK_SUBABORT:
3082                 case TBLOCK_ABORT_END:
3083                 case TBLOCK_SUBABORT_END:
3084                 case TBLOCK_ABORT_PENDING:
3085                 case TBLOCK_SUBABORT_PENDING:
3086                 case TBLOCK_SUBRESTART:
3087                 case TBLOCK_SUBABORT_RESTART:
3088                 case TBLOCK_PREPARE:
3089                         elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3090                                  BlockStateAsString(s->blockState));
3091                         break;
3092         }
3093
3094         foreach(cell, options)
3095         {
3096                 DefElem    *elem = lfirst(cell);
3097
3098                 if (strcmp(elem->defname, "savepoint_name") == 0)
3099                         name = strVal(elem->arg);
3100         }
3101
3102         Assert(PointerIsValid(name));
3103
3104         for (target = s; PointerIsValid(target); target = target->parent)
3105         {
3106                 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3107                         break;
3108         }
3109
3110         if (!PointerIsValid(target))
3111                 ereport(ERROR,
3112                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3113                                  errmsg("no such savepoint")));
3114
3115         /* disallow crossing savepoint level boundaries */
3116         if (target->savepointLevel != s->savepointLevel)
3117                 ereport(ERROR,
3118                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3119                                  errmsg("no such savepoint")));
3120
3121         /*
3122          * Mark "commit pending" all subtransactions up to the target
3123          * subtransaction.      The actual commits will happen when control gets
3124          * to CommitTransactionCommand.
3125          */
3126         xact = CurrentTransactionState;
3127         for (;;)
3128         {
3129                 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3130                 xact->blockState = TBLOCK_SUBEND;
3131                 if (xact == target)
3132                         break;
3133                 xact = xact->parent;
3134                 Assert(PointerIsValid(xact));
3135         }
3136 }
3137
3138 /*
3139  * RollbackToSavepoint
3140  *              This executes a ROLLBACK TO <savepoint> command.
3141  *
3142  * As above, we don't actually do anything here except change blockState.
3143  */
3144 void
3145 RollbackToSavepoint(List *options)
3146 {
3147         TransactionState s = CurrentTransactionState;
3148         TransactionState target,
3149                                 xact;
3150         ListCell   *cell;
3151         char       *name = NULL;
3152
3153         switch (s->blockState)
3154         {
3155                         /*
3156                          * We can't rollback to a savepoint if there is no savepoint
3157                          * defined.
3158                          */
3159                 case TBLOCK_INPROGRESS:
3160                 case TBLOCK_ABORT:
3161                         ereport(ERROR,
3162                                         (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3163                                          errmsg("no such savepoint")));
3164                         break;
3165
3166                         /*
3167                          * There is at least one savepoint, so proceed.
3168                          */
3169                 case TBLOCK_SUBINPROGRESS:
3170                 case TBLOCK_SUBABORT:
3171                         break;
3172
3173                         /* These cases are invalid. */
3174                 case TBLOCK_DEFAULT:
3175                 case TBLOCK_STARTED:
3176                 case TBLOCK_BEGIN:
3177                 case TBLOCK_SUBBEGIN:
3178                 case TBLOCK_END:
3179                 case TBLOCK_SUBEND:
3180                 case TBLOCK_ABORT_END:
3181                 case TBLOCK_SUBABORT_END:
3182                 case TBLOCK_ABORT_PENDING:
3183                 case TBLOCK_SUBABORT_PENDING:
3184                 case TBLOCK_SUBRESTART:
3185                 case TBLOCK_SUBABORT_RESTART:
3186                 case TBLOCK_PREPARE:
3187                         elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3188                                  BlockStateAsString(s->blockState));
3189                         break;
3190         }
3191
3192         foreach(cell, options)
3193         {
3194                 DefElem    *elem = lfirst(cell);
3195
3196                 if (strcmp(elem->defname, "savepoint_name") == 0)
3197                         name = strVal(elem->arg);
3198         }
3199
3200         Assert(PointerIsValid(name));
3201
3202         for (target = s; PointerIsValid(target); target = target->parent)
3203         {
3204                 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3205                         break;
3206         }
3207
3208         if (!PointerIsValid(target))
3209                 ereport(ERROR,
3210                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3211                                  errmsg("no such savepoint")));
3212
3213         /* disallow crossing savepoint level boundaries */
3214         if (target->savepointLevel != s->savepointLevel)
3215                 ereport(ERROR,
3216                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3217                                  errmsg("no such savepoint")));
3218
3219         /*
3220          * Mark "abort pending" all subtransactions up to the target
3221          * subtransaction.      The actual aborts will happen when control gets
3222          * to CommitTransactionCommand.
3223          */
3224         xact = CurrentTransactionState;
3225         for (;;)
3226         {
3227                 if (xact == target)
3228                         break;
3229                 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3230                         xact->blockState = TBLOCK_SUBABORT_PENDING;
3231                 else if (xact->blockState == TBLOCK_SUBABORT)
3232                         xact->blockState = TBLOCK_SUBABORT_END;
3233                 else
3234                         elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3235                                  BlockStateAsString(xact->blockState));
3236                 xact = xact->parent;
3237                 Assert(PointerIsValid(xact));
3238         }
3239
3240         /* And mark the target as "restart pending" */
3241         if (xact->blockState == TBLOCK_SUBINPROGRESS)
3242                 xact->blockState = TBLOCK_SUBRESTART;
3243         else if (xact->blockState == TBLOCK_SUBABORT)
3244                 xact->blockState = TBLOCK_SUBABORT_RESTART;
3245         else
3246                 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3247                          BlockStateAsString(xact->blockState));
3248 }
3249
3250 /*
3251  * BeginInternalSubTransaction
3252  *              This is the same as DefineSavepoint except it allows TBLOCK_STARTED
3253  *              state, and therefore it can safely be used in a function that might
3254  *              be called when not inside a BEGIN block.  Also, we automatically
3255  *              cycle through CommitTransactionCommand/StartTransactionCommand
3256  *              instead of expecting the caller to do it.
3257  */
3258 void
3259 BeginInternalSubTransaction(char *name)
3260 {
3261         TransactionState s = CurrentTransactionState;
3262
3263         switch (s->blockState)
3264         {
3265                 case TBLOCK_STARTED:
3266                 case TBLOCK_INPROGRESS:
3267                 case TBLOCK_SUBINPROGRESS:
3268                         /* Normal subtransaction start */
3269                         PushTransaction();
3270                         s = CurrentTransactionState;            /* changed by push */
3271
3272                         /*
3273                          * Savepoint names, like the TransactionState block itself,
3274                          * live in TopTransactionContext.
3275                          */
3276                         if (name)
3277                                 s->name = MemoryContextStrdup(TopTransactionContext, name);
3278                         break;
3279
3280                         /* These cases are invalid. */
3281                 case TBLOCK_DEFAULT:
3282                 case TBLOCK_BEGIN:
3283                 case TBLOCK_SUBBEGIN:
3284                 case TBLOCK_END:
3285                 case TBLOCK_SUBEND:
3286                 case TBLOCK_ABORT:
3287                 case TBLOCK_SUBABORT:
3288                 case TBLOCK_ABORT_END:
3289                 case TBLOCK_SUBABORT_END:
3290                 case TBLOCK_ABORT_PENDING:
3291                 case TBLOCK_SUBABORT_PENDING:
3292                 case TBLOCK_SUBRESTART:
3293                 case TBLOCK_SUBABORT_RESTART:
3294                 case TBLOCK_PREPARE:
3295                         elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3296                                  BlockStateAsString(s->blockState));
3297                         break;
3298         }
3299
3300         CommitTransactionCommand();
3301         StartTransactionCommand();
3302 }
3303
3304 /*
3305  * ReleaseCurrentSubTransaction
3306  *
3307  * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3308  * savepoint name (if any).
3309  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3310  */
3311 void
3312 ReleaseCurrentSubTransaction(void)
3313 {
3314         TransactionState s = CurrentTransactionState;
3315
3316         if (s->blockState != TBLOCK_SUBINPROGRESS)
3317                 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3318                          BlockStateAsString(s->blockState));
3319         Assert(s->state == TRANS_INPROGRESS);
3320         MemoryContextSwitchTo(CurTransactionContext);
3321         CommitSubTransaction();
3322         s = CurrentTransactionState; /* changed by pop */
3323         Assert(s->state == TRANS_INPROGRESS);
3324 }
3325
3326 /*
3327  * RollbackAndReleaseCurrentSubTransaction
3328  *
3329  * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3330  * of its savepoint name (if any).
3331  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3332  */
3333 void
3334 RollbackAndReleaseCurrentSubTransaction(void)
3335 {
3336         TransactionState s = CurrentTransactionState;
3337
3338         switch (s->blockState)
3339         {
3340                         /* Must be in a subtransaction */
3341                 case TBLOCK_SUBINPROGRESS:
3342                 case TBLOCK_SUBABORT:
3343                         break;
3344
3345                         /* These cases are invalid. */
3346                 case TBLOCK_DEFAULT:
3347                 case TBLOCK_STARTED:
3348                 case TBLOCK_BEGIN:
3349                 case TBLOCK_SUBBEGIN:
3350                 case TBLOCK_INPROGRESS:
3351                 case TBLOCK_END:
3352                 case TBLOCK_SUBEND:
3353                 case TBLOCK_ABORT:
3354                 case TBLOCK_ABORT_END:
3355                 case TBLOCK_SUBABORT_END:
3356                 case TBLOCK_ABORT_PENDING:
3357                 case TBLOCK_SUBABORT_PENDING:
3358                 case TBLOCK_SUBRESTART:
3359                 case TBLOCK_SUBABORT_RESTART:
3360                 case TBLOCK_PREPARE:
3361                         elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3362                                  BlockStateAsString(s->blockState));
3363                         break;
3364         }
3365
3366         /*
3367          * Abort the current subtransaction, if needed.
3368          */
3369         if (s->blockState == TBLOCK_SUBINPROGRESS)
3370                 AbortSubTransaction();
3371
3372         /* And clean it up, too */
3373         CleanupSubTransaction();
3374
3375         s = CurrentTransactionState;    /* changed by pop */
3376         AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3377                                 s->blockState == TBLOCK_INPROGRESS ||
3378                                 s->blockState == TBLOCK_STARTED);
3379 }
3380
3381 /*
3382  *      AbortOutOfAnyTransaction
3383  *
3384  *      This routine is provided for error recovery purposes.  It aborts any
3385  *      active transaction or transaction block, leaving the system in a known
3386  *      idle state.
3387  */
3388 void
3389 AbortOutOfAnyTransaction(void)
3390 {
3391         TransactionState s = CurrentTransactionState;
3392
3393         /*
3394          * Get out of any transaction or nested transaction
3395          */
3396         do
3397         {
3398                 switch (s->blockState)
3399                 {
3400                         case TBLOCK_DEFAULT:
3401                                 /* Not in a transaction, do nothing */
3402                                 break;
3403                         case TBLOCK_STARTED:
3404                         case TBLOCK_BEGIN:
3405                         case TBLOCK_INPROGRESS:
3406                         case TBLOCK_END:
3407                         case TBLOCK_ABORT_PENDING:
3408                         case TBLOCK_PREPARE:
3409                                 /* In a transaction, so clean up */
3410                                 AbortTransaction();
3411                                 CleanupTransaction();
3412                                 s->blockState = TBLOCK_DEFAULT;
3413                                 break;
3414                         case TBLOCK_ABORT:
3415                         case TBLOCK_ABORT_END:
3416                                 /* AbortTransaction already done, still need Cleanup */
3417                                 CleanupTransaction();
3418                                 s->blockState = TBLOCK_DEFAULT;
3419                                 break;
3420
3421                                 /*
3422                                  * In a subtransaction, so clean it up and abort parent
3423                                  * too
3424                                  */
3425                         case TBLOCK_SUBBEGIN:
3426                         case TBLOCK_SUBINPROGRESS:
3427                         case TBLOCK_SUBEND:
3428                         case TBLOCK_SUBABORT_PENDING:
3429                         case TBLOCK_SUBRESTART:
3430                                 AbortSubTransaction();
3431                                 CleanupSubTransaction();
3432                                 s = CurrentTransactionState;    /* changed by pop */
3433                                 break;
3434
3435                         case TBLOCK_SUBABORT:
3436                         case TBLOCK_SUBABORT_END:
3437                         case TBLOCK_SUBABORT_RESTART:
3438                                 /* As above, but AbortSubTransaction already done */
3439                                 CleanupSubTransaction();
3440                                 s = CurrentTransactionState;    /* changed by pop */
3441                                 break;
3442                 }
3443         } while (s->blockState != TBLOCK_DEFAULT);
3444
3445         /* Should be out of all subxacts now */
3446         Assert(s->parent == NULL);
3447 }
3448
3449 /*
3450  * IsTransactionBlock --- are we within a transaction block?
3451  */
3452 bool
3453 IsTransactionBlock(void)
3454 {
3455         TransactionState s = CurrentTransactionState;
3456
3457         if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3458                 return false;
3459
3460         return true;
3461 }
3462
3463 /*
3464  * IsTransactionOrTransactionBlock --- are we within either a transaction
3465  * or a transaction block?      (The backend is only really "idle" when this
3466  * returns false.)
3467  *
3468  * This should match up with IsTransactionBlock and IsTransactionState.
3469  */
3470 bool
3471 IsTransactionOrTransactionBlock(void)
3472 {
3473         TransactionState s = CurrentTransactionState;
3474
3475         if (s->blockState == TBLOCK_DEFAULT)
3476                 return false;
3477
3478         return true;
3479 }
3480
3481 /*
3482  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3483  */
3484 char
3485 TransactionBlockStatusCode(void)
3486 {
3487         TransactionState s = CurrentTransactionState;
3488
3489         switch (s->blockState)
3490         {
3491                 case TBLOCK_DEFAULT:
3492                 case TBLOCK_STARTED:
3493                         return 'I';                     /* idle --- not in transaction */
3494                 case TBLOCK_BEGIN:
3495                 case TBLOCK_SUBBEGIN:
3496                 case TBLOCK_INPROGRESS:
3497                 case TBLOCK_SUBINPROGRESS:
3498                 case TBLOCK_END:
3499                 case TBLOCK_SUBEND:
3500                 case TBLOCK_PREPARE:
3501                         return 'T';                     /* in transaction */
3502                 case TBLOCK_ABORT:
3503                 case TBLOCK_SUBABORT:
3504                 case TBLOCK_ABORT_END:
3505                 case TBLOCK_SUBABORT_END:
3506                 case TBLOCK_ABORT_PENDING:
3507                 case TBLOCK_SUBABORT_PENDING:
3508                 case TBLOCK_SUBRESTART:
3509                 case TBLOCK_SUBABORT_RESTART:
3510                         return 'E';                     /* in failed transaction */
3511         }
3512
3513         /* should never get here */
3514         elog(FATAL, "invalid transaction block state: %s",
3515                  BlockStateAsString(s->blockState));
3516         return 0;                                       /* keep compiler quiet */
3517 }
3518
3519 /*
3520  * IsSubTransaction
3521  */
3522 bool
3523 IsSubTransaction(void)
3524 {
3525         TransactionState s = CurrentTransactionState;
3526
3527         if (s->nestingLevel >= 2)
3528                 return true;
3529
3530         return false;
3531 }
3532
3533 /*
3534  * StartSubTransaction
3535  *
3536  * If you're wondering why this is separate from PushTransaction: it's because
3537  * we can't conveniently do this stuff right inside DefineSavepoint.  The
3538  * SAVEPOINT utility command will be executed inside a Portal, and if we
3539  * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3540  * the Portal will undo those settings.  So we make DefineSavepoint just
3541  * push a dummy transaction block, and when control returns to the main
3542  * idle loop, CommitTransactionCommand will be called, and we'll come here
3543  * to finish starting the subtransaction.
3544  */
3545 static void
3546 StartSubTransaction(void)
3547 {
3548         TransactionState s = CurrentTransactionState;
3549
3550         if (s->state != TRANS_DEFAULT)
3551                 elog(WARNING, "StartSubTransaction while in %s state",
3552                          TransStateAsString(s->state));
3553
3554         s->state = TRANS_START;
3555
3556         /*
3557          * Initialize subsystems for new subtransaction
3558          *
3559          * must initialize resource-management stuff first
3560          */
3561         AtSubStart_Memory();
3562         AtSubStart_ResourceOwner();
3563         AtSubStart_Inval();
3564         AtSubStart_Notify();
3565         AfterTriggerBeginSubXact();
3566
3567         s->state = TRANS_INPROGRESS;
3568
3569         /*
3570          * Call start-of-subxact callbacks
3571          */
3572         CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3573                                                  s->parent->subTransactionId);
3574
3575         ShowTransactionState("StartSubTransaction");
3576 }
3577
3578 /*
3579  * CommitSubTransaction
3580  *
3581  *      The caller has to make sure to always reassign CurrentTransactionState
3582  *      if it has a local pointer to it after calling this function.
3583  */
3584 static void
3585 CommitSubTransaction(void)
3586 {
3587         TransactionState s = CurrentTransactionState;
3588
3589         ShowTransactionState("CommitSubTransaction");
3590
3591         if (s->state != TRANS_INPROGRESS)
3592                 elog(WARNING, "CommitSubTransaction while in %s state",
3593                          TransStateAsString(s->state));
3594
3595         /* Pre-commit processing goes here -- nothing to do at the moment */
3596
3597         s->state = TRANS_COMMIT;
3598
3599         /* Must CCI to ensure commands of subtransaction are seen as done */
3600         CommandCounterIncrement();
3601
3602         /* Mark subtransaction as subcommitted */
3603         if (TransactionIdIsValid(s->transactionId))
3604         {
3605                 RecordSubTransactionCommit();
3606                 AtSubCommit_childXids();
3607         }
3608
3609         /* Post-commit cleanup */
3610         AfterTriggerEndSubXact(true);
3611         AtSubCommit_Portals(s->subTransactionId,
3612                                                 s->parent->subTransactionId,
3613                                                 s->parent->curTransactionOwner);
3614         AtEOSubXact_LargeObject(true, s->subTransactionId,
3615                                                         s->parent->subTransactionId);
3616         AtSubCommit_Notify();
3617         AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3618                                                                 s->parent->subTransactionId);
3619
3620         CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3621                                                  s->parent->subTransactionId);
3622
3623         ResourceOwnerRelease(s->curTransactionOwner,
3624                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
3625                                                  true, false);
3626         AtEOSubXact_RelationCache(true, s->subTransactionId,
3627                                                           s->parent->subTransactionId);
3628         AtEOSubXact_Inval(true);
3629         AtSubCommit_smgr();
3630
3631         /*
3632          * The only lock we actually release here is the subtransaction XID lock.
3633          * The rest just get transferred to the parent resource owner.
3634          */
3635         CurrentResourceOwner = s->curTransactionOwner;
3636         if (TransactionIdIsValid(s->transactionId))
3637                 XactLockTableDelete(s->transactionId);
3638
3639         ResourceOwnerRelease(s->curTransactionOwner,
3640                                                  RESOURCE_RELEASE_LOCKS,
3641                                                  true, false);
3642         ResourceOwnerRelease(s->curTransactionOwner,
3643                                                  RESOURCE_RELEASE_AFTER_LOCKS,
3644                                                  true, false);
3645
3646         AtEOXact_GUC(true, true);
3647         AtEOSubXact_SPI(true, s->subTransactionId);
3648         AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3649                                                                   s->parent->subTransactionId);
3650         AtEOSubXact_Namespace(true, s->subTransactionId,
3651                                                   s->parent->subTransactionId);
3652         AtEOSubXact_Files(true, s->subTransactionId,
3653                                           s->parent->subTransactionId);
3654
3655         /*
3656          * We need to restore the upper transaction's read-only state, in case
3657          * the upper is read-write while the child is read-only; GUC will
3658          * incorrectly think it should leave the child state in place.
3659          */
3660         XactReadOnly = s->prevXactReadOnly;
3661
3662         CurrentResourceOwner = s->parent->curTransactionOwner;
3663         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3664         ResourceOwnerDelete(s->curTransactionOwner);
3665         s->curTransactionOwner = NULL;
3666
3667         AtSubCommit_Memory();
3668
3669         s->state = TRANS_DEFAULT;
3670
3671         PopTransaction();
3672 }
3673
3674 /*
3675  * AbortSubTransaction
3676  */
3677 static void
3678 AbortSubTransaction(void)
3679 {
3680         TransactionState s = CurrentTransactionState;
3681
3682         ShowTransactionState("AbortSubTransaction");
3683
3684         if (s->state != TRANS_INPROGRESS)
3685                 elog(WARNING, "AbortSubTransaction while in %s state",
3686                          TransStateAsString(s->state));
3687
3688         HOLD_INTERRUPTS();
3689
3690         s->state = TRANS_ABORT;
3691
3692         /*
3693          * Release any LW locks we might be holding as quickly as possible.
3694          * (Regular locks, however, must be held till we finish aborting.)
3695          * Releasing LW locks is critical since we might try to grab them
3696          * again while cleaning up!
3697          *
3698          * FIXME This may be incorrect --- Are there some locks we should keep?
3699          * Buffer locks, for example?  I don't think so but I'm not sure.
3700          */
3701         LWLockReleaseAll();
3702
3703         AbortBufferIO();
3704         UnlockBuffers();
3705
3706         LockWaitCancel();
3707
3708         /*
3709          * do abort processing
3710          */
3711         AtSubAbort_Memory();
3712         AtSubAbort_ResourceOwner();
3713
3714         /*
3715          * We can skip all this stuff if the subxact failed before creating
3716          * a ResourceOwner...
3717          */
3718         if (s->curTransactionOwner)
3719         {
3720                 AfterTriggerEndSubXact(false);
3721                 AtSubAbort_Portals(s->subTransactionId,
3722                                                    s->parent->subTransactionId,
3723                                                    s->parent->curTransactionOwner);
3724                 AtEOSubXact_LargeObject(false, s->subTransactionId,
3725                                                                 s->parent->subTransactionId);
3726                 AtSubAbort_Notify();
3727                 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3728                                                                         s->parent->subTransactionId);
3729
3730                 /* Advertise the fact that we aborted in pg_clog. */
3731                 if (TransactionIdIsValid(s->transactionId))
3732                 {
3733                         RecordSubTransactionAbort();
3734                         AtSubAbort_childXids();
3735                 }
3736
3737                 /* Post-abort cleanup */
3738                 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3739                                                          s->parent->subTransactionId);
3740
3741                 ResourceOwnerRelease(s->curTransactionOwner,
3742                                                          RESOURCE_RELEASE_BEFORE_LOCKS,
3743                                                          false, false);
3744                 AtEOSubXact_RelationCache(false, s->subTransactionId,
3745                                                                   s->parent->subTransactionId);
3746                 AtEOSubXact_Inval(false);
3747                 AtSubAbort_smgr();
3748                 ResourceOwnerRelease(s->curTransactionOwner,
3749                                                          RESOURCE_RELEASE_LOCKS,
3750                                                          false, false);
3751                 ResourceOwnerRelease(s->curTransactionOwner,
3752                                                          RESOURCE_RELEASE_AFTER_LOCKS,
3753                                                          false, false);
3754
3755                 AtEOXact_GUC(false, true);
3756                 AtEOSubXact_SPI(false, s->subTransactionId);
3757                 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3758                                                                           s->parent->subTransactionId);
3759                 AtEOSubXact_Namespace(false, s->subTransactionId,
3760                                                           s->parent->subTransactionId);
3761                 AtEOSubXact_Files(false, s->subTransactionId,
3762                                                   s->parent->subTransactionId);
3763         }
3764
3765         /*
3766          * Reset user id which might have been changed transiently.  Here we
3767          * want to restore to the userid that was current at subxact entry.
3768          * (As in AbortTransaction, we need not worry about the session
3769          * userid.)
3770          *
3771          * Must do this after AtEOXact_GUC to handle the case where we entered
3772          * the subxact inside a SECURITY DEFINER function (hence current and
3773          * session userids were different) and then session auth was changed
3774          * inside the subxact.  GUC will reset both current and session
3775          * userids to the entry-time session userid.  This is right in every
3776          * other scenario so it seems simplest to let GUC do that and fix it
3777          * here.
3778          */
3779         SetUserId(s->currentUser);
3780
3781         /*
3782          * Restore the upper transaction's read-only state, too.  This should
3783          * be redundant with GUC's cleanup but we may as well do it for
3784          * consistency with the commit case.
3785          */
3786         XactReadOnly = s->prevXactReadOnly;
3787
3788         RESUME_INTERRUPTS();
3789 }
3790
3791 /*
3792  * CleanupSubTransaction
3793  *
3794  *      The caller has to make sure to always reassign CurrentTransactionState
3795  *      if it has a local pointer to it after calling this function.
3796  */
3797 static void
3798 CleanupSubTransaction(void)
3799 {
3800         TransactionState s = CurrentTransactionState;
3801
3802         ShowTransactionState("CleanupSubTransaction");
3803
3804         if (s->state != TRANS_ABORT)
3805                 elog(WARNING, "CleanupSubTransaction while in %s state",
3806                          TransStateAsString(s->state));
3807
3808         AtSubCleanup_Portals(s->subTransactionId);
3809
3810         CurrentResourceOwner = s->parent->curTransactionOwner;
3811         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3812         if (s->curTransactionOwner)
3813                 ResourceOwnerDelete(s->curTransactionOwner);
3814         s->curTransactionOwner = NULL;
3815
3816         AtSubCleanup_Memory();
3817
3818         s->state = TRANS_DEFAULT;
3819
3820         PopTransaction();
3821 }
3822
3823 /*
3824  * PushTransaction
3825  *              Create transaction state stack entry for a subtransaction
3826  *
3827  *      The caller has to make sure to always reassign CurrentTransactionState
3828  *      if it has a local pointer to it after calling this function.
3829  */
3830 static void
3831 PushTransaction(void)
3832 {
3833         TransactionState p = CurrentTransactionState;
3834         TransactionState s;
3835         Oid     currentUser;
3836
3837         /*
3838          * At present, GetUserId cannot fail, but let's not assume that.  Get
3839          * the ID before entering the critical code sequence.
3840          */
3841         currentUser = GetUserId();
3842
3843         /*
3844          * We keep subtransaction state nodes in TopTransactionContext.
3845          */
3846         s = (TransactionState)
3847                 MemoryContextAllocZero(TopTransactionContext,
3848                                                            sizeof(TransactionStateData));
3849         /*
3850          * Assign a subtransaction ID, watching out for counter wraparound.
3851          */
3852         currentSubTransactionId += 1;
3853         if (currentSubTransactionId == InvalidSubTransactionId)
3854         {
3855                 currentSubTransactionId -= 1;
3856                 pfree(s);
3857                 ereport(ERROR,
3858                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
3859                                  errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
3860         }
3861         /*
3862          * We can now stack a minimally valid subtransaction without fear of
3863          * failure.
3864          */
3865         s->transactionId = InvalidTransactionId; /* until assigned */
3866         s->subTransactionId = currentSubTransactionId;
3867         s->parent = p;
3868         s->nestingLevel = p->nestingLevel + 1;
3869         s->savepointLevel = p->savepointLevel;
3870         s->state = TRANS_DEFAULT;
3871         s->blockState = TBLOCK_SUBBEGIN;
3872         s->currentUser = currentUser;
3873         s->prevXactReadOnly = XactReadOnly;
3874
3875         CurrentTransactionState = s;
3876
3877         /*
3878          * AbortSubTransaction and CleanupSubTransaction have to be able to
3879          * cope with the subtransaction from here on out; in particular they
3880          * should not assume that it necessarily has a transaction context,
3881          * resource owner, or XID.
3882          */
3883 }
3884
3885 /*
3886  * PopTransaction
3887  *              Pop back to parent transaction state
3888  *
3889  *      The caller has to make sure to always reassign CurrentTransactionState
3890  *      if it has a local pointer to it after calling this function.
3891  */
3892 static void
3893 PopTransaction(void)
3894 {
3895         TransactionState s = CurrentTransactionState;
3896
3897         if (s->state != TRANS_DEFAULT)
3898                 elog(WARNING, "PopTransaction while in %s state",
3899                          TransStateAsString(s->state));
3900
3901         if (s->parent == NULL)
3902                 elog(FATAL, "PopTransaction with no parent");
3903
3904         CurrentTransactionState = s->parent;
3905
3906         /* Let's just make sure CurTransactionContext is good */
3907         CurTransactionContext = s->parent->curTransactionContext;
3908         MemoryContextSwitchTo(CurTransactionContext);
3909
3910         /* Ditto for ResourceOwner links */
3911         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3912         CurrentResourceOwner = s->parent->curTransactionOwner;
3913
3914         /* Free the old child structure */
3915         if (s->name)
3916                 pfree(s->name);
3917         pfree(s);
3918 }
3919
3920 /*
3921  * ShowTransactionState
3922  *              Debug support
3923  */
3924 static void
3925 ShowTransactionState(const char *str)
3926 {
3927         /* skip work if message will definitely not be printed */
3928         if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
3929         {
3930                 elog(DEBUG3, "%s", str);
3931                 ShowTransactionStateRec(CurrentTransactionState);
3932         }
3933 }
3934
3935 /*
3936  * ShowTransactionStateRec
3937  *              Recursive subroutine for ShowTransactionState
3938  */
3939 static void
3940 ShowTransactionStateRec(TransactionState s)
3941 {
3942         if (s->parent)
3943                 ShowTransactionStateRec(s->parent);
3944
3945         /* use ereport to suppress computation if msg will not be printed */
3946         ereport(DEBUG3,
3947                         (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u, nestlvl: %d, children: %s",
3948                                                    PointerIsValid(s->name) ? s->name : "unnamed",
3949                                                          BlockStateAsString(s->blockState),
3950                                                          TransStateAsString(s->state),
3951                                                          (unsigned int) s->transactionId,
3952                                                          (unsigned int) s->subTransactionId,
3953                                                          (unsigned int) currentCommandId,
3954                                                          s->nestingLevel,
3955                                                          nodeToString(s->childXids))));
3956 }
3957
3958 /*
3959  * BlockStateAsString
3960  *              Debug support
3961  */
3962 static const char *
3963 BlockStateAsString(TBlockState blockState)
3964 {
3965         switch (blockState)
3966         {
3967                 case TBLOCK_DEFAULT:
3968                         return "DEFAULT";
3969                 case TBLOCK_STARTED:
3970                         return "STARTED";
3971                 case TBLOCK_BEGIN:
3972                         return "BEGIN";
3973                 case TBLOCK_INPROGRESS:
3974                         return "INPROGRESS";
3975                 case TBLOCK_END:
3976                         return "END";
3977                 case TBLOCK_ABORT:
3978                         return "ABORT";
3979                 case TBLOCK_ABORT_END:
3980                         return "ABORT END";
3981                 case TBLOCK_ABORT_PENDING:
3982                         return "ABORT PEND";
3983                 case TBLOCK_PREPARE:
3984                         return "PREPARE";
3985                 case TBLOCK_SUBBEGIN:
3986                         return "SUB BEGIN";
3987                 case TBLOCK_SUBINPROGRESS:
3988                         return "SUB INPROGRS";
3989                 case TBLOCK_SUBEND:
3990                         return "SUB END";
3991                 case TBLOCK_SUBABORT:
3992                         return "SUB ABORT";
3993                 case TBLOCK_SUBABORT_END:
3994                         return "SUB ABORT END";
3995                 case TBLOCK_SUBABORT_PENDING:
3996                         return "SUB ABRT PEND";
3997                 case TBLOCK_SUBRESTART:
3998                         return "SUB RESTART";
3999                 case TBLOCK_SUBABORT_RESTART:
4000                         return "SUB AB RESTRT";
4001         }
4002         return "UNRECOGNIZED";
4003 }
4004
4005 /*
4006  * TransStateAsString
4007  *              Debug support
4008  */
4009 static const char *
4010 TransStateAsString(TransState state)
4011 {
4012         switch (state)
4013         {
4014                 case TRANS_DEFAULT:
4015                         return "DEFAULT";
4016                 case TRANS_START:
4017                         return "START";
4018                 case TRANS_INPROGRESS:
4019                         return "INPROGR";
4020                 case TRANS_COMMIT:
4021                         return "COMMIT";
4022                 case TRANS_ABORT:
4023                         return "ABORT";
4024                 case TRANS_PREPARE:
4025                         return "PREPARE";
4026         }
4027         return "UNRECOGNIZED";
4028 }
4029
4030 /*
4031  * xactGetCommittedChildren
4032  *
4033  * Gets the list of committed children of the current transaction.      The return
4034  * value is the number of child transactions.  *children is set to point to a
4035  * palloc'd array of TransactionIds.  If there are no subxacts, *children is
4036  * set to NULL.
4037  */
4038 int
4039 xactGetCommittedChildren(TransactionId **ptr)
4040 {
4041         TransactionState s = CurrentTransactionState;
4042         int                     nchildren;
4043         TransactionId *children;
4044         ListCell   *p;
4045
4046         nchildren = list_length(s->childXids);
4047         if (nchildren == 0)
4048         {
4049                 *ptr = NULL;
4050                 return 0;
4051         }
4052
4053         children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
4054         *ptr = children;
4055
4056         foreach(p, s->childXids)
4057         {
4058                 TransactionId child = lfirst_xid(p);
4059
4060                 *children++ = child;
4061         }
4062
4063         return nchildren;
4064 }
4065
4066 /*
4067  *      XLOG support routines
4068  */
4069
4070 static void
4071 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4072 {
4073         TransactionId *sub_xids;
4074         TransactionId max_xid;
4075         int                     i;
4076
4077         TransactionIdCommit(xid);
4078
4079         /* Mark committed subtransactions as committed */
4080         sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4081         TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4082
4083         /* Make sure nextXid is beyond any XID mentioned in the record */
4084         max_xid = xid;
4085         for (i = 0; i < xlrec->nsubxacts; i++)
4086         {
4087                 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4088                         max_xid = sub_xids[i];
4089         }
4090         if (TransactionIdFollowsOrEquals(max_xid,
4091                                                                          ShmemVariableCache->nextXid))
4092         {
4093                 ShmemVariableCache->nextXid = max_xid;
4094                 TransactionIdAdvance(ShmemVariableCache->nextXid);
4095         }
4096
4097         /* Make sure files supposed to be dropped are dropped */
4098         for (i = 0; i < xlrec->nrels; i++)
4099         {
4100                 XLogCloseRelation(xlrec->xnodes[i]);
4101                 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4102         }
4103 }
4104
4105 static void
4106 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4107 {
4108         TransactionId *sub_xids;
4109         TransactionId max_xid;
4110         int                     i;
4111
4112         TransactionIdAbort(xid);
4113
4114         /* Mark subtransactions as aborted */
4115         sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4116         TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4117
4118         /* Make sure nextXid is beyond any XID mentioned in the record */
4119         max_xid = xid;
4120         for (i = 0; i < xlrec->nsubxacts; i++)
4121         {
4122                 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4123                         max_xid = sub_xids[i];
4124         }
4125         if (TransactionIdFollowsOrEquals(max_xid,
4126                                                                          ShmemVariableCache->nextXid))
4127         {
4128                 ShmemVariableCache->nextXid = max_xid;
4129                 TransactionIdAdvance(ShmemVariableCache->nextXid);
4130         }
4131
4132         /* Make sure files supposed to be dropped are dropped */
4133         for (i = 0; i < xlrec->nrels; i++)
4134         {
4135                 XLogCloseRelation(xlrec->xnodes[i]);
4136                 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
4137         }
4138 }
4139
4140 void
4141 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4142 {
4143         uint8           info = record->xl_info & ~XLR_INFO_MASK;
4144
4145         if (info == XLOG_XACT_COMMIT)
4146         {
4147                 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4148
4149                 xact_redo_commit(xlrec, record->xl_xid);
4150         }
4151         else if (info == XLOG_XACT_ABORT)
4152         {
4153                 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4154
4155                 xact_redo_abort(xlrec, record->xl_xid);
4156         }
4157         else if (info == XLOG_XACT_PREPARE)
4158         {
4159                 /* the record contents are exactly the 2PC file */
4160                 RecreateTwoPhaseFile(record->xl_xid,
4161                                                          XLogRecGetData(record), record->xl_len);
4162         }
4163         else if (info == XLOG_XACT_COMMIT_PREPARED)
4164         {
4165                 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4166
4167                 xact_redo_commit(&xlrec->crec, xlrec->xid);
4168                 RemoveTwoPhaseFile(xlrec->xid, false);
4169         }
4170         else if (info == XLOG_XACT_ABORT_PREPARED)
4171         {
4172                 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4173
4174                 xact_redo_abort(&xlrec->arec, xlrec->xid);
4175                 RemoveTwoPhaseFile(xlrec->xid, false);
4176         }
4177         else
4178                 elog(PANIC, "xact_redo: unknown op code %u", info);
4179 }
4180
4181 static void
4182 xact_desc_commit(char *buf, xl_xact_commit *xlrec)
4183 {
4184         struct tm  *tm = localtime(&xlrec->xtime);
4185         int                     i;
4186
4187         sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4188                         tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4189                         tm->tm_hour, tm->tm_min, tm->tm_sec);
4190         if (xlrec->nrels > 0)
4191         {
4192                 sprintf(buf + strlen(buf), "; rels:");
4193                 for (i = 0; i < xlrec->nrels; i++)
4194                 {
4195                         RelFileNode rnode = xlrec->xnodes[i];
4196
4197                         sprintf(buf + strlen(buf), " %u/%u/%u",
4198                                         rnode.spcNode, rnode.dbNode, rnode.relNode);
4199                 }
4200         }
4201         if (xlrec->nsubxacts > 0)
4202         {
4203                 TransactionId *xacts = (TransactionId *)
4204                         &xlrec->xnodes[xlrec->nrels];
4205
4206                 sprintf(buf + strlen(buf), "; subxacts:");
4207                 for (i = 0; i < xlrec->nsubxacts; i++)
4208                         sprintf(buf + strlen(buf), " %u", xacts[i]);
4209         }
4210 }
4211
4212 static void
4213 xact_desc_abort(char *buf, xl_xact_abort *xlrec)
4214 {
4215         struct tm  *tm = localtime(&xlrec->xtime);
4216         int                     i;
4217
4218         sprintf(buf + strlen(buf), "%04u-%02u-%02u %02u:%02u:%02u",
4219                         tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
4220                         tm->tm_hour, tm->tm_min, tm->tm_sec);
4221         if (xlrec->nrels > 0)
4222         {
4223                 sprintf(buf + strlen(buf), "; rels:");
4224                 for (i = 0; i < xlrec->nrels; i++)
4225                 {
4226                         RelFileNode rnode = xlrec->xnodes[i];
4227
4228                         sprintf(buf + strlen(buf), " %u/%u/%u",
4229                                         rnode.spcNode, rnode.dbNode, rnode.relNode);
4230                 }
4231         }
4232         if (xlrec->nsubxacts > 0)
4233         {
4234                 TransactionId *xacts = (TransactionId *)
4235                         &xlrec->xnodes[xlrec->nrels];
4236
4237                 sprintf(buf + strlen(buf), "; subxacts:");
4238                 for (i = 0; i < xlrec->nsubxacts; i++)
4239                         sprintf(buf + strlen(buf), " %u", xacts[i]);
4240         }
4241 }
4242
4243 void
4244 xact_desc(char *buf, uint8 xl_info, char *rec)
4245 {
4246         uint8           info = xl_info & ~XLR_INFO_MASK;
4247
4248         if (info == XLOG_XACT_COMMIT)
4249         {
4250                 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4251
4252                 strcat(buf, "commit: ");
4253                 xact_desc_commit(buf, xlrec);
4254         }
4255         else if (info == XLOG_XACT_ABORT)
4256         {
4257                 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4258
4259                 strcat(buf, "abort: ");
4260                 xact_desc_abort(buf, xlrec);
4261         }
4262         else if (info == XLOG_XACT_PREPARE)
4263         {
4264                 strcat(buf, "prepare");
4265         }
4266         else if (info == XLOG_XACT_COMMIT_PREPARED)
4267         {
4268                 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4269
4270                 sprintf(buf + strlen(buf), "commit %u: ", xlrec->xid);
4271                 xact_desc_commit(buf, &xlrec->crec);
4272         }
4273         else if (info == XLOG_XACT_ABORT_PREPARED)
4274         {
4275                 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4276
4277                 sprintf(buf + strlen(buf), "abort %u: ", xlrec->xid);
4278                 xact_desc_abort(buf, &xlrec->arec);
4279         }
4280         else
4281                 strcat(buf, "UNKNOWN");
4282 }