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