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