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