Introduce the concept of relation forks. An smgr relation can now consist
[PostgreSQL.git] / src / backend / access / transam / xact.c
blobb83f9db91e4957753e0162902fe38aa425aaf07e
1 /*-------------------------------------------------------------------------
3 * xact.c
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
12 * IDENTIFICATION
13 * $PostgreSQL$
15 *-------------------------------------------------------------------------
18 #include "postgres.h"
20 #include <time.h>
21 #include <unistd.h>
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.h"
29 #include "catalog/namespace.h"
30 #include "commands/async.h"
31 #include "commands/tablecmds.h"
32 #include "commands/trigger.h"
33 #include "executor/spi.h"
34 #include "libpq/be-fsstubs.h"
35 #include "miscadmin.h"
36 #include "pgstat.h"
37 #include "storage/bufmgr.h"
38 #include "storage/fd.h"
39 #include "storage/lmgr.h"
40 #include "storage/procarray.h"
41 #include "storage/sinvaladt.h"
42 #include "storage/smgr.h"
43 #include "utils/combocid.h"
44 #include "utils/flatfiles.h"
45 #include "utils/guc.h"
46 #include "utils/inval.h"
47 #include "utils/memutils.h"
48 #include "utils/relcache.h"
49 #include "utils/snapmgr.h"
50 #include "utils/xml.h"
51 #include "pg_trace.h"
55 * User-tweakable parameters
57 int DefaultXactIsoLevel = XACT_READ_COMMITTED;
58 int XactIsoLevel;
60 bool DefaultXactReadOnly = false;
61 bool XactReadOnly;
63 bool XactSyncCommit = true;
65 int CommitDelay = 0; /* precommit delay in microseconds */
66 int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
69 * MyXactAccessedTempRel is set when a temporary relation is accessed.
70 * We don't allow PREPARE TRANSACTION in that case. (This is global
71 * so that it can be set from heapam.c.)
73 bool MyXactAccessedTempRel = false;
77 * transaction states - transaction state from server perspective
79 typedef enum TransState
81 TRANS_DEFAULT, /* idle */
82 TRANS_START, /* transaction starting */
83 TRANS_INPROGRESS, /* inside a valid transaction */
84 TRANS_COMMIT, /* commit in progress */
85 TRANS_ABORT, /* abort in progress */
86 TRANS_PREPARE /* prepare in progress */
87 } TransState;
90 * transaction block states - transaction state of client queries
92 * Note: the subtransaction states are used only for non-topmost
93 * transactions; the others appear only in the topmost transaction.
95 typedef enum TBlockState
97 /* not-in-transaction-block states */
98 TBLOCK_DEFAULT, /* idle */
99 TBLOCK_STARTED, /* running single-query transaction */
101 /* transaction block states */
102 TBLOCK_BEGIN, /* starting transaction block */
103 TBLOCK_INPROGRESS, /* live transaction */
104 TBLOCK_END, /* COMMIT received */
105 TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */
106 TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */
107 TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */
108 TBLOCK_PREPARE, /* live xact, PREPARE received */
110 /* subtransaction states */
111 TBLOCK_SUBBEGIN, /* starting a subtransaction */
112 TBLOCK_SUBINPROGRESS, /* live subtransaction */
113 TBLOCK_SUBEND, /* RELEASE received */
114 TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */
115 TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */
116 TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */
117 TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */
118 TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */
119 } TBlockState;
122 * transaction state structure
124 typedef struct TransactionStateData
126 TransactionId transactionId; /* my XID, or Invalid if none */
127 SubTransactionId subTransactionId; /* my subxact ID */
128 char *name; /* savepoint name, if any */
129 int savepointLevel; /* savepoint level */
130 TransState state; /* low-level state */
131 TBlockState blockState; /* high-level state */
132 int nestingLevel; /* transaction nesting depth */
133 int gucNestLevel; /* GUC context nesting depth */
134 MemoryContext curTransactionContext; /* my xact-lifetime context */
135 ResourceOwner curTransactionOwner; /* my query resources */
136 TransactionId *childXids; /* subcommitted child XIDs, in XID order */
137 int nChildXids; /* # of subcommitted child XIDs */
138 int maxChildXids; /* allocated size of childXids[] */
139 Oid prevUser; /* previous CurrentUserId setting */
140 bool prevSecDefCxt; /* previous SecurityDefinerContext setting */
141 bool prevXactReadOnly; /* entry-time xact r/o state */
142 struct TransactionStateData *parent; /* back link to parent */
143 } TransactionStateData;
145 typedef TransactionStateData *TransactionState;
148 * CurrentTransactionState always points to the current transaction state
149 * block. It will point to TopTransactionStateData when not in a
150 * transaction at all, or when in a top-level transaction.
152 static TransactionStateData TopTransactionStateData = {
153 0, /* transaction id */
154 0, /* subtransaction id */
155 NULL, /* savepoint name */
156 0, /* savepoint level */
157 TRANS_DEFAULT, /* transaction state */
158 TBLOCK_DEFAULT, /* transaction block state from the client
159 * perspective */
160 0, /* transaction nesting depth */
161 0, /* GUC context nesting depth */
162 NULL, /* cur transaction context */
163 NULL, /* cur transaction resource owner */
164 NULL, /* subcommitted child Xids */
165 0, /* # of subcommitted child Xids */
166 0, /* allocated size of childXids[] */
167 InvalidOid, /* previous CurrentUserId setting */
168 false, /* previous SecurityDefinerContext setting */
169 false, /* entry-time xact r/o state */
170 NULL /* link to parent state block */
173 static TransactionState CurrentTransactionState = &TopTransactionStateData;
176 * The subtransaction ID and command ID assignment counters are global
177 * to a whole transaction, so we do not keep them in the state stack.
179 static SubTransactionId currentSubTransactionId;
180 static CommandId currentCommandId;
181 static bool currentCommandIdUsed;
184 * xactStartTimestamp is the value of transaction_timestamp().
185 * stmtStartTimestamp is the value of statement_timestamp().
186 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
187 * These do not change as we enter and exit subtransactions, so we don't
188 * keep them inside the TransactionState stack.
190 static TimestampTz xactStartTimestamp;
191 static TimestampTz stmtStartTimestamp;
192 static TimestampTz xactStopTimestamp;
195 * GID to be used for preparing the current transaction. This is also
196 * global to a whole transaction, so we don't keep it in the state stack.
198 static char *prepareGID;
201 * Some commands want to force synchronous commit.
203 static bool forceSyncCommit = false;
206 * Private context for transaction-abort work --- we reserve space for this
207 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
208 * when we've run out of memory.
210 static MemoryContext TransactionAbortContext = NULL;
213 * List of add-on start- and end-of-xact callbacks
215 typedef struct XactCallbackItem
217 struct XactCallbackItem *next;
218 XactCallback callback;
219 void *arg;
220 } XactCallbackItem;
222 static XactCallbackItem *Xact_callbacks = NULL;
225 * List of add-on start- and end-of-subxact callbacks
227 typedef struct SubXactCallbackItem
229 struct SubXactCallbackItem *next;
230 SubXactCallback callback;
231 void *arg;
232 } SubXactCallbackItem;
234 static SubXactCallbackItem *SubXact_callbacks = NULL;
237 /* local function prototypes */
238 static void AssignTransactionId(TransactionState s);
239 static void AbortTransaction(void);
240 static void AtAbort_Memory(void);
241 static void AtCleanup_Memory(void);
242 static void AtAbort_ResourceOwner(void);
243 static void AtCommit_LocalCache(void);
244 static void AtCommit_Memory(void);
245 static void AtStart_Cache(void);
246 static void AtStart_Memory(void);
247 static void AtStart_ResourceOwner(void);
248 static void CallXactCallbacks(XactEvent event);
249 static void CallSubXactCallbacks(SubXactEvent event,
250 SubTransactionId mySubid,
251 SubTransactionId parentSubid);
252 static void CleanupTransaction(void);
253 static void CommitTransaction(void);
254 static TransactionId RecordTransactionAbort(bool isSubXact);
255 static void StartTransaction(void);
257 static void RecordSubTransactionCommit(void);
258 static void StartSubTransaction(void);
259 static void CommitSubTransaction(void);
260 static void AbortSubTransaction(void);
261 static void CleanupSubTransaction(void);
262 static void PushTransaction(void);
263 static void PopTransaction(void);
265 static void AtSubAbort_Memory(void);
266 static void AtSubCleanup_Memory(void);
267 static void AtSubAbort_ResourceOwner(void);
268 static void AtSubCommit_Memory(void);
269 static void AtSubStart_Memory(void);
270 static void AtSubStart_ResourceOwner(void);
272 static void ShowTransactionState(const char *str);
273 static void ShowTransactionStateRec(TransactionState state);
274 static const char *BlockStateAsString(TBlockState blockState);
275 static const char *TransStateAsString(TransState state);
278 /* ----------------------------------------------------------------
279 * transaction state accessors
280 * ----------------------------------------------------------------
284 * IsTransactionState
286 * This returns true if we are inside a valid transaction; that is,
287 * it is safe to initiate database access, take heavyweight locks, etc.
289 bool
290 IsTransactionState(void)
292 TransactionState s = CurrentTransactionState;
295 * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we
296 * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
297 * TRANS_PREPARE since it might be too soon or too late within those
298 * transition states to do anything interesting. Hence, the only "valid"
299 * state is TRANS_INPROGRESS.
301 return (s->state == TRANS_INPROGRESS);
305 * IsAbortedTransactionBlockState
307 * This returns true if we are currently running a query
308 * within an aborted transaction block.
310 bool
311 IsAbortedTransactionBlockState(void)
313 TransactionState s = CurrentTransactionState;
315 if (s->blockState == TBLOCK_ABORT ||
316 s->blockState == TBLOCK_SUBABORT)
317 return true;
319 return false;
324 * GetTopTransactionId
326 * This will return the XID of the main transaction, assigning one if
327 * it's not yet set. Be careful to call this only inside a valid xact.
329 TransactionId
330 GetTopTransactionId(void)
332 if (!TransactionIdIsValid(TopTransactionStateData.transactionId))
333 AssignTransactionId(&TopTransactionStateData);
334 return TopTransactionStateData.transactionId;
338 * GetTopTransactionIdIfAny
340 * This will return the XID of the main transaction, if one is assigned.
341 * It will return InvalidTransactionId if we are not currently inside a
342 * transaction, or inside a transaction that hasn't yet been assigned an XID.
344 TransactionId
345 GetTopTransactionIdIfAny(void)
347 return TopTransactionStateData.transactionId;
351 * GetCurrentTransactionId
353 * This will return the XID of the current transaction (main or sub
354 * transaction), assigning one if it's not yet set. Be careful to call this
355 * only inside a valid xact.
357 TransactionId
358 GetCurrentTransactionId(void)
360 TransactionState s = CurrentTransactionState;
362 if (!TransactionIdIsValid(s->transactionId))
363 AssignTransactionId(s);
364 return s->transactionId;
368 * GetCurrentTransactionIdIfAny
370 * This will return the XID of the current sub xact, if one is assigned.
371 * It will return InvalidTransactionId if we are not currently inside a
372 * transaction, or inside a transaction that hasn't been assigned an XID yet.
374 TransactionId
375 GetCurrentTransactionIdIfAny(void)
377 return CurrentTransactionState->transactionId;
382 * AssignTransactionId
384 * Assigns a new permanent XID to the given TransactionState.
385 * We do not assign XIDs to transactions until/unless this is called.
386 * Also, any parent TransactionStates that don't yet have XIDs are assigned
387 * one; this maintains the invariant that a child transaction has an XID
388 * following its parent's.
390 static void
391 AssignTransactionId(TransactionState s)
393 bool isSubXact = (s->parent != NULL);
394 ResourceOwner currentOwner;
396 /* Assert that caller didn't screw up */
397 Assert(!TransactionIdIsValid(s->transactionId));
398 Assert(s->state == TRANS_INPROGRESS);
401 * Ensure parent(s) have XIDs, so that a child always has an XID later
402 * than its parent.
404 if (isSubXact && !TransactionIdIsValid(s->parent->transactionId))
405 AssignTransactionId(s->parent);
408 * Generate a new Xid and record it in PG_PROC and pg_subtrans.
410 * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
411 * shared storage other than PG_PROC; because if there's no room for it in
412 * PG_PROC, the subtrans entry is needed to ensure that other backends see
413 * the Xid as "running". See GetNewTransactionId.
415 s->transactionId = GetNewTransactionId(isSubXact);
417 if (isSubXact)
418 SubTransSetParent(s->transactionId, s->parent->transactionId);
421 * Acquire lock on the transaction XID. (We assume this cannot block.) We
422 * have to ensure that the lock is assigned to the transaction's own
423 * ResourceOwner.
425 currentOwner = CurrentResourceOwner;
426 PG_TRY();
428 CurrentResourceOwner = s->curTransactionOwner;
429 XactLockTableInsert(s->transactionId);
431 PG_CATCH();
433 /* Ensure CurrentResourceOwner is restored on error */
434 CurrentResourceOwner = currentOwner;
435 PG_RE_THROW();
437 PG_END_TRY();
438 CurrentResourceOwner = currentOwner;
443 * GetCurrentSubTransactionId
445 SubTransactionId
446 GetCurrentSubTransactionId(void)
448 TransactionState s = CurrentTransactionState;
450 return s->subTransactionId;
455 * GetCurrentCommandId
457 * "used" must be TRUE if the caller intends to use the command ID to mark
458 * inserted/updated/deleted tuples. FALSE means the ID is being fetched
459 * for read-only purposes (ie, as a snapshot validity cutoff). See
460 * CommandCounterIncrement() for discussion.
462 CommandId
463 GetCurrentCommandId(bool used)
465 /* this is global to a transaction, not subtransaction-local */
466 if (used)
467 currentCommandIdUsed = true;
468 return currentCommandId;
472 * GetCurrentTransactionStartTimestamp
474 TimestampTz
475 GetCurrentTransactionStartTimestamp(void)
477 return xactStartTimestamp;
481 * GetCurrentStatementStartTimestamp
483 TimestampTz
484 GetCurrentStatementStartTimestamp(void)
486 return stmtStartTimestamp;
490 * GetCurrentTransactionStopTimestamp
492 * We return current time if the transaction stop time hasn't been set
493 * (which can happen if we decide we don't need to log an XLOG record).
495 TimestampTz
496 GetCurrentTransactionStopTimestamp(void)
498 if (xactStopTimestamp != 0)
499 return xactStopTimestamp;
500 return GetCurrentTimestamp();
504 * SetCurrentStatementStartTimestamp
506 void
507 SetCurrentStatementStartTimestamp(void)
509 stmtStartTimestamp = GetCurrentTimestamp();
513 * SetCurrentTransactionStopTimestamp
515 static inline void
516 SetCurrentTransactionStopTimestamp(void)
518 xactStopTimestamp = GetCurrentTimestamp();
522 * GetCurrentTransactionNestLevel
524 * Note: this will return zero when not inside any transaction, one when
525 * inside a top-level transaction, etc.
528 GetCurrentTransactionNestLevel(void)
530 TransactionState s = CurrentTransactionState;
532 return s->nestingLevel;
537 * TransactionIdIsCurrentTransactionId
539 bool
540 TransactionIdIsCurrentTransactionId(TransactionId xid)
542 TransactionState s;
545 * We always say that BootstrapTransactionId is "not my transaction ID"
546 * even when it is (ie, during bootstrap). Along with the fact that
547 * transam.c always treats BootstrapTransactionId as already committed,
548 * this causes the tqual.c routines to see all tuples as committed, which
549 * is what we need during bootstrap. (Bootstrap mode only inserts tuples,
550 * it never updates or deletes them, so all tuples can be presumed good
551 * immediately.)
553 * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
554 * not my transaction ID, so we can just return "false" immediately for
555 * any non-normal XID.
557 if (!TransactionIdIsNormal(xid))
558 return false;
561 * We will return true for the Xid of the current subtransaction, any of
562 * its subcommitted children, any of its parents, or any of their
563 * previously subcommitted children. However, a transaction being aborted
564 * is no longer "current", even though it may still have an entry on the
565 * state stack.
567 for (s = CurrentTransactionState; s != NULL; s = s->parent)
569 int low, high;
571 if (s->state == TRANS_ABORT)
572 continue;
573 if (!TransactionIdIsValid(s->transactionId))
574 continue; /* it can't have any child XIDs either */
575 if (TransactionIdEquals(xid, s->transactionId))
576 return true;
577 /* As the childXids array is ordered, we can use binary search */
578 low = 0;
579 high = s->nChildXids - 1;
580 while (low <= high)
582 int middle;
583 TransactionId probe;
585 middle = low + (high - low) / 2;
586 probe = s->childXids[middle];
587 if (TransactionIdEquals(probe, xid))
588 return true;
589 else if (TransactionIdPrecedes(probe, xid))
590 low = middle + 1;
591 else
592 high = middle - 1;
596 return false;
601 * CommandCounterIncrement
603 void
604 CommandCounterIncrement(void)
607 * If the current value of the command counter hasn't been "used" to
608 * mark tuples, we need not increment it, since there's no need to
609 * distinguish a read-only command from others. This helps postpone
610 * command counter overflow, and keeps no-op CommandCounterIncrement
611 * operations cheap.
613 if (currentCommandIdUsed)
615 currentCommandId += 1;
616 if (currentCommandId == FirstCommandId) /* check for overflow */
618 currentCommandId -= 1;
619 ereport(ERROR,
620 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
621 errmsg("cannot have more than 2^32-1 commands in a transaction")));
623 currentCommandIdUsed = false;
625 /* Propagate new command ID into static snapshots */
626 SnapshotSetCommandId(currentCommandId);
629 * Make any catalog changes done by the just-completed command
630 * visible in the local syscache. We obviously don't need to do
631 * this after a read-only command. (But see hacks in inval.c
632 * to make real sure we don't think a command that queued inval
633 * messages was read-only.)
635 AtCommit_LocalCache();
639 * Make any other backends' catalog changes visible to me.
641 * XXX this is probably in the wrong place: CommandCounterIncrement
642 * should be purely a local operation, most likely. However fooling
643 * with this will affect asynchronous cross-backend interactions,
644 * which doesn't seem like a wise thing to do in late beta, so save
645 * improving this for another day - tgl 2007-11-30
647 AtStart_Cache();
651 * ForceSyncCommit
653 * Interface routine to allow commands to force a synchronous commit of the
654 * current top-level transaction
656 void
657 ForceSyncCommit(void)
659 forceSyncCommit = true;
663 /* ----------------------------------------------------------------
664 * StartTransaction stuff
665 * ----------------------------------------------------------------
669 * AtStart_Cache
671 static void
672 AtStart_Cache(void)
674 AcceptInvalidationMessages();
678 * AtStart_Memory
680 static void
681 AtStart_Memory(void)
683 TransactionState s = CurrentTransactionState;
686 * If this is the first time through, create a private context for
687 * AbortTransaction to work in. By reserving some space now, we can
688 * insulate AbortTransaction from out-of-memory scenarios. Like
689 * ErrorContext, we set it up with slow growth rate and a nonzero minimum
690 * size, so that space will be reserved immediately.
692 if (TransactionAbortContext == NULL)
693 TransactionAbortContext =
694 AllocSetContextCreate(TopMemoryContext,
695 "TransactionAbortContext",
696 32 * 1024,
697 32 * 1024,
698 32 * 1024);
701 * We shouldn't have a transaction context already.
703 Assert(TopTransactionContext == NULL);
706 * Create a toplevel context for the transaction.
708 TopTransactionContext =
709 AllocSetContextCreate(TopMemoryContext,
710 "TopTransactionContext",
711 ALLOCSET_DEFAULT_MINSIZE,
712 ALLOCSET_DEFAULT_INITSIZE,
713 ALLOCSET_DEFAULT_MAXSIZE);
716 * In a top-level transaction, CurTransactionContext is the same as
717 * TopTransactionContext.
719 CurTransactionContext = TopTransactionContext;
720 s->curTransactionContext = CurTransactionContext;
722 /* Make the CurTransactionContext active. */
723 MemoryContextSwitchTo(CurTransactionContext);
727 * AtStart_ResourceOwner
729 static void
730 AtStart_ResourceOwner(void)
732 TransactionState s = CurrentTransactionState;
735 * We shouldn't have a transaction resource owner already.
737 Assert(TopTransactionResourceOwner == NULL);
740 * Create a toplevel resource owner for the transaction.
742 s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
744 TopTransactionResourceOwner = s->curTransactionOwner;
745 CurTransactionResourceOwner = s->curTransactionOwner;
746 CurrentResourceOwner = s->curTransactionOwner;
749 /* ----------------------------------------------------------------
750 * StartSubTransaction stuff
751 * ----------------------------------------------------------------
755 * AtSubStart_Memory
757 static void
758 AtSubStart_Memory(void)
760 TransactionState s = CurrentTransactionState;
762 Assert(CurTransactionContext != NULL);
765 * Create a CurTransactionContext, which will be used to hold data that
766 * survives subtransaction commit but disappears on subtransaction abort.
767 * We make it a child of the immediate parent's CurTransactionContext.
769 CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
770 "CurTransactionContext",
771 ALLOCSET_DEFAULT_MINSIZE,
772 ALLOCSET_DEFAULT_INITSIZE,
773 ALLOCSET_DEFAULT_MAXSIZE);
774 s->curTransactionContext = CurTransactionContext;
776 /* Make the CurTransactionContext active. */
777 MemoryContextSwitchTo(CurTransactionContext);
781 * AtSubStart_ResourceOwner
783 static void
784 AtSubStart_ResourceOwner(void)
786 TransactionState s = CurrentTransactionState;
788 Assert(s->parent != NULL);
791 * Create a resource owner for the subtransaction. We make it a child of
792 * the immediate parent's resource owner.
794 s->curTransactionOwner =
795 ResourceOwnerCreate(s->parent->curTransactionOwner,
796 "SubTransaction");
798 CurTransactionResourceOwner = s->curTransactionOwner;
799 CurrentResourceOwner = s->curTransactionOwner;
802 /* ----------------------------------------------------------------
803 * CommitTransaction stuff
804 * ----------------------------------------------------------------
808 * RecordTransactionCommit
810 * Returns latest XID among xact and its children, or InvalidTransactionId
811 * if the xact has no XID. (We compute that here just because it's easier.)
813 * This is exported only to support an ugly hack in VACUUM FULL.
815 TransactionId
816 RecordTransactionCommit(void)
818 TransactionId xid = GetTopTransactionIdIfAny();
819 bool markXidCommitted = TransactionIdIsValid(xid);
820 TransactionId latestXid = InvalidTransactionId;
821 int nrels;
822 RelFileFork *rels;
823 bool haveNonTemp;
824 int nchildren;
825 TransactionId *children;
827 /* Get data needed for commit record */
828 nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
829 nchildren = xactGetCommittedChildren(&children);
832 * If we haven't been assigned an XID yet, we neither can, nor do we want
833 * to write a COMMIT record.
835 if (!markXidCommitted)
838 * We expect that every smgrscheduleunlink is followed by a catalog
839 * update, and hence XID assignment, so we shouldn't get here with any
840 * pending deletes. Use a real test not just an Assert to check this,
841 * since it's a bit fragile.
843 if (nrels != 0)
844 elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
846 /* Can't have child XIDs either; AssignTransactionId enforces this */
847 Assert(nchildren == 0);
850 * If we didn't create XLOG entries, we're done here; otherwise we
851 * should flush those entries the same as a commit record. (An
852 * example of a possible record that wouldn't cause an XID to be
853 * assigned is a sequence advance record due to nextval() --- we want
854 * to flush that to disk before reporting commit.)
856 if (XactLastRecEnd.xrecoff == 0)
857 goto cleanup;
859 else
862 * Begin commit critical section and insert the commit XLOG record.
864 XLogRecData rdata[3];
865 int lastrdata = 0;
866 xl_xact_commit xlrec;
868 /* Tell bufmgr and smgr to prepare for commit */
869 BufmgrCommit();
872 * Mark ourselves as within our "commit critical section". This
873 * forces any concurrent checkpoint to wait until we've updated
874 * pg_clog. Without this, it is possible for the checkpoint to set
875 * REDO after the XLOG record but fail to flush the pg_clog update to
876 * disk, leading to loss of the transaction commit if the system
877 * crashes a little later.
879 * Note: we could, but don't bother to, set this flag in
880 * RecordTransactionAbort. That's because loss of a transaction abort
881 * is noncritical; the presumption would be that it aborted, anyway.
883 * It's safe to change the inCommit flag of our own backend without
884 * holding the ProcArrayLock, since we're the only one modifying it.
885 * This makes checkpoint's determination of which xacts are inCommit a
886 * bit fuzzy, but it doesn't matter.
888 START_CRIT_SECTION();
889 MyProc->inCommit = true;
891 SetCurrentTransactionStopTimestamp();
892 xlrec.xact_time = xactStopTimestamp;
893 xlrec.nrels = nrels;
894 xlrec.nsubxacts = nchildren;
895 rdata[0].data = (char *) (&xlrec);
896 rdata[0].len = MinSizeOfXactCommit;
897 rdata[0].buffer = InvalidBuffer;
898 /* dump rels to delete */
899 if (nrels > 0)
901 rdata[0].next = &(rdata[1]);
902 rdata[1].data = (char *) rels;
903 rdata[1].len = nrels * sizeof(RelFileFork);
904 rdata[1].buffer = InvalidBuffer;
905 lastrdata = 1;
907 /* dump committed child Xids */
908 if (nchildren > 0)
910 rdata[lastrdata].next = &(rdata[2]);
911 rdata[2].data = (char *) children;
912 rdata[2].len = nchildren * sizeof(TransactionId);
913 rdata[2].buffer = InvalidBuffer;
914 lastrdata = 2;
916 rdata[lastrdata].next = NULL;
918 (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata);
922 * Check if we want to commit asynchronously. If the user has set
923 * synchronous_commit = off, and we're not doing cleanup of any non-temp
924 * rels nor committing any command that wanted to force sync commit, then
925 * we can defer flushing XLOG. (We must not allow asynchronous commit if
926 * there are any non-temp tables to be deleted, because we might delete
927 * the files before the COMMIT record is flushed to disk. We do allow
928 * asynchronous commit if all to-be-deleted tables are temporary though,
929 * since they are lost anyway if we crash.)
931 if (XactSyncCommit || forceSyncCommit || haveNonTemp)
934 * Synchronous commit case.
936 * Sleep before flush! So we can flush more than one commit records
937 * per single fsync. (The idea is some other backend may do the
938 * XLogFlush while we're sleeping. This needs work still, because on
939 * most Unixen, the minimum select() delay is 10msec or more, which is
940 * way too long.)
942 * We do not sleep if enableFsync is not turned on, nor if there are
943 * fewer than CommitSiblings other backends with active transactions.
945 if (CommitDelay > 0 && enableFsync &&
946 CountActiveBackends() >= CommitSiblings)
947 pg_usleep(CommitDelay);
949 XLogFlush(XactLastRecEnd);
952 * Now we may update the CLOG, if we wrote a COMMIT record above
954 if (markXidCommitted)
956 TransactionIdCommit(xid);
957 /* to avoid race conditions, the parent must commit first */
958 TransactionIdCommitTree(nchildren, children);
961 else
964 * Asynchronous commit case.
966 * Report the latest async commit LSN, so that the WAL writer knows to
967 * flush this commit.
969 XLogSetAsyncCommitLSN(XactLastRecEnd);
972 * We must not immediately update the CLOG, since we didn't flush the
973 * XLOG. Instead, we store the LSN up to which the XLOG must be
974 * flushed before the CLOG may be updated.
976 if (markXidCommitted)
978 TransactionIdAsyncCommit(xid, XactLastRecEnd);
979 /* to avoid race conditions, the parent must commit first */
980 TransactionIdAsyncCommitTree(nchildren, children, XactLastRecEnd);
985 * If we entered a commit critical section, leave it now, and let
986 * checkpoints proceed.
988 if (markXidCommitted)
990 MyProc->inCommit = false;
991 END_CRIT_SECTION();
994 /* Compute latestXid while we have the child XIDs handy */
995 latestXid = TransactionIdLatest(xid, nchildren, children);
997 /* Reset XactLastRecEnd until the next transaction writes something */
998 XactLastRecEnd.xrecoff = 0;
1000 cleanup:
1001 /* Clean up local data */
1002 if (rels)
1003 pfree(rels);
1005 return latestXid;
1010 * AtCommit_LocalCache
1012 static void
1013 AtCommit_LocalCache(void)
1016 * Make catalog changes visible to me for the next command.
1018 CommandEndInvalidationMessages();
1022 * AtCommit_Memory
1024 static void
1025 AtCommit_Memory(void)
1028 * Now that we're "out" of a transaction, have the system allocate things
1029 * in the top memory context instead of per-transaction contexts.
1031 MemoryContextSwitchTo(TopMemoryContext);
1034 * Release all transaction-local memory.
1036 Assert(TopTransactionContext != NULL);
1037 MemoryContextDelete(TopTransactionContext);
1038 TopTransactionContext = NULL;
1039 CurTransactionContext = NULL;
1040 CurrentTransactionState->curTransactionContext = NULL;
1043 /* ----------------------------------------------------------------
1044 * CommitSubTransaction stuff
1045 * ----------------------------------------------------------------
1049 * AtSubCommit_Memory
1051 static void
1052 AtSubCommit_Memory(void)
1054 TransactionState s = CurrentTransactionState;
1056 Assert(s->parent != NULL);
1058 /* Return to parent transaction level's memory context. */
1059 CurTransactionContext = s->parent->curTransactionContext;
1060 MemoryContextSwitchTo(CurTransactionContext);
1063 * Ordinarily we cannot throw away the child's CurTransactionContext,
1064 * since the data it contains will be needed at upper commit. However, if
1065 * there isn't actually anything in it, we can throw it away. This avoids
1066 * a small memory leak in the common case of "trivial" subxacts.
1068 if (MemoryContextIsEmpty(s->curTransactionContext))
1070 MemoryContextDelete(s->curTransactionContext);
1071 s->curTransactionContext = NULL;
1076 * AtSubCommit_childXids
1078 * Pass my own XID and my child XIDs up to my parent as committed children.
1080 static void
1081 AtSubCommit_childXids(void)
1083 TransactionState s = CurrentTransactionState;
1084 int new_nChildXids;
1086 Assert(s->parent != NULL);
1089 * The parent childXids array will need to hold my XID and all my
1090 * childXids, in addition to the XIDs already there.
1092 new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
1094 /* Allocate or enlarge the parent array if necessary */
1095 if (s->parent->maxChildXids < new_nChildXids)
1097 int new_maxChildXids;
1098 TransactionId *new_childXids;
1101 * Make it 2x what's needed right now, to avoid having to enlarge it
1102 * repeatedly. But we can't go above MaxAllocSize. (The latter
1103 * limit is what ensures that we don't need to worry about integer
1104 * overflow here or in the calculation of new_nChildXids.)
1106 new_maxChildXids = Min(new_nChildXids * 2,
1107 (int) (MaxAllocSize / sizeof(TransactionId)));
1109 if (new_maxChildXids < new_nChildXids)
1110 ereport(ERROR,
1111 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1112 errmsg("maximum number of committed subtransactions (%d) exceeded",
1113 (int) (MaxAllocSize / sizeof(TransactionId)))));
1116 * We keep the child-XID arrays in TopTransactionContext; this avoids
1117 * setting up child-transaction contexts for what might be just a few
1118 * bytes of grandchild XIDs.
1120 if (s->parent->childXids == NULL)
1121 new_childXids =
1122 MemoryContextAlloc(TopTransactionContext,
1123 new_maxChildXids * sizeof(TransactionId));
1124 else
1125 new_childXids = repalloc(s->parent->childXids,
1126 new_maxChildXids * sizeof(TransactionId));
1128 s->parent->childXids = new_childXids;
1129 s->parent->maxChildXids = new_maxChildXids;
1133 * Copy all my XIDs to parent's array.
1135 * Note: We rely on the fact that the XID of a child always follows that
1136 * of its parent. By copying the XID of this subtransaction before the
1137 * XIDs of its children, we ensure that the array stays ordered. Likewise,
1138 * all XIDs already in the array belong to subtransactions started and
1139 * subcommitted before us, so their XIDs must precede ours.
1141 s->parent->childXids[s->parent->nChildXids] = s->transactionId;
1143 if (s->nChildXids > 0)
1144 memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
1145 s->childXids,
1146 s->nChildXids * sizeof(TransactionId));
1148 s->parent->nChildXids = new_nChildXids;
1150 /* Release child's array to avoid leakage */
1151 if (s->childXids != NULL)
1152 pfree(s->childXids);
1153 /* We must reset these to avoid double-free if fail later in commit */
1154 s->childXids = NULL;
1155 s->nChildXids = 0;
1156 s->maxChildXids = 0;
1160 * RecordSubTransactionCommit
1162 static void
1163 RecordSubTransactionCommit(void)
1165 TransactionId xid = GetCurrentTransactionIdIfAny();
1168 * We do not log the subcommit in XLOG; it doesn't matter until the
1169 * top-level transaction commits.
1171 * We must mark the subtransaction subcommitted in the CLOG if it had a
1172 * valid XID assigned. If it did not, nobody else will ever know about
1173 * the existence of this subxact. We don't have to deal with deletions
1174 * scheduled for on-commit here, since they'll be reassigned to our parent
1175 * (who might still abort).
1177 if (TransactionIdIsValid(xid))
1179 /* XXX does this really need to be a critical section? */
1180 START_CRIT_SECTION();
1182 /* Record subtransaction subcommit */
1183 TransactionIdSubCommit(xid);
1185 END_CRIT_SECTION();
1189 /* ----------------------------------------------------------------
1190 * AbortTransaction stuff
1191 * ----------------------------------------------------------------
1195 * RecordTransactionAbort
1197 * Returns latest XID among xact and its children, or InvalidTransactionId
1198 * if the xact has no XID. (We compute that here just because it's easier.)
1200 static TransactionId
1201 RecordTransactionAbort(bool isSubXact)
1203 TransactionId xid = GetCurrentTransactionIdIfAny();
1204 TransactionId latestXid;
1205 int nrels;
1206 RelFileFork *rels;
1207 int nchildren;
1208 TransactionId *children;
1209 XLogRecData rdata[3];
1210 int lastrdata = 0;
1211 xl_xact_abort xlrec;
1214 * If we haven't been assigned an XID, nobody will care whether we aborted
1215 * or not. Hence, we're done in that case. It does not matter if we have
1216 * rels to delete (note that this routine is not responsible for actually
1217 * deleting 'em). We cannot have any child XIDs, either.
1219 if (!TransactionIdIsValid(xid))
1221 /* Reset XactLastRecEnd until the next transaction writes something */
1222 if (!isSubXact)
1223 XactLastRecEnd.xrecoff = 0;
1224 return InvalidTransactionId;
1228 * We have a valid XID, so we should write an ABORT record for it.
1230 * We do not flush XLOG to disk here, since the default assumption after a
1231 * crash would be that we aborted, anyway. For the same reason, we don't
1232 * need to worry about interlocking against checkpoint start.
1236 * Check that we haven't aborted halfway through RecordTransactionCommit.
1238 if (TransactionIdDidCommit(xid))
1239 elog(PANIC, "cannot abort transaction %u, it was already committed",
1240 xid);
1242 /* Fetch the data we need for the abort record */
1243 nrels = smgrGetPendingDeletes(false, &rels, NULL);
1244 nchildren = xactGetCommittedChildren(&children);
1246 /* XXX do we really need a critical section here? */
1247 START_CRIT_SECTION();
1249 /* Write the ABORT record */
1250 if (isSubXact)
1251 xlrec.xact_time = GetCurrentTimestamp();
1252 else
1254 SetCurrentTransactionStopTimestamp();
1255 xlrec.xact_time = xactStopTimestamp;
1257 xlrec.nrels = nrels;
1258 xlrec.nsubxacts = nchildren;
1259 rdata[0].data = (char *) (&xlrec);
1260 rdata[0].len = MinSizeOfXactAbort;
1261 rdata[0].buffer = InvalidBuffer;
1262 /* dump rels to delete */
1263 if (nrels > 0)
1265 rdata[0].next = &(rdata[1]);
1266 rdata[1].data = (char *) rels;
1267 rdata[1].len = nrels * sizeof(RelFileFork);
1268 rdata[1].buffer = InvalidBuffer;
1269 lastrdata = 1;
1271 /* dump committed child Xids */
1272 if (nchildren > 0)
1274 rdata[lastrdata].next = &(rdata[2]);
1275 rdata[2].data = (char *) children;
1276 rdata[2].len = nchildren * sizeof(TransactionId);
1277 rdata[2].buffer = InvalidBuffer;
1278 lastrdata = 2;
1280 rdata[lastrdata].next = NULL;
1282 (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
1285 * Mark the transaction aborted in clog. This is not absolutely necessary
1286 * but we may as well do it while we are here; also, in the subxact case
1287 * it is helpful because XactLockTableWait makes use of it to avoid
1288 * waiting for already-aborted subtransactions. It is OK to do it without
1289 * having flushed the ABORT record to disk, because in event of a crash
1290 * we'd be assumed to have aborted anyway.
1292 * The ordering here isn't critical but it seems best to mark the parent
1293 * first. This assures an atomic transition of all the subtransactions to
1294 * aborted state from the point of view of concurrent
1295 * TransactionIdDidAbort calls.
1297 TransactionIdAbort(xid);
1298 TransactionIdAbortTree(nchildren, children);
1300 END_CRIT_SECTION();
1302 /* Compute latestXid while we have the child XIDs handy */
1303 latestXid = TransactionIdLatest(xid, nchildren, children);
1306 * If we're aborting a subtransaction, we can immediately remove failed
1307 * XIDs from PGPROC's cache of running child XIDs. We do that here for
1308 * subxacts, because we already have the child XID array at hand. For
1309 * main xacts, the equivalent happens just after this function returns.
1311 if (isSubXact)
1312 XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
1314 /* Reset XactLastRecEnd until the next transaction writes something */
1315 if (!isSubXact)
1316 XactLastRecEnd.xrecoff = 0;
1318 /* And clean up local data */
1319 if (rels)
1320 pfree(rels);
1322 return latestXid;
1326 * AtAbort_Memory
1328 static void
1329 AtAbort_Memory(void)
1332 * Switch into TransactionAbortContext, which should have some free space
1333 * even if nothing else does. We'll work in this context until we've
1334 * finished cleaning up.
1336 * It is barely possible to get here when we've not been able to create
1337 * TransactionAbortContext yet; if so use TopMemoryContext.
1339 if (TransactionAbortContext != NULL)
1340 MemoryContextSwitchTo(TransactionAbortContext);
1341 else
1342 MemoryContextSwitchTo(TopMemoryContext);
1346 * AtSubAbort_Memory
1348 static void
1349 AtSubAbort_Memory(void)
1351 Assert(TransactionAbortContext != NULL);
1353 MemoryContextSwitchTo(TransactionAbortContext);
1358 * AtAbort_ResourceOwner
1360 static void
1361 AtAbort_ResourceOwner(void)
1364 * Make sure we have a valid ResourceOwner, if possible (else it will be
1365 * NULL, which is OK)
1367 CurrentResourceOwner = TopTransactionResourceOwner;
1371 * AtSubAbort_ResourceOwner
1373 static void
1374 AtSubAbort_ResourceOwner(void)
1376 TransactionState s = CurrentTransactionState;
1378 /* Make sure we have a valid ResourceOwner */
1379 CurrentResourceOwner = s->curTransactionOwner;
1384 * AtSubAbort_childXids
1386 static void
1387 AtSubAbort_childXids(void)
1389 TransactionState s = CurrentTransactionState;
1392 * We keep the child-XID arrays in TopTransactionContext (see
1393 * AtSubCommit_childXids). This means we'd better free the array
1394 * explicitly at abort to avoid leakage.
1396 if (s->childXids != NULL)
1397 pfree(s->childXids);
1398 s->childXids = NULL;
1399 s->nChildXids = 0;
1400 s->maxChildXids = 0;
1403 /* ----------------------------------------------------------------
1404 * CleanupTransaction stuff
1405 * ----------------------------------------------------------------
1409 * AtCleanup_Memory
1411 static void
1412 AtCleanup_Memory(void)
1414 Assert(CurrentTransactionState->parent == NULL);
1417 * Now that we're "out" of a transaction, have the system allocate things
1418 * in the top memory context instead of per-transaction contexts.
1420 MemoryContextSwitchTo(TopMemoryContext);
1423 * Clear the special abort context for next time.
1425 if (TransactionAbortContext != NULL)
1426 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1429 * Release all transaction-local memory.
1431 if (TopTransactionContext != NULL)
1432 MemoryContextDelete(TopTransactionContext);
1433 TopTransactionContext = NULL;
1434 CurTransactionContext = NULL;
1435 CurrentTransactionState->curTransactionContext = NULL;
1439 /* ----------------------------------------------------------------
1440 * CleanupSubTransaction stuff
1441 * ----------------------------------------------------------------
1445 * AtSubCleanup_Memory
1447 static void
1448 AtSubCleanup_Memory(void)
1450 TransactionState s = CurrentTransactionState;
1452 Assert(s->parent != NULL);
1454 /* Make sure we're not in an about-to-be-deleted context */
1455 MemoryContextSwitchTo(s->parent->curTransactionContext);
1456 CurTransactionContext = s->parent->curTransactionContext;
1459 * Clear the special abort context for next time.
1461 if (TransactionAbortContext != NULL)
1462 MemoryContextResetAndDeleteChildren(TransactionAbortContext);
1465 * Delete the subxact local memory contexts. Its CurTransactionContext can
1466 * go too (note this also kills CurTransactionContexts from any children
1467 * of the subxact).
1469 if (s->curTransactionContext)
1470 MemoryContextDelete(s->curTransactionContext);
1471 s->curTransactionContext = NULL;
1474 /* ----------------------------------------------------------------
1475 * interface routines
1476 * ----------------------------------------------------------------
1480 * StartTransaction
1482 static void
1483 StartTransaction(void)
1485 TransactionState s;
1486 VirtualTransactionId vxid;
1489 * Let's just make sure the state stack is empty
1491 s = &TopTransactionStateData;
1492 CurrentTransactionState = s;
1495 * check the current transaction state
1497 if (s->state != TRANS_DEFAULT)
1498 elog(WARNING, "StartTransaction while in %s state",
1499 TransStateAsString(s->state));
1502 * set the current transaction state information appropriately during
1503 * start processing
1505 s->state = TRANS_START;
1506 s->transactionId = InvalidTransactionId; /* until assigned */
1509 * Make sure we've reset xact state variables
1511 XactIsoLevel = DefaultXactIsoLevel;
1512 XactReadOnly = DefaultXactReadOnly;
1513 forceSyncCommit = false;
1514 MyXactAccessedTempRel = false;
1517 * reinitialize within-transaction counters
1519 s->subTransactionId = TopSubTransactionId;
1520 currentSubTransactionId = TopSubTransactionId;
1521 currentCommandId = FirstCommandId;
1522 currentCommandIdUsed = false;
1525 * must initialize resource-management stuff first
1527 AtStart_Memory();
1528 AtStart_ResourceOwner();
1531 * Assign a new LocalTransactionId, and combine it with the backendId to
1532 * form a virtual transaction id.
1534 vxid.backendId = MyBackendId;
1535 vxid.localTransactionId = GetNextLocalTransactionId();
1538 * Lock the virtual transaction id before we announce it in the proc array
1540 VirtualXactLockTableInsert(vxid);
1543 * Advertise it in the proc array. We assume assignment of
1544 * LocalTransactionID is atomic, and the backendId should be set already.
1546 Assert(MyProc->backendId == vxid.backendId);
1547 MyProc->lxid = vxid.localTransactionId;
1549 TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
1552 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1553 * as the first command's statement_timestamp(), so don't do a fresh
1554 * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1555 * xactStopTimestamp as unset.
1557 xactStartTimestamp = stmtStartTimestamp;
1558 xactStopTimestamp = 0;
1559 pgstat_report_xact_timestamp(xactStartTimestamp);
1562 * initialize current transaction state fields
1564 * note: prevXactReadOnly is not used at the outermost level
1566 s->nestingLevel = 1;
1567 s->gucNestLevel = 1;
1568 s->childXids = NULL;
1569 s->nChildXids = 0;
1570 s->maxChildXids = 0;
1571 GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
1572 /* SecurityDefinerContext should never be set outside a transaction */
1573 Assert(!s->prevSecDefCxt);
1576 * initialize other subsystems for new transaction
1578 AtStart_GUC();
1579 AtStart_Inval();
1580 AtStart_Cache();
1581 AfterTriggerBeginXact();
1584 * done with start processing, set current transaction state to "in
1585 * progress"
1587 s->state = TRANS_INPROGRESS;
1589 ShowTransactionState("StartTransaction");
1594 * CommitTransaction
1596 * NB: if you change this routine, better look at PrepareTransaction too!
1598 static void
1599 CommitTransaction(void)
1601 TransactionState s = CurrentTransactionState;
1602 TransactionId latestXid;
1604 ShowTransactionState("CommitTransaction");
1607 * check the current transaction state
1609 if (s->state != TRANS_INPROGRESS)
1610 elog(WARNING, "CommitTransaction while in %s state",
1611 TransStateAsString(s->state));
1612 Assert(s->parent == NULL);
1615 * Do pre-commit processing (most of this stuff requires database access,
1616 * and in fact could still cause an error...)
1618 * It is possible for CommitHoldablePortals to invoke functions that queue
1619 * deferred triggers, and it's also possible that triggers create holdable
1620 * cursors. So we have to loop until there's nothing left to do.
1622 for (;;)
1625 * Fire all currently pending deferred triggers.
1627 AfterTriggerFireDeferred();
1630 * Convert any open holdable cursors into static portals. If there
1631 * weren't any, we are done ... otherwise loop back to check if they
1632 * queued deferred triggers. Lather, rinse, repeat.
1634 if (!CommitHoldablePortals())
1635 break;
1638 /* Now we can shut down the deferred-trigger manager */
1639 AfterTriggerEndXact(true);
1641 /* Close any open regular cursors */
1642 AtCommit_Portals();
1645 * Let ON COMMIT management do its thing (must happen after closing
1646 * cursors, to avoid dangling-reference problems)
1648 PreCommit_on_commit_actions();
1650 /* close large objects before lower-level cleanup */
1651 AtEOXact_LargeObject(true);
1653 /* NOTIFY commit must come before lower-level cleanup */
1654 AtCommit_Notify();
1657 * Update flat files if we changed pg_database, pg_authid or
1658 * pg_auth_members. This should be the last step before commit.
1660 AtEOXact_UpdateFlatFiles(true);
1662 /* Prevent cancel/die interrupt while cleaning up */
1663 HOLD_INTERRUPTS();
1666 * set the current transaction state information appropriately during
1667 * commit processing
1669 s->state = TRANS_COMMIT;
1672 * Here is where we really truly commit.
1674 latestXid = RecordTransactionCommit();
1676 TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
1679 * Let others know about no transaction in progress by me. Note that this
1680 * must be done _before_ releasing locks we hold and _after_
1681 * RecordTransactionCommit.
1683 ProcArrayEndTransaction(MyProc, latestXid);
1686 * This is all post-commit cleanup. Note that if an error is raised here,
1687 * it's too late to abort the transaction. This should be just
1688 * noncritical resource releasing.
1690 * The ordering of operations is not entirely random. The idea is:
1691 * release resources visible to other backends (eg, files, buffer pins);
1692 * then release locks; then release backend-local resources. We want to
1693 * release locks at the point where any backend waiting for us will see
1694 * our transaction as being fully cleaned up.
1696 * Resources that can be associated with individual queries are handled by
1697 * the ResourceOwner mechanism. The other calls here are for backend-wide
1698 * state.
1701 CallXactCallbacks(XACT_EVENT_COMMIT);
1703 ResourceOwnerRelease(TopTransactionResourceOwner,
1704 RESOURCE_RELEASE_BEFORE_LOCKS,
1705 true, true);
1707 /* Check we've released all buffer pins */
1708 AtEOXact_Buffers(true);
1710 /* Clean up the relation cache */
1711 AtEOXact_RelationCache(true);
1714 * Make catalog changes visible to all backends. This has to happen after
1715 * relcache references are dropped (see comments for
1716 * AtEOXact_RelationCache), but before locks are released (if anyone is
1717 * waiting for lock on a relation we've modified, we want them to know
1718 * about the catalog change before they start using the relation).
1720 AtEOXact_Inval(true);
1723 * Likewise, dropping of files deleted during the transaction is best done
1724 * after releasing relcache and buffer pins. (This is not strictly
1725 * necessary during commit, since such pins should have been released
1726 * already, but this ordering is definitely critical during abort.)
1728 smgrDoPendingDeletes(true);
1730 AtEOXact_MultiXact();
1732 ResourceOwnerRelease(TopTransactionResourceOwner,
1733 RESOURCE_RELEASE_LOCKS,
1734 true, true);
1735 ResourceOwnerRelease(TopTransactionResourceOwner,
1736 RESOURCE_RELEASE_AFTER_LOCKS,
1737 true, true);
1739 /* Check we've released all catcache entries */
1740 AtEOXact_CatCache(true);
1742 AtEOXact_GUC(true, 1);
1743 AtEOXact_SPI(true);
1744 AtEOXact_xml();
1745 AtEOXact_on_commit_actions(true);
1746 AtEOXact_Namespace(true);
1747 /* smgrcommit already done */
1748 AtEOXact_Files();
1749 AtEOXact_ComboCid();
1750 AtEOXact_HashTables(true);
1751 AtEOXact_PgStat(true);
1752 AtEOXact_Snapshot(true);
1753 pgstat_report_xact_timestamp(0);
1755 CurrentResourceOwner = NULL;
1756 ResourceOwnerDelete(TopTransactionResourceOwner);
1757 s->curTransactionOwner = NULL;
1758 CurTransactionResourceOwner = NULL;
1759 TopTransactionResourceOwner = NULL;
1761 AtCommit_Memory();
1763 s->transactionId = InvalidTransactionId;
1764 s->subTransactionId = InvalidSubTransactionId;
1765 s->nestingLevel = 0;
1766 s->gucNestLevel = 0;
1767 s->childXids = NULL;
1768 s->nChildXids = 0;
1769 s->maxChildXids = 0;
1772 * done with commit processing, set current transaction state back to
1773 * default
1775 s->state = TRANS_DEFAULT;
1777 RESUME_INTERRUPTS();
1782 * PrepareTransaction
1784 * NB: if you change this routine, better look at CommitTransaction too!
1786 static void
1787 PrepareTransaction(void)
1789 TransactionState s = CurrentTransactionState;
1790 TransactionId xid = GetCurrentTransactionId();
1791 GlobalTransaction gxact;
1792 TimestampTz prepared_at;
1794 ShowTransactionState("PrepareTransaction");
1797 * check the current transaction state
1799 if (s->state != TRANS_INPROGRESS)
1800 elog(WARNING, "PrepareTransaction while in %s state",
1801 TransStateAsString(s->state));
1802 Assert(s->parent == NULL);
1805 * Do pre-commit processing (most of this stuff requires database access,
1806 * and in fact could still cause an error...)
1808 * It is possible for PrepareHoldablePortals to invoke functions that
1809 * queue deferred triggers, and it's also possible that triggers create
1810 * holdable cursors. So we have to loop until there's nothing left to do.
1812 for (;;)
1815 * Fire all currently pending deferred triggers.
1817 AfterTriggerFireDeferred();
1820 * Convert any open holdable cursors into static portals. If there
1821 * weren't any, we are done ... otherwise loop back to check if they
1822 * queued deferred triggers. Lather, rinse, repeat.
1824 if (!PrepareHoldablePortals())
1825 break;
1828 /* Now we can shut down the deferred-trigger manager */
1829 AfterTriggerEndXact(true);
1831 /* Close any open regular cursors */
1832 AtCommit_Portals();
1835 * Let ON COMMIT management do its thing (must happen after closing
1836 * cursors, to avoid dangling-reference problems)
1838 PreCommit_on_commit_actions();
1840 /* close large objects before lower-level cleanup */
1841 AtEOXact_LargeObject(true);
1843 /* NOTIFY and flatfiles will be handled below */
1846 * Don't allow PREPARE TRANSACTION if we've accessed a temporary table
1847 * in this transaction. Having the prepared xact hold locks on another
1848 * backend's temp table seems a bad idea --- for instance it would prevent
1849 * the backend from exiting. There are other problems too, such as how
1850 * to clean up the source backend's local buffers and ON COMMIT state
1851 * if the prepared xact includes a DROP of a temp table.
1853 * We must check this after executing any ON COMMIT actions, because
1854 * they might still access a temp relation.
1856 * XXX In principle this could be relaxed to allow some useful special
1857 * cases, such as a temp table created and dropped all within the
1858 * transaction. That seems to require much more bookkeeping though.
1860 if (MyXactAccessedTempRel)
1861 ereport(ERROR,
1862 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1863 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1865 /* Prevent cancel/die interrupt while cleaning up */
1866 HOLD_INTERRUPTS();
1869 * set the current transaction state information appropriately during
1870 * prepare processing
1872 s->state = TRANS_PREPARE;
1874 prepared_at = GetCurrentTimestamp();
1876 /* Tell bufmgr and smgr to prepare for commit */
1877 BufmgrCommit();
1880 * Reserve the GID for this transaction. This could fail if the requested
1881 * GID is invalid or already in use.
1883 gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
1884 GetUserId(), MyDatabaseId);
1885 prepareGID = NULL;
1888 * Collect data for the 2PC state file. Note that in general, no actual
1889 * state change should happen in the called modules during this step,
1890 * since it's still possible to fail before commit, and in that case we
1891 * want transaction abort to be able to clean up. (In particular, the
1892 * AtPrepare routines may error out if they find cases they cannot
1893 * handle.) State cleanup should happen in the PostPrepare routines
1894 * below. However, some modules can go ahead and clear state here because
1895 * they wouldn't do anything with it during abort anyway.
1897 * Note: because the 2PC state file records will be replayed in the same
1898 * order they are made, the order of these calls has to match the order in
1899 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1900 * PREPARED; in particular, pay attention to whether things should happen
1901 * before or after releasing the transaction's locks.
1903 StartPrepare(gxact);
1905 AtPrepare_Notify();
1906 AtPrepare_UpdateFlatFiles();
1907 AtPrepare_Inval();
1908 AtPrepare_Locks();
1909 AtPrepare_PgStat();
1912 * Here is where we really truly prepare.
1914 * We have to record transaction prepares even if we didn't make any
1915 * updates, because the transaction manager might get confused if we lose
1916 * a global transaction.
1918 EndPrepare(gxact);
1921 * Now we clean up backend-internal state and release internal resources.
1924 /* Reset XactLastRecEnd until the next transaction writes something */
1925 XactLastRecEnd.xrecoff = 0;
1928 * Let others know about no transaction in progress by me. This has to be
1929 * done *after* the prepared transaction has been marked valid, else
1930 * someone may think it is unlocked and recyclable.
1932 ProcArrayClearTransaction(MyProc);
1935 * This is all post-transaction cleanup. Note that if an error is raised
1936 * here, it's too late to abort the transaction. This should be just
1937 * noncritical resource releasing. See notes in CommitTransaction.
1940 CallXactCallbacks(XACT_EVENT_PREPARE);
1942 ResourceOwnerRelease(TopTransactionResourceOwner,
1943 RESOURCE_RELEASE_BEFORE_LOCKS,
1944 true, true);
1946 /* Check we've released all buffer pins */
1947 AtEOXact_Buffers(true);
1949 /* Clean up the relation cache */
1950 AtEOXact_RelationCache(true);
1952 /* notify and flatfiles don't need a postprepare call */
1954 PostPrepare_PgStat();
1956 PostPrepare_Inval();
1958 PostPrepare_smgr();
1960 AtEOXact_MultiXact();
1962 PostPrepare_Locks(xid);
1964 ResourceOwnerRelease(TopTransactionResourceOwner,
1965 RESOURCE_RELEASE_LOCKS,
1966 true, true);
1967 ResourceOwnerRelease(TopTransactionResourceOwner,
1968 RESOURCE_RELEASE_AFTER_LOCKS,
1969 true, true);
1971 /* Check we've released all catcache entries */
1972 AtEOXact_CatCache(true);
1974 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1975 AtEOXact_GUC(true, 1);
1976 AtEOXact_SPI(true);
1977 AtEOXact_xml();
1978 AtEOXact_on_commit_actions(true);
1979 AtEOXact_Namespace(true);
1980 /* smgrcommit already done */
1981 AtEOXact_Files();
1982 AtEOXact_ComboCid();
1983 AtEOXact_HashTables(true);
1984 /* don't call AtEOXact_PgStat here */
1985 AtEOXact_Snapshot(true);
1987 CurrentResourceOwner = NULL;
1988 ResourceOwnerDelete(TopTransactionResourceOwner);
1989 s->curTransactionOwner = NULL;
1990 CurTransactionResourceOwner = NULL;
1991 TopTransactionResourceOwner = NULL;
1993 AtCommit_Memory();
1995 s->transactionId = InvalidTransactionId;
1996 s->subTransactionId = InvalidSubTransactionId;
1997 s->nestingLevel = 0;
1998 s->gucNestLevel = 0;
1999 s->childXids = NULL;
2000 s->nChildXids = 0;
2001 s->maxChildXids = 0;
2004 * done with 1st phase commit processing, set current transaction state
2005 * back to default
2007 s->state = TRANS_DEFAULT;
2009 RESUME_INTERRUPTS();
2014 * AbortTransaction
2016 static void
2017 AbortTransaction(void)
2019 TransactionState s = CurrentTransactionState;
2020 TransactionId latestXid;
2022 /* Prevent cancel/die interrupt while cleaning up */
2023 HOLD_INTERRUPTS();
2025 /* Make sure we have a valid memory context and resource owner */
2026 AtAbort_Memory();
2027 AtAbort_ResourceOwner();
2030 * Release any LW locks we might be holding as quickly as possible.
2031 * (Regular locks, however, must be held till we finish aborting.)
2032 * Releasing LW locks is critical since we might try to grab them again
2033 * while cleaning up!
2035 LWLockReleaseAll();
2037 /* Clean up buffer I/O and buffer context locks, too */
2038 AbortBufferIO();
2039 UnlockBuffers();
2042 * Also clean up any open wait for lock, since the lock manager will choke
2043 * if we try to wait for another lock before doing this.
2045 LockWaitCancel();
2048 * check the current transaction state
2050 if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
2051 elog(WARNING, "AbortTransaction while in %s state",
2052 TransStateAsString(s->state));
2053 Assert(s->parent == NULL);
2056 * set the current transaction state information appropriately during the
2057 * abort processing
2059 s->state = TRANS_ABORT;
2062 * Reset user ID which might have been changed transiently. We need this
2063 * to clean up in case control escaped out of a SECURITY DEFINER function
2064 * or other local change of CurrentUserId; therefore, the prior value
2065 * of SecurityDefinerContext also needs to be restored.
2067 * (Note: it is not necessary to restore session authorization or role
2068 * settings here because those can only be changed via GUC, and GUC will
2069 * take care of rolling them back if need be.)
2071 SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
2074 * do abort processing
2076 AfterTriggerEndXact(false);
2077 AtAbort_Portals();
2078 AtEOXact_LargeObject(false); /* 'false' means it's abort */
2079 AtAbort_Notify();
2080 AtEOXact_UpdateFlatFiles(false);
2083 * Advertise the fact that we aborted in pg_clog (assuming that we got as
2084 * far as assigning an XID to advertise).
2086 latestXid = RecordTransactionAbort(false);
2088 TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid);
2091 * Let others know about no transaction in progress by me. Note that this
2092 * must be done _before_ releasing locks we hold and _after_
2093 * RecordTransactionAbort.
2095 ProcArrayEndTransaction(MyProc, latestXid);
2098 * Post-abort cleanup. See notes in CommitTransaction() concerning
2099 * ordering.
2102 CallXactCallbacks(XACT_EVENT_ABORT);
2104 ResourceOwnerRelease(TopTransactionResourceOwner,
2105 RESOURCE_RELEASE_BEFORE_LOCKS,
2106 false, true);
2107 AtEOXact_Buffers(false);
2108 AtEOXact_RelationCache(false);
2109 AtEOXact_Inval(false);
2110 smgrDoPendingDeletes(false);
2111 AtEOXact_MultiXact();
2112 ResourceOwnerRelease(TopTransactionResourceOwner,
2113 RESOURCE_RELEASE_LOCKS,
2114 false, true);
2115 ResourceOwnerRelease(TopTransactionResourceOwner,
2116 RESOURCE_RELEASE_AFTER_LOCKS,
2117 false, true);
2118 AtEOXact_CatCache(false);
2120 AtEOXact_GUC(false, 1);
2121 AtEOXact_SPI(false);
2122 AtEOXact_xml();
2123 AtEOXact_on_commit_actions(false);
2124 AtEOXact_Namespace(false);
2125 smgrabort();
2126 AtEOXact_Files();
2127 AtEOXact_ComboCid();
2128 AtEOXact_HashTables(false);
2129 AtEOXact_PgStat(false);
2130 AtEOXact_Snapshot(false);
2131 pgstat_report_xact_timestamp(0);
2134 * State remains TRANS_ABORT until CleanupTransaction().
2136 RESUME_INTERRUPTS();
2140 * CleanupTransaction
2142 static void
2143 CleanupTransaction(void)
2145 TransactionState s = CurrentTransactionState;
2148 * State should still be TRANS_ABORT from AbortTransaction().
2150 if (s->state != TRANS_ABORT)
2151 elog(FATAL, "CleanupTransaction: unexpected state %s",
2152 TransStateAsString(s->state));
2155 * do abort cleanup processing
2157 AtCleanup_Portals(); /* now safe to release portal memory */
2159 CurrentResourceOwner = NULL; /* and resource owner */
2160 if (TopTransactionResourceOwner)
2161 ResourceOwnerDelete(TopTransactionResourceOwner);
2162 s->curTransactionOwner = NULL;
2163 CurTransactionResourceOwner = NULL;
2164 TopTransactionResourceOwner = NULL;
2166 AtCleanup_Memory(); /* and transaction memory */
2168 s->transactionId = InvalidTransactionId;
2169 s->subTransactionId = InvalidSubTransactionId;
2170 s->nestingLevel = 0;
2171 s->gucNestLevel = 0;
2172 s->childXids = NULL;
2173 s->nChildXids = 0;
2174 s->maxChildXids = 0;
2177 * done with abort processing, set current transaction state back to
2178 * default
2180 s->state = TRANS_DEFAULT;
2184 * StartTransactionCommand
2186 void
2187 StartTransactionCommand(void)
2189 TransactionState s = CurrentTransactionState;
2191 switch (s->blockState)
2194 * if we aren't in a transaction block, we just do our usual start
2195 * transaction.
2197 case TBLOCK_DEFAULT:
2198 StartTransaction();
2199 s->blockState = TBLOCK_STARTED;
2200 break;
2203 * We are somewhere in a transaction block or subtransaction and
2204 * about to start a new command. For now we do nothing, but
2205 * someday we may do command-local resource initialization. (Note
2206 * that any needed CommandCounterIncrement was done by the
2207 * previous CommitTransactionCommand.)
2209 case TBLOCK_INPROGRESS:
2210 case TBLOCK_SUBINPROGRESS:
2211 break;
2214 * Here we are in a failed transaction block (one of the commands
2215 * caused an abort) so we do nothing but remain in the abort
2216 * state. Eventually we will get a ROLLBACK command which will
2217 * get us out of this state. (It is up to other code to ensure
2218 * that no commands other than ROLLBACK will be processed in these
2219 * states.)
2221 case TBLOCK_ABORT:
2222 case TBLOCK_SUBABORT:
2223 break;
2225 /* These cases are invalid. */
2226 case TBLOCK_STARTED:
2227 case TBLOCK_BEGIN:
2228 case TBLOCK_SUBBEGIN:
2229 case TBLOCK_END:
2230 case TBLOCK_SUBEND:
2231 case TBLOCK_ABORT_END:
2232 case TBLOCK_SUBABORT_END:
2233 case TBLOCK_ABORT_PENDING:
2234 case TBLOCK_SUBABORT_PENDING:
2235 case TBLOCK_SUBRESTART:
2236 case TBLOCK_SUBABORT_RESTART:
2237 case TBLOCK_PREPARE:
2238 elog(ERROR, "StartTransactionCommand: unexpected state %s",
2239 BlockStateAsString(s->blockState));
2240 break;
2244 * We must switch to CurTransactionContext before returning. This is
2245 * already done if we called StartTransaction, otherwise not.
2247 Assert(CurTransactionContext != NULL);
2248 MemoryContextSwitchTo(CurTransactionContext);
2252 * CommitTransactionCommand
2254 void
2255 CommitTransactionCommand(void)
2257 TransactionState s = CurrentTransactionState;
2259 switch (s->blockState)
2262 * This shouldn't happen, because it means the previous
2263 * StartTransactionCommand didn't set the STARTED state
2264 * appropriately.
2266 case TBLOCK_DEFAULT:
2267 elog(FATAL, "CommitTransactionCommand: unexpected state %s",
2268 BlockStateAsString(s->blockState));
2269 break;
2272 * If we aren't in a transaction block, just do our usual
2273 * transaction commit, and return to the idle state.
2275 case TBLOCK_STARTED:
2276 CommitTransaction();
2277 s->blockState = TBLOCK_DEFAULT;
2278 break;
2281 * We are completing a "BEGIN TRANSACTION" command, so we change
2282 * to the "transaction block in progress" state and return. (We
2283 * assume the BEGIN did nothing to the database, so we need no
2284 * CommandCounterIncrement.)
2286 case TBLOCK_BEGIN:
2287 s->blockState = TBLOCK_INPROGRESS;
2288 break;
2291 * This is the case when we have finished executing a command
2292 * someplace within a transaction block. We increment the command
2293 * counter and return.
2295 case TBLOCK_INPROGRESS:
2296 case TBLOCK_SUBINPROGRESS:
2297 CommandCounterIncrement();
2298 break;
2301 * We are completing a "COMMIT" command. Do it and return to the
2302 * idle state.
2304 case TBLOCK_END:
2305 CommitTransaction();
2306 s->blockState = TBLOCK_DEFAULT;
2307 break;
2310 * Here we are in the middle of a transaction block but one of the
2311 * commands caused an abort so we do nothing but remain in the
2312 * abort state. Eventually we will get a ROLLBACK comand.
2314 case TBLOCK_ABORT:
2315 case TBLOCK_SUBABORT:
2316 break;
2319 * Here we were in an aborted transaction block and we just got
2320 * the ROLLBACK command from the user, so clean up the
2321 * already-aborted transaction and return to the idle state.
2323 case TBLOCK_ABORT_END:
2324 CleanupTransaction();
2325 s->blockState = TBLOCK_DEFAULT;
2326 break;
2329 * Here we were in a perfectly good transaction block but the user
2330 * told us to ROLLBACK anyway. We have to abort the transaction
2331 * and then clean up.
2333 case TBLOCK_ABORT_PENDING:
2334 AbortTransaction();
2335 CleanupTransaction();
2336 s->blockState = TBLOCK_DEFAULT;
2337 break;
2340 * We are completing a "PREPARE TRANSACTION" command. Do it and
2341 * return to the idle state.
2343 case TBLOCK_PREPARE:
2344 PrepareTransaction();
2345 s->blockState = TBLOCK_DEFAULT;
2346 break;
2349 * We were just issued a SAVEPOINT inside a transaction block.
2350 * Start a subtransaction. (DefineSavepoint already did
2351 * PushTransaction, so as to have someplace to put the SUBBEGIN
2352 * state.)
2354 case TBLOCK_SUBBEGIN:
2355 StartSubTransaction();
2356 s->blockState = TBLOCK_SUBINPROGRESS;
2357 break;
2360 * We were issued a COMMIT or RELEASE command, so we end the
2361 * current subtransaction and return to the parent transaction.
2362 * The parent might be ended too, so repeat till we are all the
2363 * way out or find an INPROGRESS transaction.
2365 case TBLOCK_SUBEND:
2368 CommitSubTransaction();
2369 s = CurrentTransactionState; /* changed by pop */
2370 } while (s->blockState == TBLOCK_SUBEND);
2371 /* If we had a COMMIT command, finish off the main xact too */
2372 if (s->blockState == TBLOCK_END)
2374 Assert(s->parent == NULL);
2375 CommitTransaction();
2376 s->blockState = TBLOCK_DEFAULT;
2378 else if (s->blockState == TBLOCK_PREPARE)
2380 Assert(s->parent == NULL);
2381 PrepareTransaction();
2382 s->blockState = TBLOCK_DEFAULT;
2384 else
2386 Assert(s->blockState == TBLOCK_INPROGRESS ||
2387 s->blockState == TBLOCK_SUBINPROGRESS);
2389 break;
2392 * The current already-failed subtransaction is ending due to a
2393 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2394 * examine the parent (which could be in any of several states).
2396 case TBLOCK_SUBABORT_END:
2397 CleanupSubTransaction();
2398 CommitTransactionCommand();
2399 break;
2402 * As above, but it's not dead yet, so abort first.
2404 case TBLOCK_SUBABORT_PENDING:
2405 AbortSubTransaction();
2406 CleanupSubTransaction();
2407 CommitTransactionCommand();
2408 break;
2411 * The current subtransaction is the target of a ROLLBACK TO
2412 * command. Abort and pop it, then start a new subtransaction
2413 * with the same name.
2415 case TBLOCK_SUBRESTART:
2417 char *name;
2418 int savepointLevel;
2420 /* save name and keep Cleanup from freeing it */
2421 name = s->name;
2422 s->name = NULL;
2423 savepointLevel = s->savepointLevel;
2425 AbortSubTransaction();
2426 CleanupSubTransaction();
2428 DefineSavepoint(NULL);
2429 s = CurrentTransactionState; /* changed by push */
2430 s->name = name;
2431 s->savepointLevel = savepointLevel;
2433 /* This is the same as TBLOCK_SUBBEGIN case */
2434 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2435 StartSubTransaction();
2436 s->blockState = TBLOCK_SUBINPROGRESS;
2438 break;
2441 * Same as above, but the subtransaction had already failed, so we
2442 * don't need AbortSubTransaction.
2444 case TBLOCK_SUBABORT_RESTART:
2446 char *name;
2447 int savepointLevel;
2449 /* save name and keep Cleanup from freeing it */
2450 name = s->name;
2451 s->name = NULL;
2452 savepointLevel = s->savepointLevel;
2454 CleanupSubTransaction();
2456 DefineSavepoint(NULL);
2457 s = CurrentTransactionState; /* changed by push */
2458 s->name = name;
2459 s->savepointLevel = savepointLevel;
2461 /* This is the same as TBLOCK_SUBBEGIN case */
2462 AssertState(s->blockState == TBLOCK_SUBBEGIN);
2463 StartSubTransaction();
2464 s->blockState = TBLOCK_SUBINPROGRESS;
2466 break;
2471 * AbortCurrentTransaction
2473 void
2474 AbortCurrentTransaction(void)
2476 TransactionState s = CurrentTransactionState;
2478 switch (s->blockState)
2480 case TBLOCK_DEFAULT:
2481 if (s->state == TRANS_DEFAULT)
2483 /* we are idle, so nothing to do */
2485 else
2488 * We can get here after an error during transaction start
2489 * (state will be TRANS_START). Need to clean up the
2490 * incompletely started transaction. First, adjust the
2491 * low-level state to suppress warning message from
2492 * AbortTransaction.
2494 if (s->state == TRANS_START)
2495 s->state = TRANS_INPROGRESS;
2496 AbortTransaction();
2497 CleanupTransaction();
2499 break;
2502 * if we aren't in a transaction block, we just do the basic abort
2503 * & cleanup transaction.
2505 case TBLOCK_STARTED:
2506 AbortTransaction();
2507 CleanupTransaction();
2508 s->blockState = TBLOCK_DEFAULT;
2509 break;
2512 * If we are in TBLOCK_BEGIN it means something screwed up right
2513 * after reading "BEGIN TRANSACTION". We assume that the user
2514 * will interpret the error as meaning the BEGIN failed to get him
2515 * into a transaction block, so we should abort and return to idle
2516 * state.
2518 case TBLOCK_BEGIN:
2519 AbortTransaction();
2520 CleanupTransaction();
2521 s->blockState = TBLOCK_DEFAULT;
2522 break;
2525 * We are somewhere in a transaction block and we've gotten a
2526 * failure, so we abort the transaction and set up the persistent
2527 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2529 case TBLOCK_INPROGRESS:
2530 AbortTransaction();
2531 s->blockState = TBLOCK_ABORT;
2532 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2533 break;
2536 * Here, we failed while trying to COMMIT. Clean up the
2537 * transaction and return to idle state (we do not want to stay in
2538 * the transaction).
2540 case TBLOCK_END:
2541 AbortTransaction();
2542 CleanupTransaction();
2543 s->blockState = TBLOCK_DEFAULT;
2544 break;
2547 * Here, we are already in an aborted transaction state and are
2548 * waiting for a ROLLBACK, but for some reason we failed again! So
2549 * we just remain in the abort state.
2551 case TBLOCK_ABORT:
2552 case TBLOCK_SUBABORT:
2553 break;
2556 * We are in a failed transaction and we got the ROLLBACK command.
2557 * We have already aborted, we just need to cleanup and go to idle
2558 * state.
2560 case TBLOCK_ABORT_END:
2561 CleanupTransaction();
2562 s->blockState = TBLOCK_DEFAULT;
2563 break;
2566 * We are in a live transaction and we got a ROLLBACK command.
2567 * Abort, cleanup, go to idle state.
2569 case TBLOCK_ABORT_PENDING:
2570 AbortTransaction();
2571 CleanupTransaction();
2572 s->blockState = TBLOCK_DEFAULT;
2573 break;
2576 * Here, we failed while trying to PREPARE. Clean up the
2577 * transaction and return to idle state (we do not want to stay in
2578 * the transaction).
2580 case TBLOCK_PREPARE:
2581 AbortTransaction();
2582 CleanupTransaction();
2583 s->blockState = TBLOCK_DEFAULT;
2584 break;
2587 * We got an error inside a subtransaction. Abort just the
2588 * subtransaction, and go to the persistent SUBABORT state until
2589 * we get ROLLBACK.
2591 case TBLOCK_SUBINPROGRESS:
2592 AbortSubTransaction();
2593 s->blockState = TBLOCK_SUBABORT;
2594 break;
2597 * If we failed while trying to create a subtransaction, clean up
2598 * the broken subtransaction and abort the parent. The same
2599 * applies if we get a failure while ending a subtransaction.
2601 case TBLOCK_SUBBEGIN:
2602 case TBLOCK_SUBEND:
2603 case TBLOCK_SUBABORT_PENDING:
2604 case TBLOCK_SUBRESTART:
2605 AbortSubTransaction();
2606 CleanupSubTransaction();
2607 AbortCurrentTransaction();
2608 break;
2611 * Same as above, except the Abort() was already done.
2613 case TBLOCK_SUBABORT_END:
2614 case TBLOCK_SUBABORT_RESTART:
2615 CleanupSubTransaction();
2616 AbortCurrentTransaction();
2617 break;
2622 * PreventTransactionChain
2624 * This routine is to be called by statements that must not run inside
2625 * a transaction block, typically because they have non-rollback-able
2626 * side effects or do internal commits.
2628 * If we have already started a transaction block, issue an error; also issue
2629 * an error if we appear to be running inside a user-defined function (which
2630 * could issue more commands and possibly cause a failure after the statement
2631 * completes). Subtransactions are verboten too.
2633 * isTopLevel: passed down from ProcessUtility to determine whether we are
2634 * inside a function or multi-query querystring. (We will always fail if
2635 * this is false, but it's convenient to centralize the check here instead of
2636 * making callers do it.)
2637 * stmtType: statement type name, for error messages.
2639 void
2640 PreventTransactionChain(bool isTopLevel, const char *stmtType)
2643 * xact block already started?
2645 if (IsTransactionBlock())
2646 ereport(ERROR,
2647 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2648 /* translator: %s represents an SQL statement name */
2649 errmsg("%s cannot run inside a transaction block",
2650 stmtType)));
2653 * subtransaction?
2655 if (IsSubTransaction())
2656 ereport(ERROR,
2657 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2658 /* translator: %s represents an SQL statement name */
2659 errmsg("%s cannot run inside a subtransaction",
2660 stmtType)));
2663 * inside a function call?
2665 if (!isTopLevel)
2666 ereport(ERROR,
2667 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2668 /* translator: %s represents an SQL statement name */
2669 errmsg("%s cannot be executed from a function or multi-command string",
2670 stmtType)));
2672 /* If we got past IsTransactionBlock test, should be in default state */
2673 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2674 CurrentTransactionState->blockState != TBLOCK_STARTED)
2675 elog(FATAL, "cannot prevent transaction chain");
2676 /* all okay */
2680 * RequireTransactionChain
2682 * This routine is to be called by statements that must run inside
2683 * a transaction block, because they have no effects that persist past
2684 * transaction end (and so calling them outside a transaction block
2685 * is presumably an error). DECLARE CURSOR is an example.
2687 * If we appear to be running inside a user-defined function, we do not
2688 * issue an error, since the function could issue more commands that make
2689 * use of the current statement's results. Likewise subtransactions.
2690 * Thus this is an inverse for PreventTransactionChain.
2692 * isTopLevel: passed down from ProcessUtility to determine whether we are
2693 * inside a function.
2694 * stmtType: statement type name, for error messages.
2696 void
2697 RequireTransactionChain(bool isTopLevel, const char *stmtType)
2700 * xact block already started?
2702 if (IsTransactionBlock())
2703 return;
2706 * subtransaction?
2708 if (IsSubTransaction())
2709 return;
2712 * inside a function call?
2714 if (!isTopLevel)
2715 return;
2717 ereport(ERROR,
2718 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
2719 /* translator: %s represents an SQL statement name */
2720 errmsg("%s can only be used in transaction blocks",
2721 stmtType)));
2725 * IsInTransactionChain
2727 * This routine is for statements that need to behave differently inside
2728 * a transaction block than when running as single commands. ANALYZE is
2729 * currently the only example.
2731 * isTopLevel: passed down from ProcessUtility to determine whether we are
2732 * inside a function.
2734 bool
2735 IsInTransactionChain(bool isTopLevel)
2738 * Return true on same conditions that would make PreventTransactionChain
2739 * error out
2741 if (IsTransactionBlock())
2742 return true;
2744 if (IsSubTransaction())
2745 return true;
2747 if (!isTopLevel)
2748 return true;
2750 if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
2751 CurrentTransactionState->blockState != TBLOCK_STARTED)
2752 return true;
2754 return false;
2759 * Register or deregister callback functions for start- and end-of-xact
2760 * operations.
2762 * These functions are intended for use by dynamically loaded modules.
2763 * For built-in modules we generally just hardwire the appropriate calls
2764 * (mainly because it's easier to control the order that way, where needed).
2766 * At transaction end, the callback occurs post-commit or post-abort, so the
2767 * callback functions can only do noncritical cleanup.
2769 void
2770 RegisterXactCallback(XactCallback callback, void *arg)
2772 XactCallbackItem *item;
2774 item = (XactCallbackItem *)
2775 MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
2776 item->callback = callback;
2777 item->arg = arg;
2778 item->next = Xact_callbacks;
2779 Xact_callbacks = item;
2782 void
2783 UnregisterXactCallback(XactCallback callback, void *arg)
2785 XactCallbackItem *item;
2786 XactCallbackItem *prev;
2788 prev = NULL;
2789 for (item = Xact_callbacks; item; prev = item, item = item->next)
2791 if (item->callback == callback && item->arg == arg)
2793 if (prev)
2794 prev->next = item->next;
2795 else
2796 Xact_callbacks = item->next;
2797 pfree(item);
2798 break;
2803 static void
2804 CallXactCallbacks(XactEvent event)
2806 XactCallbackItem *item;
2808 for (item = Xact_callbacks; item; item = item->next)
2809 (*item->callback) (event, item->arg);
2814 * Register or deregister callback functions for start- and end-of-subxact
2815 * operations.
2817 * Pretty much same as above, but for subtransaction events.
2819 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2820 * so the callback functions can only do noncritical cleanup. At
2821 * subtransaction start, the callback is called when the subtransaction has
2822 * finished initializing.
2824 void
2825 RegisterSubXactCallback(SubXactCallback callback, void *arg)
2827 SubXactCallbackItem *item;
2829 item = (SubXactCallbackItem *)
2830 MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
2831 item->callback = callback;
2832 item->arg = arg;
2833 item->next = SubXact_callbacks;
2834 SubXact_callbacks = item;
2837 void
2838 UnregisterSubXactCallback(SubXactCallback callback, void *arg)
2840 SubXactCallbackItem *item;
2841 SubXactCallbackItem *prev;
2843 prev = NULL;
2844 for (item = SubXact_callbacks; item; prev = item, item = item->next)
2846 if (item->callback == callback && item->arg == arg)
2848 if (prev)
2849 prev->next = item->next;
2850 else
2851 SubXact_callbacks = item->next;
2852 pfree(item);
2853 break;
2858 static void
2859 CallSubXactCallbacks(SubXactEvent event,
2860 SubTransactionId mySubid,
2861 SubTransactionId parentSubid)
2863 SubXactCallbackItem *item;
2865 for (item = SubXact_callbacks; item; item = item->next)
2866 (*item->callback) (event, mySubid, parentSubid, item->arg);
2870 /* ----------------------------------------------------------------
2871 * transaction block support
2872 * ----------------------------------------------------------------
2876 * BeginTransactionBlock
2877 * This executes a BEGIN command.
2879 void
2880 BeginTransactionBlock(void)
2882 TransactionState s = CurrentTransactionState;
2884 switch (s->blockState)
2887 * We are not inside a transaction block, so allow one to begin.
2889 case TBLOCK_STARTED:
2890 s->blockState = TBLOCK_BEGIN;
2891 break;
2894 * Already a transaction block in progress.
2896 case TBLOCK_INPROGRESS:
2897 case TBLOCK_SUBINPROGRESS:
2898 case TBLOCK_ABORT:
2899 case TBLOCK_SUBABORT:
2900 ereport(WARNING,
2901 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
2902 errmsg("there is already a transaction in progress")));
2903 break;
2905 /* These cases are invalid. */
2906 case TBLOCK_DEFAULT:
2907 case TBLOCK_BEGIN:
2908 case TBLOCK_SUBBEGIN:
2909 case TBLOCK_END:
2910 case TBLOCK_SUBEND:
2911 case TBLOCK_ABORT_END:
2912 case TBLOCK_SUBABORT_END:
2913 case TBLOCK_ABORT_PENDING:
2914 case TBLOCK_SUBABORT_PENDING:
2915 case TBLOCK_SUBRESTART:
2916 case TBLOCK_SUBABORT_RESTART:
2917 case TBLOCK_PREPARE:
2918 elog(FATAL, "BeginTransactionBlock: unexpected state %s",
2919 BlockStateAsString(s->blockState));
2920 break;
2925 * PrepareTransactionBlock
2926 * This executes a PREPARE command.
2928 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2929 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2931 * Note that we don't actually do anything here except change blockState.
2932 * The real work will be done in the upcoming PrepareTransaction().
2933 * We do it this way because it's not convenient to change memory context,
2934 * resource owner, etc while executing inside a Portal.
2936 bool
2937 PrepareTransactionBlock(char *gid)
2939 TransactionState s;
2940 bool result;
2942 /* Set up to commit the current transaction */
2943 result = EndTransactionBlock();
2945 /* If successful, change outer tblock state to PREPARE */
2946 if (result)
2948 s = CurrentTransactionState;
2950 while (s->parent != NULL)
2951 s = s->parent;
2953 if (s->blockState == TBLOCK_END)
2955 /* Save GID where PrepareTransaction can find it again */
2956 prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
2958 s->blockState = TBLOCK_PREPARE;
2960 else
2963 * ignore case where we are not in a transaction;
2964 * EndTransactionBlock already issued a warning.
2966 Assert(s->blockState == TBLOCK_STARTED);
2967 /* Don't send back a PREPARE result tag... */
2968 result = false;
2972 return result;
2976 * EndTransactionBlock
2977 * This executes a COMMIT command.
2979 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2980 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2982 * Note that we don't actually do anything here except change blockState.
2983 * The real work will be done in the upcoming CommitTransactionCommand().
2984 * We do it this way because it's not convenient to change memory context,
2985 * resource owner, etc while executing inside a Portal.
2987 bool
2988 EndTransactionBlock(void)
2990 TransactionState s = CurrentTransactionState;
2991 bool result = false;
2993 switch (s->blockState)
2996 * We are in a transaction block, so tell CommitTransactionCommand
2997 * to COMMIT.
2999 case TBLOCK_INPROGRESS:
3000 s->blockState = TBLOCK_END;
3001 result = true;
3002 break;
3005 * We are in a failed transaction block. Tell
3006 * CommitTransactionCommand it's time to exit the block.
3008 case TBLOCK_ABORT:
3009 s->blockState = TBLOCK_ABORT_END;
3010 break;
3013 * We are in a live subtransaction block. Set up to subcommit all
3014 * open subtransactions and then commit the main transaction.
3016 case TBLOCK_SUBINPROGRESS:
3017 while (s->parent != NULL)
3019 if (s->blockState == TBLOCK_SUBINPROGRESS)
3020 s->blockState = TBLOCK_SUBEND;
3021 else
3022 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3023 BlockStateAsString(s->blockState));
3024 s = s->parent;
3026 if (s->blockState == TBLOCK_INPROGRESS)
3027 s->blockState = TBLOCK_END;
3028 else
3029 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3030 BlockStateAsString(s->blockState));
3031 result = true;
3032 break;
3035 * Here we are inside an aborted subtransaction. Treat the COMMIT
3036 * as ROLLBACK: set up to abort everything and exit the main
3037 * transaction.
3039 case TBLOCK_SUBABORT:
3040 while (s->parent != NULL)
3042 if (s->blockState == TBLOCK_SUBINPROGRESS)
3043 s->blockState = TBLOCK_SUBABORT_PENDING;
3044 else if (s->blockState == TBLOCK_SUBABORT)
3045 s->blockState = TBLOCK_SUBABORT_END;
3046 else
3047 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3048 BlockStateAsString(s->blockState));
3049 s = s->parent;
3051 if (s->blockState == TBLOCK_INPROGRESS)
3052 s->blockState = TBLOCK_ABORT_PENDING;
3053 else if (s->blockState == TBLOCK_ABORT)
3054 s->blockState = TBLOCK_ABORT_END;
3055 else
3056 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3057 BlockStateAsString(s->blockState));
3058 break;
3061 * The user issued COMMIT when not inside a transaction. Issue a
3062 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
3063 * CommitTransactionCommand() will then close the transaction and
3064 * put us back into the default state.
3066 case TBLOCK_STARTED:
3067 ereport(WARNING,
3068 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3069 errmsg("there is no transaction in progress")));
3070 result = true;
3071 break;
3073 /* These cases are invalid. */
3074 case TBLOCK_DEFAULT:
3075 case TBLOCK_BEGIN:
3076 case TBLOCK_SUBBEGIN:
3077 case TBLOCK_END:
3078 case TBLOCK_SUBEND:
3079 case TBLOCK_ABORT_END:
3080 case TBLOCK_SUBABORT_END:
3081 case TBLOCK_ABORT_PENDING:
3082 case TBLOCK_SUBABORT_PENDING:
3083 case TBLOCK_SUBRESTART:
3084 case TBLOCK_SUBABORT_RESTART:
3085 case TBLOCK_PREPARE:
3086 elog(FATAL, "EndTransactionBlock: unexpected state %s",
3087 BlockStateAsString(s->blockState));
3088 break;
3091 return result;
3095 * UserAbortTransactionBlock
3096 * This executes a ROLLBACK command.
3098 * As above, we don't actually do anything here except change blockState.
3100 void
3101 UserAbortTransactionBlock(void)
3103 TransactionState s = CurrentTransactionState;
3105 switch (s->blockState)
3108 * We are inside a transaction block and we got a ROLLBACK command
3109 * from the user, so tell CommitTransactionCommand to abort and
3110 * exit the transaction block.
3112 case TBLOCK_INPROGRESS:
3113 s->blockState = TBLOCK_ABORT_PENDING;
3114 break;
3117 * We are inside a failed transaction block and we got a ROLLBACK
3118 * command from the user. Abort processing is already done, so
3119 * CommitTransactionCommand just has to cleanup and go back to
3120 * idle state.
3122 case TBLOCK_ABORT:
3123 s->blockState = TBLOCK_ABORT_END;
3124 break;
3127 * We are inside a subtransaction. Mark everything up to top
3128 * level as exitable.
3130 case TBLOCK_SUBINPROGRESS:
3131 case TBLOCK_SUBABORT:
3132 while (s->parent != NULL)
3134 if (s->blockState == TBLOCK_SUBINPROGRESS)
3135 s->blockState = TBLOCK_SUBABORT_PENDING;
3136 else if (s->blockState == TBLOCK_SUBABORT)
3137 s->blockState = TBLOCK_SUBABORT_END;
3138 else
3139 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3140 BlockStateAsString(s->blockState));
3141 s = s->parent;
3143 if (s->blockState == TBLOCK_INPROGRESS)
3144 s->blockState = TBLOCK_ABORT_PENDING;
3145 else if (s->blockState == TBLOCK_ABORT)
3146 s->blockState = TBLOCK_ABORT_END;
3147 else
3148 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3149 BlockStateAsString(s->blockState));
3150 break;
3153 * The user issued ABORT when not inside a transaction. Issue a
3154 * WARNING and go to abort state. The upcoming call to
3155 * CommitTransactionCommand() will then put us back into the
3156 * default state.
3158 case TBLOCK_STARTED:
3159 ereport(NOTICE,
3160 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
3161 errmsg("there is no transaction in progress")));
3162 s->blockState = TBLOCK_ABORT_PENDING;
3163 break;
3165 /* These cases are invalid. */
3166 case TBLOCK_DEFAULT:
3167 case TBLOCK_BEGIN:
3168 case TBLOCK_SUBBEGIN:
3169 case TBLOCK_END:
3170 case TBLOCK_SUBEND:
3171 case TBLOCK_ABORT_END:
3172 case TBLOCK_SUBABORT_END:
3173 case TBLOCK_ABORT_PENDING:
3174 case TBLOCK_SUBABORT_PENDING:
3175 case TBLOCK_SUBRESTART:
3176 case TBLOCK_SUBABORT_RESTART:
3177 case TBLOCK_PREPARE:
3178 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
3179 BlockStateAsString(s->blockState));
3180 break;
3185 * DefineSavepoint
3186 * This executes a SAVEPOINT command.
3188 void
3189 DefineSavepoint(char *name)
3191 TransactionState s = CurrentTransactionState;
3193 switch (s->blockState)
3195 case TBLOCK_INPROGRESS:
3196 case TBLOCK_SUBINPROGRESS:
3197 /* Normal subtransaction start */
3198 PushTransaction();
3199 s = CurrentTransactionState; /* changed by push */
3202 * Savepoint names, like the TransactionState block itself, live
3203 * in TopTransactionContext.
3205 if (name)
3206 s->name = MemoryContextStrdup(TopTransactionContext, name);
3207 break;
3209 /* These cases are invalid. */
3210 case TBLOCK_DEFAULT:
3211 case TBLOCK_STARTED:
3212 case TBLOCK_BEGIN:
3213 case TBLOCK_SUBBEGIN:
3214 case TBLOCK_END:
3215 case TBLOCK_SUBEND:
3216 case TBLOCK_ABORT:
3217 case TBLOCK_SUBABORT:
3218 case TBLOCK_ABORT_END:
3219 case TBLOCK_SUBABORT_END:
3220 case TBLOCK_ABORT_PENDING:
3221 case TBLOCK_SUBABORT_PENDING:
3222 case TBLOCK_SUBRESTART:
3223 case TBLOCK_SUBABORT_RESTART:
3224 case TBLOCK_PREPARE:
3225 elog(FATAL, "DefineSavepoint: unexpected state %s",
3226 BlockStateAsString(s->blockState));
3227 break;
3232 * ReleaseSavepoint
3233 * This executes a RELEASE command.
3235 * As above, we don't actually do anything here except change blockState.
3237 void
3238 ReleaseSavepoint(List *options)
3240 TransactionState s = CurrentTransactionState;
3241 TransactionState target,
3242 xact;
3243 ListCell *cell;
3244 char *name = NULL;
3246 switch (s->blockState)
3249 * We can't rollback to a savepoint if there is no savepoint
3250 * defined.
3252 case TBLOCK_INPROGRESS:
3253 ereport(ERROR,
3254 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3255 errmsg("no such savepoint")));
3256 break;
3259 * We are in a non-aborted subtransaction. This is the only valid
3260 * case.
3262 case TBLOCK_SUBINPROGRESS:
3263 break;
3265 /* These cases are invalid. */
3266 case TBLOCK_DEFAULT:
3267 case TBLOCK_STARTED:
3268 case TBLOCK_BEGIN:
3269 case TBLOCK_SUBBEGIN:
3270 case TBLOCK_END:
3271 case TBLOCK_SUBEND:
3272 case TBLOCK_ABORT:
3273 case TBLOCK_SUBABORT:
3274 case TBLOCK_ABORT_END:
3275 case TBLOCK_SUBABORT_END:
3276 case TBLOCK_ABORT_PENDING:
3277 case TBLOCK_SUBABORT_PENDING:
3278 case TBLOCK_SUBRESTART:
3279 case TBLOCK_SUBABORT_RESTART:
3280 case TBLOCK_PREPARE:
3281 elog(FATAL, "ReleaseSavepoint: unexpected state %s",
3282 BlockStateAsString(s->blockState));
3283 break;
3286 foreach(cell, options)
3288 DefElem *elem = lfirst(cell);
3290 if (strcmp(elem->defname, "savepoint_name") == 0)
3291 name = strVal(elem->arg);
3294 Assert(PointerIsValid(name));
3296 for (target = s; PointerIsValid(target); target = target->parent)
3298 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3299 break;
3302 if (!PointerIsValid(target))
3303 ereport(ERROR,
3304 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3305 errmsg("no such savepoint")));
3307 /* disallow crossing savepoint level boundaries */
3308 if (target->savepointLevel != s->savepointLevel)
3309 ereport(ERROR,
3310 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3311 errmsg("no such savepoint")));
3314 * Mark "commit pending" all subtransactions up to the target
3315 * subtransaction. The actual commits will happen when control gets to
3316 * CommitTransactionCommand.
3318 xact = CurrentTransactionState;
3319 for (;;)
3321 Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
3322 xact->blockState = TBLOCK_SUBEND;
3323 if (xact == target)
3324 break;
3325 xact = xact->parent;
3326 Assert(PointerIsValid(xact));
3331 * RollbackToSavepoint
3332 * This executes a ROLLBACK TO <savepoint> command.
3334 * As above, we don't actually do anything here except change blockState.
3336 void
3337 RollbackToSavepoint(List *options)
3339 TransactionState s = CurrentTransactionState;
3340 TransactionState target,
3341 xact;
3342 ListCell *cell;
3343 char *name = NULL;
3345 switch (s->blockState)
3348 * We can't rollback to a savepoint if there is no savepoint
3349 * defined.
3351 case TBLOCK_INPROGRESS:
3352 case TBLOCK_ABORT:
3353 ereport(ERROR,
3354 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3355 errmsg("no such savepoint")));
3356 break;
3359 * There is at least one savepoint, so proceed.
3361 case TBLOCK_SUBINPROGRESS:
3362 case TBLOCK_SUBABORT:
3363 break;
3365 /* These cases are invalid. */
3366 case TBLOCK_DEFAULT:
3367 case TBLOCK_STARTED:
3368 case TBLOCK_BEGIN:
3369 case TBLOCK_SUBBEGIN:
3370 case TBLOCK_END:
3371 case TBLOCK_SUBEND:
3372 case TBLOCK_ABORT_END:
3373 case TBLOCK_SUBABORT_END:
3374 case TBLOCK_ABORT_PENDING:
3375 case TBLOCK_SUBABORT_PENDING:
3376 case TBLOCK_SUBRESTART:
3377 case TBLOCK_SUBABORT_RESTART:
3378 case TBLOCK_PREPARE:
3379 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3380 BlockStateAsString(s->blockState));
3381 break;
3384 foreach(cell, options)
3386 DefElem *elem = lfirst(cell);
3388 if (strcmp(elem->defname, "savepoint_name") == 0)
3389 name = strVal(elem->arg);
3392 Assert(PointerIsValid(name));
3394 for (target = s; PointerIsValid(target); target = target->parent)
3396 if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
3397 break;
3400 if (!PointerIsValid(target))
3401 ereport(ERROR,
3402 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3403 errmsg("no such savepoint")));
3405 /* disallow crossing savepoint level boundaries */
3406 if (target->savepointLevel != s->savepointLevel)
3407 ereport(ERROR,
3408 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
3409 errmsg("no such savepoint")));
3412 * Mark "abort pending" all subtransactions up to the target
3413 * subtransaction. The actual aborts will happen when control gets to
3414 * CommitTransactionCommand.
3416 xact = CurrentTransactionState;
3417 for (;;)
3419 if (xact == target)
3420 break;
3421 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3422 xact->blockState = TBLOCK_SUBABORT_PENDING;
3423 else if (xact->blockState == TBLOCK_SUBABORT)
3424 xact->blockState = TBLOCK_SUBABORT_END;
3425 else
3426 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3427 BlockStateAsString(xact->blockState));
3428 xact = xact->parent;
3429 Assert(PointerIsValid(xact));
3432 /* And mark the target as "restart pending" */
3433 if (xact->blockState == TBLOCK_SUBINPROGRESS)
3434 xact->blockState = TBLOCK_SUBRESTART;
3435 else if (xact->blockState == TBLOCK_SUBABORT)
3436 xact->blockState = TBLOCK_SUBABORT_RESTART;
3437 else
3438 elog(FATAL, "RollbackToSavepoint: unexpected state %s",
3439 BlockStateAsString(xact->blockState));
3443 * BeginInternalSubTransaction
3444 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3445 * TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3446 * used in functions that might be called when not inside a BEGIN block
3447 * or when running deferred triggers at COMMIT/PREPARE time. Also, it
3448 * automatically does CommitTransactionCommand/StartTransactionCommand
3449 * instead of expecting the caller to do it.
3451 void
3452 BeginInternalSubTransaction(char *name)
3454 TransactionState s = CurrentTransactionState;
3456 switch (s->blockState)
3458 case TBLOCK_STARTED:
3459 case TBLOCK_INPROGRESS:
3460 case TBLOCK_END:
3461 case TBLOCK_PREPARE:
3462 case TBLOCK_SUBINPROGRESS:
3463 /* Normal subtransaction start */
3464 PushTransaction();
3465 s = CurrentTransactionState; /* changed by push */
3468 * Savepoint names, like the TransactionState block itself, live
3469 * in TopTransactionContext.
3471 if (name)
3472 s->name = MemoryContextStrdup(TopTransactionContext, name);
3473 break;
3475 /* These cases are invalid. */
3476 case TBLOCK_DEFAULT:
3477 case TBLOCK_BEGIN:
3478 case TBLOCK_SUBBEGIN:
3479 case TBLOCK_SUBEND:
3480 case TBLOCK_ABORT:
3481 case TBLOCK_SUBABORT:
3482 case TBLOCK_ABORT_END:
3483 case TBLOCK_SUBABORT_END:
3484 case TBLOCK_ABORT_PENDING:
3485 case TBLOCK_SUBABORT_PENDING:
3486 case TBLOCK_SUBRESTART:
3487 case TBLOCK_SUBABORT_RESTART:
3488 elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
3489 BlockStateAsString(s->blockState));
3490 break;
3493 CommitTransactionCommand();
3494 StartTransactionCommand();
3498 * ReleaseCurrentSubTransaction
3500 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3501 * savepoint name (if any).
3502 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3504 void
3505 ReleaseCurrentSubTransaction(void)
3507 TransactionState s = CurrentTransactionState;
3509 if (s->blockState != TBLOCK_SUBINPROGRESS)
3510 elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
3511 BlockStateAsString(s->blockState));
3512 Assert(s->state == TRANS_INPROGRESS);
3513 MemoryContextSwitchTo(CurTransactionContext);
3514 CommitSubTransaction();
3515 s = CurrentTransactionState; /* changed by pop */
3516 Assert(s->state == TRANS_INPROGRESS);
3520 * RollbackAndReleaseCurrentSubTransaction
3522 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3523 * of its savepoint name (if any).
3524 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3526 void
3527 RollbackAndReleaseCurrentSubTransaction(void)
3529 TransactionState s = CurrentTransactionState;
3531 switch (s->blockState)
3533 /* Must be in a subtransaction */
3534 case TBLOCK_SUBINPROGRESS:
3535 case TBLOCK_SUBABORT:
3536 break;
3538 /* These cases are invalid. */
3539 case TBLOCK_DEFAULT:
3540 case TBLOCK_STARTED:
3541 case TBLOCK_BEGIN:
3542 case TBLOCK_SUBBEGIN:
3543 case TBLOCK_INPROGRESS:
3544 case TBLOCK_END:
3545 case TBLOCK_SUBEND:
3546 case TBLOCK_ABORT:
3547 case TBLOCK_ABORT_END:
3548 case TBLOCK_SUBABORT_END:
3549 case TBLOCK_ABORT_PENDING:
3550 case TBLOCK_SUBABORT_PENDING:
3551 case TBLOCK_SUBRESTART:
3552 case TBLOCK_SUBABORT_RESTART:
3553 case TBLOCK_PREPARE:
3554 elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3555 BlockStateAsString(s->blockState));
3556 break;
3560 * Abort the current subtransaction, if needed.
3562 if (s->blockState == TBLOCK_SUBINPROGRESS)
3563 AbortSubTransaction();
3565 /* And clean it up, too */
3566 CleanupSubTransaction();
3568 s = CurrentTransactionState; /* changed by pop */
3569 AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
3570 s->blockState == TBLOCK_INPROGRESS ||
3571 s->blockState == TBLOCK_STARTED);
3575 * AbortOutOfAnyTransaction
3577 * This routine is provided for error recovery purposes. It aborts any
3578 * active transaction or transaction block, leaving the system in a known
3579 * idle state.
3581 void
3582 AbortOutOfAnyTransaction(void)
3584 TransactionState s = CurrentTransactionState;
3587 * Get out of any transaction or nested transaction
3591 switch (s->blockState)
3593 case TBLOCK_DEFAULT:
3594 /* Not in a transaction, do nothing */
3595 break;
3596 case TBLOCK_STARTED:
3597 case TBLOCK_BEGIN:
3598 case TBLOCK_INPROGRESS:
3599 case TBLOCK_END:
3600 case TBLOCK_ABORT_PENDING:
3601 case TBLOCK_PREPARE:
3602 /* In a transaction, so clean up */
3603 AbortTransaction();
3604 CleanupTransaction();
3605 s->blockState = TBLOCK_DEFAULT;
3606 break;
3607 case TBLOCK_ABORT:
3608 case TBLOCK_ABORT_END:
3609 /* AbortTransaction already done, still need Cleanup */
3610 CleanupTransaction();
3611 s->blockState = TBLOCK_DEFAULT;
3612 break;
3615 * In a subtransaction, so clean it up and abort parent too
3617 case TBLOCK_SUBBEGIN:
3618 case TBLOCK_SUBINPROGRESS:
3619 case TBLOCK_SUBEND:
3620 case TBLOCK_SUBABORT_PENDING:
3621 case TBLOCK_SUBRESTART:
3622 AbortSubTransaction();
3623 CleanupSubTransaction();
3624 s = CurrentTransactionState; /* changed by pop */
3625 break;
3627 case TBLOCK_SUBABORT:
3628 case TBLOCK_SUBABORT_END:
3629 case TBLOCK_SUBABORT_RESTART:
3630 /* As above, but AbortSubTransaction already done */
3631 CleanupSubTransaction();
3632 s = CurrentTransactionState; /* changed by pop */
3633 break;
3635 } while (s->blockState != TBLOCK_DEFAULT);
3637 /* Should be out of all subxacts now */
3638 Assert(s->parent == NULL);
3642 * IsTransactionBlock --- are we within a transaction block?
3644 bool
3645 IsTransactionBlock(void)
3647 TransactionState s = CurrentTransactionState;
3649 if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
3650 return false;
3652 return true;
3656 * IsTransactionOrTransactionBlock --- are we within either a transaction
3657 * or a transaction block? (The backend is only really "idle" when this
3658 * returns false.)
3660 * This should match up with IsTransactionBlock and IsTransactionState.
3662 bool
3663 IsTransactionOrTransactionBlock(void)
3665 TransactionState s = CurrentTransactionState;
3667 if (s->blockState == TBLOCK_DEFAULT)
3668 return false;
3670 return true;
3674 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3676 char
3677 TransactionBlockStatusCode(void)
3679 TransactionState s = CurrentTransactionState;
3681 switch (s->blockState)
3683 case TBLOCK_DEFAULT:
3684 case TBLOCK_STARTED:
3685 return 'I'; /* idle --- not in transaction */
3686 case TBLOCK_BEGIN:
3687 case TBLOCK_SUBBEGIN:
3688 case TBLOCK_INPROGRESS:
3689 case TBLOCK_SUBINPROGRESS:
3690 case TBLOCK_END:
3691 case TBLOCK_SUBEND:
3692 case TBLOCK_PREPARE:
3693 return 'T'; /* in transaction */
3694 case TBLOCK_ABORT:
3695 case TBLOCK_SUBABORT:
3696 case TBLOCK_ABORT_END:
3697 case TBLOCK_SUBABORT_END:
3698 case TBLOCK_ABORT_PENDING:
3699 case TBLOCK_SUBABORT_PENDING:
3700 case TBLOCK_SUBRESTART:
3701 case TBLOCK_SUBABORT_RESTART:
3702 return 'E'; /* in failed transaction */
3705 /* should never get here */
3706 elog(FATAL, "invalid transaction block state: %s",
3707 BlockStateAsString(s->blockState));
3708 return 0; /* keep compiler quiet */
3712 * IsSubTransaction
3714 bool
3715 IsSubTransaction(void)
3717 TransactionState s = CurrentTransactionState;
3719 if (s->nestingLevel >= 2)
3720 return true;
3722 return false;
3726 * StartSubTransaction
3728 * If you're wondering why this is separate from PushTransaction: it's because
3729 * we can't conveniently do this stuff right inside DefineSavepoint. The
3730 * SAVEPOINT utility command will be executed inside a Portal, and if we
3731 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3732 * the Portal will undo those settings. So we make DefineSavepoint just
3733 * push a dummy transaction block, and when control returns to the main
3734 * idle loop, CommitTransactionCommand will be called, and we'll come here
3735 * to finish starting the subtransaction.
3737 static void
3738 StartSubTransaction(void)
3740 TransactionState s = CurrentTransactionState;
3742 if (s->state != TRANS_DEFAULT)
3743 elog(WARNING, "StartSubTransaction while in %s state",
3744 TransStateAsString(s->state));
3746 s->state = TRANS_START;
3749 * Initialize subsystems for new subtransaction
3751 * must initialize resource-management stuff first
3753 AtSubStart_Memory();
3754 AtSubStart_ResourceOwner();
3755 AtSubStart_Inval();
3756 AtSubStart_Notify();
3757 AfterTriggerBeginSubXact();
3759 s->state = TRANS_INPROGRESS;
3762 * Call start-of-subxact callbacks
3764 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
3765 s->parent->subTransactionId);
3767 ShowTransactionState("StartSubTransaction");
3771 * CommitSubTransaction
3773 * The caller has to make sure to always reassign CurrentTransactionState
3774 * if it has a local pointer to it after calling this function.
3776 static void
3777 CommitSubTransaction(void)
3779 TransactionState s = CurrentTransactionState;
3781 ShowTransactionState("CommitSubTransaction");
3783 if (s->state != TRANS_INPROGRESS)
3784 elog(WARNING, "CommitSubTransaction while in %s state",
3785 TransStateAsString(s->state));
3787 /* Pre-commit processing goes here -- nothing to do at the moment */
3789 s->state = TRANS_COMMIT;
3791 /* Must CCI to ensure commands of subtransaction are seen as done */
3792 CommandCounterIncrement();
3794 /* Mark subtransaction as subcommitted */
3795 RecordSubTransactionCommit();
3797 /* Post-commit cleanup */
3798 if (TransactionIdIsValid(s->transactionId))
3799 AtSubCommit_childXids();
3800 AfterTriggerEndSubXact(true);
3801 AtSubCommit_Portals(s->subTransactionId,
3802 s->parent->subTransactionId,
3803 s->parent->curTransactionOwner);
3804 AtEOSubXact_LargeObject(true, s->subTransactionId,
3805 s->parent->subTransactionId);
3806 AtSubCommit_Notify();
3807 AtEOSubXact_UpdateFlatFiles(true, s->subTransactionId,
3808 s->parent->subTransactionId);
3810 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
3811 s->parent->subTransactionId);
3813 ResourceOwnerRelease(s->curTransactionOwner,
3814 RESOURCE_RELEASE_BEFORE_LOCKS,
3815 true, false);
3816 AtEOSubXact_RelationCache(true, s->subTransactionId,
3817 s->parent->subTransactionId);
3818 AtEOSubXact_Inval(true);
3819 AtSubCommit_smgr();
3822 * The only lock we actually release here is the subtransaction XID lock.
3823 * The rest just get transferred to the parent resource owner.
3825 CurrentResourceOwner = s->curTransactionOwner;
3826 if (TransactionIdIsValid(s->transactionId))
3827 XactLockTableDelete(s->transactionId);
3829 ResourceOwnerRelease(s->curTransactionOwner,
3830 RESOURCE_RELEASE_LOCKS,
3831 true, false);
3832 ResourceOwnerRelease(s->curTransactionOwner,
3833 RESOURCE_RELEASE_AFTER_LOCKS,
3834 true, false);
3836 AtEOXact_GUC(true, s->gucNestLevel);
3837 AtEOSubXact_SPI(true, s->subTransactionId);
3838 AtEOSubXact_on_commit_actions(true, s->subTransactionId,
3839 s->parent->subTransactionId);
3840 AtEOSubXact_Namespace(true, s->subTransactionId,
3841 s->parent->subTransactionId);
3842 AtEOSubXact_Files(true, s->subTransactionId,
3843 s->parent->subTransactionId);
3844 AtEOSubXact_HashTables(true, s->nestingLevel);
3845 AtEOSubXact_PgStat(true, s->nestingLevel);
3846 AtSubCommit_Snapshot(s->nestingLevel);
3849 * We need to restore the upper transaction's read-only state, in case the
3850 * upper is read-write while the child is read-only; GUC will incorrectly
3851 * think it should leave the child state in place.
3853 XactReadOnly = s->prevXactReadOnly;
3855 CurrentResourceOwner = s->parent->curTransactionOwner;
3856 CurTransactionResourceOwner = s->parent->curTransactionOwner;
3857 ResourceOwnerDelete(s->curTransactionOwner);
3858 s->curTransactionOwner = NULL;
3860 AtSubCommit_Memory();
3862 s->state = TRANS_DEFAULT;
3864 PopTransaction();
3868 * AbortSubTransaction
3870 static void
3871 AbortSubTransaction(void)
3873 TransactionState s = CurrentTransactionState;
3875 /* Prevent cancel/die interrupt while cleaning up */
3876 HOLD_INTERRUPTS();
3878 /* Make sure we have a valid memory context and resource owner */
3879 AtSubAbort_Memory();
3880 AtSubAbort_ResourceOwner();
3883 * Release any LW locks we might be holding as quickly as possible.
3884 * (Regular locks, however, must be held till we finish aborting.)
3885 * Releasing LW locks is critical since we might try to grab them again
3886 * while cleaning up!
3888 * FIXME This may be incorrect --- Are there some locks we should keep?
3889 * Buffer locks, for example? I don't think so but I'm not sure.
3891 LWLockReleaseAll();
3893 AbortBufferIO();
3894 UnlockBuffers();
3896 LockWaitCancel();
3899 * check the current transaction state
3901 ShowTransactionState("AbortSubTransaction");
3903 if (s->state != TRANS_INPROGRESS)
3904 elog(WARNING, "AbortSubTransaction while in %s state",
3905 TransStateAsString(s->state));
3907 s->state = TRANS_ABORT;
3910 * Reset user ID which might have been changed transiently. (See notes
3911 * in AbortTransaction.)
3913 SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
3916 * We can skip all this stuff if the subxact failed before creating a
3917 * ResourceOwner...
3919 if (s->curTransactionOwner)
3921 AfterTriggerEndSubXact(false);
3922 AtSubAbort_Portals(s->subTransactionId,
3923 s->parent->subTransactionId,
3924 s->parent->curTransactionOwner);
3925 AtEOSubXact_LargeObject(false, s->subTransactionId,
3926 s->parent->subTransactionId);
3927 AtSubAbort_Notify();
3928 AtEOSubXact_UpdateFlatFiles(false, s->subTransactionId,
3929 s->parent->subTransactionId);
3931 /* Advertise the fact that we aborted in pg_clog. */
3932 (void) RecordTransactionAbort(true);
3934 /* Post-abort cleanup */
3935 if (TransactionIdIsValid(s->transactionId))
3936 AtSubAbort_childXids();
3938 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
3939 s->parent->subTransactionId);
3941 ResourceOwnerRelease(s->curTransactionOwner,
3942 RESOURCE_RELEASE_BEFORE_LOCKS,
3943 false, false);
3944 AtEOSubXact_RelationCache(false, s->subTransactionId,
3945 s->parent->subTransactionId);
3946 AtEOSubXact_Inval(false);
3947 AtSubAbort_smgr();
3948 ResourceOwnerRelease(s->curTransactionOwner,
3949 RESOURCE_RELEASE_LOCKS,
3950 false, false);
3951 ResourceOwnerRelease(s->curTransactionOwner,
3952 RESOURCE_RELEASE_AFTER_LOCKS,
3953 false, false);
3955 AtEOXact_GUC(false, s->gucNestLevel);
3956 AtEOSubXact_SPI(false, s->subTransactionId);
3957 AtEOXact_xml();
3958 AtEOSubXact_on_commit_actions(false, s->subTransactionId,
3959 s->parent->subTransactionId);
3960 AtEOSubXact_Namespace(false, s->subTransactionId,
3961 s->parent->subTransactionId);
3962 AtEOSubXact_Files(false, s->subTransactionId,
3963 s->parent->subTransactionId);
3964 AtEOSubXact_HashTables(false, s->nestingLevel);
3965 AtEOSubXact_PgStat(false, s->nestingLevel);
3966 AtSubAbort_Snapshot(s->nestingLevel);
3970 * Restore the upper transaction's read-only state, too. This should be
3971 * redundant with GUC's cleanup but we may as well do it for consistency
3972 * with the commit case.
3974 XactReadOnly = s->prevXactReadOnly;
3976 RESUME_INTERRUPTS();
3980 * CleanupSubTransaction
3982 * The caller has to make sure to always reassign CurrentTransactionState
3983 * if it has a local pointer to it after calling this function.
3985 static void
3986 CleanupSubTransaction(void)
3988 TransactionState s = CurrentTransactionState;
3990 ShowTransactionState("CleanupSubTransaction");
3992 if (s->state != TRANS_ABORT)
3993 elog(WARNING, "CleanupSubTransaction while in %s state",
3994 TransStateAsString(s->state));
3996 AtSubCleanup_Portals(s->subTransactionId);
3998 CurrentResourceOwner = s->parent->curTransactionOwner;
3999 CurTransactionResourceOwner = s->parent->curTransactionOwner;
4000 if (s->curTransactionOwner)
4001 ResourceOwnerDelete(s->curTransactionOwner);
4002 s->curTransactionOwner = NULL;
4004 AtSubCleanup_Memory();
4006 s->state = TRANS_DEFAULT;
4008 PopTransaction();
4012 * PushTransaction
4013 * Create transaction state stack entry for a subtransaction
4015 * The caller has to make sure to always reassign CurrentTransactionState
4016 * if it has a local pointer to it after calling this function.
4018 static void
4019 PushTransaction(void)
4021 TransactionState p = CurrentTransactionState;
4022 TransactionState s;
4025 * We keep subtransaction state nodes in TopTransactionContext.
4027 s = (TransactionState)
4028 MemoryContextAllocZero(TopTransactionContext,
4029 sizeof(TransactionStateData));
4032 * Assign a subtransaction ID, watching out for counter wraparound.
4034 currentSubTransactionId += 1;
4035 if (currentSubTransactionId == InvalidSubTransactionId)
4037 currentSubTransactionId -= 1;
4038 pfree(s);
4039 ereport(ERROR,
4040 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
4041 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
4045 * We can now stack a minimally valid subtransaction without fear of
4046 * failure.
4048 s->transactionId = InvalidTransactionId; /* until assigned */
4049 s->subTransactionId = currentSubTransactionId;
4050 s->parent = p;
4051 s->nestingLevel = p->nestingLevel + 1;
4052 s->gucNestLevel = NewGUCNestLevel();
4053 s->savepointLevel = p->savepointLevel;
4054 s->state = TRANS_DEFAULT;
4055 s->blockState = TBLOCK_SUBBEGIN;
4056 GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
4057 s->prevXactReadOnly = XactReadOnly;
4059 CurrentTransactionState = s;
4062 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
4063 * with the subtransaction from here on out; in particular they should not
4064 * assume that it necessarily has a transaction context, resource owner,
4065 * or XID.
4070 * PopTransaction
4071 * Pop back to parent transaction state
4073 * The caller has to make sure to always reassign CurrentTransactionState
4074 * if it has a local pointer to it after calling this function.
4076 static void
4077 PopTransaction(void)
4079 TransactionState s = CurrentTransactionState;
4081 if (s->state != TRANS_DEFAULT)
4082 elog(WARNING, "PopTransaction while in %s state",
4083 TransStateAsString(s->state));
4085 if (s->parent == NULL)
4086 elog(FATAL, "PopTransaction with no parent");
4088 CurrentTransactionState = s->parent;
4090 /* Let's just make sure CurTransactionContext is good */
4091 CurTransactionContext = s->parent->curTransactionContext;
4092 MemoryContextSwitchTo(CurTransactionContext);
4094 /* Ditto for ResourceOwner links */
4095 CurTransactionResourceOwner = s->parent->curTransactionOwner;
4096 CurrentResourceOwner = s->parent->curTransactionOwner;
4098 /* Free the old child structure */
4099 if (s->name)
4100 pfree(s->name);
4101 pfree(s);
4105 * ShowTransactionState
4106 * Debug support
4108 static void
4109 ShowTransactionState(const char *str)
4111 /* skip work if message will definitely not be printed */
4112 if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3)
4114 elog(DEBUG3, "%s", str);
4115 ShowTransactionStateRec(CurrentTransactionState);
4120 * ShowTransactionStateRec
4121 * Recursive subroutine for ShowTransactionState
4123 static void
4124 ShowTransactionStateRec(TransactionState s)
4126 StringInfoData buf;
4128 initStringInfo(&buf);
4130 if (s->nChildXids > 0)
4132 int i;
4134 appendStringInfo(&buf, "%u", s->childXids[0]);
4135 for (i = 1; i < s->nChildXids; i++)
4136 appendStringInfo(&buf, " %u", s->childXids[i]);
4139 if (s->parent)
4140 ShowTransactionStateRec(s->parent);
4142 /* use ereport to suppress computation if msg will not be printed */
4143 ereport(DEBUG3,
4144 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
4145 PointerIsValid(s->name) ? s->name : "unnamed",
4146 BlockStateAsString(s->blockState),
4147 TransStateAsString(s->state),
4148 (unsigned int) s->transactionId,
4149 (unsigned int) s->subTransactionId,
4150 (unsigned int) currentCommandId,
4151 currentCommandIdUsed ? " (used)" : "",
4152 s->nestingLevel, buf.data)));
4154 pfree(buf.data);
4158 * BlockStateAsString
4159 * Debug support
4161 static const char *
4162 BlockStateAsString(TBlockState blockState)
4164 switch (blockState)
4166 case TBLOCK_DEFAULT:
4167 return "DEFAULT";
4168 case TBLOCK_STARTED:
4169 return "STARTED";
4170 case TBLOCK_BEGIN:
4171 return "BEGIN";
4172 case TBLOCK_INPROGRESS:
4173 return "INPROGRESS";
4174 case TBLOCK_END:
4175 return "END";
4176 case TBLOCK_ABORT:
4177 return "ABORT";
4178 case TBLOCK_ABORT_END:
4179 return "ABORT END";
4180 case TBLOCK_ABORT_PENDING:
4181 return "ABORT PEND";
4182 case TBLOCK_PREPARE:
4183 return "PREPARE";
4184 case TBLOCK_SUBBEGIN:
4185 return "SUB BEGIN";
4186 case TBLOCK_SUBINPROGRESS:
4187 return "SUB INPROGRS";
4188 case TBLOCK_SUBEND:
4189 return "SUB END";
4190 case TBLOCK_SUBABORT:
4191 return "SUB ABORT";
4192 case TBLOCK_SUBABORT_END:
4193 return "SUB ABORT END";
4194 case TBLOCK_SUBABORT_PENDING:
4195 return "SUB ABRT PEND";
4196 case TBLOCK_SUBRESTART:
4197 return "SUB RESTART";
4198 case TBLOCK_SUBABORT_RESTART:
4199 return "SUB AB RESTRT";
4201 return "UNRECOGNIZED";
4205 * TransStateAsString
4206 * Debug support
4208 static const char *
4209 TransStateAsString(TransState state)
4211 switch (state)
4213 case TRANS_DEFAULT:
4214 return "DEFAULT";
4215 case TRANS_START:
4216 return "START";
4217 case TRANS_INPROGRESS:
4218 return "INPROGR";
4219 case TRANS_COMMIT:
4220 return "COMMIT";
4221 case TRANS_ABORT:
4222 return "ABORT";
4223 case TRANS_PREPARE:
4224 return "PREPARE";
4226 return "UNRECOGNIZED";
4230 * xactGetCommittedChildren
4232 * Gets the list of committed children of the current transaction. The return
4233 * value is the number of child transactions. *ptr is set to point to an
4234 * array of TransactionIds. The array is allocated in TopTransactionContext;
4235 * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
4236 * If there are no subxacts, *ptr is set to NULL.
4239 xactGetCommittedChildren(TransactionId **ptr)
4241 TransactionState s = CurrentTransactionState;
4243 if (s->nChildXids == 0)
4244 *ptr = NULL;
4245 else
4246 *ptr = s->childXids;
4248 return s->nChildXids;
4252 * XLOG support routines
4255 static void
4256 xact_redo_commit(xl_xact_commit *xlrec, TransactionId xid)
4258 TransactionId *sub_xids;
4259 TransactionId max_xid;
4260 int i;
4262 TransactionIdCommit(xid);
4264 /* Mark committed subtransactions as committed */
4265 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4266 TransactionIdCommitTree(xlrec->nsubxacts, sub_xids);
4268 /* Make sure nextXid is beyond any XID mentioned in the record */
4269 max_xid = xid;
4270 for (i = 0; i < xlrec->nsubxacts; i++)
4272 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4273 max_xid = sub_xids[i];
4275 if (TransactionIdFollowsOrEquals(max_xid,
4276 ShmemVariableCache->nextXid))
4278 ShmemVariableCache->nextXid = max_xid;
4279 TransactionIdAdvance(ShmemVariableCache->nextXid);
4282 /* Make sure files supposed to be dropped are dropped */
4283 for (i = 0; i < xlrec->nrels; i++)
4285 SMgrRelation srel;
4287 XLogDropRelation(xlrec->xnodes[i].rnode, xlrec->xnodes[i].forknum);
4289 srel = smgropen(xlrec->xnodes[i].rnode);
4290 smgrdounlink(srel, xlrec->xnodes[i].forknum, false, true);
4291 smgrclose(srel);
4295 static void
4296 xact_redo_abort(xl_xact_abort *xlrec, TransactionId xid)
4298 TransactionId *sub_xids;
4299 TransactionId max_xid;
4300 int i;
4302 TransactionIdAbort(xid);
4304 /* Mark subtransactions as aborted */
4305 sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]);
4306 TransactionIdAbortTree(xlrec->nsubxacts, sub_xids);
4308 /* Make sure nextXid is beyond any XID mentioned in the record */
4309 max_xid = xid;
4310 for (i = 0; i < xlrec->nsubxacts; i++)
4312 if (TransactionIdPrecedes(max_xid, sub_xids[i]))
4313 max_xid = sub_xids[i];
4315 if (TransactionIdFollowsOrEquals(max_xid,
4316 ShmemVariableCache->nextXid))
4318 ShmemVariableCache->nextXid = max_xid;
4319 TransactionIdAdvance(ShmemVariableCache->nextXid);
4322 /* Make sure files supposed to be dropped are dropped */
4323 for (i = 0; i < xlrec->nrels; i++)
4325 SMgrRelation srel;
4327 XLogDropRelation(xlrec->xnodes[i].rnode, xlrec->xnodes[i].forknum);
4329 srel = smgropen(xlrec->xnodes[i].rnode);
4330 smgrdounlink(srel, xlrec->xnodes[i].forknum, false, true);
4331 smgrclose(srel);
4335 void
4336 xact_redo(XLogRecPtr lsn, XLogRecord *record)
4338 uint8 info = record->xl_info & ~XLR_INFO_MASK;
4340 if (info == XLOG_XACT_COMMIT)
4342 xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
4344 xact_redo_commit(xlrec, record->xl_xid);
4346 else if (info == XLOG_XACT_ABORT)
4348 xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
4350 xact_redo_abort(xlrec, record->xl_xid);
4352 else if (info == XLOG_XACT_PREPARE)
4354 /* the record contents are exactly the 2PC file */
4355 RecreateTwoPhaseFile(record->xl_xid,
4356 XLogRecGetData(record), record->xl_len);
4358 else if (info == XLOG_XACT_COMMIT_PREPARED)
4360 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record);
4362 xact_redo_commit(&xlrec->crec, xlrec->xid);
4363 RemoveTwoPhaseFile(xlrec->xid, false);
4365 else if (info == XLOG_XACT_ABORT_PREPARED)
4367 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record);
4369 xact_redo_abort(&xlrec->arec, xlrec->xid);
4370 RemoveTwoPhaseFile(xlrec->xid, false);
4372 else
4373 elog(PANIC, "xact_redo: unknown op code %u", info);
4376 static void
4377 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
4379 int i;
4381 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4382 if (xlrec->nrels > 0)
4384 appendStringInfo(buf, "; rels:");
4385 for (i = 0; i < xlrec->nrels; i++)
4387 RelFileNode rnode = xlrec->xnodes[i].rnode;
4388 ForkNumber forknum = xlrec->xnodes[i].forknum;
4390 appendStringInfo(buf, " %u/%u/%u/%u",
4391 rnode.spcNode, rnode.dbNode, rnode.relNode,
4392 forknum);
4395 if (xlrec->nsubxacts > 0)
4397 TransactionId *xacts = (TransactionId *)
4398 &xlrec->xnodes[xlrec->nrels];
4400 appendStringInfo(buf, "; subxacts:");
4401 for (i = 0; i < xlrec->nsubxacts; i++)
4402 appendStringInfo(buf, " %u", xacts[i]);
4406 static void
4407 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
4409 int i;
4411 appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
4412 if (xlrec->nrels > 0)
4414 appendStringInfo(buf, "; rels:");
4415 for (i = 0; i < xlrec->nrels; i++)
4417 RelFileNode rnode = xlrec->xnodes[i].rnode;
4418 ForkNumber forknum = xlrec->xnodes[i].forknum;
4420 appendStringInfo(buf, " %u/%u/%u/%u",
4421 rnode.spcNode, rnode.dbNode, rnode.relNode,
4422 forknum);
4425 if (xlrec->nsubxacts > 0)
4427 TransactionId *xacts = (TransactionId *)
4428 &xlrec->xnodes[xlrec->nrels];
4430 appendStringInfo(buf, "; subxacts:");
4431 for (i = 0; i < xlrec->nsubxacts; i++)
4432 appendStringInfo(buf, " %u", xacts[i]);
4436 void
4437 xact_desc(StringInfo buf, uint8 xl_info, char *rec)
4439 uint8 info = xl_info & ~XLR_INFO_MASK;
4441 if (info == XLOG_XACT_COMMIT)
4443 xl_xact_commit *xlrec = (xl_xact_commit *) rec;
4445 appendStringInfo(buf, "commit: ");
4446 xact_desc_commit(buf, xlrec);
4448 else if (info == XLOG_XACT_ABORT)
4450 xl_xact_abort *xlrec = (xl_xact_abort *) rec;
4452 appendStringInfo(buf, "abort: ");
4453 xact_desc_abort(buf, xlrec);
4455 else if (info == XLOG_XACT_PREPARE)
4457 appendStringInfo(buf, "prepare");
4459 else if (info == XLOG_XACT_COMMIT_PREPARED)
4461 xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) rec;
4463 appendStringInfo(buf, "commit %u: ", xlrec->xid);
4464 xact_desc_commit(buf, &xlrec->crec);
4466 else if (info == XLOG_XACT_ABORT_PREPARED)
4468 xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) rec;
4470 appendStringInfo(buf, "abort %u: ", xlrec->xid);
4471 xact_desc_abort(buf, &xlrec->arec);
4473 else
4474 appendStringInfo(buf, "UNKNOWN");