]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/xact.c
Update the in-code documentation about the transaction system. Move it
[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-2003, 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.176 2004/08/01 20:57:59 tgl Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17
18 #include "postgres.h"
19
20 #include <time.h>
21 #include <unistd.h>
22
23 #include "access/subtrans.h"
24 #include "access/xact.h"
25 #include "catalog/heap.h"
26 #include "catalog/index.h"
27 #include "catalog/namespace.h"
28 #include "commands/async.h"
29 #include "commands/tablecmds.h"
30 #include "commands/trigger.h"
31 #include "commands/user.h"
32 #include "executor/spi.h"
33 #include "libpq/be-fsstubs.h"
34 #include "miscadmin.h"
35 #include "storage/fd.h"
36 #include "storage/proc.h"
37 #include "storage/sinval.h"
38 #include "storage/smgr.h"
39 #include "utils/guc.h"
40 #include "utils/inval.h"
41 #include "utils/memutils.h"
42 #include "utils/portal.h"
43 #include "utils/resowner.h"
44 #include "pgstat.h"
45
46
47 /*
48  *      transaction states - transaction state from server perspective
49  */
50 typedef enum TransState
51 {
52         TRANS_DEFAULT,
53         TRANS_START,
54         TRANS_INPROGRESS,
55         TRANS_COMMIT,
56         TRANS_ABORT
57 } TransState;
58
59 /*
60  *      transaction block states - transaction state of client queries
61  */
62 typedef enum TBlockState
63 {
64         /* not-in-transaction-block states */
65         TBLOCK_DEFAULT,
66         TBLOCK_STARTED,
67
68         /* transaction block states */
69         TBLOCK_BEGIN,
70         TBLOCK_INPROGRESS,
71         TBLOCK_END,
72         TBLOCK_ABORT,
73         TBLOCK_ENDABORT,
74
75         /* subtransaction states */
76         TBLOCK_SUBBEGIN,
77         TBLOCK_SUBINPROGRESS,
78         TBLOCK_SUBEND,
79         TBLOCK_SUBABORT,
80         TBLOCK_SUBABORT_PENDING,
81         TBLOCK_SUBENDABORT_ALL,
82         TBLOCK_SUBENDABORT_RELEASE,
83         TBLOCK_SUBENDABORT
84 } TBlockState;
85
86 /*
87  *      transaction state structure
88  */
89 typedef struct TransactionStateData
90 {
91         TransactionId   transactionIdData;              /* my XID */
92         char               *name;                                       /* savepoint name, if any */
93         int                             savepointLevel;                 /* savepoint level */
94         CommandId               commandId;                              /* current CID */
95         TransState              state;                                  /* low-level state */
96         TBlockState             blockState;                             /* high-level state */
97         int                             nestingLevel;                   /* nest depth */
98         MemoryContext   curTransactionContext;  /* my xact-lifetime context */
99         ResourceOwner   curTransactionOwner;    /* my query resources */
100         List               *childXids;                          /* subcommitted child XIDs */
101         AclId                   currentUser;                    /* subxact start current_user */
102         bool                    prevXactReadOnly;               /* entry-time xact r/o state */
103         struct TransactionStateData *parent;    /* back link to parent */
104 } TransactionStateData;
105
106 typedef TransactionStateData *TransactionState;
107
108 /*
109  * childXids is currently implemented as an integer List, relying on the
110  * assumption that TransactionIds are no wider than int.  We use these
111  * macros to provide some isolation in case that changes in the future.
112  */
113 #define lfirst_xid(lc)                          ((TransactionId) lfirst_int(lc))
114 #define lappend_xid(list, datum)        lappend_int(list, (int) (datum))
115
116
117 static void AbortTransaction(void);
118 static void AtAbort_Memory(void);
119 static void AtCleanup_Memory(void);
120 static void AtCommit_LocalCache(void);
121 static void AtCommit_Memory(void);
122 static void AtStart_Cache(void);
123 static void AtStart_Memory(void);
124 static void AtStart_ResourceOwner(void);
125 static void CallXactCallbacks(XactEvent event, TransactionId parentXid);
126 static void CleanupTransaction(void);
127 static void CommitTransaction(void);
128 static void RecordTransactionAbort(void);
129 static void StartTransaction(void);
130
131 static void RecordSubTransactionCommit(void);
132 static void StartSubTransaction(void);
133 static void CommitSubTransaction(void);
134 static void AbortSubTransaction(void);
135 static void CleanupSubTransaction(void);
136 static void StartAbortedSubTransaction(void);
137 static void PushTransaction(void);
138 static void PopTransaction(void);
139 static void CommitTransactionToLevel(int level);
140 static char *CleanupAbortedSubTransactions(bool returnName);
141
142 static void AtSubAbort_Memory(void);
143 static void AtSubCleanup_Memory(void);
144 static void AtSubCommit_Memory(void);
145 static void AtSubStart_Memory(void);
146 static void AtSubStart_ResourceOwner(void);
147
148 static void ShowTransactionState(const char *str);
149 static void ShowTransactionStateRec(TransactionState state);
150 static const char *BlockStateAsString(TBlockState blockState);
151 static const char *TransStateAsString(TransState state);
152
153 /*
154  * CurrentTransactionState always points to the current transaction state
155  * block.  It will point to TopTransactionStateData when not in a
156  * transaction at all, or when in a top-level transaction.
157  */
158 static TransactionStateData TopTransactionStateData = {
159         0,                                                      /* transaction id */
160         NULL,                                           /* savepoint name */
161         0,                                                      /* savepoint level */
162         FirstCommandId,                         /* command id */
163         TRANS_DEFAULT,                          /* transaction state */
164         TBLOCK_DEFAULT,                         /* transaction block state from the client
165                                                                  * perspective */
166         0,                                                      /* nesting level */
167         NULL,                                           /* cur transaction context */
168         NULL,                                           /* cur transaction resource owner */
169         NIL,                                            /* subcommitted child Xids */
170         0,                                                      /* entry-time current userid */
171         false,                                          /* entry-time xact r/o state */
172         NULL                                            /* link to parent state block */
173 };
174
175 static TransactionState CurrentTransactionState = &TopTransactionStateData;
176
177 /*
178  * These vars hold the value of now(), ie, the transaction start time.
179  * This does not change as we enter and exit subtransactions, so we don't
180  * keep it inside the TransactionState stack.
181  */
182 static AbsoluteTime xactStartTime;                      /* integer part */
183 static int              xactStartTimeUsec;                      /* microsecond part */
184
185
186 /*
187  *      User-tweakable parameters
188  */
189 int                     DefaultXactIsoLevel = XACT_READ_COMMITTED;
190 int                     XactIsoLevel;
191
192 bool            DefaultXactReadOnly = false;
193 bool            XactReadOnly;
194
195 int                     CommitDelay = 0;        /* precommit delay in microseconds */
196 int                     CommitSiblings = 5; /* number of concurrent xacts needed to
197                                                                  * sleep */
198
199
200 /*
201  * List of add-on start- and end-of-xact callbacks
202  */
203 typedef struct XactCallbackItem
204 {
205         struct XactCallbackItem *next;
206         XactCallback callback;
207         void       *arg;
208 } XactCallbackItem;
209
210 static XactCallbackItem *Xact_callbacks = NULL;
211
212 static void (*_RollbackFunc) (void *) = NULL;
213 static void *_RollbackData = NULL;
214
215
216 /* ----------------------------------------------------------------
217  *      transaction state accessors
218  * ----------------------------------------------------------------
219  */
220
221 /*
222  *      IsTransactionState
223  *
224  *      This returns true if we are currently running a query
225  *      within an executing transaction.
226  */
227 bool
228 IsTransactionState(void)
229 {
230         TransactionState s = CurrentTransactionState;
231
232         switch (s->state)
233         {
234                 case TRANS_DEFAULT:
235                         return false;
236                 case TRANS_START:
237                         return true;
238                 case TRANS_INPROGRESS:
239                         return true;
240                 case TRANS_COMMIT:
241                         return true;
242                 case TRANS_ABORT:
243                         return true;
244         }
245
246         /*
247          * Shouldn't get here, but lint is not happy with this...
248          */
249         return false;
250 }
251
252 /*
253  *      IsAbortedTransactionBlockState
254  *
255  *      This returns true if we are currently running a query
256  *      within an aborted transaction block.
257  */
258 bool
259 IsAbortedTransactionBlockState(void)
260 {
261         TransactionState s = CurrentTransactionState;
262
263         if (s->blockState == TBLOCK_ABORT || 
264                 s->blockState == TBLOCK_SUBABORT)
265                 return true;
266
267         return false;
268 }
269
270
271 /*
272  *      GetTopTransactionId
273  *
274  * Get the ID of the main transaction, even if we are currently inside
275  * a subtransaction.
276  */
277 TransactionId
278 GetTopTransactionId(void)
279 {
280         return TopTransactionStateData.transactionIdData;
281 }
282
283
284 /*
285  *      GetCurrentTransactionId
286  */
287 TransactionId
288 GetCurrentTransactionId(void)
289 {
290         TransactionState s = CurrentTransactionState;
291
292         return s->transactionIdData;
293 }
294
295
296 /*
297  *      GetCurrentCommandId
298  */
299 CommandId
300 GetCurrentCommandId(void)
301 {
302         TransactionState s = CurrentTransactionState;
303
304         return s->commandId;
305 }
306
307
308 /*
309  *      GetCurrentTransactionStartTime
310  */
311 AbsoluteTime
312 GetCurrentTransactionStartTime(void)
313 {
314         return xactStartTime;
315 }
316
317
318 /*
319  *      GetCurrentTransactionStartTimeUsec
320  */
321 AbsoluteTime
322 GetCurrentTransactionStartTimeUsec(int *msec)
323 {
324         *msec = xactStartTimeUsec;
325         return xactStartTime;
326 }
327
328
329 /*
330  *      GetCurrentTransactionNestLevel
331  *
332  * Note: this will return zero when not inside any transaction, one when
333  * inside a top-level transaction, etc.
334  */
335 int
336 GetCurrentTransactionNestLevel(void)
337 {
338         TransactionState s = CurrentTransactionState;
339
340         return s->nestingLevel;
341 }
342
343
344 /*
345  *      TransactionIdIsCurrentTransactionId
346  *
347  *      During bootstrap, we cheat and say "it's not my transaction ID" even though
348  *      it is.  Along with transam.c's cheat to say that the bootstrap XID is
349  *      already committed, this causes the tqual.c routines to see previously
350  *      inserted tuples as committed, which is what we need during bootstrap.
351  */
352 bool
353 TransactionIdIsCurrentTransactionId(TransactionId xid)
354 {
355         TransactionState s = CurrentTransactionState;
356
357         if (AMI_OVERRIDE)
358         {
359                 Assert(xid == BootstrapTransactionId);
360                 return false;
361         }
362
363         /*
364          * We will return true for the Xid of the current subtransaction,
365          * any of its subcommitted children, any of its parents, or any of
366          * their previously subcommitted children.
367          */
368         while (s != NULL)
369         {
370                 ListCell *cell;
371
372                 if (TransactionIdEquals(xid, s->transactionIdData))
373                         return true;
374                 foreach(cell, s->childXids)
375                 {
376                         if (TransactionIdEquals(xid, lfirst_xid(cell)))
377                                 return true;
378                 }
379
380                 s = s->parent;
381         }
382
383         return false;
384 }
385
386
387 /*
388  *      CommandCounterIncrement
389  */
390 void
391 CommandCounterIncrement(void)
392 {
393         TransactionState s = CurrentTransactionState;
394
395         s->commandId += 1;
396         if (s->commandId == FirstCommandId) /* check for overflow */
397                 ereport(ERROR,
398                                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
399                                  errmsg("cannot have more than 2^32-1 commands in a transaction")));
400
401         /* Propagate new command ID into query snapshots, if set */
402         if (QuerySnapshot)
403                 QuerySnapshot->curcid = s->commandId;
404         if (SerializableSnapshot)
405                 SerializableSnapshot->curcid = s->commandId;
406
407         /*
408          * make cache changes visible to me.
409          */
410         AtCommit_LocalCache();
411         AtStart_Cache();
412 }
413
414
415 /* ----------------------------------------------------------------
416  *                                              StartTransaction stuff
417  * ----------------------------------------------------------------
418  */
419
420 /*
421  *      AtStart_Cache
422  */
423 static void
424 AtStart_Cache(void)
425 {
426         AcceptInvalidationMessages();
427 }
428
429 /*
430  *      AtStart_Memory
431  */
432 static void
433 AtStart_Memory(void)
434 {
435         TransactionState s = CurrentTransactionState;
436
437         /*
438          * We shouldn't have a transaction context already.
439          */
440         Assert(TopTransactionContext == NULL);
441
442         /*
443          * Create a toplevel context for the transaction.
444          */
445         TopTransactionContext =
446                 AllocSetContextCreate(TopMemoryContext,
447                                                           "TopTransactionContext",
448                                                           ALLOCSET_DEFAULT_MINSIZE,
449                                                           ALLOCSET_DEFAULT_INITSIZE,
450                                                           ALLOCSET_DEFAULT_MAXSIZE);
451
452         /*
453          * In a top-level transaction, CurTransactionContext is the same as
454          * TopTransactionContext.
455          */
456         CurTransactionContext = TopTransactionContext;
457         s->curTransactionContext = CurTransactionContext;
458
459         /* Make the CurTransactionContext active. */
460         MemoryContextSwitchTo(CurTransactionContext);
461 }
462
463 /*
464  *      AtStart_ResourceOwner
465  */
466 static void
467 AtStart_ResourceOwner(void)
468 {
469         TransactionState s = CurrentTransactionState;
470
471         /*
472          * We shouldn't have a transaction resource owner already.
473          */
474         Assert(TopTransactionResourceOwner == NULL);
475
476         /*
477          * Create a toplevel resource owner for the transaction.
478          */
479         s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
480
481         TopTransactionResourceOwner = s->curTransactionOwner;
482         CurTransactionResourceOwner = s->curTransactionOwner;
483         CurrentResourceOwner = s->curTransactionOwner;
484 }
485
486 /* ----------------------------------------------------------------
487  *                                              StartSubTransaction stuff
488  * ----------------------------------------------------------------
489  */
490
491 /*
492  * AtSubStart_Memory
493  */
494 static void
495 AtSubStart_Memory(void)
496 {
497         TransactionState s = CurrentTransactionState;
498
499         Assert(CurTransactionContext != NULL);
500
501         /*
502          * Create a CurTransactionContext, which will be used to hold data that
503          * survives subtransaction commit but disappears on subtransaction abort.
504          * We make it a child of the immediate parent's CurTransactionContext.
505          */
506         CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
507                                                                                                   "CurTransactionContext",
508                                                                                                   ALLOCSET_DEFAULT_MINSIZE,
509                                                                                                   ALLOCSET_DEFAULT_INITSIZE,
510                                                                                                   ALLOCSET_DEFAULT_MAXSIZE);
511         s->curTransactionContext = CurTransactionContext;
512
513         /* Make the CurTransactionContext active. */
514         MemoryContextSwitchTo(CurTransactionContext);
515 }
516
517 /*
518  * AtSubStart_ResourceOwner
519  */
520 static void
521 AtSubStart_ResourceOwner(void)
522 {
523         TransactionState s = CurrentTransactionState;
524
525         Assert(s->parent != NULL);
526
527         /*
528          * Create a resource owner for the subtransaction.  We make it a
529          * child of the immediate parent's resource owner.
530          */
531         s->curTransactionOwner =
532                 ResourceOwnerCreate(s->parent->curTransactionOwner,
533                                                         "SubTransaction");
534
535         CurTransactionResourceOwner = s->curTransactionOwner;
536         CurrentResourceOwner = s->curTransactionOwner;
537 }
538
539 /* ----------------------------------------------------------------
540  *                                              CommitTransaction stuff
541  * ----------------------------------------------------------------
542  */
543
544 /*
545  *      RecordTransactionCommit
546  */
547 void
548 RecordTransactionCommit(void)
549 {
550         int                     nrels;
551         RelFileNode *rptr;
552         int                     nchildren;
553         TransactionId *children;
554
555         /* Get data needed for commit record */
556         nrels = smgrGetPendingDeletes(true, &rptr);
557         nchildren = xactGetCommittedChildren(&children);
558
559         /*
560          * If we made neither any XLOG entries nor any temp-rel updates,
561          * and have no files to be deleted, we can omit recording the transaction
562          * commit at all.  (This test includes the effects of subtransactions,
563          * so the presence of committed subxacts need not alone force a write.)
564          */
565         if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
566         {
567                 TransactionId xid = GetCurrentTransactionId();
568                 bool            madeTCentries;
569                 XLogRecPtr      recptr;
570
571                 /* Tell bufmgr and smgr to prepare for commit */
572                 BufmgrCommit();
573
574                 START_CRIT_SECTION();
575
576                 /*
577                  * We only need to log the commit in XLOG if the transaction made
578                  * any transaction-controlled XLOG entries or will delete files.
579                  * (If it made no transaction-controlled XLOG entries, its XID
580                  * appears nowhere in permanent storage, so no one else will ever care
581                  * if it committed.)
582                  */
583                 madeTCentries = (MyLastRecPtr.xrecoff != 0);
584                 if (madeTCentries || nrels > 0)
585                 {
586                         XLogRecData rdata[3];
587                         int                     lastrdata = 0;
588                         xl_xact_commit xlrec;
589
590                         xlrec.xtime = time(NULL);
591                         xlrec.nrels = nrels;
592                         xlrec.nsubxacts = nchildren;
593                         rdata[0].buffer = InvalidBuffer;
594                         rdata[0].data = (char *) (&xlrec);
595                         rdata[0].len = MinSizeOfXactCommit;
596                         /* dump rels to delete */
597                         if (nrels > 0)
598                         {
599                                 rdata[0].next = &(rdata[1]);
600                                 rdata[1].buffer = InvalidBuffer;
601                                 rdata[1].data = (char *) rptr;
602                                 rdata[1].len = nrels * sizeof(RelFileNode);
603                                 lastrdata = 1;
604                         }
605                         /* dump committed child Xids */
606                         if (nchildren > 0)
607                         {
608                                 rdata[lastrdata].next = &(rdata[2]);
609                                 rdata[2].buffer = InvalidBuffer;
610                                 rdata[2].data = (char *) children;
611                                 rdata[2].len = nchildren * sizeof(TransactionId);
612                                 lastrdata = 2;
613                         }
614                         rdata[lastrdata].next = NULL;
615
616                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
617                 }
618                 else
619                 {
620                         /* Just flush through last record written by me */
621                         recptr = ProcLastRecEnd;
622                 }
623
624                 /*
625                  * We must flush our XLOG entries to disk if we made any XLOG
626                  * entries, whether in or out of transaction control.  For
627                  * example, if we reported a nextval() result to the client, this
628                  * ensures that any XLOG record generated by nextval will hit the
629                  * disk before we report the transaction committed.
630                  *
631                  * Note: if we generated a commit record above, MyXactMadeXLogEntry
632                  * will certainly be set now.
633                  */
634                 if (MyXactMadeXLogEntry)
635                 {
636                         /*
637                          * Sleep before flush! So we can flush more than one commit
638                          * records per single fsync.  (The idea is some other backend
639                          * may do the XLogFlush while we're sleeping.  This needs work
640                          * still, because on most Unixen, the minimum select() delay
641                          * is 10msec or more, which is way too long.)
642                          *
643                          * We do not sleep if enableFsync is not turned on, nor if there
644                          * are fewer than CommitSiblings other backends with active
645                          * transactions.
646                          */
647                         if (CommitDelay > 0 && enableFsync &&
648                                 CountActiveBackends() >= CommitSiblings)
649                                 pg_usleep(CommitDelay);
650
651                         XLogFlush(recptr);
652                 }
653
654                 /*
655                  * We must mark the transaction committed in clog if its XID
656                  * appears either in permanent rels or in local temporary rels. We
657                  * test this by seeing if we made transaction-controlled entries
658                  * *OR* local-rel tuple updates.  Note that if we made only the
659                  * latter, we have not emitted an XLOG record for our commit, and
660                  * so in the event of a crash the clog update might be lost.  This
661                  * is okay because no one else will ever care whether we
662                  * committed.
663                  */
664                 if (madeTCentries || MyXactMadeTempRelUpdate)
665                 {
666                         TransactionIdCommit(xid);
667                         /* to avoid race conditions, the parent must commit first */
668                         TransactionIdCommitTree(nchildren, children);
669                 }
670
671                 END_CRIT_SECTION();
672         }
673
674         /* Break the chain of back-links in the XLOG records I output */
675         MyLastRecPtr.xrecoff = 0;
676         MyXactMadeXLogEntry = false;
677         MyXactMadeTempRelUpdate = false;
678
679         /* Show myself as out of the transaction in PGPROC array */
680         MyProc->logRec.xrecoff = 0;
681
682         /* And clean up local data */
683         if (rptr)
684                 pfree(rptr);
685         if (children)
686                 pfree(children);
687 }
688
689
690 /*
691  *      AtCommit_LocalCache
692  */
693 static void
694 AtCommit_LocalCache(void)
695 {
696         /*
697          * Make catalog changes visible to me for the next command.
698          */
699         CommandEndInvalidationMessages();
700 }
701
702 /*
703  *      AtCommit_Memory
704  */
705 static void
706 AtCommit_Memory(void)
707 {
708         /*
709          * Now that we're "out" of a transaction, have the system allocate
710          * things in the top memory context instead of per-transaction
711          * contexts.
712          */
713         MemoryContextSwitchTo(TopMemoryContext);
714
715         /*
716          * Release all transaction-local memory.
717          */
718         Assert(TopTransactionContext != NULL);
719         MemoryContextDelete(TopTransactionContext);
720         TopTransactionContext = NULL;
721         CurTransactionContext = NULL;
722         CurrentTransactionState->curTransactionContext = NULL;
723 }
724
725 /* ----------------------------------------------------------------
726  *                                              CommitSubTransaction stuff
727  * ----------------------------------------------------------------
728  */
729
730 /*
731  * AtSubCommit_Memory
732  *
733  * We do not throw away the child's CurTransactionContext, since the data
734  * it contains will be needed at upper commit.
735  */
736 static void
737 AtSubCommit_Memory(void)
738 {
739         TransactionState s = CurrentTransactionState;
740
741         Assert(s->parent != NULL);
742
743         /* Return to parent transaction level's memory context. */
744         CurTransactionContext = s->parent->curTransactionContext;
745         MemoryContextSwitchTo(CurTransactionContext);
746 }
747
748 /*
749  * AtSubCommit_childXids
750  *
751  * Pass my own XID and my child XIDs up to my parent as committed children.
752  */
753 static void
754 AtSubCommit_childXids(void)
755 {
756         TransactionState s = CurrentTransactionState;
757         MemoryContext old_cxt;
758
759         Assert(s->parent != NULL);
760
761         old_cxt = MemoryContextSwitchTo(s->parent->curTransactionContext);
762
763         s->parent->childXids = lappend_xid(s->parent->childXids,
764                                                                            s->transactionIdData);
765
766         s->parent->childXids = list_concat(s->parent->childXids, s->childXids);
767         s->childXids = NIL;                     /* ensure list not doubly referenced */
768
769         MemoryContextSwitchTo(old_cxt);
770 }
771
772 /*
773  * RecordSubTransactionCommit
774  */
775 static void
776 RecordSubTransactionCommit(void)
777 {
778         /*
779          * We do not log the subcommit in XLOG; it doesn't matter until
780          * the top-level transaction commits.
781          *
782          * We must mark the subtransaction subcommitted in clog if its XID
783          * appears either in permanent rels or in local temporary rels. We
784          * test this by seeing if we made transaction-controlled entries
785          * *OR* local-rel tuple updates.  (The test here actually covers the
786          * entire transaction tree so far, so it may mark subtransactions that
787          * don't really need it, but it's probably not worth being tenser.
788          * Note that if a prior subtransaction dirtied these variables, then
789          * RecordTransactionCommit will have to do the full pushup anyway...)
790          */
791         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
792         {
793                 TransactionId   xid = GetCurrentTransactionId();
794
795                 /* XXX does this really need to be a critical section? */
796                 START_CRIT_SECTION();
797
798                 /* Record subtransaction subcommit */
799                 TransactionIdSubCommit(xid);
800
801                 END_CRIT_SECTION();
802         }
803 }
804
805 /* ----------------------------------------------------------------
806  *                                              AbortTransaction stuff
807  * ----------------------------------------------------------------
808  */
809
810 /*
811  *      RecordTransactionAbort
812  */
813 static void
814 RecordTransactionAbort(void)
815 {
816         int                     nrels;
817         RelFileNode *rptr;
818         int                     nchildren;
819         TransactionId  *children;
820
821         /* Get data needed for abort record */
822         nrels = smgrGetPendingDeletes(false, &rptr);
823         nchildren = xactGetCommittedChildren(&children);
824
825         /*
826          * If we made neither any transaction-controlled XLOG entries nor any
827          * temp-rel updates, and are not going to delete any files, we can omit
828          * recording the transaction abort at all.  No one will ever care that
829          * it aborted.  (These tests cover our whole transaction tree.)
830          */
831         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
832         {
833                 TransactionId   xid = GetCurrentTransactionId();
834
835                 /*
836                  * Catch the scenario where we aborted partway through
837                  * RecordTransactionCommit ...
838                  */
839                 if (TransactionIdDidCommit(xid))
840                         elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
841
842                 START_CRIT_SECTION();
843
844                 /*
845                  * We only need to log the abort in XLOG if the transaction made
846                  * any transaction-controlled XLOG entries or will delete files.
847                  * (If it made no transaction-controlled XLOG entries, its XID
848                  * appears nowhere in permanent storage, so no one else will ever care
849                  * if it committed.)
850                  *
851                  * We do not flush XLOG to disk unless deleting files, since the
852                  * default assumption after a crash would be that we aborted, anyway.
853                  */
854                 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
855                 {
856                         XLogRecData rdata[3];
857                         int                     lastrdata = 0;
858                         xl_xact_abort xlrec;
859                         XLogRecPtr      recptr;
860
861                         xlrec.xtime = time(NULL);
862                         xlrec.nrels = nrels;
863                         xlrec.nsubxacts = nchildren;
864                         rdata[0].buffer = InvalidBuffer;
865                         rdata[0].data = (char *) (&xlrec);
866                         rdata[0].len = MinSizeOfXactAbort;
867                         /* dump rels to delete */
868                         if (nrels > 0)
869                         {
870                                 rdata[0].next = &(rdata[1]);
871                                 rdata[1].buffer = InvalidBuffer;
872                                 rdata[1].data = (char *) rptr;
873                                 rdata[1].len = nrels * sizeof(RelFileNode);
874                                 lastrdata = 1;
875                         }
876                         /* dump committed child Xids */
877                         if (nchildren > 0)
878                         {
879                                 rdata[lastrdata].next = &(rdata[2]);
880                                 rdata[2].buffer = InvalidBuffer;
881                                 rdata[2].data = (char *) children;
882                                 rdata[2].len = nchildren * sizeof(TransactionId);
883                                 lastrdata = 2;
884                         }
885                         rdata[lastrdata].next = NULL;
886
887                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
888
889                         /* Must flush if we are deleting files... */
890                         if (nrels > 0)
891                                 XLogFlush(recptr);
892                 }
893
894                 /*
895                  * Mark the transaction aborted in clog.  This is not absolutely
896                  * necessary but we may as well do it while we are here.
897                  *
898                  * The ordering here isn't critical but it seems best to mark the
899                  * parent last.  That reduces the chance that concurrent
900                  * TransactionIdDidAbort calls will decide they need to do redundant
901                  * work.
902                  */
903                 TransactionIdAbortTree(nchildren, children);
904                 TransactionIdAbort(xid);
905
906                 END_CRIT_SECTION();
907         }
908
909         /* Break the chain of back-links in the XLOG records I output */
910         MyLastRecPtr.xrecoff = 0;
911         MyXactMadeXLogEntry = false;
912         MyXactMadeTempRelUpdate = false;
913
914         /* Show myself as out of the transaction in PGPROC array */
915         MyProc->logRec.xrecoff = 0;
916
917         /* And clean up local data */
918         if (rptr)
919                 pfree(rptr);
920         if (children)
921                 pfree(children);
922 }
923
924 /*
925  *      AtAbort_Memory
926  */
927 static void
928 AtAbort_Memory(void)
929 {
930         /*
931          * Make sure we are in a valid context (not a child of
932          * TopTransactionContext...).  Note that it is possible for this code
933          * to be called when we aren't in a transaction at all; go directly to
934          * TopMemoryContext in that case.
935          */
936         if (TopTransactionContext != NULL)
937         {
938                 MemoryContextSwitchTo(TopTransactionContext);
939
940                 /*
941                  * We do not want to destroy the transaction's global state yet,
942                  * so we can't free any memory here.
943                  */
944         }
945         else
946                 MemoryContextSwitchTo(TopMemoryContext);
947 }
948
949
950 /*
951  * AtSubAbort_Memory
952  */
953 static void
954 AtSubAbort_Memory(void)
955 {
956         Assert(TopTransactionContext != NULL);
957
958         MemoryContextSwitchTo(TopTransactionContext);
959 }
960
961 /*
962  * RecordSubTransactionAbort
963  */
964 static void
965 RecordSubTransactionAbort(void)
966 {
967         int                     nrels;
968         RelFileNode *rptr;
969         TransactionId   xid = GetCurrentTransactionId();
970         int                     nchildren;
971         TransactionId  *children;
972
973         /* Get data needed for abort record */
974         nrels = smgrGetPendingDeletes(false, &rptr);
975         nchildren = xactGetCommittedChildren(&children);
976
977         /*
978          * If we made neither any transaction-controlled XLOG entries nor any
979          * temp-rel updates, and are not going to delete any files, we can omit
980          * recording the transaction abort at all.  No one will ever care that
981          * it aborted.  (These tests cover our whole transaction tree, and
982          * therefore may mark subxacts that don't really need it, but it's
983          * probably not worth being tenser.)
984          *
985          * In this case we needn't worry about marking subcommitted children as
986          * aborted, because they didn't mark themselves as subcommitted in the
987          * first place; see the optimization in RecordSubTransactionCommit.
988          */
989         if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
990         {
991                 START_CRIT_SECTION();
992
993                 /*
994                  * We only need to log the abort in XLOG if the transaction made
995                  * any transaction-controlled XLOG entries or will delete files.
996                  */
997                 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
998                 {
999                         XLogRecData rdata[3];
1000                         int lastrdata = 0;
1001                         xl_xact_abort xlrec;
1002                         XLogRecPtr      recptr;
1003
1004                         xlrec.xtime = time(NULL);
1005                         xlrec.nrels = nrels;
1006                         xlrec.nsubxacts = nchildren;
1007                         rdata[0].buffer = InvalidBuffer;
1008                         rdata[0].data = (char *) (&xlrec);
1009                         rdata[0].len = MinSizeOfXactAbort;
1010                         /* dump rels to delete */
1011                         if (nrels > 0)
1012                         {
1013                                 rdata[0].next = &(rdata[1]);
1014                                 rdata[1].buffer = InvalidBuffer;
1015                                 rdata[1].data = (char *) rptr;
1016                                 rdata[1].len = nrels * sizeof(RelFileNode);
1017                                 lastrdata = 1;
1018                         }
1019                         /* dump committed child Xids */
1020                         if (nchildren > 0)
1021                         {
1022                                 rdata[lastrdata].next = &(rdata[2]);
1023                                 rdata[2].buffer = InvalidBuffer;
1024                                 rdata[2].data = (char *) children;
1025                                 rdata[2].len = nchildren * sizeof(TransactionId);
1026                                 lastrdata = 2;
1027                         }
1028                         rdata[lastrdata].next = NULL;
1029
1030                         recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1031
1032                         /* Must flush if we are deleting files... */
1033                         if (nrels > 0)
1034                                 XLogFlush(recptr);
1035                 }
1036
1037                 /*
1038                  * Mark the transaction aborted in clog.  This is not absolutely
1039                  * necessary but we may as well do it while we are here.
1040                  */
1041                 TransactionIdAbortTree(nchildren, children);
1042                 TransactionIdAbort(xid);
1043
1044                 END_CRIT_SECTION();
1045         }
1046
1047         /*
1048          * We can immediately remove failed XIDs from PGPROC's cache of
1049          * running child XIDs. It's easiest to do it here while we have the
1050          * child XID array at hand, even though in the main-transaction
1051          * case the equivalent work happens just after return from
1052          * RecordTransactionAbort.
1053          */
1054         XidCacheRemoveRunningXids(xid, nchildren, children);
1055
1056         /* And clean up local data */
1057         if (rptr)
1058                 pfree(rptr);
1059         if (children)
1060                 pfree(children);
1061 }
1062
1063 /* ----------------------------------------------------------------
1064  *                                              CleanupTransaction stuff
1065  * ----------------------------------------------------------------
1066  */
1067
1068 /*
1069  *      AtCleanup_Memory
1070  */
1071 static void
1072 AtCleanup_Memory(void)
1073 {
1074         /*
1075          * Now that we're "out" of a transaction, have the system allocate
1076          * things in the top memory context instead of per-transaction
1077          * contexts.
1078          */
1079         MemoryContextSwitchTo(TopMemoryContext);
1080
1081         Assert(CurrentTransactionState->parent == NULL);
1082
1083         /*
1084          * Release all transaction-local memory.
1085          */
1086         if (TopTransactionContext != NULL)
1087                 MemoryContextDelete(TopTransactionContext);
1088         TopTransactionContext = NULL;
1089         CurTransactionContext = NULL;
1090         CurrentTransactionState->curTransactionContext = NULL;
1091 }
1092
1093
1094 /* ----------------------------------------------------------------
1095  *                                              CleanupSubTransaction stuff
1096  * ----------------------------------------------------------------
1097  */
1098
1099 /*
1100  * AtSubCleanup_Memory
1101  */
1102 static void
1103 AtSubCleanup_Memory(void)
1104 {
1105         TransactionState s = CurrentTransactionState;
1106
1107         Assert(s->parent != NULL);
1108
1109         /* Make sure we're not in an about-to-be-deleted context */
1110         MemoryContextSwitchTo(s->parent->curTransactionContext);
1111         CurTransactionContext = s->parent->curTransactionContext;
1112
1113         /*
1114          * Delete the subxact local memory contexts. Its CurTransactionContext
1115          * can go too (note this also kills CurTransactionContexts from any
1116          * children of the subxact).
1117          */
1118         MemoryContextDelete(s->curTransactionContext);
1119 }
1120
1121 /* ----------------------------------------------------------------
1122  *                                              interface routines
1123  * ----------------------------------------------------------------
1124  */
1125
1126 /*
1127  *      StartTransaction
1128  */
1129 static void
1130 StartTransaction(void)
1131 {
1132         TransactionState s = CurrentTransactionState;
1133
1134         /*
1135          * check the current transaction state
1136          */
1137         if (s->state != TRANS_DEFAULT)
1138                 elog(WARNING, "StartTransaction while in %s state",
1139                          TransStateAsString(s->state));
1140
1141         /*
1142          * set the current transaction state information appropriately during
1143          * start processing
1144          */
1145         s->state = TRANS_START;
1146
1147         /*
1148          * Make sure we've freed any old snapshot, and reset xact state variables
1149          */
1150         FreeXactSnapshot();
1151         XactIsoLevel = DefaultXactIsoLevel;
1152         XactReadOnly = DefaultXactReadOnly;
1153
1154         /*
1155          * must initialize resource-management stuff first
1156          */
1157         AtStart_Memory();
1158         AtStart_ResourceOwner();
1159
1160         /*
1161          * generate a new transaction id
1162          */
1163         s->transactionIdData = GetNewTransactionId(false);
1164
1165         XactLockTableInsert(s->transactionIdData);
1166
1167         /*
1168          * set now()
1169          */
1170         xactStartTime = GetCurrentAbsoluteTimeUsec(&(xactStartTimeUsec));
1171
1172         /*
1173          * initialize current transaction state fields
1174          */
1175         s->commandId = FirstCommandId;
1176         s->nestingLevel = 1;
1177         s->childXids = NIL;
1178
1179         /*
1180          * You might expect to see "s->currentUser = GetUserId();" here, but
1181          * you won't because it doesn't work during startup; the userid isn't
1182          * set yet during a backend's first transaction start.  We only use
1183          * the currentUser field in sub-transaction state structs.
1184          *
1185          * prevXactReadOnly is also valid only in sub-transactions.
1186          */
1187
1188         /*
1189          * initialize other subsystems for new transaction
1190          */
1191         AtStart_Inval();
1192         AtStart_Cache();
1193         DeferredTriggerBeginXact();
1194
1195         /*
1196          * done with start processing, set current transaction state to "in
1197          * progress"
1198          */
1199         s->state = TRANS_INPROGRESS;
1200
1201         ShowTransactionState("StartTransaction");
1202 }
1203
1204 /*
1205  *      CommitTransaction
1206  */
1207 static void
1208 CommitTransaction(void)
1209 {
1210         TransactionState s = CurrentTransactionState;
1211
1212         ShowTransactionState("CommitTransaction");
1213
1214         /*
1215          * check the current transaction state
1216          */
1217         if (s->state != TRANS_INPROGRESS)
1218                 elog(WARNING, "CommitTransaction while in %s state",
1219                          TransStateAsString(s->state));
1220         Assert(s->parent == NULL);
1221
1222         /*
1223          * Tell the trigger manager that this transaction is about to be
1224          * committed. He'll invoke all trigger deferred until XACT before we
1225          * really start on committing the transaction.
1226          */
1227         DeferredTriggerEndXact();
1228
1229         /*
1230          * Similarly, let ON COMMIT management do its thing before we start to
1231          * commit.
1232          */
1233         PreCommit_on_commit_actions();
1234
1235         /* Prevent cancel/die interrupt while cleaning up */
1236         HOLD_INTERRUPTS();
1237
1238         /*
1239          * set the current transaction state information appropriately during
1240          * the abort processing
1241          */
1242         s->state = TRANS_COMMIT;
1243
1244         /*
1245          * Do pre-commit processing (most of this stuff requires database
1246          * access, and in fact could still cause an error...)
1247          */
1248
1249         AtCommit_Portals();
1250
1251         /* close large objects before lower-level cleanup */
1252         AtEOXact_LargeObject(true);
1253
1254         /* NOTIFY commit must come before lower-level cleanup */
1255         AtCommit_Notify();
1256
1257         /* Update the flat password file if we changed pg_shadow or pg_group */
1258         /* This should be the last step before commit */
1259         AtEOXact_UpdatePasswordFile(true);
1260
1261         /*
1262          * Here is where we really truly commit.
1263          */
1264         RecordTransactionCommit();
1265
1266         /*
1267          * Let others know about no transaction in progress by me. Note that
1268          * this must be done _before_ releasing locks we hold and _after_
1269          * RecordTransactionCommit.
1270          *
1271          * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by
1272          * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if
1273          * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0
1274          * as running as well or it will see two tuple versions - one deleted
1275          * by xid 1 and one inserted by xid 0.  See notes in GetSnapshotData.
1276          */
1277         if (MyProc != NULL)
1278         {
1279                 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1280                 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1281                 MyProc->xid = InvalidTransactionId;
1282                 MyProc->xmin = InvalidTransactionId;
1283
1284                 /* Clear the subtransaction-XID cache too while holding the lock */
1285                 MyProc->subxids.nxids = 0;
1286                 MyProc->subxids.overflowed = false;
1287
1288                 LWLockRelease(SInvalLock);
1289         }
1290
1291         /*
1292          * This is all post-commit cleanup.  Note that if an error is raised
1293          * here, it's too late to abort the transaction.  This should be just
1294          * noncritical resource releasing.
1295          *
1296          * The ordering of operations is not entirely random.  The idea is:
1297          * release resources visible to other backends (eg, files, buffer
1298          * pins); then release locks; then release backend-local resources. We
1299          * want to release locks at the point where any backend waiting for us
1300          * will see our transaction as being fully cleaned up.
1301          *
1302          * Resources that can be associated with individual queries are
1303          * handled by the ResourceOwner mechanism.  The other calls here
1304          * are for backend-wide state.
1305          */
1306
1307         smgrDoPendingDeletes(true);
1308         /* smgrcommit already done */
1309
1310         CallXactCallbacks(XACT_EVENT_COMMIT, InvalidTransactionId);
1311
1312         ResourceOwnerRelease(TopTransactionResourceOwner,
1313                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
1314                                                  true, true);
1315
1316         /*
1317          * Make catalog changes visible to all backends.  This has to happen
1318          * after relcache references are dropped (see comments for
1319          * AtEOXact_RelationCache), but before locks are released (if anyone
1320          * is waiting for lock on a relation we've modified, we want them to
1321          * know about the catalog change before they start using the relation).
1322          */
1323         AtEOXact_Inval(true);
1324
1325         ResourceOwnerRelease(TopTransactionResourceOwner,
1326                                                  RESOURCE_RELEASE_LOCKS,
1327                                                  true, true);
1328         ResourceOwnerRelease(TopTransactionResourceOwner,
1329                                                  RESOURCE_RELEASE_AFTER_LOCKS,
1330                                                  true, true);
1331
1332         AtEOXact_GUC(true, false);
1333         AtEOXact_SPI(true);
1334         AtEOXact_on_commit_actions(true, s->transactionIdData);
1335         AtEOXact_Namespace(true);
1336         AtEOXact_Files();
1337         pgstat_count_xact_commit();
1338
1339         CurrentResourceOwner = NULL;
1340         ResourceOwnerDelete(TopTransactionResourceOwner);
1341         s->curTransactionOwner = NULL;
1342         CurTransactionResourceOwner = NULL;
1343         TopTransactionResourceOwner = NULL;
1344
1345         AtCommit_Memory();
1346
1347         s->nestingLevel = 0;
1348         s->childXids = NIL;
1349
1350         /*
1351          * done with commit processing, set current transaction state back to
1352          * default
1353          */
1354         s->state = TRANS_DEFAULT;
1355
1356         RESUME_INTERRUPTS();
1357 }
1358
1359 /*
1360  *      AbortTransaction
1361  */
1362 static void
1363 AbortTransaction(void)
1364 {
1365         TransactionState s = CurrentTransactionState;
1366
1367         /* Prevent cancel/die interrupt while cleaning up */
1368         HOLD_INTERRUPTS();
1369
1370         /*
1371          * Release any LW locks we might be holding as quickly as possible.
1372          * (Regular locks, however, must be held till we finish aborting.)
1373          * Releasing LW locks is critical since we might try to grab them
1374          * again while cleaning up!
1375          */
1376         LWLockReleaseAll();
1377
1378         /* Clean up buffer I/O and buffer context locks, too */
1379         AbortBufferIO();
1380         UnlockBuffers();
1381
1382         /*
1383          * Also clean up any open wait for lock, since the lock manager will
1384          * choke if we try to wait for another lock before doing this.
1385          */
1386         LockWaitCancel();
1387
1388         /*
1389          * check the current transaction state
1390          */
1391         if (s->state != TRANS_INPROGRESS)
1392                 elog(WARNING, "AbortTransaction while in %s state",
1393                          TransStateAsString(s->state));
1394         Assert(s->parent == NULL);
1395
1396         /*
1397          * set the current transaction state information appropriately during
1398          * the abort processing
1399          */
1400         s->state = TRANS_ABORT;
1401
1402         /* Make sure we are in a valid memory context */
1403         AtAbort_Memory();
1404
1405         /*
1406          * Reset user id which might have been changed transiently.  We cannot
1407          * use s->currentUser, but must get the session userid from miscinit.c.
1408          *
1409          * (Note: it is not necessary to restore session authorization here
1410          * because that can only be changed via GUC, and GUC will take care of
1411          * rolling it back if need be.  However, an error within a SECURITY
1412          * DEFINER function could send control here with the wrong current
1413          * userid.)
1414          */
1415         SetUserId(GetSessionUserId());
1416
1417         /*
1418          * do abort processing
1419          */
1420         DeferredTriggerAbortXact();
1421         AtAbort_Portals();
1422         AtEOXact_LargeObject(false);                    /* 'false' means it's abort */
1423         AtAbort_Notify();
1424         AtEOXact_UpdatePasswordFile(false);
1425
1426         /* Advertise the fact that we aborted in pg_clog. */
1427         RecordTransactionAbort();
1428
1429         /*
1430          * Let others know about no transaction in progress by me. Note that
1431          * this must be done _before_ releasing locks we hold and _after_
1432          * RecordTransactionAbort.
1433          */
1434         if (MyProc != NULL)
1435         {
1436                 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1437                 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1438                 MyProc->xid = InvalidTransactionId;
1439                 MyProc->xmin = InvalidTransactionId;
1440
1441                 /* Clear the subtransaction-XID cache too while holding the lock */
1442                 MyProc->subxids.nxids = 0;
1443                 MyProc->subxids.overflowed = false;
1444
1445                 LWLockRelease(SInvalLock);
1446         }
1447
1448         /*
1449          * Post-abort cleanup.  See notes in CommitTransaction() concerning
1450          * ordering.
1451          */
1452
1453         smgrDoPendingDeletes(false);
1454         smgrabort();
1455
1456         CallXactCallbacks(XACT_EVENT_ABORT, InvalidTransactionId);
1457
1458         ResourceOwnerRelease(TopTransactionResourceOwner,
1459                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
1460                                                  false, true);
1461         AtEOXact_Inval(false);
1462         ResourceOwnerRelease(TopTransactionResourceOwner,
1463                                                  RESOURCE_RELEASE_LOCKS,
1464                                                  false, true);
1465         ResourceOwnerRelease(TopTransactionResourceOwner,
1466                                                  RESOURCE_RELEASE_AFTER_LOCKS,
1467                                                  false, true);
1468
1469         AtEOXact_GUC(false, false);
1470         AtEOXact_SPI(false);
1471         AtEOXact_on_commit_actions(false, s->transactionIdData);
1472         AtEOXact_Namespace(false);
1473         AtEOXact_Files();
1474         pgstat_count_xact_rollback();
1475
1476         /*
1477          * State remains TRANS_ABORT until CleanupTransaction().
1478          */
1479         RESUME_INTERRUPTS();
1480 }
1481
1482 /*
1483  *      CleanupTransaction
1484  */
1485 static void
1486 CleanupTransaction(void)
1487 {
1488         TransactionState s = CurrentTransactionState;
1489
1490         /*
1491          * State should still be TRANS_ABORT from AbortTransaction().
1492          */
1493         if (s->state != TRANS_ABORT)
1494                 elog(FATAL, "CleanupTransaction: unexpected state %s",
1495                          TransStateAsString(s->state));
1496
1497         /*
1498          * do abort cleanup processing
1499          */
1500         AtCleanup_Portals();            /* now safe to release portal memory */
1501
1502         CurrentResourceOwner = NULL; /* and resource owner */
1503         ResourceOwnerDelete(TopTransactionResourceOwner);
1504         s->curTransactionOwner = NULL;
1505         CurTransactionResourceOwner = NULL;
1506         TopTransactionResourceOwner = NULL;
1507
1508         AtCleanup_Memory();                     /* and transaction memory */
1509
1510         s->nestingLevel = 0;
1511         s->childXids = NIL;
1512
1513         /*
1514          * done with abort processing, set current transaction state back to
1515          * default
1516          */
1517         s->state = TRANS_DEFAULT;
1518 }
1519
1520 /*
1521  *      StartTransactionCommand
1522  */
1523 void
1524 StartTransactionCommand(void)
1525 {
1526         TransactionState s = CurrentTransactionState;
1527
1528         switch (s->blockState)
1529         {
1530                         /*
1531                          * if we aren't in a transaction block, we just do our usual
1532                          * start transaction.
1533                          */
1534                 case TBLOCK_DEFAULT:
1535                         StartTransaction();
1536                         s->blockState = TBLOCK_STARTED;
1537                         break;
1538
1539                         /*
1540                          * This is the case when we are somewhere in a transaction block
1541                          * and about to start a new command.  For now we do nothing
1542                          * but someday we may do command-local resource initialization.
1543                          */
1544                 case TBLOCK_INPROGRESS:
1545                 case TBLOCK_SUBINPROGRESS:
1546                         break;
1547
1548                         /*
1549                          * Here we are in the middle of a transaction block but one of
1550                          * the commands caused an abort so we do nothing but remain in
1551                          * the abort state.  Eventually we will get to the "END
1552                          * TRANSACTION" which will set things straight.
1553                          */
1554                 case TBLOCK_ABORT:
1555                 case TBLOCK_SUBABORT:
1556                         break;
1557
1558                         /* These cases are invalid. */
1559                 case TBLOCK_STARTED:
1560                 case TBLOCK_BEGIN:
1561                 case TBLOCK_SUBBEGIN:
1562                 case TBLOCK_END:
1563                 case TBLOCK_SUBEND:
1564                 case TBLOCK_SUBENDABORT_ALL:
1565                 case TBLOCK_SUBENDABORT:
1566                 case TBLOCK_SUBABORT_PENDING:
1567                 case TBLOCK_SUBENDABORT_RELEASE:
1568                 case TBLOCK_ENDABORT:
1569                         elog(FATAL, "StartTransactionCommand: unexpected state %s",
1570                                  BlockStateAsString(s->blockState));
1571                         break;
1572         }
1573
1574         /*
1575          * We must switch to CurTransactionContext before returning. This is
1576          * already done if we called StartTransaction, otherwise not.
1577          */
1578         Assert(CurTransactionContext != NULL);
1579         MemoryContextSwitchTo(CurTransactionContext);
1580 }
1581
1582 /*
1583  *      CommitTransactionCommand
1584  */
1585 void
1586 CommitTransactionCommand(void)
1587 {
1588         TransactionState s = CurrentTransactionState;
1589
1590         switch (s->blockState)
1591         {
1592                         /*
1593                          * This shouldn't happen, because it means the previous
1594                          * StartTransactionCommand didn't set the STARTED state
1595                          * appropriately, or we didn't manage previous pending
1596                          * abort states.
1597                          */
1598                 case TBLOCK_DEFAULT:
1599                 case TBLOCK_SUBABORT_PENDING:
1600                         elog(FATAL, "CommitTransactionCommand: unexpected state %s",
1601                                  BlockStateAsString(s->blockState));
1602                         break;
1603
1604                         /*
1605                          * If we aren't in a transaction block, just do our usual
1606                          * transaction commit.
1607                          */
1608                 case TBLOCK_STARTED:
1609                         CommitTransaction();
1610                         s->blockState = TBLOCK_DEFAULT;
1611                         break;
1612
1613                         /*
1614                          * This is the case right after we get a "BEGIN TRANSACTION"
1615                          * command, but the user hasn't done anything else yet, so we
1616                          * change to the "transaction block in progress" state and
1617                          * return.
1618                          */
1619                 case TBLOCK_BEGIN:
1620                         s->blockState = TBLOCK_INPROGRESS;
1621                         break;
1622
1623                         /*
1624                          * This is the case when we have finished executing a command
1625                          * someplace within a transaction block.  We increment the
1626                          * command counter and return.
1627                          */
1628                 case TBLOCK_INPROGRESS:
1629                         CommandCounterIncrement();
1630                         break;
1631
1632                         /*
1633                          * This is the case when we just got the "END TRANSACTION"
1634                          * statement, so we commit the transaction and go back to the
1635                          * default state.
1636                          */
1637                 case TBLOCK_END:
1638                         /* commit all open subtransactions */
1639                         if (s->nestingLevel > 1)
1640                                 CommitTransactionToLevel(2);
1641                         s = CurrentTransactionState;
1642                         Assert(s->parent == NULL);
1643                         /* and now the outer transaction */
1644                         CommitTransaction();
1645                         s->blockState = TBLOCK_DEFAULT;
1646                         break;
1647
1648                         /*
1649                          * Here we are in the middle of a transaction block but one of
1650                          * the commands caused an abort so we do nothing but remain in
1651                          * the abort state.  Eventually we will get to the "END
1652                          * TRANSACTION" which will set things straight.
1653                          */
1654                 case TBLOCK_ABORT:
1655                         break;
1656
1657                         /*
1658                          * Here we were in an aborted transaction block which just
1659                          * processed the "END TRANSACTION" command from the user, so
1660                          * clean up and return to the default state.
1661                          */
1662                 case TBLOCK_ENDABORT:
1663                         CleanupTransaction();
1664                         s->blockState = TBLOCK_DEFAULT;
1665                         break;
1666
1667                         /*
1668                          * Ditto, but in a subtransaction.  AbortOutOfAnyTransaction
1669                          * will do the dirty work.
1670                          */
1671                 case TBLOCK_SUBENDABORT_ALL:
1672                         AbortOutOfAnyTransaction();
1673                         s = CurrentTransactionState;            /* changed by AbortOutOfAnyTransaction */
1674                         /* AbortOutOfAnyTransaction sets the blockState */
1675                         break;
1676
1677                         /*
1678                          * We were just issued a SAVEPOINT inside a transaction block.
1679                          * Start a subtransaction.  (DefineSavepoint already
1680                          * did PushTransaction, so as to have someplace to put the
1681                          * SUBBEGIN state.)
1682                          */
1683                 case TBLOCK_SUBBEGIN:
1684                         StartSubTransaction();
1685                         s->blockState = TBLOCK_SUBINPROGRESS;
1686                         break;
1687
1688                         /*
1689                          * Inside a subtransaction, increment the command counter.
1690                          */
1691                 case TBLOCK_SUBINPROGRESS:
1692                         CommandCounterIncrement();
1693                         break;
1694
1695                         /*
1696                          * We were issued a RELEASE command, so we end the current
1697                          * subtransaction and return to the parent transaction.
1698                          */
1699                 case TBLOCK_SUBEND:
1700                         CommitSubTransaction();
1701                         PopTransaction();
1702                         s = CurrentTransactionState;            /* changed by pop */
1703                         break;
1704
1705                         /*
1706                          * If we are in an aborted subtransaction, do nothing.
1707                          */
1708                 case TBLOCK_SUBABORT:
1709                         break;
1710
1711                         /*
1712                          * The current subtransaction is ending.  Do the equivalent
1713                          * of a ROLLBACK TO followed by a RELEASE command.
1714                          */
1715                 case TBLOCK_SUBENDABORT_RELEASE:
1716                         CleanupAbortedSubTransactions(false);
1717                         break;
1718
1719                         /*
1720                          * The current subtransaction is ending due to a ROLLBACK
1721                          * TO command, so close all savepoints up to the target
1722                          * level.  When finished, recreate the savepoint.
1723                          */
1724                 case TBLOCK_SUBENDABORT:
1725                         {
1726                                 char *name = CleanupAbortedSubTransactions(true);
1727
1728                                 Assert(PointerIsValid(name));
1729                                 DefineSavepoint(name);
1730                                 s = CurrentTransactionState; /* changed by DefineSavepoint */
1731                                 pfree(name);
1732
1733                                 /* This is the same as TBLOCK_SUBBEGIN case */
1734                                 AssertState(s->blockState == TBLOCK_SUBBEGIN);
1735                                 StartSubTransaction();
1736                                 s->blockState = TBLOCK_SUBINPROGRESS;
1737                         }
1738                         break;
1739         }
1740 }
1741
1742 /*
1743  * CleanupAbortedSubTransactions
1744  *
1745  * Helper function for CommitTransactionCommand.  Aborts and cleans up
1746  * dead subtransactions after a ROLLBACK TO command.  Optionally returns
1747  * the name of the last dead subtransaction so it can be reused to redefine
1748  * the savepoint.  (Caller is responsible for pfree'ing the result.)
1749  */
1750 static char *
1751 CleanupAbortedSubTransactions(bool returnName)
1752 {
1753         TransactionState s = CurrentTransactionState;
1754         char *name = NULL;
1755         
1756         AssertState(PointerIsValid(s->parent));
1757         Assert(s->parent->blockState == TBLOCK_SUBINPROGRESS ||
1758                    s->parent->blockState == TBLOCK_INPROGRESS ||
1759                    s->parent->blockState == TBLOCK_STARTED ||
1760                    s->parent->blockState == TBLOCK_SUBABORT_PENDING);
1761
1762         /*
1763          * Abort everything up to the target level.  The current
1764          * subtransaction only needs cleanup.  If we need to save the name,
1765          * look for the last subtransaction in TBLOCK_SUBABORT_PENDING state.
1766          */
1767         if (returnName && s->parent->blockState != TBLOCK_SUBABORT_PENDING)
1768                 name = MemoryContextStrdup(TopMemoryContext, s->name);
1769
1770         CleanupSubTransaction();
1771         PopTransaction();
1772         s = CurrentTransactionState;            /* changed by pop */
1773
1774         while (s->blockState == TBLOCK_SUBABORT_PENDING)
1775         {
1776                 AbortSubTransaction();
1777                 if (returnName && s->parent->blockState != TBLOCK_SUBABORT_PENDING)
1778                         name = MemoryContextStrdup(TopMemoryContext, s->name);
1779                 CleanupSubTransaction();
1780                 PopTransaction();
1781                 s = CurrentTransactionState;
1782         }
1783
1784         AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
1785                                 s->blockState == TBLOCK_INPROGRESS ||
1786                                 s->blockState == TBLOCK_STARTED);
1787
1788         return name;
1789 }
1790
1791 /*
1792  *      AbortCurrentTransaction
1793  */
1794 void
1795 AbortCurrentTransaction(void)
1796 {
1797         TransactionState s = CurrentTransactionState;
1798
1799         switch (s->blockState)
1800         {
1801                 /*
1802                  * we aren't in a transaction, so we do nothing.
1803                  */
1804                 case TBLOCK_DEFAULT:
1805                         break;
1806
1807                         /*
1808                          * if we aren't in a transaction block, we just do the basic
1809                          * abort & cleanup transaction.
1810                          */
1811                 case TBLOCK_STARTED:
1812                         AbortTransaction();
1813                         CleanupTransaction();
1814                         s->blockState = TBLOCK_DEFAULT;
1815                         break;
1816
1817                         /*
1818                          * If we are in TBLOCK_BEGIN it means something screwed up
1819                          * right after reading "BEGIN TRANSACTION" so we enter the
1820                          * abort state.  Eventually an "END TRANSACTION" will fix
1821                          * things.
1822                          */
1823                 case TBLOCK_BEGIN:
1824                         AbortTransaction();
1825                         s->blockState = TBLOCK_ABORT;
1826                         /* CleanupTransaction happens when we exit TBLOCK_ENDABORT */
1827                         break;
1828
1829                         /*
1830                          * This is the case when we are somewhere in a transaction block
1831                          * and we've gotten a failure, so we abort the transaction and
1832                          * set up the persistent ABORT state.  We will stay in ABORT
1833                          * until we get an "END TRANSACTION".
1834                          */
1835                 case TBLOCK_INPROGRESS:
1836                         AbortTransaction();
1837                         s->blockState = TBLOCK_ABORT;
1838                         /* CleanupTransaction happens when we exit TBLOCK_ENDABORT */
1839                         break;
1840
1841                         /*
1842                          * Here, the system was fouled up just after the user wanted
1843                          * to end the transaction block so we abort the transaction
1844                          * and return to the default state.
1845                          */
1846                 case TBLOCK_END:
1847                         AbortTransaction();
1848                         CleanupTransaction();
1849                         s->blockState = TBLOCK_DEFAULT;
1850                         break;
1851
1852                         /*
1853                          * Here, we are already in an aborted transaction state and
1854                          * are waiting for an "END TRANSACTION" to come along and lo
1855                          * and behold, we abort again! So we just remain in the abort
1856                          * state.
1857                          */
1858                 case TBLOCK_ABORT:
1859                 case TBLOCK_SUBABORT:
1860                         break;
1861
1862                         /*
1863                          * Here we were in an aborted transaction block which just
1864                          * processed the "END TRANSACTION" command but somehow aborted
1865                          * again.. since we must have done the abort processing, we
1866                          * clean up and return to the default state.
1867                          */
1868                 case TBLOCK_ENDABORT:
1869                         CleanupTransaction();
1870                         s->blockState = TBLOCK_DEFAULT;
1871                         break;
1872
1873                         /*
1874                          * If we are just starting a subtransaction, put it
1875                          * in aborted state.
1876                          */
1877                 case TBLOCK_SUBBEGIN:
1878                         StartAbortedSubTransaction();
1879                         s->blockState = TBLOCK_SUBABORT;
1880                         break;
1881
1882                 case TBLOCK_SUBINPROGRESS:
1883                         AbortSubTransaction();
1884                         s->blockState = TBLOCK_SUBABORT;
1885                         break;
1886
1887                         /*
1888                          * If we are aborting an ending transaction,
1889                          * we have to abort the parent transaction too.
1890                          */
1891                 case TBLOCK_SUBEND:
1892                 case TBLOCK_SUBABORT_PENDING:
1893                         AbortSubTransaction();
1894                         CleanupSubTransaction();
1895                         PopTransaction();
1896                         s = CurrentTransactionState;            /* changed by pop */
1897                         Assert(s->blockState != TBLOCK_SUBEND &&
1898                                         s->blockState != TBLOCK_SUBENDABORT);
1899                         AbortCurrentTransaction();
1900                         break;
1901
1902                         /*
1903                          * Same as above, except the Abort() was already done.
1904                          */
1905                 case TBLOCK_SUBENDABORT:
1906                 case TBLOCK_SUBENDABORT_RELEASE:
1907                         CleanupSubTransaction();
1908                         PopTransaction();
1909                         s = CurrentTransactionState;            /* changed by pop */
1910                         Assert(s->blockState != TBLOCK_SUBEND &&
1911                                         s->blockState != TBLOCK_SUBENDABORT);
1912                         AbortCurrentTransaction();
1913                         break;
1914
1915                         /*
1916                          * We are already aborting the whole transaction tree.
1917                          * Do nothing, CommitTransactionCommand will call
1918                          * AbortOutOfAnyTransaction and set things straight.
1919                          */
1920                 case TBLOCK_SUBENDABORT_ALL:
1921                         break;
1922         }
1923 }
1924
1925 /*
1926  *      PreventTransactionChain
1927  *
1928  *      This routine is to be called by statements that must not run inside
1929  *      a transaction block, typically because they have non-rollback-able
1930  *      side effects or do internal commits.
1931  *
1932  *      If we have already started a transaction block, issue an error; also issue
1933  *      an error if we appear to be running inside a user-defined function (which
1934  *      could issue more commands and possibly cause a failure after the statement
1935  *      completes).  Subtransactions are verboten too.
1936  *
1937  *      stmtNode: pointer to parameter block for statement; this is used in
1938  *      a very klugy way to determine whether we are inside a function.
1939  *      stmtType: statement type name for error messages.
1940  */
1941 void
1942 PreventTransactionChain(void *stmtNode, const char *stmtType)
1943 {
1944         /*
1945          * xact block already started?
1946          */
1947         if (IsTransactionBlock())
1948                 ereport(ERROR,
1949                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1950                 /* translator: %s represents an SQL statement name */
1951                                  errmsg("%s cannot run inside a transaction block",
1952                                                 stmtType)));
1953
1954         /*
1955          * subtransaction?
1956          */
1957         if (IsSubTransaction())
1958                 ereport(ERROR,
1959                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1960                 /* translator: %s represents an SQL statement name */
1961                                  errmsg("%s cannot run inside a subtransaction",
1962                                                 stmtType)));
1963
1964         /*
1965          * Are we inside a function call?  If the statement's parameter block
1966          * was allocated in QueryContext, assume it is an interactive command.
1967          * Otherwise assume it is coming from a function.
1968          */
1969         if (!MemoryContextContains(QueryContext, stmtNode))
1970                 ereport(ERROR,
1971                                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1972                 /* translator: %s represents an SQL statement name */
1973                          errmsg("%s cannot be executed from a function", stmtType)));
1974
1975         /* If we got past IsTransactionBlock test, should be in default state */
1976         if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
1977                 CurrentTransactionState->blockState != TBLOCK_STARTED)
1978                 elog(FATAL, "cannot prevent transaction chain");
1979         /* all okay */
1980 }
1981
1982 /*
1983  *      RequireTransactionChain
1984  *
1985  *      This routine is to be called by statements that must run inside
1986  *      a transaction block, because they have no effects that persist past
1987  *      transaction end (and so calling them outside a transaction block
1988  *      is presumably an error).  DECLARE CURSOR is an example.
1989  *
1990  *      If we appear to be running inside a user-defined function, we do not
1991  *      issue an error, since the function could issue more commands that make
1992  *      use of the current statement's results.  Likewise subtransactions.
1993  *      Thus this is an inverse for PreventTransactionChain.
1994  *
1995  *      stmtNode: pointer to parameter block for statement; this is used in
1996  *      a very klugy way to determine whether we are inside a function.
1997  *      stmtType: statement type name for error messages.
1998  */
1999 void
2000 RequireTransactionChain(void *stmtNode, const char *stmtType)
2001 {
2002         /*
2003          * xact block already started?
2004          */
2005         if (IsTransactionBlock())
2006                 return;
2007
2008         /*
2009          * subtransaction?
2010          */
2011         if (IsSubTransaction())
2012                 return;
2013
2014         /*
2015          * Are we inside a function call?  If the statement's parameter block
2016          * was allocated in QueryContext, assume it is an interactive command.
2017          * Otherwise assume it is coming from a function.
2018          */
2019         if (!MemoryContextContains(QueryContext, stmtNode))
2020                 return;
2021         ereport(ERROR,
2022                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2023         /* translator: %s represents an SQL statement name */
2024                          errmsg("%s may only be used in transaction blocks",
2025                                         stmtType)));
2026 }
2027
2028 /*
2029  *      IsInTransactionChain
2030  *
2031  *      This routine is for statements that need to behave differently inside
2032  *      a transaction block than when running as single commands.  ANALYZE is
2033  *      currently the only example.
2034  *
2035  *      stmtNode: pointer to parameter block for statement; this is used in
2036  *      a very klugy way to determine whether we are inside a function.
2037  */
2038 bool
2039 IsInTransactionChain(void *stmtNode)
2040 {
2041         /*
2042          * Return true on same conditions that would make PreventTransactionChain
2043          * error out
2044          */
2045         if (IsTransactionBlock())
2046                 return true;
2047
2048         if (IsSubTransaction())
2049                 return true;
2050
2051         if (!MemoryContextContains(QueryContext, stmtNode))
2052                 return true;
2053
2054         if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2055                 CurrentTransactionState->blockState != TBLOCK_STARTED)
2056                 return true;
2057
2058         return false;
2059 }
2060
2061
2062 /*
2063  * Register or deregister callback functions for start- and end-of-xact
2064  * operations.
2065  *
2066  * These functions are intended for use by dynamically loaded modules.
2067  * For built-in modules we generally just hardwire the appropriate calls
2068  * (mainly because it's easier to control the order that way, where needed).
2069  *
2070  * At transaction end, the callback occurs post-commit or post-abort, so the
2071  * callback functions can only do noncritical cleanup.  At subtransaction
2072  * start, the callback is called when the subtransaction has finished 
2073  * initializing.
2074  */
2075 void
2076 RegisterXactCallback(XactCallback callback, void *arg)
2077 {
2078         XactCallbackItem *item;
2079
2080         item = (XactCallbackItem *)
2081                 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2082         item->callback = callback;
2083         item->arg = arg;
2084         item->next = Xact_callbacks;
2085         Xact_callbacks = item;
2086 }
2087
2088 void
2089 UnregisterXactCallback(XactCallback callback, void *arg)
2090 {
2091         XactCallbackItem *item;
2092         XactCallbackItem *prev;
2093
2094         prev = NULL;
2095         for (item = Xact_callbacks; item; prev = item, item = item->next)
2096         {
2097                 if (item->callback == callback && item->arg == arg)
2098                 {
2099                         if (prev)
2100                                 prev->next = item->next;
2101                         else
2102                                 Xact_callbacks = item->next;
2103                         pfree(item);
2104                         break;
2105                 }
2106         }
2107 }
2108
2109 static void
2110 CallXactCallbacks(XactEvent event, TransactionId parentXid)
2111 {
2112         XactCallbackItem *item;
2113
2114         for (item = Xact_callbacks; item; item = item->next)
2115         {
2116                 (*item->callback) (event, parentXid, item->arg);
2117         }
2118 }
2119
2120
2121 /* ----------------------------------------------------------------
2122  *                                         transaction block support
2123  * ----------------------------------------------------------------
2124  */
2125
2126 /*
2127  *      BeginTransactionBlock
2128  *              This executes a BEGIN command.
2129  */
2130 void
2131 BeginTransactionBlock(void)
2132 {
2133         TransactionState s = CurrentTransactionState;
2134
2135         switch (s->blockState)
2136         {
2137                         /*
2138                          * We are not inside a transaction block, so allow one
2139                          * to begin.
2140                          */
2141                 case TBLOCK_STARTED:
2142                         s->blockState = TBLOCK_BEGIN;
2143                         break;
2144
2145                         /*
2146                          * Already a transaction block in progress.
2147                          */
2148                 case TBLOCK_INPROGRESS:
2149                 case TBLOCK_SUBINPROGRESS:
2150                 case TBLOCK_ABORT:
2151                 case TBLOCK_SUBABORT:
2152                         ereport(WARNING,
2153                                         (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2154                                          errmsg("there is already a transaction in progress")));
2155                         break;
2156
2157                         /* These cases are invalid.  Reject them altogether. */
2158                 case TBLOCK_DEFAULT:
2159                 case TBLOCK_BEGIN:
2160                 case TBLOCK_SUBBEGIN:
2161                 case TBLOCK_ENDABORT:
2162                 case TBLOCK_END:
2163                 case TBLOCK_SUBENDABORT_ALL:
2164                 case TBLOCK_SUBENDABORT:
2165                 case TBLOCK_SUBABORT_PENDING:
2166                 case TBLOCK_SUBENDABORT_RELEASE:
2167                 case TBLOCK_SUBEND:
2168                         elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2169                                  BlockStateAsString(s->blockState));
2170                         break;
2171         }
2172 }
2173
2174 /*
2175  *      EndTransactionBlock
2176  *              This executes a COMMIT command.
2177  *
2178  * Since COMMIT may actually do a ROLLBACK, the result indicates what
2179  * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2180  */
2181 bool
2182 EndTransactionBlock(void)
2183 {
2184         TransactionState s = CurrentTransactionState;
2185         bool            result = false;
2186
2187         switch (s->blockState)
2188         {
2189                 /*
2190                  * We are in a transaction block which should commit when we
2191                  * get to the upcoming CommitTransactionCommand() so we set the
2192                  * state to "END".      CommitTransactionCommand() will recognize this
2193                  * and commit the transaction and return us to the default state.
2194                  */
2195                 case TBLOCK_INPROGRESS:
2196                 case TBLOCK_SUBINPROGRESS:
2197                         s->blockState = TBLOCK_END;
2198                         result = true;
2199                         break;
2200
2201                         /*
2202                          * We are in a transaction block which aborted. Since the
2203                          * AbortTransaction() was already done, we need only
2204                          * change to the special "END ABORT" state.  The upcoming
2205                          * CommitTransactionCommand() will recognise this and then put us
2206                          * back in the default state.
2207                          */
2208                 case TBLOCK_ABORT:
2209                         s->blockState = TBLOCK_ENDABORT;
2210                         break;
2211
2212                         /*
2213                          * Here we are inside an aborted subtransaction.  Go to the "abort
2214                          * the whole tree" state so that CommitTransactionCommand() calls
2215                          * AbortOutOfAnyTransaction.
2216                          */
2217                 case TBLOCK_SUBABORT:
2218                         s->blockState = TBLOCK_SUBENDABORT_ALL;
2219                         break;
2220
2221                 case TBLOCK_STARTED:
2222                         /*
2223                          * here, the user issued COMMIT when not inside a
2224                          * transaction. Issue a WARNING and go to abort state.  The
2225                          * upcoming call to CommitTransactionCommand() will then put us
2226                          * back into the default state.
2227                          */
2228                         ereport(WARNING,
2229                                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2230                                          errmsg("there is no transaction in progress")));
2231                         AbortTransaction();
2232                         s->blockState = TBLOCK_ENDABORT;
2233                         break;
2234
2235                         /* these cases are invalid. */
2236                 case TBLOCK_DEFAULT:
2237                 case TBLOCK_BEGIN:
2238                 case TBLOCK_ENDABORT:
2239                 case TBLOCK_END:
2240                 case TBLOCK_SUBBEGIN:
2241                 case TBLOCK_SUBEND:
2242                 case TBLOCK_SUBENDABORT_ALL:
2243                 case TBLOCK_SUBENDABORT:
2244                 case TBLOCK_SUBABORT_PENDING:
2245                 case TBLOCK_SUBENDABORT_RELEASE:
2246                         elog(FATAL, "EndTransactionBlock: unexpected state %s",
2247                                  BlockStateAsString(s->blockState));
2248                         break;
2249         }
2250
2251         return result;
2252 }
2253
2254 /*
2255  *      UserAbortTransactionBlock
2256  *              This executes a ROLLBACK command.
2257  */
2258 void
2259 UserAbortTransactionBlock(void)
2260 {
2261         TransactionState s = CurrentTransactionState;
2262
2263         switch (s->blockState)
2264         {
2265                         /*
2266                          * We are inside a failed transaction block and we got an
2267                          * abort command from the user.  Abort processing is already
2268                          * done, we just need to move to the ENDABORT state so we will
2269                          * end up in the default state after the upcoming
2270                          * CommitTransactionCommand().
2271                          */
2272                 case TBLOCK_ABORT:
2273                         s->blockState = TBLOCK_ENDABORT;
2274                         break;
2275
2276                         /*
2277                          * We are inside a failed subtransaction and we got an
2278                          * abort command from the user.  Abort processing is already
2279                          * done, so go to the "abort all" state and
2280                          * CommitTransactionCommand will call AbortOutOfAnyTransaction
2281                          * to set things straight.
2282                          */
2283                 case TBLOCK_SUBABORT:
2284                         s->blockState = TBLOCK_SUBENDABORT_ALL;
2285                         break;
2286
2287                         /*
2288                          * We are inside a transaction block and we got an abort
2289                          * command from the user, so we move to the ENDABORT state and
2290                          * do abort processing so we will end up in the default state
2291                          * after the upcoming CommitTransactionCommand().
2292                          */
2293                 case TBLOCK_INPROGRESS:
2294                         AbortTransaction();
2295                         s->blockState = TBLOCK_ENDABORT;
2296                         break;
2297
2298                         /*
2299                          * We are inside a subtransaction.  Abort the current
2300                          * subtransaction and go to the "abort all" state, so
2301                          * CommitTransactionCommand will call AbortOutOfAnyTransaction
2302                          * to set things straight.
2303                          */
2304                 case TBLOCK_SUBINPROGRESS:
2305                         AbortSubTransaction();
2306                         s->blockState = TBLOCK_SUBENDABORT_ALL;
2307                         break;
2308
2309                         /*
2310                          * The user issued ABORT when not inside a transaction. Issue
2311                          * a WARNING and go to abort state.  The upcoming call to
2312                          * CommitTransactionCommand() will then put us back into the
2313                          * default state.
2314                          */
2315                 case TBLOCK_STARTED:
2316                         ereport(WARNING,
2317                                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2318                                          errmsg("there is no transaction in progress")));
2319                         AbortTransaction();
2320                         s->blockState = TBLOCK_ENDABORT;
2321                         break;
2322
2323                         /* These cases are invalid. */
2324                 case TBLOCK_DEFAULT:
2325                 case TBLOCK_BEGIN:
2326                 case TBLOCK_END:
2327                 case TBLOCK_ENDABORT:
2328                 case TBLOCK_SUBEND:
2329                 case TBLOCK_SUBENDABORT_ALL:
2330                 case TBLOCK_SUBENDABORT:
2331                 case TBLOCK_SUBABORT_PENDING:
2332                 case TBLOCK_SUBENDABORT_RELEASE:
2333                 case TBLOCK_SUBBEGIN:
2334                         elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
2335                                  BlockStateAsString(s->blockState));
2336                         break;
2337         }
2338 }
2339
2340 /*
2341  * DefineSavepoint
2342  *              This executes a SAVEPOINT command.
2343  */
2344 void
2345 DefineSavepoint(char *name)
2346 {
2347         TransactionState        s = CurrentTransactionState;
2348
2349         switch (s->blockState)
2350         {
2351                 case TBLOCK_INPROGRESS:
2352                 case TBLOCK_SUBINPROGRESS:
2353                         /* Normal subtransaction start */
2354                         PushTransaction();
2355                         s = CurrentTransactionState;    /* changed by push */
2356                         /*
2357                          * Note that we are allocating the savepoint name in the
2358                          * parent transaction's CurTransactionContext, since we
2359                          * don't yet have a transaction context for the new guy.
2360                          */
2361                         s->name = MemoryContextStrdup(CurTransactionContext, name);
2362                         s->blockState = TBLOCK_SUBBEGIN;
2363                         break;
2364
2365                         /* These cases are invalid.  Reject them altogether. */
2366                 case TBLOCK_DEFAULT:
2367                 case TBLOCK_STARTED:
2368                 case TBLOCK_BEGIN:
2369                 case TBLOCK_SUBBEGIN:
2370                 case TBLOCK_ABORT:
2371                 case TBLOCK_SUBABORT:
2372                 case TBLOCK_ENDABORT:
2373                 case TBLOCK_END:
2374                 case TBLOCK_SUBENDABORT_ALL:
2375                 case TBLOCK_SUBENDABORT:
2376                 case TBLOCK_SUBABORT_PENDING:
2377                 case TBLOCK_SUBENDABORT_RELEASE:
2378                 case TBLOCK_SUBEND:
2379                         elog(FATAL, "DefineSavepoint: unexpected state %s",
2380                                  BlockStateAsString(s->blockState));
2381                         break;
2382         }
2383 }
2384
2385 /*
2386  * ReleaseSavepoint
2387  *              This executes a RELEASE command.
2388  */
2389 void
2390 ReleaseSavepoint(List *options)
2391 {
2392         TransactionState        s = CurrentTransactionState;
2393         TransactionState        target = s;
2394         char                       *name = NULL;
2395         ListCell                   *cell;
2396
2397         /*
2398          * Check valid block state transaction status.
2399          */
2400         switch (s->blockState)
2401         {
2402                 case TBLOCK_INPROGRESS:
2403                 case TBLOCK_ABORT:
2404                         ereport(ERROR,
2405                                         (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2406                                          errmsg("no such savepoint")));
2407                         break;
2408
2409                         /*
2410                          * We are in a non-aborted subtransaction.  This is
2411                          * the only valid case.
2412                          */
2413                 case TBLOCK_SUBINPROGRESS:
2414                         break;
2415
2416                         /* these cases are invalid. */
2417                 case TBLOCK_DEFAULT:
2418                 case TBLOCK_STARTED:
2419                 case TBLOCK_BEGIN:
2420                 case TBLOCK_ENDABORT:
2421                 case TBLOCK_END:
2422                 case TBLOCK_SUBABORT:
2423                 case TBLOCK_SUBBEGIN:
2424                 case TBLOCK_SUBEND:
2425                 case TBLOCK_SUBENDABORT_ALL:
2426                 case TBLOCK_SUBENDABORT:
2427                 case TBLOCK_SUBABORT_PENDING:
2428                 case TBLOCK_SUBENDABORT_RELEASE:
2429                         elog(FATAL, "ReleaseSavepoint: unexpected state %s",
2430                                  BlockStateAsString(s->blockState));
2431                         break;
2432         }
2433
2434         foreach (cell, options)
2435         {
2436                 DefElem *elem = lfirst(cell);
2437
2438                 if (strcmp(elem->defname, "savepoint_name") == 0)
2439                         name = strVal(elem->arg);
2440         }
2441
2442         Assert(PointerIsValid(name));
2443
2444         while (target != NULL)
2445         {
2446                 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
2447                         break;
2448                 target = target->parent;
2449         }
2450
2451         if (!PointerIsValid(target))
2452                 ereport(ERROR,
2453                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2454                                  errmsg("no such savepoint")));
2455
2456         CommitTransactionToLevel(target->nestingLevel);
2457 }
2458
2459 /*
2460  * RollbackToSavepoint
2461  *              This executes a ROLLBACK TO <savepoint> command.
2462  */
2463 void
2464 RollbackToSavepoint(List *options)
2465 {
2466         TransactionState s = CurrentTransactionState;
2467         TransactionState target,
2468                                          xact;
2469         ListCell                *cell;
2470         char                    *name = NULL;
2471
2472         switch (s->blockState)
2473         {
2474                 /*
2475                  * We can't rollback to a savepoint if there is no saveopint
2476                  * defined.
2477                  */
2478                 case TBLOCK_ABORT:
2479                 case TBLOCK_INPROGRESS:
2480                         ereport(ERROR,
2481                                         (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2482                                          errmsg("no such savepoint")));
2483                         break;
2484
2485                         /*
2486                          * There is at least one savepoint, so proceed.
2487                          */
2488                 case TBLOCK_SUBABORT:
2489                 case TBLOCK_SUBINPROGRESS:
2490                         /*
2491                          * Have to do AbortSubTransaction, but first check
2492                          * if this is the right subtransaction
2493                          */
2494                         break;
2495
2496                         /* these cases are invalid. */
2497                 case TBLOCK_DEFAULT:
2498                 case TBLOCK_STARTED:
2499                 case TBLOCK_BEGIN:
2500                 case TBLOCK_END:
2501                 case TBLOCK_ENDABORT:
2502                 case TBLOCK_SUBEND:
2503                 case TBLOCK_SUBENDABORT_ALL:
2504                 case TBLOCK_SUBENDABORT:
2505                 case TBLOCK_SUBABORT_PENDING:
2506                 case TBLOCK_SUBENDABORT_RELEASE:
2507                 case TBLOCK_SUBBEGIN:
2508                         elog(FATAL, "RollbackToSavepoint: unexpected state %s",
2509                                  BlockStateAsString(s->blockState));
2510                         break;
2511         }
2512
2513         foreach (cell, options)
2514         {
2515                 DefElem *elem = lfirst(cell);
2516
2517                 if (strcmp(elem->defname, "savepoint_name") == 0)
2518                         name = strVal(elem->arg);
2519         }
2520
2521         Assert(PointerIsValid(name));
2522
2523         target = CurrentTransactionState;
2524
2525         while (target != NULL)
2526         {
2527                 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
2528                         break;
2529                 target = target->parent;
2530
2531                 /* we don't cross savepoint level boundaries */
2532                 if (target->savepointLevel != s->savepointLevel)
2533                         ereport(ERROR,
2534                                         (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2535                                          errmsg("no such savepoint")));
2536         }
2537
2538         if (!PointerIsValid(target))
2539                 ereport(ERROR,
2540                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2541                                  errmsg("no such savepoint")));
2542
2543         /*
2544          * Abort the current subtransaction, if needed.  We can't Cleanup the
2545          * savepoint yet, so signal CommitTransactionCommand to do it and
2546          * close all savepoints up to the target level.
2547          */
2548         if (s->blockState == TBLOCK_SUBINPROGRESS)
2549                 AbortSubTransaction();
2550         s->blockState = TBLOCK_SUBENDABORT;
2551
2552         /*
2553          * Mark "abort pending" all subtransactions up to the target
2554          * subtransaction.  (Except the current subtransaction!)
2555          */
2556         xact = CurrentTransactionState;
2557
2558         while (xact != target)
2559         {
2560                 xact = xact->parent;
2561                 Assert(PointerIsValid(xact));
2562                 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
2563                 xact->blockState = TBLOCK_SUBABORT_PENDING;
2564         }
2565 }
2566
2567 /*
2568  * BeginInternalSubTransaction
2569  *              This is the same as DefineSavepoint except it allows TBLOCK_STARTED
2570  *              state, and therefore it can safely be used in a function that might
2571  *              be called when not inside a BEGIN block.  Also, we automatically
2572  *              cycle through CommitTransactionCommand/StartTransactionCommand
2573  *              instead of expecting the caller to do it.
2574  *
2575  * Optionally, name can be NULL to create an unnamed savepoint.
2576  */
2577 void
2578 BeginInternalSubTransaction(char *name)
2579 {
2580         TransactionState        s = CurrentTransactionState;
2581
2582         switch (s->blockState)
2583         {
2584                 case TBLOCK_STARTED:
2585                 case TBLOCK_INPROGRESS:
2586                 case TBLOCK_SUBINPROGRESS:
2587                         /* Normal subtransaction start */
2588                         PushTransaction();
2589                         s = CurrentTransactionState;    /* changed by push */
2590                         /*
2591                          * Note that we are allocating the savepoint name in the
2592                          * parent transaction's CurTransactionContext, since we
2593                          * don't yet have a transaction context for the new guy.
2594                          */
2595                         if (name)
2596                                 s->name = MemoryContextStrdup(CurTransactionContext, name);
2597                         s->blockState = TBLOCK_SUBBEGIN;
2598                         break;
2599
2600                         /* These cases are invalid.  Reject them altogether. */
2601                 case TBLOCK_DEFAULT:
2602                 case TBLOCK_BEGIN:
2603                 case TBLOCK_SUBBEGIN:
2604                 case TBLOCK_ABORT:
2605                 case TBLOCK_SUBABORT:
2606                 case TBLOCK_ENDABORT:
2607                 case TBLOCK_END:
2608                 case TBLOCK_SUBENDABORT_ALL:
2609                 case TBLOCK_SUBENDABORT:
2610                 case TBLOCK_SUBABORT_PENDING:
2611                 case TBLOCK_SUBENDABORT_RELEASE:
2612                 case TBLOCK_SUBEND:
2613                         elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
2614                                  BlockStateAsString(s->blockState));
2615                         break;
2616         }
2617
2618         CommitTransactionCommand();
2619         StartTransactionCommand();
2620 }
2621
2622 /*
2623  * ReleaseCurrentSubTransaction
2624  *
2625  * RELEASE (ie, commit) the innermost subtransaction, regardless of its
2626  * savepoint name (if any).
2627  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
2628  */
2629 void
2630 ReleaseCurrentSubTransaction(void)
2631 {
2632         TransactionState s = CurrentTransactionState;
2633
2634         if (s->blockState != TBLOCK_SUBINPROGRESS)
2635                 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
2636                          BlockStateAsString(s->blockState));
2637         MemoryContextSwitchTo(CurTransactionContext);
2638         CommitTransactionToLevel(GetCurrentTransactionNestLevel());
2639 }
2640
2641 /*
2642  * RollbackAndReleaseCurrentSubTransaction
2643  *
2644  * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
2645  * of its savepoint name (if any).
2646  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
2647  */
2648 void
2649 RollbackAndReleaseCurrentSubTransaction(void)
2650 {
2651         TransactionState s = CurrentTransactionState;
2652
2653         switch (s->blockState)
2654         {
2655                 /* Must be in a subtransaction */
2656                 case TBLOCK_SUBABORT:
2657                 case TBLOCK_SUBINPROGRESS:
2658                         break;
2659
2660                         /* these cases are invalid. */
2661                 case TBLOCK_DEFAULT:
2662                 case TBLOCK_STARTED:
2663                 case TBLOCK_ABORT:
2664                 case TBLOCK_INPROGRESS:
2665                 case TBLOCK_BEGIN:
2666                 case TBLOCK_END:
2667                 case TBLOCK_ENDABORT:
2668                 case TBLOCK_SUBEND:
2669                 case TBLOCK_SUBENDABORT_ALL:
2670                 case TBLOCK_SUBENDABORT:
2671                 case TBLOCK_SUBABORT_PENDING:
2672                 case TBLOCK_SUBENDABORT_RELEASE:
2673                 case TBLOCK_SUBBEGIN:
2674                         elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
2675                                  BlockStateAsString(s->blockState));
2676                         break;
2677         }
2678
2679         /*
2680          * Abort the current subtransaction, if needed.
2681          */
2682         if (s->blockState == TBLOCK_SUBINPROGRESS)
2683                 AbortSubTransaction();
2684         s->blockState = TBLOCK_SUBENDABORT_RELEASE;
2685
2686         /* And clean it up, too */
2687         CleanupAbortedSubTransactions(false);
2688 }
2689
2690 /*
2691  *      AbortOutOfAnyTransaction
2692  *
2693  *      This routine is provided for error recovery purposes.  It aborts any
2694  *      active transaction or transaction block, leaving the system in a known
2695  *      idle state.
2696  */
2697 void
2698 AbortOutOfAnyTransaction(void)
2699 {
2700         TransactionState s = CurrentTransactionState;
2701
2702         /*
2703          * Get out of any transaction or nested transaction
2704          */
2705         do {
2706                 switch (s->blockState)
2707                 {
2708                         case TBLOCK_DEFAULT:
2709                                 /* Not in a transaction, do nothing */
2710                                 break;
2711                         case TBLOCK_STARTED:
2712                         case TBLOCK_BEGIN:
2713                         case TBLOCK_INPROGRESS:
2714                         case TBLOCK_END:
2715                                 /* In a transaction, so clean up */
2716                                 AbortTransaction();
2717                                 CleanupTransaction();
2718                                 s->blockState = TBLOCK_DEFAULT;
2719                                 break;
2720                         case TBLOCK_ABORT:
2721                         case TBLOCK_ENDABORT:
2722                                 /* AbortTransaction already done, still need Cleanup */
2723                                 CleanupTransaction();
2724                                 s->blockState = TBLOCK_DEFAULT;
2725                                 break;
2726                         case TBLOCK_SUBBEGIN:
2727                                 /*
2728                                  * We didn't get as far as starting the subxact, so there's
2729                                  * nothing to abort.  Just pop back to parent.
2730                                  */
2731                                 PopTransaction();
2732                                 s = CurrentTransactionState;            /* changed by pop */
2733                                 break;
2734                         case TBLOCK_SUBINPROGRESS:
2735                         case TBLOCK_SUBEND:
2736                         case TBLOCK_SUBABORT_PENDING:
2737                                 /* In a subtransaction, so clean it up and abort parent too */
2738                                 AbortSubTransaction();
2739                                 CleanupSubTransaction();
2740                                 PopTransaction();
2741                                 s = CurrentTransactionState;            /* changed by pop */
2742                                 break;
2743                         case TBLOCK_SUBABORT:
2744                         case TBLOCK_SUBENDABORT_ALL:
2745                         case TBLOCK_SUBENDABORT:
2746                         case TBLOCK_SUBENDABORT_RELEASE:
2747                                 /* As above, but AbortSubTransaction already done */
2748                                 CleanupSubTransaction();
2749                                 PopTransaction();
2750                                 s = CurrentTransactionState;            /* changed by pop */
2751                                 break;
2752                 }
2753         } while (s->blockState != TBLOCK_DEFAULT);
2754
2755         /* Should be out of all subxacts now */
2756         Assert(s->parent == NULL);
2757 }
2758
2759 /*
2760  * CommitTransactionToLevel
2761  *
2762  * Commit everything from the current transaction level
2763  * up to the specified level (inclusive).
2764  */
2765 static void
2766 CommitTransactionToLevel(int level)
2767 {
2768         TransactionState s = CurrentTransactionState;
2769
2770         Assert(s->state == TRANS_INPROGRESS);
2771
2772         while (s->nestingLevel >= level)
2773         {
2774                 CommitSubTransaction();
2775                 PopTransaction();
2776                 s = CurrentTransactionState;                            /* changed by pop */
2777                 Assert(s->state == TRANS_INPROGRESS);
2778         }
2779 }
2780
2781 /*
2782  * IsTransactionBlock --- are we within a transaction block?
2783  */
2784 bool
2785 IsTransactionBlock(void)
2786 {
2787         TransactionState s = CurrentTransactionState;
2788
2789         if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
2790                 return false;
2791
2792         return true;
2793 }
2794
2795 /*
2796  * IsTransactionOrTransactionBlock --- are we within either a transaction
2797  * or a transaction block?  (The backend is only really "idle" when this
2798  * returns false.)
2799  *
2800  * This should match up with IsTransactionBlock and IsTransactionState.
2801  */
2802 bool
2803 IsTransactionOrTransactionBlock(void)
2804 {
2805         TransactionState s = CurrentTransactionState;
2806
2807         if (s->blockState == TBLOCK_DEFAULT)
2808                 return false;
2809
2810         return true;
2811 }
2812
2813 /*
2814  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
2815  */
2816 char
2817 TransactionBlockStatusCode(void)
2818 {
2819         TransactionState s = CurrentTransactionState;
2820
2821         switch (s->blockState)
2822         {
2823                 case TBLOCK_DEFAULT:
2824                 case TBLOCK_STARTED:
2825                         return 'I';                     /* idle --- not in transaction */
2826                 case TBLOCK_BEGIN:
2827                 case TBLOCK_INPROGRESS:
2828                 case TBLOCK_END:
2829                 case TBLOCK_SUBINPROGRESS:
2830                 case TBLOCK_SUBBEGIN:
2831                 case TBLOCK_SUBEND:
2832                         return 'T';                     /* in transaction */
2833                 case TBLOCK_ABORT:
2834                 case TBLOCK_ENDABORT:
2835                 case TBLOCK_SUBABORT:
2836                 case TBLOCK_SUBENDABORT_ALL:
2837                 case TBLOCK_SUBENDABORT:
2838                 case TBLOCK_SUBABORT_PENDING:
2839                 case TBLOCK_SUBENDABORT_RELEASE:
2840                         return 'E';                     /* in failed transaction */
2841         }
2842
2843         /* should never get here */
2844         elog(FATAL, "invalid transaction block state: %s",
2845                  BlockStateAsString(s->blockState));
2846         return 0;                                       /* keep compiler quiet */
2847 }
2848
2849 /*
2850  * IsSubTransaction
2851  */
2852 bool
2853 IsSubTransaction(void)
2854 {
2855         TransactionState s = CurrentTransactionState;
2856
2857         if (s->nestingLevel >= 2)
2858                 return true;
2859
2860         return false;
2861 }
2862
2863 /*
2864  * StartSubTransaction
2865  */
2866 static void
2867 StartSubTransaction(void)
2868 {
2869         TransactionState s = CurrentTransactionState;
2870
2871         if (s->state != TRANS_DEFAULT)
2872                 elog(WARNING, "StartSubTransaction while in %s state",
2873                          TransStateAsString(s->state));
2874
2875         s->state = TRANS_START;
2876
2877         /*
2878          * must initialize resource-management stuff first
2879          */
2880         AtSubStart_Memory();
2881         AtSubStart_ResourceOwner();
2882
2883         /*
2884          * Generate a new Xid and record it in pg_subtrans.  NB: we must make
2885          * the subtrans entry BEFORE the Xid appears anywhere in shared storage,
2886          * such as in the lock table; because until it's made the Xid may not
2887          * appear to be "running" to other backends. See GetNewTransactionId.
2888          */
2889         s->transactionIdData = GetNewTransactionId(true);
2890
2891         SubTransSetParent(s->transactionIdData, s->parent->transactionIdData);
2892
2893         XactLockTableInsert(s->transactionIdData);
2894
2895         /*
2896          * Finish setup of other transaction state fields.
2897          */
2898         s->currentUser = GetUserId();
2899         s->prevXactReadOnly = XactReadOnly;
2900         
2901         /*
2902          * Initialize other subsystems for new subtransaction
2903          */
2904         AtSubStart_Inval();
2905         AtSubStart_Notify();
2906         DeferredTriggerBeginSubXact();
2907
2908         s->state = TRANS_INPROGRESS;
2909
2910         /*
2911          * Call start-of-subxact callbacks 
2912          */
2913         CallXactCallbacks(XACT_EVENT_START_SUB, s->parent->transactionIdData);
2914
2915         ShowTransactionState("StartSubTransaction");
2916 }
2917
2918 /*
2919  * CommitSubTransaction
2920  */
2921 static void
2922 CommitSubTransaction(void)
2923 {
2924         TransactionState s = CurrentTransactionState;
2925
2926         ShowTransactionState("CommitSubTransaction");
2927
2928         if (s->state != TRANS_INPROGRESS)
2929                 elog(WARNING, "CommitSubTransaction while in %s state",
2930                          TransStateAsString(s->state));
2931
2932         /* Pre-commit processing goes here -- nothing to do at the moment */
2933
2934         s->state = TRANS_COMMIT;
2935
2936         /* Mark subtransaction as subcommitted */
2937         CommandCounterIncrement();
2938         RecordSubTransactionCommit();
2939         AtSubCommit_childXids();
2940
2941         /* Post-commit cleanup */
2942         DeferredTriggerEndSubXact(true);
2943         AtSubCommit_Portals(s->parent->transactionIdData,
2944                                                 s->parent->curTransactionOwner);
2945         AtEOSubXact_LargeObject(true, s->transactionIdData,
2946                                                         s->parent->transactionIdData);
2947         AtSubCommit_Notify();
2948         AtEOSubXact_UpdatePasswordFile(true, s->transactionIdData,
2949                                                                    s->parent->transactionIdData);
2950         AtSubCommit_smgr();
2951
2952         CallXactCallbacks(XACT_EVENT_COMMIT_SUB, s->parent->transactionIdData);
2953
2954         /*
2955          * Note that we just release the resource owner's resources and don't
2956          * delete it.  This is because locks are not actually released here.
2957          * The owner object continues to exist as a child of its parent owner
2958          * (namely my parent transaction's resource owner), and the locks
2959          * effectively become that owner object's responsibility.
2960          */
2961         ResourceOwnerRelease(s->curTransactionOwner,
2962                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
2963                                                  true, false);
2964         AtEOSubXact_Inval(true);
2965         /* we can skip the LOCKS phase */
2966         ResourceOwnerRelease(s->curTransactionOwner,
2967                                                  RESOURCE_RELEASE_AFTER_LOCKS,
2968                                                  true, false);
2969
2970         AtEOXact_GUC(true, true);
2971         AtEOSubXact_SPI(true, s->transactionIdData);
2972         AtEOSubXact_on_commit_actions(true, s->transactionIdData,
2973                                                                   s->parent->transactionIdData);
2974         AtEOSubXact_Namespace(true, s->transactionIdData,
2975                                                   s->parent->transactionIdData);
2976         AtEOSubXact_Files(true, s->transactionIdData,
2977                                           s->parent->transactionIdData);
2978
2979         /*
2980          * We need to restore the upper transaction's read-only state,
2981          * in case the upper is read-write while the child is read-only;
2982          * GUC will incorrectly think it should leave the child state in place.
2983          */
2984         XactReadOnly = s->prevXactReadOnly;
2985
2986         CurrentResourceOwner = s->parent->curTransactionOwner;
2987         CurTransactionResourceOwner = s->parent->curTransactionOwner;
2988         s->curTransactionOwner = NULL;
2989
2990         AtSubCommit_Memory();
2991
2992         s->state = TRANS_DEFAULT;
2993 }
2994
2995 /*
2996  * AbortSubTransaction
2997  */
2998 static void
2999 AbortSubTransaction(void)
3000 {
3001         TransactionState s = CurrentTransactionState;
3002
3003         ShowTransactionState("AbortSubTransaction");
3004
3005         if (s->state != TRANS_INPROGRESS)
3006                 elog(WARNING, "AbortSubTransaction while in %s state",
3007                          TransStateAsString(s->state));
3008
3009         HOLD_INTERRUPTS();
3010
3011         s->state = TRANS_ABORT;
3012
3013         /*
3014          * Release any LW locks we might be holding as quickly as possible.
3015          * (Regular locks, however, must be held till we finish aborting.)
3016          * Releasing LW locks is critical since we might try to grab them
3017          * again while cleaning up!
3018          *
3019          * FIXME This may be incorrect --- Are there some locks we should keep?
3020          * Buffer locks, for example?  I don't think so but I'm not sure.
3021          */
3022         LWLockReleaseAll();
3023
3024         AbortBufferIO();
3025         UnlockBuffers();
3026
3027         LockWaitCancel();
3028
3029         /*
3030          * do abort processing
3031          */
3032         AtSubAbort_Memory();
3033
3034         DeferredTriggerEndSubXact(false);
3035         AtSubAbort_Portals(s->parent->transactionIdData,
3036                                            s->parent->curTransactionOwner);
3037         AtEOSubXact_LargeObject(false, s->transactionIdData,
3038                                                         s->parent->transactionIdData);
3039         AtSubAbort_Notify();
3040         AtEOSubXact_UpdatePasswordFile(false, s->transactionIdData,
3041                                                                    s->parent->transactionIdData);
3042
3043         /* Advertise the fact that we aborted in pg_clog. */
3044         RecordSubTransactionAbort();
3045
3046         /* Post-abort cleanup */
3047         AtSubAbort_smgr();
3048
3049         CallXactCallbacks(XACT_EVENT_ABORT_SUB, s->parent->transactionIdData);
3050
3051         ResourceOwnerRelease(s->curTransactionOwner,
3052                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
3053                                                  false, false);
3054         AtEOSubXact_Inval(false);
3055         ResourceOwnerRelease(s->curTransactionOwner,
3056                                                  RESOURCE_RELEASE_LOCKS,
3057                                                  false, false);
3058         ResourceOwnerRelease(s->curTransactionOwner,
3059                                                  RESOURCE_RELEASE_AFTER_LOCKS,
3060                                                  false, false);
3061
3062         AtEOXact_GUC(false, true);
3063         AtEOSubXact_SPI(false, s->transactionIdData);
3064         AtEOSubXact_on_commit_actions(false, s->transactionIdData,
3065                                                                   s->parent->transactionIdData);
3066         AtEOSubXact_Namespace(false, s->transactionIdData,
3067                                                   s->parent->transactionIdData);
3068         AtEOSubXact_Files(false, s->transactionIdData,
3069                                           s->parent->transactionIdData);
3070
3071         /*
3072          * Reset user id which might have been changed transiently.  Here we
3073          * want to restore to the userid that was current at subxact entry.
3074          * (As in AbortTransaction, we need not worry about the session userid.)
3075          *
3076          * Must do this after AtEOXact_GUC to handle the case where we entered
3077          * the subxact inside a SECURITY DEFINER function (hence current and
3078          * session userids were different) and then session auth was changed
3079          * inside the subxact.  GUC will reset both current and session userids
3080          * to the entry-time session userid.  This is right in every other
3081          * scenario so it seems simplest to let GUC do that and fix it here.
3082          */
3083         SetUserId(s->currentUser);
3084
3085         /*
3086          * Restore the upper transaction's read-only state, too.  This should
3087          * be redundant with GUC's cleanup but we may as well do it for
3088          * consistency with the commit case.
3089          */
3090         XactReadOnly = s->prevXactReadOnly;
3091
3092         RESUME_INTERRUPTS();
3093 }
3094
3095 /*
3096  * CleanupSubTransaction
3097  */
3098 static void
3099 CleanupSubTransaction(void)
3100 {
3101         TransactionState s = CurrentTransactionState;
3102
3103         ShowTransactionState("CleanupSubTransaction");
3104
3105         if (s->state != TRANS_ABORT)
3106                 elog(WARNING, "CleanupSubTransaction while in %s state",
3107                          TransStateAsString(s->state));
3108
3109         AtSubCleanup_Portals();
3110
3111         CurrentResourceOwner = s->parent->curTransactionOwner;
3112         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3113         ResourceOwnerDelete(s->curTransactionOwner);
3114         s->curTransactionOwner = NULL;
3115
3116         AtSubCleanup_Memory();
3117
3118         s->state = TRANS_DEFAULT;
3119 }
3120
3121 /*
3122  * StartAbortedSubTransaction
3123  *
3124  * This function is used to start a subtransaction and put it immediately
3125  * into aborted state.  The end result should be equivalent to
3126  * StartSubTransaction immediately followed by AbortSubTransaction.
3127  * The reason we don't implement it just that way is that many of the backend
3128  * modules aren't designed to handle starting a subtransaction when not
3129  * inside a valid transaction.  Rather than making them all capable of
3130  * doing that, we just omit the paired start and abort calls in this path.
3131  */
3132 static void
3133 StartAbortedSubTransaction(void)
3134 {
3135         TransactionState s = CurrentTransactionState;
3136
3137         if (s->state != TRANS_DEFAULT)
3138                 elog(WARNING, "StartAbortedSubTransaction while in %s state",
3139                          TransStateAsString(s->state));
3140
3141         s->state = TRANS_START;
3142
3143         /*
3144          * We don't bother to generate a new Xid, so the end state is not
3145          * *exactly* like we had done a full Start/AbortSubTransaction...
3146          */
3147         s->transactionIdData = InvalidTransactionId;
3148
3149         /* Make sure currentUser is reasonably valid */
3150         Assert(s->parent != NULL);
3151         s->currentUser = s->parent->currentUser;
3152         
3153         /*
3154          * Initialize only what has to be there for CleanupSubTransaction to work.
3155          */
3156         AtSubStart_Memory();
3157         AtSubStart_ResourceOwner();
3158
3159         s->state = TRANS_ABORT;
3160
3161         AtSubAbort_Memory();
3162
3163         ShowTransactionState("StartAbortedSubTransaction");
3164 }
3165
3166 /*
3167  * PushTransaction
3168  *              Set up transaction state for a subtransaction
3169  *
3170  *      The caller has to make sure to always reassign CurrentTransactionState
3171  *      if it has a local pointer to it after calling this function.
3172  */
3173 static void
3174 PushTransaction(void)
3175 {
3176         TransactionState    p = CurrentTransactionState;
3177         TransactionState    s;
3178
3179         /*
3180          * We keep subtransaction state nodes in TopTransactionContext.
3181          */
3182         s = (TransactionState)
3183                 MemoryContextAllocZero(TopTransactionContext,
3184                                                            sizeof(TransactionStateData));
3185         s->parent = p;
3186         s->nestingLevel = p->nestingLevel + 1;
3187         s->savepointLevel = p->savepointLevel;
3188         s->state = TRANS_DEFAULT;
3189         s->blockState = TBLOCK_SUBBEGIN;
3190
3191         /* Command IDs count in a continuous sequence through subtransactions */
3192         s->commandId = p->commandId;
3193
3194         /*
3195          * Copy down some other data so that we will have valid state until
3196          * StartSubTransaction runs.
3197          */
3198         s->transactionIdData = p->transactionIdData;
3199         s->curTransactionContext = p->curTransactionContext;
3200         s->curTransactionOwner = p->curTransactionOwner;
3201         s->currentUser = p->currentUser;
3202
3203         CurrentTransactionState = s;
3204 }
3205
3206 /*
3207  * PopTransaction
3208  *              Pop back to parent transaction state
3209  *
3210  *      The caller has to make sure to always reassign CurrentTransactionState
3211  *      if it has a local pointer to it after calling this function.
3212  */
3213 static void
3214 PopTransaction(void)
3215 {
3216         TransactionState s = CurrentTransactionState;
3217
3218         if (s->state != TRANS_DEFAULT)
3219                 elog(WARNING, "PopTransaction while in %s state",
3220                          TransStateAsString(s->state));
3221
3222         if (s->parent == NULL)
3223                 elog(FATAL, "PopTransaction with no parent");
3224
3225         /* Command IDs count in a continuous sequence through subtransactions */
3226         s->parent->commandId = s->commandId;
3227
3228         CurrentTransactionState = s->parent;
3229
3230         /* Let's just make sure CurTransactionContext is good */
3231         CurTransactionContext = s->parent->curTransactionContext;
3232         MemoryContextSwitchTo(CurTransactionContext);
3233
3234         /* Ditto for ResourceOwner links */
3235         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3236         CurrentResourceOwner = s->parent->curTransactionOwner;
3237
3238         /* Free the old child structure */
3239         if (s->name)
3240                 pfree(s->name);
3241         pfree(s);
3242 }
3243
3244 /*
3245  * ShowTransactionState
3246  *              Debug support
3247  */
3248 static void
3249 ShowTransactionState(const char *str)
3250 {
3251         /* skip work if message will definitely not be printed */
3252         if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
3253         {
3254                 elog(DEBUG2, "%s", str);
3255                 ShowTransactionStateRec(CurrentTransactionState);
3256         }
3257 }
3258
3259 /*
3260  * ShowTransactionStateRec
3261  *              Recursive subroutine for ShowTransactionState
3262  */
3263 static void
3264 ShowTransactionStateRec(TransactionState s)
3265 {
3266         if (s->parent)
3267                 ShowTransactionStateRec(s->parent);
3268
3269         /* use ereport to suppress computation if msg will not be printed */
3270         ereport(DEBUG2,
3271                         (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/cid: %u/%02u, nestlvl: %d, children: %s",
3272                                                          PointerIsValid(s->name) ? s->name : "unnamed",
3273                                                          BlockStateAsString(s->blockState),
3274                                                          TransStateAsString(s->state),
3275                                                          (unsigned int) s->transactionIdData,
3276                                                          (unsigned int) s->commandId,
3277                                                          s->nestingLevel,
3278                                                          nodeToString(s->childXids))));
3279 }
3280
3281 /*
3282  * BlockStateAsString
3283  *              Debug support
3284  */
3285 static const char *
3286 BlockStateAsString(TBlockState blockState)
3287 {
3288         switch (blockState)
3289         {
3290                 case TBLOCK_DEFAULT:
3291                         return "DEFAULT";
3292                 case TBLOCK_STARTED:
3293                         return "STARTED";
3294                 case TBLOCK_BEGIN:
3295                         return "BEGIN";
3296                 case TBLOCK_INPROGRESS:
3297                         return "INPROGRESS";
3298                 case TBLOCK_END:
3299                         return "END";
3300                 case TBLOCK_ABORT:
3301                         return "ABORT";
3302                 case TBLOCK_ENDABORT:
3303                         return "ENDABORT";
3304                 case TBLOCK_SUBBEGIN:
3305                         return "SUB BEGIN";
3306                 case TBLOCK_SUBINPROGRESS:
3307                         return "SUB INPROGRS";
3308                 case TBLOCK_SUBEND:
3309                         return "SUB END";
3310                 case TBLOCK_SUBABORT:
3311                         return "SUB ABORT";
3312                 case TBLOCK_SUBENDABORT_ALL:
3313                         return "SUB ENDAB ALL";
3314                 case TBLOCK_SUBENDABORT:
3315                         return "SUB ENDAB";
3316                 case TBLOCK_SUBABORT_PENDING:
3317                         return "SUB ABRT PEND";
3318                 case TBLOCK_SUBENDABORT_RELEASE:
3319                         return "SUB ENDAB REL";
3320         }
3321         return "UNRECOGNIZED";
3322 }
3323
3324 /*
3325  * TransStateAsString
3326  *              Debug support
3327  */
3328 static const char *
3329 TransStateAsString(TransState state)
3330 {
3331         switch (state)
3332         {
3333                 case TRANS_DEFAULT:
3334                         return "DEFAULT";
3335                 case TRANS_START:
3336                         return "START";
3337                 case TRANS_COMMIT:
3338                         return "COMMIT";
3339                 case TRANS_ABORT:
3340                         return "ABORT";
3341                 case TRANS_INPROGRESS:
3342                         return "INPROGR";
3343         }
3344         return "UNRECOGNIZED";
3345 }
3346
3347 /*
3348  * xactGetCommittedChildren
3349  *
3350  * Gets the list of committed children of the current transaction.  The return
3351  * value is the number of child transactions.  *children is set to point to a
3352  * palloc'd array of TransactionIds.  If there are no subxacts, *children is
3353  * set to NULL.
3354  */
3355 int
3356 xactGetCommittedChildren(TransactionId **ptr)
3357 {
3358         TransactionState        s = CurrentTransactionState;
3359         int                                     nchildren;
3360         TransactionId      *children;
3361         ListCell                   *p;
3362
3363         nchildren = list_length(s->childXids);
3364         if (nchildren == 0)
3365         {
3366                 *ptr = NULL;
3367                 return 0;
3368         }
3369
3370         children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
3371         *ptr = children;
3372
3373         foreach(p, s->childXids)
3374         {
3375                 TransactionId child = lfirst_xid(p);
3376
3377                 *children++ = child;
3378         }
3379
3380         return nchildren;
3381 }
3382
3383 /*
3384  *      XLOG support routines
3385  */
3386
3387 void
3388 xact_redo(XLogRecPtr lsn, XLogRecord *record)
3389 {
3390         uint8           info = record->xl_info & ~XLR_INFO_MASK;
3391
3392         if (info == XLOG_XACT_COMMIT)
3393         {
3394                 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
3395                 int             i;
3396
3397                 TransactionIdCommit(record->xl_xid);
3398                 /* Mark committed subtransactions as committed */
3399                 TransactionIdCommitTree(xlrec->nsubxacts,
3400                                                                 (TransactionId *) &(xlrec->xnodes[xlrec->nrels]));
3401                 /* Make sure files supposed to be dropped are dropped */
3402                 for (i = 0; i < xlrec->nrels; i++)
3403                 {
3404                         XLogCloseRelation(xlrec->xnodes[i]);
3405                         smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3406                 }
3407         }
3408         else if (info == XLOG_XACT_ABORT)
3409         {
3410                 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
3411                 int             i;
3412
3413                 TransactionIdAbort(record->xl_xid);
3414                 /* mark subtransactions as aborted */
3415                 TransactionIdAbortTree(xlrec->nsubxacts,
3416                                                            (TransactionId *) &(xlrec->xnodes[xlrec->nrels]));
3417                 /* Make sure files supposed to be dropped are dropped */
3418                 for (i = 0; i < xlrec->nrels; i++)
3419                 {
3420                         XLogCloseRelation(xlrec->xnodes[i]);
3421                         smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3422                 }
3423         }
3424         else
3425                 elog(PANIC, "xact_redo: unknown op code %u", info);
3426 }
3427
3428 void
3429 xact_undo(XLogRecPtr lsn, XLogRecord *record)
3430 {
3431         uint8           info = record->xl_info & ~XLR_INFO_MASK;
3432
3433         if (info == XLOG_XACT_COMMIT)           /* shouldn't be called by XLOG */
3434                 elog(PANIC, "xact_undo: can't undo committed xaction");
3435         else if (info != XLOG_XACT_ABORT)
3436                 elog(PANIC, "xact_redo: unknown op code %u", info);
3437 }
3438
3439 void
3440 xact_desc(char *buf, uint8 xl_info, char *rec)
3441 {
3442         uint8           info = xl_info & ~XLR_INFO_MASK;
3443         int i;
3444
3445         if (info == XLOG_XACT_COMMIT)
3446         {
3447                 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
3448                 struct tm  *tm = localtime(&xlrec->xtime);
3449
3450                 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
3451                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3452                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
3453                 if (xlrec->nrels > 0)
3454                 {
3455                         sprintf(buf + strlen(buf), "; rels:");
3456                         for (i = 0; i < xlrec->nrels; i++)
3457                         {
3458                                 RelFileNode rnode = xlrec->xnodes[i];
3459                                 sprintf(buf + strlen(buf), " %u/%u/%u",
3460                                                 rnode.spcNode, rnode.dbNode, rnode.relNode);
3461                         }
3462                 }
3463                 if (xlrec->nsubxacts > 0)
3464                 {
3465                         TransactionId *xacts = (TransactionId *)
3466                                 &xlrec->xnodes[xlrec->nrels];
3467
3468                         sprintf(buf + strlen(buf), "; subxacts:");
3469                         for (i = 0; i < xlrec->nsubxacts; i++)
3470                                 sprintf(buf + strlen(buf), " %u", xacts[i]);
3471                 }
3472         }
3473         else if (info == XLOG_XACT_ABORT)
3474         {
3475                 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
3476                 struct tm  *tm = localtime(&xlrec->xtime);
3477
3478                 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
3479                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3480                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
3481                 if (xlrec->nrels > 0)
3482                 {
3483                         sprintf(buf + strlen(buf), "; rels:");
3484                         for (i = 0; i < xlrec->nrels; i++)
3485                         {
3486                                 RelFileNode rnode = xlrec->xnodes[i];
3487                                 sprintf(buf + strlen(buf), " %u/%u/%u",
3488                                                 rnode.spcNode, rnode.dbNode, rnode.relNode);
3489                         }
3490                 }
3491                 if (xlrec->nsubxacts > 0)
3492                 {
3493                         TransactionId *xacts = (TransactionId *)
3494                                 &xlrec->xnodes[xlrec->nrels];
3495
3496                         sprintf(buf + strlen(buf), "; subxacts:");
3497                         for (i = 0; i < xlrec->nsubxacts; i++)
3498                                 sprintf(buf + strlen(buf), " %u", xacts[i]);
3499                 }
3500         }
3501         else
3502                 strcat(buf, "UNKNOWN");
3503 }
3504
3505 void
3506 XactPushRollback(void (*func) (void *), void *data)
3507 {
3508 #ifdef XLOG_II
3509         if (_RollbackFunc != NULL)
3510                 elog(PANIC, "XactPushRollback: already installed");
3511 #endif
3512
3513         _RollbackFunc = func;
3514         _RollbackData = data;
3515 }
3516
3517 void
3518 XactPopRollback(void)
3519 {
3520         _RollbackFunc = NULL;
3521 }