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