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