]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/xact.c
Fix misplacement of savepointLevel test, per report from Chris K-L.
[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.177 2004/08/03 15:57:26 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         for (target = s; PointerIsValid(target); target = target->parent)
2524         {
2525                 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
2526                         break;
2527         }
2528
2529         if (!PointerIsValid(target))
2530                 ereport(ERROR,
2531                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2532                                  errmsg("no such savepoint")));
2533
2534         /* disallow crossing savepoint level boundaries */
2535         if (target->savepointLevel != s->savepointLevel)
2536                 ereport(ERROR,
2537                                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2538                                  errmsg("no such savepoint")));
2539
2540         /*
2541          * Abort the current subtransaction, if needed.  We can't Cleanup the
2542          * savepoint yet, so signal CommitTransactionCommand to do it and
2543          * close all savepoints up to the target level.
2544          */
2545         if (s->blockState == TBLOCK_SUBINPROGRESS)
2546                 AbortSubTransaction();
2547         s->blockState = TBLOCK_SUBENDABORT;
2548
2549         /*
2550          * Mark "abort pending" all subtransactions up to the target
2551          * subtransaction.  (Except the current subtransaction!)
2552          */
2553         xact = CurrentTransactionState;
2554
2555         while (xact != target)
2556         {
2557                 xact = xact->parent;
2558                 Assert(PointerIsValid(xact));
2559                 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
2560                 xact->blockState = TBLOCK_SUBABORT_PENDING;
2561         }
2562 }
2563
2564 /*
2565  * BeginInternalSubTransaction
2566  *              This is the same as DefineSavepoint except it allows TBLOCK_STARTED
2567  *              state, and therefore it can safely be used in a function that might
2568  *              be called when not inside a BEGIN block.  Also, we automatically
2569  *              cycle through CommitTransactionCommand/StartTransactionCommand
2570  *              instead of expecting the caller to do it.
2571  *
2572  * Optionally, name can be NULL to create an unnamed savepoint.
2573  */
2574 void
2575 BeginInternalSubTransaction(char *name)
2576 {
2577         TransactionState        s = CurrentTransactionState;
2578
2579         switch (s->blockState)
2580         {
2581                 case TBLOCK_STARTED:
2582                 case TBLOCK_INPROGRESS:
2583                 case TBLOCK_SUBINPROGRESS:
2584                         /* Normal subtransaction start */
2585                         PushTransaction();
2586                         s = CurrentTransactionState;    /* changed by push */
2587                         /*
2588                          * Note that we are allocating the savepoint name in the
2589                          * parent transaction's CurTransactionContext, since we
2590                          * don't yet have a transaction context for the new guy.
2591                          */
2592                         if (name)
2593                                 s->name = MemoryContextStrdup(CurTransactionContext, name);
2594                         s->blockState = TBLOCK_SUBBEGIN;
2595                         break;
2596
2597                         /* These cases are invalid.  Reject them altogether. */
2598                 case TBLOCK_DEFAULT:
2599                 case TBLOCK_BEGIN:
2600                 case TBLOCK_SUBBEGIN:
2601                 case TBLOCK_ABORT:
2602                 case TBLOCK_SUBABORT:
2603                 case TBLOCK_ENDABORT:
2604                 case TBLOCK_END:
2605                 case TBLOCK_SUBENDABORT_ALL:
2606                 case TBLOCK_SUBENDABORT:
2607                 case TBLOCK_SUBABORT_PENDING:
2608                 case TBLOCK_SUBENDABORT_RELEASE:
2609                 case TBLOCK_SUBEND:
2610                         elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
2611                                  BlockStateAsString(s->blockState));
2612                         break;
2613         }
2614
2615         CommitTransactionCommand();
2616         StartTransactionCommand();
2617 }
2618
2619 /*
2620  * ReleaseCurrentSubTransaction
2621  *
2622  * RELEASE (ie, commit) the innermost subtransaction, regardless of its
2623  * savepoint name (if any).
2624  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
2625  */
2626 void
2627 ReleaseCurrentSubTransaction(void)
2628 {
2629         TransactionState s = CurrentTransactionState;
2630
2631         if (s->blockState != TBLOCK_SUBINPROGRESS)
2632                 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
2633                          BlockStateAsString(s->blockState));
2634         MemoryContextSwitchTo(CurTransactionContext);
2635         CommitTransactionToLevel(GetCurrentTransactionNestLevel());
2636 }
2637
2638 /*
2639  * RollbackAndReleaseCurrentSubTransaction
2640  *
2641  * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
2642  * of its savepoint name (if any).
2643  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
2644  */
2645 void
2646 RollbackAndReleaseCurrentSubTransaction(void)
2647 {
2648         TransactionState s = CurrentTransactionState;
2649
2650         switch (s->blockState)
2651         {
2652                 /* Must be in a subtransaction */
2653                 case TBLOCK_SUBABORT:
2654                 case TBLOCK_SUBINPROGRESS:
2655                         break;
2656
2657                         /* these cases are invalid. */
2658                 case TBLOCK_DEFAULT:
2659                 case TBLOCK_STARTED:
2660                 case TBLOCK_ABORT:
2661                 case TBLOCK_INPROGRESS:
2662                 case TBLOCK_BEGIN:
2663                 case TBLOCK_END:
2664                 case TBLOCK_ENDABORT:
2665                 case TBLOCK_SUBEND:
2666                 case TBLOCK_SUBENDABORT_ALL:
2667                 case TBLOCK_SUBENDABORT:
2668                 case TBLOCK_SUBABORT_PENDING:
2669                 case TBLOCK_SUBENDABORT_RELEASE:
2670                 case TBLOCK_SUBBEGIN:
2671                         elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
2672                                  BlockStateAsString(s->blockState));
2673                         break;
2674         }
2675
2676         /*
2677          * Abort the current subtransaction, if needed.
2678          */
2679         if (s->blockState == TBLOCK_SUBINPROGRESS)
2680                 AbortSubTransaction();
2681         s->blockState = TBLOCK_SUBENDABORT_RELEASE;
2682
2683         /* And clean it up, too */
2684         CleanupAbortedSubTransactions(false);
2685 }
2686
2687 /*
2688  *      AbortOutOfAnyTransaction
2689  *
2690  *      This routine is provided for error recovery purposes.  It aborts any
2691  *      active transaction or transaction block, leaving the system in a known
2692  *      idle state.
2693  */
2694 void
2695 AbortOutOfAnyTransaction(void)
2696 {
2697         TransactionState s = CurrentTransactionState;
2698
2699         /*
2700          * Get out of any transaction or nested transaction
2701          */
2702         do {
2703                 switch (s->blockState)
2704                 {
2705                         case TBLOCK_DEFAULT:
2706                                 /* Not in a transaction, do nothing */
2707                                 break;
2708                         case TBLOCK_STARTED:
2709                         case TBLOCK_BEGIN:
2710                         case TBLOCK_INPROGRESS:
2711                         case TBLOCK_END:
2712                                 /* In a transaction, so clean up */
2713                                 AbortTransaction();
2714                                 CleanupTransaction();
2715                                 s->blockState = TBLOCK_DEFAULT;
2716                                 break;
2717                         case TBLOCK_ABORT:
2718                         case TBLOCK_ENDABORT:
2719                                 /* AbortTransaction already done, still need Cleanup */
2720                                 CleanupTransaction();
2721                                 s->blockState = TBLOCK_DEFAULT;
2722                                 break;
2723                         case TBLOCK_SUBBEGIN:
2724                                 /*
2725                                  * We didn't get as far as starting the subxact, so there's
2726                                  * nothing to abort.  Just pop back to parent.
2727                                  */
2728                                 PopTransaction();
2729                                 s = CurrentTransactionState;            /* changed by pop */
2730                                 break;
2731                         case TBLOCK_SUBINPROGRESS:
2732                         case TBLOCK_SUBEND:
2733                         case TBLOCK_SUBABORT_PENDING:
2734                                 /* In a subtransaction, so clean it up and abort parent too */
2735                                 AbortSubTransaction();
2736                                 CleanupSubTransaction();
2737                                 PopTransaction();
2738                                 s = CurrentTransactionState;            /* changed by pop */
2739                                 break;
2740                         case TBLOCK_SUBABORT:
2741                         case TBLOCK_SUBENDABORT_ALL:
2742                         case TBLOCK_SUBENDABORT:
2743                         case TBLOCK_SUBENDABORT_RELEASE:
2744                                 /* As above, but AbortSubTransaction already done */
2745                                 CleanupSubTransaction();
2746                                 PopTransaction();
2747                                 s = CurrentTransactionState;            /* changed by pop */
2748                                 break;
2749                 }
2750         } while (s->blockState != TBLOCK_DEFAULT);
2751
2752         /* Should be out of all subxacts now */
2753         Assert(s->parent == NULL);
2754 }
2755
2756 /*
2757  * CommitTransactionToLevel
2758  *
2759  * Commit everything from the current transaction level
2760  * up to the specified level (inclusive).
2761  */
2762 static void
2763 CommitTransactionToLevel(int level)
2764 {
2765         TransactionState s = CurrentTransactionState;
2766
2767         Assert(s->state == TRANS_INPROGRESS);
2768
2769         while (s->nestingLevel >= level)
2770         {
2771                 CommitSubTransaction();
2772                 PopTransaction();
2773                 s = CurrentTransactionState;                            /* changed by pop */
2774                 Assert(s->state == TRANS_INPROGRESS);
2775         }
2776 }
2777
2778 /*
2779  * IsTransactionBlock --- are we within a transaction block?
2780  */
2781 bool
2782 IsTransactionBlock(void)
2783 {
2784         TransactionState s = CurrentTransactionState;
2785
2786         if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
2787                 return false;
2788
2789         return true;
2790 }
2791
2792 /*
2793  * IsTransactionOrTransactionBlock --- are we within either a transaction
2794  * or a transaction block?  (The backend is only really "idle" when this
2795  * returns false.)
2796  *
2797  * This should match up with IsTransactionBlock and IsTransactionState.
2798  */
2799 bool
2800 IsTransactionOrTransactionBlock(void)
2801 {
2802         TransactionState s = CurrentTransactionState;
2803
2804         if (s->blockState == TBLOCK_DEFAULT)
2805                 return false;
2806
2807         return true;
2808 }
2809
2810 /*
2811  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
2812  */
2813 char
2814 TransactionBlockStatusCode(void)
2815 {
2816         TransactionState s = CurrentTransactionState;
2817
2818         switch (s->blockState)
2819         {
2820                 case TBLOCK_DEFAULT:
2821                 case TBLOCK_STARTED:
2822                         return 'I';                     /* idle --- not in transaction */
2823                 case TBLOCK_BEGIN:
2824                 case TBLOCK_INPROGRESS:
2825                 case TBLOCK_END:
2826                 case TBLOCK_SUBINPROGRESS:
2827                 case TBLOCK_SUBBEGIN:
2828                 case TBLOCK_SUBEND:
2829                         return 'T';                     /* in transaction */
2830                 case TBLOCK_ABORT:
2831                 case TBLOCK_ENDABORT:
2832                 case TBLOCK_SUBABORT:
2833                 case TBLOCK_SUBENDABORT_ALL:
2834                 case TBLOCK_SUBENDABORT:
2835                 case TBLOCK_SUBABORT_PENDING:
2836                 case TBLOCK_SUBENDABORT_RELEASE:
2837                         return 'E';                     /* in failed transaction */
2838         }
2839
2840         /* should never get here */
2841         elog(FATAL, "invalid transaction block state: %s",
2842                  BlockStateAsString(s->blockState));
2843         return 0;                                       /* keep compiler quiet */
2844 }
2845
2846 /*
2847  * IsSubTransaction
2848  */
2849 bool
2850 IsSubTransaction(void)
2851 {
2852         TransactionState s = CurrentTransactionState;
2853
2854         if (s->nestingLevel >= 2)
2855                 return true;
2856
2857         return false;
2858 }
2859
2860 /*
2861  * StartSubTransaction
2862  */
2863 static void
2864 StartSubTransaction(void)
2865 {
2866         TransactionState s = CurrentTransactionState;
2867
2868         if (s->state != TRANS_DEFAULT)
2869                 elog(WARNING, "StartSubTransaction while in %s state",
2870                          TransStateAsString(s->state));
2871
2872         s->state = TRANS_START;
2873
2874         /*
2875          * must initialize resource-management stuff first
2876          */
2877         AtSubStart_Memory();
2878         AtSubStart_ResourceOwner();
2879
2880         /*
2881          * Generate a new Xid and record it in pg_subtrans.  NB: we must make
2882          * the subtrans entry BEFORE the Xid appears anywhere in shared storage,
2883          * such as in the lock table; because until it's made the Xid may not
2884          * appear to be "running" to other backends. See GetNewTransactionId.
2885          */
2886         s->transactionIdData = GetNewTransactionId(true);
2887
2888         SubTransSetParent(s->transactionIdData, s->parent->transactionIdData);
2889
2890         XactLockTableInsert(s->transactionIdData);
2891
2892         /*
2893          * Finish setup of other transaction state fields.
2894          */
2895         s->currentUser = GetUserId();
2896         s->prevXactReadOnly = XactReadOnly;
2897         
2898         /*
2899          * Initialize other subsystems for new subtransaction
2900          */
2901         AtSubStart_Inval();
2902         AtSubStart_Notify();
2903         DeferredTriggerBeginSubXact();
2904
2905         s->state = TRANS_INPROGRESS;
2906
2907         /*
2908          * Call start-of-subxact callbacks 
2909          */
2910         CallXactCallbacks(XACT_EVENT_START_SUB, s->parent->transactionIdData);
2911
2912         ShowTransactionState("StartSubTransaction");
2913 }
2914
2915 /*
2916  * CommitSubTransaction
2917  */
2918 static void
2919 CommitSubTransaction(void)
2920 {
2921         TransactionState s = CurrentTransactionState;
2922
2923         ShowTransactionState("CommitSubTransaction");
2924
2925         if (s->state != TRANS_INPROGRESS)
2926                 elog(WARNING, "CommitSubTransaction while in %s state",
2927                          TransStateAsString(s->state));
2928
2929         /* Pre-commit processing goes here -- nothing to do at the moment */
2930
2931         s->state = TRANS_COMMIT;
2932
2933         /* Mark subtransaction as subcommitted */
2934         CommandCounterIncrement();
2935         RecordSubTransactionCommit();
2936         AtSubCommit_childXids();
2937
2938         /* Post-commit cleanup */
2939         DeferredTriggerEndSubXact(true);
2940         AtSubCommit_Portals(s->parent->transactionIdData,
2941                                                 s->parent->curTransactionOwner);
2942         AtEOSubXact_LargeObject(true, s->transactionIdData,
2943                                                         s->parent->transactionIdData);
2944         AtSubCommit_Notify();
2945         AtEOSubXact_UpdatePasswordFile(true, s->transactionIdData,
2946                                                                    s->parent->transactionIdData);
2947         AtSubCommit_smgr();
2948
2949         CallXactCallbacks(XACT_EVENT_COMMIT_SUB, s->parent->transactionIdData);
2950
2951         /*
2952          * Note that we just release the resource owner's resources and don't
2953          * delete it.  This is because locks are not actually released here.
2954          * The owner object continues to exist as a child of its parent owner
2955          * (namely my parent transaction's resource owner), and the locks
2956          * effectively become that owner object's responsibility.
2957          */
2958         ResourceOwnerRelease(s->curTransactionOwner,
2959                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
2960                                                  true, false);
2961         AtEOSubXact_Inval(true);
2962         /* we can skip the LOCKS phase */
2963         ResourceOwnerRelease(s->curTransactionOwner,
2964                                                  RESOURCE_RELEASE_AFTER_LOCKS,
2965                                                  true, false);
2966
2967         AtEOXact_GUC(true, true);
2968         AtEOSubXact_SPI(true, s->transactionIdData);
2969         AtEOSubXact_on_commit_actions(true, s->transactionIdData,
2970                                                                   s->parent->transactionIdData);
2971         AtEOSubXact_Namespace(true, s->transactionIdData,
2972                                                   s->parent->transactionIdData);
2973         AtEOSubXact_Files(true, s->transactionIdData,
2974                                           s->parent->transactionIdData);
2975
2976         /*
2977          * We need to restore the upper transaction's read-only state,
2978          * in case the upper is read-write while the child is read-only;
2979          * GUC will incorrectly think it should leave the child state in place.
2980          */
2981         XactReadOnly = s->prevXactReadOnly;
2982
2983         CurrentResourceOwner = s->parent->curTransactionOwner;
2984         CurTransactionResourceOwner = s->parent->curTransactionOwner;
2985         s->curTransactionOwner = NULL;
2986
2987         AtSubCommit_Memory();
2988
2989         s->state = TRANS_DEFAULT;
2990 }
2991
2992 /*
2993  * AbortSubTransaction
2994  */
2995 static void
2996 AbortSubTransaction(void)
2997 {
2998         TransactionState s = CurrentTransactionState;
2999
3000         ShowTransactionState("AbortSubTransaction");
3001
3002         if (s->state != TRANS_INPROGRESS)
3003                 elog(WARNING, "AbortSubTransaction while in %s state",
3004                          TransStateAsString(s->state));
3005
3006         HOLD_INTERRUPTS();
3007
3008         s->state = TRANS_ABORT;
3009
3010         /*
3011          * Release any LW locks we might be holding as quickly as possible.
3012          * (Regular locks, however, must be held till we finish aborting.)
3013          * Releasing LW locks is critical since we might try to grab them
3014          * again while cleaning up!
3015          *
3016          * FIXME This may be incorrect --- Are there some locks we should keep?
3017          * Buffer locks, for example?  I don't think so but I'm not sure.
3018          */
3019         LWLockReleaseAll();
3020
3021         AbortBufferIO();
3022         UnlockBuffers();
3023
3024         LockWaitCancel();
3025
3026         /*
3027          * do abort processing
3028          */
3029         AtSubAbort_Memory();
3030
3031         DeferredTriggerEndSubXact(false);
3032         AtSubAbort_Portals(s->parent->transactionIdData,
3033                                            s->parent->curTransactionOwner);
3034         AtEOSubXact_LargeObject(false, s->transactionIdData,
3035                                                         s->parent->transactionIdData);
3036         AtSubAbort_Notify();
3037         AtEOSubXact_UpdatePasswordFile(false, s->transactionIdData,
3038                                                                    s->parent->transactionIdData);
3039
3040         /* Advertise the fact that we aborted in pg_clog. */
3041         RecordSubTransactionAbort();
3042
3043         /* Post-abort cleanup */
3044         AtSubAbort_smgr();
3045
3046         CallXactCallbacks(XACT_EVENT_ABORT_SUB, s->parent->transactionIdData);
3047
3048         ResourceOwnerRelease(s->curTransactionOwner,
3049                                                  RESOURCE_RELEASE_BEFORE_LOCKS,
3050                                                  false, false);
3051         AtEOSubXact_Inval(false);
3052         ResourceOwnerRelease(s->curTransactionOwner,
3053                                                  RESOURCE_RELEASE_LOCKS,
3054                                                  false, false);
3055         ResourceOwnerRelease(s->curTransactionOwner,
3056                                                  RESOURCE_RELEASE_AFTER_LOCKS,
3057                                                  false, false);
3058
3059         AtEOXact_GUC(false, true);
3060         AtEOSubXact_SPI(false, s->transactionIdData);
3061         AtEOSubXact_on_commit_actions(false, s->transactionIdData,
3062                                                                   s->parent->transactionIdData);
3063         AtEOSubXact_Namespace(false, s->transactionIdData,
3064                                                   s->parent->transactionIdData);
3065         AtEOSubXact_Files(false, s->transactionIdData,
3066                                           s->parent->transactionIdData);
3067
3068         /*
3069          * Reset user id which might have been changed transiently.  Here we
3070          * want to restore to the userid that was current at subxact entry.
3071          * (As in AbortTransaction, we need not worry about the session userid.)
3072          *
3073          * Must do this after AtEOXact_GUC to handle the case where we entered
3074          * the subxact inside a SECURITY DEFINER function (hence current and
3075          * session userids were different) and then session auth was changed
3076          * inside the subxact.  GUC will reset both current and session userids
3077          * to the entry-time session userid.  This is right in every other
3078          * scenario so it seems simplest to let GUC do that and fix it here.
3079          */
3080         SetUserId(s->currentUser);
3081
3082         /*
3083          * Restore the upper transaction's read-only state, too.  This should
3084          * be redundant with GUC's cleanup but we may as well do it for
3085          * consistency with the commit case.
3086          */
3087         XactReadOnly = s->prevXactReadOnly;
3088
3089         RESUME_INTERRUPTS();
3090 }
3091
3092 /*
3093  * CleanupSubTransaction
3094  */
3095 static void
3096 CleanupSubTransaction(void)
3097 {
3098         TransactionState s = CurrentTransactionState;
3099
3100         ShowTransactionState("CleanupSubTransaction");
3101
3102         if (s->state != TRANS_ABORT)
3103                 elog(WARNING, "CleanupSubTransaction while in %s state",
3104                          TransStateAsString(s->state));
3105
3106         AtSubCleanup_Portals();
3107
3108         CurrentResourceOwner = s->parent->curTransactionOwner;
3109         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3110         ResourceOwnerDelete(s->curTransactionOwner);
3111         s->curTransactionOwner = NULL;
3112
3113         AtSubCleanup_Memory();
3114
3115         s->state = TRANS_DEFAULT;
3116 }
3117
3118 /*
3119  * StartAbortedSubTransaction
3120  *
3121  * This function is used to start a subtransaction and put it immediately
3122  * into aborted state.  The end result should be equivalent to
3123  * StartSubTransaction immediately followed by AbortSubTransaction.
3124  * The reason we don't implement it just that way is that many of the backend
3125  * modules aren't designed to handle starting a subtransaction when not
3126  * inside a valid transaction.  Rather than making them all capable of
3127  * doing that, we just omit the paired start and abort calls in this path.
3128  */
3129 static void
3130 StartAbortedSubTransaction(void)
3131 {
3132         TransactionState s = CurrentTransactionState;
3133
3134         if (s->state != TRANS_DEFAULT)
3135                 elog(WARNING, "StartAbortedSubTransaction while in %s state",
3136                          TransStateAsString(s->state));
3137
3138         s->state = TRANS_START;
3139
3140         /*
3141          * We don't bother to generate a new Xid, so the end state is not
3142          * *exactly* like we had done a full Start/AbortSubTransaction...
3143          */
3144         s->transactionIdData = InvalidTransactionId;
3145
3146         /* Make sure currentUser is reasonably valid */
3147         Assert(s->parent != NULL);
3148         s->currentUser = s->parent->currentUser;
3149         
3150         /*
3151          * Initialize only what has to be there for CleanupSubTransaction to work.
3152          */
3153         AtSubStart_Memory();
3154         AtSubStart_ResourceOwner();
3155
3156         s->state = TRANS_ABORT;
3157
3158         AtSubAbort_Memory();
3159
3160         ShowTransactionState("StartAbortedSubTransaction");
3161 }
3162
3163 /*
3164  * PushTransaction
3165  *              Set up transaction state for a subtransaction
3166  *
3167  *      The caller has to make sure to always reassign CurrentTransactionState
3168  *      if it has a local pointer to it after calling this function.
3169  */
3170 static void
3171 PushTransaction(void)
3172 {
3173         TransactionState    p = CurrentTransactionState;
3174         TransactionState    s;
3175
3176         /*
3177          * We keep subtransaction state nodes in TopTransactionContext.
3178          */
3179         s = (TransactionState)
3180                 MemoryContextAllocZero(TopTransactionContext,
3181                                                            sizeof(TransactionStateData));
3182         s->parent = p;
3183         s->nestingLevel = p->nestingLevel + 1;
3184         s->savepointLevel = p->savepointLevel;
3185         s->state = TRANS_DEFAULT;
3186         s->blockState = TBLOCK_SUBBEGIN;
3187
3188         /* Command IDs count in a continuous sequence through subtransactions */
3189         s->commandId = p->commandId;
3190
3191         /*
3192          * Copy down some other data so that we will have valid state until
3193          * StartSubTransaction runs.
3194          */
3195         s->transactionIdData = p->transactionIdData;
3196         s->curTransactionContext = p->curTransactionContext;
3197         s->curTransactionOwner = p->curTransactionOwner;
3198         s->currentUser = p->currentUser;
3199
3200         CurrentTransactionState = s;
3201 }
3202
3203 /*
3204  * PopTransaction
3205  *              Pop back to parent transaction state
3206  *
3207  *      The caller has to make sure to always reassign CurrentTransactionState
3208  *      if it has a local pointer to it after calling this function.
3209  */
3210 static void
3211 PopTransaction(void)
3212 {
3213         TransactionState s = CurrentTransactionState;
3214
3215         if (s->state != TRANS_DEFAULT)
3216                 elog(WARNING, "PopTransaction while in %s state",
3217                          TransStateAsString(s->state));
3218
3219         if (s->parent == NULL)
3220                 elog(FATAL, "PopTransaction with no parent");
3221
3222         /* Command IDs count in a continuous sequence through subtransactions */
3223         s->parent->commandId = s->commandId;
3224
3225         CurrentTransactionState = s->parent;
3226
3227         /* Let's just make sure CurTransactionContext is good */
3228         CurTransactionContext = s->parent->curTransactionContext;
3229         MemoryContextSwitchTo(CurTransactionContext);
3230
3231         /* Ditto for ResourceOwner links */
3232         CurTransactionResourceOwner = s->parent->curTransactionOwner;
3233         CurrentResourceOwner = s->parent->curTransactionOwner;
3234
3235         /* Free the old child structure */
3236         if (s->name)
3237                 pfree(s->name);
3238         pfree(s);
3239 }
3240
3241 /*
3242  * ShowTransactionState
3243  *              Debug support
3244  */
3245 static void
3246 ShowTransactionState(const char *str)
3247 {
3248         /* skip work if message will definitely not be printed */
3249         if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
3250         {
3251                 elog(DEBUG2, "%s", str);
3252                 ShowTransactionStateRec(CurrentTransactionState);
3253         }
3254 }
3255
3256 /*
3257  * ShowTransactionStateRec
3258  *              Recursive subroutine for ShowTransactionState
3259  */
3260 static void
3261 ShowTransactionStateRec(TransactionState s)
3262 {
3263         if (s->parent)
3264                 ShowTransactionStateRec(s->parent);
3265
3266         /* use ereport to suppress computation if msg will not be printed */
3267         ereport(DEBUG2,
3268                         (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/cid: %u/%02u, nestlvl: %d, children: %s",
3269                                                          PointerIsValid(s->name) ? s->name : "unnamed",
3270                                                          BlockStateAsString(s->blockState),
3271                                                          TransStateAsString(s->state),
3272                                                          (unsigned int) s->transactionIdData,
3273                                                          (unsigned int) s->commandId,
3274                                                          s->nestingLevel,
3275                                                          nodeToString(s->childXids))));
3276 }
3277
3278 /*
3279  * BlockStateAsString
3280  *              Debug support
3281  */
3282 static const char *
3283 BlockStateAsString(TBlockState blockState)
3284 {
3285         switch (blockState)
3286         {
3287                 case TBLOCK_DEFAULT:
3288                         return "DEFAULT";
3289                 case TBLOCK_STARTED:
3290                         return "STARTED";
3291                 case TBLOCK_BEGIN:
3292                         return "BEGIN";
3293                 case TBLOCK_INPROGRESS:
3294                         return "INPROGRESS";
3295                 case TBLOCK_END:
3296                         return "END";
3297                 case TBLOCK_ABORT:
3298                         return "ABORT";
3299                 case TBLOCK_ENDABORT:
3300                         return "ENDABORT";
3301                 case TBLOCK_SUBBEGIN:
3302                         return "SUB BEGIN";
3303                 case TBLOCK_SUBINPROGRESS:
3304                         return "SUB INPROGRS";
3305                 case TBLOCK_SUBEND:
3306                         return "SUB END";
3307                 case TBLOCK_SUBABORT:
3308                         return "SUB ABORT";
3309                 case TBLOCK_SUBENDABORT_ALL:
3310                         return "SUB ENDAB ALL";
3311                 case TBLOCK_SUBENDABORT:
3312                         return "SUB ENDAB";
3313                 case TBLOCK_SUBABORT_PENDING:
3314                         return "SUB ABRT PEND";
3315                 case TBLOCK_SUBENDABORT_RELEASE:
3316                         return "SUB ENDAB REL";
3317         }
3318         return "UNRECOGNIZED";
3319 }
3320
3321 /*
3322  * TransStateAsString
3323  *              Debug support
3324  */
3325 static const char *
3326 TransStateAsString(TransState state)
3327 {
3328         switch (state)
3329         {
3330                 case TRANS_DEFAULT:
3331                         return "DEFAULT";
3332                 case TRANS_START:
3333                         return "START";
3334                 case TRANS_COMMIT:
3335                         return "COMMIT";
3336                 case TRANS_ABORT:
3337                         return "ABORT";
3338                 case TRANS_INPROGRESS:
3339                         return "INPROGR";
3340         }
3341         return "UNRECOGNIZED";
3342 }
3343
3344 /*
3345  * xactGetCommittedChildren
3346  *
3347  * Gets the list of committed children of the current transaction.  The return
3348  * value is the number of child transactions.  *children is set to point to a
3349  * palloc'd array of TransactionIds.  If there are no subxacts, *children is
3350  * set to NULL.
3351  */
3352 int
3353 xactGetCommittedChildren(TransactionId **ptr)
3354 {
3355         TransactionState        s = CurrentTransactionState;
3356         int                                     nchildren;
3357         TransactionId      *children;
3358         ListCell                   *p;
3359
3360         nchildren = list_length(s->childXids);
3361         if (nchildren == 0)
3362         {
3363                 *ptr = NULL;
3364                 return 0;
3365         }
3366
3367         children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
3368         *ptr = children;
3369
3370         foreach(p, s->childXids)
3371         {
3372                 TransactionId child = lfirst_xid(p);
3373
3374                 *children++ = child;
3375         }
3376
3377         return nchildren;
3378 }
3379
3380 /*
3381  *      XLOG support routines
3382  */
3383
3384 void
3385 xact_redo(XLogRecPtr lsn, XLogRecord *record)
3386 {
3387         uint8           info = record->xl_info & ~XLR_INFO_MASK;
3388
3389         if (info == XLOG_XACT_COMMIT)
3390         {
3391                 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
3392                 int             i;
3393
3394                 TransactionIdCommit(record->xl_xid);
3395                 /* Mark committed subtransactions as committed */
3396                 TransactionIdCommitTree(xlrec->nsubxacts,
3397                                                                 (TransactionId *) &(xlrec->xnodes[xlrec->nrels]));
3398                 /* Make sure files supposed to be dropped are dropped */
3399                 for (i = 0; i < xlrec->nrels; i++)
3400                 {
3401                         XLogCloseRelation(xlrec->xnodes[i]);
3402                         smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3403                 }
3404         }
3405         else if (info == XLOG_XACT_ABORT)
3406         {
3407                 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
3408                 int             i;
3409
3410                 TransactionIdAbort(record->xl_xid);
3411                 /* mark subtransactions as aborted */
3412                 TransactionIdAbortTree(xlrec->nsubxacts,
3413                                                            (TransactionId *) &(xlrec->xnodes[xlrec->nrels]));
3414                 /* Make sure files supposed to be dropped are dropped */
3415                 for (i = 0; i < xlrec->nrels; i++)
3416                 {
3417                         XLogCloseRelation(xlrec->xnodes[i]);
3418                         smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3419                 }
3420         }
3421         else
3422                 elog(PANIC, "xact_redo: unknown op code %u", info);
3423 }
3424
3425 void
3426 xact_undo(XLogRecPtr lsn, XLogRecord *record)
3427 {
3428         uint8           info = record->xl_info & ~XLR_INFO_MASK;
3429
3430         if (info == XLOG_XACT_COMMIT)           /* shouldn't be called by XLOG */
3431                 elog(PANIC, "xact_undo: can't undo committed xaction");
3432         else if (info != XLOG_XACT_ABORT)
3433                 elog(PANIC, "xact_redo: unknown op code %u", info);
3434 }
3435
3436 void
3437 xact_desc(char *buf, uint8 xl_info, char *rec)
3438 {
3439         uint8           info = xl_info & ~XLR_INFO_MASK;
3440         int i;
3441
3442         if (info == XLOG_XACT_COMMIT)
3443         {
3444                 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
3445                 struct tm  *tm = localtime(&xlrec->xtime);
3446
3447                 sprintf(buf + strlen(buf), "commit: %04u-%02u-%02u %02u:%02u:%02u",
3448                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3449                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
3450                 if (xlrec->nrels > 0)
3451                 {
3452                         sprintf(buf + strlen(buf), "; rels:");
3453                         for (i = 0; i < xlrec->nrels; i++)
3454                         {
3455                                 RelFileNode rnode = xlrec->xnodes[i];
3456                                 sprintf(buf + strlen(buf), " %u/%u/%u",
3457                                                 rnode.spcNode, rnode.dbNode, rnode.relNode);
3458                         }
3459                 }
3460                 if (xlrec->nsubxacts > 0)
3461                 {
3462                         TransactionId *xacts = (TransactionId *)
3463                                 &xlrec->xnodes[xlrec->nrels];
3464
3465                         sprintf(buf + strlen(buf), "; subxacts:");
3466                         for (i = 0; i < xlrec->nsubxacts; i++)
3467                                 sprintf(buf + strlen(buf), " %u", xacts[i]);
3468                 }
3469         }
3470         else if (info == XLOG_XACT_ABORT)
3471         {
3472                 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
3473                 struct tm  *tm = localtime(&xlrec->xtime);
3474
3475                 sprintf(buf + strlen(buf), "abort: %04u-%02u-%02u %02u:%02u:%02u",
3476                                 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
3477                                 tm->tm_hour, tm->tm_min, tm->tm_sec);
3478                 if (xlrec->nrels > 0)
3479                 {
3480                         sprintf(buf + strlen(buf), "; rels:");
3481                         for (i = 0; i < xlrec->nrels; i++)
3482                         {
3483                                 RelFileNode rnode = xlrec->xnodes[i];
3484                                 sprintf(buf + strlen(buf), " %u/%u/%u",
3485                                                 rnode.spcNode, rnode.dbNode, rnode.relNode);
3486                         }
3487                 }
3488                 if (xlrec->nsubxacts > 0)
3489                 {
3490                         TransactionId *xacts = (TransactionId *)
3491                                 &xlrec->xnodes[xlrec->nrels];
3492
3493                         sprintf(buf + strlen(buf), "; subxacts:");
3494                         for (i = 0; i < xlrec->nsubxacts; i++)
3495                                 sprintf(buf + strlen(buf), " %u", xacts[i]);
3496                 }
3497         }
3498         else
3499                 strcat(buf, "UNKNOWN");
3500 }
3501
3502 void
3503 XactPushRollback(void (*func) (void *), void *data)
3504 {
3505 #ifdef XLOG_II
3506         if (_RollbackFunc != NULL)
3507                 elog(PANIC, "XactPushRollback: already installed");
3508 #endif
3509
3510         _RollbackFunc = func;
3511         _RollbackData = data;
3512 }
3513
3514 void
3515 XactPopRollback(void)
3516 {
3517         _RollbackFunc = NULL;
3518 }