1 /*-------------------------------------------------------------------------
4 * top level transaction system support routines
6 * See src/backend/access/transam/README for more information.
8 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
15 *-------------------------------------------------------------------------
23 #include "access/multixact.h"
24 #include "access/subtrans.h"
25 #include "access/transam.h"
26 #include "access/twophase.h"
27 #include "access/xact.h"
28 #include "access/xlogutils.h"
29 #include "catalog/catalog.h"
30 #include "catalog/namespace.h"
31 #include "catalog/storage.h"
32 #include "commands/async.h"
33 #include "commands/tablecmds.h"
34 #include "commands/trigger.h"
35 #include "executor/spi.h"
36 #include "libpq/be-fsstubs.h"
37 #include "miscadmin.h"
39 #include "storage/bufmgr.h"
40 #include "storage/fd.h"
41 #include "storage/lmgr.h"
42 #include "storage/procarray.h"
43 #include "storage/sinvaladt.h"
44 #include "storage/smgr.h"
45 #include "utils/combocid.h"
46 #include "utils/flatfiles.h"
47 #include "utils/guc.h"
48 #include "utils/inval.h"
49 #include "utils/memutils.h"
50 #include "utils/relcache.h"
51 #include "utils/snapmgr.h"
56 * User-tweakable parameters
58 int DefaultXactIsoLevel
= XACT_READ_COMMITTED
;
61 bool DefaultXactReadOnly
= false;
64 bool XactSyncCommit
= true;
66 int CommitDelay
= 0; /* precommit delay in microseconds */
67 int CommitSiblings
= 5; /* # concurrent xacts needed to sleep */
70 * MyXactAccessedTempRel is set when a temporary relation is accessed.
71 * We don't allow PREPARE TRANSACTION in that case. (This is global
72 * so that it can be set from heapam.c.)
74 bool MyXactAccessedTempRel
= false;
78 * transaction states - transaction state from server perspective
80 typedef enum TransState
82 TRANS_DEFAULT
, /* idle */
83 TRANS_START
, /* transaction starting */
84 TRANS_INPROGRESS
, /* inside a valid transaction */
85 TRANS_COMMIT
, /* commit in progress */
86 TRANS_ABORT
, /* abort in progress */
87 TRANS_PREPARE
/* prepare in progress */
91 * transaction block states - transaction state of client queries
93 * Note: the subtransaction states are used only for non-topmost
94 * transactions; the others appear only in the topmost transaction.
96 typedef enum TBlockState
98 /* not-in-transaction-block states */
99 TBLOCK_DEFAULT
, /* idle */
100 TBLOCK_STARTED
, /* running single-query transaction */
102 /* transaction block states */
103 TBLOCK_BEGIN
, /* starting transaction block */
104 TBLOCK_INPROGRESS
, /* live transaction */
105 TBLOCK_END
, /* COMMIT received */
106 TBLOCK_ABORT
, /* failed xact, awaiting ROLLBACK */
107 TBLOCK_ABORT_END
, /* failed xact, ROLLBACK received */
108 TBLOCK_ABORT_PENDING
, /* live xact, ROLLBACK received */
109 TBLOCK_PREPARE
, /* live xact, PREPARE received */
111 /* subtransaction states */
112 TBLOCK_SUBBEGIN
, /* starting a subtransaction */
113 TBLOCK_SUBINPROGRESS
, /* live subtransaction */
114 TBLOCK_SUBEND
, /* RELEASE received */
115 TBLOCK_SUBABORT
, /* failed subxact, awaiting ROLLBACK */
116 TBLOCK_SUBABORT_END
, /* failed subxact, ROLLBACK received */
117 TBLOCK_SUBABORT_PENDING
, /* live subxact, ROLLBACK received */
118 TBLOCK_SUBRESTART
, /* live subxact, ROLLBACK TO received */
119 TBLOCK_SUBABORT_RESTART
/* failed subxact, ROLLBACK TO received */
123 * transaction state structure
125 typedef struct TransactionStateData
127 TransactionId transactionId
; /* my XID, or Invalid if none */
128 SubTransactionId subTransactionId
; /* my subxact ID */
129 char *name
; /* savepoint name, if any */
130 int savepointLevel
; /* savepoint level */
131 TransState state
; /* low-level state */
132 TBlockState blockState
; /* high-level state */
133 int nestingLevel
; /* transaction nesting depth */
134 int gucNestLevel
; /* GUC context nesting depth */
135 MemoryContext curTransactionContext
; /* my xact-lifetime context */
136 ResourceOwner curTransactionOwner
; /* my query resources */
137 TransactionId
*childXids
; /* subcommitted child XIDs, in XID order */
138 int nChildXids
; /* # of subcommitted child XIDs */
139 int maxChildXids
; /* allocated size of childXids[] */
140 Oid prevUser
; /* previous CurrentUserId setting */
141 bool prevSecDefCxt
; /* previous SecurityDefinerContext setting */
142 bool prevXactReadOnly
; /* entry-time xact r/o state */
143 struct TransactionStateData
*parent
; /* back link to parent */
144 } TransactionStateData
;
146 typedef TransactionStateData
*TransactionState
;
149 * CurrentTransactionState always points to the current transaction state
150 * block. It will point to TopTransactionStateData when not in a
151 * transaction at all, or when in a top-level transaction.
153 static TransactionStateData TopTransactionStateData
= {
154 0, /* transaction id */
155 0, /* subtransaction id */
156 NULL
, /* savepoint name */
157 0, /* savepoint level */
158 TRANS_DEFAULT
, /* transaction state */
159 TBLOCK_DEFAULT
, /* transaction block state from the client
161 0, /* transaction nesting depth */
162 0, /* GUC context nesting depth */
163 NULL
, /* cur transaction context */
164 NULL
, /* cur transaction resource owner */
165 NULL
, /* subcommitted child Xids */
166 0, /* # of subcommitted child Xids */
167 0, /* allocated size of childXids[] */
168 InvalidOid
, /* previous CurrentUserId setting */
169 false, /* previous SecurityDefinerContext setting */
170 false, /* entry-time xact r/o state */
171 NULL
/* link to parent state block */
174 static TransactionState CurrentTransactionState
= &TopTransactionStateData
;
177 * The subtransaction ID and command ID assignment counters are global
178 * to a whole transaction, so we do not keep them in the state stack.
180 static SubTransactionId currentSubTransactionId
;
181 static CommandId currentCommandId
;
182 static bool currentCommandIdUsed
;
185 * xactStartTimestamp is the value of transaction_timestamp().
186 * stmtStartTimestamp is the value of statement_timestamp().
187 * xactStopTimestamp is the time at which we log a commit or abort WAL record.
188 * These do not change as we enter and exit subtransactions, so we don't
189 * keep them inside the TransactionState stack.
191 static TimestampTz xactStartTimestamp
;
192 static TimestampTz stmtStartTimestamp
;
193 static TimestampTz xactStopTimestamp
;
196 * GID to be used for preparing the current transaction. This is also
197 * global to a whole transaction, so we don't keep it in the state stack.
199 static char *prepareGID
;
202 * Some commands want to force synchronous commit.
204 static bool forceSyncCommit
= false;
207 * Private context for transaction-abort work --- we reserve space for this
208 * at startup to ensure that AbortTransaction and AbortSubTransaction can work
209 * when we've run out of memory.
211 static MemoryContext TransactionAbortContext
= NULL
;
214 * List of add-on start- and end-of-xact callbacks
216 typedef struct XactCallbackItem
218 struct XactCallbackItem
*next
;
219 XactCallback callback
;
223 static XactCallbackItem
*Xact_callbacks
= NULL
;
226 * List of add-on start- and end-of-subxact callbacks
228 typedef struct SubXactCallbackItem
230 struct SubXactCallbackItem
*next
;
231 SubXactCallback callback
;
233 } SubXactCallbackItem
;
235 static SubXactCallbackItem
*SubXact_callbacks
= NULL
;
238 /* local function prototypes */
239 static void AssignTransactionId(TransactionState s
);
240 static void AbortTransaction(void);
241 static void AtAbort_Memory(void);
242 static void AtCleanup_Memory(void);
243 static void AtAbort_ResourceOwner(void);
244 static void AtCommit_LocalCache(void);
245 static void AtCommit_Memory(void);
246 static void AtStart_Cache(void);
247 static void AtStart_Memory(void);
248 static void AtStart_ResourceOwner(void);
249 static void CallXactCallbacks(XactEvent event
);
250 static void CallSubXactCallbacks(SubXactEvent event
,
251 SubTransactionId mySubid
,
252 SubTransactionId parentSubid
);
253 static void CleanupTransaction(void);
254 static void CommitTransaction(void);
255 static TransactionId
RecordTransactionAbort(bool isSubXact
);
256 static void StartTransaction(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 * ----------------------------------------------------------------
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.
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.
311 IsAbortedTransactionBlockState(void)
313 TransactionState s
= CurrentTransactionState
;
315 if (s
->blockState
== TBLOCK_ABORT
||
316 s
->blockState
== TBLOCK_SUBABORT
)
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.
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.
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.
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.
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.
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
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
);
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
425 currentOwner
= CurrentResourceOwner
;
428 CurrentResourceOwner
= s
->curTransactionOwner
;
429 XactLockTableInsert(s
->transactionId
);
433 /* Ensure CurrentResourceOwner is restored on error */
434 CurrentResourceOwner
= currentOwner
;
438 CurrentResourceOwner
= currentOwner
;
443 * GetCurrentSubTransactionId
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.
463 GetCurrentCommandId(bool used
)
465 /* this is global to a transaction, not subtransaction-local */
467 currentCommandIdUsed
= true;
468 return currentCommandId
;
472 * GetCurrentTransactionStartTimestamp
475 GetCurrentTransactionStartTimestamp(void)
477 return xactStartTimestamp
;
481 * GetCurrentStatementStartTimestamp
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).
496 GetCurrentTransactionStopTimestamp(void)
498 if (xactStopTimestamp
!= 0)
499 return xactStopTimestamp
;
500 return GetCurrentTimestamp();
504 * SetCurrentStatementStartTimestamp
507 SetCurrentStatementStartTimestamp(void)
509 stmtStartTimestamp
= GetCurrentTimestamp();
513 * SetCurrentTransactionStopTimestamp
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
540 TransactionIdIsCurrentTransactionId(TransactionId xid
)
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
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
))
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
567 for (s
= CurrentTransactionState
; s
!= NULL
; s
= s
->parent
)
572 if (s
->state
== TRANS_ABORT
)
574 if (!TransactionIdIsValid(s
->transactionId
))
575 continue; /* it can't have any child XIDs either */
576 if (TransactionIdEquals(xid
, s
->transactionId
))
578 /* As the childXids array is ordered, we can use binary search */
580 high
= s
->nChildXids
- 1;
586 middle
= low
+ (high
- low
) / 2;
587 probe
= s
->childXids
[middle
];
588 if (TransactionIdEquals(probe
, xid
))
590 else if (TransactionIdPrecedes(probe
, xid
))
602 * CommandCounterIncrement
605 CommandCounterIncrement(void)
608 * If the current value of the command counter hasn't been "used" to mark
609 * tuples, we need not increment it, since there's no need to distinguish
610 * a read-only command from others. This helps postpone command counter
611 * overflow, and keeps no-op CommandCounterIncrement operations cheap.
613 if (currentCommandIdUsed
)
615 currentCommandId
+= 1;
616 if (currentCommandId
== FirstCommandId
) /* check for overflow */
618 currentCommandId
-= 1;
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 visible
630 * in the local syscache. We obviously don't need to do this after a
631 * read-only command. (But see hacks in inval.c to make real sure we
632 * don't think a command that queued inval messages was read-only.)
634 AtCommit_LocalCache();
638 * Make any other backends' catalog changes visible to me.
640 * XXX this is probably in the wrong place: CommandCounterIncrement should
641 * be purely a local operation, most likely. However fooling with this
642 * will affect asynchronous cross-backend interactions, which doesn't seem
643 * like a wise thing to do in late beta, so save improving this for
644 * another day - tgl 2007-11-30
652 * Interface routine to allow commands to force a synchronous commit of the
653 * current top-level transaction
656 ForceSyncCommit(void)
658 forceSyncCommit
= true;
662 /* ----------------------------------------------------------------
663 * StartTransaction stuff
664 * ----------------------------------------------------------------
673 AcceptInvalidationMessages();
682 TransactionState s
= CurrentTransactionState
;
685 * If this is the first time through, create a private context for
686 * AbortTransaction to work in. By reserving some space now, we can
687 * insulate AbortTransaction from out-of-memory scenarios. Like
688 * ErrorContext, we set it up with slow growth rate and a nonzero minimum
689 * size, so that space will be reserved immediately.
691 if (TransactionAbortContext
== NULL
)
692 TransactionAbortContext
=
693 AllocSetContextCreate(TopMemoryContext
,
694 "TransactionAbortContext",
700 * We shouldn't have a transaction context already.
702 Assert(TopTransactionContext
== NULL
);
705 * Create a toplevel context for the transaction.
707 TopTransactionContext
=
708 AllocSetContextCreate(TopMemoryContext
,
709 "TopTransactionContext",
710 ALLOCSET_DEFAULT_MINSIZE
,
711 ALLOCSET_DEFAULT_INITSIZE
,
712 ALLOCSET_DEFAULT_MAXSIZE
);
715 * In a top-level transaction, CurTransactionContext is the same as
716 * TopTransactionContext.
718 CurTransactionContext
= TopTransactionContext
;
719 s
->curTransactionContext
= CurTransactionContext
;
721 /* Make the CurTransactionContext active. */
722 MemoryContextSwitchTo(CurTransactionContext
);
726 * AtStart_ResourceOwner
729 AtStart_ResourceOwner(void)
731 TransactionState s
= CurrentTransactionState
;
734 * We shouldn't have a transaction resource owner already.
736 Assert(TopTransactionResourceOwner
== NULL
);
739 * Create a toplevel resource owner for the transaction.
741 s
->curTransactionOwner
= ResourceOwnerCreate(NULL
, "TopTransaction");
743 TopTransactionResourceOwner
= s
->curTransactionOwner
;
744 CurTransactionResourceOwner
= s
->curTransactionOwner
;
745 CurrentResourceOwner
= s
->curTransactionOwner
;
748 /* ----------------------------------------------------------------
749 * StartSubTransaction stuff
750 * ----------------------------------------------------------------
757 AtSubStart_Memory(void)
759 TransactionState s
= CurrentTransactionState
;
761 Assert(CurTransactionContext
!= NULL
);
764 * Create a CurTransactionContext, which will be used to hold data that
765 * survives subtransaction commit but disappears on subtransaction abort.
766 * We make it a child of the immediate parent's CurTransactionContext.
768 CurTransactionContext
= AllocSetContextCreate(CurTransactionContext
,
769 "CurTransactionContext",
770 ALLOCSET_DEFAULT_MINSIZE
,
771 ALLOCSET_DEFAULT_INITSIZE
,
772 ALLOCSET_DEFAULT_MAXSIZE
);
773 s
->curTransactionContext
= CurTransactionContext
;
775 /* Make the CurTransactionContext active. */
776 MemoryContextSwitchTo(CurTransactionContext
);
780 * AtSubStart_ResourceOwner
783 AtSubStart_ResourceOwner(void)
785 TransactionState s
= CurrentTransactionState
;
787 Assert(s
->parent
!= NULL
);
790 * Create a resource owner for the subtransaction. We make it a child of
791 * the immediate parent's resource owner.
793 s
->curTransactionOwner
=
794 ResourceOwnerCreate(s
->parent
->curTransactionOwner
,
797 CurTransactionResourceOwner
= s
->curTransactionOwner
;
798 CurrentResourceOwner
= s
->curTransactionOwner
;
801 /* ----------------------------------------------------------------
802 * CommitTransaction stuff
803 * ----------------------------------------------------------------
807 * RecordTransactionCommit
809 * Returns latest XID among xact and its children, or InvalidTransactionId
810 * if the xact has no XID. (We compute that here just because it's easier.)
812 * This is exported only to support an ugly hack in VACUUM FULL.
815 RecordTransactionCommit(void)
817 TransactionId xid
= GetTopTransactionIdIfAny();
818 bool markXidCommitted
= TransactionIdIsValid(xid
);
819 TransactionId latestXid
= InvalidTransactionId
;
824 TransactionId
*children
;
826 /* Get data needed for commit record */
827 nrels
= smgrGetPendingDeletes(true, &rels
, &haveNonTemp
);
828 nchildren
= xactGetCommittedChildren(&children
);
831 * If we haven't been assigned an XID yet, we neither can, nor do we want
832 * to write a COMMIT record.
834 if (!markXidCommitted
)
837 * We expect that every smgrscheduleunlink is followed by a catalog
838 * update, and hence XID assignment, so we shouldn't get here with any
839 * pending deletes. Use a real test not just an Assert to check this,
840 * since it's a bit fragile.
843 elog(ERROR
, "cannot commit a transaction that deleted files but has no xid");
845 /* Can't have child XIDs either; AssignTransactionId enforces this */
846 Assert(nchildren
== 0);
849 * If we didn't create XLOG entries, we're done here; otherwise we
850 * should flush those entries the same as a commit record. (An
851 * example of a possible record that wouldn't cause an XID to be
852 * assigned is a sequence advance record due to nextval() --- we want
853 * to flush that to disk before reporting commit.)
855 if (XactLastRecEnd
.xrecoff
== 0)
861 * Begin commit critical section and insert the commit XLOG record.
863 XLogRecData rdata
[3];
865 xl_xact_commit xlrec
;
867 /* Tell bufmgr and smgr to prepare for commit */
871 * Mark ourselves as within our "commit critical section". This
872 * forces any concurrent checkpoint to wait until we've updated
873 * pg_clog. Without this, it is possible for the checkpoint to set
874 * REDO after the XLOG record but fail to flush the pg_clog update to
875 * disk, leading to loss of the transaction commit if the system
876 * crashes a little later.
878 * Note: we could, but don't bother to, set this flag in
879 * RecordTransactionAbort. That's because loss of a transaction abort
880 * is noncritical; the presumption would be that it aborted, anyway.
882 * It's safe to change the inCommit flag of our own backend without
883 * holding the ProcArrayLock, since we're the only one modifying it.
884 * This makes checkpoint's determination of which xacts are inCommit a
885 * bit fuzzy, but it doesn't matter.
887 START_CRIT_SECTION();
888 MyProc
->inCommit
= true;
890 SetCurrentTransactionStopTimestamp();
891 xlrec
.xact_time
= xactStopTimestamp
;
893 xlrec
.nsubxacts
= nchildren
;
894 rdata
[0].data
= (char *) (&xlrec
);
895 rdata
[0].len
= MinSizeOfXactCommit
;
896 rdata
[0].buffer
= InvalidBuffer
;
897 /* dump rels to delete */
900 rdata
[0].next
= &(rdata
[1]);
901 rdata
[1].data
= (char *) rels
;
902 rdata
[1].len
= nrels
* sizeof(RelFileNode
);
903 rdata
[1].buffer
= InvalidBuffer
;
906 /* dump committed child Xids */
909 rdata
[lastrdata
].next
= &(rdata
[2]);
910 rdata
[2].data
= (char *) children
;
911 rdata
[2].len
= nchildren
* sizeof(TransactionId
);
912 rdata
[2].buffer
= InvalidBuffer
;
915 rdata
[lastrdata
].next
= NULL
;
917 (void) XLogInsert(RM_XACT_ID
, XLOG_XACT_COMMIT
, rdata
);
921 * Check if we want to commit asynchronously. If the user has set
922 * synchronous_commit = off, and we're not doing cleanup of any non-temp
923 * rels nor committing any command that wanted to force sync commit, then
924 * we can defer flushing XLOG. (We must not allow asynchronous commit if
925 * there are any non-temp tables to be deleted, because we might delete
926 * the files before the COMMIT record is flushed to disk. We do allow
927 * asynchronous commit if all to-be-deleted tables are temporary though,
928 * since they are lost anyway if we crash.)
930 if (XactSyncCommit
|| forceSyncCommit
|| haveNonTemp
)
933 * Synchronous commit case.
935 * Sleep before flush! So we can flush more than one commit records
936 * per single fsync. (The idea is some other backend may do the
937 * XLogFlush while we're sleeping. This needs work still, because on
938 * most Unixen, the minimum select() delay is 10msec or more, which is
941 * We do not sleep if enableFsync is not turned on, nor if there are
942 * fewer than CommitSiblings other backends with active transactions.
944 if (CommitDelay
> 0 && enableFsync
&&
945 CountActiveBackends() >= CommitSiblings
)
946 pg_usleep(CommitDelay
);
948 XLogFlush(XactLastRecEnd
);
951 * Now we may update the CLOG, if we wrote a COMMIT record above
953 if (markXidCommitted
)
954 TransactionIdCommitTree(xid
, nchildren
, children
);
959 * Asynchronous commit case.
961 * Report the latest async commit LSN, so that the WAL writer knows to
964 XLogSetAsyncCommitLSN(XactLastRecEnd
);
967 * We must not immediately update the CLOG, since we didn't flush the
968 * XLOG. Instead, we store the LSN up to which the XLOG must be
969 * flushed before the CLOG may be updated.
971 if (markXidCommitted
)
972 TransactionIdAsyncCommitTree(xid
, nchildren
, children
, XactLastRecEnd
);
976 * If we entered a commit critical section, leave it now, and let
977 * checkpoints proceed.
979 if (markXidCommitted
)
981 MyProc
->inCommit
= false;
985 /* Compute latestXid while we have the child XIDs handy */
986 latestXid
= TransactionIdLatest(xid
, nchildren
, children
);
988 /* Reset XactLastRecEnd until the next transaction writes something */
989 XactLastRecEnd
.xrecoff
= 0;
992 /* Clean up local data */
1001 * AtCommit_LocalCache
1004 AtCommit_LocalCache(void)
1007 * Make catalog changes visible to me for the next command.
1009 CommandEndInvalidationMessages();
1016 AtCommit_Memory(void)
1019 * Now that we're "out" of a transaction, have the system allocate things
1020 * in the top memory context instead of per-transaction contexts.
1022 MemoryContextSwitchTo(TopMemoryContext
);
1025 * Release all transaction-local memory.
1027 Assert(TopTransactionContext
!= NULL
);
1028 MemoryContextDelete(TopTransactionContext
);
1029 TopTransactionContext
= NULL
;
1030 CurTransactionContext
= NULL
;
1031 CurrentTransactionState
->curTransactionContext
= NULL
;
1034 /* ----------------------------------------------------------------
1035 * CommitSubTransaction stuff
1036 * ----------------------------------------------------------------
1040 * AtSubCommit_Memory
1043 AtSubCommit_Memory(void)
1045 TransactionState s
= CurrentTransactionState
;
1047 Assert(s
->parent
!= NULL
);
1049 /* Return to parent transaction level's memory context. */
1050 CurTransactionContext
= s
->parent
->curTransactionContext
;
1051 MemoryContextSwitchTo(CurTransactionContext
);
1054 * Ordinarily we cannot throw away the child's CurTransactionContext,
1055 * since the data it contains will be needed at upper commit. However, if
1056 * there isn't actually anything in it, we can throw it away. This avoids
1057 * a small memory leak in the common case of "trivial" subxacts.
1059 if (MemoryContextIsEmpty(s
->curTransactionContext
))
1061 MemoryContextDelete(s
->curTransactionContext
);
1062 s
->curTransactionContext
= NULL
;
1067 * AtSubCommit_childXids
1069 * Pass my own XID and my child XIDs up to my parent as committed children.
1072 AtSubCommit_childXids(void)
1074 TransactionState s
= CurrentTransactionState
;
1077 Assert(s
->parent
!= NULL
);
1080 * The parent childXids array will need to hold my XID and all my
1081 * childXids, in addition to the XIDs already there.
1083 new_nChildXids
= s
->parent
->nChildXids
+ s
->nChildXids
+ 1;
1085 /* Allocate or enlarge the parent array if necessary */
1086 if (s
->parent
->maxChildXids
< new_nChildXids
)
1088 int new_maxChildXids
;
1089 TransactionId
*new_childXids
;
1092 * Make it 2x what's needed right now, to avoid having to enlarge it
1093 * repeatedly. But we can't go above MaxAllocSize. (The latter limit
1094 * is what ensures that we don't need to worry about integer overflow
1095 * here or in the calculation of new_nChildXids.)
1097 new_maxChildXids
= Min(new_nChildXids
* 2,
1098 (int) (MaxAllocSize
/ sizeof(TransactionId
)));
1100 if (new_maxChildXids
< new_nChildXids
)
1102 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
1103 errmsg("maximum number of committed subtransactions (%d) exceeded",
1104 (int) (MaxAllocSize
/ sizeof(TransactionId
)))));
1107 * We keep the child-XID arrays in TopTransactionContext; this avoids
1108 * setting up child-transaction contexts for what might be just a few
1109 * bytes of grandchild XIDs.
1111 if (s
->parent
->childXids
== NULL
)
1113 MemoryContextAlloc(TopTransactionContext
,
1114 new_maxChildXids
* sizeof(TransactionId
));
1116 new_childXids
= repalloc(s
->parent
->childXids
,
1117 new_maxChildXids
* sizeof(TransactionId
));
1119 s
->parent
->childXids
= new_childXids
;
1120 s
->parent
->maxChildXids
= new_maxChildXids
;
1124 * Copy all my XIDs to parent's array.
1126 * Note: We rely on the fact that the XID of a child always follows that
1127 * of its parent. By copying the XID of this subtransaction before the
1128 * XIDs of its children, we ensure that the array stays ordered.
1129 * Likewise, all XIDs already in the array belong to subtransactions
1130 * started and subcommitted before us, so their XIDs must precede ours.
1132 s
->parent
->childXids
[s
->parent
->nChildXids
] = s
->transactionId
;
1134 if (s
->nChildXids
> 0)
1135 memcpy(&s
->parent
->childXids
[s
->parent
->nChildXids
+ 1],
1137 s
->nChildXids
* sizeof(TransactionId
));
1139 s
->parent
->nChildXids
= new_nChildXids
;
1141 /* Release child's array to avoid leakage */
1142 if (s
->childXids
!= NULL
)
1143 pfree(s
->childXids
);
1144 /* We must reset these to avoid double-free if fail later in commit */
1145 s
->childXids
= NULL
;
1147 s
->maxChildXids
= 0;
1150 /* ----------------------------------------------------------------
1151 * AbortTransaction stuff
1152 * ----------------------------------------------------------------
1156 * RecordTransactionAbort
1158 * Returns latest XID among xact and its children, or InvalidTransactionId
1159 * if the xact has no XID. (We compute that here just because it's easier.)
1161 static TransactionId
1162 RecordTransactionAbort(bool isSubXact
)
1164 TransactionId xid
= GetCurrentTransactionIdIfAny();
1165 TransactionId latestXid
;
1169 TransactionId
*children
;
1170 XLogRecData rdata
[3];
1172 xl_xact_abort xlrec
;
1175 * If we haven't been assigned an XID, nobody will care whether we aborted
1176 * or not. Hence, we're done in that case. It does not matter if we have
1177 * rels to delete (note that this routine is not responsible for actually
1178 * deleting 'em). We cannot have any child XIDs, either.
1180 if (!TransactionIdIsValid(xid
))
1182 /* Reset XactLastRecEnd until the next transaction writes something */
1184 XactLastRecEnd
.xrecoff
= 0;
1185 return InvalidTransactionId
;
1189 * We have a valid XID, so we should write an ABORT record for it.
1191 * We do not flush XLOG to disk here, since the default assumption after a
1192 * crash would be that we aborted, anyway. For the same reason, we don't
1193 * need to worry about interlocking against checkpoint start.
1197 * Check that we haven't aborted halfway through RecordTransactionCommit.
1199 if (TransactionIdDidCommit(xid
))
1200 elog(PANIC
, "cannot abort transaction %u, it was already committed",
1203 /* Fetch the data we need for the abort record */
1204 nrels
= smgrGetPendingDeletes(false, &rels
, NULL
);
1205 nchildren
= xactGetCommittedChildren(&children
);
1207 /* XXX do we really need a critical section here? */
1208 START_CRIT_SECTION();
1210 /* Write the ABORT record */
1212 xlrec
.xact_time
= GetCurrentTimestamp();
1215 SetCurrentTransactionStopTimestamp();
1216 xlrec
.xact_time
= xactStopTimestamp
;
1218 xlrec
.nrels
= nrels
;
1219 xlrec
.nsubxacts
= nchildren
;
1220 rdata
[0].data
= (char *) (&xlrec
);
1221 rdata
[0].len
= MinSizeOfXactAbort
;
1222 rdata
[0].buffer
= InvalidBuffer
;
1223 /* dump rels to delete */
1226 rdata
[0].next
= &(rdata
[1]);
1227 rdata
[1].data
= (char *) rels
;
1228 rdata
[1].len
= nrels
* sizeof(RelFileNode
);
1229 rdata
[1].buffer
= InvalidBuffer
;
1232 /* dump committed child Xids */
1235 rdata
[lastrdata
].next
= &(rdata
[2]);
1236 rdata
[2].data
= (char *) children
;
1237 rdata
[2].len
= nchildren
* sizeof(TransactionId
);
1238 rdata
[2].buffer
= InvalidBuffer
;
1241 rdata
[lastrdata
].next
= NULL
;
1243 (void) XLogInsert(RM_XACT_ID
, XLOG_XACT_ABORT
, rdata
);
1246 * Mark the transaction aborted in clog. This is not absolutely necessary
1247 * but we may as well do it while we are here; also, in the subxact case
1248 * it is helpful because XactLockTableWait makes use of it to avoid
1249 * waiting for already-aborted subtransactions. It is OK to do it without
1250 * having flushed the ABORT record to disk, because in event of a crash
1251 * we'd be assumed to have aborted anyway.
1253 TransactionIdAbortTree(xid
, nchildren
, children
);
1257 /* Compute latestXid while we have the child XIDs handy */
1258 latestXid
= TransactionIdLatest(xid
, nchildren
, children
);
1261 * If we're aborting a subtransaction, we can immediately remove failed
1262 * XIDs from PGPROC's cache of running child XIDs. We do that here for
1263 * subxacts, because we already have the child XID array at hand. For
1264 * main xacts, the equivalent happens just after this function returns.
1267 XidCacheRemoveRunningXids(xid
, nchildren
, children
, latestXid
);
1269 /* Reset XactLastRecEnd until the next transaction writes something */
1271 XactLastRecEnd
.xrecoff
= 0;
1273 /* And clean up local data */
1284 AtAbort_Memory(void)
1287 * Switch into TransactionAbortContext, which should have some free space
1288 * even if nothing else does. We'll work in this context until we've
1289 * finished cleaning up.
1291 * It is barely possible to get here when we've not been able to create
1292 * TransactionAbortContext yet; if so use TopMemoryContext.
1294 if (TransactionAbortContext
!= NULL
)
1295 MemoryContextSwitchTo(TransactionAbortContext
);
1297 MemoryContextSwitchTo(TopMemoryContext
);
1304 AtSubAbort_Memory(void)
1306 Assert(TransactionAbortContext
!= NULL
);
1308 MemoryContextSwitchTo(TransactionAbortContext
);
1313 * AtAbort_ResourceOwner
1316 AtAbort_ResourceOwner(void)
1319 * Make sure we have a valid ResourceOwner, if possible (else it will be
1320 * NULL, which is OK)
1322 CurrentResourceOwner
= TopTransactionResourceOwner
;
1326 * AtSubAbort_ResourceOwner
1329 AtSubAbort_ResourceOwner(void)
1331 TransactionState s
= CurrentTransactionState
;
1333 /* Make sure we have a valid ResourceOwner */
1334 CurrentResourceOwner
= s
->curTransactionOwner
;
1339 * AtSubAbort_childXids
1342 AtSubAbort_childXids(void)
1344 TransactionState s
= CurrentTransactionState
;
1347 * We keep the child-XID arrays in TopTransactionContext (see
1348 * AtSubCommit_childXids). This means we'd better free the array
1349 * explicitly at abort to avoid leakage.
1351 if (s
->childXids
!= NULL
)
1352 pfree(s
->childXids
);
1353 s
->childXids
= NULL
;
1355 s
->maxChildXids
= 0;
1358 /* ----------------------------------------------------------------
1359 * CleanupTransaction stuff
1360 * ----------------------------------------------------------------
1367 AtCleanup_Memory(void)
1369 Assert(CurrentTransactionState
->parent
== NULL
);
1372 * Now that we're "out" of a transaction, have the system allocate things
1373 * in the top memory context instead of per-transaction contexts.
1375 MemoryContextSwitchTo(TopMemoryContext
);
1378 * Clear the special abort context for next time.
1380 if (TransactionAbortContext
!= NULL
)
1381 MemoryContextResetAndDeleteChildren(TransactionAbortContext
);
1384 * Release all transaction-local memory.
1386 if (TopTransactionContext
!= NULL
)
1387 MemoryContextDelete(TopTransactionContext
);
1388 TopTransactionContext
= NULL
;
1389 CurTransactionContext
= NULL
;
1390 CurrentTransactionState
->curTransactionContext
= NULL
;
1394 /* ----------------------------------------------------------------
1395 * CleanupSubTransaction stuff
1396 * ----------------------------------------------------------------
1400 * AtSubCleanup_Memory
1403 AtSubCleanup_Memory(void)
1405 TransactionState s
= CurrentTransactionState
;
1407 Assert(s
->parent
!= NULL
);
1409 /* Make sure we're not in an about-to-be-deleted context */
1410 MemoryContextSwitchTo(s
->parent
->curTransactionContext
);
1411 CurTransactionContext
= s
->parent
->curTransactionContext
;
1414 * Clear the special abort context for next time.
1416 if (TransactionAbortContext
!= NULL
)
1417 MemoryContextResetAndDeleteChildren(TransactionAbortContext
);
1420 * Delete the subxact local memory contexts. Its CurTransactionContext can
1421 * go too (note this also kills CurTransactionContexts from any children
1424 if (s
->curTransactionContext
)
1425 MemoryContextDelete(s
->curTransactionContext
);
1426 s
->curTransactionContext
= NULL
;
1429 /* ----------------------------------------------------------------
1430 * interface routines
1431 * ----------------------------------------------------------------
1438 StartTransaction(void)
1441 VirtualTransactionId vxid
;
1444 * Let's just make sure the state stack is empty
1446 s
= &TopTransactionStateData
;
1447 CurrentTransactionState
= s
;
1450 * check the current transaction state
1452 if (s
->state
!= TRANS_DEFAULT
)
1453 elog(WARNING
, "StartTransaction while in %s state",
1454 TransStateAsString(s
->state
));
1457 * set the current transaction state information appropriately during
1460 s
->state
= TRANS_START
;
1461 s
->transactionId
= InvalidTransactionId
; /* until assigned */
1464 * Make sure we've reset xact state variables
1466 XactIsoLevel
= DefaultXactIsoLevel
;
1467 XactReadOnly
= DefaultXactReadOnly
;
1468 forceSyncCommit
= false;
1469 MyXactAccessedTempRel
= false;
1472 * reinitialize within-transaction counters
1474 s
->subTransactionId
= TopSubTransactionId
;
1475 currentSubTransactionId
= TopSubTransactionId
;
1476 currentCommandId
= FirstCommandId
;
1477 currentCommandIdUsed
= false;
1480 * must initialize resource-management stuff first
1483 AtStart_ResourceOwner();
1486 * Assign a new LocalTransactionId, and combine it with the backendId to
1487 * form a virtual transaction id.
1489 vxid
.backendId
= MyBackendId
;
1490 vxid
.localTransactionId
= GetNextLocalTransactionId();
1493 * Lock the virtual transaction id before we announce it in the proc array
1495 VirtualXactLockTableInsert(vxid
);
1498 * Advertise it in the proc array. We assume assignment of
1499 * LocalTransactionID is atomic, and the backendId should be set already.
1501 Assert(MyProc
->backendId
== vxid
.backendId
);
1502 MyProc
->lxid
= vxid
.localTransactionId
;
1504 TRACE_POSTGRESQL_TRANSACTION_START(vxid
.localTransactionId
);
1507 * set transaction_timestamp() (a/k/a now()). We want this to be the same
1508 * as the first command's statement_timestamp(), so don't do a fresh
1509 * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark
1510 * xactStopTimestamp as unset.
1512 xactStartTimestamp
= stmtStartTimestamp
;
1513 xactStopTimestamp
= 0;
1514 pgstat_report_xact_timestamp(xactStartTimestamp
);
1517 * initialize current transaction state fields
1519 * note: prevXactReadOnly is not used at the outermost level
1521 s
->nestingLevel
= 1;
1522 s
->gucNestLevel
= 1;
1523 s
->childXids
= NULL
;
1525 s
->maxChildXids
= 0;
1526 GetUserIdAndContext(&s
->prevUser
, &s
->prevSecDefCxt
);
1527 /* SecurityDefinerContext should never be set outside a transaction */
1528 Assert(!s
->prevSecDefCxt
);
1531 * initialize other subsystems for new transaction
1536 AfterTriggerBeginXact();
1539 * done with start processing, set current transaction state to "in
1542 s
->state
= TRANS_INPROGRESS
;
1544 ShowTransactionState("StartTransaction");
1551 * NB: if you change this routine, better look at PrepareTransaction too!
1554 CommitTransaction(void)
1556 TransactionState s
= CurrentTransactionState
;
1557 TransactionId latestXid
;
1559 ShowTransactionState("CommitTransaction");
1562 * check the current transaction state
1564 if (s
->state
!= TRANS_INPROGRESS
)
1565 elog(WARNING
, "CommitTransaction while in %s state",
1566 TransStateAsString(s
->state
));
1567 Assert(s
->parent
== NULL
);
1570 * Do pre-commit processing (most of this stuff requires database access,
1571 * and in fact could still cause an error...)
1573 * It is possible for CommitHoldablePortals to invoke functions that queue
1574 * deferred triggers, and it's also possible that triggers create holdable
1575 * cursors. So we have to loop until there's nothing left to do.
1580 * Fire all currently pending deferred triggers.
1582 AfterTriggerFireDeferred();
1585 * Convert any open holdable cursors into static portals. If there
1586 * weren't any, we are done ... otherwise loop back to check if they
1587 * queued deferred triggers. Lather, rinse, repeat.
1589 if (!CommitHoldablePortals())
1593 /* Now we can shut down the deferred-trigger manager */
1594 AfterTriggerEndXact(true);
1596 /* Close any open regular cursors */
1600 * Let ON COMMIT management do its thing (must happen after closing
1601 * cursors, to avoid dangling-reference problems)
1603 PreCommit_on_commit_actions();
1605 /* close large objects before lower-level cleanup */
1606 AtEOXact_LargeObject(true);
1608 /* NOTIFY commit must come before lower-level cleanup */
1612 * Update flat files if we changed pg_database, pg_authid or
1613 * pg_auth_members. This should be the last step before commit.
1615 AtEOXact_UpdateFlatFiles(true);
1617 /* Prevent cancel/die interrupt while cleaning up */
1621 * set the current transaction state information appropriately during
1624 s
->state
= TRANS_COMMIT
;
1627 * Here is where we really truly commit.
1629 latestXid
= RecordTransactionCommit();
1631 TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc
->lxid
);
1634 * Let others know about no transaction in progress by me. Note that this
1635 * must be done _before_ releasing locks we hold and _after_
1636 * RecordTransactionCommit.
1638 ProcArrayEndTransaction(MyProc
, latestXid
);
1641 * This is all post-commit cleanup. Note that if an error is raised here,
1642 * it's too late to abort the transaction. This should be just
1643 * noncritical resource releasing.
1645 * The ordering of operations is not entirely random. The idea is:
1646 * release resources visible to other backends (eg, files, buffer pins);
1647 * then release locks; then release backend-local resources. We want to
1648 * release locks at the point where any backend waiting for us will see
1649 * our transaction as being fully cleaned up.
1651 * Resources that can be associated with individual queries are handled by
1652 * the ResourceOwner mechanism. The other calls here are for backend-wide
1656 CallXactCallbacks(XACT_EVENT_COMMIT
);
1658 ResourceOwnerRelease(TopTransactionResourceOwner
,
1659 RESOURCE_RELEASE_BEFORE_LOCKS
,
1662 /* Check we've released all buffer pins */
1663 AtEOXact_Buffers(true);
1665 /* Clean up the relation cache */
1666 AtEOXact_RelationCache(true);
1668 /* Clean up the snapshot manager */
1669 AtEarlyCommit_Snapshot();
1672 * Make catalog changes visible to all backends. This has to happen after
1673 * relcache references are dropped (see comments for
1674 * AtEOXact_RelationCache), but before locks are released (if anyone is
1675 * waiting for lock on a relation we've modified, we want them to know
1676 * about the catalog change before they start using the relation).
1678 AtEOXact_Inval(true);
1681 * Likewise, dropping of files deleted during the transaction is best done
1682 * after releasing relcache and buffer pins. (This is not strictly
1683 * necessary during commit, since such pins should have been released
1684 * already, but this ordering is definitely critical during abort.)
1686 smgrDoPendingDeletes(true);
1688 AtEOXact_MultiXact();
1690 ResourceOwnerRelease(TopTransactionResourceOwner
,
1691 RESOURCE_RELEASE_LOCKS
,
1693 ResourceOwnerRelease(TopTransactionResourceOwner
,
1694 RESOURCE_RELEASE_AFTER_LOCKS
,
1697 /* Check we've released all catcache entries */
1698 AtEOXact_CatCache(true);
1700 AtEOXact_GUC(true, 1);
1702 AtEOXact_on_commit_actions(true);
1703 AtEOXact_Namespace(true);
1704 /* smgrcommit already done */
1706 AtEOXact_ComboCid();
1707 AtEOXact_HashTables(true);
1708 AtEOXact_PgStat(true);
1709 AtEOXact_Snapshot(true);
1710 pgstat_report_xact_timestamp(0);
1712 CurrentResourceOwner
= NULL
;
1713 ResourceOwnerDelete(TopTransactionResourceOwner
);
1714 s
->curTransactionOwner
= NULL
;
1715 CurTransactionResourceOwner
= NULL
;
1716 TopTransactionResourceOwner
= NULL
;
1720 s
->transactionId
= InvalidTransactionId
;
1721 s
->subTransactionId
= InvalidSubTransactionId
;
1722 s
->nestingLevel
= 0;
1723 s
->gucNestLevel
= 0;
1724 s
->childXids
= NULL
;
1726 s
->maxChildXids
= 0;
1729 * done with commit processing, set current transaction state back to
1732 s
->state
= TRANS_DEFAULT
;
1734 RESUME_INTERRUPTS();
1739 * PrepareTransaction
1741 * NB: if you change this routine, better look at CommitTransaction too!
1744 PrepareTransaction(void)
1746 TransactionState s
= CurrentTransactionState
;
1747 TransactionId xid
= GetCurrentTransactionId();
1748 GlobalTransaction gxact
;
1749 TimestampTz prepared_at
;
1751 ShowTransactionState("PrepareTransaction");
1754 * check the current transaction state
1756 if (s
->state
!= TRANS_INPROGRESS
)
1757 elog(WARNING
, "PrepareTransaction while in %s state",
1758 TransStateAsString(s
->state
));
1759 Assert(s
->parent
== NULL
);
1762 * Do pre-commit processing (most of this stuff requires database access,
1763 * and in fact could still cause an error...)
1765 * It is possible for PrepareHoldablePortals to invoke functions that
1766 * queue deferred triggers, and it's also possible that triggers create
1767 * holdable cursors. So we have to loop until there's nothing left to do.
1772 * Fire all currently pending deferred triggers.
1774 AfterTriggerFireDeferred();
1777 * Convert any open holdable cursors into static portals. If there
1778 * weren't any, we are done ... otherwise loop back to check if they
1779 * queued deferred triggers. Lather, rinse, repeat.
1781 if (!PrepareHoldablePortals())
1785 /* Now we can shut down the deferred-trigger manager */
1786 AfterTriggerEndXact(true);
1788 /* Close any open regular cursors */
1792 * Let ON COMMIT management do its thing (must happen after closing
1793 * cursors, to avoid dangling-reference problems)
1795 PreCommit_on_commit_actions();
1797 /* close large objects before lower-level cleanup */
1798 AtEOXact_LargeObject(true);
1800 /* NOTIFY and flatfiles will be handled below */
1803 * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
1804 * this transaction. Having the prepared xact hold locks on another
1805 * backend's temp table seems a bad idea --- for instance it would prevent
1806 * the backend from exiting. There are other problems too, such as how to
1807 * clean up the source backend's local buffers and ON COMMIT state if the
1808 * prepared xact includes a DROP of a temp table.
1810 * We must check this after executing any ON COMMIT actions, because they
1811 * might still access a temp relation.
1813 * XXX In principle this could be relaxed to allow some useful special
1814 * cases, such as a temp table created and dropped all within the
1815 * transaction. That seems to require much more bookkeeping though.
1817 if (MyXactAccessedTempRel
)
1819 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1820 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1822 /* Prevent cancel/die interrupt while cleaning up */
1826 * set the current transaction state information appropriately during
1827 * prepare processing
1829 s
->state
= TRANS_PREPARE
;
1831 prepared_at
= GetCurrentTimestamp();
1833 /* Tell bufmgr and smgr to prepare for commit */
1837 * Reserve the GID for this transaction. This could fail if the requested
1838 * GID is invalid or already in use.
1840 gxact
= MarkAsPreparing(xid
, prepareGID
, prepared_at
,
1841 GetUserId(), MyDatabaseId
);
1845 * Collect data for the 2PC state file. Note that in general, no actual
1846 * state change should happen in the called modules during this step,
1847 * since it's still possible to fail before commit, and in that case we
1848 * want transaction abort to be able to clean up. (In particular, the
1849 * AtPrepare routines may error out if they find cases they cannot
1850 * handle.) State cleanup should happen in the PostPrepare routines
1851 * below. However, some modules can go ahead and clear state here because
1852 * they wouldn't do anything with it during abort anyway.
1854 * Note: because the 2PC state file records will be replayed in the same
1855 * order they are made, the order of these calls has to match the order in
1856 * which we want things to happen during COMMIT PREPARED or ROLLBACK
1857 * PREPARED; in particular, pay attention to whether things should happen
1858 * before or after releasing the transaction's locks.
1860 StartPrepare(gxact
);
1863 AtPrepare_UpdateFlatFiles();
1869 * Here is where we really truly prepare.
1871 * We have to record transaction prepares even if we didn't make any
1872 * updates, because the transaction manager might get confused if we lose
1873 * a global transaction.
1878 * Now we clean up backend-internal state and release internal resources.
1881 /* Reset XactLastRecEnd until the next transaction writes something */
1882 XactLastRecEnd
.xrecoff
= 0;
1885 * Let others know about no transaction in progress by me. This has to be
1886 * done *after* the prepared transaction has been marked valid, else
1887 * someone may think it is unlocked and recyclable.
1889 ProcArrayClearTransaction(MyProc
);
1892 * This is all post-transaction cleanup. Note that if an error is raised
1893 * here, it's too late to abort the transaction. This should be just
1894 * noncritical resource releasing. See notes in CommitTransaction.
1897 CallXactCallbacks(XACT_EVENT_PREPARE
);
1899 ResourceOwnerRelease(TopTransactionResourceOwner
,
1900 RESOURCE_RELEASE_BEFORE_LOCKS
,
1903 /* Check we've released all buffer pins */
1904 AtEOXact_Buffers(true);
1906 /* Clean up the relation cache */
1907 AtEOXact_RelationCache(true);
1909 /* Clean up the snapshot manager */
1910 AtEarlyCommit_Snapshot();
1912 /* notify and flatfiles don't need a postprepare call */
1914 PostPrepare_PgStat();
1916 PostPrepare_Inval();
1920 AtEOXact_MultiXact();
1922 PostPrepare_Locks(xid
);
1924 ResourceOwnerRelease(TopTransactionResourceOwner
,
1925 RESOURCE_RELEASE_LOCKS
,
1927 ResourceOwnerRelease(TopTransactionResourceOwner
,
1928 RESOURCE_RELEASE_AFTER_LOCKS
,
1931 /* Check we've released all catcache entries */
1932 AtEOXact_CatCache(true);
1934 /* PREPARE acts the same as COMMIT as far as GUC is concerned */
1935 AtEOXact_GUC(true, 1);
1937 AtEOXact_on_commit_actions(true);
1938 AtEOXact_Namespace(true);
1939 /* smgrcommit already done */
1941 AtEOXact_ComboCid();
1942 AtEOXact_HashTables(true);
1943 /* don't call AtEOXact_PgStat here */
1944 AtEOXact_Snapshot(true);
1946 CurrentResourceOwner
= NULL
;
1947 ResourceOwnerDelete(TopTransactionResourceOwner
);
1948 s
->curTransactionOwner
= NULL
;
1949 CurTransactionResourceOwner
= NULL
;
1950 TopTransactionResourceOwner
= NULL
;
1954 s
->transactionId
= InvalidTransactionId
;
1955 s
->subTransactionId
= InvalidSubTransactionId
;
1956 s
->nestingLevel
= 0;
1957 s
->gucNestLevel
= 0;
1958 s
->childXids
= NULL
;
1960 s
->maxChildXids
= 0;
1963 * done with 1st phase commit processing, set current transaction state
1966 s
->state
= TRANS_DEFAULT
;
1968 RESUME_INTERRUPTS();
1976 AbortTransaction(void)
1978 TransactionState s
= CurrentTransactionState
;
1979 TransactionId latestXid
;
1981 /* Prevent cancel/die interrupt while cleaning up */
1984 /* Make sure we have a valid memory context and resource owner */
1986 AtAbort_ResourceOwner();
1989 * Release any LW locks we might be holding as quickly as possible.
1990 * (Regular locks, however, must be held till we finish aborting.)
1991 * Releasing LW locks is critical since we might try to grab them again
1992 * while cleaning up!
1996 /* Clean up buffer I/O and buffer context locks, too */
2001 * Also clean up any open wait for lock, since the lock manager will choke
2002 * if we try to wait for another lock before doing this.
2007 * check the current transaction state
2009 if (s
->state
!= TRANS_INPROGRESS
&& s
->state
!= TRANS_PREPARE
)
2010 elog(WARNING
, "AbortTransaction while in %s state",
2011 TransStateAsString(s
->state
));
2012 Assert(s
->parent
== NULL
);
2015 * set the current transaction state information appropriately during the
2018 s
->state
= TRANS_ABORT
;
2021 * Reset user ID which might have been changed transiently. We need this
2022 * to clean up in case control escaped out of a SECURITY DEFINER function
2023 * or other local change of CurrentUserId; therefore, the prior value of
2024 * SecurityDefinerContext also needs to be restored.
2026 * (Note: it is not necessary to restore session authorization or role
2027 * settings here because those can only be changed via GUC, and GUC will
2028 * take care of rolling them back if need be.)
2030 SetUserIdAndContext(s
->prevUser
, s
->prevSecDefCxt
);
2033 * do abort processing
2035 AfterTriggerEndXact(false);
2037 AtEOXact_LargeObject(false); /* 'false' means it's abort */
2039 AtEOXact_UpdateFlatFiles(false);
2042 * Advertise the fact that we aborted in pg_clog (assuming that we got as
2043 * far as assigning an XID to advertise).
2045 latestXid
= RecordTransactionAbort(false);
2047 TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc
->lxid
);
2050 * Let others know about no transaction in progress by me. Note that this
2051 * must be done _before_ releasing locks we hold and _after_
2052 * RecordTransactionAbort.
2054 ProcArrayEndTransaction(MyProc
, latestXid
);
2057 * Post-abort cleanup. See notes in CommitTransaction() concerning
2061 CallXactCallbacks(XACT_EVENT_ABORT
);
2063 ResourceOwnerRelease(TopTransactionResourceOwner
,
2064 RESOURCE_RELEASE_BEFORE_LOCKS
,
2066 AtEOXact_Buffers(false);
2067 AtEOXact_RelationCache(false);
2068 AtEOXact_Inval(false);
2069 smgrDoPendingDeletes(false);
2070 AtEOXact_MultiXact();
2071 ResourceOwnerRelease(TopTransactionResourceOwner
,
2072 RESOURCE_RELEASE_LOCKS
,
2074 ResourceOwnerRelease(TopTransactionResourceOwner
,
2075 RESOURCE_RELEASE_AFTER_LOCKS
,
2077 AtEOXact_CatCache(false);
2079 AtEOXact_GUC(false, 1);
2080 AtEOXact_SPI(false);
2081 AtEOXact_on_commit_actions(false);
2082 AtEOXact_Namespace(false);
2084 AtEOXact_ComboCid();
2085 AtEOXact_HashTables(false);
2086 AtEOXact_PgStat(false);
2087 AtEOXact_Snapshot(false);
2088 pgstat_report_xact_timestamp(0);
2091 * State remains TRANS_ABORT until CleanupTransaction().
2093 RESUME_INTERRUPTS();
2097 * CleanupTransaction
2100 CleanupTransaction(void)
2102 TransactionState s
= CurrentTransactionState
;
2105 * State should still be TRANS_ABORT from AbortTransaction().
2107 if (s
->state
!= TRANS_ABORT
)
2108 elog(FATAL
, "CleanupTransaction: unexpected state %s",
2109 TransStateAsString(s
->state
));
2112 * do abort cleanup processing
2114 AtCleanup_Portals(); /* now safe to release portal memory */
2116 CurrentResourceOwner
= NULL
; /* and resource owner */
2117 if (TopTransactionResourceOwner
)
2118 ResourceOwnerDelete(TopTransactionResourceOwner
);
2119 s
->curTransactionOwner
= NULL
;
2120 CurTransactionResourceOwner
= NULL
;
2121 TopTransactionResourceOwner
= NULL
;
2123 AtCleanup_Memory(); /* and transaction memory */
2125 s
->transactionId
= InvalidTransactionId
;
2126 s
->subTransactionId
= InvalidSubTransactionId
;
2127 s
->nestingLevel
= 0;
2128 s
->gucNestLevel
= 0;
2129 s
->childXids
= NULL
;
2131 s
->maxChildXids
= 0;
2134 * done with abort processing, set current transaction state back to
2137 s
->state
= TRANS_DEFAULT
;
2141 * StartTransactionCommand
2144 StartTransactionCommand(void)
2146 TransactionState s
= CurrentTransactionState
;
2148 switch (s
->blockState
)
2151 * if we aren't in a transaction block, we just do our usual start
2154 case TBLOCK_DEFAULT
:
2156 s
->blockState
= TBLOCK_STARTED
;
2160 * We are somewhere in a transaction block or subtransaction and
2161 * about to start a new command. For now we do nothing, but
2162 * someday we may do command-local resource initialization. (Note
2163 * that any needed CommandCounterIncrement was done by the
2164 * previous CommitTransactionCommand.)
2166 case TBLOCK_INPROGRESS
:
2167 case TBLOCK_SUBINPROGRESS
:
2171 * Here we are in a failed transaction block (one of the commands
2172 * caused an abort) so we do nothing but remain in the abort
2173 * state. Eventually we will get a ROLLBACK command which will
2174 * get us out of this state. (It is up to other code to ensure
2175 * that no commands other than ROLLBACK will be processed in these
2179 case TBLOCK_SUBABORT
:
2182 /* These cases are invalid. */
2183 case TBLOCK_STARTED
:
2185 case TBLOCK_SUBBEGIN
:
2188 case TBLOCK_ABORT_END
:
2189 case TBLOCK_SUBABORT_END
:
2190 case TBLOCK_ABORT_PENDING
:
2191 case TBLOCK_SUBABORT_PENDING
:
2192 case TBLOCK_SUBRESTART
:
2193 case TBLOCK_SUBABORT_RESTART
:
2194 case TBLOCK_PREPARE
:
2195 elog(ERROR
, "StartTransactionCommand: unexpected state %s",
2196 BlockStateAsString(s
->blockState
));
2201 * We must switch to CurTransactionContext before returning. This is
2202 * already done if we called StartTransaction, otherwise not.
2204 Assert(CurTransactionContext
!= NULL
);
2205 MemoryContextSwitchTo(CurTransactionContext
);
2209 * CommitTransactionCommand
2212 CommitTransactionCommand(void)
2214 TransactionState s
= CurrentTransactionState
;
2216 switch (s
->blockState
)
2219 * This shouldn't happen, because it means the previous
2220 * StartTransactionCommand didn't set the STARTED state
2223 case TBLOCK_DEFAULT
:
2224 elog(FATAL
, "CommitTransactionCommand: unexpected state %s",
2225 BlockStateAsString(s
->blockState
));
2229 * If we aren't in a transaction block, just do our usual
2230 * transaction commit, and return to the idle state.
2232 case TBLOCK_STARTED
:
2233 CommitTransaction();
2234 s
->blockState
= TBLOCK_DEFAULT
;
2238 * We are completing a "BEGIN TRANSACTION" command, so we change
2239 * to the "transaction block in progress" state and return. (We
2240 * assume the BEGIN did nothing to the database, so we need no
2241 * CommandCounterIncrement.)
2244 s
->blockState
= TBLOCK_INPROGRESS
;
2248 * This is the case when we have finished executing a command
2249 * someplace within a transaction block. We increment the command
2250 * counter and return.
2252 case TBLOCK_INPROGRESS
:
2253 case TBLOCK_SUBINPROGRESS
:
2254 CommandCounterIncrement();
2258 * We are completing a "COMMIT" command. Do it and return to the
2262 CommitTransaction();
2263 s
->blockState
= TBLOCK_DEFAULT
;
2267 * Here we are in the middle of a transaction block but one of the
2268 * commands caused an abort so we do nothing but remain in the
2269 * abort state. Eventually we will get a ROLLBACK comand.
2272 case TBLOCK_SUBABORT
:
2276 * Here we were in an aborted transaction block and we just got
2277 * the ROLLBACK command from the user, so clean up the
2278 * already-aborted transaction and return to the idle state.
2280 case TBLOCK_ABORT_END
:
2281 CleanupTransaction();
2282 s
->blockState
= TBLOCK_DEFAULT
;
2286 * Here we were in a perfectly good transaction block but the user
2287 * told us to ROLLBACK anyway. We have to abort the transaction
2288 * and then clean up.
2290 case TBLOCK_ABORT_PENDING
:
2292 CleanupTransaction();
2293 s
->blockState
= TBLOCK_DEFAULT
;
2297 * We are completing a "PREPARE TRANSACTION" command. Do it and
2298 * return to the idle state.
2300 case TBLOCK_PREPARE
:
2301 PrepareTransaction();
2302 s
->blockState
= TBLOCK_DEFAULT
;
2306 * We were just issued a SAVEPOINT inside a transaction block.
2307 * Start a subtransaction. (DefineSavepoint already did
2308 * PushTransaction, so as to have someplace to put the SUBBEGIN
2311 case TBLOCK_SUBBEGIN
:
2312 StartSubTransaction();
2313 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2317 * We were issued a COMMIT or RELEASE command, so we end the
2318 * current subtransaction and return to the parent transaction.
2319 * The parent might be ended too, so repeat till we are all the
2320 * way out or find an INPROGRESS transaction.
2325 CommitSubTransaction();
2326 s
= CurrentTransactionState
; /* changed by pop */
2327 } while (s
->blockState
== TBLOCK_SUBEND
);
2328 /* If we had a COMMIT command, finish off the main xact too */
2329 if (s
->blockState
== TBLOCK_END
)
2331 Assert(s
->parent
== NULL
);
2332 CommitTransaction();
2333 s
->blockState
= TBLOCK_DEFAULT
;
2335 else if (s
->blockState
== TBLOCK_PREPARE
)
2337 Assert(s
->parent
== NULL
);
2338 PrepareTransaction();
2339 s
->blockState
= TBLOCK_DEFAULT
;
2343 Assert(s
->blockState
== TBLOCK_INPROGRESS
||
2344 s
->blockState
== TBLOCK_SUBINPROGRESS
);
2349 * The current already-failed subtransaction is ending due to a
2350 * ROLLBACK or ROLLBACK TO command, so pop it and recursively
2351 * examine the parent (which could be in any of several states).
2353 case TBLOCK_SUBABORT_END
:
2354 CleanupSubTransaction();
2355 CommitTransactionCommand();
2359 * As above, but it's not dead yet, so abort first.
2361 case TBLOCK_SUBABORT_PENDING
:
2362 AbortSubTransaction();
2363 CleanupSubTransaction();
2364 CommitTransactionCommand();
2368 * The current subtransaction is the target of a ROLLBACK TO
2369 * command. Abort and pop it, then start a new subtransaction
2370 * with the same name.
2372 case TBLOCK_SUBRESTART
:
2377 /* save name and keep Cleanup from freeing it */
2380 savepointLevel
= s
->savepointLevel
;
2382 AbortSubTransaction();
2383 CleanupSubTransaction();
2385 DefineSavepoint(NULL
);
2386 s
= CurrentTransactionState
; /* changed by push */
2388 s
->savepointLevel
= savepointLevel
;
2390 /* This is the same as TBLOCK_SUBBEGIN case */
2391 AssertState(s
->blockState
== TBLOCK_SUBBEGIN
);
2392 StartSubTransaction();
2393 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2398 * Same as above, but the subtransaction had already failed, so we
2399 * don't need AbortSubTransaction.
2401 case TBLOCK_SUBABORT_RESTART
:
2406 /* save name and keep Cleanup from freeing it */
2409 savepointLevel
= s
->savepointLevel
;
2411 CleanupSubTransaction();
2413 DefineSavepoint(NULL
);
2414 s
= CurrentTransactionState
; /* changed by push */
2416 s
->savepointLevel
= savepointLevel
;
2418 /* This is the same as TBLOCK_SUBBEGIN case */
2419 AssertState(s
->blockState
== TBLOCK_SUBBEGIN
);
2420 StartSubTransaction();
2421 s
->blockState
= TBLOCK_SUBINPROGRESS
;
2428 * AbortCurrentTransaction
2431 AbortCurrentTransaction(void)
2433 TransactionState s
= CurrentTransactionState
;
2435 switch (s
->blockState
)
2437 case TBLOCK_DEFAULT
:
2438 if (s
->state
== TRANS_DEFAULT
)
2440 /* we are idle, so nothing to do */
2445 * We can get here after an error during transaction start
2446 * (state will be TRANS_START). Need to clean up the
2447 * incompletely started transaction. First, adjust the
2448 * low-level state to suppress warning message from
2451 if (s
->state
== TRANS_START
)
2452 s
->state
= TRANS_INPROGRESS
;
2454 CleanupTransaction();
2459 * if we aren't in a transaction block, we just do the basic abort
2460 * & cleanup transaction.
2462 case TBLOCK_STARTED
:
2464 CleanupTransaction();
2465 s
->blockState
= TBLOCK_DEFAULT
;
2469 * If we are in TBLOCK_BEGIN it means something screwed up right
2470 * after reading "BEGIN TRANSACTION". We assume that the user
2471 * will interpret the error as meaning the BEGIN failed to get him
2472 * into a transaction block, so we should abort and return to idle
2477 CleanupTransaction();
2478 s
->blockState
= TBLOCK_DEFAULT
;
2482 * We are somewhere in a transaction block and we've gotten a
2483 * failure, so we abort the transaction and set up the persistent
2484 * ABORT state. We will stay in ABORT until we get a ROLLBACK.
2486 case TBLOCK_INPROGRESS
:
2488 s
->blockState
= TBLOCK_ABORT
;
2489 /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
2493 * Here, we failed while trying to COMMIT. Clean up the
2494 * transaction and return to idle state (we do not want to stay in
2499 CleanupTransaction();
2500 s
->blockState
= TBLOCK_DEFAULT
;
2504 * Here, we are already in an aborted transaction state and are
2505 * waiting for a ROLLBACK, but for some reason we failed again! So
2506 * we just remain in the abort state.
2509 case TBLOCK_SUBABORT
:
2513 * We are in a failed transaction and we got the ROLLBACK command.
2514 * We have already aborted, we just need to cleanup and go to idle
2517 case TBLOCK_ABORT_END
:
2518 CleanupTransaction();
2519 s
->blockState
= TBLOCK_DEFAULT
;
2523 * We are in a live transaction and we got a ROLLBACK command.
2524 * Abort, cleanup, go to idle state.
2526 case TBLOCK_ABORT_PENDING
:
2528 CleanupTransaction();
2529 s
->blockState
= TBLOCK_DEFAULT
;
2533 * Here, we failed while trying to PREPARE. Clean up the
2534 * transaction and return to idle state (we do not want to stay in
2537 case TBLOCK_PREPARE
:
2539 CleanupTransaction();
2540 s
->blockState
= TBLOCK_DEFAULT
;
2544 * We got an error inside a subtransaction. Abort just the
2545 * subtransaction, and go to the persistent SUBABORT state until
2548 case TBLOCK_SUBINPROGRESS
:
2549 AbortSubTransaction();
2550 s
->blockState
= TBLOCK_SUBABORT
;
2554 * If we failed while trying to create a subtransaction, clean up
2555 * the broken subtransaction and abort the parent. The same
2556 * applies if we get a failure while ending a subtransaction.
2558 case TBLOCK_SUBBEGIN
:
2560 case TBLOCK_SUBABORT_PENDING
:
2561 case TBLOCK_SUBRESTART
:
2562 AbortSubTransaction();
2563 CleanupSubTransaction();
2564 AbortCurrentTransaction();
2568 * Same as above, except the Abort() was already done.
2570 case TBLOCK_SUBABORT_END
:
2571 case TBLOCK_SUBABORT_RESTART
:
2572 CleanupSubTransaction();
2573 AbortCurrentTransaction();
2579 * PreventTransactionChain
2581 * This routine is to be called by statements that must not run inside
2582 * a transaction block, typically because they have non-rollback-able
2583 * side effects or do internal commits.
2585 * If we have already started a transaction block, issue an error; also issue
2586 * an error if we appear to be running inside a user-defined function (which
2587 * could issue more commands and possibly cause a failure after the statement
2588 * completes). Subtransactions are verboten too.
2590 * isTopLevel: passed down from ProcessUtility to determine whether we are
2591 * inside a function or multi-query querystring. (We will always fail if
2592 * this is false, but it's convenient to centralize the check here instead of
2593 * making callers do it.)
2594 * stmtType: statement type name, for error messages.
2597 PreventTransactionChain(bool isTopLevel
, const char *stmtType
)
2600 * xact block already started?
2602 if (IsTransactionBlock())
2604 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2605 /* translator: %s represents an SQL statement name */
2606 errmsg("%s cannot run inside a transaction block",
2612 if (IsSubTransaction())
2614 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2615 /* translator: %s represents an SQL statement name */
2616 errmsg("%s cannot run inside a subtransaction",
2620 * inside a function call?
2624 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2625 /* translator: %s represents an SQL statement name */
2626 errmsg("%s cannot be executed from a function or multi-command string",
2629 /* If we got past IsTransactionBlock test, should be in default state */
2630 if (CurrentTransactionState
->blockState
!= TBLOCK_DEFAULT
&&
2631 CurrentTransactionState
->blockState
!= TBLOCK_STARTED
)
2632 elog(FATAL
, "cannot prevent transaction chain");
2637 * RequireTransactionChain
2639 * This routine is to be called by statements that must run inside
2640 * a transaction block, because they have no effects that persist past
2641 * transaction end (and so calling them outside a transaction block
2642 * is presumably an error). DECLARE CURSOR is an example.
2644 * If we appear to be running inside a user-defined function, we do not
2645 * issue an error, since the function could issue more commands that make
2646 * use of the current statement's results. Likewise subtransactions.
2647 * Thus this is an inverse for PreventTransactionChain.
2649 * isTopLevel: passed down from ProcessUtility to determine whether we are
2650 * inside a function.
2651 * stmtType: statement type name, for error messages.
2654 RequireTransactionChain(bool isTopLevel
, const char *stmtType
)
2657 * xact block already started?
2659 if (IsTransactionBlock())
2665 if (IsSubTransaction())
2669 * inside a function call?
2675 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
2676 /* translator: %s represents an SQL statement name */
2677 errmsg("%s can only be used in transaction blocks",
2682 * IsInTransactionChain
2684 * This routine is for statements that need to behave differently inside
2685 * a transaction block than when running as single commands. ANALYZE is
2686 * currently the only example.
2688 * isTopLevel: passed down from ProcessUtility to determine whether we are
2689 * inside a function.
2692 IsInTransactionChain(bool isTopLevel
)
2695 * Return true on same conditions that would make PreventTransactionChain
2698 if (IsTransactionBlock())
2701 if (IsSubTransaction())
2707 if (CurrentTransactionState
->blockState
!= TBLOCK_DEFAULT
&&
2708 CurrentTransactionState
->blockState
!= TBLOCK_STARTED
)
2716 * Register or deregister callback functions for start- and end-of-xact
2719 * These functions are intended for use by dynamically loaded modules.
2720 * For built-in modules we generally just hardwire the appropriate calls
2721 * (mainly because it's easier to control the order that way, where needed).
2723 * At transaction end, the callback occurs post-commit or post-abort, so the
2724 * callback functions can only do noncritical cleanup.
2727 RegisterXactCallback(XactCallback callback
, void *arg
)
2729 XactCallbackItem
*item
;
2731 item
= (XactCallbackItem
*)
2732 MemoryContextAlloc(TopMemoryContext
, sizeof(XactCallbackItem
));
2733 item
->callback
= callback
;
2735 item
->next
= Xact_callbacks
;
2736 Xact_callbacks
= item
;
2740 UnregisterXactCallback(XactCallback callback
, void *arg
)
2742 XactCallbackItem
*item
;
2743 XactCallbackItem
*prev
;
2746 for (item
= Xact_callbacks
; item
; prev
= item
, item
= item
->next
)
2748 if (item
->callback
== callback
&& item
->arg
== arg
)
2751 prev
->next
= item
->next
;
2753 Xact_callbacks
= item
->next
;
2761 CallXactCallbacks(XactEvent event
)
2763 XactCallbackItem
*item
;
2765 for (item
= Xact_callbacks
; item
; item
= item
->next
)
2766 (*item
->callback
) (event
, item
->arg
);
2771 * Register or deregister callback functions for start- and end-of-subxact
2774 * Pretty much same as above, but for subtransaction events.
2776 * At subtransaction end, the callback occurs post-subcommit or post-subabort,
2777 * so the callback functions can only do noncritical cleanup. At
2778 * subtransaction start, the callback is called when the subtransaction has
2779 * finished initializing.
2782 RegisterSubXactCallback(SubXactCallback callback
, void *arg
)
2784 SubXactCallbackItem
*item
;
2786 item
= (SubXactCallbackItem
*)
2787 MemoryContextAlloc(TopMemoryContext
, sizeof(SubXactCallbackItem
));
2788 item
->callback
= callback
;
2790 item
->next
= SubXact_callbacks
;
2791 SubXact_callbacks
= item
;
2795 UnregisterSubXactCallback(SubXactCallback callback
, void *arg
)
2797 SubXactCallbackItem
*item
;
2798 SubXactCallbackItem
*prev
;
2801 for (item
= SubXact_callbacks
; item
; prev
= item
, item
= item
->next
)
2803 if (item
->callback
== callback
&& item
->arg
== arg
)
2806 prev
->next
= item
->next
;
2808 SubXact_callbacks
= item
->next
;
2816 CallSubXactCallbacks(SubXactEvent event
,
2817 SubTransactionId mySubid
,
2818 SubTransactionId parentSubid
)
2820 SubXactCallbackItem
*item
;
2822 for (item
= SubXact_callbacks
; item
; item
= item
->next
)
2823 (*item
->callback
) (event
, mySubid
, parentSubid
, item
->arg
);
2827 /* ----------------------------------------------------------------
2828 * transaction block support
2829 * ----------------------------------------------------------------
2833 * BeginTransactionBlock
2834 * This executes a BEGIN command.
2837 BeginTransactionBlock(void)
2839 TransactionState s
= CurrentTransactionState
;
2841 switch (s
->blockState
)
2844 * We are not inside a transaction block, so allow one to begin.
2846 case TBLOCK_STARTED
:
2847 s
->blockState
= TBLOCK_BEGIN
;
2851 * Already a transaction block in progress.
2853 case TBLOCK_INPROGRESS
:
2854 case TBLOCK_SUBINPROGRESS
:
2856 case TBLOCK_SUBABORT
:
2858 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION
),
2859 errmsg("there is already a transaction in progress")));
2862 /* These cases are invalid. */
2863 case TBLOCK_DEFAULT
:
2865 case TBLOCK_SUBBEGIN
:
2868 case TBLOCK_ABORT_END
:
2869 case TBLOCK_SUBABORT_END
:
2870 case TBLOCK_ABORT_PENDING
:
2871 case TBLOCK_SUBABORT_PENDING
:
2872 case TBLOCK_SUBRESTART
:
2873 case TBLOCK_SUBABORT_RESTART
:
2874 case TBLOCK_PREPARE
:
2875 elog(FATAL
, "BeginTransactionBlock: unexpected state %s",
2876 BlockStateAsString(s
->blockState
));
2882 * PrepareTransactionBlock
2883 * This executes a PREPARE command.
2885 * Since PREPARE may actually do a ROLLBACK, the result indicates what
2886 * happened: TRUE for PREPARE, FALSE for ROLLBACK.
2888 * Note that we don't actually do anything here except change blockState.
2889 * The real work will be done in the upcoming PrepareTransaction().
2890 * We do it this way because it's not convenient to change memory context,
2891 * resource owner, etc while executing inside a Portal.
2894 PrepareTransactionBlock(char *gid
)
2899 /* Set up to commit the current transaction */
2900 result
= EndTransactionBlock();
2902 /* If successful, change outer tblock state to PREPARE */
2905 s
= CurrentTransactionState
;
2907 while (s
->parent
!= NULL
)
2910 if (s
->blockState
== TBLOCK_END
)
2912 /* Save GID where PrepareTransaction can find it again */
2913 prepareGID
= MemoryContextStrdup(TopTransactionContext
, gid
);
2915 s
->blockState
= TBLOCK_PREPARE
;
2920 * ignore case where we are not in a transaction;
2921 * EndTransactionBlock already issued a warning.
2923 Assert(s
->blockState
== TBLOCK_STARTED
);
2924 /* Don't send back a PREPARE result tag... */
2933 * EndTransactionBlock
2934 * This executes a COMMIT command.
2936 * Since COMMIT may actually do a ROLLBACK, the result indicates what
2937 * happened: TRUE for COMMIT, FALSE for ROLLBACK.
2939 * Note that we don't actually do anything here except change blockState.
2940 * The real work will be done in the upcoming CommitTransactionCommand().
2941 * We do it this way because it's not convenient to change memory context,
2942 * resource owner, etc while executing inside a Portal.
2945 EndTransactionBlock(void)
2947 TransactionState s
= CurrentTransactionState
;
2948 bool result
= false;
2950 switch (s
->blockState
)
2953 * We are in a transaction block, so tell CommitTransactionCommand
2956 case TBLOCK_INPROGRESS
:
2957 s
->blockState
= TBLOCK_END
;
2962 * We are in a failed transaction block. Tell
2963 * CommitTransactionCommand it's time to exit the block.
2966 s
->blockState
= TBLOCK_ABORT_END
;
2970 * We are in a live subtransaction block. Set up to subcommit all
2971 * open subtransactions and then commit the main transaction.
2973 case TBLOCK_SUBINPROGRESS
:
2974 while (s
->parent
!= NULL
)
2976 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
2977 s
->blockState
= TBLOCK_SUBEND
;
2979 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
2980 BlockStateAsString(s
->blockState
));
2983 if (s
->blockState
== TBLOCK_INPROGRESS
)
2984 s
->blockState
= TBLOCK_END
;
2986 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
2987 BlockStateAsString(s
->blockState
));
2992 * Here we are inside an aborted subtransaction. Treat the COMMIT
2993 * as ROLLBACK: set up to abort everything and exit the main
2996 case TBLOCK_SUBABORT
:
2997 while (s
->parent
!= NULL
)
2999 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3000 s
->blockState
= TBLOCK_SUBABORT_PENDING
;
3001 else if (s
->blockState
== TBLOCK_SUBABORT
)
3002 s
->blockState
= TBLOCK_SUBABORT_END
;
3004 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3005 BlockStateAsString(s
->blockState
));
3008 if (s
->blockState
== TBLOCK_INPROGRESS
)
3009 s
->blockState
= TBLOCK_ABORT_PENDING
;
3010 else if (s
->blockState
== TBLOCK_ABORT
)
3011 s
->blockState
= TBLOCK_ABORT_END
;
3013 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3014 BlockStateAsString(s
->blockState
));
3018 * The user issued COMMIT when not inside a transaction. Issue a
3019 * WARNING, staying in TBLOCK_STARTED state. The upcoming call to
3020 * CommitTransactionCommand() will then close the transaction and
3021 * put us back into the default state.
3023 case TBLOCK_STARTED
:
3025 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
3026 errmsg("there is no transaction in progress")));
3030 /* These cases are invalid. */
3031 case TBLOCK_DEFAULT
:
3033 case TBLOCK_SUBBEGIN
:
3036 case TBLOCK_ABORT_END
:
3037 case TBLOCK_SUBABORT_END
:
3038 case TBLOCK_ABORT_PENDING
:
3039 case TBLOCK_SUBABORT_PENDING
:
3040 case TBLOCK_SUBRESTART
:
3041 case TBLOCK_SUBABORT_RESTART
:
3042 case TBLOCK_PREPARE
:
3043 elog(FATAL
, "EndTransactionBlock: unexpected state %s",
3044 BlockStateAsString(s
->blockState
));
3052 * UserAbortTransactionBlock
3053 * This executes a ROLLBACK command.
3055 * As above, we don't actually do anything here except change blockState.
3058 UserAbortTransactionBlock(void)
3060 TransactionState s
= CurrentTransactionState
;
3062 switch (s
->blockState
)
3065 * We are inside a transaction block and we got a ROLLBACK command
3066 * from the user, so tell CommitTransactionCommand to abort and
3067 * exit the transaction block.
3069 case TBLOCK_INPROGRESS
:
3070 s
->blockState
= TBLOCK_ABORT_PENDING
;
3074 * We are inside a failed transaction block and we got a ROLLBACK
3075 * command from the user. Abort processing is already done, so
3076 * CommitTransactionCommand just has to cleanup and go back to
3080 s
->blockState
= TBLOCK_ABORT_END
;
3084 * We are inside a subtransaction. Mark everything up to top
3085 * level as exitable.
3087 case TBLOCK_SUBINPROGRESS
:
3088 case TBLOCK_SUBABORT
:
3089 while (s
->parent
!= NULL
)
3091 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3092 s
->blockState
= TBLOCK_SUBABORT_PENDING
;
3093 else if (s
->blockState
== TBLOCK_SUBABORT
)
3094 s
->blockState
= TBLOCK_SUBABORT_END
;
3096 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3097 BlockStateAsString(s
->blockState
));
3100 if (s
->blockState
== TBLOCK_INPROGRESS
)
3101 s
->blockState
= TBLOCK_ABORT_PENDING
;
3102 else if (s
->blockState
== TBLOCK_ABORT
)
3103 s
->blockState
= TBLOCK_ABORT_END
;
3105 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3106 BlockStateAsString(s
->blockState
));
3110 * The user issued ABORT when not inside a transaction. Issue a
3111 * WARNING and go to abort state. The upcoming call to
3112 * CommitTransactionCommand() will then put us back into the
3115 case TBLOCK_STARTED
:
3117 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION
),
3118 errmsg("there is no transaction in progress")));
3119 s
->blockState
= TBLOCK_ABORT_PENDING
;
3122 /* These cases are invalid. */
3123 case TBLOCK_DEFAULT
:
3125 case TBLOCK_SUBBEGIN
:
3128 case TBLOCK_ABORT_END
:
3129 case TBLOCK_SUBABORT_END
:
3130 case TBLOCK_ABORT_PENDING
:
3131 case TBLOCK_SUBABORT_PENDING
:
3132 case TBLOCK_SUBRESTART
:
3133 case TBLOCK_SUBABORT_RESTART
:
3134 case TBLOCK_PREPARE
:
3135 elog(FATAL
, "UserAbortTransactionBlock: unexpected state %s",
3136 BlockStateAsString(s
->blockState
));
3143 * This executes a SAVEPOINT command.
3146 DefineSavepoint(char *name
)
3148 TransactionState s
= CurrentTransactionState
;
3150 switch (s
->blockState
)
3152 case TBLOCK_INPROGRESS
:
3153 case TBLOCK_SUBINPROGRESS
:
3154 /* Normal subtransaction start */
3156 s
= CurrentTransactionState
; /* changed by push */
3159 * Savepoint names, like the TransactionState block itself, live
3160 * in TopTransactionContext.
3163 s
->name
= MemoryContextStrdup(TopTransactionContext
, name
);
3166 /* These cases are invalid. */
3167 case TBLOCK_DEFAULT
:
3168 case TBLOCK_STARTED
:
3170 case TBLOCK_SUBBEGIN
:
3174 case TBLOCK_SUBABORT
:
3175 case TBLOCK_ABORT_END
:
3176 case TBLOCK_SUBABORT_END
:
3177 case TBLOCK_ABORT_PENDING
:
3178 case TBLOCK_SUBABORT_PENDING
:
3179 case TBLOCK_SUBRESTART
:
3180 case TBLOCK_SUBABORT_RESTART
:
3181 case TBLOCK_PREPARE
:
3182 elog(FATAL
, "DefineSavepoint: unexpected state %s",
3183 BlockStateAsString(s
->blockState
));
3190 * This executes a RELEASE command.
3192 * As above, we don't actually do anything here except change blockState.
3195 ReleaseSavepoint(List
*options
)
3197 TransactionState s
= CurrentTransactionState
;
3198 TransactionState target
,
3203 switch (s
->blockState
)
3206 * We can't rollback to a savepoint if there is no savepoint
3209 case TBLOCK_INPROGRESS
:
3211 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3212 errmsg("no such savepoint")));
3216 * We are in a non-aborted subtransaction. This is the only valid
3219 case TBLOCK_SUBINPROGRESS
:
3222 /* These cases are invalid. */
3223 case TBLOCK_DEFAULT
:
3224 case TBLOCK_STARTED
:
3226 case TBLOCK_SUBBEGIN
:
3230 case TBLOCK_SUBABORT
:
3231 case TBLOCK_ABORT_END
:
3232 case TBLOCK_SUBABORT_END
:
3233 case TBLOCK_ABORT_PENDING
:
3234 case TBLOCK_SUBABORT_PENDING
:
3235 case TBLOCK_SUBRESTART
:
3236 case TBLOCK_SUBABORT_RESTART
:
3237 case TBLOCK_PREPARE
:
3238 elog(FATAL
, "ReleaseSavepoint: unexpected state %s",
3239 BlockStateAsString(s
->blockState
));
3243 foreach(cell
, options
)
3245 DefElem
*elem
= lfirst(cell
);
3247 if (strcmp(elem
->defname
, "savepoint_name") == 0)
3248 name
= strVal(elem
->arg
);
3251 Assert(PointerIsValid(name
));
3253 for (target
= s
; PointerIsValid(target
); target
= target
->parent
)
3255 if (PointerIsValid(target
->name
) && strcmp(target
->name
, name
) == 0)
3259 if (!PointerIsValid(target
))
3261 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3262 errmsg("no such savepoint")));
3264 /* disallow crossing savepoint level boundaries */
3265 if (target
->savepointLevel
!= s
->savepointLevel
)
3267 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3268 errmsg("no such savepoint")));
3271 * Mark "commit pending" all subtransactions up to the target
3272 * subtransaction. The actual commits will happen when control gets to
3273 * CommitTransactionCommand.
3275 xact
= CurrentTransactionState
;
3278 Assert(xact
->blockState
== TBLOCK_SUBINPROGRESS
);
3279 xact
->blockState
= TBLOCK_SUBEND
;
3282 xact
= xact
->parent
;
3283 Assert(PointerIsValid(xact
));
3288 * RollbackToSavepoint
3289 * This executes a ROLLBACK TO <savepoint> command.
3291 * As above, we don't actually do anything here except change blockState.
3294 RollbackToSavepoint(List
*options
)
3296 TransactionState s
= CurrentTransactionState
;
3297 TransactionState target
,
3302 switch (s
->blockState
)
3305 * We can't rollback to a savepoint if there is no savepoint
3308 case TBLOCK_INPROGRESS
:
3311 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3312 errmsg("no such savepoint")));
3316 * There is at least one savepoint, so proceed.
3318 case TBLOCK_SUBINPROGRESS
:
3319 case TBLOCK_SUBABORT
:
3322 /* These cases are invalid. */
3323 case TBLOCK_DEFAULT
:
3324 case TBLOCK_STARTED
:
3326 case TBLOCK_SUBBEGIN
:
3329 case TBLOCK_ABORT_END
:
3330 case TBLOCK_SUBABORT_END
:
3331 case TBLOCK_ABORT_PENDING
:
3332 case TBLOCK_SUBABORT_PENDING
:
3333 case TBLOCK_SUBRESTART
:
3334 case TBLOCK_SUBABORT_RESTART
:
3335 case TBLOCK_PREPARE
:
3336 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3337 BlockStateAsString(s
->blockState
));
3341 foreach(cell
, options
)
3343 DefElem
*elem
= lfirst(cell
);
3345 if (strcmp(elem
->defname
, "savepoint_name") == 0)
3346 name
= strVal(elem
->arg
);
3349 Assert(PointerIsValid(name
));
3351 for (target
= s
; PointerIsValid(target
); target
= target
->parent
)
3353 if (PointerIsValid(target
->name
) && strcmp(target
->name
, name
) == 0)
3357 if (!PointerIsValid(target
))
3359 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3360 errmsg("no such savepoint")));
3362 /* disallow crossing savepoint level boundaries */
3363 if (target
->savepointLevel
!= s
->savepointLevel
)
3365 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION
),
3366 errmsg("no such savepoint")));
3369 * Mark "abort pending" all subtransactions up to the target
3370 * subtransaction. The actual aborts will happen when control gets to
3371 * CommitTransactionCommand.
3373 xact
= CurrentTransactionState
;
3378 if (xact
->blockState
== TBLOCK_SUBINPROGRESS
)
3379 xact
->blockState
= TBLOCK_SUBABORT_PENDING
;
3380 else if (xact
->blockState
== TBLOCK_SUBABORT
)
3381 xact
->blockState
= TBLOCK_SUBABORT_END
;
3383 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3384 BlockStateAsString(xact
->blockState
));
3385 xact
= xact
->parent
;
3386 Assert(PointerIsValid(xact
));
3389 /* And mark the target as "restart pending" */
3390 if (xact
->blockState
== TBLOCK_SUBINPROGRESS
)
3391 xact
->blockState
= TBLOCK_SUBRESTART
;
3392 else if (xact
->blockState
== TBLOCK_SUBABORT
)
3393 xact
->blockState
= TBLOCK_SUBABORT_RESTART
;
3395 elog(FATAL
, "RollbackToSavepoint: unexpected state %s",
3396 BlockStateAsString(xact
->blockState
));
3400 * BeginInternalSubTransaction
3401 * This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
3402 * TBLOCK_END, and TBLOCK_PREPARE states, and therefore it can safely be
3403 * used in functions that might be called when not inside a BEGIN block
3404 * or when running deferred triggers at COMMIT/PREPARE time. Also, it
3405 * automatically does CommitTransactionCommand/StartTransactionCommand
3406 * instead of expecting the caller to do it.
3409 BeginInternalSubTransaction(char *name
)
3411 TransactionState s
= CurrentTransactionState
;
3413 switch (s
->blockState
)
3415 case TBLOCK_STARTED
:
3416 case TBLOCK_INPROGRESS
:
3418 case TBLOCK_PREPARE
:
3419 case TBLOCK_SUBINPROGRESS
:
3420 /* Normal subtransaction start */
3422 s
= CurrentTransactionState
; /* changed by push */
3425 * Savepoint names, like the TransactionState block itself, live
3426 * in TopTransactionContext.
3429 s
->name
= MemoryContextStrdup(TopTransactionContext
, name
);
3432 /* These cases are invalid. */
3433 case TBLOCK_DEFAULT
:
3435 case TBLOCK_SUBBEGIN
:
3438 case TBLOCK_SUBABORT
:
3439 case TBLOCK_ABORT_END
:
3440 case TBLOCK_SUBABORT_END
:
3441 case TBLOCK_ABORT_PENDING
:
3442 case TBLOCK_SUBABORT_PENDING
:
3443 case TBLOCK_SUBRESTART
:
3444 case TBLOCK_SUBABORT_RESTART
:
3445 elog(FATAL
, "BeginInternalSubTransaction: unexpected state %s",
3446 BlockStateAsString(s
->blockState
));
3450 CommitTransactionCommand();
3451 StartTransactionCommand();
3455 * ReleaseCurrentSubTransaction
3457 * RELEASE (ie, commit) the innermost subtransaction, regardless of its
3458 * savepoint name (if any).
3459 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3462 ReleaseCurrentSubTransaction(void)
3464 TransactionState s
= CurrentTransactionState
;
3466 if (s
->blockState
!= TBLOCK_SUBINPROGRESS
)
3467 elog(ERROR
, "ReleaseCurrentSubTransaction: unexpected state %s",
3468 BlockStateAsString(s
->blockState
));
3469 Assert(s
->state
== TRANS_INPROGRESS
);
3470 MemoryContextSwitchTo(CurTransactionContext
);
3471 CommitSubTransaction();
3472 s
= CurrentTransactionState
; /* changed by pop */
3473 Assert(s
->state
== TRANS_INPROGRESS
);
3477 * RollbackAndReleaseCurrentSubTransaction
3479 * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
3480 * of its savepoint name (if any).
3481 * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
3484 RollbackAndReleaseCurrentSubTransaction(void)
3486 TransactionState s
= CurrentTransactionState
;
3488 switch (s
->blockState
)
3490 /* Must be in a subtransaction */
3491 case TBLOCK_SUBINPROGRESS
:
3492 case TBLOCK_SUBABORT
:
3495 /* These cases are invalid. */
3496 case TBLOCK_DEFAULT
:
3497 case TBLOCK_STARTED
:
3499 case TBLOCK_SUBBEGIN
:
3500 case TBLOCK_INPROGRESS
:
3504 case TBLOCK_ABORT_END
:
3505 case TBLOCK_SUBABORT_END
:
3506 case TBLOCK_ABORT_PENDING
:
3507 case TBLOCK_SUBABORT_PENDING
:
3508 case TBLOCK_SUBRESTART
:
3509 case TBLOCK_SUBABORT_RESTART
:
3510 case TBLOCK_PREPARE
:
3511 elog(FATAL
, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
3512 BlockStateAsString(s
->blockState
));
3517 * Abort the current subtransaction, if needed.
3519 if (s
->blockState
== TBLOCK_SUBINPROGRESS
)
3520 AbortSubTransaction();
3522 /* And clean it up, too */
3523 CleanupSubTransaction();
3525 s
= CurrentTransactionState
; /* changed by pop */
3526 AssertState(s
->blockState
== TBLOCK_SUBINPROGRESS
||
3527 s
->blockState
== TBLOCK_INPROGRESS
||
3528 s
->blockState
== TBLOCK_STARTED
);
3532 * AbortOutOfAnyTransaction
3534 * This routine is provided for error recovery purposes. It aborts any
3535 * active transaction or transaction block, leaving the system in a known
3539 AbortOutOfAnyTransaction(void)
3541 TransactionState s
= CurrentTransactionState
;
3544 * Get out of any transaction or nested transaction
3548 switch (s
->blockState
)
3550 case TBLOCK_DEFAULT
:
3551 /* Not in a transaction, do nothing */
3553 case TBLOCK_STARTED
:
3555 case TBLOCK_INPROGRESS
:
3557 case TBLOCK_ABORT_PENDING
:
3558 case TBLOCK_PREPARE
:
3559 /* In a transaction, so clean up */
3561 CleanupTransaction();
3562 s
->blockState
= TBLOCK_DEFAULT
;
3565 case TBLOCK_ABORT_END
:
3566 /* AbortTransaction already done, still need Cleanup */
3567 CleanupTransaction();
3568 s
->blockState
= TBLOCK_DEFAULT
;
3572 * In a subtransaction, so clean it up and abort parent too
3574 case TBLOCK_SUBBEGIN
:
3575 case TBLOCK_SUBINPROGRESS
:
3577 case TBLOCK_SUBABORT_PENDING
:
3578 case TBLOCK_SUBRESTART
:
3579 AbortSubTransaction();
3580 CleanupSubTransaction();
3581 s
= CurrentTransactionState
; /* changed by pop */
3584 case TBLOCK_SUBABORT
:
3585 case TBLOCK_SUBABORT_END
:
3586 case TBLOCK_SUBABORT_RESTART
:
3587 /* As above, but AbortSubTransaction already done */
3588 CleanupSubTransaction();
3589 s
= CurrentTransactionState
; /* changed by pop */
3592 } while (s
->blockState
!= TBLOCK_DEFAULT
);
3594 /* Should be out of all subxacts now */
3595 Assert(s
->parent
== NULL
);
3599 * IsTransactionBlock --- are we within a transaction block?
3602 IsTransactionBlock(void)
3604 TransactionState s
= CurrentTransactionState
;
3606 if (s
->blockState
== TBLOCK_DEFAULT
|| s
->blockState
== TBLOCK_STARTED
)
3613 * IsTransactionOrTransactionBlock --- are we within either a transaction
3614 * or a transaction block? (The backend is only really "idle" when this
3617 * This should match up with IsTransactionBlock and IsTransactionState.
3620 IsTransactionOrTransactionBlock(void)
3622 TransactionState s
= CurrentTransactionState
;
3624 if (s
->blockState
== TBLOCK_DEFAULT
)
3631 * TransactionBlockStatusCode - return status code to send in ReadyForQuery
3634 TransactionBlockStatusCode(void)
3636 TransactionState s
= CurrentTransactionState
;
3638 switch (s
->blockState
)
3640 case TBLOCK_DEFAULT
:
3641 case TBLOCK_STARTED
:
3642 return 'I'; /* idle --- not in transaction */
3644 case TBLOCK_SUBBEGIN
:
3645 case TBLOCK_INPROGRESS
:
3646 case TBLOCK_SUBINPROGRESS
:
3649 case TBLOCK_PREPARE
:
3650 return 'T'; /* in transaction */
3652 case TBLOCK_SUBABORT
:
3653 case TBLOCK_ABORT_END
:
3654 case TBLOCK_SUBABORT_END
:
3655 case TBLOCK_ABORT_PENDING
:
3656 case TBLOCK_SUBABORT_PENDING
:
3657 case TBLOCK_SUBRESTART
:
3658 case TBLOCK_SUBABORT_RESTART
:
3659 return 'E'; /* in failed transaction */
3662 /* should never get here */
3663 elog(FATAL
, "invalid transaction block state: %s",
3664 BlockStateAsString(s
->blockState
));
3665 return 0; /* keep compiler quiet */
3672 IsSubTransaction(void)
3674 TransactionState s
= CurrentTransactionState
;
3676 if (s
->nestingLevel
>= 2)
3683 * StartSubTransaction
3685 * If you're wondering why this is separate from PushTransaction: it's because
3686 * we can't conveniently do this stuff right inside DefineSavepoint. The
3687 * SAVEPOINT utility command will be executed inside a Portal, and if we
3688 * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
3689 * the Portal will undo those settings. So we make DefineSavepoint just
3690 * push a dummy transaction block, and when control returns to the main
3691 * idle loop, CommitTransactionCommand will be called, and we'll come here
3692 * to finish starting the subtransaction.
3695 StartSubTransaction(void)
3697 TransactionState s
= CurrentTransactionState
;
3699 if (s
->state
!= TRANS_DEFAULT
)
3700 elog(WARNING
, "StartSubTransaction while in %s state",
3701 TransStateAsString(s
->state
));
3703 s
->state
= TRANS_START
;
3706 * Initialize subsystems for new subtransaction
3708 * must initialize resource-management stuff first
3710 AtSubStart_Memory();
3711 AtSubStart_ResourceOwner();
3713 AtSubStart_Notify();
3714 AfterTriggerBeginSubXact();
3716 s
->state
= TRANS_INPROGRESS
;
3719 * Call start-of-subxact callbacks
3721 CallSubXactCallbacks(SUBXACT_EVENT_START_SUB
, s
->subTransactionId
,
3722 s
->parent
->subTransactionId
);
3724 ShowTransactionState("StartSubTransaction");
3728 * CommitSubTransaction
3730 * The caller has to make sure to always reassign CurrentTransactionState
3731 * if it has a local pointer to it after calling this function.
3734 CommitSubTransaction(void)
3736 TransactionState s
= CurrentTransactionState
;
3738 ShowTransactionState("CommitSubTransaction");
3740 if (s
->state
!= TRANS_INPROGRESS
)
3741 elog(WARNING
, "CommitSubTransaction while in %s state",
3742 TransStateAsString(s
->state
));
3744 /* Pre-commit processing goes here -- nothing to do at the moment */
3746 s
->state
= TRANS_COMMIT
;
3748 /* Must CCI to ensure commands of subtransaction are seen as done */
3749 CommandCounterIncrement();
3752 * Prior to 8.4 we marked subcommit in clog at this point. We now only
3753 * perform that step, if required, as part of the atomic update of the
3754 * whole transaction tree at top level commit or abort.
3757 /* Post-commit cleanup */
3758 if (TransactionIdIsValid(s
->transactionId
))
3759 AtSubCommit_childXids();
3760 AfterTriggerEndSubXact(true);
3761 AtSubCommit_Portals(s
->subTransactionId
,
3762 s
->parent
->subTransactionId
,
3763 s
->parent
->curTransactionOwner
);
3764 AtEOSubXact_LargeObject(true, s
->subTransactionId
,
3765 s
->parent
->subTransactionId
);
3766 AtSubCommit_Notify();
3767 AtEOSubXact_UpdateFlatFiles(true, s
->subTransactionId
,
3768 s
->parent
->subTransactionId
);
3770 CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB
, s
->subTransactionId
,
3771 s
->parent
->subTransactionId
);
3773 ResourceOwnerRelease(s
->curTransactionOwner
,
3774 RESOURCE_RELEASE_BEFORE_LOCKS
,
3776 AtEOSubXact_RelationCache(true, s
->subTransactionId
,
3777 s
->parent
->subTransactionId
);
3778 AtEOSubXact_Inval(true);
3782 * The only lock we actually release here is the subtransaction XID lock.
3783 * The rest just get transferred to the parent resource owner.
3785 CurrentResourceOwner
= s
->curTransactionOwner
;
3786 if (TransactionIdIsValid(s
->transactionId
))
3787 XactLockTableDelete(s
->transactionId
);
3789 ResourceOwnerRelease(s
->curTransactionOwner
,
3790 RESOURCE_RELEASE_LOCKS
,
3792 ResourceOwnerRelease(s
->curTransactionOwner
,
3793 RESOURCE_RELEASE_AFTER_LOCKS
,
3796 AtEOXact_GUC(true, s
->gucNestLevel
);
3797 AtEOSubXact_SPI(true, s
->subTransactionId
);
3798 AtEOSubXact_on_commit_actions(true, s
->subTransactionId
,
3799 s
->parent
->subTransactionId
);
3800 AtEOSubXact_Namespace(true, s
->subTransactionId
,
3801 s
->parent
->subTransactionId
);
3802 AtEOSubXact_Files(true, s
->subTransactionId
,
3803 s
->parent
->subTransactionId
);
3804 AtEOSubXact_HashTables(true, s
->nestingLevel
);
3805 AtEOSubXact_PgStat(true, s
->nestingLevel
);
3806 AtSubCommit_Snapshot(s
->nestingLevel
);
3809 * We need to restore the upper transaction's read-only state, in case the
3810 * upper is read-write while the child is read-only; GUC will incorrectly
3811 * think it should leave the child state in place.
3813 XactReadOnly
= s
->prevXactReadOnly
;
3815 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
3816 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
3817 ResourceOwnerDelete(s
->curTransactionOwner
);
3818 s
->curTransactionOwner
= NULL
;
3820 AtSubCommit_Memory();
3822 s
->state
= TRANS_DEFAULT
;
3828 * AbortSubTransaction
3831 AbortSubTransaction(void)
3833 TransactionState s
= CurrentTransactionState
;
3835 /* Prevent cancel/die interrupt while cleaning up */
3838 /* Make sure we have a valid memory context and resource owner */
3839 AtSubAbort_Memory();
3840 AtSubAbort_ResourceOwner();
3843 * Release any LW locks we might be holding as quickly as possible.
3844 * (Regular locks, however, must be held till we finish aborting.)
3845 * Releasing LW locks is critical since we might try to grab them again
3846 * while cleaning up!
3848 * FIXME This may be incorrect --- Are there some locks we should keep?
3849 * Buffer locks, for example? I don't think so but I'm not sure.
3859 * check the current transaction state
3861 ShowTransactionState("AbortSubTransaction");
3863 if (s
->state
!= TRANS_INPROGRESS
)
3864 elog(WARNING
, "AbortSubTransaction while in %s state",
3865 TransStateAsString(s
->state
));
3867 s
->state
= TRANS_ABORT
;
3870 * Reset user ID which might have been changed transiently. (See notes in
3871 * AbortTransaction.)
3873 SetUserIdAndContext(s
->prevUser
, s
->prevSecDefCxt
);
3876 * We can skip all this stuff if the subxact failed before creating a
3879 if (s
->curTransactionOwner
)
3881 AfterTriggerEndSubXact(false);
3882 AtSubAbort_Portals(s
->subTransactionId
,
3883 s
->parent
->subTransactionId
,
3884 s
->parent
->curTransactionOwner
);
3885 AtEOSubXact_LargeObject(false, s
->subTransactionId
,
3886 s
->parent
->subTransactionId
);
3887 AtSubAbort_Notify();
3888 AtEOSubXact_UpdateFlatFiles(false, s
->subTransactionId
,
3889 s
->parent
->subTransactionId
);
3891 /* Advertise the fact that we aborted in pg_clog. */
3892 (void) RecordTransactionAbort(true);
3894 /* Post-abort cleanup */
3895 if (TransactionIdIsValid(s
->transactionId
))
3896 AtSubAbort_childXids();
3898 CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB
, s
->subTransactionId
,
3899 s
->parent
->subTransactionId
);
3901 ResourceOwnerRelease(s
->curTransactionOwner
,
3902 RESOURCE_RELEASE_BEFORE_LOCKS
,
3904 AtEOSubXact_RelationCache(false, s
->subTransactionId
,
3905 s
->parent
->subTransactionId
);
3906 AtEOSubXact_Inval(false);
3908 ResourceOwnerRelease(s
->curTransactionOwner
,
3909 RESOURCE_RELEASE_LOCKS
,
3911 ResourceOwnerRelease(s
->curTransactionOwner
,
3912 RESOURCE_RELEASE_AFTER_LOCKS
,
3915 AtEOXact_GUC(false, s
->gucNestLevel
);
3916 AtEOSubXact_SPI(false, s
->subTransactionId
);
3917 AtEOSubXact_on_commit_actions(false, s
->subTransactionId
,
3918 s
->parent
->subTransactionId
);
3919 AtEOSubXact_Namespace(false, s
->subTransactionId
,
3920 s
->parent
->subTransactionId
);
3921 AtEOSubXact_Files(false, s
->subTransactionId
,
3922 s
->parent
->subTransactionId
);
3923 AtEOSubXact_HashTables(false, s
->nestingLevel
);
3924 AtEOSubXact_PgStat(false, s
->nestingLevel
);
3925 AtSubAbort_Snapshot(s
->nestingLevel
);
3929 * Restore the upper transaction's read-only state, too. This should be
3930 * redundant with GUC's cleanup but we may as well do it for consistency
3931 * with the commit case.
3933 XactReadOnly
= s
->prevXactReadOnly
;
3935 RESUME_INTERRUPTS();
3939 * CleanupSubTransaction
3941 * The caller has to make sure to always reassign CurrentTransactionState
3942 * if it has a local pointer to it after calling this function.
3945 CleanupSubTransaction(void)
3947 TransactionState s
= CurrentTransactionState
;
3949 ShowTransactionState("CleanupSubTransaction");
3951 if (s
->state
!= TRANS_ABORT
)
3952 elog(WARNING
, "CleanupSubTransaction while in %s state",
3953 TransStateAsString(s
->state
));
3955 AtSubCleanup_Portals(s
->subTransactionId
);
3957 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
3958 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
3959 if (s
->curTransactionOwner
)
3960 ResourceOwnerDelete(s
->curTransactionOwner
);
3961 s
->curTransactionOwner
= NULL
;
3963 AtSubCleanup_Memory();
3965 s
->state
= TRANS_DEFAULT
;
3972 * Create transaction state stack entry for a subtransaction
3974 * The caller has to make sure to always reassign CurrentTransactionState
3975 * if it has a local pointer to it after calling this function.
3978 PushTransaction(void)
3980 TransactionState p
= CurrentTransactionState
;
3984 * We keep subtransaction state nodes in TopTransactionContext.
3986 s
= (TransactionState
)
3987 MemoryContextAllocZero(TopTransactionContext
,
3988 sizeof(TransactionStateData
));
3991 * Assign a subtransaction ID, watching out for counter wraparound.
3993 currentSubTransactionId
+= 1;
3994 if (currentSubTransactionId
== InvalidSubTransactionId
)
3996 currentSubTransactionId
-= 1;
3999 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED
),
4000 errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
4004 * We can now stack a minimally valid subtransaction without fear of
4007 s
->transactionId
= InvalidTransactionId
; /* until assigned */
4008 s
->subTransactionId
= currentSubTransactionId
;
4010 s
->nestingLevel
= p
->nestingLevel
+ 1;
4011 s
->gucNestLevel
= NewGUCNestLevel();
4012 s
->savepointLevel
= p
->savepointLevel
;
4013 s
->state
= TRANS_DEFAULT
;
4014 s
->blockState
= TBLOCK_SUBBEGIN
;
4015 GetUserIdAndContext(&s
->prevUser
, &s
->prevSecDefCxt
);
4016 s
->prevXactReadOnly
= XactReadOnly
;
4018 CurrentTransactionState
= s
;
4021 * AbortSubTransaction and CleanupSubTransaction have to be able to cope
4022 * with the subtransaction from here on out; in particular they should not
4023 * assume that it necessarily has a transaction context, resource owner,
4030 * Pop back to parent transaction state
4032 * The caller has to make sure to always reassign CurrentTransactionState
4033 * if it has a local pointer to it after calling this function.
4036 PopTransaction(void)
4038 TransactionState s
= CurrentTransactionState
;
4040 if (s
->state
!= TRANS_DEFAULT
)
4041 elog(WARNING
, "PopTransaction while in %s state",
4042 TransStateAsString(s
->state
));
4044 if (s
->parent
== NULL
)
4045 elog(FATAL
, "PopTransaction with no parent");
4047 CurrentTransactionState
= s
->parent
;
4049 /* Let's just make sure CurTransactionContext is good */
4050 CurTransactionContext
= s
->parent
->curTransactionContext
;
4051 MemoryContextSwitchTo(CurTransactionContext
);
4053 /* Ditto for ResourceOwner links */
4054 CurTransactionResourceOwner
= s
->parent
->curTransactionOwner
;
4055 CurrentResourceOwner
= s
->parent
->curTransactionOwner
;
4057 /* Free the old child structure */
4064 * ShowTransactionState
4068 ShowTransactionState(const char *str
)
4070 /* skip work if message will definitely not be printed */
4071 if (log_min_messages
<= DEBUG3
|| client_min_messages
<= DEBUG3
)
4073 elog(DEBUG3
, "%s", str
);
4074 ShowTransactionStateRec(CurrentTransactionState
);
4079 * ShowTransactionStateRec
4080 * Recursive subroutine for ShowTransactionState
4083 ShowTransactionStateRec(TransactionState s
)
4087 initStringInfo(&buf
);
4089 if (s
->nChildXids
> 0)
4093 appendStringInfo(&buf
, "%u", s
->childXids
[0]);
4094 for (i
= 1; i
< s
->nChildXids
; i
++)
4095 appendStringInfo(&buf
, " %u", s
->childXids
[i
]);
4099 ShowTransactionStateRec(s
->parent
);
4101 /* use ereport to suppress computation if msg will not be printed */
4103 (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s",
4104 PointerIsValid(s
->name
) ? s
->name
: "unnamed",
4105 BlockStateAsString(s
->blockState
),
4106 TransStateAsString(s
->state
),
4107 (unsigned int) s
->transactionId
,
4108 (unsigned int) s
->subTransactionId
,
4109 (unsigned int) currentCommandId
,
4110 currentCommandIdUsed
? " (used)" : "",
4111 s
->nestingLevel
, buf
.data
)));
4117 * BlockStateAsString
4121 BlockStateAsString(TBlockState blockState
)
4125 case TBLOCK_DEFAULT
:
4127 case TBLOCK_STARTED
:
4131 case TBLOCK_INPROGRESS
:
4132 return "INPROGRESS";
4137 case TBLOCK_ABORT_END
:
4139 case TBLOCK_ABORT_PENDING
:
4140 return "ABORT PEND";
4141 case TBLOCK_PREPARE
:
4143 case TBLOCK_SUBBEGIN
:
4145 case TBLOCK_SUBINPROGRESS
:
4146 return "SUB INPROGRS";
4149 case TBLOCK_SUBABORT
:
4151 case TBLOCK_SUBABORT_END
:
4152 return "SUB ABORT END";
4153 case TBLOCK_SUBABORT_PENDING
:
4154 return "SUB ABRT PEND";
4155 case TBLOCK_SUBRESTART
:
4156 return "SUB RESTART";
4157 case TBLOCK_SUBABORT_RESTART
:
4158 return "SUB AB RESTRT";
4160 return "UNRECOGNIZED";
4164 * TransStateAsString
4168 TransStateAsString(TransState state
)
4176 case TRANS_INPROGRESS
:
4185 return "UNRECOGNIZED";
4189 * xactGetCommittedChildren
4191 * Gets the list of committed children of the current transaction. The return
4192 * value is the number of child transactions. *ptr is set to point to an
4193 * array of TransactionIds. The array is allocated in TopTransactionContext;
4194 * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
4195 * If there are no subxacts, *ptr is set to NULL.
4198 xactGetCommittedChildren(TransactionId
**ptr
)
4200 TransactionState s
= CurrentTransactionState
;
4202 if (s
->nChildXids
== 0)
4205 *ptr
= s
->childXids
;
4207 return s
->nChildXids
;
4211 * XLOG support routines
4215 xact_redo_commit(xl_xact_commit
*xlrec
, TransactionId xid
)
4217 TransactionId
*sub_xids
;
4218 TransactionId max_xid
;
4221 /* Mark the transaction committed in pg_clog */
4222 sub_xids
= (TransactionId
*) &(xlrec
->xnodes
[xlrec
->nrels
]);
4223 TransactionIdCommitTree(xid
, xlrec
->nsubxacts
, sub_xids
);
4225 /* Make sure nextXid is beyond any XID mentioned in the record */
4227 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4229 if (TransactionIdPrecedes(max_xid
, sub_xids
[i
]))
4230 max_xid
= sub_xids
[i
];
4232 if (TransactionIdFollowsOrEquals(max_xid
,
4233 ShmemVariableCache
->nextXid
))
4235 ShmemVariableCache
->nextXid
= max_xid
;
4236 TransactionIdAdvance(ShmemVariableCache
->nextXid
);
4239 /* Make sure files supposed to be dropped are dropped */
4240 for (i
= 0; i
< xlrec
->nrels
; i
++)
4242 SMgrRelation srel
= smgropen(xlrec
->xnodes
[i
]);
4245 for (fork
= 0; fork
<= MAX_FORKNUM
; fork
++)
4247 if (smgrexists(srel
, fork
))
4249 XLogDropRelation(xlrec
->xnodes
[i
], fork
);
4250 smgrdounlink(srel
, fork
, false, true);
4258 xact_redo_abort(xl_xact_abort
*xlrec
, TransactionId xid
)
4260 TransactionId
*sub_xids
;
4261 TransactionId max_xid
;
4264 /* Mark the transaction aborted in pg_clog */
4265 sub_xids
= (TransactionId
*) &(xlrec
->xnodes
[xlrec
->nrels
]);
4266 TransactionIdAbortTree(xid
, xlrec
->nsubxacts
, sub_xids
);
4268 /* Make sure nextXid is beyond any XID mentioned in the record */
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
= smgropen(xlrec
->xnodes
[i
]);
4288 for (fork
= 0; fork
<= MAX_FORKNUM
; fork
++)
4290 if (smgrexists(srel
, fork
))
4292 XLogDropRelation(xlrec
->xnodes
[i
], fork
);
4293 smgrdounlink(srel
, fork
, false, true);
4301 xact_redo(XLogRecPtr lsn
, XLogRecord
*record
)
4303 uint8 info
= record
->xl_info
& ~XLR_INFO_MASK
;
4305 /* Backup blocks are not used in xact records */
4306 Assert(!(record
->xl_info
& XLR_BKP_BLOCK_MASK
));
4308 if (info
== XLOG_XACT_COMMIT
)
4310 xl_xact_commit
*xlrec
= (xl_xact_commit
*) XLogRecGetData(record
);
4312 xact_redo_commit(xlrec
, record
->xl_xid
);
4314 else if (info
== XLOG_XACT_ABORT
)
4316 xl_xact_abort
*xlrec
= (xl_xact_abort
*) XLogRecGetData(record
);
4318 xact_redo_abort(xlrec
, record
->xl_xid
);
4320 else if (info
== XLOG_XACT_PREPARE
)
4322 /* the record contents are exactly the 2PC file */
4323 RecreateTwoPhaseFile(record
->xl_xid
,
4324 XLogRecGetData(record
), record
->xl_len
);
4326 else if (info
== XLOG_XACT_COMMIT_PREPARED
)
4328 xl_xact_commit_prepared
*xlrec
= (xl_xact_commit_prepared
*) XLogRecGetData(record
);
4330 xact_redo_commit(&xlrec
->crec
, xlrec
->xid
);
4331 RemoveTwoPhaseFile(xlrec
->xid
, false);
4333 else if (info
== XLOG_XACT_ABORT_PREPARED
)
4335 xl_xact_abort_prepared
*xlrec
= (xl_xact_abort_prepared
*) XLogRecGetData(record
);
4337 xact_redo_abort(&xlrec
->arec
, xlrec
->xid
);
4338 RemoveTwoPhaseFile(xlrec
->xid
, false);
4341 elog(PANIC
, "xact_redo: unknown op code %u", info
);
4345 xact_desc_commit(StringInfo buf
, xl_xact_commit
*xlrec
)
4349 appendStringInfoString(buf
, timestamptz_to_str(xlrec
->xact_time
));
4350 if (xlrec
->nrels
> 0)
4352 appendStringInfo(buf
, "; rels:");
4353 for (i
= 0; i
< xlrec
->nrels
; i
++)
4355 char *path
= relpath(xlrec
->xnodes
[i
], MAIN_FORKNUM
);
4357 appendStringInfo(buf
, " %s", path
);
4361 if (xlrec
->nsubxacts
> 0)
4363 TransactionId
*xacts
= (TransactionId
*)
4364 &xlrec
->xnodes
[xlrec
->nrels
];
4366 appendStringInfo(buf
, "; subxacts:");
4367 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4368 appendStringInfo(buf
, " %u", xacts
[i
]);
4373 xact_desc_abort(StringInfo buf
, xl_xact_abort
*xlrec
)
4377 appendStringInfoString(buf
, timestamptz_to_str(xlrec
->xact_time
));
4378 if (xlrec
->nrels
> 0)
4380 appendStringInfo(buf
, "; rels:");
4381 for (i
= 0; i
< xlrec
->nrels
; i
++)
4383 char *path
= relpath(xlrec
->xnodes
[i
], MAIN_FORKNUM
);
4385 appendStringInfo(buf
, " %s", path
);
4389 if (xlrec
->nsubxacts
> 0)
4391 TransactionId
*xacts
= (TransactionId
*)
4392 &xlrec
->xnodes
[xlrec
->nrels
];
4394 appendStringInfo(buf
, "; subxacts:");
4395 for (i
= 0; i
< xlrec
->nsubxacts
; i
++)
4396 appendStringInfo(buf
, " %u", xacts
[i
]);
4401 xact_desc(StringInfo buf
, uint8 xl_info
, char *rec
)
4403 uint8 info
= xl_info
& ~XLR_INFO_MASK
;
4405 if (info
== XLOG_XACT_COMMIT
)
4407 xl_xact_commit
*xlrec
= (xl_xact_commit
*) rec
;
4409 appendStringInfo(buf
, "commit: ");
4410 xact_desc_commit(buf
, xlrec
);
4412 else if (info
== XLOG_XACT_ABORT
)
4414 xl_xact_abort
*xlrec
= (xl_xact_abort
*) rec
;
4416 appendStringInfo(buf
, "abort: ");
4417 xact_desc_abort(buf
, xlrec
);
4419 else if (info
== XLOG_XACT_PREPARE
)
4421 appendStringInfo(buf
, "prepare");
4423 else if (info
== XLOG_XACT_COMMIT_PREPARED
)
4425 xl_xact_commit_prepared
*xlrec
= (xl_xact_commit_prepared
*) rec
;
4427 appendStringInfo(buf
, "commit %u: ", xlrec
->xid
);
4428 xact_desc_commit(buf
, &xlrec
->crec
);
4430 else if (info
== XLOG_XACT_ABORT_PREPARED
)
4432 xl_xact_abort_prepared
*xlrec
= (xl_xact_abort_prepared
*) rec
;
4434 appendStringInfo(buf
, "abort %u: ", xlrec
->xid
);
4435 xact_desc_abort(buf
, &xlrec
->arec
);
4438 appendStringInfo(buf
, "UNKNOWN");