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