1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
13 * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.177 2004/08/03 15:57:26 tgl Exp $
15 *-------------------------------------------------------------------------
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"
48 * transaction states - transaction state from server perspective
50 typedef enum TransState
60 * transaction block states - transaction state of client queries
62 typedef enum TBlockState
64 /* not-in-transaction-block states */
68 /* transaction block states */
75 /* subtransaction states */
80 TBLOCK_SUBABORT_PENDING,
81 TBLOCK_SUBENDABORT_ALL,
82 TBLOCK_SUBENDABORT_RELEASE,
87 * transaction state structure
89 typedef struct TransactionStateData
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;
106 typedef TransactionStateData *TransactionState;
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.
113 #define lfirst_xid(lc) ((TransactionId) lfirst_int(lc))
114 #define lappend_xid(list, datum) lappend_int(list, (int) (datum))
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);
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);
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);
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);
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.
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
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 */
175 static TransactionState CurrentTransactionState = &TopTransactionStateData;
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.
182 static AbsoluteTime xactStartTime; /* integer part */
183 static int xactStartTimeUsec; /* microsecond part */
187 * User-tweakable parameters
189 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
192 bool DefaultXactReadOnly = false;
195 int CommitDelay = 0; /* precommit delay in microseconds */
196 int CommitSiblings = 5; /* number of concurrent xacts needed to
201 * List of add-on start- and end-of-xact callbacks
203 typedef struct XactCallbackItem
205 struct XactCallbackItem *next;
206 XactCallback callback;
210 static XactCallbackItem *Xact_callbacks = NULL;
212 static void (*_RollbackFunc) (void *) = NULL;
213 static void *_RollbackData = NULL;
216 /* ----------------------------------------------------------------
217 * transaction state accessors
218 * ----------------------------------------------------------------
224 * This returns true if we are currently running a query
225 * within an executing transaction.
228 IsTransactionState(void)
230 TransactionState s = CurrentTransactionState;
238 case TRANS_INPROGRESS:
247 * Shouldn't get here, but lint is not happy with this...
253 * IsAbortedTransactionBlockState
255 * This returns true if we are currently running a query
256 * within an aborted transaction block.
259 IsAbortedTransactionBlockState(void)
261 TransactionState s = CurrentTransactionState;
263 if (s->blockState == TBLOCK_ABORT ||
264 s->blockState == TBLOCK_SUBABORT)
272 * GetTopTransactionId
274 * Get the ID of the main transaction, even if we are currently inside
278 GetTopTransactionId(void)
280 return TopTransactionStateData.transactionIdData;
285 * GetCurrentTransactionId
288 GetCurrentTransactionId(void)
290 TransactionState s = CurrentTransactionState;
292 return s->transactionIdData;
297 * GetCurrentCommandId
300 GetCurrentCommandId(void)
302 TransactionState s = CurrentTransactionState;
309 * GetCurrentTransactionStartTime
312 GetCurrentTransactionStartTime(void)
314 return xactStartTime;
319 * GetCurrentTransactionStartTimeUsec
322 GetCurrentTransactionStartTimeUsec(int *msec)
324 *msec = xactStartTimeUsec;
325 return xactStartTime;
330 * GetCurrentTransactionNestLevel
332 * Note: this will return zero when not inside any transaction, one when
333 * inside a top-level transaction, etc.
336 GetCurrentTransactionNestLevel(void)
338 TransactionState s = CurrentTransactionState;
340 return s->nestingLevel;
345 * TransactionIdIsCurrentTransactionId
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.
353 TransactionIdIsCurrentTransactionId(TransactionId xid)
355 TransactionState s = CurrentTransactionState;
359 Assert(xid == BootstrapTransactionId);
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.
372 if (TransactionIdEquals(xid, s->transactionIdData))
374 foreach(cell, s->childXids)
376 if (TransactionIdEquals(xid, lfirst_xid(cell)))
388 * CommandCounterIncrement
391 CommandCounterIncrement(void)
393 TransactionState s = CurrentTransactionState;
396 if (s->commandId == FirstCommandId) /* check for overflow */
398 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
399 errmsg("cannot have more than 2^32-1 commands in a transaction")));
401 /* Propagate new command ID into query snapshots, if set */
403 QuerySnapshot->curcid = s->commandId;
404 if (SerializableSnapshot)
405 SerializableSnapshot->curcid = s->commandId;
408 * make cache changes visible to me.
410 AtCommit_LocalCache();
415 /* ----------------------------------------------------------------
416 * StartTransaction stuff
417 * ----------------------------------------------------------------
426 AcceptInvalidationMessages();
435 TransactionState s = CurrentTransactionState;
438 * We shouldn't have a transaction context already.
440 Assert(TopTransactionContext == NULL);
443 * Create a toplevel context for the transaction.
445 TopTransactionContext =
446 AllocSetContextCreate(TopMemoryContext,
447 "TopTransactionContext",
448 ALLOCSET_DEFAULT_MINSIZE,
449 ALLOCSET_DEFAULT_INITSIZE,
450 ALLOCSET_DEFAULT_MAXSIZE);
453 * In a top-level transaction, CurTransactionContext is the same as
454 * TopTransactionContext.
456 CurTransactionContext = TopTransactionContext;
457 s->curTransactionContext = CurTransactionContext;
459 /* Make the CurTransactionContext active. */
460 MemoryContextSwitchTo(CurTransactionContext);
464 * AtStart_ResourceOwner
467 AtStart_ResourceOwner(void)
469 TransactionState s = CurrentTransactionState;
472 * We shouldn't have a transaction resource owner already.
474 Assert(TopTransactionResourceOwner == NULL);
477 * Create a toplevel resource owner for the transaction.
479 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
481 TopTransactionResourceOwner = s->curTransactionOwner;
482 CurTransactionResourceOwner = s->curTransactionOwner;
483 CurrentResourceOwner = s->curTransactionOwner;
486 /* ----------------------------------------------------------------
487 * StartSubTransaction stuff
488 * ----------------------------------------------------------------
495 AtSubStart_Memory(void)
497 TransactionState s = CurrentTransactionState;
499 Assert(CurTransactionContext != NULL);
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.
506 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
507 "CurTransactionContext",
508 ALLOCSET_DEFAULT_MINSIZE,
509 ALLOCSET_DEFAULT_INITSIZE,
510 ALLOCSET_DEFAULT_MAXSIZE);
511 s->curTransactionContext = CurTransactionContext;
513 /* Make the CurTransactionContext active. */
514 MemoryContextSwitchTo(CurTransactionContext);
518 * AtSubStart_ResourceOwner
521 AtSubStart_ResourceOwner(void)
523 TransactionState s = CurrentTransactionState;
525 Assert(s->parent != NULL);
528 * Create a resource owner for the subtransaction. We make it a
529 * child of the immediate parent's resource owner.
531 s->curTransactionOwner =
532 ResourceOwnerCreate(s->parent->curTransactionOwner,
535 CurTransactionResourceOwner = s->curTransactionOwner;
536 CurrentResourceOwner = s->curTransactionOwner;
539 /* ----------------------------------------------------------------
540 * CommitTransaction stuff
541 * ----------------------------------------------------------------
545 * RecordTransactionCommit
548 RecordTransactionCommit(void)
553 TransactionId *children;
555 /* Get data needed for commit record */
556 nrels = smgrGetPendingDeletes(true, &rptr);
557 nchildren = xactGetCommittedChildren(&children);
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.)
565 if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0)
567 TransactionId xid = GetCurrentTransactionId();
571 /* Tell bufmgr and smgr to prepare for commit */
574 START_CRIT_SECTION();
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
583 madeTCentries = (MyLastRecPtr.xrecoff != 0);
584 if (madeTCentries || nrels > 0)
586 XLogRecData rdata[3];
588 xl_xact_commit xlrec;
590 xlrec.xtime = time(NULL);
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 */
599 rdata[0].next = &(rdata[1]);
600 rdata[1].buffer = InvalidBuffer;
601 rdata[1].data = (char *) rptr;
602 rdata[1].len = nrels * sizeof(RelFileNode);
605 /* dump committed child Xids */
608 rdata[lastrdata].next = &(rdata[2]);
609 rdata[2].buffer = InvalidBuffer;
610 rdata[2].data = (char *) children;
611 rdata[2].len = nchildren * sizeof(TransactionId);
614 rdata[lastrdata].next = NULL;
616 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
620 /* Just flush through last record written by me */
621 recptr = ProcLastRecEnd;
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.
631 * Note: if we generated a commit record above, MyXactMadeXLogEntry
632 * will certainly be set now.
634 if (MyXactMadeXLogEntry)
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.)
643 * We do not sleep if enableFsync is not turned on, nor if there
644 * are fewer than CommitSiblings other backends with active
647 if (CommitDelay > 0 && enableFsync &&
648 CountActiveBackends() >= CommitSiblings)
649 pg_usleep(CommitDelay);
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
664 if (madeTCentries || MyXactMadeTempRelUpdate)
666 TransactionIdCommit(xid);
667 /* to avoid race conditions, the parent must commit first */
668 TransactionIdCommitTree(nchildren, children);
674 /* Break the chain of back-links in the XLOG records I output */
675 MyLastRecPtr.xrecoff = 0;
676 MyXactMadeXLogEntry = false;
677 MyXactMadeTempRelUpdate = false;
679 /* Show myself as out of the transaction in PGPROC array */
680 MyProc->logRec.xrecoff = 0;
682 /* And clean up local data */
691 * AtCommit_LocalCache
694 AtCommit_LocalCache(void)
697 * Make catalog changes visible to me for the next command.
699 CommandEndInvalidationMessages();
706 AtCommit_Memory(void)
709 * Now that we're "out" of a transaction, have the system allocate
710 * things in the top memory context instead of per-transaction
713 MemoryContextSwitchTo(TopMemoryContext);
716 * Release all transaction-local memory.
718 Assert(TopTransactionContext != NULL);
719 MemoryContextDelete(TopTransactionContext);
720 TopTransactionContext = NULL;
721 CurTransactionContext = NULL;
722 CurrentTransactionState->curTransactionContext = NULL;
725 /* ----------------------------------------------------------------
726 * CommitSubTransaction stuff
727 * ----------------------------------------------------------------
733 * We do not throw away the child's CurTransactionContext, since the data
734 * it contains will be needed at upper commit.
737 AtSubCommit_Memory(void)
739 TransactionState s = CurrentTransactionState;
741 Assert(s->parent != NULL);
743 /* Return to parent transaction level's memory context. */
744 CurTransactionContext = s->parent->curTransactionContext;
745 MemoryContextSwitchTo(CurTransactionContext);
749 * AtSubCommit_childXids
751 * Pass my own XID and my child XIDs up to my parent as committed children.
754 AtSubCommit_childXids(void)
756 TransactionState s = CurrentTransactionState;
757 MemoryContext old_cxt;
759 Assert(s->parent != NULL);
761 old_cxt = MemoryContextSwitchTo(s->parent->curTransactionContext);
763 s->parent->childXids = lappend_xid(s->parent->childXids,
764 s->transactionIdData);
766 s->parent->childXids = list_concat(s->parent->childXids, s->childXids);
767 s->childXids = NIL; /* ensure list not doubly referenced */
769 MemoryContextSwitchTo(old_cxt);
773 * RecordSubTransactionCommit
776 RecordSubTransactionCommit(void)
779 * We do not log the subcommit in XLOG; it doesn't matter until
780 * the top-level transaction commits.
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...)
791 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate)
793 TransactionId xid = GetCurrentTransactionId();
795 /* XXX does this really need to be a critical section? */
796 START_CRIT_SECTION();
798 /* Record subtransaction subcommit */
799 TransactionIdSubCommit(xid);
805 /* ----------------------------------------------------------------
806 * AbortTransaction stuff
807 * ----------------------------------------------------------------
811 * RecordTransactionAbort
814 RecordTransactionAbort(void)
819 TransactionId *children;
821 /* Get data needed for abort record */
822 nrels = smgrGetPendingDeletes(false, &rptr);
823 nchildren = xactGetCommittedChildren(&children);
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.)
831 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
833 TransactionId xid = GetCurrentTransactionId();
836 * Catch the scenario where we aborted partway through
837 * RecordTransactionCommit ...
839 if (TransactionIdDidCommit(xid))
840 elog(PANIC, "cannot abort transaction %u, it was already committed", xid);
842 START_CRIT_SECTION();
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
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.
854 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
856 XLogRecData rdata[3];
861 xlrec.xtime = time(NULL);
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 */
870 rdata[0].next = &(rdata[1]);
871 rdata[1].buffer = InvalidBuffer;
872 rdata[1].data = (char *) rptr;
873 rdata[1].len = nrels * sizeof(RelFileNode);
876 /* dump committed child Xids */
879 rdata[lastrdata].next = &(rdata[2]);
880 rdata[2].buffer = InvalidBuffer;
881 rdata[2].data = (char *) children;
882 rdata[2].len = nchildren * sizeof(TransactionId);
885 rdata[lastrdata].next = NULL;
887 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
889 /* Must flush if we are deleting files... */
895 * Mark the transaction aborted in clog. This is not absolutely
896 * necessary but we may as well do it while we are here.
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
903 TransactionIdAbortTree(nchildren, children);
904 TransactionIdAbort(xid);
909 /* Break the chain of back-links in the XLOG records I output */
910 MyLastRecPtr.xrecoff = 0;
911 MyXactMadeXLogEntry = false;
912 MyXactMadeTempRelUpdate = false;
914 /* Show myself as out of the transaction in PGPROC array */
915 MyProc->logRec.xrecoff = 0;
917 /* And clean up local data */
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.
936 if (TopTransactionContext != NULL)
938 MemoryContextSwitchTo(TopTransactionContext);
941 * We do not want to destroy the transaction's global state yet,
942 * so we can't free any memory here.
946 MemoryContextSwitchTo(TopMemoryContext);
954 AtSubAbort_Memory(void)
956 Assert(TopTransactionContext != NULL);
958 MemoryContextSwitchTo(TopTransactionContext);
962 * RecordSubTransactionAbort
965 RecordSubTransactionAbort(void)
969 TransactionId xid = GetCurrentTransactionId();
971 TransactionId *children;
973 /* Get data needed for abort record */
974 nrels = smgrGetPendingDeletes(false, &rptr);
975 nchildren = xactGetCommittedChildren(&children);
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.)
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.
989 if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
991 START_CRIT_SECTION();
994 * We only need to log the abort in XLOG if the transaction made
995 * any transaction-controlled XLOG entries or will delete files.
997 if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
999 XLogRecData rdata[3];
1001 xl_xact_abort xlrec;
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 */
1013 rdata[0].next = &(rdata[1]);
1014 rdata[1].buffer = InvalidBuffer;
1015 rdata[1].data = (char *) rptr;
1016 rdata[1].len = nrels * sizeof(RelFileNode);
1019 /* dump committed child Xids */
1022 rdata[lastrdata].next = &(rdata[2]);
1023 rdata[2].buffer = InvalidBuffer;
1024 rdata[2].data = (char *) children;
1025 rdata[2].len = nchildren * sizeof(TransactionId);
1028 rdata[lastrdata].next = NULL;
1030 recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1032 /* Must flush if we are deleting files... */
1038 * Mark the transaction aborted in clog. This is not absolutely
1039 * necessary but we may as well do it while we are here.
1041 TransactionIdAbortTree(nchildren, children);
1042 TransactionIdAbort(xid);
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.
1054 XidCacheRemoveRunningXids(xid, nchildren, children);
1056 /* And clean up local data */
1063 /* ----------------------------------------------------------------
1064 * CleanupTransaction stuff
1065 * ----------------------------------------------------------------
1072 AtCleanup_Memory(void)
1075 * Now that we're "out" of a transaction, have the system allocate
1076 * things in the top memory context instead of per-transaction
1079 MemoryContextSwitchTo(TopMemoryContext);
1081 Assert(CurrentTransactionState->parent == NULL);
1084 * Release all transaction-local memory.
1086 if (TopTransactionContext != NULL)
1087 MemoryContextDelete(TopTransactionContext);
1088 TopTransactionContext = NULL;
1089 CurTransactionContext = NULL;
1090 CurrentTransactionState->curTransactionContext = NULL;
1094 /* ----------------------------------------------------------------
1095 * CleanupSubTransaction stuff
1096 * ----------------------------------------------------------------
1100 * AtSubCleanup_Memory
1103 AtSubCleanup_Memory(void)
1105 TransactionState s = CurrentTransactionState;
1107 Assert(s->parent != NULL);
1109 /* Make sure we're not in an about-to-be-deleted context */
1110 MemoryContextSwitchTo(s->parent->curTransactionContext);
1111 CurTransactionContext = s->parent->curTransactionContext;
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).
1118 MemoryContextDelete(s->curTransactionContext);
1121 /* ----------------------------------------------------------------
1122 * interface routines
1123 * ----------------------------------------------------------------
1130 StartTransaction(void)
1132 TransactionState s = CurrentTransactionState;
1135 * check the current transaction state
1137 if (s->state != TRANS_DEFAULT)
1138 elog(WARNING, "StartTransaction while in %s state",
1139 TransStateAsString(s->state));
1142 * set the current transaction state information appropriately during
1145 s->state = TRANS_START;
1148 * Make sure we've freed any old snapshot, and reset xact state variables
1151 XactIsoLevel = DefaultXactIsoLevel;
1152 XactReadOnly = DefaultXactReadOnly;
1155 * must initialize resource-management stuff first
1158 AtStart_ResourceOwner();
1161 * generate a new transaction id
1163 s->transactionIdData = GetNewTransactionId(false);
1165 XactLockTableInsert(s->transactionIdData);
1170 xactStartTime = GetCurrentAbsoluteTimeUsec(&(xactStartTimeUsec));
1173 * initialize current transaction state fields
1175 s->commandId = FirstCommandId;
1176 s->nestingLevel = 1;
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.
1185 * prevXactReadOnly is also valid only in sub-transactions.
1189 * initialize other subsystems for new transaction
1193 DeferredTriggerBeginXact();
1196 * done with start processing, set current transaction state to "in
1199 s->state = TRANS_INPROGRESS;
1201 ShowTransactionState("StartTransaction");
1208 CommitTransaction(void)
1210 TransactionState s = CurrentTransactionState;
1212 ShowTransactionState("CommitTransaction");
1215 * check the current transaction state
1217 if (s->state != TRANS_INPROGRESS)
1218 elog(WARNING, "CommitTransaction while in %s state",
1219 TransStateAsString(s->state));
1220 Assert(s->parent == NULL);
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.
1227 DeferredTriggerEndXact();
1230 * Similarly, let ON COMMIT management do its thing before we start to
1233 PreCommit_on_commit_actions();
1235 /* Prevent cancel/die interrupt while cleaning up */
1239 * set the current transaction state information appropriately during
1240 * the abort processing
1242 s->state = TRANS_COMMIT;
1245 * Do pre-commit processing (most of this stuff requires database
1246 * access, and in fact could still cause an error...)
1251 /* close large objects before lower-level cleanup */
1252 AtEOXact_LargeObject(true);
1254 /* NOTIFY commit must come before lower-level cleanup */
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);
1262 * Here is where we really truly commit.
1264 RecordTransactionCommit();
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.
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.
1279 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1280 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1281 MyProc->xid = InvalidTransactionId;
1282 MyProc->xmin = InvalidTransactionId;
1284 /* Clear the subtransaction-XID cache too while holding the lock */
1285 MyProc->subxids.nxids = 0;
1286 MyProc->subxids.overflowed = false;
1288 LWLockRelease(SInvalLock);
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.
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.
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.
1307 smgrDoPendingDeletes(true);
1308 /* smgrcommit already done */
1310 CallXactCallbacks(XACT_EVENT_COMMIT, InvalidTransactionId);
1312 ResourceOwnerRelease(TopTransactionResourceOwner,
1313 RESOURCE_RELEASE_BEFORE_LOCKS,
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).
1323 AtEOXact_Inval(true);
1325 ResourceOwnerRelease(TopTransactionResourceOwner,
1326 RESOURCE_RELEASE_LOCKS,
1328 ResourceOwnerRelease(TopTransactionResourceOwner,
1329 RESOURCE_RELEASE_AFTER_LOCKS,
1332 AtEOXact_GUC(true, false);
1334 AtEOXact_on_commit_actions(true, s->transactionIdData);
1335 AtEOXact_Namespace(true);
1337 pgstat_count_xact_commit();
1339 CurrentResourceOwner = NULL;
1340 ResourceOwnerDelete(TopTransactionResourceOwner);
1341 s->curTransactionOwner = NULL;
1342 CurTransactionResourceOwner = NULL;
1343 TopTransactionResourceOwner = NULL;
1347 s->nestingLevel = 0;
1351 * done with commit processing, set current transaction state back to
1354 s->state = TRANS_DEFAULT;
1356 RESUME_INTERRUPTS();
1363 AbortTransaction(void)
1365 TransactionState s = CurrentTransactionState;
1367 /* Prevent cancel/die interrupt while cleaning up */
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!
1378 /* Clean up buffer I/O and buffer context locks, too */
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.
1389 * check the current transaction state
1391 if (s->state != TRANS_INPROGRESS)
1392 elog(WARNING, "AbortTransaction while in %s state",
1393 TransStateAsString(s->state));
1394 Assert(s->parent == NULL);
1397 * set the current transaction state information appropriately during
1398 * the abort processing
1400 s->state = TRANS_ABORT;
1402 /* Make sure we are in a valid memory context */
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.
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
1415 SetUserId(GetSessionUserId());
1418 * do abort processing
1420 DeferredTriggerAbortXact();
1422 AtEOXact_LargeObject(false); /* 'false' means it's abort */
1424 AtEOXact_UpdatePasswordFile(false);
1426 /* Advertise the fact that we aborted in pg_clog. */
1427 RecordTransactionAbort();
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.
1436 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1437 LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
1438 MyProc->xid = InvalidTransactionId;
1439 MyProc->xmin = InvalidTransactionId;
1441 /* Clear the subtransaction-XID cache too while holding the lock */
1442 MyProc->subxids.nxids = 0;
1443 MyProc->subxids.overflowed = false;
1445 LWLockRelease(SInvalLock);
1449 * Post-abort cleanup. See notes in CommitTransaction() concerning
1453 smgrDoPendingDeletes(false);
1456 CallXactCallbacks(XACT_EVENT_ABORT, InvalidTransactionId);
1458 ResourceOwnerRelease(TopTransactionResourceOwner,
1459 RESOURCE_RELEASE_BEFORE_LOCKS,
1461 AtEOXact_Inval(false);
1462 ResourceOwnerRelease(TopTransactionResourceOwner,
1463 RESOURCE_RELEASE_LOCKS,
1465 ResourceOwnerRelease(TopTransactionResourceOwner,
1466 RESOURCE_RELEASE_AFTER_LOCKS,
1469 AtEOXact_GUC(false, false);
1470 AtEOXact_SPI(false);
1471 AtEOXact_on_commit_actions(false, s->transactionIdData);
1472 AtEOXact_Namespace(false);
1474 pgstat_count_xact_rollback();
1477 * State remains TRANS_ABORT until CleanupTransaction().
1479 RESUME_INTERRUPTS();
1483 * CleanupTransaction
1486 CleanupTransaction(void)
1488 TransactionState s = CurrentTransactionState;
1491 * State should still be TRANS_ABORT from AbortTransaction().
1493 if (s->state != TRANS_ABORT)
1494 elog(FATAL, "CleanupTransaction: unexpected state %s",
1495 TransStateAsString(s->state));
1498 * do abort cleanup processing
1500 AtCleanup_Portals(); /* now safe to release portal memory */
1502 CurrentResourceOwner = NULL; /* and resource owner */
1503 ResourceOwnerDelete(TopTransactionResourceOwner);
1504 s->curTransactionOwner = NULL;
1505 CurTransactionResourceOwner = NULL;
1506 TopTransactionResourceOwner = NULL;
1508 AtCleanup_Memory(); /* and transaction memory */
1510 s->nestingLevel = 0;
1514 * done with abort processing, set current transaction state back to
1517 s->state = TRANS_DEFAULT;
1521 * StartTransactionCommand
1524 StartTransactionCommand(void)
1526 TransactionState s = CurrentTransactionState;
1528 switch (s->blockState)
1531 * if we aren't in a transaction block, we just do our usual
1532 * start transaction.
1534 case TBLOCK_DEFAULT:
1536 s->blockState = TBLOCK_STARTED;
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.
1544 case TBLOCK_INPROGRESS:
1545 case TBLOCK_SUBINPROGRESS:
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.
1555 case TBLOCK_SUBABORT:
1558 /* These cases are invalid. */
1559 case TBLOCK_STARTED:
1561 case TBLOCK_SUBBEGIN:
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));
1575 * We must switch to CurTransactionContext before returning. This is
1576 * already done if we called StartTransaction, otherwise not.
1578 Assert(CurTransactionContext != NULL);
1579 MemoryContextSwitchTo(CurTransactionContext);
1583 * CommitTransactionCommand
1586 CommitTransactionCommand(void)
1588 TransactionState s = CurrentTransactionState;
1590 switch (s->blockState)
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
1598 case TBLOCK_DEFAULT:
1599 case TBLOCK_SUBABORT_PENDING:
1600 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
1601 BlockStateAsString(s->blockState));
1605 * If we aren't in a transaction block, just do our usual
1606 * transaction commit.
1608 case TBLOCK_STARTED:
1609 CommitTransaction();
1610 s->blockState = TBLOCK_DEFAULT;
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
1620 s->blockState = TBLOCK_INPROGRESS;
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.
1628 case TBLOCK_INPROGRESS:
1629 CommandCounterIncrement();
1633 * This is the case when we just got the "END TRANSACTION"
1634 * statement, so we commit the transaction and go back to the
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;
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.
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.
1662 case TBLOCK_ENDABORT:
1663 CleanupTransaction();
1664 s->blockState = TBLOCK_DEFAULT;
1668 * Ditto, but in a subtransaction. AbortOutOfAnyTransaction
1669 * will do the dirty work.
1671 case TBLOCK_SUBENDABORT_ALL:
1672 AbortOutOfAnyTransaction();
1673 s = CurrentTransactionState; /* changed by AbortOutOfAnyTransaction */
1674 /* AbortOutOfAnyTransaction sets the blockState */
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
1683 case TBLOCK_SUBBEGIN:
1684 StartSubTransaction();
1685 s->blockState = TBLOCK_SUBINPROGRESS;
1689 * Inside a subtransaction, increment the command counter.
1691 case TBLOCK_SUBINPROGRESS:
1692 CommandCounterIncrement();
1696 * We were issued a RELEASE command, so we end the current
1697 * subtransaction and return to the parent transaction.
1700 CommitSubTransaction();
1702 s = CurrentTransactionState; /* changed by pop */
1706 * If we are in an aborted subtransaction, do nothing.
1708 case TBLOCK_SUBABORT:
1712 * The current subtransaction is ending. Do the equivalent
1713 * of a ROLLBACK TO followed by a RELEASE command.
1715 case TBLOCK_SUBENDABORT_RELEASE:
1716 CleanupAbortedSubTransactions(false);
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.
1724 case TBLOCK_SUBENDABORT:
1726 char *name = CleanupAbortedSubTransactions(true);
1728 Assert(PointerIsValid(name));
1729 DefineSavepoint(name);
1730 s = CurrentTransactionState; /* changed by DefineSavepoint */
1733 /* This is the same as TBLOCK_SUBBEGIN case */
1734 AssertState(s->blockState == TBLOCK_SUBBEGIN);
1735 StartSubTransaction();
1736 s->blockState = TBLOCK_SUBINPROGRESS;
1743 * CleanupAbortedSubTransactions
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.)
1751 CleanupAbortedSubTransactions(bool returnName)
1753 TransactionState s = CurrentTransactionState;
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);
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.
1767 if (returnName && s->parent->blockState != TBLOCK_SUBABORT_PENDING)
1768 name = MemoryContextStrdup(TopMemoryContext, s->name);
1770 CleanupSubTransaction();
1772 s = CurrentTransactionState; /* changed by pop */
1774 while (s->blockState == TBLOCK_SUBABORT_PENDING)
1776 AbortSubTransaction();
1777 if (returnName && s->parent->blockState != TBLOCK_SUBABORT_PENDING)
1778 name = MemoryContextStrdup(TopMemoryContext, s->name);
1779 CleanupSubTransaction();
1781 s = CurrentTransactionState;
1784 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
1785 s->blockState == TBLOCK_INPROGRESS ||
1786 s->blockState == TBLOCK_STARTED);
1792 * AbortCurrentTransaction
1795 AbortCurrentTransaction(void)
1797 TransactionState s = CurrentTransactionState;
1799 switch (s->blockState)
1802 * we aren't in a transaction, so we do nothing.
1804 case TBLOCK_DEFAULT:
1808 * if we aren't in a transaction block, we just do the basic
1809 * abort & cleanup transaction.
1811 case TBLOCK_STARTED:
1813 CleanupTransaction();
1814 s->blockState = TBLOCK_DEFAULT;
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
1825 s->blockState = TBLOCK_ABORT;
1826 /* CleanupTransaction happens when we exit TBLOCK_ENDABORT */
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".
1835 case TBLOCK_INPROGRESS:
1837 s->blockState = TBLOCK_ABORT;
1838 /* CleanupTransaction happens when we exit TBLOCK_ENDABORT */
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.
1848 CleanupTransaction();
1849 s->blockState = TBLOCK_DEFAULT;
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
1859 case TBLOCK_SUBABORT:
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.
1868 case TBLOCK_ENDABORT:
1869 CleanupTransaction();
1870 s->blockState = TBLOCK_DEFAULT;
1874 * If we are just starting a subtransaction, put it
1877 case TBLOCK_SUBBEGIN:
1878 StartAbortedSubTransaction();
1879 s->blockState = TBLOCK_SUBABORT;
1882 case TBLOCK_SUBINPROGRESS:
1883 AbortSubTransaction();
1884 s->blockState = TBLOCK_SUBABORT;
1888 * If we are aborting an ending transaction,
1889 * we have to abort the parent transaction too.
1892 case TBLOCK_SUBABORT_PENDING:
1893 AbortSubTransaction();
1894 CleanupSubTransaction();
1896 s = CurrentTransactionState; /* changed by pop */
1897 Assert(s->blockState != TBLOCK_SUBEND &&
1898 s->blockState != TBLOCK_SUBENDABORT);
1899 AbortCurrentTransaction();
1903 * Same as above, except the Abort() was already done.
1905 case TBLOCK_SUBENDABORT:
1906 case TBLOCK_SUBENDABORT_RELEASE:
1907 CleanupSubTransaction();
1909 s = CurrentTransactionState; /* changed by pop */
1910 Assert(s->blockState != TBLOCK_SUBEND &&
1911 s->blockState != TBLOCK_SUBENDABORT);
1912 AbortCurrentTransaction();
1916 * We are already aborting the whole transaction tree.
1917 * Do nothing, CommitTransactionCommand will call
1918 * AbortOutOfAnyTransaction and set things straight.
1920 case TBLOCK_SUBENDABORT_ALL:
1926 * PreventTransactionChain
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.
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.
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.
1942 PreventTransactionChain(void *stmtNode, const char *stmtType)
1945 * xact block already started?
1947 if (IsTransactionBlock())
1949 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1950 /* translator: %s represents an SQL statement name */
1951 errmsg("%s cannot run inside a transaction block",
1957 if (IsSubTransaction())
1959 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1960 /* translator: %s represents an SQL statement name */
1961 errmsg("%s cannot run inside a subtransaction",
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.
1969 if (!MemoryContextContains(QueryContext, stmtNode))
1971 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
1972 /* translator: %s represents an SQL statement name */
1973 errmsg("%s cannot be executed from a function", stmtType)));
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");
1983 * RequireTransactionChain
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.
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.
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.
2000 RequireTransactionChain(void *stmtNode, const char *stmtType)
2003 * xact block already started?
2005 if (IsTransactionBlock())
2011 if (IsSubTransaction())
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.
2019 if (!MemoryContextContains(QueryContext, stmtNode))
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",
2029 * IsInTransactionChain
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.
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.
2039 IsInTransactionChain(void *stmtNode)
2042 * Return true on same conditions that would make PreventTransactionChain
2045 if (IsTransactionBlock())
2048 if (IsSubTransaction())
2051 if (!MemoryContextContains(QueryContext, stmtNode))
2054 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2055 CurrentTransactionState->blockState != TBLOCK_STARTED)
2063 * Register or deregister callback functions for start- and end-of-xact
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).
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
2076 RegisterXactCallback(XactCallback callback, void *arg)
2078 XactCallbackItem *item;
2080 item = (XactCallbackItem *)
2081 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2082 item->callback = callback;
2084 item->next = Xact_callbacks;
2085 Xact_callbacks = item;
2089 UnregisterXactCallback(XactCallback callback, void *arg)
2091 XactCallbackItem *item;
2092 XactCallbackItem *prev;
2095 for (item = Xact_callbacks; item; prev = item, item = item->next)
2097 if (item->callback == callback && item->arg == arg)
2100 prev->next = item->next;
2102 Xact_callbacks = item->next;
2110 CallXactCallbacks(XactEvent event, TransactionId parentXid)
2112 XactCallbackItem *item;
2114 for (item = Xact_callbacks; item; item = item->next)
2116 (*item->callback) (event, parentXid, item->arg);
2121 /* ----------------------------------------------------------------
2122 * transaction block support
2123 * ----------------------------------------------------------------
2127 * BeginTransactionBlock
2128 * This executes a BEGIN command.
2131 BeginTransactionBlock(void)
2133 TransactionState s = CurrentTransactionState;
2135 switch (s->blockState)
2138 * We are not inside a transaction block, so allow one
2141 case TBLOCK_STARTED:
2142 s->blockState = TBLOCK_BEGIN;
2146 * Already a transaction block in progress.
2148 case TBLOCK_INPROGRESS:
2149 case TBLOCK_SUBINPROGRESS:
2151 case TBLOCK_SUBABORT:
2153 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2154 errmsg("there is already a transaction in progress")));
2157 /* These cases are invalid. Reject them altogether. */
2158 case TBLOCK_DEFAULT:
2160 case TBLOCK_SUBBEGIN:
2161 case TBLOCK_ENDABORT:
2163 case TBLOCK_SUBENDABORT_ALL:
2164 case TBLOCK_SUBENDABORT:
2165 case TBLOCK_SUBABORT_PENDING:
2166 case TBLOCK_SUBENDABORT_RELEASE:
2168 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2169 BlockStateAsString(s->blockState));
2175 * EndTransactionBlock
2176 * This executes a COMMIT command.
2178 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2179 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2182 EndTransactionBlock(void)
2184 TransactionState s = CurrentTransactionState;
2185 bool result = false;
2187 switch (s->blockState)
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.
2195 case TBLOCK_INPROGRESS:
2196 case TBLOCK_SUBINPROGRESS:
2197 s->blockState = TBLOCK_END;
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.
2209 s->blockState = TBLOCK_ENDABORT;
2213 * Here we are inside an aborted subtransaction. Go to the "abort
2214 * the whole tree" state so that CommitTransactionCommand() calls
2215 * AbortOutOfAnyTransaction.
2217 case TBLOCK_SUBABORT:
2218 s->blockState = TBLOCK_SUBENDABORT_ALL;
2221 case TBLOCK_STARTED:
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.
2229 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2230 errmsg("there is no transaction in progress")));
2232 s->blockState = TBLOCK_ENDABORT;
2235 /* these cases are invalid. */
2236 case TBLOCK_DEFAULT:
2238 case TBLOCK_ENDABORT:
2240 case TBLOCK_SUBBEGIN:
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));
2255 * UserAbortTransactionBlock
2256 * This executes a ROLLBACK command.
2259 UserAbortTransactionBlock(void)
2261 TransactionState s = CurrentTransactionState;
2263 switch (s->blockState)
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().
2273 s->blockState = TBLOCK_ENDABORT;
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.
2283 case TBLOCK_SUBABORT:
2284 s->blockState = TBLOCK_SUBENDABORT_ALL;
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().
2293 case TBLOCK_INPROGRESS:
2295 s->blockState = TBLOCK_ENDABORT;
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.
2304 case TBLOCK_SUBINPROGRESS:
2305 AbortSubTransaction();
2306 s->blockState = TBLOCK_SUBENDABORT_ALL;
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
2315 case TBLOCK_STARTED:
2317 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2318 errmsg("there is no transaction in progress")));
2320 s->blockState = TBLOCK_ENDABORT;
2323 /* These cases are invalid. */
2324 case TBLOCK_DEFAULT:
2327 case TBLOCK_ENDABORT:
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));
2342 * This executes a SAVEPOINT command.
2345 DefineSavepoint(char *name)
2347 TransactionState s = CurrentTransactionState;
2349 switch (s->blockState)
2351 case TBLOCK_INPROGRESS:
2352 case TBLOCK_SUBINPROGRESS:
2353 /* Normal subtransaction start */
2355 s = CurrentTransactionState; /* changed by push */
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.
2361 s->name = MemoryContextStrdup(CurTransactionContext, name);
2362 s->blockState = TBLOCK_SUBBEGIN;
2365 /* These cases are invalid. Reject them altogether. */
2366 case TBLOCK_DEFAULT:
2367 case TBLOCK_STARTED:
2369 case TBLOCK_SUBBEGIN:
2371 case TBLOCK_SUBABORT:
2372 case TBLOCK_ENDABORT:
2374 case TBLOCK_SUBENDABORT_ALL:
2375 case TBLOCK_SUBENDABORT:
2376 case TBLOCK_SUBABORT_PENDING:
2377 case TBLOCK_SUBENDABORT_RELEASE:
2379 elog(FATAL, "DefineSavepoint: unexpected state %s",
2380 BlockStateAsString(s->blockState));
2387 * This executes a RELEASE command.
2390 ReleaseSavepoint(List *options)
2392 TransactionState s = CurrentTransactionState;
2393 TransactionState target = s;
2398 * Check valid block state transaction status.
2400 switch (s->blockState)
2402 case TBLOCK_INPROGRESS:
2405 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2406 errmsg("no such savepoint")));
2410 * We are in a non-aborted subtransaction. This is
2411 * the only valid case.
2413 case TBLOCK_SUBINPROGRESS:
2416 /* these cases are invalid. */
2417 case TBLOCK_DEFAULT:
2418 case TBLOCK_STARTED:
2420 case TBLOCK_ENDABORT:
2422 case TBLOCK_SUBABORT:
2423 case TBLOCK_SUBBEGIN:
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));
2434 foreach (cell, options)
2436 DefElem *elem = lfirst(cell);
2438 if (strcmp(elem->defname, "savepoint_name") == 0)
2439 name = strVal(elem->arg);
2442 Assert(PointerIsValid(name));
2444 while (target != NULL)
2446 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
2448 target = target->parent;
2451 if (!PointerIsValid(target))
2453 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2454 errmsg("no such savepoint")));
2456 CommitTransactionToLevel(target->nestingLevel);
2460 * RollbackToSavepoint
2461 * This executes a ROLLBACK TO <savepoint> command.
2464 RollbackToSavepoint(List *options)
2466 TransactionState s = CurrentTransactionState;
2467 TransactionState target,
2472 switch (s->blockState)
2475 * We can't rollback to a savepoint if there is no saveopint
2479 case TBLOCK_INPROGRESS:
2481 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2482 errmsg("no such savepoint")));
2486 * There is at least one savepoint, so proceed.
2488 case TBLOCK_SUBABORT:
2489 case TBLOCK_SUBINPROGRESS:
2491 * Have to do AbortSubTransaction, but first check
2492 * if this is the right subtransaction
2496 /* these cases are invalid. */
2497 case TBLOCK_DEFAULT:
2498 case TBLOCK_STARTED:
2501 case TBLOCK_ENDABORT:
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));
2513 foreach (cell, options)
2515 DefElem *elem = lfirst(cell);
2517 if (strcmp(elem->defname, "savepoint_name") == 0)
2518 name = strVal(elem->arg);
2521 Assert(PointerIsValid(name));
2523 for (target = s; PointerIsValid(target); target = target->parent)
2525 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
2529 if (!PointerIsValid(target))
2531 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2532 errmsg("no such savepoint")));
2534 /* disallow crossing savepoint level boundaries */
2535 if (target->savepointLevel != s->savepointLevel)
2537 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
2538 errmsg("no such savepoint")));
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.
2545 if (s->blockState == TBLOCK_SUBINPROGRESS)
2546 AbortSubTransaction();
2547 s->blockState = TBLOCK_SUBENDABORT;
2550 * Mark "abort pending" all subtransactions up to the target
2551 * subtransaction. (Except the current subtransaction!)
2553 xact = CurrentTransactionState;
2555 while (xact != target)
2557 xact = xact->parent;
2558 Assert(PointerIsValid(xact));
2559 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
2560 xact->blockState = TBLOCK_SUBABORT_PENDING;
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.
2572 * Optionally, name can be NULL to create an unnamed savepoint.
2575 BeginInternalSubTransaction(char *name)
2577 TransactionState s = CurrentTransactionState;
2579 switch (s->blockState)
2581 case TBLOCK_STARTED:
2582 case TBLOCK_INPROGRESS:
2583 case TBLOCK_SUBINPROGRESS:
2584 /* Normal subtransaction start */
2586 s = CurrentTransactionState; /* changed by push */
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.
2593 s->name = MemoryContextStrdup(CurTransactionContext, name);
2594 s->blockState = TBLOCK_SUBBEGIN;
2597 /* These cases are invalid. Reject them altogether. */
2598 case TBLOCK_DEFAULT:
2600 case TBLOCK_SUBBEGIN:
2602 case TBLOCK_SUBABORT:
2603 case TBLOCK_ENDABORT:
2605 case TBLOCK_SUBENDABORT_ALL:
2606 case TBLOCK_SUBENDABORT:
2607 case TBLOCK_SUBABORT_PENDING:
2608 case TBLOCK_SUBENDABORT_RELEASE:
2610 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
2611 BlockStateAsString(s->blockState));
2615 CommitTransactionCommand();
2616 StartTransactionCommand();
2620 * ReleaseCurrentSubTransaction
2622 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
2623 * savepoint name (if any).
2624 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
2627 ReleaseCurrentSubTransaction(void)
2629 TransactionState s = CurrentTransactionState;
2631 if (s->blockState != TBLOCK_SUBINPROGRESS)
2632 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
2633 BlockStateAsString(s->blockState));
2634 MemoryContextSwitchTo(CurTransactionContext);
2635 CommitTransactionToLevel(GetCurrentTransactionNestLevel());
2639 * RollbackAndReleaseCurrentSubTransaction
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.
2646 RollbackAndReleaseCurrentSubTransaction(void)
2648 TransactionState s = CurrentTransactionState;
2650 switch (s->blockState)
2652 /* Must be in a subtransaction */
2653 case TBLOCK_SUBABORT:
2654 case TBLOCK_SUBINPROGRESS:
2657 /* these cases are invalid. */
2658 case TBLOCK_DEFAULT:
2659 case TBLOCK_STARTED:
2661 case TBLOCK_INPROGRESS:
2664 case TBLOCK_ENDABORT:
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));
2677 * Abort the current subtransaction, if needed.
2679 if (s->blockState == TBLOCK_SUBINPROGRESS)
2680 AbortSubTransaction();
2681 s->blockState = TBLOCK_SUBENDABORT_RELEASE;
2683 /* And clean it up, too */
2684 CleanupAbortedSubTransactions(false);
2688 * AbortOutOfAnyTransaction
2690 * This routine is provided for error recovery purposes. It aborts any
2691 * active transaction or transaction block, leaving the system in a known
2695 AbortOutOfAnyTransaction(void)
2697 TransactionState s = CurrentTransactionState;
2700 * Get out of any transaction or nested transaction
2703 switch (s->blockState)
2705 case TBLOCK_DEFAULT:
2706 /* Not in a transaction, do nothing */
2708 case TBLOCK_STARTED:
2710 case TBLOCK_INPROGRESS:
2712 /* In a transaction, so clean up */
2714 CleanupTransaction();
2715 s->blockState = TBLOCK_DEFAULT;
2718 case TBLOCK_ENDABORT:
2719 /* AbortTransaction already done, still need Cleanup */
2720 CleanupTransaction();
2721 s->blockState = TBLOCK_DEFAULT;
2723 case TBLOCK_SUBBEGIN:
2725 * We didn't get as far as starting the subxact, so there's
2726 * nothing to abort. Just pop back to parent.
2729 s = CurrentTransactionState; /* changed by pop */
2731 case TBLOCK_SUBINPROGRESS:
2733 case TBLOCK_SUBABORT_PENDING:
2734 /* In a subtransaction, so clean it up and abort parent too */
2735 AbortSubTransaction();
2736 CleanupSubTransaction();
2738 s = CurrentTransactionState; /* changed by pop */
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();
2747 s = CurrentTransactionState; /* changed by pop */
2750 } while (s->blockState != TBLOCK_DEFAULT);
2752 /* Should be out of all subxacts now */
2753 Assert(s->parent == NULL);
2757 * CommitTransactionToLevel
2759 * Commit everything from the current transaction level
2760 * up to the specified level (inclusive).
2763 CommitTransactionToLevel(int level)
2765 TransactionState s = CurrentTransactionState;
2767 Assert(s->state == TRANS_INPROGRESS);
2769 while (s->nestingLevel >= level)
2771 CommitSubTransaction();
2773 s = CurrentTransactionState; /* changed by pop */
2774 Assert(s->state == TRANS_INPROGRESS);
2779 * IsTransactionBlock --- are we within a transaction block?
2782 IsTransactionBlock(void)
2784 TransactionState s = CurrentTransactionState;
2786 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
2793 * IsTransactionOrTransactionBlock --- are we within either a transaction
2794 * or a transaction block? (The backend is only really "idle" when this
2797 * This should match up with IsTransactionBlock and IsTransactionState.
2800 IsTransactionOrTransactionBlock(void)
2802 TransactionState s = CurrentTransactionState;
2804 if (s->blockState == TBLOCK_DEFAULT)
2811 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
2814 TransactionBlockStatusCode(void)
2816 TransactionState s = CurrentTransactionState;
2818 switch (s->blockState)
2820 case TBLOCK_DEFAULT:
2821 case TBLOCK_STARTED:
2822 return 'I'; /* idle --- not in transaction */
2824 case TBLOCK_INPROGRESS:
2826 case TBLOCK_SUBINPROGRESS:
2827 case TBLOCK_SUBBEGIN:
2829 return 'T'; /* in transaction */
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 */
2840 /* should never get here */
2841 elog(FATAL, "invalid transaction block state: %s",
2842 BlockStateAsString(s->blockState));
2843 return 0; /* keep compiler quiet */
2850 IsSubTransaction(void)
2852 TransactionState s = CurrentTransactionState;
2854 if (s->nestingLevel >= 2)
2861 * StartSubTransaction
2864 StartSubTransaction(void)
2866 TransactionState s = CurrentTransactionState;
2868 if (s->state != TRANS_DEFAULT)
2869 elog(WARNING, "StartSubTransaction while in %s state",
2870 TransStateAsString(s->state));
2872 s->state = TRANS_START;
2875 * must initialize resource-management stuff first
2877 AtSubStart_Memory();
2878 AtSubStart_ResourceOwner();
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.
2886 s->transactionIdData = GetNewTransactionId(true);
2888 SubTransSetParent(s->transactionIdData, s->parent->transactionIdData);
2890 XactLockTableInsert(s->transactionIdData);
2893 * Finish setup of other transaction state fields.
2895 s->currentUser = GetUserId();
2896 s->prevXactReadOnly = XactReadOnly;
2899 * Initialize other subsystems for new subtransaction
2902 AtSubStart_Notify();
2903 DeferredTriggerBeginSubXact();
2905 s->state = TRANS_INPROGRESS;
2908 * Call start-of-subxact callbacks
2910 CallXactCallbacks(XACT_EVENT_START_SUB, s->parent->transactionIdData);
2912 ShowTransactionState("StartSubTransaction");
2916 * CommitSubTransaction
2919 CommitSubTransaction(void)
2921 TransactionState s = CurrentTransactionState;
2923 ShowTransactionState("CommitSubTransaction");
2925 if (s->state != TRANS_INPROGRESS)
2926 elog(WARNING, "CommitSubTransaction while in %s state",
2927 TransStateAsString(s->state));
2929 /* Pre-commit processing goes here -- nothing to do at the moment */
2931 s->state = TRANS_COMMIT;
2933 /* Mark subtransaction as subcommitted */
2934 CommandCounterIncrement();
2935 RecordSubTransactionCommit();
2936 AtSubCommit_childXids();
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);
2949 CallXactCallbacks(XACT_EVENT_COMMIT_SUB, s->parent->transactionIdData);
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.
2958 ResourceOwnerRelease(s->curTransactionOwner,
2959 RESOURCE_RELEASE_BEFORE_LOCKS,
2961 AtEOSubXact_Inval(true);
2962 /* we can skip the LOCKS phase */
2963 ResourceOwnerRelease(s->curTransactionOwner,
2964 RESOURCE_RELEASE_AFTER_LOCKS,
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);
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.
2981 XactReadOnly = s->prevXactReadOnly;
2983 CurrentResourceOwner = s->parent->curTransactionOwner;
2984 CurTransactionResourceOwner = s->parent->curTransactionOwner;
2985 s->curTransactionOwner = NULL;
2987 AtSubCommit_Memory();
2989 s->state = TRANS_DEFAULT;
2993 * AbortSubTransaction
2996 AbortSubTransaction(void)
2998 TransactionState s = CurrentTransactionState;
3000 ShowTransactionState("AbortSubTransaction");
3002 if (s->state != TRANS_INPROGRESS)
3003 elog(WARNING, "AbortSubTransaction while in %s state",
3004 TransStateAsString(s->state));
3008 s->state = TRANS_ABORT;
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!
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.
3027 * do abort processing
3029 AtSubAbort_Memory();
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);
3040 /* Advertise the fact that we aborted in pg_clog. */
3041 RecordSubTransactionAbort();
3043 /* Post-abort cleanup */
3046 CallXactCallbacks(XACT_EVENT_ABORT_SUB, s->parent->transactionIdData);
3048 ResourceOwnerRelease(s->curTransactionOwner,
3049 RESOURCE_RELEASE_BEFORE_LOCKS,
3051 AtEOSubXact_Inval(false);
3052 ResourceOwnerRelease(s->curTransactionOwner,
3053 RESOURCE_RELEASE_LOCKS,
3055 ResourceOwnerRelease(s->curTransactionOwner,
3056 RESOURCE_RELEASE_AFTER_LOCKS,
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);
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.)
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.
3080 SetUserId(s->currentUser);
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.
3087 XactReadOnly = s->prevXactReadOnly;
3089 RESUME_INTERRUPTS();
3093 * CleanupSubTransaction
3096 CleanupSubTransaction(void)
3098 TransactionState s = CurrentTransactionState;
3100 ShowTransactionState("CleanupSubTransaction");
3102 if (s->state != TRANS_ABORT)
3103 elog(WARNING, "CleanupSubTransaction while in %s state",
3104 TransStateAsString(s->state));
3106 AtSubCleanup_Portals();
3108 CurrentResourceOwner = s->parent->curTransactionOwner;
3109 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3110 ResourceOwnerDelete(s->curTransactionOwner);
3111 s->curTransactionOwner = NULL;
3113 AtSubCleanup_Memory();
3115 s->state = TRANS_DEFAULT;
3119 * StartAbortedSubTransaction
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.
3130 StartAbortedSubTransaction(void)
3132 TransactionState s = CurrentTransactionState;
3134 if (s->state != TRANS_DEFAULT)
3135 elog(WARNING, "StartAbortedSubTransaction while in %s state",
3136 TransStateAsString(s->state));
3138 s->state = TRANS_START;
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...
3144 s->transactionIdData = InvalidTransactionId;
3146 /* Make sure currentUser is reasonably valid */
3147 Assert(s->parent != NULL);
3148 s->currentUser = s->parent->currentUser;
3151 * Initialize only what has to be there for CleanupSubTransaction to work.
3153 AtSubStart_Memory();
3154 AtSubStart_ResourceOwner();
3156 s->state = TRANS_ABORT;
3158 AtSubAbort_Memory();
3160 ShowTransactionState("StartAbortedSubTransaction");
3165 * Set up transaction state for a subtransaction
3167 * The caller has to make sure to always reassign CurrentTransactionState
3168 * if it has a local pointer to it after calling this function.
3171 PushTransaction(void)
3173 TransactionState p = CurrentTransactionState;
3177 * We keep subtransaction state nodes in TopTransactionContext.
3179 s = (TransactionState)
3180 MemoryContextAllocZero(TopTransactionContext,
3181 sizeof(TransactionStateData));
3183 s->nestingLevel = p->nestingLevel + 1;
3184 s->savepointLevel = p->savepointLevel;
3185 s->state = TRANS_DEFAULT;
3186 s->blockState = TBLOCK_SUBBEGIN;
3188 /* Command IDs count in a continuous sequence through subtransactions */
3189 s->commandId = p->commandId;
3192 * Copy down some other data so that we will have valid state until
3193 * StartSubTransaction runs.
3195 s->transactionIdData = p->transactionIdData;
3196 s->curTransactionContext = p->curTransactionContext;
3197 s->curTransactionOwner = p->curTransactionOwner;
3198 s->currentUser = p->currentUser;
3200 CurrentTransactionState = s;
3205 * Pop back to parent transaction state
3207 * The caller has to make sure to always reassign CurrentTransactionState
3208 * if it has a local pointer to it after calling this function.
3211 PopTransaction(void)
3213 TransactionState s = CurrentTransactionState;
3215 if (s->state != TRANS_DEFAULT)
3216 elog(WARNING, "PopTransaction while in %s state",
3217 TransStateAsString(s->state));
3219 if (s->parent == NULL)
3220 elog(FATAL, "PopTransaction with no parent");
3222 /* Command IDs count in a continuous sequence through subtransactions */
3223 s->parent->commandId = s->commandId;
3225 CurrentTransactionState = s->parent;
3227 /* Let's just make sure CurTransactionContext is good */
3228 CurTransactionContext = s->parent->curTransactionContext;
3229 MemoryContextSwitchTo(CurTransactionContext);
3231 /* Ditto for ResourceOwner links */
3232 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3233 CurrentResourceOwner = s->parent->curTransactionOwner;
3235 /* Free the old child structure */
3242 * ShowTransactionState
3246 ShowTransactionState(const char *str)
3248 /* skip work if message will definitely not be printed */
3249 if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2)
3251 elog(DEBUG2, "%s", str);
3252 ShowTransactionStateRec(CurrentTransactionState);
3257 * ShowTransactionStateRec
3258 * Recursive subroutine for ShowTransactionState
3261 ShowTransactionStateRec(TransactionState s)
3264 ShowTransactionStateRec(s->parent);
3266 /* use ereport to suppress computation if msg will not be printed */
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,
3275 nodeToString(s->childXids))));
3279 * BlockStateAsString
3283 BlockStateAsString(TBlockState blockState)
3287 case TBLOCK_DEFAULT:
3289 case TBLOCK_STARTED:
3293 case TBLOCK_INPROGRESS:
3294 return "INPROGRESS";
3299 case TBLOCK_ENDABORT:
3301 case TBLOCK_SUBBEGIN:
3303 case TBLOCK_SUBINPROGRESS:
3304 return "SUB INPROGRS";
3307 case TBLOCK_SUBABORT:
3309 case TBLOCK_SUBENDABORT_ALL:
3310 return "SUB ENDAB ALL";
3311 case TBLOCK_SUBENDABORT:
3313 case TBLOCK_SUBABORT_PENDING:
3314 return "SUB ABRT PEND";
3315 case TBLOCK_SUBENDABORT_RELEASE:
3316 return "SUB ENDAB REL";
3318 return "UNRECOGNIZED";
3322 * TransStateAsString
3326 TransStateAsString(TransState state)
3338 case TRANS_INPROGRESS:
3341 return "UNRECOGNIZED";
3345 * xactGetCommittedChildren
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
3353 xactGetCommittedChildren(TransactionId **ptr)
3355 TransactionState s = CurrentTransactionState;
3357 TransactionId *children;
3360 nchildren = list_length(s->childXids);
3367 children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
3370 foreach(p, s->childXids)
3372 TransactionId child = lfirst_xid(p);
3374 *children++ = child;
3381 * XLOG support routines
3385 xact_redo(XLogRecPtr lsn, XLogRecord *record)
3387 uint8 info = record->xl_info & ~XLR_INFO_MASK;
3389 if (info == XLOG_XACT_COMMIT)
3391 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
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++)
3401 XLogCloseRelation(xlrec->xnodes[i]);
3402 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3405 else if (info == XLOG_XACT_ABORT)
3407 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
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++)
3417 XLogCloseRelation(xlrec->xnodes[i]);
3418 smgrdounlink(smgropen(xlrec->xnodes[i]), false, true);
3422 elog(PANIC, "xact_redo: unknown op code %u", info);
3426 xact_undo(XLogRecPtr lsn, XLogRecord *record)
3428 uint8 info = record->xl_info & ~XLR_INFO_MASK;
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);
3437 xact_desc(char *buf, uint8 xl_info, char *rec)
3439 uint8 info = xl_info & ~XLR_INFO_MASK;
3442 if (info == XLOG_XACT_COMMIT)
3444 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
3445 struct tm *tm = localtime(&xlrec->xtime);
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)
3452 sprintf(buf + strlen(buf), "; rels:");
3453 for (i = 0; i < xlrec->nrels; i++)
3455 RelFileNode rnode = xlrec->xnodes[i];
3456 sprintf(buf + strlen(buf), " %u/%u/%u",
3457 rnode.spcNode, rnode.dbNode, rnode.relNode);
3460 if (xlrec->nsubxacts > 0)
3462 TransactionId *xacts = (TransactionId *)
3463 &xlrec->xnodes[xlrec->nrels];
3465 sprintf(buf + strlen(buf), "; subxacts:");
3466 for (i = 0; i < xlrec->nsubxacts; i++)
3467 sprintf(buf + strlen(buf), " %u", xacts[i]);
3470 else if (info == XLOG_XACT_ABORT)
3472 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
3473 struct tm *tm = localtime(&xlrec->xtime);
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)
3480 sprintf(buf + strlen(buf), "; rels:");
3481 for (i = 0; i < xlrec->nrels; i++)
3483 RelFileNode rnode = xlrec->xnodes[i];
3484 sprintf(buf + strlen(buf), " %u/%u/%u",
3485 rnode.spcNode, rnode.dbNode, rnode.relNode);
3488 if (xlrec->nsubxacts > 0)
3490 TransactionId *xacts = (TransactionId *)
3491 &xlrec->xnodes[xlrec->nrels];
3493 sprintf(buf + strlen(buf), "; subxacts:");
3494 for (i = 0; i < xlrec->nsubxacts; i++)
3495 sprintf(buf + strlen(buf), " %u", xacts[i]);
3499 strcat(buf, "UNKNOWN");
3503 XactPushRollback(void (*func) (void *), void *data)
3506 if (_RollbackFunc != NULL)
3507 elog(PANIC, "XactPushRollback: already installed");
3510 _RollbackFunc = func;
3511 _RollbackData = data;
3515 XactPopRollback(void)
3517 _RollbackFunc = NULL;