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