LCOV - code coverage report
Current view: top level - src/backend/access/transam - xact.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 1440 1649 87.3 %
Date: 2019-11-13 23:06:49 Functions: 97 106 91.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * xact.c
       4             :  *    top level transaction system support routines
       5             :  *
       6             :  * See src/backend/access/transam/README for more information.
       7             :  *
       8             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       9             :  * Portions Copyright (c) 1994, Regents of the University of California
      10             :  *
      11             :  *
      12             :  * IDENTIFICATION
      13             :  *    src/backend/access/transam/xact.c
      14             :  *
      15             :  *-------------------------------------------------------------------------
      16             :  */
      17             : 
      18             : #include "postgres.h"
      19             : 
      20             : #include <time.h>
      21             : #include <unistd.h>
      22             : 
      23             : #include "access/commit_ts.h"
      24             : #include "access/multixact.h"
      25             : #include "access/parallel.h"
      26             : #include "access/subtrans.h"
      27             : #include "access/transam.h"
      28             : #include "access/twophase.h"
      29             : #include "access/xact.h"
      30             : #include "access/xlog.h"
      31             : #include "access/xloginsert.h"
      32             : #include "access/xlogutils.h"
      33             : #include "catalog/namespace.h"
      34             : #include "catalog/pg_enum.h"
      35             : #include "catalog/storage.h"
      36             : #include "commands/async.h"
      37             : #include "commands/tablecmds.h"
      38             : #include "commands/trigger.h"
      39             : #include "executor/spi.h"
      40             : #include "libpq/be-fsstubs.h"
      41             : #include "libpq/pqsignal.h"
      42             : #include "miscadmin.h"
      43             : #include "pg_trace.h"
      44             : #include "pgstat.h"
      45             : #include "replication/logical.h"
      46             : #include "replication/logicallauncher.h"
      47             : #include "replication/origin.h"
      48             : #include "replication/syncrep.h"
      49             : #include "replication/walsender.h"
      50             : #include "storage/condition_variable.h"
      51             : #include "storage/fd.h"
      52             : #include "storage/lmgr.h"
      53             : #include "storage/md.h"
      54             : #include "storage/predicate.h"
      55             : #include "storage/proc.h"
      56             : #include "storage/procarray.h"
      57             : #include "storage/sinvaladt.h"
      58             : #include "storage/smgr.h"
      59             : #include "utils/builtins.h"
      60             : #include "utils/catcache.h"
      61             : #include "utils/combocid.h"
      62             : #include "utils/guc.h"
      63             : #include "utils/inval.h"
      64             : #include "utils/memutils.h"
      65             : #include "utils/relmapper.h"
      66             : #include "utils/snapmgr.h"
      67             : #include "utils/timeout.h"
      68             : #include "utils/timestamp.h"
      69             : 
      70             : /*
      71             :  *  User-tweakable parameters
      72             :  */
      73             : int         DefaultXactIsoLevel = XACT_READ_COMMITTED;
      74             : int         XactIsoLevel;
      75             : 
      76             : bool        DefaultXactReadOnly = false;
      77             : bool        XactReadOnly;
      78             : 
      79             : bool        DefaultXactDeferrable = false;
      80             : bool        XactDeferrable;
      81             : 
      82             : int         synchronous_commit = SYNCHRONOUS_COMMIT_ON;
      83             : 
      84             : /*
      85             :  * When running as a parallel worker, we place only a single
      86             :  * TransactionStateData on the parallel worker's state stack, and the XID
      87             :  * reflected there will be that of the *innermost* currently-active
      88             :  * subtransaction in the backend that initiated parallelism.  However,
      89             :  * GetTopTransactionId() and TransactionIdIsCurrentTransactionId()
      90             :  * need to return the same answers in the parallel worker as they would have
      91             :  * in the user backend, so we need some additional bookkeeping.
      92             :  *
      93             :  * XactTopFullTransactionId stores the XID of our toplevel transaction, which
      94             :  * will be the same as TopTransactionStateData.fullTransactionId in an
      95             :  * ordinary backend; but in a parallel backend, which does not have the entire
      96             :  * transaction state, it will instead be copied from the backend that started
      97             :  * the parallel operation.
      98             :  *
      99             :  * nParallelCurrentXids will be 0 and ParallelCurrentXids NULL in an ordinary
     100             :  * backend, but in a parallel backend, nParallelCurrentXids will contain the
     101             :  * number of XIDs that need to be considered current, and ParallelCurrentXids
     102             :  * will contain the XIDs themselves.  This includes all XIDs that were current
     103             :  * or sub-committed in the parent at the time the parallel operation began.
     104             :  * The XIDs are stored sorted in numerical order (not logical order) to make
     105             :  * lookups as fast as possible.
     106             :  */
     107             : FullTransactionId XactTopFullTransactionId = {InvalidTransactionId};
     108             : int         nParallelCurrentXids = 0;
     109             : TransactionId *ParallelCurrentXids;
     110             : 
     111             : /*
     112             :  * Miscellaneous flag bits to record events which occur on the top level
     113             :  * transaction. These flags are only persisted in MyXactFlags and are intended
     114             :  * so we remember to do certain things later on in the transaction. This is
     115             :  * globally accessible, so can be set from anywhere in the code that requires
     116             :  * recording flags.
     117             :  */
     118             : int         MyXactFlags;
     119             : 
     120             : /*
     121             :  *  transaction states - transaction state from server perspective
     122             :  */
     123             : typedef enum TransState
     124             : {
     125             :     TRANS_DEFAULT,              /* idle */
     126             :     TRANS_START,                /* transaction starting */
     127             :     TRANS_INPROGRESS,           /* inside a valid transaction */
     128             :     TRANS_COMMIT,               /* commit in progress */
     129             :     TRANS_ABORT,                /* abort in progress */
     130             :     TRANS_PREPARE               /* prepare in progress */
     131             : } TransState;
     132             : 
     133             : /*
     134             :  *  transaction block states - transaction state of client queries
     135             :  *
     136             :  * Note: the subtransaction states are used only for non-topmost
     137             :  * transactions; the others appear only in the topmost transaction.
     138             :  */
     139             : typedef enum TBlockState
     140             : {
     141             :     /* not-in-transaction-block states */
     142             :     TBLOCK_DEFAULT,             /* idle */
     143             :     TBLOCK_STARTED,             /* running single-query transaction */
     144             : 
     145             :     /* transaction block states */
     146             :     TBLOCK_BEGIN,               /* starting transaction block */
     147             :     TBLOCK_INPROGRESS,          /* live transaction */
     148             :     TBLOCK_IMPLICIT_INPROGRESS, /* live transaction after implicit BEGIN */
     149             :     TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
     150             :     TBLOCK_END,                 /* COMMIT received */
     151             :     TBLOCK_ABORT,               /* failed xact, awaiting ROLLBACK */
     152             :     TBLOCK_ABORT_END,           /* failed xact, ROLLBACK received */
     153             :     TBLOCK_ABORT_PENDING,       /* live xact, ROLLBACK received */
     154             :     TBLOCK_PREPARE,             /* live xact, PREPARE received */
     155             : 
     156             :     /* subtransaction states */
     157             :     TBLOCK_SUBBEGIN,            /* starting a subtransaction */
     158             :     TBLOCK_SUBINPROGRESS,       /* live subtransaction */
     159             :     TBLOCK_SUBRELEASE,          /* RELEASE received */
     160             :     TBLOCK_SUBCOMMIT,           /* COMMIT received while TBLOCK_SUBINPROGRESS */
     161             :     TBLOCK_SUBABORT,            /* failed subxact, awaiting ROLLBACK */
     162             :     TBLOCK_SUBABORT_END,        /* failed subxact, ROLLBACK received */
     163             :     TBLOCK_SUBABORT_PENDING,    /* live subxact, ROLLBACK received */
     164             :     TBLOCK_SUBRESTART,          /* live subxact, ROLLBACK TO received */
     165             :     TBLOCK_SUBABORT_RESTART     /* failed subxact, ROLLBACK TO received */
     166             : } TBlockState;
     167             : 
     168             : /*
     169             :  *  transaction state structure
     170             :  */
     171             : typedef struct TransactionStateData
     172             : {
     173             :     FullTransactionId fullTransactionId;    /* my FullTransactionId */
     174             :     SubTransactionId subTransactionId;  /* my subxact ID */
     175             :     char       *name;           /* savepoint name, if any */
     176             :     int         savepointLevel; /* savepoint level */
     177             :     TransState  state;          /* low-level state */
     178             :     TBlockState blockState;     /* high-level state */
     179             :     int         nestingLevel;   /* transaction nesting depth */
     180             :     int         gucNestLevel;   /* GUC context nesting depth */
     181             :     MemoryContext curTransactionContext;    /* my xact-lifetime context */
     182             :     ResourceOwner curTransactionOwner;  /* my query resources */
     183             :     TransactionId *childXids;   /* subcommitted child XIDs, in XID order */
     184             :     int         nChildXids;     /* # of subcommitted child XIDs */
     185             :     int         maxChildXids;   /* allocated size of childXids[] */
     186             :     Oid         prevUser;       /* previous CurrentUserId setting */
     187             :     int         prevSecContext; /* previous SecurityRestrictionContext */
     188             :     bool        prevXactReadOnly;   /* entry-time xact r/o state */
     189             :     bool        startedInRecovery;  /* did we start in recovery? */
     190             :     bool        didLogXid;      /* has xid been included in WAL record? */
     191             :     int         parallelModeLevel;  /* Enter/ExitParallelMode counter */
     192             :     bool        chain;          /* start a new block after this one */
     193             :     struct TransactionStateData *parent;    /* back link to parent */
     194             : } TransactionStateData;
     195             : 
     196             : typedef TransactionStateData *TransactionState;
     197             : 
     198             : /*
     199             :  * Serialized representation used to transmit transaction state to parallel
     200             :  * workers through shared memory.
     201             :  */
     202             : typedef struct SerializedTransactionState
     203             : {
     204             :     int         xactIsoLevel;
     205             :     bool        xactDeferrable;
     206             :     FullTransactionId topFullTransactionId;
     207             :     FullTransactionId currentFullTransactionId;
     208             :     CommandId   currentCommandId;
     209             :     int         nParallelCurrentXids;
     210             :     TransactionId parallelCurrentXids[FLEXIBLE_ARRAY_MEMBER];
     211             : } SerializedTransactionState;
     212             : 
     213             : /* The size of SerializedTransactionState, not including the final array. */
     214             : #define SerializedTransactionStateHeaderSize \
     215             :     offsetof(SerializedTransactionState, parallelCurrentXids)
     216             : 
     217             : /*
     218             :  * CurrentTransactionState always points to the current transaction state
     219             :  * block.  It will point to TopTransactionStateData when not in a
     220             :  * transaction at all, or when in a top-level transaction.
     221             :  */
     222             : static TransactionStateData TopTransactionStateData = {
     223             :     .state = TRANS_DEFAULT,
     224             :     .blockState = TBLOCK_DEFAULT,
     225             : };
     226             : 
     227             : /*
     228             :  * unreportedXids holds XIDs of all subtransactions that have not yet been
     229             :  * reported in an XLOG_XACT_ASSIGNMENT record.
     230             :  */
     231             : static int  nUnreportedXids;
     232             : static TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS];
     233             : 
     234             : static TransactionState CurrentTransactionState = &TopTransactionStateData;
     235             : 
     236             : /*
     237             :  * The subtransaction ID and command ID assignment counters are global
     238             :  * to a whole transaction, so we do not keep them in the state stack.
     239             :  */
     240             : static SubTransactionId currentSubTransactionId;
     241             : static CommandId currentCommandId;
     242             : static bool currentCommandIdUsed;
     243             : 
     244             : /*
     245             :  * xactStartTimestamp is the value of transaction_timestamp().
     246             :  * stmtStartTimestamp is the value of statement_timestamp().
     247             :  * xactStopTimestamp is the time at which we log a commit or abort WAL record.
     248             :  * These do not change as we enter and exit subtransactions, so we don't
     249             :  * keep them inside the TransactionState stack.
     250             :  */
     251             : static TimestampTz xactStartTimestamp;
     252             : static TimestampTz stmtStartTimestamp;
     253             : static TimestampTz xactStopTimestamp;
     254             : 
     255             : /*
     256             :  * GID to be used for preparing the current transaction.  This is also
     257             :  * global to a whole transaction, so we don't keep it in the state stack.
     258             :  */
     259             : static char *prepareGID;
     260             : 
     261             : /*
     262             :  * Some commands want to force synchronous commit.
     263             :  */
     264             : static bool forceSyncCommit = false;
     265             : 
     266             : /* Flag for logging statements in a transaction. */
     267             : bool        xact_is_sampled = false;
     268             : 
     269             : /*
     270             :  * Private context for transaction-abort work --- we reserve space for this
     271             :  * at startup to ensure that AbortTransaction and AbortSubTransaction can work
     272             :  * when we've run out of memory.
     273             :  */
     274             : static MemoryContext TransactionAbortContext = NULL;
     275             : 
     276             : /*
     277             :  * List of add-on start- and end-of-xact callbacks
     278             :  */
     279             : typedef struct XactCallbackItem
     280             : {
     281             :     struct XactCallbackItem *next;
     282             :     XactCallback callback;
     283             :     void       *arg;
     284             : } XactCallbackItem;
     285             : 
     286             : static XactCallbackItem *Xact_callbacks = NULL;
     287             : 
     288             : /*
     289             :  * List of add-on start- and end-of-subxact callbacks
     290             :  */
     291             : typedef struct SubXactCallbackItem
     292             : {
     293             :     struct SubXactCallbackItem *next;
     294             :     SubXactCallback callback;
     295             :     void       *arg;
     296             : } SubXactCallbackItem;
     297             : 
     298             : static SubXactCallbackItem *SubXact_callbacks = NULL;
     299             : 
     300             : 
     301             : /* local function prototypes */
     302             : static void AssignTransactionId(TransactionState s);
     303             : static void AbortTransaction(void);
     304             : static void AtAbort_Memory(void);
     305             : static void AtCleanup_Memory(void);
     306             : static void AtAbort_ResourceOwner(void);
     307             : static void AtCCI_LocalCache(void);
     308             : static void AtCommit_Memory(void);
     309             : static void AtStart_Cache(void);
     310             : static void AtStart_Memory(void);
     311             : static void AtStart_ResourceOwner(void);
     312             : static void CallXactCallbacks(XactEvent event);
     313             : static void CallSubXactCallbacks(SubXactEvent event,
     314             :                                  SubTransactionId mySubid,
     315             :                                  SubTransactionId parentSubid);
     316             : static void CleanupTransaction(void);
     317             : static void CheckTransactionBlock(bool isTopLevel, bool throwError,
     318             :                                   const char *stmtType);
     319             : static void CommitTransaction(void);
     320             : static TransactionId RecordTransactionAbort(bool isSubXact);
     321             : static void StartTransaction(void);
     322             : 
     323             : static void StartSubTransaction(void);
     324             : static void CommitSubTransaction(void);
     325             : static void AbortSubTransaction(void);
     326             : static void CleanupSubTransaction(void);
     327             : static void PushTransaction(void);
     328             : static void PopTransaction(void);
     329             : 
     330             : static void AtSubAbort_Memory(void);
     331             : static void AtSubCleanup_Memory(void);
     332             : static void AtSubAbort_ResourceOwner(void);
     333             : static void AtSubCommit_Memory(void);
     334             : static void AtSubStart_Memory(void);
     335             : static void AtSubStart_ResourceOwner(void);
     336             : 
     337             : static void ShowTransactionState(const char *str);
     338             : static void ShowTransactionStateRec(const char *str, TransactionState state);
     339             : static const char *BlockStateAsString(TBlockState blockState);
     340             : static const char *TransStateAsString(TransState state);
     341             : 
     342             : 
     343             : /* ----------------------------------------------------------------
     344             :  *  transaction state accessors
     345             :  * ----------------------------------------------------------------
     346             :  */
     347             : 
     348             : /*
     349             :  *  IsTransactionState
     350             :  *
     351             :  *  This returns true if we are inside a valid transaction; that is,
     352             :  *  it is safe to initiate database access, take heavyweight locks, etc.
     353             :  */
     354             : bool
     355      777980 : IsTransactionState(void)
     356             : {
     357      777980 :     TransactionState s = CurrentTransactionState;
     358             : 
     359             :     /*
     360             :      * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states.  However, we
     361             :      * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
     362             :      * TRANS_PREPARE since it might be too soon or too late within those
     363             :      * transition states to do anything interesting.  Hence, the only "valid"
     364             :      * state is TRANS_INPROGRESS.
     365             :      */
     366      777980 :     return (s->state == TRANS_INPROGRESS);
     367             : }
     368             : 
     369             : /*
     370             :  *  IsAbortedTransactionBlockState
     371             :  *
     372             :  *  This returns true if we are within an aborted transaction block.
     373             :  */
     374             : bool
     375     1028270 : IsAbortedTransactionBlockState(void)
     376             : {
     377     1028270 :     TransactionState s = CurrentTransactionState;
     378             : 
     379     2054806 :     if (s->blockState == TBLOCK_ABORT ||
     380     1026536 :         s->blockState == TBLOCK_SUBABORT)
     381        2026 :         return true;
     382             : 
     383     1026244 :     return false;
     384             : }
     385             : 
     386             : 
     387             : /*
     388             :  *  GetTopTransactionId
     389             :  *
     390             :  * This will return the XID of the main transaction, assigning one if
     391             :  * it's not yet set.  Be careful to call this only inside a valid xact.
     392             :  */
     393             : TransactionId
     394       33562 : GetTopTransactionId(void)
     395             : {
     396       33562 :     if (!FullTransactionIdIsValid(XactTopFullTransactionId))
     397        4666 :         AssignTransactionId(&TopTransactionStateData);
     398       33562 :     return XidFromFullTransactionId(XactTopFullTransactionId);
     399             : }
     400             : 
     401             : /*
     402             :  *  GetTopTransactionIdIfAny
     403             :  *
     404             :  * This will return the XID of the main transaction, if one is assigned.
     405             :  * It will return InvalidTransactionId if we are not currently inside a
     406             :  * transaction, or inside a transaction that hasn't yet been assigned an XID.
     407             :  */
     408             : TransactionId
     409    32000884 : GetTopTransactionIdIfAny(void)
     410             : {
     411    32000884 :     return XidFromFullTransactionId(XactTopFullTransactionId);
     412             : }
     413             : 
     414             : /*
     415             :  *  GetCurrentTransactionId
     416             :  *
     417             :  * This will return the XID of the current transaction (main or sub
     418             :  * transaction), assigning one if it's not yet set.  Be careful to call this
     419             :  * only inside a valid xact.
     420             :  */
     421             : TransactionId
     422    19747976 : GetCurrentTransactionId(void)
     423             : {
     424    19747976 :     TransactionState s = CurrentTransactionState;
     425             : 
     426    19747976 :     if (!FullTransactionIdIsValid(s->fullTransactionId))
     427      250230 :         AssignTransactionId(s);
     428    19747976 :     return XidFromFullTransactionId(s->fullTransactionId);
     429             : }
     430             : 
     431             : /*
     432             :  *  GetCurrentTransactionIdIfAny
     433             :  *
     434             :  * This will return the XID of the current sub xact, if one is assigned.
     435             :  * It will return InvalidTransactionId if we are not currently inside a
     436             :  * transaction, or inside a transaction that hasn't been assigned an XID yet.
     437             :  */
     438             : TransactionId
     439    29413252 : GetCurrentTransactionIdIfAny(void)
     440             : {
     441    29413252 :     return XidFromFullTransactionId(CurrentTransactionState->fullTransactionId);
     442             : }
     443             : 
     444             : /*
     445             :  *  GetTopFullTransactionId
     446             :  *
     447             :  * This will return the FullTransactionId of the main transaction, assigning
     448             :  * one if it's not yet set.  Be careful to call this only inside a valid xact.
     449             :  */
     450             : FullTransactionId
     451           0 : GetTopFullTransactionId(void)
     452             : {
     453           0 :     if (!FullTransactionIdIsValid(XactTopFullTransactionId))
     454           0 :         AssignTransactionId(&TopTransactionStateData);
     455           0 :     return XactTopFullTransactionId;
     456             : }
     457             : 
     458             : /*
     459             :  *  GetTopFullTransactionIdIfAny
     460             :  *
     461             :  * This will return the FullTransactionId of the main transaction, if one is
     462             :  * assigned.  It will return InvalidFullTransactionId if we are not currently
     463             :  * inside a transaction, or inside a transaction that hasn't yet been assigned
     464             :  * one.
     465             :  */
     466             : FullTransactionId
     467           0 : GetTopFullTransactionIdIfAny(void)
     468             : {
     469           0 :     return XactTopFullTransactionId;
     470             : }
     471             : 
     472             : /*
     473             :  *  GetCurrentFullTransactionId
     474             :  *
     475             :  * This will return the FullTransactionId of the current transaction (main or
     476             :  * sub transaction), assigning one if it's not yet set.  Be careful to call
     477             :  * this only inside a valid xact.
     478             :  */
     479             : FullTransactionId
     480           0 : GetCurrentFullTransactionId(void)
     481             : {
     482           0 :     TransactionState s = CurrentTransactionState;
     483             : 
     484           0 :     if (!FullTransactionIdIsValid(s->fullTransactionId))
     485           0 :         AssignTransactionId(s);
     486           0 :     return s->fullTransactionId;
     487             : }
     488             : 
     489             : /*
     490             :  *  GetCurrentFullTransactionIdIfAny
     491             :  *
     492             :  * This will return the FullTransactionId of the current sub xact, if one is
     493             :  * assigned.  It will return InvalidFullTransactionId if we are not currently
     494             :  * inside a transaction, or inside a transaction that hasn't been assigned one
     495             :  * yet.
     496             :  */
     497             : FullTransactionId
     498           0 : GetCurrentFullTransactionIdIfAny(void)
     499             : {
     500           0 :     return CurrentTransactionState->fullTransactionId;
     501             : }
     502             : 
     503             : /*
     504             :  *  MarkCurrentTransactionIdLoggedIfAny
     505             :  *
     506             :  * Remember that the current xid - if it is assigned - now has been wal logged.
     507             :  */
     508             : void
     509    29390072 : MarkCurrentTransactionIdLoggedIfAny(void)
     510             : {
     511    29390072 :     if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
     512    28798698 :         CurrentTransactionState->didLogXid = true;
     513    29390072 : }
     514             : 
     515             : 
     516             : /*
     517             :  *  GetStableLatestTransactionId
     518             :  *
     519             :  * Get the transaction's XID if it has one, else read the next-to-be-assigned
     520             :  * XID.  Once we have a value, return that same value for the remainder of the
     521             :  * current transaction.  This is meant to provide the reference point for the
     522             :  * age(xid) function, but might be useful for other maintenance tasks as well.
     523             :  */
     524             : TransactionId
     525         220 : GetStableLatestTransactionId(void)
     526             : {
     527             :     static LocalTransactionId lxid = InvalidLocalTransactionId;
     528             :     static TransactionId stablexid = InvalidTransactionId;
     529             : 
     530         220 :     if (lxid != MyProc->lxid)
     531             :     {
     532           2 :         lxid = MyProc->lxid;
     533           2 :         stablexid = GetTopTransactionIdIfAny();
     534           2 :         if (!TransactionIdIsValid(stablexid))
     535           2 :             stablexid = ReadNewTransactionId();
     536             :     }
     537             : 
     538             :     Assert(TransactionIdIsValid(stablexid));
     539             : 
     540         220 :     return stablexid;
     541             : }
     542             : 
     543             : /*
     544             :  * AssignTransactionId
     545             :  *
     546             :  * Assigns a new permanent FullTransactionId to the given TransactionState.
     547             :  * We do not assign XIDs to transactions until/unless this is called.
     548             :  * Also, any parent TransactionStates that don't yet have XIDs are assigned
     549             :  * one; this maintains the invariant that a child transaction has an XID
     550             :  * following its parent's.
     551             :  */
     552             : static void
     553      255564 : AssignTransactionId(TransactionState s)
     554             : {
     555      255564 :     bool        isSubXact = (s->parent != NULL);
     556             :     ResourceOwner currentOwner;
     557      255564 :     bool        log_unknown_top = false;
     558             : 
     559             :     /* Assert that caller didn't screw up */
     560             :     Assert(!FullTransactionIdIsValid(s->fullTransactionId));
     561             :     Assert(s->state == TRANS_INPROGRESS);
     562             : 
     563             :     /*
     564             :      * Workers synchronize transaction state at the beginning of each parallel
     565             :      * operation, so we can't account for new XIDs at this point.
     566             :      */
     567      255564 :     if (IsInParallelMode() || IsParallelWorker())
     568           0 :         elog(ERROR, "cannot assign XIDs during a parallel operation");
     569             : 
     570             :     /*
     571             :      * Ensure parent(s) have XIDs, so that a child always has an XID later
     572             :      * than its parent.  Mustn't recurse here, or we might get a stack
     573             :      * overflow if we're at the bottom of a huge stack of subtransactions none
     574             :      * of which have XIDs yet.
     575             :      */
     576      255564 :     if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId))
     577             :     {
     578         420 :         TransactionState p = s->parent;
     579             :         TransactionState *parents;
     580         420 :         size_t      parentOffset = 0;
     581             : 
     582         420 :         parents = palloc(sizeof(TransactionState) * s->nestingLevel);
     583        1508 :         while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
     584             :         {
     585         668 :             parents[parentOffset++] = p;
     586         668 :             p = p->parent;
     587             :         }
     588             : 
     589             :         /*
     590             :          * This is technically a recursive call, but the recursion will never
     591             :          * be more than one layer deep.
     592             :          */
     593        1508 :         while (parentOffset != 0)
     594         668 :             AssignTransactionId(parents[--parentOffset]);
     595             : 
     596         420 :         pfree(parents);
     597             :     }
     598             : 
     599             :     /*
     600             :      * When wal_level=logical, guarantee that a subtransaction's xid can only
     601             :      * be seen in the WAL stream if its toplevel xid has been logged before.
     602             :      * If necessary we log an xact_assignment record with fewer than
     603             :      * PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't set
     604             :      * for a transaction even though it appears in a WAL record, we just might
     605             :      * superfluously log something. That can happen when an xid is included
     606             :      * somewhere inside a wal record, but not in XLogRecord->xl_xid, like in
     607             :      * xl_standby_locks.
     608             :      */
     609      255798 :     if (isSubXact && XLogLogicalInfoActive() &&
     610         234 :         !TopTransactionStateData.didLogXid)
     611          34 :         log_unknown_top = true;
     612             : 
     613             :     /*
     614             :      * Generate a new FullTransactionId and record its xid in PG_PROC and
     615             :      * pg_subtrans.
     616             :      *
     617             :      * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
     618             :      * shared storage other than PG_PROC; because if there's no room for it in
     619             :      * PG_PROC, the subtrans entry is needed to ensure that other backends see
     620             :      * the Xid as "running".  See GetNewTransactionId.
     621             :      */
     622      255564 :     s->fullTransactionId = GetNewTransactionId(isSubXact);
     623      255564 :     if (!isSubXact)
     624      251540 :         XactTopFullTransactionId = s->fullTransactionId;
     625             : 
     626      255564 :     if (isSubXact)
     627        4024 :         SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),
     628        4024 :                           XidFromFullTransactionId(s->parent->fullTransactionId));
     629             : 
     630             :     /*
     631             :      * If it's a top-level transaction, the predicate locking system needs to
     632             :      * be told about it too.
     633             :      */
     634      255564 :     if (!isSubXact)
     635      251540 :         RegisterPredicateLockingXid(XidFromFullTransactionId(s->fullTransactionId));
     636             : 
     637             :     /*
     638             :      * Acquire lock on the transaction XID.  (We assume this cannot block.) We
     639             :      * have to ensure that the lock is assigned to the transaction's own
     640             :      * ResourceOwner.
     641             :      */
     642      255564 :     currentOwner = CurrentResourceOwner;
     643      255564 :     CurrentResourceOwner = s->curTransactionOwner;
     644             : 
     645      255564 :     XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));
     646             : 
     647      255564 :     CurrentResourceOwner = currentOwner;
     648             : 
     649             :     /*
     650             :      * Every PGPROC_MAX_CACHED_SUBXIDS assigned transaction ids within each
     651             :      * top-level transaction we issue a WAL record for the assignment. We
     652             :      * include the top-level xid and all the subxids that have not yet been
     653             :      * reported using XLOG_XACT_ASSIGNMENT records.
     654             :      *
     655             :      * This is required to limit the amount of shared memory required in a hot
     656             :      * standby server to keep track of in-progress XIDs. See notes for
     657             :      * RecordKnownAssignedTransactionIds().
     658             :      *
     659             :      * We don't keep track of the immediate parent of each subxid, only the
     660             :      * top-level transaction that each subxact belongs to. This is correct in
     661             :      * recovery only because aborted subtransactions are separately WAL
     662             :      * logged.
     663             :      *
     664             :      * This is correct even for the case where several levels above us didn't
     665             :      * have an xid assigned as we recursed up to them beforehand.
     666             :      */
     667      255564 :     if (isSubXact && XLogStandbyInfoActive())
     668             :     {
     669        4024 :         unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);
     670        4024 :         nUnreportedXids++;
     671             : 
     672             :         /*
     673             :          * ensure this test matches similar one in
     674             :          * RecoverPreparedTransactions()
     675             :          */
     676        4024 :         if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS ||
     677             :             log_unknown_top)
     678             :         {
     679             :             xl_xact_assignment xlrec;
     680             : 
     681             :             /*
     682             :              * xtop is always set by now because we recurse up transaction
     683             :              * stack to the highest unassigned xid and then come back down
     684             :              */
     685          76 :             xlrec.xtop = GetTopTransactionId();
     686             :             Assert(TransactionIdIsValid(xlrec.xtop));
     687          76 :             xlrec.nsubxacts = nUnreportedXids;
     688             : 
     689          76 :             XLogBeginInsert();
     690          76 :             XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment);
     691          76 :             XLogRegisterData((char *) unreportedXids,
     692          76 :                              nUnreportedXids * sizeof(TransactionId));
     693             : 
     694          76 :             (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
     695             : 
     696          76 :             nUnreportedXids = 0;
     697             :             /* mark top, not current xact as having been logged */
     698          76 :             TopTransactionStateData.didLogXid = true;
     699             :         }
     700             :     }
     701      255564 : }
     702             : 
     703             : /*
     704             :  *  GetCurrentSubTransactionId
     705             :  */
     706             : SubTransactionId
     707     2277440 : GetCurrentSubTransactionId(void)
     708             : {
     709     2277440 :     TransactionState s = CurrentTransactionState;
     710             : 
     711     2277440 :     return s->subTransactionId;
     712             : }
     713             : 
     714             : /*
     715             :  *  SubTransactionIsActive
     716             :  *
     717             :  * Test if the specified subxact ID is still active.  Note caller is
     718             :  * responsible for checking whether this ID is relevant to the current xact.
     719             :  */
     720             : bool
     721       49030 : SubTransactionIsActive(SubTransactionId subxid)
     722             : {
     723             :     TransactionState s;
     724             : 
     725       49038 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
     726             :     {
     727       49038 :         if (s->state == TRANS_ABORT)
     728           0 :             continue;
     729       49038 :         if (s->subTransactionId == subxid)
     730       49030 :             return true;
     731             :     }
     732           0 :     return false;
     733             : }
     734             : 
     735             : 
     736             : /*
     737             :  *  GetCurrentCommandId
     738             :  *
     739             :  * "used" must be true if the caller intends to use the command ID to mark
     740             :  * inserted/updated/deleted tuples.  false means the ID is being fetched
     741             :  * for read-only purposes (ie, as a snapshot validity cutoff).  See
     742             :  * CommandCounterIncrement() for discussion.
     743             :  */
     744             : CommandId
     745     9289002 : GetCurrentCommandId(bool used)
     746             : {
     747             :     /* this is global to a transaction, not subtransaction-local */
     748     9289002 :     if (used)
     749             :     {
     750             :         /*
     751             :          * Forbid setting currentCommandIdUsed in a parallel worker, because
     752             :          * we have no provision for communicating this back to the master.  We
     753             :          * could relax this restriction when currentCommandIdUsed was already
     754             :          * true at the start of the parallel operation.
     755             :          */
     756             :         Assert(!IsParallelWorker());
     757     7329690 :         currentCommandIdUsed = true;
     758             :     }
     759     9289002 :     return currentCommandId;
     760             : }
     761             : 
     762             : /*
     763             :  *  SetParallelStartTimestamps
     764             :  *
     765             :  * In a parallel worker, we should inherit the parent transaction's
     766             :  * timestamps rather than setting our own.  The parallel worker
     767             :  * infrastructure must call this to provide those values before
     768             :  * calling StartTransaction() or SetCurrentStatementStartTimestamp().
     769             :  */
     770             : void
     771        1520 : SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
     772             : {
     773             :     Assert(IsParallelWorker());
     774        1520 :     xactStartTimestamp = xact_ts;
     775        1520 :     stmtStartTimestamp = stmt_ts;
     776        1520 : }
     777             : 
     778             : /*
     779             :  *  GetCurrentTransactionStartTimestamp
     780             :  */
     781             : TimestampTz
     782        5798 : GetCurrentTransactionStartTimestamp(void)
     783             : {
     784        5798 :     return xactStartTimestamp;
     785             : }
     786             : 
     787             : /*
     788             :  *  GetCurrentStatementStartTimestamp
     789             :  */
     790             : TimestampTz
     791     1458470 : GetCurrentStatementStartTimestamp(void)
     792             : {
     793     1458470 :     return stmtStartTimestamp;
     794             : }
     795             : 
     796             : /*
     797             :  *  GetCurrentTransactionStopTimestamp
     798             :  *
     799             :  * We return current time if the transaction stop time hasn't been set
     800             :  * (which can happen if we decide we don't need to log an XLOG record).
     801             :  */
     802             : TimestampTz
     803      380444 : GetCurrentTransactionStopTimestamp(void)
     804             : {
     805      380444 :     if (xactStopTimestamp != 0)
     806      232590 :         return xactStopTimestamp;
     807      147854 :     return GetCurrentTimestamp();
     808             : }
     809             : 
     810             : /*
     811             :  *  SetCurrentStatementStartTimestamp
     812             :  *
     813             :  * In a parallel worker, this should already have been provided by a call
     814             :  * to SetParallelStartTimestamps().
     815             :  */
     816             : void
     817      521092 : SetCurrentStatementStartTimestamp(void)
     818             : {
     819      521092 :     if (!IsParallelWorker())
     820      519572 :         stmtStartTimestamp = GetCurrentTimestamp();
     821             :     else
     822             :         Assert(stmtStartTimestamp != 0);
     823      521092 : }
     824             : 
     825             : /*
     826             :  *  SetCurrentTransactionStopTimestamp
     827             :  */
     828             : static inline void
     829      251480 : SetCurrentTransactionStopTimestamp(void)
     830             : {
     831      251480 :     xactStopTimestamp = GetCurrentTimestamp();
     832      251480 : }
     833             : 
     834             : /*
     835             :  *  GetCurrentTransactionNestLevel
     836             :  *
     837             :  * Note: this will return zero when not inside any transaction, one when
     838             :  * inside a top-level transaction, etc.
     839             :  */
     840             : int
     841    23554218 : GetCurrentTransactionNestLevel(void)
     842             : {
     843    23554218 :     TransactionState s = CurrentTransactionState;
     844             : 
     845    23554218 :     return s->nestingLevel;
     846             : }
     847             : 
     848             : 
     849             : /*
     850             :  *  TransactionIdIsCurrentTransactionId
     851             :  */
     852             : bool
     853    33943194 : TransactionIdIsCurrentTransactionId(TransactionId xid)
     854             : {
     855             :     TransactionState s;
     856             : 
     857             :     /*
     858             :      * We always say that BootstrapTransactionId is "not my transaction ID"
     859             :      * even when it is (ie, during bootstrap).  Along with the fact that
     860             :      * transam.c always treats BootstrapTransactionId as already committed,
     861             :      * this causes the heapam_visibility.c routines to see all tuples as
     862             :      * committed, which is what we need during bootstrap.  (Bootstrap mode
     863             :      * only inserts tuples, it never updates or deletes them, so all tuples
     864             :      * can be presumed good immediately.)
     865             :      *
     866             :      * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
     867             :      * not my transaction ID, so we can just return "false" immediately for
     868             :      * any non-normal XID.
     869             :      */
     870    33943194 :     if (!TransactionIdIsNormal(xid))
     871     2535156 :         return false;
     872             : 
     873    31408038 :     if (TransactionIdEquals(xid, GetTopTransactionIdIfAny()))
     874    15387990 :         return true;
     875             : 
     876             :     /*
     877             :      * In parallel workers, the XIDs we must consider as current are stored in
     878             :      * ParallelCurrentXids rather than the transaction-state stack.  Note that
     879             :      * the XIDs in this array are sorted numerically rather than according to
     880             :      * transactionIdPrecedes order.
     881             :      */
     882    16020048 :     if (nParallelCurrentXids > 0)
     883             :     {
     884             :         int         low,
     885             :                     high;
     886             : 
     887     2403922 :         low = 0;
     888     2403922 :         high = nParallelCurrentXids - 1;
     889    12019418 :         while (low <= high)
     890             :         {
     891             :             int         middle;
     892             :             TransactionId probe;
     893             : 
     894     9615478 :             middle = low + (high - low) / 2;
     895     9615478 :             probe = ParallelCurrentXids[middle];
     896     9615478 :             if (probe == xid)
     897     2403904 :                 return true;
     898     7211574 :             else if (probe < xid)
     899     7211556 :                 low = middle + 1;
     900             :             else
     901          18 :                 high = middle - 1;
     902             :         }
     903          18 :         return false;
     904             :     }
     905             : 
     906             :     /*
     907             :      * We will return true for the Xid of the current subtransaction, any of
     908             :      * its subcommitted children, any of its parents, or any of their
     909             :      * previously subcommitted children.  However, a transaction being aborted
     910             :      * is no longer "current", even though it may still have an entry on the
     911             :      * state stack.
     912             :      */
     913    27228710 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
     914             :     {
     915             :         int         low,
     916             :                     high;
     917             : 
     918    13621242 :         if (s->state == TRANS_ABORT)
     919           0 :             continue;
     920    13621242 :         if (!FullTransactionIdIsValid(s->fullTransactionId))
     921     8330914 :             continue;           /* it can't have any child XIDs either */
     922     5290328 :         if (TransactionIdEquals(xid, XidFromFullTransactionId(s->fullTransactionId)))
     923        5780 :             return true;
     924             :         /* As the childXids array is ordered, we can use binary search */
     925     5284548 :         low = 0;
     926     5284548 :         high = s->nChildXids - 1;
     927    10570754 :         while (low <= high)
     928             :         {
     929             :             int         middle;
     930             :             TransactionId probe;
     931             : 
     932        4536 :             middle = low + (high - low) / 2;
     933        4536 :             probe = s->childXids[middle];
     934        4536 :             if (TransactionIdEquals(probe, xid))
     935        2878 :                 return true;
     936        1658 :             else if (TransactionIdPrecedes(probe, xid))
     937        1600 :                 low = middle + 1;
     938             :             else
     939          58 :                 high = middle - 1;
     940             :         }
     941             :     }
     942             : 
     943    13607468 :     return false;
     944             : }
     945             : 
     946             : /*
     947             :  *  TransactionStartedDuringRecovery
     948             :  *
     949             :  * Returns true if the current transaction started while recovery was still
     950             :  * in progress. Recovery might have ended since so RecoveryInProgress() might
     951             :  * return false already.
     952             :  */
     953             : bool
     954     9980728 : TransactionStartedDuringRecovery(void)
     955             : {
     956     9980728 :     return CurrentTransactionState->startedInRecovery;
     957             : }
     958             : 
     959             : /*
     960             :  *  EnterParallelMode
     961             :  */
     962             : void
     963        3470 : EnterParallelMode(void)
     964             : {
     965        3470 :     TransactionState s = CurrentTransactionState;
     966             : 
     967             :     Assert(s->parallelModeLevel >= 0);
     968             : 
     969        3470 :     ++s->parallelModeLevel;
     970        3470 : }
     971             : 
     972             : /*
     973             :  *  ExitParallelMode
     974             :  */
     975             : void
     976        1946 : ExitParallelMode(void)
     977             : {
     978        1946 :     TransactionState s = CurrentTransactionState;
     979             : 
     980             :     Assert(s->parallelModeLevel > 0);
     981             :     Assert(s->parallelModeLevel > 1 || !ParallelContextActive());
     982             : 
     983        1946 :     --s->parallelModeLevel;
     984        1946 : }
     985             : 
     986             : /*
     987             :  *  IsInParallelMode
     988             :  *
     989             :  * Are we in a parallel operation, as either the master or a worker?  Check
     990             :  * this to prohibit operations that change backend-local state expected to
     991             :  * match across all workers.  Mere caches usually don't require such a
     992             :  * restriction.  State modified in a strict push/pop fashion, such as the
     993             :  * active snapshot stack, is often fine.
     994             :  */
     995             : bool
     996     5164056 : IsInParallelMode(void)
     997             : {
     998     5164056 :     return CurrentTransactionState->parallelModeLevel != 0;
     999             : }
    1000             : 
    1001             : /*
    1002             :  *  CommandCounterIncrement
    1003             :  */
    1004             : void
    1005     1350166 : CommandCounterIncrement(void)
    1006             : {
    1007             :     /*
    1008             :      * If the current value of the command counter hasn't been "used" to mark
    1009             :      * tuples, we need not increment it, since there's no need to distinguish
    1010             :      * a read-only command from others.  This helps postpone command counter
    1011             :      * overflow, and keeps no-op CommandCounterIncrement operations cheap.
    1012             :      */
    1013     1350166 :     if (currentCommandIdUsed)
    1014             :     {
    1015             :         /*
    1016             :          * Workers synchronize transaction state at the beginning of each
    1017             :          * parallel operation, so we can't account for new commands after that
    1018             :          * point.
    1019             :          */
    1020      588934 :         if (IsInParallelMode() || IsParallelWorker())
    1021           0 :             elog(ERROR, "cannot start commands during a parallel operation");
    1022             : 
    1023      588934 :         currentCommandId += 1;
    1024      588934 :         if (currentCommandId == InvalidCommandId)
    1025             :         {
    1026           0 :             currentCommandId -= 1;
    1027           0 :             ereport(ERROR,
    1028             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1029             :                      errmsg("cannot have more than 2^32-2 commands in a transaction")));
    1030             :         }
    1031      588934 :         currentCommandIdUsed = false;
    1032             : 
    1033             :         /* Propagate new command ID into static snapshots */
    1034      588934 :         SnapshotSetCommandId(currentCommandId);
    1035             : 
    1036             :         /*
    1037             :          * Make any catalog changes done by the just-completed command visible
    1038             :          * in the local syscache.  We obviously don't need to do this after a
    1039             :          * read-only command.  (But see hacks in inval.c to make real sure we
    1040             :          * don't think a command that queued inval messages was read-only.)
    1041             :          */
    1042      588934 :         AtCCI_LocalCache();
    1043             :     }
    1044     1350166 : }
    1045             : 
    1046             : /*
    1047             :  * ForceSyncCommit
    1048             :  *
    1049             :  * Interface routine to allow commands to force a synchronous commit of the
    1050             :  * current top-level transaction
    1051             :  */
    1052             : void
    1053         934 : ForceSyncCommit(void)
    1054             : {
    1055         934 :     forceSyncCommit = true;
    1056         934 : }
    1057             : 
    1058             : 
    1059             : /* ----------------------------------------------------------------
    1060             :  *                      StartTransaction stuff
    1061             :  * ----------------------------------------------------------------
    1062             :  */
    1063             : 
    1064             : /*
    1065             :  *  AtStart_Cache
    1066             :  */
    1067             : static void
    1068      458256 : AtStart_Cache(void)
    1069             : {
    1070      458256 :     AcceptInvalidationMessages();
    1071      458256 : }
    1072             : 
    1073             : /*
    1074             :  *  AtStart_Memory
    1075             :  */
    1076             : static void
    1077      458256 : AtStart_Memory(void)
    1078             : {
    1079      458256 :     TransactionState s = CurrentTransactionState;
    1080             : 
    1081             :     /*
    1082             :      * If this is the first time through, create a private context for
    1083             :      * AbortTransaction to work in.  By reserving some space now, we can
    1084             :      * insulate AbortTransaction from out-of-memory scenarios.  Like
    1085             :      * ErrorContext, we set it up with slow growth rate and a nonzero minimum
    1086             :      * size, so that space will be reserved immediately.
    1087             :      */
    1088      458256 :     if (TransactionAbortContext == NULL)
    1089        9844 :         TransactionAbortContext =
    1090        9844 :             AllocSetContextCreate(TopMemoryContext,
    1091             :                                   "TransactionAbortContext",
    1092             :                                   32 * 1024,
    1093             :                                   32 * 1024,
    1094             :                                   32 * 1024);
    1095             : 
    1096             :     /*
    1097             :      * We shouldn't have a transaction context already.
    1098             :      */
    1099             :     Assert(TopTransactionContext == NULL);
    1100             : 
    1101             :     /*
    1102             :      * Create a toplevel context for the transaction.
    1103             :      */
    1104      458256 :     TopTransactionContext =
    1105      458256 :         AllocSetContextCreate(TopMemoryContext,
    1106             :                               "TopTransactionContext",
    1107             :                               ALLOCSET_DEFAULT_SIZES);
    1108             : 
    1109             :     /*
    1110             :      * In a top-level transaction, CurTransactionContext is the same as
    1111             :      * TopTransactionContext.
    1112             :      */
    1113      458256 :     CurTransactionContext = TopTransactionContext;
    1114      458256 :     s->curTransactionContext = CurTransactionContext;
    1115             : 
    1116             :     /* Make the CurTransactionContext active. */
    1117      458256 :     MemoryContextSwitchTo(CurTransactionContext);
    1118      458256 : }
    1119             : 
    1120             : /*
    1121             :  *  AtStart_ResourceOwner
    1122             :  */
    1123             : static void
    1124      458256 : AtStart_ResourceOwner(void)
    1125             : {
    1126      458256 :     TransactionState s = CurrentTransactionState;
    1127             : 
    1128             :     /*
    1129             :      * We shouldn't have a transaction resource owner already.
    1130             :      */
    1131             :     Assert(TopTransactionResourceOwner == NULL);
    1132             : 
    1133             :     /*
    1134             :      * Create a toplevel resource owner for the transaction.
    1135             :      */
    1136      458256 :     s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
    1137             : 
    1138      458256 :     TopTransactionResourceOwner = s->curTransactionOwner;
    1139      458256 :     CurTransactionResourceOwner = s->curTransactionOwner;
    1140      458256 :     CurrentResourceOwner = s->curTransactionOwner;
    1141      458256 : }
    1142             : 
    1143             : /* ----------------------------------------------------------------
    1144             :  *                      StartSubTransaction stuff
    1145             :  * ----------------------------------------------------------------
    1146             :  */
    1147             : 
    1148             : /*
    1149             :  * AtSubStart_Memory
    1150             :  */
    1151             : static void
    1152        7360 : AtSubStart_Memory(void)
    1153             : {
    1154        7360 :     TransactionState s = CurrentTransactionState;
    1155             : 
    1156             :     Assert(CurTransactionContext != NULL);
    1157             : 
    1158             :     /*
    1159             :      * Create a CurTransactionContext, which will be used to hold data that
    1160             :      * survives subtransaction commit but disappears on subtransaction abort.
    1161             :      * We make it a child of the immediate parent's CurTransactionContext.
    1162             :      */
    1163        7360 :     CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
    1164             :                                                   "CurTransactionContext",
    1165             :                                                   ALLOCSET_DEFAULT_SIZES);
    1166        7360 :     s->curTransactionContext = CurTransactionContext;
    1167             : 
    1168             :     /* Make the CurTransactionContext active. */
    1169        7360 :     MemoryContextSwitchTo(CurTransactionContext);
    1170        7360 : }
    1171             : 
    1172             : /*
    1173             :  * AtSubStart_ResourceOwner
    1174             :  */
    1175             : static void
    1176        7360 : AtSubStart_ResourceOwner(void)
    1177             : {
    1178        7360 :     TransactionState s = CurrentTransactionState;
    1179             : 
    1180             :     Assert(s->parent != NULL);
    1181             : 
    1182             :     /*
    1183             :      * Create a resource owner for the subtransaction.  We make it a child of
    1184             :      * the immediate parent's resource owner.
    1185             :      */
    1186        7360 :     s->curTransactionOwner =
    1187        7360 :         ResourceOwnerCreate(s->parent->curTransactionOwner,
    1188             :                             "SubTransaction");
    1189             : 
    1190        7360 :     CurTransactionResourceOwner = s->curTransactionOwner;
    1191        7360 :     CurrentResourceOwner = s->curTransactionOwner;
    1192        7360 : }
    1193             : 
    1194             : /* ----------------------------------------------------------------
    1195             :  *                      CommitTransaction stuff
    1196             :  * ----------------------------------------------------------------
    1197             :  */
    1198             : 
    1199             : /*
    1200             :  *  RecordTransactionCommit
    1201             :  *
    1202             :  * Returns latest XID among xact and its children, or InvalidTransactionId
    1203             :  * if the xact has no XID.  (We compute that here just because it's easier.)
    1204             :  *
    1205             :  * If you change this function, see RecordTransactionCommitPrepared also.
    1206             :  */
    1207             : static TransactionId
    1208      437332 : RecordTransactionCommit(void)
    1209             : {
    1210      437332 :     TransactionId xid = GetTopTransactionIdIfAny();
    1211      437332 :     bool        markXidCommitted = TransactionIdIsValid(xid);
    1212      437332 :     TransactionId latestXid = InvalidTransactionId;
    1213             :     int         nrels;
    1214             :     RelFileNode *rels;
    1215             :     int         nchildren;
    1216             :     TransactionId *children;
    1217      437332 :     int         nmsgs = 0;
    1218      437332 :     SharedInvalidationMessage *invalMessages = NULL;
    1219      437332 :     bool        RelcacheInitFileInval = false;
    1220             :     bool        wrote_xlog;
    1221             : 
    1222             :     /* Get data needed for commit record */
    1223      437332 :     nrels = smgrGetPendingDeletes(true, &rels);
    1224      437332 :     nchildren = xactGetCommittedChildren(&children);
    1225      437332 :     if (XLogStandbyInfoActive())
    1226      418610 :         nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
    1227             :                                                      &RelcacheInitFileInval);
    1228      437332 :     wrote_xlog = (XactLastRecEnd != 0);
    1229             : 
    1230             :     /*
    1231             :      * If we haven't been assigned an XID yet, we neither can, nor do we want
    1232             :      * to write a COMMIT record.
    1233             :      */
    1234      437332 :     if (!markXidCommitted)
    1235             :     {
    1236             :         /*
    1237             :          * We expect that every RelationDropStorage is followed by a catalog
    1238             :          * update, and hence XID assignment, so we shouldn't get here with any
    1239             :          * pending deletes.  Use a real test not just an Assert to check this,
    1240             :          * since it's a bit fragile.
    1241             :          */
    1242      191030 :         if (nrels != 0)
    1243           0 :             elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
    1244             : 
    1245             :         /* Can't have child XIDs either; AssignTransactionId enforces this */
    1246             :         Assert(nchildren == 0);
    1247             : 
    1248             :         /*
    1249             :          * Transactions without an assigned xid can contain invalidation
    1250             :          * messages (e.g. explicit relcache invalidations or catcache
    1251             :          * invalidations for inplace updates); standbys need to process those.
    1252             :          * We can't emit a commit record without an xid, and we don't want to
    1253             :          * force assigning an xid, because that'd be problematic for e.g.
    1254             :          * vacuum.  Hence we emit a bespoke record for the invalidations. We
    1255             :          * don't want to use that in case a commit record is emitted, so they
    1256             :          * happen synchronously with commits (besides not wanting to emit more
    1257             :          * WAL records).
    1258             :          */
    1259      191030 :         if (nmsgs != 0)
    1260             :         {
    1261       36774 :             LogStandbyInvalidations(nmsgs, invalMessages,
    1262             :                                     RelcacheInitFileInval);
    1263       36774 :             wrote_xlog = true;  /* not strictly necessary */
    1264             :         }
    1265             : 
    1266             :         /*
    1267             :          * If we didn't create XLOG entries, we're done here; otherwise we
    1268             :          * should trigger flushing those entries the same as a commit record
    1269             :          * would.  This will primarily happen for HOT pruning and the like; we
    1270             :          * want these to be flushed to disk in due time.
    1271             :          */
    1272      191030 :         if (!wrote_xlog)
    1273      150202 :             goto cleanup;
    1274             :     }
    1275             :     else
    1276             :     {
    1277             :         bool        replorigin;
    1278             : 
    1279             :         /*
    1280             :          * Are we using the replication origins feature?  Or, in other words,
    1281             :          * are we replaying remote actions?
    1282             :          */
    1283      246580 :         replorigin = (replorigin_session_origin != InvalidRepOriginId &&
    1284         278 :                       replorigin_session_origin != DoNotReplicateId);
    1285             : 
    1286             :         /*
    1287             :          * Begin commit critical section and insert the commit XLOG record.
    1288             :          */
    1289             :         /* Tell bufmgr and smgr to prepare for commit */
    1290      246302 :         BufmgrCommit();
    1291             : 
    1292             :         /*
    1293             :          * Mark ourselves as within our "commit critical section".  This
    1294             :          * forces any concurrent checkpoint to wait until we've updated
    1295             :          * pg_xact.  Without this, it is possible for the checkpoint to set
    1296             :          * REDO after the XLOG record but fail to flush the pg_xact update to
    1297             :          * disk, leading to loss of the transaction commit if the system
    1298             :          * crashes a little later.
    1299             :          *
    1300             :          * Note: we could, but don't bother to, set this flag in
    1301             :          * RecordTransactionAbort.  That's because loss of a transaction abort
    1302             :          * is noncritical; the presumption would be that it aborted, anyway.
    1303             :          *
    1304             :          * It's safe to change the delayChkpt flag of our own backend without
    1305             :          * holding the ProcArrayLock, since we're the only one modifying it.
    1306             :          * This makes checkpoint's determination of which xacts are delayChkpt
    1307             :          * a bit fuzzy, but it doesn't matter.
    1308             :          */
    1309      246302 :         START_CRIT_SECTION();
    1310      246302 :         MyPgXact->delayChkpt = true;
    1311             : 
    1312      246302 :         SetCurrentTransactionStopTimestamp();
    1313             : 
    1314      246302 :         XactLogCommitRecord(xactStopTimestamp,
    1315             :                             nchildren, children, nrels, rels,
    1316             :                             nmsgs, invalMessages,
    1317             :                             RelcacheInitFileInval, forceSyncCommit,
    1318             :                             MyXactFlags,
    1319             :                             InvalidTransactionId, NULL /* plain commit */ );
    1320             : 
    1321      246302 :         if (replorigin)
    1322             :             /* Move LSNs forward for this replication origin */
    1323         278 :             replorigin_session_advance(replorigin_session_origin_lsn,
    1324             :                                        XactLastRecEnd);
    1325             : 
    1326             :         /*
    1327             :          * Record commit timestamp.  The value comes from plain commit
    1328             :          * timestamp if there's no replication origin; otherwise, the
    1329             :          * timestamp was already set in replorigin_session_origin_timestamp by
    1330             :          * replication.
    1331             :          *
    1332             :          * We don't need to WAL-log anything here, as the commit record
    1333             :          * written above already contains the data.
    1334             :          */
    1335             : 
    1336      246302 :         if (!replorigin || replorigin_session_origin_timestamp == 0)
    1337      246052 :             replorigin_session_origin_timestamp = xactStopTimestamp;
    1338             : 
    1339      246302 :         TransactionTreeSetCommitTsData(xid, nchildren, children,
    1340             :                                        replorigin_session_origin_timestamp,
    1341             :                                        replorigin_session_origin, false);
    1342             :     }
    1343             : 
    1344             :     /*
    1345             :      * Check if we want to commit asynchronously.  We can allow the XLOG flush
    1346             :      * to happen asynchronously if synchronous_commit=off, or if the current
    1347             :      * transaction has not performed any WAL-logged operation or didn't assign
    1348             :      * an xid.  The transaction can end up not writing any WAL, even if it has
    1349             :      * an xid, if it only wrote to temporary and/or unlogged tables.  It can
    1350             :      * end up having written WAL without an xid if it did HOT pruning.  In
    1351             :      * case of a crash, the loss of such a transaction will be irrelevant;
    1352             :      * temp tables will be lost anyway, unlogged tables will be truncated and
    1353             :      * HOT pruning will be done again later. (Given the foregoing, you might
    1354             :      * think that it would be unnecessary to emit the XLOG record at all in
    1355             :      * this case, but we don't currently try to do that.  It would certainly
    1356             :      * cause problems at least in Hot Standby mode, where the
    1357             :      * KnownAssignedXids machinery requires tracking every XID assignment.  It
    1358             :      * might be OK to skip it only when wal_level < replica, but for now we
    1359             :      * don't.)
    1360             :      *
    1361             :      * However, if we're doing cleanup of any non-temp rels or committing any
    1362             :      * command that wanted to force sync commit, then we must flush XLOG
    1363             :      * immediately.  (We must not allow asynchronous commit if there are any
    1364             :      * non-temp tables to be deleted, because we might delete the files before
    1365             :      * the COMMIT record is flushed to disk.  We do allow asynchronous commit
    1366             :      * if all to-be-deleted tables are temporary though, since they are lost
    1367             :      * anyway if we crash.)
    1368             :      */
    1369      526756 :     if ((wrote_xlog && markXidCommitted &&
    1370      291842 :          synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
    1371       52200 :         forceSyncCommit || nrels > 0)
    1372             :     {
    1373      234940 :         XLogFlush(XactLastRecEnd);
    1374             : 
    1375             :         /*
    1376             :          * Now we may update the CLOG, if we wrote a COMMIT record above
    1377             :          */
    1378      469880 :         if (markXidCommitted)
    1379      234940 :             TransactionIdCommitTree(xid, nchildren, children);
    1380             :     }
    1381             :     else
    1382             :     {
    1383             :         /*
    1384             :          * Asynchronous commit case:
    1385             :          *
    1386             :          * This enables possible committed transaction loss in the case of a
    1387             :          * postmaster crash because WAL buffers are left unwritten. Ideally we
    1388             :          * could issue the WAL write without the fsync, but some
    1389             :          * wal_sync_methods do not allow separate write/fsync.
    1390             :          *
    1391             :          * Report the latest async commit LSN, so that the WAL writer knows to
    1392             :          * flush this commit.
    1393             :          */
    1394       52190 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    1395             : 
    1396             :         /*
    1397             :          * We must not immediately update the CLOG, since we didn't flush the
    1398             :          * XLOG. Instead, we store the LSN up to which the XLOG must be
    1399             :          * flushed before the CLOG may be updated.
    1400             :          */
    1401       52190 :         if (markXidCommitted)
    1402       11362 :             TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
    1403             :     }
    1404             : 
    1405             :     /*
    1406             :      * If we entered a commit critical section, leave it now, and let
    1407             :      * checkpoints proceed.
    1408             :      */
    1409      287130 :     if (markXidCommitted)
    1410             :     {
    1411      246302 :         MyPgXact->delayChkpt = false;
    1412      246302 :         END_CRIT_SECTION();
    1413             :     }
    1414             : 
    1415             :     /* Compute latestXid while we have the child XIDs handy */
    1416      287130 :     latestXid = TransactionIdLatest(xid, nchildren, children);
    1417             : 
    1418             :     /*
    1419             :      * Wait for synchronous replication, if required. Similar to the decision
    1420             :      * above about using committing asynchronously we only want to wait if
    1421             :      * this backend assigned an xid and wrote WAL.  No need to wait if an xid
    1422             :      * was assigned due to temporary/unlogged tables or due to HOT pruning.
    1423             :      *
    1424             :      * Note that at this stage we have marked clog, but still show as running
    1425             :      * in the procarray and continue to hold locks.
    1426             :      */
    1427      287130 :     if (wrote_xlog && markXidCommitted)
    1428      239626 :         SyncRepWaitForLSN(XactLastRecEnd, true);
    1429             : 
    1430             :     /* remember end of last commit record */
    1431      287130 :     XactLastCommitEnd = XactLastRecEnd;
    1432             : 
    1433             :     /* Reset XactLastRecEnd until the next transaction writes something */
    1434      287130 :     XactLastRecEnd = 0;
    1435             : cleanup:
    1436             :     /* Clean up local data */
    1437      437332 :     if (rels)
    1438       10122 :         pfree(rels);
    1439             : 
    1440      437332 :     return latestXid;
    1441             : }
    1442             : 
    1443             : 
    1444             : /*
    1445             :  *  AtCCI_LocalCache
    1446             :  */
    1447             : static void
    1448      588934 : AtCCI_LocalCache(void)
    1449             : {
    1450             :     /*
    1451             :      * Make any pending relation map changes visible.  We must do this before
    1452             :      * processing local sinval messages, so that the map changes will get
    1453             :      * reflected into the relcache when relcache invals are processed.
    1454             :      */
    1455      588934 :     AtCCI_RelationMap();
    1456             : 
    1457             :     /*
    1458             :      * Make catalog changes visible to me for the next command.
    1459             :      */
    1460      588934 :     CommandEndInvalidationMessages();
    1461      588934 : }
    1462             : 
    1463             : /*
    1464             :  *  AtCommit_Memory
    1465             :  */
    1466             : static void
    1467      438908 : AtCommit_Memory(void)
    1468             : {
    1469             :     /*
    1470             :      * Now that we're "out" of a transaction, have the system allocate things
    1471             :      * in the top memory context instead of per-transaction contexts.
    1472             :      */
    1473      438908 :     MemoryContextSwitchTo(TopMemoryContext);
    1474             : 
    1475             :     /*
    1476             :      * Release all transaction-local memory.
    1477             :      */
    1478             :     Assert(TopTransactionContext != NULL);
    1479      438908 :     MemoryContextDelete(TopTransactionContext);
    1480      438908 :     TopTransactionContext = NULL;
    1481      438908 :     CurTransactionContext = NULL;
    1482      438908 :     CurrentTransactionState->curTransactionContext = NULL;
    1483      438908 : }
    1484             : 
    1485             : /* ----------------------------------------------------------------
    1486             :  *                      CommitSubTransaction stuff
    1487             :  * ----------------------------------------------------------------
    1488             :  */
    1489             : 
    1490             : /*
    1491             :  * AtSubCommit_Memory
    1492             :  */
    1493             : static void
    1494        4432 : AtSubCommit_Memory(void)
    1495             : {
    1496        4432 :     TransactionState s = CurrentTransactionState;
    1497             : 
    1498             :     Assert(s->parent != NULL);
    1499             : 
    1500             :     /* Return to parent transaction level's memory context. */
    1501        4432 :     CurTransactionContext = s->parent->curTransactionContext;
    1502        4432 :     MemoryContextSwitchTo(CurTransactionContext);
    1503             : 
    1504             :     /*
    1505             :      * Ordinarily we cannot throw away the child's CurTransactionContext,
    1506             :      * since the data it contains will be needed at upper commit.  However, if
    1507             :      * there isn't actually anything in it, we can throw it away.  This avoids
    1508             :      * a small memory leak in the common case of "trivial" subxacts.
    1509             :      */
    1510        4432 :     if (MemoryContextIsEmpty(s->curTransactionContext))
    1511             :     {
    1512        4372 :         MemoryContextDelete(s->curTransactionContext);
    1513        4372 :         s->curTransactionContext = NULL;
    1514             :     }
    1515        4432 : }
    1516             : 
    1517             : /*
    1518             :  * AtSubCommit_childXids
    1519             :  *
    1520             :  * Pass my own XID and my child XIDs up to my parent as committed children.
    1521             :  */
    1522             : static void
    1523        3666 : AtSubCommit_childXids(void)
    1524             : {
    1525        3666 :     TransactionState s = CurrentTransactionState;
    1526             :     int         new_nChildXids;
    1527             : 
    1528             :     Assert(s->parent != NULL);
    1529             : 
    1530             :     /*
    1531             :      * The parent childXids array will need to hold my XID and all my
    1532             :      * childXids, in addition to the XIDs already there.
    1533             :      */
    1534        3666 :     new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
    1535             : 
    1536             :     /* Allocate or enlarge the parent array if necessary */
    1537        3666 :     if (s->parent->maxChildXids < new_nChildXids)
    1538             :     {
    1539             :         int         new_maxChildXids;
    1540             :         TransactionId *new_childXids;
    1541             : 
    1542             :         /*
    1543             :          * Make it 2x what's needed right now, to avoid having to enlarge it
    1544             :          * repeatedly. But we can't go above MaxAllocSize.  (The latter limit
    1545             :          * is what ensures that we don't need to worry about integer overflow
    1546             :          * here or in the calculation of new_nChildXids.)
    1547             :          */
    1548        1660 :         new_maxChildXids = Min(new_nChildXids * 2,
    1549             :                                (int) (MaxAllocSize / sizeof(TransactionId)));
    1550             : 
    1551        1660 :         if (new_maxChildXids < new_nChildXids)
    1552           0 :             ereport(ERROR,
    1553             :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1554             :                      errmsg("maximum number of committed subtransactions (%d) exceeded",
    1555             :                             (int) (MaxAllocSize / sizeof(TransactionId)))));
    1556             : 
    1557             :         /*
    1558             :          * We keep the child-XID arrays in TopTransactionContext; this avoids
    1559             :          * setting up child-transaction contexts for what might be just a few
    1560             :          * bytes of grandchild XIDs.
    1561             :          */
    1562        1660 :         if (s->parent->childXids == NULL)
    1563        1628 :             new_childXids =
    1564        1628 :                 MemoryContextAlloc(TopTransactionContext,
    1565             :                                    new_maxChildXids * sizeof(TransactionId));
    1566             :         else
    1567          32 :             new_childXids = repalloc(s->parent->childXids,
    1568             :                                      new_maxChildXids * sizeof(TransactionId));
    1569             : 
    1570        1660 :         s->parent->childXids = new_childXids;
    1571        1660 :         s->parent->maxChildXids = new_maxChildXids;
    1572             :     }
    1573             : 
    1574             :     /*
    1575             :      * Copy all my XIDs to parent's array.
    1576             :      *
    1577             :      * Note: We rely on the fact that the XID of a child always follows that
    1578             :      * of its parent.  By copying the XID of this subtransaction before the
    1579             :      * XIDs of its children, we ensure that the array stays ordered. Likewise,
    1580             :      * all XIDs already in the array belong to subtransactions started and
    1581             :      * subcommitted before us, so their XIDs must precede ours.
    1582             :      */
    1583        3666 :     s->parent->childXids[s->parent->nChildXids] = XidFromFullTransactionId(s->fullTransactionId);
    1584             : 
    1585        3666 :     if (s->nChildXids > 0)
    1586        2272 :         memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
    1587        1136 :                s->childXids,
    1588        1136 :                s->nChildXids * sizeof(TransactionId));
    1589             : 
    1590        3666 :     s->parent->nChildXids = new_nChildXids;
    1591             : 
    1592             :     /* Release child's array to avoid leakage */
    1593        3666 :     if (s->childXids != NULL)
    1594        1136 :         pfree(s->childXids);
    1595             :     /* We must reset these to avoid double-free if fail later in commit */
    1596        3666 :     s->childXids = NULL;
    1597        3666 :     s->nChildXids = 0;
    1598        3666 :     s->maxChildXids = 0;
    1599        3666 : }
    1600             : 
    1601             : /* ----------------------------------------------------------------
    1602             :  *                      AbortTransaction stuff
    1603             :  * ----------------------------------------------------------------
    1604             :  */
    1605             : 
    1606             : /*
    1607             :  *  RecordTransactionAbort
    1608             :  *
    1609             :  * Returns latest XID among xact and its children, or InvalidTransactionId
    1610             :  * if the xact has no XID.  (We compute that here just because it's easier.)
    1611             :  */
    1612             : static TransactionId
    1613       22272 : RecordTransactionAbort(bool isSubXact)
    1614             : {
    1615       22272 :     TransactionId xid = GetCurrentTransactionIdIfAny();
    1616             :     TransactionId latestXid;
    1617             :     int         nrels;
    1618             :     RelFileNode *rels;
    1619             :     int         nchildren;
    1620             :     TransactionId *children;
    1621             :     TimestampTz xact_time;
    1622             : 
    1623             :     /*
    1624             :      * If we haven't been assigned an XID, nobody will care whether we aborted
    1625             :      * or not.  Hence, we're done in that case.  It does not matter if we have
    1626             :      * rels to delete (note that this routine is not responsible for actually
    1627             :      * deleting 'em).  We cannot have any child XIDs, either.
    1628             :      */
    1629       22272 :     if (!TransactionIdIsValid(xid))
    1630             :     {
    1631             :         /* Reset XactLastRecEnd until the next transaction writes something */
    1632       16736 :         if (!isSubXact)
    1633       14166 :             XactLastRecEnd = 0;
    1634       16736 :         return InvalidTransactionId;
    1635             :     }
    1636             : 
    1637             :     /*
    1638             :      * We have a valid XID, so we should write an ABORT record for it.
    1639             :      *
    1640             :      * We do not flush XLOG to disk here, since the default assumption after a
    1641             :      * crash would be that we aborted, anyway.  For the same reason, we don't
    1642             :      * need to worry about interlocking against checkpoint start.
    1643             :      */
    1644             : 
    1645             :     /*
    1646             :      * Check that we haven't aborted halfway through RecordTransactionCommit.
    1647             :      */
    1648        5536 :     if (TransactionIdDidCommit(xid))
    1649           0 :         elog(PANIC, "cannot abort transaction %u, it was already committed",
    1650             :              xid);
    1651             : 
    1652             :     /* Fetch the data we need for the abort record */
    1653        5536 :     nrels = smgrGetPendingDeletes(false, &rels);
    1654        5536 :     nchildren = xactGetCommittedChildren(&children);
    1655             : 
    1656             :     /* XXX do we really need a critical section here? */
    1657        5536 :     START_CRIT_SECTION();
    1658             : 
    1659             :     /* Write the ABORT record */
    1660        5536 :     if (isSubXact)
    1661         358 :         xact_time = GetCurrentTimestamp();
    1662             :     else
    1663             :     {
    1664        5178 :         SetCurrentTransactionStopTimestamp();
    1665        5178 :         xact_time = xactStopTimestamp;
    1666             :     }
    1667             : 
    1668        5536 :     XactLogAbortRecord(xact_time,
    1669             :                        nchildren, children,
    1670             :                        nrels, rels,
    1671             :                        MyXactFlags, InvalidTransactionId,
    1672             :                        NULL);
    1673             : 
    1674             :     /*
    1675             :      * Report the latest async abort LSN, so that the WAL writer knows to
    1676             :      * flush this abort. There's nothing to be gained by delaying this, since
    1677             :      * WALWriter may as well do this when it can. This is important with
    1678             :      * streaming replication because if we don't flush WAL regularly we will
    1679             :      * find that large aborts leave us with a long backlog for when commits
    1680             :      * occur after the abort, increasing our window of data loss should
    1681             :      * problems occur at that point.
    1682             :      */
    1683        5536 :     if (!isSubXact)
    1684        5178 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    1685             : 
    1686             :     /*
    1687             :      * Mark the transaction aborted in clog.  This is not absolutely necessary
    1688             :      * but we may as well do it while we are here; also, in the subxact case
    1689             :      * it is helpful because XactLockTableWait makes use of it to avoid
    1690             :      * waiting for already-aborted subtransactions.  It is OK to do it without
    1691             :      * having flushed the ABORT record to disk, because in event of a crash
    1692             :      * we'd be assumed to have aborted anyway.
    1693             :      */
    1694        5536 :     TransactionIdAbortTree(xid, nchildren, children);
    1695             : 
    1696        5536 :     END_CRIT_SECTION();
    1697             : 
    1698             :     /* Compute latestXid while we have the child XIDs handy */
    1699        5536 :     latestXid = TransactionIdLatest(xid, nchildren, children);
    1700             : 
    1701             :     /*
    1702             :      * If we're aborting a subtransaction, we can immediately remove failed
    1703             :      * XIDs from PGPROC's cache of running child XIDs.  We do that here for
    1704             :      * subxacts, because we already have the child XID array at hand.  For
    1705             :      * main xacts, the equivalent happens just after this function returns.
    1706             :      */
    1707        5536 :     if (isSubXact)
    1708         358 :         XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
    1709             : 
    1710             :     /* Reset XactLastRecEnd until the next transaction writes something */
    1711        5536 :     if (!isSubXact)
    1712        5178 :         XactLastRecEnd = 0;
    1713             : 
    1714             :     /* And clean up local data */
    1715        5536 :     if (rels)
    1716         806 :         pfree(rels);
    1717             : 
    1718        5536 :     return latestXid;
    1719             : }
    1720             : 
    1721             : /*
    1722             :  *  AtAbort_Memory
    1723             :  */
    1724             : static void
    1725       29800 : AtAbort_Memory(void)
    1726             : {
    1727             :     /*
    1728             :      * Switch into TransactionAbortContext, which should have some free space
    1729             :      * even if nothing else does.  We'll work in this context until we've
    1730             :      * finished cleaning up.
    1731             :      *
    1732             :      * It is barely possible to get here when we've not been able to create
    1733             :      * TransactionAbortContext yet; if so use TopMemoryContext.
    1734             :      */
    1735       29800 :     if (TransactionAbortContext != NULL)
    1736       29800 :         MemoryContextSwitchTo(TransactionAbortContext);
    1737             :     else
    1738           0 :         MemoryContextSwitchTo(TopMemoryContext);
    1739       29800 : }
    1740             : 
    1741             : /*
    1742             :  * AtSubAbort_Memory
    1743             :  */
    1744             : static void
    1745        2928 : AtSubAbort_Memory(void)
    1746             : {
    1747             :     Assert(TransactionAbortContext != NULL);
    1748             : 
    1749        2928 :     MemoryContextSwitchTo(TransactionAbortContext);
    1750        2928 : }
    1751             : 
    1752             : 
    1753             : /*
    1754             :  *  AtAbort_ResourceOwner
    1755             :  */
    1756             : static void
    1757       19348 : AtAbort_ResourceOwner(void)
    1758             : {
    1759             :     /*
    1760             :      * Make sure we have a valid ResourceOwner, if possible (else it will be
    1761             :      * NULL, which is OK)
    1762             :      */
    1763       19348 :     CurrentResourceOwner = TopTransactionResourceOwner;
    1764       19348 : }
    1765             : 
    1766             : /*
    1767             :  * AtSubAbort_ResourceOwner
    1768             :  */
    1769             : static void
    1770        2928 : AtSubAbort_ResourceOwner(void)
    1771             : {
    1772        2928 :     TransactionState s = CurrentTransactionState;
    1773             : 
    1774             :     /* Make sure we have a valid ResourceOwner */
    1775        2928 :     CurrentResourceOwner = s->curTransactionOwner;
    1776        2928 : }
    1777             : 
    1778             : 
    1779             : /*
    1780             :  * AtSubAbort_childXids
    1781             :  */
    1782             : static void
    1783         358 : AtSubAbort_childXids(void)
    1784             : {
    1785         358 :     TransactionState s = CurrentTransactionState;
    1786             : 
    1787             :     /*
    1788             :      * We keep the child-XID arrays in TopTransactionContext (see
    1789             :      * AtSubCommit_childXids).  This means we'd better free the array
    1790             :      * explicitly at abort to avoid leakage.
    1791             :      */
    1792         358 :     if (s->childXids != NULL)
    1793          48 :         pfree(s->childXids);
    1794         358 :     s->childXids = NULL;
    1795         358 :     s->nChildXids = 0;
    1796         358 :     s->maxChildXids = 0;
    1797             : 
    1798             :     /*
    1799             :      * We could prune the unreportedXids array here. But we don't bother. That
    1800             :      * would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it
    1801             :      * would likely introduce more CPU time into the more common paths, so we
    1802             :      * choose not to do that.
    1803             :      */
    1804         358 : }
    1805             : 
    1806             : /* ----------------------------------------------------------------
    1807             :  *                      CleanupTransaction stuff
    1808             :  * ----------------------------------------------------------------
    1809             :  */
    1810             : 
    1811             : /*
    1812             :  *  AtCleanup_Memory
    1813             :  */
    1814             : static void
    1815       29800 : AtCleanup_Memory(void)
    1816             : {
    1817             :     Assert(CurrentTransactionState->parent == NULL);
    1818             : 
    1819             :     /*
    1820             :      * Now that we're "out" of a transaction, have the system allocate things
    1821             :      * in the top memory context instead of per-transaction contexts.
    1822             :      */
    1823       29800 :     MemoryContextSwitchTo(TopMemoryContext);
    1824             : 
    1825             :     /*
    1826             :      * Clear the special abort context for next time.
    1827             :      */
    1828       29800 :     if (TransactionAbortContext != NULL)
    1829       29800 :         MemoryContextResetAndDeleteChildren(TransactionAbortContext);
    1830             : 
    1831             :     /*
    1832             :      * Release all transaction-local memory.
    1833             :      */
    1834       29800 :     if (TopTransactionContext != NULL)
    1835       19348 :         MemoryContextDelete(TopTransactionContext);
    1836       29800 :     TopTransactionContext = NULL;
    1837       29800 :     CurTransactionContext = NULL;
    1838       29800 :     CurrentTransactionState->curTransactionContext = NULL;
    1839       29800 : }
    1840             : 
    1841             : 
    1842             : /* ----------------------------------------------------------------
    1843             :  *                      CleanupSubTransaction stuff
    1844             :  * ----------------------------------------------------------------
    1845             :  */
    1846             : 
    1847             : /*
    1848             :  * AtSubCleanup_Memory
    1849             :  */
    1850             : static void
    1851        2928 : AtSubCleanup_Memory(void)
    1852             : {
    1853        2928 :     TransactionState s = CurrentTransactionState;
    1854             : 
    1855             :     Assert(s->parent != NULL);
    1856             : 
    1857             :     /* Make sure we're not in an about-to-be-deleted context */
    1858        2928 :     MemoryContextSwitchTo(s->parent->curTransactionContext);
    1859        2928 :     CurTransactionContext = s->parent->curTransactionContext;
    1860             : 
    1861             :     /*
    1862             :      * Clear the special abort context for next time.
    1863             :      */
    1864        2928 :     if (TransactionAbortContext != NULL)
    1865        2928 :         MemoryContextResetAndDeleteChildren(TransactionAbortContext);
    1866             : 
    1867             :     /*
    1868             :      * Delete the subxact local memory contexts. Its CurTransactionContext can
    1869             :      * go too (note this also kills CurTransactionContexts from any children
    1870             :      * of the subxact).
    1871             :      */
    1872        2928 :     if (s->curTransactionContext)
    1873        2928 :         MemoryContextDelete(s->curTransactionContext);
    1874        2928 :     s->curTransactionContext = NULL;
    1875        2928 : }
    1876             : 
    1877             : /* ----------------------------------------------------------------
    1878             :  *                      interface routines
    1879             :  * ----------------------------------------------------------------
    1880             :  */
    1881             : 
    1882             : /*
    1883             :  *  StartTransaction
    1884             :  */
    1885             : static void
    1886      458256 : StartTransaction(void)
    1887             : {
    1888             :     TransactionState s;
    1889             :     VirtualTransactionId vxid;
    1890             : 
    1891             :     /*
    1892             :      * Let's just make sure the state stack is empty
    1893             :      */
    1894      458256 :     s = &TopTransactionStateData;
    1895      458256 :     CurrentTransactionState = s;
    1896             : 
    1897             :     Assert(!FullTransactionIdIsValid(XactTopFullTransactionId));
    1898             : 
    1899             :     /* check the current transaction state */
    1900             :     Assert(s->state == TRANS_DEFAULT);
    1901             : 
    1902             :     /*
    1903             :      * Set the current transaction state information appropriately during
    1904             :      * start processing.  Note that once the transaction status is switched
    1905             :      * this process cannot fail until the user ID and the security context
    1906             :      * flags are fetched below.
    1907             :      */
    1908      458256 :     s->state = TRANS_START;
    1909      458256 :     s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
    1910             : 
    1911             :     /* Determine if statements are logged in this transaction */
    1912      458256 :     xact_is_sampled = log_xact_sample_rate != 0 &&
    1913           0 :         (log_xact_sample_rate == 1 ||
    1914           0 :          random() <= log_xact_sample_rate * MAX_RANDOM_VALUE);
    1915             : 
    1916             :     /*
    1917             :      * initialize current transaction state fields
    1918             :      *
    1919             :      * note: prevXactReadOnly is not used at the outermost level
    1920             :      */
    1921      458256 :     s->nestingLevel = 1;
    1922      458256 :     s->gucNestLevel = 1;
    1923      458256 :     s->childXids = NULL;
    1924      458256 :     s->nChildXids = 0;
    1925      458256 :     s->maxChildXids = 0;
    1926             : 
    1927             :     /*
    1928             :      * Once the current user ID and the security context flags are fetched,
    1929             :      * both will be properly reset even if transaction startup fails.
    1930             :      */
    1931      458256 :     GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    1932             : 
    1933             :     /* SecurityRestrictionContext should never be set outside a transaction */
    1934             :     Assert(s->prevSecContext == 0);
    1935             : 
    1936             :     /*
    1937             :      * Make sure we've reset xact state variables
    1938             :      *
    1939             :      * If recovery is still in progress, mark this transaction as read-only.
    1940             :      * We have lower level defences in XLogInsert and elsewhere to stop us
    1941             :      * from modifying data during recovery, but this gives the normal
    1942             :      * indication to the user that the transaction is read-only.
    1943             :      */
    1944      458256 :     if (RecoveryInProgress())
    1945             :     {
    1946         424 :         s->startedInRecovery = true;
    1947         424 :         XactReadOnly = true;
    1948             :     }
    1949             :     else
    1950             :     {
    1951      457832 :         s->startedInRecovery = false;
    1952      457832 :         XactReadOnly = DefaultXactReadOnly;
    1953             :     }
    1954      458256 :     XactDeferrable = DefaultXactDeferrable;
    1955      458256 :     XactIsoLevel = DefaultXactIsoLevel;
    1956      458256 :     forceSyncCommit = false;
    1957      458256 :     MyXactFlags = 0;
    1958             : 
    1959             :     /*
    1960             :      * reinitialize within-transaction counters
    1961             :      */
    1962      458256 :     s->subTransactionId = TopSubTransactionId;
    1963      458256 :     currentSubTransactionId = TopSubTransactionId;
    1964      458256 :     currentCommandId = FirstCommandId;
    1965      458256 :     currentCommandIdUsed = false;
    1966             : 
    1967             :     /*
    1968             :      * initialize reported xid accounting
    1969             :      */
    1970      458256 :     nUnreportedXids = 0;
    1971      458256 :     s->didLogXid = false;
    1972             : 
    1973             :     /*
    1974             :      * must initialize resource-management stuff first
    1975             :      */
    1976      458256 :     AtStart_Memory();
    1977      458256 :     AtStart_ResourceOwner();
    1978             : 
    1979             :     /*
    1980             :      * Assign a new LocalTransactionId, and combine it with the backendId to
    1981             :      * form a virtual transaction id.
    1982             :      */
    1983      458256 :     vxid.backendId = MyBackendId;
    1984      458256 :     vxid.localTransactionId = GetNextLocalTransactionId();
    1985             : 
    1986             :     /*
    1987             :      * Lock the virtual transaction id before we announce it in the proc array
    1988             :      */
    1989      458256 :     VirtualXactLockTableInsert(vxid);
    1990             : 
    1991             :     /*
    1992             :      * Advertise it in the proc array.  We assume assignment of
    1993             :      * localTransactionId is atomic, and the backendId should be set already.
    1994             :      */
    1995             :     Assert(MyProc->backendId == vxid.backendId);
    1996      458256 :     MyProc->lxid = vxid.localTransactionId;
    1997             : 
    1998             :     TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
    1999             : 
    2000             :     /*
    2001             :      * set transaction_timestamp() (a/k/a now()).  Normally, we want this to
    2002             :      * be the same as the first command's statement_timestamp(), so don't do a
    2003             :      * fresh GetCurrentTimestamp() call (which'd be expensive anyway).  But
    2004             :      * for transactions started inside procedures (i.e., nonatomic SPI
    2005             :      * contexts), we do need to advance the timestamp.  Also, in a parallel
    2006             :      * worker, the timestamp should already have been provided by a call to
    2007             :      * SetParallelStartTimestamps().
    2008             :      */
    2009      458256 :     if (!IsParallelWorker())
    2010             :     {
    2011      453696 :         if (!SPI_inside_nonatomic_context())
    2012      449374 :             xactStartTimestamp = stmtStartTimestamp;
    2013             :         else
    2014        4322 :             xactStartTimestamp = GetCurrentTimestamp();
    2015             :     }
    2016             :     else
    2017             :         Assert(xactStartTimestamp != 0);
    2018      458256 :     pgstat_report_xact_timestamp(xactStartTimestamp);
    2019             :     /* Mark xactStopTimestamp as unset. */
    2020      458256 :     xactStopTimestamp = 0;
    2021             : 
    2022             :     /*
    2023             :      * initialize other subsystems for new transaction
    2024             :      */
    2025      458256 :     AtStart_GUC();
    2026      458256 :     AtStart_Cache();
    2027      458256 :     AfterTriggerBeginXact();
    2028             : 
    2029             :     /*
    2030             :      * done with start processing, set current transaction state to "in
    2031             :      * progress"
    2032             :      */
    2033      458256 :     s->state = TRANS_INPROGRESS;
    2034             : 
    2035      458256 :     ShowTransactionState("StartTransaction");
    2036      458256 : }
    2037             : 
    2038             : 
    2039             : /*
    2040             :  *  CommitTransaction
    2041             :  *
    2042             :  * NB: if you change this routine, better look at PrepareTransaction too!
    2043             :  */
    2044             : static void
    2045      439202 : CommitTransaction(void)
    2046             : {
    2047      439202 :     TransactionState s = CurrentTransactionState;
    2048             :     TransactionId latestXid;
    2049             :     bool        is_parallel_worker;
    2050             : 
    2051      439202 :     is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
    2052             : 
    2053             :     /* Enforce parallel mode restrictions during parallel worker commit. */
    2054      439202 :     if (is_parallel_worker)
    2055        1516 :         EnterParallelMode();
    2056             : 
    2057      439202 :     ShowTransactionState("CommitTransaction");
    2058             : 
    2059             :     /*
    2060             :      * check the current transaction state
    2061             :      */
    2062      439202 :     if (s->state != TRANS_INPROGRESS)
    2063           0 :         elog(WARNING, "CommitTransaction while in %s state",
    2064             :              TransStateAsString(s->state));
    2065             :     Assert(s->parent == NULL);
    2066             : 
    2067             :     /*
    2068             :      * Do pre-commit processing that involves calling user-defined code, such
    2069             :      * as triggers.  Since closing cursors could queue trigger actions,
    2070             :      * triggers could open cursors, etc, we have to keep looping until there's
    2071             :      * nothing left to do.
    2072             :      */
    2073             :     for (;;)
    2074             :     {
    2075             :         /*
    2076             :          * Fire all currently pending deferred triggers.
    2077             :          */
    2078      481174 :         AfterTriggerFireDeferred();
    2079             : 
    2080             :         /*
    2081             :          * Close open portals (converting holdable ones into static portals).
    2082             :          * If there weren't any, we are done ... otherwise loop back to check
    2083             :          * if they queued deferred triggers.  Lather, rinse, repeat.
    2084             :          */
    2085      460132 :         if (!PreCommit_Portals(false))
    2086      439146 :             break;
    2087             :     }
    2088             : 
    2089      439146 :     CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
    2090             :                       : XACT_EVENT_PRE_COMMIT);
    2091             : 
    2092             :     /*
    2093             :      * The remaining actions cannot call any user-defined code, so it's safe
    2094             :      * to start shutting down within-transaction services.  But note that most
    2095             :      * of this stuff could still throw an error, which would switch us into
    2096             :      * the transaction-abort path.
    2097             :      */
    2098             : 
    2099             :     /* If we might have parallel workers, clean them up now. */
    2100      439146 :     if (IsInParallelMode())
    2101        1516 :         AtEOXact_Parallel(true);
    2102             : 
    2103             :     /* Shut down the deferred-trigger manager */
    2104      439146 :     AfterTriggerEndXact(true);
    2105             : 
    2106             :     /*
    2107             :      * Let ON COMMIT management do its thing (must happen after closing
    2108             :      * cursors, to avoid dangling-reference problems)
    2109             :      */
    2110      439146 :     PreCommit_on_commit_actions();
    2111             : 
    2112             :     /* close large objects before lower-level cleanup */
    2113      439142 :     AtEOXact_LargeObject(true);
    2114             : 
    2115             :     /*
    2116             :      * Mark serializable transaction as complete for predicate locking
    2117             :      * purposes.  This should be done as late as we can put it and still allow
    2118             :      * errors to be raised for failure patterns found at commit.  This is not
    2119             :      * appropriate in a parallel worker however, because we aren't committing
    2120             :      * the leader's transaction and its serializable state will live on.
    2121             :      */
    2122      439142 :     if (!is_parallel_worker)
    2123      437626 :         PreCommit_CheckForSerializationFailure();
    2124             : 
    2125             :     /*
    2126             :      * Insert notifications sent by NOTIFY commands into the queue.  This
    2127             :      * should be late in the pre-commit sequence to minimize time spent
    2128             :      * holding the notify-insertion lock.
    2129             :      */
    2130      438848 :     PreCommit_Notify();
    2131             : 
    2132             :     /* Prevent cancel/die interrupt while cleaning up */
    2133      438848 :     HOLD_INTERRUPTS();
    2134             : 
    2135             :     /* Commit updates to the relation map --- do this as late as possible */
    2136      438848 :     AtEOXact_RelationMap(true, is_parallel_worker);
    2137             : 
    2138             :     /*
    2139             :      * set the current transaction state information appropriately during
    2140             :      * commit processing
    2141             :      */
    2142      438848 :     s->state = TRANS_COMMIT;
    2143      438848 :     s->parallelModeLevel = 0;
    2144             : 
    2145      438848 :     if (!is_parallel_worker)
    2146             :     {
    2147             :         /*
    2148             :          * We need to mark our XIDs as committed in pg_xact.  This is where we
    2149             :          * durably commit.
    2150             :          */
    2151      437332 :         latestXid = RecordTransactionCommit();
    2152             :     }
    2153             :     else
    2154             :     {
    2155             :         /*
    2156             :          * We must not mark our XID committed; the parallel master is
    2157             :          * responsible for that.
    2158             :          */
    2159        1516 :         latestXid = InvalidTransactionId;
    2160             : 
    2161             :         /*
    2162             :          * Make sure the master will know about any WAL we wrote before it
    2163             :          * commits.
    2164             :          */
    2165        1516 :         ParallelWorkerReportLastRecEnd(XactLastRecEnd);
    2166             :     }
    2167             : 
    2168             :     TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid);
    2169             : 
    2170             :     /*
    2171             :      * Let others know about no transaction in progress by me. Note that this
    2172             :      * must be done _before_ releasing locks we hold and _after_
    2173             :      * RecordTransactionCommit.
    2174             :      */
    2175      438848 :     ProcArrayEndTransaction(MyProc, latestXid);
    2176             : 
    2177             :     /*
    2178             :      * This is all post-commit cleanup.  Note that if an error is raised here,
    2179             :      * it's too late to abort the transaction.  This should be just
    2180             :      * noncritical resource releasing.
    2181             :      *
    2182             :      * The ordering of operations is not entirely random.  The idea is:
    2183             :      * release resources visible to other backends (eg, files, buffer pins);
    2184             :      * then release locks; then release backend-local resources. We want to
    2185             :      * release locks at the point where any backend waiting for us will see
    2186             :      * our transaction as being fully cleaned up.
    2187             :      *
    2188             :      * Resources that can be associated with individual queries are handled by
    2189             :      * the ResourceOwner mechanism.  The other calls here are for backend-wide
    2190             :      * state.
    2191             :      */
    2192             : 
    2193      438848 :     CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
    2194             :                       : XACT_EVENT_COMMIT);
    2195             : 
    2196      438848 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2197             :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    2198             :                          true, true);
    2199             : 
    2200             :     /* Check we've released all buffer pins */
    2201      438848 :     AtEOXact_Buffers(true);
    2202             : 
    2203             :     /* Clean up the relation cache */
    2204      438848 :     AtEOXact_RelationCache(true);
    2205             : 
    2206             :     /*
    2207             :      * Make catalog changes visible to all backends.  This has to happen after
    2208             :      * relcache references are dropped (see comments for
    2209             :      * AtEOXact_RelationCache), but before locks are released (if anyone is
    2210             :      * waiting for lock on a relation we've modified, we want them to know
    2211             :      * about the catalog change before they start using the relation).
    2212             :      */
    2213      438848 :     AtEOXact_Inval(true);
    2214             : 
    2215      438848 :     AtEOXact_MultiXact();
    2216             : 
    2217      438848 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2218             :                          RESOURCE_RELEASE_LOCKS,
    2219             :                          true, true);
    2220      438848 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2221             :                          RESOURCE_RELEASE_AFTER_LOCKS,
    2222             :                          true, true);
    2223             : 
    2224             :     /*
    2225             :      * Likewise, dropping of files deleted during the transaction is best done
    2226             :      * after releasing relcache and buffer pins.  (This is not strictly
    2227             :      * necessary during commit, since such pins should have been released
    2228             :      * already, but this ordering is definitely critical during abort.)  Since
    2229             :      * this may take many seconds, also delay until after releasing locks.
    2230             :      * Other backends will observe the attendant catalog changes and not
    2231             :      * attempt to access affected files.
    2232             :      */
    2233      438848 :     smgrDoPendingDeletes(true);
    2234             : 
    2235      438848 :     AtCommit_Notify();
    2236      438848 :     AtEOXact_GUC(true, 1);
    2237      438848 :     AtEOXact_SPI(true);
    2238      438848 :     AtEOXact_Enum();
    2239      438848 :     AtEOXact_on_commit_actions(true);
    2240      438848 :     AtEOXact_Namespace(true, is_parallel_worker);
    2241      438848 :     AtEOXact_SMgr();
    2242      438848 :     AtEOXact_Files(true);
    2243      438848 :     AtEOXact_ComboCid();
    2244      438848 :     AtEOXact_HashTables(true);
    2245      438848 :     AtEOXact_PgStat(true, is_parallel_worker);
    2246      438848 :     AtEOXact_Snapshot(true, false);
    2247      438848 :     AtEOXact_ApplyLauncher(true);
    2248      438848 :     pgstat_report_xact_timestamp(0);
    2249             : 
    2250      438848 :     CurrentResourceOwner = NULL;
    2251      438848 :     ResourceOwnerDelete(TopTransactionResourceOwner);
    2252      438848 :     s->curTransactionOwner = NULL;
    2253      438848 :     CurTransactionResourceOwner = NULL;
    2254      438848 :     TopTransactionResourceOwner = NULL;
    2255             : 
    2256      438848 :     AtCommit_Memory();
    2257             : 
    2258      438848 :     s->fullTransactionId = InvalidFullTransactionId;
    2259      438848 :     s->subTransactionId = InvalidSubTransactionId;
    2260      438848 :     s->nestingLevel = 0;
    2261      438848 :     s->gucNestLevel = 0;
    2262      438848 :     s->childXids = NULL;
    2263      438848 :     s->nChildXids = 0;
    2264      438848 :     s->maxChildXids = 0;
    2265             : 
    2266      438848 :     XactTopFullTransactionId = InvalidFullTransactionId;
    2267      438848 :     nParallelCurrentXids = 0;
    2268             : 
    2269             :     /*
    2270             :      * done with commit processing, set current transaction state back to
    2271             :      * default
    2272             :      */
    2273      438848 :     s->state = TRANS_DEFAULT;
    2274             : 
    2275      438848 :     RESUME_INTERRUPTS();
    2276      438848 : }
    2277             : 
    2278             : 
    2279             : /*
    2280             :  *  PrepareTransaction
    2281             :  *
    2282             :  * NB: if you change this routine, better look at CommitTransaction too!
    2283             :  */
    2284             : static void
    2285         126 : PrepareTransaction(void)
    2286             : {
    2287         126 :     TransactionState s = CurrentTransactionState;
    2288         126 :     TransactionId xid = GetCurrentTransactionId();
    2289             :     GlobalTransaction gxact;
    2290             :     TimestampTz prepared_at;
    2291             : 
    2292             :     Assert(!IsInParallelMode());
    2293             : 
    2294         126 :     ShowTransactionState("PrepareTransaction");
    2295             : 
    2296             :     /*
    2297             :      * check the current transaction state
    2298             :      */
    2299         126 :     if (s->state != TRANS_INPROGRESS)
    2300           0 :         elog(WARNING, "PrepareTransaction while in %s state",
    2301             :              TransStateAsString(s->state));
    2302             :     Assert(s->parent == NULL);
    2303             : 
    2304             :     /*
    2305             :      * Do pre-commit processing that involves calling user-defined code, such
    2306             :      * as triggers.  Since closing cursors could queue trigger actions,
    2307             :      * triggers could open cursors, etc, we have to keep looping until there's
    2308             :      * nothing left to do.
    2309             :      */
    2310             :     for (;;)
    2311             :     {
    2312             :         /*
    2313             :          * Fire all currently pending deferred triggers.
    2314             :          */
    2315         134 :         AfterTriggerFireDeferred();
    2316             : 
    2317             :         /*
    2318             :          * Close open portals (converting holdable ones into static portals).
    2319             :          * If there weren't any, we are done ... otherwise loop back to check
    2320             :          * if they queued deferred triggers.  Lather, rinse, repeat.
    2321             :          */
    2322         130 :         if (!PreCommit_Portals(true))
    2323         126 :             break;
    2324             :     }
    2325             : 
    2326         126 :     CallXactCallbacks(XACT_EVENT_PRE_PREPARE);
    2327             : 
    2328             :     /*
    2329             :      * The remaining actions cannot call any user-defined code, so it's safe
    2330             :      * to start shutting down within-transaction services.  But note that most
    2331             :      * of this stuff could still throw an error, which would switch us into
    2332             :      * the transaction-abort path.
    2333             :      */
    2334             : 
    2335             :     /* Shut down the deferred-trigger manager */
    2336         124 :     AfterTriggerEndXact(true);
    2337             : 
    2338             :     /*
    2339             :      * Let ON COMMIT management do its thing (must happen after closing
    2340             :      * cursors, to avoid dangling-reference problems)
    2341             :      */
    2342         124 :     PreCommit_on_commit_actions();
    2343             : 
    2344             :     /* close large objects before lower-level cleanup */
    2345         124 :     AtEOXact_LargeObject(true);
    2346             : 
    2347             :     /*
    2348             :      * Mark serializable transaction as complete for predicate locking
    2349             :      * purposes.  This should be done as late as we can put it and still allow
    2350             :      * errors to be raised for failure patterns found at commit.
    2351             :      */
    2352         124 :     PreCommit_CheckForSerializationFailure();
    2353             : 
    2354             :     /* NOTIFY will be handled below */
    2355             : 
    2356             :     /*
    2357             :      * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
    2358             :      * this transaction.  Having the prepared xact hold locks on another
    2359             :      * backend's temp table seems a bad idea --- for instance it would prevent
    2360             :      * the backend from exiting.  There are other problems too, such as how to
    2361             :      * clean up the source backend's local buffers and ON COMMIT state if the
    2362             :      * prepared xact includes a DROP of a temp table.
    2363             :      *
    2364             :      * Other objects types, like functions, operators or extensions, share the
    2365             :      * same restriction as they should not be created, locked or dropped as
    2366             :      * this can mess up with this session or even a follow-up session trying
    2367             :      * to use the same temporary namespace.
    2368             :      *
    2369             :      * We must check this after executing any ON COMMIT actions, because they
    2370             :      * might still access a temp relation.
    2371             :      *
    2372             :      * XXX In principle this could be relaxed to allow some useful special
    2373             :      * cases, such as a temp table created and dropped all within the
    2374             :      * transaction.  That seems to require much more bookkeeping though.
    2375             :      */
    2376         124 :     if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPNAMESPACE))
    2377          46 :         ereport(ERROR,
    2378             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2379             :                  errmsg("cannot PREPARE a transaction that has operated on temporary objects")));
    2380             : 
    2381             :     /*
    2382             :      * Likewise, don't allow PREPARE after pg_export_snapshot.  This could be
    2383             :      * supported if we added cleanup logic to twophase.c, but for now it
    2384             :      * doesn't seem worth the trouble.
    2385             :      */
    2386          78 :     if (XactHasExportedSnapshots())
    2387           0 :         ereport(ERROR,
    2388             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2389             :                  errmsg("cannot PREPARE a transaction that has exported snapshots")));
    2390             : 
    2391             :     /*
    2392             :      * Don't allow PREPARE but for transaction that has/might kill logical
    2393             :      * replication workers.
    2394             :      */
    2395          78 :     if (XactManipulatesLogicalReplicationWorkers())
    2396           0 :         ereport(ERROR,
    2397             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2398             :                  errmsg("cannot PREPARE a transaction that has manipulated logical replication workers")));
    2399             : 
    2400             :     /* Prevent cancel/die interrupt while cleaning up */
    2401          78 :     HOLD_INTERRUPTS();
    2402             : 
    2403             :     /*
    2404             :      * set the current transaction state information appropriately during
    2405             :      * prepare processing
    2406             :      */
    2407          78 :     s->state = TRANS_PREPARE;
    2408             : 
    2409          78 :     prepared_at = GetCurrentTimestamp();
    2410             : 
    2411             :     /* Tell bufmgr and smgr to prepare for commit */
    2412          78 :     BufmgrCommit();
    2413             : 
    2414             :     /*
    2415             :      * Reserve the GID for this transaction. This could fail if the requested
    2416             :      * GID is invalid or already in use.
    2417             :      */
    2418          78 :     gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
    2419             :                             GetUserId(), MyDatabaseId);
    2420          60 :     prepareGID = NULL;
    2421             : 
    2422             :     /*
    2423             :      * Collect data for the 2PC state file.  Note that in general, no actual
    2424             :      * state change should happen in the called modules during this step,
    2425             :      * since it's still possible to fail before commit, and in that case we
    2426             :      * want transaction abort to be able to clean up.  (In particular, the
    2427             :      * AtPrepare routines may error out if they find cases they cannot
    2428             :      * handle.)  State cleanup should happen in the PostPrepare routines
    2429             :      * below.  However, some modules can go ahead and clear state here because
    2430             :      * they wouldn't do anything with it during abort anyway.
    2431             :      *
    2432             :      * Note: because the 2PC state file records will be replayed in the same
    2433             :      * order they are made, the order of these calls has to match the order in
    2434             :      * which we want things to happen during COMMIT PREPARED or ROLLBACK
    2435             :      * PREPARED; in particular, pay attention to whether things should happen
    2436             :      * before or after releasing the transaction's locks.
    2437             :      */
    2438          60 :     StartPrepare(gxact);
    2439             : 
    2440          60 :     AtPrepare_Notify();
    2441          60 :     AtPrepare_Locks();
    2442          60 :     AtPrepare_PredicateLocks();
    2443          60 :     AtPrepare_PgStat();
    2444          60 :     AtPrepare_MultiXact();
    2445          60 :     AtPrepare_RelationMap();
    2446             : 
    2447             :     /*
    2448             :      * Here is where we really truly prepare.
    2449             :      *
    2450             :      * We have to record transaction prepares even if we didn't make any
    2451             :      * updates, because the transaction manager might get confused if we lose
    2452             :      * a global transaction.
    2453             :      */
    2454          60 :     EndPrepare(gxact);
    2455             : 
    2456             :     /*
    2457             :      * Now we clean up backend-internal state and release internal resources.
    2458             :      */
    2459             : 
    2460             :     /* Reset XactLastRecEnd until the next transaction writes something */
    2461          60 :     XactLastRecEnd = 0;
    2462             : 
    2463             :     /*
    2464             :      * Let others know about no transaction in progress by me.  This has to be
    2465             :      * done *after* the prepared transaction has been marked valid, else
    2466             :      * someone may think it is unlocked and recyclable.
    2467             :      */
    2468          60 :     ProcArrayClearTransaction(MyProc);
    2469             : 
    2470             :     /*
    2471             :      * In normal commit-processing, this is all non-critical post-transaction
    2472             :      * cleanup.  When the transaction is prepared, however, it's important
    2473             :      * that the locks and other per-backend resources are transferred to the
    2474             :      * prepared transaction's PGPROC entry.  Note that if an error is raised
    2475             :      * here, it's too late to abort the transaction. XXX: This probably should
    2476             :      * be in a critical section, to force a PANIC if any of this fails, but
    2477             :      * that cure could be worse than the disease.
    2478             :      */
    2479             : 
    2480          60 :     CallXactCallbacks(XACT_EVENT_PREPARE);
    2481             : 
    2482          60 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2483             :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    2484             :                          true, true);
    2485             : 
    2486             :     /* Check we've released all buffer pins */
    2487          60 :     AtEOXact_Buffers(true);
    2488             : 
    2489             :     /* Clean up the relation cache */
    2490          60 :     AtEOXact_RelationCache(true);
    2491             : 
    2492             :     /* notify doesn't need a postprepare call */
    2493             : 
    2494          60 :     PostPrepare_PgStat();
    2495             : 
    2496          60 :     PostPrepare_Inval();
    2497             : 
    2498          60 :     PostPrepare_smgr();
    2499             : 
    2500          60 :     PostPrepare_MultiXact(xid);
    2501             : 
    2502          60 :     PostPrepare_Locks(xid);
    2503          60 :     PostPrepare_PredicateLocks(xid);
    2504             : 
    2505          60 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2506             :                          RESOURCE_RELEASE_LOCKS,
    2507             :                          true, true);
    2508          60 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2509             :                          RESOURCE_RELEASE_AFTER_LOCKS,
    2510             :                          true, true);
    2511             : 
    2512             :     /*
    2513             :      * Allow another backend to finish the transaction.  After
    2514             :      * PostPrepare_Twophase(), the transaction is completely detached from our
    2515             :      * backend.  The rest is just non-critical cleanup of backend-local state.
    2516             :      */
    2517          60 :     PostPrepare_Twophase();
    2518             : 
    2519             :     /* PREPARE acts the same as COMMIT as far as GUC is concerned */
    2520          60 :     AtEOXact_GUC(true, 1);
    2521          60 :     AtEOXact_SPI(true);
    2522          60 :     AtEOXact_Enum();
    2523          60 :     AtEOXact_on_commit_actions(true);
    2524          60 :     AtEOXact_Namespace(true, false);
    2525          60 :     AtEOXact_SMgr();
    2526          60 :     AtEOXact_Files(true);
    2527          60 :     AtEOXact_ComboCid();
    2528          60 :     AtEOXact_HashTables(true);
    2529             :     /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
    2530          60 :     AtEOXact_Snapshot(true, true);
    2531          60 :     pgstat_report_xact_timestamp(0);
    2532             : 
    2533          60 :     CurrentResourceOwner = NULL;
    2534          60 :     ResourceOwnerDelete(TopTransactionResourceOwner);
    2535          60 :     s->curTransactionOwner = NULL;
    2536          60 :     CurTransactionResourceOwner = NULL;
    2537          60 :     TopTransactionResourceOwner = NULL;
    2538             : 
    2539          60 :     AtCommit_Memory();
    2540             : 
    2541          60 :     s->fullTransactionId = InvalidFullTransactionId;
    2542          60 :     s->subTransactionId = InvalidSubTransactionId;
    2543          60 :     s->nestingLevel = 0;
    2544          60 :     s->gucNestLevel = 0;
    2545          60 :     s->childXids = NULL;
    2546          60 :     s->nChildXids = 0;
    2547          60 :     s->maxChildXids = 0;
    2548             : 
    2549          60 :     XactTopFullTransactionId = InvalidFullTransactionId;
    2550          60 :     nParallelCurrentXids = 0;
    2551             : 
    2552             :     /*
    2553             :      * done with 1st phase commit processing, set current transaction state
    2554             :      * back to default
    2555             :      */
    2556          60 :     s->state = TRANS_DEFAULT;
    2557             : 
    2558          60 :     RESUME_INTERRUPTS();
    2559          60 : }
    2560             : 
    2561             : 
    2562             : /*
    2563             :  *  AbortTransaction
    2564             :  */
    2565             : static void
    2566       19348 : AbortTransaction(void)
    2567             : {
    2568       19348 :     TransactionState s = CurrentTransactionState;
    2569             :     TransactionId latestXid;
    2570             :     bool        is_parallel_worker;
    2571             : 
    2572             :     /* Prevent cancel/die interrupt while cleaning up */
    2573       19348 :     HOLD_INTERRUPTS();
    2574             : 
    2575             :     /* Make sure we have a valid memory context and resource owner */
    2576       19348 :     AtAbort_Memory();
    2577       19348 :     AtAbort_ResourceOwner();
    2578             : 
    2579             :     /*
    2580             :      * Release any LW locks we might be holding as quickly as possible.
    2581             :      * (Regular locks, however, must be held till we finish aborting.)
    2582             :      * Releasing LW locks is critical since we might try to grab them again
    2583             :      * while cleaning up!
    2584             :      */
    2585       19348 :     LWLockReleaseAll();
    2586             : 
    2587             :     /* Clear wait information and command progress indicator */
    2588       19348 :     pgstat_report_wait_end();
    2589       19348 :     pgstat_progress_end_command();
    2590             : 
    2591             :     /* Clean up buffer I/O and buffer context locks, too */
    2592       19348 :     AbortBufferIO();
    2593       19348 :     UnlockBuffers();
    2594             : 
    2595             :     /* Reset WAL record construction state */
    2596       19348 :     XLogResetInsertion();
    2597             : 
    2598             :     /* Cancel condition variable sleep */
    2599       19348 :     ConditionVariableCancelSleep();
    2600             : 
    2601             :     /*
    2602             :      * Also clean up any open wait for lock, since the lock manager will choke
    2603             :      * if we try to wait for another lock before doing this.
    2604             :      */
    2605       19348 :     LockErrorCleanup();
    2606             : 
    2607             :     /*
    2608             :      * If any timeout events are still active, make sure the timeout interrupt
    2609             :      * is scheduled.  This covers possible loss of a timeout interrupt due to
    2610             :      * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
    2611             :      * We delay this till after LockErrorCleanup so that we don't uselessly
    2612             :      * reschedule lock or deadlock check timeouts.
    2613             :      */
    2614       19348 :     reschedule_timeouts();
    2615             : 
    2616             :     /*
    2617             :      * Re-enable signals, in case we got here by longjmp'ing out of a signal
    2618             :      * handler.  We do this fairly early in the sequence so that the timeout
    2619             :      * infrastructure will be functional if needed while aborting.
    2620             :      */
    2621       19348 :     PG_SETMASK(&UnBlockSig);
    2622             : 
    2623             :     /*
    2624             :      * check the current transaction state
    2625             :      */
    2626       19348 :     is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
    2627       19348 :     if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
    2628           0 :         elog(WARNING, "AbortTransaction while in %s state",
    2629             :              TransStateAsString(s->state));
    2630             :     Assert(s->parent == NULL);
    2631             : 
    2632             :     /*
    2633             :      * set the current transaction state information appropriately during the
    2634             :      * abort processing
    2635             :      */
    2636       19348 :     s->state = TRANS_ABORT;
    2637             : 
    2638             :     /*
    2639             :      * Reset user ID which might have been changed transiently.  We need this
    2640             :      * to clean up in case control escaped out of a SECURITY DEFINER function
    2641             :      * or other local change of CurrentUserId; therefore, the prior value of
    2642             :      * SecurityRestrictionContext also needs to be restored.
    2643             :      *
    2644             :      * (Note: it is not necessary to restore session authorization or role
    2645             :      * settings here because those can only be changed via GUC, and GUC will
    2646             :      * take care of rolling them back if need be.)
    2647             :      */
    2648       19348 :     SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
    2649             : 
    2650             :     /* If in parallel mode, clean up workers and exit parallel mode. */
    2651       19348 :     if (IsInParallelMode())
    2652             :     {
    2653           4 :         AtEOXact_Parallel(false);
    2654           4 :         s->parallelModeLevel = 0;
    2655             :     }
    2656             : 
    2657             :     /*
    2658             :      * do abort processing
    2659             :      */
    2660       19348 :     AfterTriggerEndXact(false); /* 'false' means it's abort */
    2661       19348 :     AtAbort_Portals();
    2662       19348 :     AtEOXact_LargeObject(false);
    2663       19348 :     AtAbort_Notify();
    2664       19348 :     AtEOXact_RelationMap(false, is_parallel_worker);
    2665       19348 :     AtAbort_Twophase();
    2666             : 
    2667             :     /*
    2668             :      * Advertise the fact that we aborted in pg_xact (assuming that we got as
    2669             :      * far as assigning an XID to advertise).  But if we're inside a parallel
    2670             :      * worker, skip this; the user backend must be the one to write the abort
    2671             :      * record.
    2672             :      */
    2673       19348 :     if (!is_parallel_worker)
    2674       19344 :         latestXid = RecordTransactionAbort(false);
    2675             :     else
    2676             :     {
    2677           4 :         latestXid = InvalidTransactionId;
    2678             : 
    2679             :         /*
    2680             :          * Since the parallel master won't get our value of XactLastRecEnd in
    2681             :          * this case, we nudge WAL-writer ourselves in this case.  See related
    2682             :          * comments in RecordTransactionAbort for why this matters.
    2683             :          */
    2684           4 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    2685             :     }
    2686             : 
    2687             :     TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid);
    2688             : 
    2689             :     /*
    2690             :      * Let others know about no transaction in progress by me. Note that this
    2691             :      * must be done _before_ releasing locks we hold and _after_
    2692             :      * RecordTransactionAbort.
    2693             :      */
    2694       19348 :     ProcArrayEndTransaction(MyProc, latestXid);
    2695             : 
    2696             :     /*
    2697             :      * Post-abort cleanup.  See notes in CommitTransaction() concerning
    2698             :      * ordering.  We can skip all of it if the transaction failed before
    2699             :      * creating a resource owner.
    2700             :      */
    2701       19348 :     if (TopTransactionResourceOwner != NULL)
    2702             :     {
    2703       19348 :         if (is_parallel_worker)
    2704           4 :             CallXactCallbacks(XACT_EVENT_PARALLEL_ABORT);
    2705             :         else
    2706       19344 :             CallXactCallbacks(XACT_EVENT_ABORT);
    2707             : 
    2708       19348 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    2709             :                              RESOURCE_RELEASE_BEFORE_LOCKS,
    2710             :                              false, true);
    2711       19348 :         AtEOXact_Buffers(false);
    2712       19348 :         AtEOXact_RelationCache(false);
    2713       19348 :         AtEOXact_Inval(false);
    2714       19348 :         AtEOXact_MultiXact();
    2715       19348 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    2716             :                              RESOURCE_RELEASE_LOCKS,
    2717             :                              false, true);
    2718       19348 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    2719             :                              RESOURCE_RELEASE_AFTER_LOCKS,
    2720             :                              false, true);
    2721       19348 :         smgrDoPendingDeletes(false);
    2722             : 
    2723       19348 :         AtEOXact_GUC(false, 1);
    2724       19348 :         AtEOXact_SPI(false);
    2725       19348 :         AtEOXact_Enum();
    2726       19348 :         AtEOXact_on_commit_actions(false);
    2727       19348 :         AtEOXact_Namespace(false, is_parallel_worker);
    2728       19348 :         AtEOXact_SMgr();
    2729       19348 :         AtEOXact_Files(false);
    2730       19348 :         AtEOXact_ComboCid();
    2731       19348 :         AtEOXact_HashTables(false);
    2732       19348 :         AtEOXact_PgStat(false, is_parallel_worker);
    2733       19348 :         AtEOXact_ApplyLauncher(false);
    2734       19348 :         pgstat_report_xact_timestamp(0);
    2735             :     }
    2736             : 
    2737             :     /*
    2738             :      * State remains TRANS_ABORT until CleanupTransaction().
    2739             :      */
    2740       19348 :     RESUME_INTERRUPTS();
    2741       19348 : }
    2742             : 
    2743             : /*
    2744             :  *  CleanupTransaction
    2745             :  */
    2746             : static void
    2747       19348 : CleanupTransaction(void)
    2748             : {
    2749       19348 :     TransactionState s = CurrentTransactionState;
    2750             : 
    2751             :     /*
    2752             :      * State should still be TRANS_ABORT from AbortTransaction().
    2753             :      */
    2754       19348 :     if (s->state != TRANS_ABORT)
    2755           0 :         elog(FATAL, "CleanupTransaction: unexpected state %s",
    2756             :              TransStateAsString(s->state));
    2757             : 
    2758             :     /*
    2759             :      * do abort cleanup processing
    2760             :      */
    2761       19348 :     AtCleanup_Portals();        /* now safe to release portal memory */
    2762       19348 :     AtEOXact_Snapshot(false, true); /* and release the transaction's snapshots */
    2763             : 
    2764       19348 :     CurrentResourceOwner = NULL;    /* and resource owner */
    2765       19348 :     if (TopTransactionResourceOwner)
    2766       19348 :         ResourceOwnerDelete(TopTransactionResourceOwner);
    2767       19348 :     s->curTransactionOwner = NULL;
    2768       19348 :     CurTransactionResourceOwner = NULL;
    2769       19348 :     TopTransactionResourceOwner = NULL;
    2770             : 
    2771       19348 :     AtCleanup_Memory();         /* and transaction memory */
    2772             : 
    2773       19348 :     s->fullTransactionId = InvalidFullTransactionId;
    2774       19348 :     s->subTransactionId = InvalidSubTransactionId;
    2775       19348 :     s->nestingLevel = 0;
    2776       19348 :     s->gucNestLevel = 0;
    2777       19348 :     s->childXids = NULL;
    2778       19348 :     s->nChildXids = 0;
    2779       19348 :     s->maxChildXids = 0;
    2780       19348 :     s->parallelModeLevel = 0;
    2781             : 
    2782       19348 :     XactTopFullTransactionId = InvalidFullTransactionId;
    2783       19348 :     nParallelCurrentXids = 0;
    2784             : 
    2785             :     /*
    2786             :      * done with abort processing, set current transaction state back to
    2787             :      * default
    2788             :      */
    2789       19348 :     s->state = TRANS_DEFAULT;
    2790       19348 : }
    2791             : 
    2792             : /*
    2793             :  *  StartTransactionCommand
    2794             :  */
    2795             : void
    2796      552700 : StartTransactionCommand(void)
    2797             : {
    2798      552700 :     TransactionState s = CurrentTransactionState;
    2799             : 
    2800      552700 :     switch (s->blockState)
    2801             :     {
    2802             :             /*
    2803             :              * if we aren't in a transaction block, we just do our usual start
    2804             :              * transaction.
    2805             :              */
    2806             :         case TBLOCK_DEFAULT:
    2807      456708 :             StartTransaction();
    2808      456708 :             s->blockState = TBLOCK_STARTED;
    2809      456708 :             break;
    2810             : 
    2811             :             /*
    2812             :              * We are somewhere in a transaction block or subtransaction and
    2813             :              * about to start a new command.  For now we do nothing, but
    2814             :              * someday we may do command-local resource initialization. (Note
    2815             :              * that any needed CommandCounterIncrement was done by the
    2816             :              * previous CommitTransactionCommand.)
    2817             :              */
    2818             :         case TBLOCK_INPROGRESS:
    2819             :         case TBLOCK_IMPLICIT_INPROGRESS:
    2820             :         case TBLOCK_SUBINPROGRESS:
    2821       94984 :             break;
    2822             : 
    2823             :             /*
    2824             :              * Here we are in a failed transaction block (one of the commands
    2825             :              * caused an abort) so we do nothing but remain in the abort
    2826             :              * state.  Eventually we will get a ROLLBACK command which will
    2827             :              * get us out of this state.  (It is up to other code to ensure
    2828             :              * that no commands other than ROLLBACK will be processed in these
    2829             :              * states.)
    2830             :              */
    2831             :         case TBLOCK_ABORT:
    2832             :         case TBLOCK_SUBABORT:
    2833        1008 :             break;
    2834             : 
    2835             :             /* These cases are invalid. */
    2836             :         case TBLOCK_STARTED:
    2837             :         case TBLOCK_BEGIN:
    2838             :         case TBLOCK_PARALLEL_INPROGRESS:
    2839             :         case TBLOCK_SUBBEGIN:
    2840             :         case TBLOCK_END:
    2841             :         case TBLOCK_SUBRELEASE:
    2842             :         case TBLOCK_SUBCOMMIT:
    2843             :         case TBLOCK_ABORT_END:
    2844             :         case TBLOCK_SUBABORT_END:
    2845             :         case TBLOCK_ABORT_PENDING:
    2846             :         case TBLOCK_SUBABORT_PENDING:
    2847             :         case TBLOCK_SUBRESTART:
    2848             :         case TBLOCK_SUBABORT_RESTART:
    2849             :         case TBLOCK_PREPARE:
    2850           0 :             elog(ERROR, "StartTransactionCommand: unexpected state %s",
    2851             :                  BlockStateAsString(s->blockState));
    2852             :             break;
    2853             :     }
    2854             : 
    2855             :     /*
    2856             :      * We must switch to CurTransactionContext before returning. This is
    2857             :      * already done if we called StartTransaction, otherwise not.
    2858             :      */
    2859             :     Assert(CurTransactionContext != NULL);
    2860      552700 :     MemoryContextSwitchTo(CurTransactionContext);
    2861      552700 : }
    2862             : 
    2863             : 
    2864             : /*
    2865             :  * Simple system for saving and restoring transaction characteristics
    2866             :  * (isolation level, read only, deferrable).  We need this for transaction
    2867             :  * chaining, so that we can set the characteristics of the new transaction to
    2868             :  * be the same as the previous one.  (We need something like this because the
    2869             :  * GUC system resets the characteristics at transaction end, so for example
    2870             :  * just skipping the reset in StartTransaction() won't work.)
    2871             :  */
    2872             : static int  save_XactIsoLevel;
    2873             : static bool save_XactReadOnly;
    2874             : static bool save_XactDeferrable;
    2875             : 
    2876             : void
    2877          36 : SaveTransactionCharacteristics(void)
    2878             : {
    2879          36 :     save_XactIsoLevel = XactIsoLevel;
    2880          36 :     save_XactReadOnly = XactReadOnly;
    2881          36 :     save_XactDeferrable = XactDeferrable;
    2882          36 : }
    2883             : 
    2884             : void
    2885          36 : RestoreTransactionCharacteristics(void)
    2886             : {
    2887          36 :     XactIsoLevel = save_XactIsoLevel;
    2888          36 :     XactReadOnly = save_XactReadOnly;
    2889          36 :     XactDeferrable = save_XactDeferrable;
    2890          36 : }
    2891             : 
    2892             : 
    2893             : /*
    2894             :  *  CommitTransactionCommand
    2895             :  */
    2896             : void
    2897      534854 : CommitTransactionCommand(void)
    2898             : {
    2899      534854 :     TransactionState s = CurrentTransactionState;
    2900             : 
    2901      534854 :     if (s->chain)
    2902          28 :         SaveTransactionCharacteristics();
    2903             : 
    2904      534854 :     switch (s->blockState)
    2905             :     {
    2906             :             /*
    2907             :              * These shouldn't happen.  TBLOCK_DEFAULT means the previous
    2908             :              * StartTransactionCommand didn't set the STARTED state
    2909             :              * appropriately, while TBLOCK_PARALLEL_INPROGRESS should be ended
    2910             :              * by EndParallelWorkerTransaction(), not this function.
    2911             :              */
    2912             :         case TBLOCK_DEFAULT:
    2913             :         case TBLOCK_PARALLEL_INPROGRESS:
    2914           0 :             elog(FATAL, "CommitTransactionCommand: unexpected state %s",
    2915             :                  BlockStateAsString(s->blockState));
    2916             :             break;
    2917             : 
    2918             :             /*
    2919             :              * If we aren't in a transaction block, just do our usual
    2920             :              * transaction commit, and return to the idle state.
    2921             :              */
    2922             :         case TBLOCK_STARTED:
    2923      429698 :             CommitTransaction();
    2924      429692 :             s->blockState = TBLOCK_DEFAULT;
    2925      429692 :             break;
    2926             : 
    2927             :             /*
    2928             :              * We are completing a "BEGIN TRANSACTION" command, so we change
    2929             :              * to the "transaction block in progress" state and return.  (We
    2930             :              * assume the BEGIN did nothing to the database, so we need no
    2931             :              * CommandCounterIncrement.)
    2932             :              */
    2933             :         case TBLOCK_BEGIN:
    2934        9898 :             s->blockState = TBLOCK_INPROGRESS;
    2935        9898 :             break;
    2936             : 
    2937             :             /*
    2938             :              * This is the case when we have finished executing a command
    2939             :              * someplace within a transaction block.  We increment the command
    2940             :              * counter and return.
    2941             :              */
    2942             :         case TBLOCK_INPROGRESS:
    2943             :         case TBLOCK_IMPLICIT_INPROGRESS:
    2944             :         case TBLOCK_SUBINPROGRESS:
    2945       77836 :             CommandCounterIncrement();
    2946       77836 :             break;
    2947             : 
    2948             :             /*
    2949             :              * We are completing a "COMMIT" command.  Do it and return to the
    2950             :              * idle state.
    2951             :              */
    2952             :         case TBLOCK_END:
    2953        7812 :             CommitTransaction();
    2954        7482 :             s->blockState = TBLOCK_DEFAULT;
    2955        7482 :             if (s->chain)
    2956             :             {
    2957           8 :                 StartTransaction();
    2958           8 :                 s->blockState = TBLOCK_INPROGRESS;
    2959           8 :                 s->chain = false;
    2960           8 :                 RestoreTransactionCharacteristics();
    2961             :             }
    2962        7482 :             break;
    2963             : 
    2964             :             /*
    2965             :              * Here we are in the middle of a transaction block but one of the
    2966             :              * commands caused an abort so we do nothing but remain in the
    2967             :              * abort state.  Eventually we will get a ROLLBACK command.
    2968             :              */
    2969             :         case TBLOCK_ABORT:
    2970             :         case TBLOCK_SUBABORT:
    2971           0 :             break;
    2972             : 
    2973             :             /*
    2974             :              * Here we were in an aborted transaction block and we just got
    2975             :              * the ROLLBACK command from the user, so clean up the
    2976             :              * already-aborted transaction and return to the idle state.
    2977             :              */
    2978             :         case TBLOCK_ABORT_END:
    2979         820 :             CleanupTransaction();
    2980         820 :             s->blockState = TBLOCK_DEFAULT;
    2981         820 :             if (s->chain)
    2982             :             {
    2983           8 :                 StartTransaction();
    2984           8 :                 s->blockState = TBLOCK_INPROGRESS;
    2985           8 :                 s->chain = false;
    2986           8 :                 RestoreTransactionCharacteristics();
    2987             :             }
    2988         820 :             break;
    2989             : 
    2990             :             /*
    2991             :              * Here we were in a perfectly good transaction block but the user
    2992             :              * told us to ROLLBACK anyway.  We have to abort the transaction
    2993             :              * and then clean up.
    2994             :              */
    2995             :         case TBLOCK_ABORT_PENDING:
    2996         756 :             AbortTransaction();
    2997         756 :             CleanupTransaction();
    2998         756 :             s->blockState = TBLOCK_DEFAULT;
    2999         756 :             if (s->chain)
    3000             :             {
    3001          12 :                 StartTransaction();
    3002          12 :                 s->blockState = TBLOCK_INPROGRESS;
    3003          12 :                 s->chain = false;
    3004          12 :                 RestoreTransactionCharacteristics();
    3005             :             }
    3006         756 :             break;
    3007             : 
    3008             :             /*
    3009             :              * We are completing a "PREPARE TRANSACTION" command.  Do it and
    3010             :              * return to the idle state.
    3011             :              */
    3012             :         case TBLOCK_PREPARE:
    3013          90 :             PrepareTransaction();
    3014          26 :             s->blockState = TBLOCK_DEFAULT;
    3015          26 :             break;
    3016             : 
    3017             :             /*
    3018             :              * We were just issued a SAVEPOINT inside a transaction block.
    3019             :              * Start a subtransaction.  (DefineSavepoint already did
    3020             :              * PushTransaction, so as to have someplace to put the SUBBEGIN
    3021             :              * state.)
    3022             :              */
    3023             :         case TBLOCK_SUBBEGIN:
    3024        6980 :             StartSubTransaction();
    3025        6980 :             s->blockState = TBLOCK_SUBINPROGRESS;
    3026        6980 :             break;
    3027             : 
    3028             :             /*
    3029             :              * We were issued a RELEASE command, so we end the current
    3030             :              * subtransaction and return to the parent transaction. The parent
    3031             :              * might be ended too, so repeat till we find an INPROGRESS
    3032             :              * transaction or subtransaction.
    3033             :              */
    3034             :         case TBLOCK_SUBRELEASE:
    3035             :             do
    3036             :             {
    3037         300 :                 CommitSubTransaction();
    3038         300 :                 s = CurrentTransactionState;    /* changed by pop */
    3039         300 :             } while (s->blockState == TBLOCK_SUBRELEASE);
    3040             : 
    3041             :             Assert(s->blockState == TBLOCK_INPROGRESS ||
    3042             :                    s->blockState == TBLOCK_SUBINPROGRESS);
    3043         138 :             break;
    3044             : 
    3045             :             /*
    3046             :              * We were issued a COMMIT, so we end the current subtransaction
    3047             :              * hierarchy and perform final commit. We do this by rolling up
    3048             :              * any subtransactions into their parent, which leads to O(N^2)
    3049             :              * operations with respect to resource owners - this isn't that
    3050             :              * bad until we approach a thousands of savepoints but is
    3051             :              * necessary for correctness should after triggers create new
    3052             :              * resource owners.
    3053             :              */
    3054             :         case TBLOCK_SUBCOMMIT:
    3055             :             do
    3056             :             {
    3057         248 :                 CommitSubTransaction();
    3058         248 :                 s = CurrentTransactionState;    /* changed by pop */
    3059         248 :             } while (s->blockState == TBLOCK_SUBCOMMIT);
    3060             :             /* If we had a COMMIT command, finish off the main xact too */
    3061         212 :             if (s->blockState == TBLOCK_END)
    3062             :             {
    3063             :                 Assert(s->parent == NULL);
    3064         176 :                 CommitTransaction();
    3065         158 :                 s->blockState = TBLOCK_DEFAULT;
    3066             :             }
    3067          36 :             else if (s->blockState == TBLOCK_PREPARE)
    3068             :             {
    3069             :                 Assert(s->parent == NULL);
    3070          36 :                 PrepareTransaction();
    3071          34 :                 s->blockState = TBLOCK_DEFAULT;
    3072             :             }
    3073             :             else
    3074           0 :                 elog(ERROR, "CommitTransactionCommand: unexpected state %s",
    3075             :                      BlockStateAsString(s->blockState));
    3076         192 :             break;
    3077             : 
    3078             :             /*
    3079             :              * The current already-failed subtransaction is ending due to a
    3080             :              * ROLLBACK or ROLLBACK TO command, so pop it and recursively
    3081             :              * examine the parent (which could be in any of several states).
    3082             :              */
    3083             :         case TBLOCK_SUBABORT_END:
    3084          44 :             CleanupSubTransaction();
    3085          44 :             CommitTransactionCommand();
    3086          44 :             break;
    3087             : 
    3088             :             /*
    3089             :              * As above, but it's not dead yet, so abort first.
    3090             :              */
    3091             :         case TBLOCK_SUBABORT_PENDING:
    3092         190 :             AbortSubTransaction();
    3093         190 :             CleanupSubTransaction();
    3094         190 :             CommitTransactionCommand();
    3095         190 :             break;
    3096             : 
    3097             :             /*
    3098             :              * The current subtransaction is the target of a ROLLBACK TO
    3099             :              * command.  Abort and pop it, then start a new subtransaction
    3100             :              * with the same name.
    3101             :              */
    3102             :         case TBLOCK_SUBRESTART:
    3103             :             {
    3104             :                 char       *name;
    3105             :                 int         savepointLevel;
    3106             : 
    3107             :                 /* save name and keep Cleanup from freeing it */
    3108         286 :                 name = s->name;
    3109         286 :                 s->name = NULL;
    3110         286 :                 savepointLevel = s->savepointLevel;
    3111             : 
    3112         286 :                 AbortSubTransaction();
    3113         286 :                 CleanupSubTransaction();
    3114             : 
    3115         286 :                 DefineSavepoint(NULL);
    3116         286 :                 s = CurrentTransactionState;    /* changed by push */
    3117         286 :                 s->name = name;
    3118         286 :                 s->savepointLevel = savepointLevel;
    3119             : 
    3120             :                 /* This is the same as TBLOCK_SUBBEGIN case */
    3121             :                 AssertState(s->blockState == TBLOCK_SUBBEGIN);
    3122         286 :                 StartSubTransaction();
    3123         286 :                 s->blockState = TBLOCK_SUBINPROGRESS;
    3124             :             }
    3125         286 :             break;
    3126             : 
    3127             :             /*
    3128             :              * Same as above, but the subtransaction had already failed, so we
    3129             :              * don't need AbortSubTransaction.
    3130             :              */
    3131             :         case TBLOCK_SUBABORT_RESTART:
    3132             :             {
    3133             :                 char       *name;
    3134             :                 int         savepointLevel;
    3135             : 
    3136             :                 /* save name and keep Cleanup from freeing it */
    3137          94 :                 name = s->name;
    3138          94 :                 s->name = NULL;
    3139          94 :                 savepointLevel = s->savepointLevel;
    3140             : 
    3141          94 :                 CleanupSubTransaction();
    3142             : 
    3143          94 :                 DefineSavepoint(NULL);
    3144          94 :                 s = CurrentTransactionState;    /* changed by push */
    3145          94 :                 s->name = name;
    3146          94 :                 s->savepointLevel = savepointLevel;
    3147             : 
    3148             :                 /* This is the same as TBLOCK_SUBBEGIN case */
    3149             :                 AssertState(s->blockState == TBLOCK_SUBBEGIN);
    3150          94 :                 StartSubTransaction();
    3151          94 :                 s->blockState = TBLOCK_SUBINPROGRESS;
    3152             :             }
    3153          94 :             break;
    3154             :     }
    3155      534434 : }
    3156             : 
    3157             : /*
    3158             :  *  AbortCurrentTransaction
    3159             :  */
    3160             : void
    3161       19624 : AbortCurrentTransaction(void)
    3162             : {
    3163       19624 :     TransactionState s = CurrentTransactionState;
    3164             : 
    3165       19624 :     switch (s->blockState)
    3166             :     {
    3167             :         case TBLOCK_DEFAULT:
    3168          18 :             if (s->state == TRANS_DEFAULT)
    3169             :             {
    3170             :                 /* we are idle, so nothing to do */
    3171             :             }
    3172             :             else
    3173             :             {
    3174             :                 /*
    3175             :                  * We can get here after an error during transaction start
    3176             :                  * (state will be TRANS_START).  Need to clean up the
    3177             :                  * incompletely started transaction.  First, adjust the
    3178             :                  * low-level state to suppress warning message from
    3179             :                  * AbortTransaction.
    3180             :                  */
    3181           0 :                 if (s->state == TRANS_START)
    3182           0 :                     s->state = TRANS_INPROGRESS;
    3183           0 :                 AbortTransaction();
    3184           0 :                 CleanupTransaction();
    3185             :             }
    3186          18 :             break;
    3187             : 
    3188             :             /*
    3189             :              * If we aren't in a transaction block, we just do the basic abort
    3190             :              * & cleanup transaction.  For this purpose, we treat an implicit
    3191             :              * transaction block as if it were a simple statement.
    3192             :              */
    3193             :         case TBLOCK_STARTED:
    3194             :         case TBLOCK_IMPLICIT_INPROGRESS:
    3195       16988 :             AbortTransaction();
    3196       16988 :             CleanupTransaction();
    3197       16988 :             s->blockState = TBLOCK_DEFAULT;
    3198       16988 :             break;
    3199             : 
    3200             :             /*
    3201             :              * If we are in TBLOCK_BEGIN it means something screwed up right
    3202             :              * after reading "BEGIN TRANSACTION".  We assume that the user
    3203             :              * will interpret the error as meaning the BEGIN failed to get him
    3204             :              * into a transaction block, so we should abort and return to idle
    3205             :              * state.
    3206             :              */
    3207             :         case TBLOCK_BEGIN:
    3208           0 :             AbortTransaction();
    3209           0 :             CleanupTransaction();
    3210           0 :             s->blockState = TBLOCK_DEFAULT;
    3211           0 :             break;
    3212             : 
    3213             :             /*
    3214             :              * We are somewhere in a transaction block and we've gotten a
    3215             :              * failure, so we abort the transaction and set up the persistent
    3216             :              * ABORT state.  We will stay in ABORT until we get a ROLLBACK.
    3217             :              */
    3218             :         case TBLOCK_INPROGRESS:
    3219             :         case TBLOCK_PARALLEL_INPROGRESS:
    3220         830 :             AbortTransaction();
    3221         830 :             s->blockState = TBLOCK_ABORT;
    3222             :             /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
    3223         830 :             break;
    3224             : 
    3225             :             /*
    3226             :              * Here, we failed while trying to COMMIT.  Clean up the
    3227             :              * transaction and return to idle state (we do not want to stay in
    3228             :              * the transaction).
    3229             :              */
    3230             :         case TBLOCK_END:
    3231         348 :             AbortTransaction();
    3232         348 :             CleanupTransaction();
    3233         348 :             s->blockState = TBLOCK_DEFAULT;
    3234         348 :             break;
    3235             : 
    3236             :             /*
    3237             :              * Here, we are already in an aborted transaction state and are
    3238             :              * waiting for a ROLLBACK, but for some reason we failed again! So
    3239             :              * we just remain in the abort state.
    3240             :              */
    3241             :         case TBLOCK_ABORT:
    3242             :         case TBLOCK_SUBABORT:
    3243          50 :             break;
    3244             : 
    3245             :             /*
    3246             :              * We are in a failed transaction and we got the ROLLBACK command.
    3247             :              * We have already aborted, we just need to cleanup and go to idle
    3248             :              * state.
    3249             :              */
    3250             :         case TBLOCK_ABORT_END:
    3251           0 :             CleanupTransaction();
    3252           0 :             s->blockState = TBLOCK_DEFAULT;
    3253           0 :             break;
    3254             : 
    3255             :             /*
    3256             :              * We are in a live transaction and we got a ROLLBACK command.
    3257             :              * Abort, cleanup, go to idle state.
    3258             :              */
    3259             :         case TBLOCK_ABORT_PENDING:
    3260           0 :             AbortTransaction();
    3261           0 :             CleanupTransaction();
    3262           0 :             s->blockState = TBLOCK_DEFAULT;
    3263           0 :             break;
    3264             : 
    3265             :             /*
    3266             :              * Here, we failed while trying to PREPARE.  Clean up the
    3267             :              * transaction and return to idle state (we do not want to stay in
    3268             :              * the transaction).
    3269             :              */
    3270             :         case TBLOCK_PREPARE:
    3271          66 :             AbortTransaction();
    3272          66 :             CleanupTransaction();
    3273          66 :             s->blockState = TBLOCK_DEFAULT;
    3274          66 :             break;
    3275             : 
    3276             :             /*
    3277             :              * We got an error inside a subtransaction.  Abort just the
    3278             :              * subtransaction, and go to the persistent SUBABORT state until
    3279             :              * we get ROLLBACK.
    3280             :              */
    3281             :         case TBLOCK_SUBINPROGRESS:
    3282        1324 :             AbortSubTransaction();
    3283        1324 :             s->blockState = TBLOCK_SUBABORT;
    3284        1324 :             break;
    3285             : 
    3286             :             /*
    3287             :              * If we failed while trying to create a subtransaction, clean up
    3288             :              * the broken subtransaction and abort the parent.  The same
    3289             :              * applies if we get a failure while ending a subtransaction.
    3290             :              */
    3291             :         case TBLOCK_SUBBEGIN:
    3292             :         case TBLOCK_SUBRELEASE:
    3293             :         case TBLOCK_SUBCOMMIT:
    3294             :         case TBLOCK_SUBABORT_PENDING:
    3295             :         case TBLOCK_SUBRESTART:
    3296           0 :             AbortSubTransaction();
    3297           0 :             CleanupSubTransaction();
    3298           0 :             AbortCurrentTransaction();
    3299           0 :             break;
    3300             : 
    3301             :             /*
    3302             :              * Same as above, except the Abort() was already done.
    3303             :              */
    3304             :         case TBLOCK_SUBABORT_END:
    3305             :         case TBLOCK_SUBABORT_RESTART:
    3306           0 :             CleanupSubTransaction();
    3307           0 :             AbortCurrentTransaction();
    3308           0 :             break;
    3309             :     }
    3310       19624 : }
    3311             : 
    3312             : /*
    3313             :  *  PreventInTransactionBlock
    3314             :  *
    3315             :  *  This routine is to be called by statements that must not run inside
    3316             :  *  a transaction block, typically because they have non-rollback-able
    3317             :  *  side effects or do internal commits.
    3318             :  *
    3319             :  *  If we have already started a transaction block, issue an error; also issue
    3320             :  *  an error if we appear to be running inside a user-defined function (which
    3321             :  *  could issue more commands and possibly cause a failure after the statement
    3322             :  *  completes).  Subtransactions are verboten too.
    3323             :  *
    3324             :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3325             :  *  inside a function.  (We will always fail if this is false, but it's
    3326             :  *  convenient to centralize the check here instead of making callers do it.)
    3327             :  *  stmtType: statement type name, for error messages.
    3328             :  */
    3329             : void
    3330        5446 : PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
    3331             : {
    3332             :     /*
    3333             :      * xact block already started?
    3334             :      */
    3335        5446 :     if (IsTransactionBlock())
    3336          32 :         ereport(ERROR,
    3337             :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3338             :         /* translator: %s represents an SQL statement name */
    3339             :                  errmsg("%s cannot run inside a transaction block",
    3340             :                         stmtType)));
    3341             : 
    3342             :     /*
    3343             :      * subtransaction?
    3344             :      */
    3345        5414 :     if (IsSubTransaction())
    3346           0 :         ereport(ERROR,
    3347             :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3348             :         /* translator: %s represents an SQL statement name */
    3349             :                  errmsg("%s cannot run inside a subtransaction",
    3350             :                         stmtType)));
    3351             : 
    3352             :     /*
    3353             :      * inside a function call?
    3354             :      */
    3355        5414 :     if (!isTopLevel)
    3356           0 :         ereport(ERROR,
    3357             :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3358             :         /* translator: %s represents an SQL statement name */
    3359             :                  errmsg("%s cannot be executed from a function", stmtType)));
    3360             : 
    3361             :     /* If we got past IsTransactionBlock test, should be in default state */
    3362       10502 :     if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
    3363        5088 :         CurrentTransactionState->blockState != TBLOCK_STARTED)
    3364           0 :         elog(FATAL, "cannot prevent transaction chain");
    3365             :     /* all okay */
    3366        5414 : }
    3367             : 
    3368             : /*
    3369             :  *  WarnNoTransactionBlock
    3370             :  *  RequireTransactionBlock
    3371             :  *
    3372             :  *  These two functions allow for warnings or errors if a command is executed
    3373             :  *  outside of a transaction block.  This is useful for commands that have no
    3374             :  *  effects that persist past transaction end (and so calling them outside a
    3375             :  *  transaction block is presumably an error).  DECLARE CURSOR is an example.
    3376             :  *  While top-level transaction control commands (BEGIN/COMMIT/ABORT) and SET
    3377             :  *  that have no effect issue warnings, all other no-effect commands generate
    3378             :  *  errors.
    3379             :  *
    3380             :  *  If we appear to be running inside a user-defined function, we do not
    3381             :  *  issue anything, since the function could issue more commands that make
    3382             :  *  use of the current statement's results.  Likewise subtransactions.
    3383             :  *  Thus these are inverses for PreventInTransactionBlock.
    3384             :  *
    3385             :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3386             :  *  inside a function.
    3387             :  *  stmtType: statement type name, for warning or error messages.
    3388             :  */
    3389             : void
    3390         790 : WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
    3391             : {
    3392         790 :     CheckTransactionBlock(isTopLevel, false, stmtType);
    3393         790 : }
    3394             : 
    3395             : void
    3396        7240 : RequireTransactionBlock(bool isTopLevel, const char *stmtType)
    3397             : {
    3398        7240 :     CheckTransactionBlock(isTopLevel, true, stmtType);
    3399        7226 : }
    3400             : 
    3401             : /*
    3402             :  * This is the implementation of the above two.
    3403             :  */
    3404             : static void
    3405        8030 : CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
    3406             : {
    3407             :     /*
    3408             :      * xact block already started?
    3409             :      */
    3410        8030 :     if (IsTransactionBlock())
    3411        7990 :         return;
    3412             : 
    3413             :     /*
    3414             :      * subtransaction?
    3415             :      */
    3416          40 :     if (IsSubTransaction())
    3417           0 :         return;
    3418             : 
    3419             :     /*
    3420             :      * inside a function call?
    3421             :      */
    3422          40 :     if (!isTopLevel)
    3423          18 :         return;
    3424             : 
    3425          22 :     ereport(throwError ? ERROR : WARNING,
    3426             :             (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3427             :     /* translator: %s represents an SQL statement name */
    3428             :              errmsg("%s can only be used in transaction blocks",
    3429             :                     stmtType)));
    3430           8 :     return;
    3431             : }
    3432             : 
    3433             : /*
    3434             :  *  IsInTransactionBlock
    3435             :  *
    3436             :  *  This routine is for statements that need to behave differently inside
    3437             :  *  a transaction block than when running as single commands.  ANALYZE is
    3438             :  *  currently the only example.
    3439             :  *
    3440             :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3441             :  *  inside a function.
    3442             :  */
    3443             : bool
    3444        8926 : IsInTransactionBlock(bool isTopLevel)
    3445             : {
    3446             :     /*
    3447             :      * Return true on same conditions that would make
    3448             :      * PreventInTransactionBlock error out
    3449             :      */
    3450        8926 :     if (IsTransactionBlock())
    3451          44 :         return true;
    3452             : 
    3453        8882 :     if (IsSubTransaction())
    3454           0 :         return true;
    3455             : 
    3456        8882 :     if (!isTopLevel)
    3457          64 :         return true;
    3458             : 
    3459       17636 :     if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
    3460        8818 :         CurrentTransactionState->blockState != TBLOCK_STARTED)
    3461           0 :         return true;
    3462             : 
    3463        8818 :     return false;
    3464             : }
    3465             : 
    3466             : 
    3467             : /*
    3468             :  * Register or deregister callback functions for start- and end-of-xact
    3469             :  * operations.
    3470             :  *
    3471             :  * These functions are intended for use by dynamically loaded modules.
    3472             :  * For built-in modules we generally just hardwire the appropriate calls
    3473             :  * (mainly because it's easier to control the order that way, where needed).
    3474             :  *
    3475             :  * At transaction end, the callback occurs post-commit or post-abort, so the
    3476             :  * callback functions can only do noncritical cleanup.
    3477             :  */
    3478             : void
    3479        2064 : RegisterXactCallback(XactCallback callback, void *arg)
    3480             : {
    3481             :     XactCallbackItem *item;
    3482             : 
    3483        2064 :     item = (XactCallbackItem *)
    3484        2064 :         MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
    3485        2064 :     item->callback = callback;
    3486        2064 :     item->arg = arg;
    3487        2064 :     item->next = Xact_callbacks;
    3488        2064 :     Xact_callbacks = item;
    3489        2064 : }
    3490             : 
    3491             : void
    3492           0 : UnregisterXactCallback(XactCallback callback, void *arg)
    3493             : {
    3494             :     XactCallbackItem *item;
    3495             :     XactCallbackItem *prev;
    3496             : 
    3497           0 :     prev = NULL;
    3498           0 :     for (item = Xact_callbacks; item; prev = item, item = item->next)
    3499             :     {
    3500           0 :         if (item->callback == callback && item->arg == arg)
    3501             :         {
    3502           0 :             if (prev)
    3503           0 :                 prev->next = item->next;
    3504             :             else
    3505           0 :                 Xact_callbacks = item->next;
    3506           0 :             pfree(item);
    3507           0 :             break;
    3508             :         }
    3509             :     }
    3510           0 : }
    3511             : 
    3512             : static void
    3513      897528 : CallXactCallbacks(XactEvent event)
    3514             : {
    3515             :     XactCallbackItem *item;
    3516             : 
    3517     1132182 :     for (item = Xact_callbacks; item; item = item->next)
    3518      234656 :         item->callback(event, item->arg);
    3519      897526 : }
    3520             : 
    3521             : 
    3522             : /*
    3523             :  * Register or deregister callback functions for start- and end-of-subxact
    3524             :  * operations.
    3525             :  *
    3526             :  * Pretty much same as above, but for subtransaction events.
    3527             :  *
    3528             :  * At subtransaction end, the callback occurs post-subcommit or post-subabort,
    3529             :  * so the callback functions can only do noncritical cleanup.  At
    3530             :  * subtransaction start, the callback is called when the subtransaction has
    3531             :  * finished initializing.
    3532             :  */
    3533             : void
    3534        2064 : RegisterSubXactCallback(SubXactCallback callback, void *arg)
    3535             : {
    3536             :     SubXactCallbackItem *item;
    3537             : 
    3538        2064 :     item = (SubXactCallbackItem *)
    3539        2064 :         MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
    3540        2064 :     item->callback = callback;
    3541        2064 :     item->arg = arg;
    3542        2064 :     item->next = SubXact_callbacks;
    3543        2064 :     SubXact_callbacks = item;
    3544        2064 : }
    3545             : 
    3546             : void
    3547           0 : UnregisterSubXactCallback(SubXactCallback callback, void *arg)
    3548             : {
    3549             :     SubXactCallbackItem *item;
    3550             :     SubXactCallbackItem *prev;
    3551             : 
    3552           0 :     prev = NULL;
    3553           0 :     for (item = SubXact_callbacks; item; prev = item, item = item->next)
    3554             :     {
    3555           0 :         if (item->callback == callback && item->arg == arg)
    3556             :         {
    3557           0 :             if (prev)
    3558           0 :                 prev->next = item->next;
    3559             :             else
    3560           0 :                 SubXact_callbacks = item->next;
    3561           0 :             pfree(item);
    3562           0 :             break;
    3563             :         }
    3564             :     }
    3565           0 : }
    3566             : 
    3567             : static void
    3568       19152 : CallSubXactCallbacks(SubXactEvent event,
    3569             :                      SubTransactionId mySubid,
    3570             :                      SubTransactionId parentSubid)
    3571             : {
    3572             :     SubXactCallbackItem *item;
    3573             : 
    3574       31268 :     for (item = SubXact_callbacks; item; item = item->next)
    3575       12116 :         item->callback(event, mySubid, parentSubid, item->arg);
    3576       19152 : }
    3577             : 
    3578             : 
    3579             : /* ----------------------------------------------------------------
    3580             :  *                     transaction block support
    3581             :  * ----------------------------------------------------------------
    3582             :  */
    3583             : 
    3584             : /*
    3585             :  *  BeginTransactionBlock
    3586             :  *      This executes a BEGIN command.
    3587             :  */
    3588             : void
    3589        9898 : BeginTransactionBlock(void)
    3590             : {
    3591        9898 :     TransactionState s = CurrentTransactionState;
    3592             : 
    3593        9898 :     switch (s->blockState)
    3594             :     {
    3595             :             /*
    3596             :              * We are not inside a transaction block, so allow one to begin.
    3597             :              */
    3598             :         case TBLOCK_STARTED:
    3599        9020 :             s->blockState = TBLOCK_BEGIN;
    3600        9020 :             break;
    3601             : 
    3602             :             /*
    3603             :              * BEGIN converts an implicit transaction block to a regular one.
    3604             :              * (Note that we allow this even if we've already done some
    3605             :              * commands, which is a bit odd but matches historical practice.)
    3606             :              */
    3607             :         case TBLOCK_IMPLICIT_INPROGRESS:
    3608         878 :             s->blockState = TBLOCK_BEGIN;
    3609         878 :             break;
    3610             : 
    3611             :             /*
    3612             :              * Already a transaction block in progress.
    3613             :              */
    3614             :         case TBLOCK_INPROGRESS:
    3615             :         case TBLOCK_PARALLEL_INPROGRESS:
    3616             :         case TBLOCK_SUBINPROGRESS:
    3617             :         case TBLOCK_ABORT:
    3618             :         case TBLOCK_SUBABORT:
    3619           0 :             ereport(WARNING,
    3620             :                     (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3621             :                      errmsg("there is already a transaction in progress")));
    3622           0 :             break;
    3623             : 
    3624             :             /* These cases are invalid. */
    3625             :         case TBLOCK_DEFAULT:
    3626             :         case TBLOCK_BEGIN:
    3627             :         case TBLOCK_SUBBEGIN:
    3628             :         case TBLOCK_END:
    3629             :         case TBLOCK_SUBRELEASE:
    3630             :         case TBLOCK_SUBCOMMIT:
    3631             :         case TBLOCK_ABORT_END:
    3632             :         case TBLOCK_SUBABORT_END:
    3633             :         case TBLOCK_ABORT_PENDING:
    3634             :         case TBLOCK_SUBABORT_PENDING:
    3635             :         case TBLOCK_SUBRESTART:
    3636             :         case TBLOCK_SUBABORT_RESTART:
    3637             :         case TBLOCK_PREPARE:
    3638           0 :             elog(FATAL, "BeginTransactionBlock: unexpected state %s",
    3639             :                  BlockStateAsString(s->blockState));
    3640             :             break;
    3641             :     }
    3642        9898 : }
    3643             : 
    3644             : /*
    3645             :  *  PrepareTransactionBlock
    3646             :  *      This executes a PREPARE command.
    3647             :  *
    3648             :  * Since PREPARE may actually do a ROLLBACK, the result indicates what
    3649             :  * happened: true for PREPARE, false for ROLLBACK.
    3650             :  *
    3651             :  * Note that we don't actually do anything here except change blockState.
    3652             :  * The real work will be done in the upcoming PrepareTransaction().
    3653             :  * We do it this way because it's not convenient to change memory context,
    3654             :  * resource owner, etc while executing inside a Portal.
    3655             :  */
    3656             : bool
    3657         128 : PrepareTransactionBlock(const char *gid)
    3658             : {
    3659             :     TransactionState s;
    3660             :     bool        result;
    3661             : 
    3662             :     /* Set up to commit the current transaction */
    3663         128 :     result = EndTransactionBlock(false);
    3664             : 
    3665             :     /* If successful, change outer tblock state to PREPARE */
    3666         128 :     if (result)
    3667             :     {
    3668         126 :         s = CurrentTransactionState;
    3669             : 
    3670         300 :         while (s->parent != NULL)
    3671          48 :             s = s->parent;
    3672             : 
    3673         126 :         if (s->blockState == TBLOCK_END)
    3674             :         {
    3675             :             /* Save GID where PrepareTransaction can find it again */
    3676         126 :             prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
    3677             : 
    3678         126 :             s->blockState = TBLOCK_PREPARE;
    3679             :         }
    3680             :         else
    3681             :         {
    3682             :             /*
    3683             :              * ignore case where we are not in a transaction;
    3684             :              * EndTransactionBlock already issued a warning.
    3685             :              */
    3686             :             Assert(s->blockState == TBLOCK_STARTED ||
    3687             :                    s->blockState == TBLOCK_IMPLICIT_INPROGRESS);
    3688             :             /* Don't send back a PREPARE result tag... */
    3689           0 :             result = false;
    3690             :         }
    3691             :     }
    3692             : 
    3693         128 :     return result;
    3694             : }
    3695             : 
    3696             : /*
    3697             :  *  EndTransactionBlock
    3698             :  *      This executes a COMMIT command.
    3699             :  *
    3700             :  * Since COMMIT may actually do a ROLLBACK, the result indicates what
    3701             :  * happened: true for COMMIT, false for ROLLBACK.
    3702             :  *
    3703             :  * Note that we don't actually do anything here except change blockState.
    3704             :  * The real work will be done in the upcoming CommitTransactionCommand().
    3705             :  * We do it this way because it's not convenient to change memory context,
    3706             :  * resource owner, etc while executing inside a Portal.
    3707             :  */
    3708             : bool
    3709        8698 : EndTransactionBlock(bool chain)
    3710             : {
    3711        8698 :     TransactionState s = CurrentTransactionState;
    3712        8698 :     bool        result = false;
    3713             : 
    3714        8698 :     switch (s->blockState)
    3715             :     {
    3716             :             /*
    3717             :              * We are in a transaction block, so tell CommitTransactionCommand
    3718             :              * to COMMIT.
    3719             :              */
    3720             :         case TBLOCK_INPROGRESS:
    3721        7886 :             s->blockState = TBLOCK_END;
    3722        7886 :             result = true;
    3723        7886 :             break;
    3724             : 
    3725             :             /*
    3726             :              * We are in an implicit transaction block.  If AND CHAIN was
    3727             :              * specified, error.  Otherwise commit, but issue a warning
    3728             :              * because there was no explicit BEGIN before this.
    3729             :              */
    3730             :         case TBLOCK_IMPLICIT_INPROGRESS:
    3731          32 :             if (chain)
    3732          16 :                 ereport(ERROR,
    3733             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3734             :                          /* translator: %s represents an SQL statement name */
    3735             :                          errmsg("%s can only be used in transaction blocks",
    3736             :                                 "COMMIT AND CHAIN")));
    3737             :             else
    3738          16 :                 ereport(WARNING,
    3739             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3740             :                          errmsg("there is no transaction in progress")));
    3741          16 :             s->blockState = TBLOCK_END;
    3742          16 :             result = true;
    3743          16 :             break;
    3744             : 
    3745             :             /*
    3746             :              * We are in a failed transaction block.  Tell
    3747             :              * CommitTransactionCommand it's time to exit the block.
    3748             :              */
    3749             :         case TBLOCK_ABORT:
    3750         512 :             s->blockState = TBLOCK_ABORT_END;
    3751         512 :             break;
    3752             : 
    3753             :             /*
    3754             :              * We are in a live subtransaction block.  Set up to subcommit all
    3755             :              * open subtransactions and then commit the main transaction.
    3756             :              */
    3757             :         case TBLOCK_SUBINPROGRESS:
    3758         672 :             while (s->parent != NULL)
    3759             :             {
    3760         248 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    3761         248 :                     s->blockState = TBLOCK_SUBCOMMIT;
    3762             :                 else
    3763           0 :                     elog(FATAL, "EndTransactionBlock: unexpected state %s",
    3764             :                          BlockStateAsString(s->blockState));
    3765         248 :                 s = s->parent;
    3766             :             }
    3767         212 :             if (s->blockState == TBLOCK_INPROGRESS)
    3768         212 :                 s->blockState = TBLOCK_END;
    3769             :             else
    3770           0 :                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
    3771             :                      BlockStateAsString(s->blockState));
    3772         212 :             result = true;
    3773         212 :             break;
    3774             : 
    3775             :             /*
    3776             :              * Here we are inside an aborted subtransaction.  Treat the COMMIT
    3777             :              * as ROLLBACK: set up to abort everything and exit the main
    3778             :              * transaction.
    3779             :              */
    3780             :         case TBLOCK_SUBABORT:
    3781         120 :             while (s->parent != NULL)
    3782             :             {
    3783          40 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    3784           0 :                     s->blockState = TBLOCK_SUBABORT_PENDING;
    3785          40 :                 else if (s->blockState == TBLOCK_SUBABORT)
    3786          40 :                     s->blockState = TBLOCK_SUBABORT_END;
    3787             :                 else
    3788           0 :                     elog(FATAL, "EndTransactionBlock: unexpected state %s",
    3789             :                          BlockStateAsString(s->blockState));
    3790          40 :                 s = s->parent;
    3791             :             }
    3792          40 :             if (s->blockState == TBLOCK_INPROGRESS)
    3793          40 :                 s->blockState = TBLOCK_ABORT_PENDING;
    3794           0 :             else if (s->blockState == TBLOCK_ABORT)
    3795           0 :                 s->blockState = TBLOCK_ABORT_END;
    3796             :             else
    3797           0 :                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
    3798             :                      BlockStateAsString(s->blockState));
    3799          40 :             break;
    3800             : 
    3801             :             /*
    3802             :              * The user issued COMMIT when not inside a transaction.  For
    3803             :              * COMMIT without CHAIN, issue a WARNING, staying in
    3804             :              * TBLOCK_STARTED state.  The upcoming call to
    3805             :              * CommitTransactionCommand() will then close the transaction and
    3806             :              * put us back into the default state.  For COMMIT AND CHAIN,
    3807             :              * error.
    3808             :              */
    3809             :         case TBLOCK_STARTED:
    3810          16 :             if (chain)
    3811           4 :                 ereport(ERROR,
    3812             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3813             :                          /* translator: %s represents an SQL statement name */
    3814             :                          errmsg("%s can only be used in transaction blocks",
    3815             :                                 "COMMIT AND CHAIN")));
    3816             :             else
    3817          12 :                 ereport(WARNING,
    3818             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3819             :                          errmsg("there is no transaction in progress")));
    3820          12 :             result = true;
    3821          12 :             break;
    3822             : 
    3823             :             /*
    3824             :              * The user issued a COMMIT that somehow ran inside a parallel
    3825             :              * worker.  We can't cope with that.
    3826             :              */
    3827             :         case TBLOCK_PARALLEL_INPROGRESS:
    3828           0 :             ereport(FATAL,
    3829             :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    3830             :                      errmsg("cannot commit during a parallel operation")));
    3831             :             break;
    3832             : 
    3833             :             /* These cases are invalid. */
    3834             :         case TBLOCK_DEFAULT:
    3835             :         case TBLOCK_BEGIN:
    3836             :         case TBLOCK_SUBBEGIN:
    3837             :         case TBLOCK_END:
    3838             :         case TBLOCK_SUBRELEASE:
    3839             :         case TBLOCK_SUBCOMMIT:
    3840             :         case TBLOCK_ABORT_END:
    3841             :         case TBLOCK_SUBABORT_END:
    3842             :         case TBLOCK_ABORT_PENDING:
    3843             :         case TBLOCK_SUBABORT_PENDING:
    3844             :         case TBLOCK_SUBRESTART:
    3845             :         case TBLOCK_SUBABORT_RESTART:
    3846             :         case TBLOCK_PREPARE:
    3847           0 :             elog(FATAL, "EndTransactionBlock: unexpected state %s",
    3848             :                  BlockStateAsString(s->blockState));
    3849             :             break;
    3850             :     }
    3851             : 
    3852             :     Assert(s->blockState == TBLOCK_STARTED ||
    3853             :            s->blockState == TBLOCK_END ||
    3854             :            s->blockState == TBLOCK_ABORT_END ||
    3855             :            s->blockState == TBLOCK_ABORT_PENDING);
    3856             : 
    3857        8678 :     s->chain = chain;
    3858             : 
    3859        8678 :     return result;
    3860             : }
    3861             : 
    3862             : /*
    3863             :  *  UserAbortTransactionBlock
    3864             :  *      This executes a ROLLBACK command.
    3865             :  *
    3866             :  * As above, we don't actually do anything here except change blockState.
    3867             :  */
    3868             : void
    3869        1044 : UserAbortTransactionBlock(bool chain)
    3870             : {
    3871        1044 :     TransactionState s = CurrentTransactionState;
    3872             : 
    3873        1044 :     switch (s->blockState)
    3874             :     {
    3875             :             /*
    3876             :              * We are inside a transaction block and we got a ROLLBACK command
    3877             :              * from the user, so tell CommitTransactionCommand to abort and
    3878             :              * exit the transaction block.
    3879             :              */
    3880             :         case TBLOCK_INPROGRESS:
    3881         630 :             s->blockState = TBLOCK_ABORT_PENDING;
    3882         630 :             break;
    3883             : 
    3884             :             /*
    3885             :              * We are inside a failed transaction block and we got a ROLLBACK
    3886             :              * command from the user.  Abort processing is already done, so
    3887             :              * CommitTransactionCommand just has to cleanup and go back to
    3888             :              * idle state.
    3889             :              */
    3890             :         case TBLOCK_ABORT:
    3891         308 :             s->blockState = TBLOCK_ABORT_END;
    3892         308 :             break;
    3893             : 
    3894             :             /*
    3895             :              * We are inside a subtransaction.  Mark everything up to top
    3896             :              * level as exitable.
    3897             :              */
    3898             :         case TBLOCK_SUBINPROGRESS:
    3899             :         case TBLOCK_SUBABORT:
    3900         284 :             while (s->parent != NULL)
    3901             :             {
    3902         180 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    3903         176 :                     s->blockState = TBLOCK_SUBABORT_PENDING;
    3904           4 :                 else if (s->blockState == TBLOCK_SUBABORT)
    3905           4 :                     s->blockState = TBLOCK_SUBABORT_END;
    3906             :                 else
    3907           0 :                     elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    3908             :                          BlockStateAsString(s->blockState));
    3909         180 :                 s = s->parent;
    3910             :             }
    3911          52 :             if (s->blockState == TBLOCK_INPROGRESS)
    3912          52 :                 s->blockState = TBLOCK_ABORT_PENDING;
    3913           0 :             else if (s->blockState == TBLOCK_ABORT)
    3914           0 :                 s->blockState = TBLOCK_ABORT_END;
    3915             :             else
    3916           0 :                 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    3917             :                      BlockStateAsString(s->blockState));
    3918          52 :             break;
    3919             : 
    3920             :             /*
    3921             :              * The user issued ABORT when not inside a transaction.  For
    3922             :              * ROLLBACK without CHAIN, issue a WARNING and go to abort state.
    3923             :              * The upcoming call to CommitTransactionCommand() will then put
    3924             :              * us back into the default state.  For ROLLBACK AND CHAIN, error.
    3925             :              *
    3926             :              * We do the same thing with ABORT inside an implicit transaction,
    3927             :              * although in this case we might be rolling back actual database
    3928             :              * state changes.  (It's debatable whether we should issue a
    3929             :              * WARNING in this case, but we have done so historically.)
    3930             :              */
    3931             :         case TBLOCK_STARTED:
    3932             :         case TBLOCK_IMPLICIT_INPROGRESS:
    3933          54 :             if (chain)
    3934          20 :                 ereport(ERROR,
    3935             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3936             :                          /* translator: %s represents an SQL statement name */
    3937             :                          errmsg("%s can only be used in transaction blocks",
    3938             :                                 "ROLLBACK AND CHAIN")));
    3939             :             else
    3940          34 :                 ereport(WARNING,
    3941             :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3942             :                          errmsg("there is no transaction in progress")));
    3943          34 :             s->blockState = TBLOCK_ABORT_PENDING;
    3944          34 :             break;
    3945             : 
    3946             :             /*
    3947             :              * The user issued an ABORT that somehow ran inside a parallel
    3948             :              * worker.  We can't cope with that.
    3949             :              */
    3950             :         case TBLOCK_PARALLEL_INPROGRESS:
    3951           0 :             ereport(FATAL,
    3952             :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    3953             :                      errmsg("cannot abort during a parallel operation")));
    3954             :             break;
    3955             : 
    3956             :             /* These cases are invalid. */
    3957             :         case TBLOCK_DEFAULT:
    3958             :         case TBLOCK_BEGIN:
    3959             :         case TBLOCK_SUBBEGIN:
    3960             :         case TBLOCK_END:
    3961             :         case TBLOCK_SUBRELEASE:
    3962             :         case TBLOCK_SUBCOMMIT:
    3963             :         case TBLOCK_ABORT_END:
    3964             :         case TBLOCK_SUBABORT_END:
    3965             :         case TBLOCK_ABORT_PENDING:
    3966             :         case TBLOCK_SUBABORT_PENDING:
    3967             :         case TBLOCK_SUBRESTART:
    3968             :         case TBLOCK_SUBABORT_RESTART:
    3969             :         case TBLOCK_PREPARE:
    3970           0 :             elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    3971             :                  BlockStateAsString(s->blockState));
    3972             :             break;
    3973             :     }
    3974             : 
    3975             :     Assert(s->blockState == TBLOCK_ABORT_END ||
    3976             :            s->blockState == TBLOCK_ABORT_PENDING);
    3977             : 
    3978        1024 :     s->chain = chain;
    3979        1024 : }
    3980             : 
    3981             : /*
    3982             :  * BeginImplicitTransactionBlock
    3983             :  *      Start an implicit transaction block if we're not already in one.
    3984             :  *
    3985             :  * Unlike BeginTransactionBlock, this is called directly from the main loop
    3986             :  * in postgres.c, not within a Portal.  So we can just change blockState
    3987             :  * without a lot of ceremony.  We do not expect caller to do
    3988             :  * CommitTransactionCommand/StartTransactionCommand.
    3989             :  */
    3990             : void
    3991       74334 : BeginImplicitTransactionBlock(void)
    3992             : {
    3993       74334 :     TransactionState s = CurrentTransactionState;
    3994             : 
    3995             :     /*
    3996             :      * If we are in STARTED state (that is, no transaction block is open),
    3997             :      * switch to IMPLICIT_INPROGRESS state, creating an implicit transaction
    3998             :      * block.
    3999             :      *
    4000             :      * For caller convenience, we consider all other transaction states as
    4001             :      * legal here; otherwise the caller would need its own state check, which
    4002             :      * seems rather pointless.
    4003             :      */
    4004       74334 :     if (s->blockState == TBLOCK_STARTED)
    4005       19026 :         s->blockState = TBLOCK_IMPLICIT_INPROGRESS;
    4006       74334 : }
    4007             : 
    4008             : /*
    4009             :  * EndImplicitTransactionBlock
    4010             :  *      End an implicit transaction block, if we're in one.
    4011             :  *
    4012             :  * Like EndTransactionBlock, we just make any needed blockState change here.
    4013             :  * The real work will be done in the upcoming CommitTransactionCommand().
    4014             :  */
    4015             : void
    4016       18996 : EndImplicitTransactionBlock(void)
    4017             : {
    4018       18996 :     TransactionState s = CurrentTransactionState;
    4019             : 
    4020             :     /*
    4021             :      * If we are in IMPLICIT_INPROGRESS state, switch back to STARTED state,
    4022             :      * allowing CommitTransactionCommand to commit whatever happened during
    4023             :      * the implicit transaction block as though it were a single statement.
    4024             :      *
    4025             :      * For caller convenience, we consider all other transaction states as
    4026             :      * legal here; otherwise the caller would need its own state check, which
    4027             :      * seems rather pointless.
    4028             :      */
    4029       18996 :     if (s->blockState == TBLOCK_IMPLICIT_INPROGRESS)
    4030       18050 :         s->blockState = TBLOCK_STARTED;
    4031       18996 : }
    4032             : 
    4033             : /*
    4034             :  * DefineSavepoint
    4035             :  *      This executes a SAVEPOINT command.
    4036             :  */
    4037             : void
    4038        1170 : DefineSavepoint(const char *name)
    4039             : {
    4040        1170 :     TransactionState s = CurrentTransactionState;
    4041             : 
    4042             :     /*
    4043             :      * Workers synchronize transaction state at the beginning of each parallel
    4044             :      * operation, so we can't account for new subtransactions after that
    4045             :      * point.  (Note that this check will certainly error out if s->blockState
    4046             :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4047             :      * below.)
    4048             :      */
    4049        1170 :     if (IsInParallelMode())
    4050           0 :         ereport(ERROR,
    4051             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4052             :                  errmsg("cannot define savepoints during a parallel operation")));
    4053             : 
    4054        1170 :     switch (s->blockState)
    4055             :     {
    4056             :         case TBLOCK_INPROGRESS:
    4057             :         case TBLOCK_SUBINPROGRESS:
    4058             :             /* Normal subtransaction start */
    4059        1162 :             PushTransaction();
    4060        1162 :             s = CurrentTransactionState;    /* changed by push */
    4061             : 
    4062             :             /*
    4063             :              * Savepoint names, like the TransactionState block itself, live
    4064             :              * in TopTransactionContext.
    4065             :              */
    4066        1162 :             if (name)
    4067         782 :                 s->name = MemoryContextStrdup(TopTransactionContext, name);
    4068        1162 :             break;
    4069             : 
    4070             :             /*
    4071             :              * We disallow savepoint commands in implicit transaction blocks.
    4072             :              * There would be no great difficulty in allowing them so far as
    4073             :              * this module is concerned, but a savepoint seems inconsistent
    4074             :              * with exec_simple_query's behavior of abandoning the whole query
    4075             :              * string upon error.  Also, the point of an implicit transaction
    4076             :              * block (as opposed to a regular one) is to automatically close
    4077             :              * after an error, so it's hard to see how a savepoint would fit
    4078             :              * into that.
    4079             :              *
    4080             :              * The error messages for this are phrased as if there were no
    4081             :              * active transaction block at all, which is historical but
    4082             :              * perhaps could be improved.
    4083             :              */
    4084             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4085           8 :             ereport(ERROR,
    4086             :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4087             :             /* translator: %s represents an SQL statement name */
    4088             :                      errmsg("%s can only be used in transaction blocks",
    4089             :                             "SAVEPOINT")));
    4090             :             break;
    4091             : 
    4092             :             /* These cases are invalid. */
    4093             :         case TBLOCK_DEFAULT:
    4094             :         case TBLOCK_STARTED:
    4095             :         case TBLOCK_BEGIN:
    4096             :         case TBLOCK_PARALLEL_INPROGRESS:
    4097             :         case TBLOCK_SUBBEGIN:
    4098             :         case TBLOCK_END:
    4099             :         case TBLOCK_SUBRELEASE:
    4100             :         case TBLOCK_SUBCOMMIT:
    4101             :         case TBLOCK_ABORT:
    4102             :         case TBLOCK_SUBABORT:
    4103             :         case TBLOCK_ABORT_END:
    4104             :         case TBLOCK_SUBABORT_END:
    4105             :         case TBLOCK_ABORT_PENDING:
    4106             :         case TBLOCK_SUBABORT_PENDING:
    4107             :         case TBLOCK_SUBRESTART:
    4108             :         case TBLOCK_SUBABORT_RESTART:
    4109             :         case TBLOCK_PREPARE:
    4110           0 :             elog(FATAL, "DefineSavepoint: unexpected state %s",
    4111             :                  BlockStateAsString(s->blockState));
    4112             :             break;
    4113             :     }
    4114        1162 : }
    4115             : 
    4116             : /*
    4117             :  * ReleaseSavepoint
    4118             :  *      This executes a RELEASE command.
    4119             :  *
    4120             :  * As above, we don't actually do anything here except change blockState.
    4121             :  */
    4122             : void
    4123         142 : ReleaseSavepoint(const char *name)
    4124             : {
    4125         142 :     TransactionState s = CurrentTransactionState;
    4126             :     TransactionState target,
    4127             :                 xact;
    4128             : 
    4129             :     /*
    4130             :      * Workers synchronize transaction state at the beginning of each parallel
    4131             :      * operation, so we can't account for transaction state change after that
    4132             :      * point.  (Note that this check will certainly error out if s->blockState
    4133             :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4134             :      * below.)
    4135             :      */
    4136         142 :     if (IsInParallelMode())
    4137           0 :         ereport(ERROR,
    4138             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4139             :                  errmsg("cannot release savepoints during a parallel operation")));
    4140             : 
    4141         142 :     switch (s->blockState)
    4142             :     {
    4143             :             /*
    4144             :              * We can't release a savepoint if there is no savepoint defined.
    4145             :              */
    4146             :         case TBLOCK_INPROGRESS:
    4147           0 :             ereport(ERROR,
    4148             :                     (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4149             :                      errmsg("savepoint \"%s\" does not exist", name)));
    4150             :             break;
    4151             : 
    4152             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4153             :             /* See comment about implicit transactions in DefineSavepoint */
    4154           4 :             ereport(ERROR,
    4155             :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4156             :             /* translator: %s represents an SQL statement name */
    4157             :                      errmsg("%s can only be used in transaction blocks",
    4158             :                             "RELEASE SAVEPOINT")));
    4159             :             break;
    4160             : 
    4161             :             /*
    4162             :              * We are in a non-aborted subtransaction.  This is the only valid
    4163             :              * case.
    4164             :              */
    4165             :         case TBLOCK_SUBINPROGRESS:
    4166         138 :             break;
    4167             : 
    4168             :             /* These cases are invalid. */
    4169             :         case TBLOCK_DEFAULT:
    4170             :         case TBLOCK_STARTED:
    4171             :         case TBLOCK_BEGIN:
    4172             :         case TBLOCK_PARALLEL_INPROGRESS:
    4173             :         case TBLOCK_SUBBEGIN:
    4174             :         case TBLOCK_END:
    4175             :         case TBLOCK_SUBRELEASE:
    4176             :         case TBLOCK_SUBCOMMIT:
    4177             :         case TBLOCK_ABORT:
    4178             :         case TBLOCK_SUBABORT:
    4179             :         case TBLOCK_ABORT_END:
    4180             :         case TBLOCK_SUBABORT_END:
    4181             :         case TBLOCK_ABORT_PENDING:
    4182             :         case TBLOCK_SUBABORT_PENDING:
    4183             :         case TBLOCK_SUBRESTART:
    4184             :         case TBLOCK_SUBABORT_RESTART:
    4185             :         case TBLOCK_PREPARE:
    4186           0 :             elog(FATAL, "ReleaseSavepoint: unexpected state %s",
    4187             :                  BlockStateAsString(s->blockState));
    4188             :             break;
    4189             :     }
    4190             : 
    4191         300 :     for (target = s; PointerIsValid(target); target = target->parent)
    4192             :     {
    4193         300 :         if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
    4194         138 :             break;
    4195             :     }
    4196             : 
    4197         138 :     if (!PointerIsValid(target))
    4198           0 :         ereport(ERROR,
    4199             :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4200             :                  errmsg("savepoint \"%s\" does not exist", name)));
    4201             : 
    4202             :     /* disallow crossing savepoint level boundaries */
    4203         138 :     if (target->savepointLevel != s->savepointLevel)
    4204           0 :         ereport(ERROR,
    4205             :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4206             :                  errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
    4207             : 
    4208             :     /*
    4209             :      * Mark "commit pending" all subtransactions up to the target
    4210             :      * subtransaction.  The actual commits will happen when control gets to
    4211             :      * CommitTransactionCommand.
    4212             :      */
    4213         138 :     xact = CurrentTransactionState;
    4214             :     for (;;)
    4215             :     {
    4216         162 :         Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
    4217         300 :         xact->blockState = TBLOCK_SUBRELEASE;
    4218         300 :         if (xact == target)
    4219         138 :             break;
    4220         162 :         xact = xact->parent;
    4221             :         Assert(PointerIsValid(xact));
    4222             :     }
    4223         138 : }
    4224             : 
    4225             : /*
    4226             :  * RollbackToSavepoint
    4227             :  *      This executes a ROLLBACK TO <savepoint> command.
    4228             :  *
    4229             :  * As above, we don't actually do anything here except change blockState.
    4230             :  */
    4231             : void
    4232         388 : RollbackToSavepoint(const char *name)
    4233             : {
    4234         388 :     TransactionState s = CurrentTransactionState;
    4235             :     TransactionState target,
    4236             :                 xact;
    4237             : 
    4238             :     /*
    4239             :      * Workers synchronize transaction state at the beginning of each parallel
    4240             :      * operation, so we can't account for transaction state change after that
    4241             :      * point.  (Note that this check will certainly error out if s->blockState
    4242             :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4243             :      * below.)
    4244             :      */
    4245         388 :     if (IsInParallelMode())
    4246           0 :         ereport(ERROR,
    4247             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4248             :                  errmsg("cannot rollback to savepoints during a parallel operation")));
    4249             : 
    4250         388 :     switch (s->blockState)
    4251             :     {
    4252             :             /*
    4253             :              * We can't rollback to a savepoint if there is no savepoint
    4254             :              * defined.
    4255             :              */
    4256             :         case TBLOCK_INPROGRESS:
    4257             :         case TBLOCK_ABORT:
    4258           4 :             ereport(ERROR,
    4259             :                     (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4260             :                      errmsg("savepoint \"%s\" does not exist", name)));
    4261             :             break;
    4262             : 
    4263             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4264             :             /* See comment about implicit transactions in DefineSavepoint */
    4265           4 :             ereport(ERROR,
    4266             :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4267             :             /* translator: %s represents an SQL statement name */
    4268             :                      errmsg("%s can only be used in transaction blocks",
    4269             :                             "ROLLBACK TO SAVEPOINT")));
    4270             :             break;
    4271             : 
    4272             :             /*
    4273             :              * There is at least one savepoint, so proceed.
    4274             :              */
    4275             :         case TBLOCK_SUBINPROGRESS:
    4276             :         case TBLOCK_SUBABORT:
    4277         380 :             break;
    4278             : 
    4279             :             /* These cases are invalid. */
    4280             :         case TBLOCK_DEFAULT:
    4281             :         case TBLOCK_STARTED:
    4282             :         case TBLOCK_BEGIN:
    4283             :         case TBLOCK_PARALLEL_INPROGRESS:
    4284             :         case TBLOCK_SUBBEGIN:
    4285             :         case TBLOCK_END:
    4286             :         case TBLOCK_SUBRELEASE:
    4287             :         case TBLOCK_SUBCOMMIT:
    4288             :         case TBLOCK_ABORT_END:
    4289             :         case TBLOCK_SUBABORT_END:
    4290             :         case TBLOCK_ABORT_PENDING:
    4291             :         case TBLOCK_SUBABORT_PENDING:
    4292             :         case TBLOCK_SUBRESTART:
    4293             :         case TBLOCK_SUBABORT_RESTART:
    4294             :         case TBLOCK_PREPARE:
    4295           0 :             elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4296             :                  BlockStateAsString(s->blockState));
    4297             :             break;
    4298             :     }
    4299             : 
    4300         394 :     for (target = s; PointerIsValid(target); target = target->parent)
    4301             :     {
    4302         394 :         if (PointerIsValid(target->name) && strcmp(target->name, name) == 0)
    4303         380 :             break;
    4304             :     }
    4305             : 
    4306         380 :     if (!PointerIsValid(target))
    4307           0 :         ereport(ERROR,
    4308             :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4309             :                  errmsg("savepoint \"%s\" does not exist", name)));
    4310             : 
    4311             :     /* disallow crossing savepoint level boundaries */
    4312         380 :     if (target->savepointLevel != s->savepointLevel)
    4313           0 :         ereport(ERROR,
    4314             :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4315             :                  errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
    4316             : 
    4317             :     /*
    4318             :      * Mark "abort pending" all subtransactions up to the target
    4319             :      * subtransaction.  The actual aborts will happen when control gets to
    4320             :      * CommitTransactionCommand.
    4321             :      */
    4322         380 :     xact = CurrentTransactionState;
    4323             :     for (;;)
    4324             :     {
    4325         408 :         if (xact == target)
    4326         380 :             break;
    4327          14 :         if (xact->blockState == TBLOCK_SUBINPROGRESS)
    4328          14 :             xact->blockState = TBLOCK_SUBABORT_PENDING;
    4329           0 :         else if (xact->blockState == TBLOCK_SUBABORT)
    4330           0 :             xact->blockState = TBLOCK_SUBABORT_END;
    4331             :         else
    4332           0 :             elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4333             :                  BlockStateAsString(xact->blockState));
    4334          14 :         xact = xact->parent;
    4335             :         Assert(PointerIsValid(xact));
    4336             :     }
    4337             : 
    4338             :     /* And mark the target as "restart pending" */
    4339         380 :     if (xact->blockState == TBLOCK_SUBINPROGRESS)
    4340         286 :         xact->blockState = TBLOCK_SUBRESTART;
    4341          94 :     else if (xact->blockState == TBLOCK_SUBABORT)
    4342          94 :         xact->blockState = TBLOCK_SUBABORT_RESTART;
    4343             :     else
    4344           0 :         elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4345             :              BlockStateAsString(xact->blockState));
    4346         380 : }
    4347             : 
    4348             : /*
    4349             :  * BeginInternalSubTransaction
    4350             :  *      This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
    4351             :  *      TBLOCK_IMPLICIT_INPROGRESS, TBLOCK_END, and TBLOCK_PREPARE states,
    4352             :  *      and therefore it can safely be used in functions that might be called
    4353             :  *      when not inside a BEGIN block or when running deferred triggers at
    4354             :  *      COMMIT/PREPARE time.  Also, it automatically does
    4355             :  *      CommitTransactionCommand/StartTransactionCommand instead of expecting
    4356             :  *      the caller to do it.
    4357             :  */
    4358             : void
    4359        6198 : BeginInternalSubTransaction(const char *name)
    4360             : {
    4361        6198 :     TransactionState s = CurrentTransactionState;
    4362             : 
    4363             :     /*
    4364             :      * Workers synchronize transaction state at the beginning of each parallel
    4365             :      * operation, so we can't account for new subtransactions after that
    4366             :      * point. We might be able to make an exception for the type of
    4367             :      * subtransaction established by this function, which is typically used in
    4368             :      * contexts where we're going to release or roll back the subtransaction
    4369             :      * before proceeding further, so that no enduring change to the
    4370             :      * transaction state occurs. For now, however, we prohibit this case along
    4371             :      * with all the others.
    4372             :      */
    4373        6198 :     if (IsInParallelMode())
    4374           0 :         ereport(ERROR,
    4375             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4376             :                  errmsg("cannot start subtransactions during a parallel operation")));
    4377             : 
    4378        6198 :     switch (s->blockState)
    4379             :     {
    4380             :         case TBLOCK_STARTED:
    4381             :         case TBLOCK_INPROGRESS:
    4382             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4383             :         case TBLOCK_END:
    4384             :         case TBLOCK_PREPARE:
    4385             :         case TBLOCK_SUBINPROGRESS:
    4386             :             /* Normal subtransaction start */
    4387        6198 :             PushTransaction();
    4388        6198 :             s = CurrentTransactionState;    /* changed by push */
    4389             : 
    4390             :             /*
    4391             :              * Savepoint names, like the TransactionState block itself, live
    4392             :              * in TopTransactionContext.
    4393             :              */
    4394        6198 :             if (name)
    4395        1186 :                 s->name = MemoryContextStrdup(TopTransactionContext, name);
    4396        6198 :             break;
    4397             : 
    4398             :             /* These cases are invalid. */
    4399             :         case TBLOCK_DEFAULT:
    4400             :         case TBLOCK_BEGIN:
    4401             :         case TBLOCK_PARALLEL_INPROGRESS:
    4402             :         case TBLOCK_SUBBEGIN:
    4403             :         case TBLOCK_SUBRELEASE:
    4404             :         case TBLOCK_SUBCOMMIT:
    4405             :         case TBLOCK_ABORT:
    4406             :         case TBLOCK_SUBABORT:
    4407             :         case TBLOCK_ABORT_END:
    4408             :         case TBLOCK_SUBABORT_END:
    4409             :         case TBLOCK_ABORT_PENDING:
    4410             :         case TBLOCK_SUBABORT_PENDING:
    4411             :         case TBLOCK_SUBRESTART:
    4412             :         case TBLOCK_SUBABORT_RESTART:
    4413           0 :             elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
    4414             :                  BlockStateAsString(s->blockState));
    4415             :             break;
    4416             :     }
    4417             : 
    4418        6198 :     CommitTransactionCommand();
    4419        6198 :     StartTransactionCommand();
    4420        6198 : }
    4421             : 
    4422             : /*
    4423             :  * ReleaseCurrentSubTransaction
    4424             :  *
    4425             :  * RELEASE (ie, commit) the innermost subtransaction, regardless of its
    4426             :  * savepoint name (if any).
    4427             :  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
    4428             :  */
    4429             : void
    4430        3884 : ReleaseCurrentSubTransaction(void)
    4431             : {
    4432        3884 :     TransactionState s = CurrentTransactionState;
    4433             : 
    4434             :     /*
    4435             :      * Workers synchronize transaction state at the beginning of each parallel
    4436             :      * operation, so we can't account for commit of subtransactions after that
    4437             :      * point.  This should not happen anyway.  Code calling this would
    4438             :      * typically have called BeginInternalSubTransaction() first, failing
    4439             :      * there.
    4440             :      */
    4441        3884 :     if (IsInParallelMode())
    4442           0 :         ereport(ERROR,
    4443             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4444             :                  errmsg("cannot commit subtransactions during a parallel operation")));
    4445             : 
    4446        3884 :     if (s->blockState != TBLOCK_SUBINPROGRESS)
    4447           0 :         elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
    4448             :              BlockStateAsString(s->blockState));
    4449             :     Assert(s->state == TRANS_INPROGRESS);
    4450        3884 :     MemoryContextSwitchTo(CurTransactionContext);
    4451        3884 :     CommitSubTransaction();
    4452        3884 :     s = CurrentTransactionState;    /* changed by pop */
    4453             :     Assert(s->state == TRANS_INPROGRESS);
    4454        3884 : }
    4455             : 
    4456             : /*
    4457             :  * RollbackAndReleaseCurrentSubTransaction
    4458             :  *
    4459             :  * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
    4460             :  * of its savepoint name (if any).
    4461             :  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
    4462             :  */
    4463             : void
    4464        2314 : RollbackAndReleaseCurrentSubTransaction(void)
    4465             : {
    4466        2314 :     TransactionState s = CurrentTransactionState;
    4467             : 
    4468             :     /*
    4469             :      * Unlike ReleaseCurrentSubTransaction(), this is nominally permitted
    4470             :      * during parallel operations.  That's because we may be in the master,
    4471             :      * recovering from an error thrown while we were in parallel mode.  We
    4472             :      * won't reach here in a worker, because BeginInternalSubTransaction()
    4473             :      * will have failed.
    4474             :      */
    4475             : 
    4476        2314 :     switch (s->blockState)
    4477             :     {
    4478             :             /* Must be in a subtransaction */
    4479             :         case TBLOCK_SUBINPROGRESS:
    4480             :         case TBLOCK_SUBABORT:
    4481        2314 :             break;
    4482             : 
    4483             :             /* These cases are invalid. */
    4484             :         case TBLOCK_DEFAULT:
    4485             :         case TBLOCK_STARTED:
    4486             :         case TBLOCK_BEGIN:
    4487             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4488             :         case TBLOCK_PARALLEL_INPROGRESS:
    4489             :         case TBLOCK_SUBBEGIN:
    4490             :         case TBLOCK_INPROGRESS:
    4491             :         case TBLOCK_END:
    4492             :         case TBLOCK_SUBRELEASE:
    4493             :         case TBLOCK_SUBCOMMIT:
    4494             :         case TBLOCK_ABORT:
    4495             :         case TBLOCK_ABORT_END:
    4496             :         case TBLOCK_SUBABORT_END:
    4497             :         case TBLOCK_ABORT_PENDING:
    4498             :         case TBLOCK_SUBABORT_PENDING:
    4499             :         case TBLOCK_SUBRESTART:
    4500             :         case TBLOCK_SUBABORT_RESTART:
    4501             :         case TBLOCK_PREPARE:
    4502           0 :             elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
    4503             :                  BlockStateAsString(s->blockState));
    4504             :             break;
    4505             :     }
    4506             : 
    4507             :     /*
    4508             :      * Abort the current subtransaction, if needed.
    4509             :      */
    4510        2314 :     if (s->blockState == TBLOCK_SUBINPROGRESS)
    4511        1128 :         AbortSubTransaction();
    4512             : 
    4513             :     /* And clean it up, too */
    4514        2314 :     CleanupSubTransaction();
    4515             : 
    4516        2314 :     s = CurrentTransactionState;    /* changed by pop */
    4517             :     AssertState(s->blockState == TBLOCK_SUBINPROGRESS ||
    4518             :                 s->blockState == TBLOCK_INPROGRESS ||
    4519             :                 s->blockState == TBLOCK_IMPLICIT_INPROGRESS ||
    4520             :                 s->blockState == TBLOCK_STARTED);
    4521        2314 : }
    4522             : 
    4523             : /*
    4524             :  *  AbortOutOfAnyTransaction
    4525             :  *
    4526             :  *  This routine is provided for error recovery purposes.  It aborts any
    4527             :  *  active transaction or transaction block, leaving the system in a known
    4528             :  *  idle state.
    4529             :  */
    4530             : void
    4531       10452 : AbortOutOfAnyTransaction(void)
    4532             : {
    4533       10452 :     TransactionState s = CurrentTransactionState;
    4534             : 
    4535             :     /* Ensure we're not running in a doomed memory context */
    4536       10452 :     AtAbort_Memory();
    4537             : 
    4538             :     /*
    4539             :      * Get out of any transaction or nested transaction
    4540             :      */
    4541             :     do
    4542             :     {
    4543       10452 :         switch (s->blockState)
    4544             :         {
    4545             :             case TBLOCK_DEFAULT:
    4546       10082 :                 if (s->state == TRANS_DEFAULT)
    4547             :                 {
    4548             :                     /* Not in a transaction, do nothing */
    4549             :                 }
    4550             :                 else
    4551             :                 {
    4552             :                     /*
    4553             :                      * We can get here after an error during transaction start
    4554             :                      * (state will be TRANS_START).  Need to clean up the
    4555             :                      * incompletely started transaction.  First, adjust the
    4556             :                      * low-level state to suppress warning message from
    4557             :                      * AbortTransaction.
    4558             :                      */
    4559           0 :                     if (s->state == TRANS_START)
    4560           0 :                         s->state = TRANS_INPROGRESS;
    4561           0 :                     AbortTransaction();
    4562           0 :                     CleanupTransaction();
    4563             :                 }
    4564       10082 :                 break;
    4565             :             case TBLOCK_STARTED:
    4566             :             case TBLOCK_BEGIN:
    4567             :             case TBLOCK_INPROGRESS:
    4568             :             case TBLOCK_IMPLICIT_INPROGRESS:
    4569             :             case TBLOCK_PARALLEL_INPROGRESS:
    4570             :             case TBLOCK_END:
    4571             :             case TBLOCK_ABORT_PENDING:
    4572             :             case TBLOCK_PREPARE:
    4573             :                 /* In a transaction, so clean up */
    4574         360 :                 AbortTransaction();
    4575         360 :                 CleanupTransaction();
    4576         360 :                 s->blockState = TBLOCK_DEFAULT;
    4577         360 :                 break;
    4578             :             case TBLOCK_ABORT:
    4579             :             case TBLOCK_ABORT_END:
    4580             : 
    4581             :                 /*
    4582             :                  * AbortTransaction is already done, still need Cleanup.
    4583             :                  * However, if we failed partway through running ROLLBACK,
    4584             :                  * there will be an active portal running that command, which
    4585             :                  * we need to shut down before doing CleanupTransaction.
    4586             :                  */
    4587          10 :                 AtAbort_Portals();
    4588          10 :                 CleanupTransaction();
    4589          10 :                 s->blockState = TBLOCK_DEFAULT;
    4590          10 :                 break;
    4591             : 
    4592             :                 /*
    4593             :                  * In a subtransaction, so clean it up and abort parent too
    4594             :                  */
    4595             :             case TBLOCK_SUBBEGIN:
    4596             :             case TBLOCK_SUBINPROGRESS:
    4597             :             case TBLOCK_SUBRELEASE:
    4598             :             case TBLOCK_SUBCOMMIT:
    4599             :             case TBLOCK_SUBABORT_PENDING:
    4600             :             case TBLOCK_SUBRESTART:
    4601           0 :                 AbortSubTransaction();
    4602           0 :                 CleanupSubTransaction();
    4603           0 :                 s = CurrentTransactionState;    /* changed by pop */
    4604           0 :                 break;
    4605             : 
    4606             :             case TBLOCK_SUBABORT:
    4607             :             case TBLOCK_SUBABORT_END:
    4608             :             case TBLOCK_SUBABORT_RESTART:
    4609             :                 /* As above, but AbortSubTransaction already done */
    4610           0 :                 if (s->curTransactionOwner)
    4611             :                 {
    4612             :                     /* As in TBLOCK_ABORT, might have a live portal to zap */
    4613           0 :                     AtSubAbort_Portals(s->subTransactionId,
    4614           0 :                                        s->parent->subTransactionId,
    4615             :                                        s->curTransactionOwner,
    4616           0 :                                        s->parent->curTransactionOwner);
    4617             :                 }
    4618           0 :                 CleanupSubTransaction();
    4619           0 :                 s = CurrentTransactionState;    /* changed by pop */
    4620           0 :                 break;
    4621             :         }
    4622       10452 :     } while (s->blockState != TBLOCK_DEFAULT);
    4623             : 
    4624             :     /* Should be out of all subxacts now */
    4625             :     Assert(s->parent == NULL);
    4626             : 
    4627             :     /* If we didn't actually have anything to do, revert to TopMemoryContext */
    4628       10452 :     AtCleanup_Memory();
    4629       10452 : }
    4630             : 
    4631             : /*
    4632             :  * IsTransactionBlock --- are we within a transaction block?
    4633             :  */
    4634             : bool
    4635      320732 : IsTransactionBlock(void)
    4636             : {
    4637      320732 :     TransactionState s = CurrentTransactionState;
    4638             : 
    4639      320732 :     if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
    4640      233212 :         return false;
    4641             : 
    4642       87520 :     return true;
    4643             : }
    4644             : 
    4645             : /*
    4646             :  * IsTransactionOrTransactionBlock --- are we within either a transaction
    4647             :  * or a transaction block?  (The backend is only really "idle" when this
    4648             :  * returns false.)
    4649             :  *
    4650             :  * This should match up with IsTransactionBlock and IsTransactionState.
    4651             :  */
    4652             : bool
    4653      463528 : IsTransactionOrTransactionBlock(void)
    4654             : {
    4655      463528 :     TransactionState s = CurrentTransactionState;
    4656             : 
    4657      463528 :     if (s->blockState == TBLOCK_DEFAULT)
    4658      373642 :         return false;
    4659             : 
    4660       89886 :     return true;
    4661             : }
    4662             : 
    4663             : /*
    4664             :  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
    4665             :  */
    4666             : char
    4667      312622 : TransactionBlockStatusCode(void)
    4668             : {
    4669      312622 :     TransactionState s = CurrentTransactionState;
    4670             : 
    4671      312622 :     switch (s->blockState)
    4672             :     {
    4673             :         case TBLOCK_DEFAULT:
    4674             :         case TBLOCK_STARTED:
    4675      223376 :             return 'I';         /* idle --- not in transaction */
    4676             :         case TBLOCK_BEGIN:
    4677             :         case TBLOCK_SUBBEGIN:
    4678             :         case TBLOCK_INPROGRESS:
    4679             :         case TBLOCK_IMPLICIT_INPROGRESS:
    4680             :         case TBLOCK_PARALLEL_INPROGRESS:
    4681             :         case TBLOCK_SUBINPROGRESS:
    4682             :         case TBLOCK_END:
    4683             :         case TBLOCK_SUBRELEASE:
    4684             :         case TBLOCK_SUBCOMMIT:
    4685             :         case TBLOCK_PREPARE:
    4686       88228 :             return 'T';         /* in transaction */
    4687             :         case TBLOCK_ABORT:
    4688             :         case TBLOCK_SUBABORT:
    4689             :         case TBLOCK_ABORT_END:
    4690             :         case TBLOCK_SUBABORT_END:
    4691             :         case TBLOCK_ABORT_PENDING:
    4692             :         case TBLOCK_SUBABORT_PENDING:
    4693             :         case TBLOCK_SUBRESTART:
    4694             :         case TBLOCK_SUBABORT_RESTART:
    4695        1018 :             return 'E';         /* in failed transaction */
    4696             :     }
    4697             : 
    4698             :     /* should never get here */
    4699           0 :     elog(FATAL, "invalid transaction block state: %s",
    4700             :          BlockStateAsString(s->blockState));
    4701             :     return 0;                   /* keep compiler quiet */
    4702             : }
    4703             : 
    4704             : /*
    4705             :  * IsSubTransaction
    4706             :  */
    4707             : bool
    4708       34194 : IsSubTransaction(void)
    4709             : {
    4710       34194 :     TransactionState s = CurrentTransactionState;
    4711             : 
    4712       34194 :     if (s->nestingLevel >= 2)
    4713          22 :         return true;
    4714             : 
    4715       34172 :     return false;
    4716             : }
    4717             : 
    4718             : /*
    4719             :  * StartSubTransaction
    4720             :  *
    4721             :  * If you're wondering why this is separate from PushTransaction: it's because
    4722             :  * we can't conveniently do this stuff right inside DefineSavepoint.  The
    4723             :  * SAVEPOINT utility command will be executed inside a Portal, and if we
    4724             :  * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
    4725             :  * the Portal will undo those settings.  So we make DefineSavepoint just
    4726             :  * push a dummy transaction block, and when control returns to the main
    4727             :  * idle loop, CommitTransactionCommand will be called, and we'll come here
    4728             :  * to finish starting the subtransaction.
    4729             :  */
    4730             : static void
    4731        7360 : StartSubTransaction(void)
    4732             : {
    4733        7360 :     TransactionState s = CurrentTransactionState;
    4734             : 
    4735        7360 :     if (s->state != TRANS_DEFAULT)
    4736           0 :         elog(WARNING, "StartSubTransaction while in %s state",
    4737             :              TransStateAsString(s->state));
    4738             : 
    4739        7360 :     s->state = TRANS_START;
    4740             : 
    4741             :     /*
    4742             :      * Initialize subsystems for new subtransaction
    4743             :      *
    4744             :      * must initialize resource-management stuff first
    4745             :      */
    4746        7360 :     AtSubStart_Memory();
    4747        7360 :     AtSubStart_ResourceOwner();
    4748        7360 :     AfterTriggerBeginSubXact();
    4749             : 
    4750        7360 :     s->state = TRANS_INPROGRESS;
    4751             : 
    4752             :     /*
    4753             :      * Call start-of-subxact callbacks
    4754             :      */
    4755        7360 :     CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
    4756        7360 :                          s->parent->subTransactionId);
    4757             : 
    4758        7360 :     ShowTransactionState("StartSubTransaction");
    4759        7360 : }
    4760             : 
    4761             : /*
    4762             :  * CommitSubTransaction
    4763             :  *
    4764             :  *  The caller has to make sure to always reassign CurrentTransactionState
    4765             :  *  if it has a local pointer to it after calling this function.
    4766             :  */
    4767             : static void
    4768        4432 : CommitSubTransaction(void)
    4769             : {
    4770        4432 :     TransactionState s = CurrentTransactionState;
    4771             : 
    4772        4432 :     ShowTransactionState("CommitSubTransaction");
    4773             : 
    4774        4432 :     if (s->state != TRANS_INPROGRESS)
    4775           0 :         elog(WARNING, "CommitSubTransaction while in %s state",
    4776             :              TransStateAsString(s->state));
    4777             : 
    4778             :     /* Pre-commit processing goes here */
    4779             : 
    4780        4432 :     CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
    4781        4432 :                          s->parent->subTransactionId);
    4782             : 
    4783             :     /* If in parallel mode, clean up workers and exit parallel mode. */
    4784        4432 :     if (IsInParallelMode())
    4785             :     {
    4786           0 :         AtEOSubXact_Parallel(true, s->subTransactionId);
    4787           0 :         s->parallelModeLevel = 0;
    4788             :     }
    4789             : 
    4790             :     /* Do the actual "commit", such as it is */
    4791        4432 :     s->state = TRANS_COMMIT;
    4792             : 
    4793             :     /* Must CCI to ensure commands of subtransaction are seen as done */
    4794        4432 :     CommandCounterIncrement();
    4795             : 
    4796             :     /*
    4797             :      * Prior to 8.4 we marked subcommit in clog at this point.  We now only
    4798             :      * perform that step, if required, as part of the atomic update of the
    4799             :      * whole transaction tree at top level commit or abort.
    4800             :      */
    4801             : 
    4802             :     /* Post-commit cleanup */
    4803        4432 :     if (FullTransactionIdIsValid(s->fullTransactionId))
    4804        3666 :         AtSubCommit_childXids();
    4805        4432 :     AfterTriggerEndSubXact(true);
    4806        8864 :     AtSubCommit_Portals(s->subTransactionId,
    4807        4432 :                         s->parent->subTransactionId,
    4808        4432 :                         s->parent->curTransactionOwner);
    4809        4432 :     AtEOSubXact_LargeObject(true, s->subTransactionId,
    4810        4432 :                             s->parent->subTransactionId);
    4811        4432 :     AtSubCommit_Notify();
    4812             : 
    4813        4432 :     CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
    4814        4432 :                          s->parent->subTransactionId);
    4815             : 
    4816        4432 :     ResourceOwnerRelease(s->curTransactionOwner,
    4817             :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    4818             :                          true, false);
    4819        4432 :     AtEOSubXact_RelationCache(true, s->subTransactionId,
    4820        4432 :                               s->parent->subTransactionId);
    4821        4432 :     AtEOSubXact_Inval(true);
    4822        4432 :     AtSubCommit_smgr();
    4823             : 
    4824             :     /*
    4825             :      * The only lock we actually release here is the subtransaction XID lock.
    4826             :      */
    4827        4432 :     CurrentResourceOwner = s->curTransactionOwner;
    4828        4432 :     if (FullTransactionIdIsValid(s->fullTransactionId))
    4829        3666 :         XactLockTableDelete(XidFromFullTransactionId(s->fullTransactionId));
    4830             : 
    4831             :     /*
    4832             :      * Other locks should get transferred to their parent resource owner.
    4833             :      */
    4834        4432 :     ResourceOwnerRelease(s->curTransactionOwner,
    4835             :                          RESOURCE_RELEASE_LOCKS,
    4836             :                          true, false);
    4837        4432 :     ResourceOwnerRelease(s->curTransactionOwner,
    4838             :                          RESOURCE_RELEASE_AFTER_LOCKS,
    4839             :                          true, false);
    4840             : 
    4841        4432 :     AtEOXact_GUC(true, s->gucNestLevel);
    4842        4432 :     AtEOSubXact_SPI(true, s->subTransactionId);
    4843        4432 :     AtEOSubXact_on_commit_actions(true, s->subTransactionId,
    4844        4432 :                                   s->parent->subTransactionId);
    4845        4432 :     AtEOSubXact_Namespace(true, s->subTransactionId,
    4846        4432 :                           s->parent->subTransactionId);
    4847        4432 :     AtEOSubXact_Files(true, s->subTransactionId,
    4848        4432 :                       s->parent->subTransactionId);
    4849        4432 :     AtEOSubXact_HashTables(true, s->nestingLevel);
    4850        4432 :     AtEOSubXact_PgStat(true, s->nestingLevel);
    4851        4432 :     AtSubCommit_Snapshot(s->nestingLevel);
    4852        4432 :     AtEOSubXact_ApplyLauncher(true, s->nestingLevel);
    4853             : 
    4854             :     /*
    4855             :      * We need to restore the upper transaction's read-only state, in case the
    4856             :      * upper is read-write while the child is read-only; GUC will incorrectly
    4857             :      * think it should leave the child state in place.
    4858             :      */
    4859        4432 :     XactReadOnly = s->prevXactReadOnly;
    4860             : 
    4861        4432 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    4862        4432 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    4863        4432 :     ResourceOwnerDelete(s->curTransactionOwner);
    4864        4432 :     s->curTransactionOwner = NULL;
    4865             : 
    4866        4432 :     AtSubCommit_Memory();
    4867             : 
    4868        4432 :     s->state = TRANS_DEFAULT;
    4869             : 
    4870        4432 :     PopTransaction();
    4871        4432 : }
    4872             : 
    4873             : /*
    4874             :  * AbortSubTransaction
    4875             :  */
    4876             : static void
    4877        2928 : AbortSubTransaction(void)
    4878             : {
    4879        2928 :     TransactionState s = CurrentTransactionState;
    4880             : 
    4881             :     /* Prevent cancel/die interrupt while cleaning up */
    4882        2928 :     HOLD_INTERRUPTS();
    4883             : 
    4884             :     /* Make sure we have a valid memory context and resource owner */
    4885        2928 :     AtSubAbort_Memory();
    4886        2928 :     AtSubAbort_ResourceOwner();
    4887             : 
    4888             :     /*
    4889             :      * Release any LW locks we might be holding as quickly as possible.
    4890             :      * (Regular locks, however, must be held till we finish aborting.)
    4891             :      * Releasing LW locks is critical since we might try to grab them again
    4892             :      * while cleaning up!
    4893             :      *
    4894             :      * FIXME This may be incorrect --- Are there some locks we should keep?
    4895             :      * Buffer locks, for example?  I don't think so but I'm not sure.
    4896             :      */
    4897        2928 :     LWLockReleaseAll();
    4898             : 
    4899        2928 :     pgstat_report_wait_end();
    4900        2928 :     pgstat_progress_end_command();
    4901        2928 :     AbortBufferIO();
    4902        2928 :     UnlockBuffers();
    4903             : 
    4904             :     /* Reset WAL record construction state */
    4905        2928 :     XLogResetInsertion();
    4906             : 
    4907             :     /* Cancel condition variable sleep */
    4908        2928 :     ConditionVariableCancelSleep();
    4909             : 
    4910             :     /*
    4911             :      * Also clean up any open wait for lock, since the lock manager will choke
    4912             :      * if we try to wait for another lock before doing this.
    4913             :      */
    4914        2928 :     LockErrorCleanup();
    4915             : 
    4916             :     /*
    4917             :      * If any timeout events are still active, make sure the timeout interrupt
    4918             :      * is scheduled.  This covers possible loss of a timeout interrupt due to
    4919             :      * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
    4920             :      * We delay this till after LockErrorCleanup so that we don't uselessly
    4921             :      * reschedule lock or deadlock check timeouts.
    4922             :      */
    4923        2928 :     reschedule_timeouts();
    4924             : 
    4925             :     /*
    4926             :      * Re-enable signals, in case we got here by longjmp'ing out of a signal
    4927             :      * handler.  We do this fairly early in the sequence so that the timeout
    4928             :      * infrastructure will be functional if needed while aborting.
    4929             :      */
    4930        2928 :     PG_SETMASK(&UnBlockSig);
    4931             : 
    4932             :     /*
    4933             :      * check the current transaction state
    4934             :      */
    4935        2928 :     ShowTransactionState("AbortSubTransaction");
    4936             : 
    4937        2928 :     if (s->state != TRANS_INPROGRESS)
    4938           0 :         elog(WARNING, "AbortSubTransaction while in %s state",
    4939             :              TransStateAsString(s->state));
    4940             : 
    4941        2928 :     s->state = TRANS_ABORT;
    4942             : 
    4943             :     /*
    4944             :      * Reset user ID which might have been changed transiently.  (See notes in
    4945             :      * AbortTransaction.)
    4946             :      */
    4947        2928 :     SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
    4948             : 
    4949             :     /* Exit from parallel mode, if necessary. */
    4950        2928 :     if (IsInParallelMode())
    4951             :     {
    4952           4 :         AtEOSubXact_Parallel(false, s->subTransactionId);
    4953           4 :         s->parallelModeLevel = 0;
    4954             :     }
    4955             : 
    4956             :     /*
    4957             :      * We can skip all this stuff if the subxact failed before creating a
    4958             :      * ResourceOwner...
    4959             :      */
    4960        2928 :     if (s->curTransactionOwner)
    4961             :     {
    4962        2928 :         AfterTriggerEndSubXact(false);
    4963        5856 :         AtSubAbort_Portals(s->subTransactionId,
    4964        2928 :                            s->parent->subTransactionId,
    4965             :                            s->curTransactionOwner,
    4966        2928 :                            s->parent->curTransactionOwner);
    4967        2928 :         AtEOSubXact_LargeObject(false, s->subTransactionId,
    4968        2928 :                                 s->parent->subTransactionId);
    4969        2928 :         AtSubAbort_Notify();
    4970             : 
    4971             :         /* Advertise the fact that we aborted in pg_xact. */
    4972        2928 :         (void) RecordTransactionAbort(true);
    4973             : 
    4974             :         /* Post-abort cleanup */
    4975        2928 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    4976         358 :             AtSubAbort_childXids();
    4977             : 
    4978        2928 :         CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
    4979        2928 :                              s->parent->subTransactionId);
    4980             : 
    4981        2928 :         ResourceOwnerRelease(s->curTransactionOwner,
    4982             :                              RESOURCE_RELEASE_BEFORE_LOCKS,
    4983             :                              false, false);
    4984        2928 :         AtEOSubXact_RelationCache(false, s->subTransactionId,
    4985        2928 :                                   s->parent->subTransactionId);
    4986        2928 :         AtEOSubXact_Inval(false);
    4987        2928 :         ResourceOwnerRelease(s->curTransactionOwner,
    4988             :                              RESOURCE_RELEASE_LOCKS,
    4989             :                              false, false);
    4990        2928 :         ResourceOwnerRelease(s->curTransactionOwner,
    4991             :                              RESOURCE_RELEASE_AFTER_LOCKS,
    4992             :                              false, false);
    4993        2928 :         AtSubAbort_smgr();
    4994             : 
    4995        2928 :         AtEOXact_GUC(false, s->gucNestLevel);
    4996        2928 :         AtEOSubXact_SPI(false, s->subTransactionId);
    4997        2928 :         AtEOSubXact_on_commit_actions(false, s->subTransactionId,
    4998        2928 :                                       s->parent->subTransactionId);
    4999        2928 :         AtEOSubXact_Namespace(false, s->subTransactionId,
    5000        2928 :                               s->parent->subTransactionId);
    5001        2928 :         AtEOSubXact_Files(false, s->subTransactionId,
    5002        2928 :                           s->parent->subTransactionId);
    5003        2928 :         AtEOSubXact_HashTables(false, s->nestingLevel);
    5004        2928 :         AtEOSubXact_PgStat(false, s->nestingLevel);
    5005        2928 :         AtSubAbort_Snapshot(s->nestingLevel);
    5006        2928 :         AtEOSubXact_ApplyLauncher(false, s->nestingLevel);
    5007             :     }
    5008             : 
    5009             :     /*
    5010             :      * Restore the upper transaction's read-only state, too.  This should be
    5011             :      * redundant with GUC's cleanup but we may as well do it for consistency
    5012             :      * with the commit case.
    5013             :      */
    5014        2928 :     XactReadOnly = s->prevXactReadOnly;
    5015             : 
    5016        2928 :     RESUME_INTERRUPTS();
    5017        2928 : }
    5018             : 
    5019             : /*
    5020             :  * CleanupSubTransaction
    5021             :  *
    5022             :  *  The caller has to make sure to always reassign CurrentTransactionState
    5023             :  *  if it has a local pointer to it after calling this function.
    5024             :  */
    5025             : static void
    5026        2928 : CleanupSubTransaction(void)
    5027             : {
    5028        2928 :     TransactionState s = CurrentTransactionState;
    5029             : 
    5030        2928 :     ShowTransactionState("CleanupSubTransaction");
    5031             : 
    5032        2928 :     if (s->state != TRANS_ABORT)
    5033           0 :         elog(WARNING, "CleanupSubTransaction while in %s state",
    5034             :              TransStateAsString(s->state));
    5035             : 
    5036        2928 :     AtSubCleanup_Portals(s->subTransactionId);
    5037             : 
    5038        2928 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    5039        2928 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    5040        2928 :     if (s->curTransactionOwner)
    5041        2928 :         ResourceOwnerDelete(s->curTransactionOwner);
    5042        2928 :     s->curTransactionOwner = NULL;
    5043             : 
    5044        2928 :     AtSubCleanup_Memory();
    5045             : 
    5046        2928 :     s->state = TRANS_DEFAULT;
    5047             : 
    5048        2928 :     PopTransaction();
    5049        2928 : }
    5050             : 
    5051             : /*
    5052             :  * PushTransaction
    5053             :  *      Create transaction state stack entry for a subtransaction
    5054             :  *
    5055             :  *  The caller has to make sure to always reassign CurrentTransactionState
    5056             :  *  if it has a local pointer to it after calling this function.
    5057             :  */
    5058             : static void
    5059        7360 : PushTransaction(void)
    5060             : {
    5061        7360 :     TransactionState p = CurrentTransactionState;
    5062             :     TransactionState s;
    5063             : 
    5064             :     /*
    5065             :      * We keep subtransaction state nodes in TopTransactionContext.
    5066             :      */
    5067        7360 :     s = (TransactionState)
    5068        7360 :         MemoryContextAllocZero(TopTransactionContext,
    5069             :                                sizeof(TransactionStateData));
    5070             : 
    5071             :     /*
    5072             :      * Assign a subtransaction ID, watching out for counter wraparound.
    5073             :      */
    5074        7360 :     currentSubTransactionId += 1;
    5075        7360 :     if (currentSubTransactionId == InvalidSubTransactionId)
    5076             :     {
    5077           0 :         currentSubTransactionId -= 1;
    5078           0 :         pfree(s);
    5079           0 :         ereport(ERROR,
    5080             :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    5081             :                  errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
    5082             :     }
    5083             : 
    5084             :     /*
    5085             :      * We can now stack a minimally valid subtransaction without fear of
    5086             :      * failure.
    5087             :      */
    5088        7360 :     s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
    5089        7360 :     s->subTransactionId = currentSubTransactionId;
    5090        7360 :     s->parent = p;
    5091        7360 :     s->nestingLevel = p->nestingLevel + 1;
    5092        7360 :     s->gucNestLevel = NewGUCNestLevel();
    5093        7360 :     s->savepointLevel = p->savepointLevel;
    5094        7360 :     s->state = TRANS_DEFAULT;
    5095        7360 :     s->blockState = TBLOCK_SUBBEGIN;
    5096        7360 :     GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    5097        7360 :     s->prevXactReadOnly = XactReadOnly;
    5098        7360 :     s->parallelModeLevel = 0;
    5099             : 
    5100        7360 :     CurrentTransactionState = s;
    5101             : 
    5102             :     /*
    5103             :      * AbortSubTransaction and CleanupSubTransaction have to be able to cope
    5104             :      * with the subtransaction from here on out; in particular they should not
    5105             :      * assume that it necessarily has a transaction context, resource owner,
    5106             :      * or XID.
    5107             :      */
    5108        7360 : }
    5109             : 
    5110             : /*
    5111             :  * PopTransaction
    5112             :  *      Pop back to parent transaction state
    5113             :  *
    5114             :  *  The caller has to make sure to always reassign CurrentTransactionState
    5115             :  *  if it has a local pointer to it after calling this function.
    5116             :  */
    5117             : static void
    5118        7360 : PopTransaction(void)
    5119             : {
    5120        7360 :     TransactionState s = CurrentTransactionState;
    5121             : 
    5122        7360 :     if (s->state != TRANS_DEFAULT)
    5123           0 :         elog(WARNING, "PopTransaction while in %s state",
    5124             :              TransStateAsString(s->state));
    5125             : 
    5126        7360 :     if (s->parent == NULL)
    5127           0 :         elog(FATAL, "PopTransaction with no parent");
    5128             : 
    5129        7360 :     CurrentTransactionState = s->parent;
    5130             : 
    5131             :     /* Let's just make sure CurTransactionContext is good */
    5132        7360 :     CurTransactionContext = s->parent->curTransactionContext;
    5133        7360 :     MemoryContextSwitchTo(CurTransactionContext);
    5134             : 
    5135             :     /* Ditto for ResourceOwner links */
    5136        7360 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    5137        7360 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    5138             : 
    5139             :     /* Free the old child structure */
    5140        7360 :     if (s->name)
    5141        1968 :         pfree(s->name);
    5142        7360 :     pfree(s);
    5143        7360 : }
    5144             : 
    5145             : /*
    5146             :  * EstimateTransactionStateSpace
    5147             :  *      Estimate the amount of space that will be needed by
    5148             :  *      SerializeTransactionState.  It would be OK to overestimate slightly,
    5149             :  *      but it's simple for us to work out the precise value, so we do.
    5150             :  */
    5151             : Size
    5152         446 : EstimateTransactionStateSpace(void)
    5153             : {
    5154             :     TransactionState s;
    5155         446 :     Size        nxids = 0;
    5156         446 :     Size        size = SerializedTransactionStateHeaderSize;
    5157             : 
    5158        2272 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5159             :     {
    5160        1826 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5161        1044 :             nxids = add_size(nxids, 1);
    5162        1826 :         nxids = add_size(nxids, s->nChildXids);
    5163             :     }
    5164             : 
    5165         446 :     return add_size(size, mul_size(sizeof(TransactionId), nxids));
    5166             : }
    5167             : 
    5168             : /*
    5169             :  * SerializeTransactionState
    5170             :  *      Write out relevant details of our transaction state that will be
    5171             :  *      needed by a parallel worker.
    5172             :  *
    5173             :  * We need to save and restore XactDeferrable, XactIsoLevel, and the XIDs
    5174             :  * associated with this transaction.  These are serialized into a
    5175             :  * caller-supplied buffer big enough to hold the number of bytes reported by
    5176             :  * EstimateTransactionStateSpace().  We emit the XIDs in sorted order for the
    5177             :  * convenience of the receiving process.
    5178             :  */
    5179             : void
    5180         446 : SerializeTransactionState(Size maxsize, char *start_address)
    5181             : {
    5182             :     TransactionState s;
    5183         446 :     Size        nxids = 0;
    5184         446 :     Size        i = 0;
    5185             :     TransactionId *workspace;
    5186             :     SerializedTransactionState *result;
    5187             : 
    5188         446 :     result = (SerializedTransactionState *) start_address;
    5189             : 
    5190         446 :     result->xactIsoLevel = XactIsoLevel;
    5191         446 :     result->xactDeferrable = XactDeferrable;
    5192         446 :     result->topFullTransactionId = XactTopFullTransactionId;
    5193         446 :     result->currentFullTransactionId =
    5194         446 :         CurrentTransactionState->fullTransactionId;
    5195         446 :     result->currentCommandId = currentCommandId;
    5196             : 
    5197             :     /*
    5198             :      * If we're running in a parallel worker and launching a parallel worker
    5199             :      * of our own, we can just pass along the information that was passed to
    5200             :      * us.
    5201             :      */
    5202         446 :     if (nParallelCurrentXids > 0)
    5203             :     {
    5204           0 :         result->nParallelCurrentXids = nParallelCurrentXids;
    5205           0 :         memcpy(&result->parallelCurrentXids[0], ParallelCurrentXids,
    5206             :                nParallelCurrentXids * sizeof(TransactionId));
    5207           0 :         return;
    5208             :     }
    5209             : 
    5210             :     /*
    5211             :      * OK, we need to generate a sorted list of XIDs that our workers should
    5212             :      * view as current.  First, figure out how many there are.
    5213             :      */
    5214        2272 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5215             :     {
    5216        1826 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5217        1044 :             nxids = add_size(nxids, 1);
    5218        1826 :         nxids = add_size(nxids, s->nChildXids);
    5219             :     }
    5220             :     Assert(SerializedTransactionStateHeaderSize + nxids * sizeof(TransactionId)
    5221             :            <= maxsize);
    5222             : 
    5223             :     /* Copy them to our scratch space. */
    5224         446 :     workspace = palloc(nxids * sizeof(TransactionId));
    5225        2272 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5226             :     {
    5227        1826 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5228        1044 :             workspace[i++] = XidFromFullTransactionId(s->fullTransactionId);
    5229        1826 :         memcpy(&workspace[i], s->childXids,
    5230        1826 :                s->nChildXids * sizeof(TransactionId));
    5231        1826 :         i += s->nChildXids;
    5232             :     }
    5233             :     Assert(i == nxids);
    5234             : 
    5235             :     /* Sort them. */
    5236         446 :     qsort(workspace, nxids, sizeof(TransactionId), xidComparator);
    5237             : 
    5238             :     /* Copy data into output area. */
    5239         446 :     result->nParallelCurrentXids = nxids;
    5240         446 :     memcpy(&result->parallelCurrentXids[0], workspace,
    5241             :            nxids * sizeof(TransactionId));
    5242             : }
    5243             : 
    5244             : /*
    5245             :  * StartParallelWorkerTransaction
    5246             :  *      Start a parallel worker transaction, restoring the relevant
    5247             :  *      transaction state serialized by SerializeTransactionState.
    5248             :  */
    5249             : void
    5250        1520 : StartParallelWorkerTransaction(char *tstatespace)
    5251             : {
    5252             :     SerializedTransactionState *tstate;
    5253             : 
    5254             :     Assert(CurrentTransactionState->blockState == TBLOCK_DEFAULT);
    5255        1520 :     StartTransaction();
    5256             : 
    5257        1520 :     tstate = (SerializedTransactionState *) tstatespace;
    5258        1520 :     XactIsoLevel = tstate->xactIsoLevel;
    5259        1520 :     XactDeferrable = tstate->xactDeferrable;
    5260        1520 :     XactTopFullTransactionId = tstate->topFullTransactionId;
    5261        1520 :     CurrentTransactionState->fullTransactionId =
    5262             :         tstate->currentFullTransactionId;
    5263        1520 :     currentCommandId = tstate->currentCommandId;
    5264        1520 :     nParallelCurrentXids = tstate->nParallelCurrentXids;
    5265        1520 :     ParallelCurrentXids = &tstate->parallelCurrentXids[0];
    5266             : 
    5267        1520 :     CurrentTransactionState->blockState = TBLOCK_PARALLEL_INPROGRESS;
    5268        1520 : }
    5269             : 
    5270             : /*
    5271             :  * EndParallelWorkerTransaction
    5272             :  *      End a parallel worker transaction.
    5273             :  */
    5274             : void
    5275        1516 : EndParallelWorkerTransaction(void)
    5276             : {
    5277             :     Assert(CurrentTransactionState->blockState == TBLOCK_PARALLEL_INPROGRESS);
    5278        1516 :     CommitTransaction();
    5279        1516 :     CurrentTransactionState->blockState = TBLOCK_DEFAULT;
    5280        1516 : }
    5281             : 
    5282             : /*
    5283             :  * ShowTransactionState
    5284             :  *      Debug support
    5285             :  */
    5286             : static void
    5287      915232 : ShowTransactionState(const char *str)
    5288             : {
    5289             :     /* skip work if message will definitely not be printed */
    5290      915232 :     if (log_min_messages <= DEBUG5 || client_min_messages <= DEBUG5)
    5291           0 :         ShowTransactionStateRec(str, CurrentTransactionState);
    5292      915232 : }
    5293             : 
    5294             : /*
    5295             :  * ShowTransactionStateRec
    5296             :  *      Recursive subroutine for ShowTransactionState
    5297             :  */
    5298             : static void
    5299           0 : ShowTransactionStateRec(const char *str, TransactionState s)
    5300             : {
    5301             :     StringInfoData buf;
    5302             : 
    5303           0 :     initStringInfo(&buf);
    5304             : 
    5305           0 :     if (s->nChildXids > 0)
    5306             :     {
    5307             :         int         i;
    5308             : 
    5309           0 :         appendStringInfo(&buf, ", children: %u", s->childXids[0]);
    5310           0 :         for (i = 1; i < s->nChildXids; i++)
    5311           0 :             appendStringInfo(&buf, " %u", s->childXids[i]);
    5312             :     }
    5313             : 
    5314           0 :     if (s->parent)
    5315           0 :         ShowTransactionStateRec(str, s->parent);
    5316             : 
    5317             :     /* use ereport to suppress computation if msg will not be printed */
    5318           0 :     ereport(DEBUG5,
    5319             :             (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
    5320             :                              str, s->nestingLevel,
    5321             :                              PointerIsValid(s->name) ? s->name : "unnamed",
    5322             :                              BlockStateAsString(s->blockState),
    5323             :                              TransStateAsString(s->state),
    5324             :                              (unsigned int) XidFromFullTransactionId(s->fullTransactionId),
    5325             :                              (unsigned int) s->subTransactionId,
    5326             :                              (unsigned int) currentCommandId,
    5327             :                              currentCommandIdUsed ? " (used)" : "",
    5328             :                              buf.data)));
    5329             : 
    5330           0 :     pfree(buf.data);
    5331           0 : }
    5332             : 
    5333             : /*
    5334             :  * BlockStateAsString
    5335             :  *      Debug support
    5336             :  */
    5337             : static const char *
    5338           0 : BlockStateAsString(TBlockState blockState)
    5339             : {
    5340           0 :     switch (blockState)
    5341             :     {
    5342             :         case TBLOCK_DEFAULT:
    5343           0 :             return "DEFAULT";
    5344             :         case TBLOCK_STARTED:
    5345           0 :             return "STARTED";
    5346             :         case TBLOCK_BEGIN:
    5347           0 :             return "BEGIN";
    5348             :         case TBLOCK_INPROGRESS:
    5349           0 :             return "INPROGRESS";
    5350             :         case TBLOCK_IMPLICIT_INPROGRESS:
    5351           0 :             return "IMPLICIT_INPROGRESS";
    5352             :         case TBLOCK_PARALLEL_INPROGRESS:
    5353           0 :             return "PARALLEL_INPROGRESS";
    5354             :         case TBLOCK_END:
    5355           0 :             return "END";
    5356             :         case TBLOCK_ABORT:
    5357           0 :             return "ABORT";
    5358             :         case TBLOCK_ABORT_END:
    5359           0 :             return "ABORT_END";
    5360             :         case TBLOCK_ABORT_PENDING:
    5361           0 :             return "ABORT_PENDING";
    5362             :         case TBLOCK_PREPARE:
    5363           0 :             return "PREPARE";
    5364             :         case TBLOCK_SUBBEGIN:
    5365           0 :             return "SUBBEGIN";
    5366             :         case TBLOCK_SUBINPROGRESS:
    5367           0 :             return "SUBINPROGRESS";
    5368             :         case TBLOCK_SUBRELEASE:
    5369           0 :             return "SUBRELEASE";
    5370             :         case TBLOCK_SUBCOMMIT:
    5371           0 :             return "SUBCOMMIT";
    5372             :         case TBLOCK_SUBABORT:
    5373           0 :             return "SUBABORT";
    5374             :         case TBLOCK_SUBABORT_END:
    5375           0 :             return "SUBABORT_END";
    5376             :         case TBLOCK_SUBABORT_PENDING:
    5377           0 :             return "SUBABORT_PENDING";
    5378             :         case TBLOCK_SUBRESTART:
    5379           0 :             return "SUBRESTART";
    5380             :         case TBLOCK_SUBABORT_RESTART:
    5381           0 :             return "SUBABORT_RESTART";
    5382             :     }
    5383           0 :     return "UNRECOGNIZED";
    5384             : }
    5385             : 
    5386             : /*
    5387             :  * TransStateAsString
    5388             :  *      Debug support
    5389             :  */
    5390             : static const char *
    5391           0 : TransStateAsString(TransState state)
    5392             : {
    5393           0 :     switch (state)
    5394             :     {
    5395             :         case TRANS_DEFAULT:
    5396           0 :             return "DEFAULT";
    5397             :         case TRANS_START:
    5398           0 :             return "START";
    5399             :         case TRANS_INPROGRESS:
    5400           0 :             return "INPROGRESS";
    5401             :         case TRANS_COMMIT:
    5402           0 :             return "COMMIT";
    5403             :         case TRANS_ABORT:
    5404           0 :             return "ABORT";
    5405             :         case TRANS_PREPARE:
    5406           0 :             return "PREPARE";
    5407             :     }
    5408           0 :     return "UNRECOGNIZED";
    5409             : }
    5410             : 
    5411             : /*
    5412             :  * xactGetCommittedChildren
    5413             :  *
    5414             :  * Gets the list of committed children of the current transaction.  The return
    5415             :  * value is the number of child transactions.  *ptr is set to point to an
    5416             :  * array of TransactionIds.  The array is allocated in TopTransactionContext;
    5417             :  * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
    5418             :  * If there are no subxacts, *ptr is set to NULL.
    5419             :  */
    5420             : int
    5421      442936 : xactGetCommittedChildren(TransactionId **ptr)
    5422             : {
    5423      442936 :     TransactionState s = CurrentTransactionState;
    5424             : 
    5425      442936 :     if (s->nChildXids == 0)
    5426      442444 :         *ptr = NULL;
    5427             :     else
    5428         492 :         *ptr = s->childXids;
    5429             : 
    5430      442936 :     return s->nChildXids;
    5431             : }
    5432             : 
    5433             : /*
    5434             :  *  XLOG support routines
    5435             :  */
    5436             : 
    5437             : 
    5438             : /*
    5439             :  * Log the commit record for a plain or twophase transaction commit.
    5440             :  *
    5441             :  * A 2pc commit will be emitted when twophase_xid is valid, a plain one
    5442             :  * otherwise.
    5443             :  */
    5444             : XLogRecPtr
    5445      246346 : XactLogCommitRecord(TimestampTz commit_time,
    5446             :                     int nsubxacts, TransactionId *subxacts,
    5447             :                     int nrels, RelFileNode *rels,
    5448             :                     int nmsgs, SharedInvalidationMessage *msgs,
    5449             :                     bool relcacheInval, bool forceSync,
    5450             :                     int xactflags, TransactionId twophase_xid,
    5451             :                     const char *twophase_gid)
    5452             : {
    5453             :     xl_xact_commit xlrec;
    5454             :     xl_xact_xinfo xl_xinfo;
    5455             :     xl_xact_dbinfo xl_dbinfo;
    5456             :     xl_xact_subxacts xl_subxacts;
    5457             :     xl_xact_relfilenodes xl_relfilenodes;
    5458             :     xl_xact_invals xl_invals;
    5459             :     xl_xact_twophase xl_twophase;
    5460             :     xl_xact_origin xl_origin;
    5461             :     uint8       info;
    5462             : 
    5463             :     Assert(CritSectionCount > 0);
    5464             : 
    5465      246346 :     xl_xinfo.xinfo = 0;
    5466             : 
    5467             :     /* decide between a plain and 2pc commit */
    5468      246346 :     if (!TransactionIdIsValid(twophase_xid))
    5469      246302 :         info = XLOG_XACT_COMMIT;
    5470             :     else
    5471          44 :         info = XLOG_XACT_COMMIT_PREPARED;
    5472             : 
    5473             :     /* First figure out and collect all the information needed */
    5474             : 
    5475      246346 :     xlrec.xact_time = commit_time;
    5476             : 
    5477      246346 :     if (relcacheInval)
    5478        7386 :         xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
    5479      246346 :     if (forceSyncCommit)
    5480         934 :         xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
    5481      246346 :     if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
    5482       79352 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
    5483             : 
    5484             :     /*
    5485             :      * Check if the caller would like to ask standbys for immediate feedback
    5486             :      * once this commit is applied.
    5487             :      */
    5488      246346 :     if (synchronous_commit >= SYNCHRONOUS_COMMIT_REMOTE_APPLY)
    5489           0 :         xl_xinfo.xinfo |= XACT_COMPLETION_APPLY_FEEDBACK;
    5490             : 
    5491             :     /*
    5492             :      * Relcache invalidations requires information about the current database
    5493             :      * and so does logical decoding.
    5494             :      */
    5495      246346 :     if (nmsgs > 0 || XLogLogicalInfoActive())
    5496             :     {
    5497      208588 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
    5498      208588 :         xl_dbinfo.dbId = MyDatabaseId;
    5499      208588 :         xl_dbinfo.tsId = MyDatabaseTableSpace;
    5500             :     }
    5501             : 
    5502      246346 :     if (nsubxacts > 0)
    5503             :     {
    5504         326 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
    5505         326 :         xl_subxacts.nsubxacts = nsubxacts;
    5506             :     }
    5507             : 
    5508      246346 :     if (nrels > 0)
    5509             :     {
    5510       10124 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILENODES;
    5511       10124 :         xl_relfilenodes.nrels = nrels;
    5512             :     }
    5513             : 
    5514      246346 :     if (nmsgs > 0)
    5515             :     {
    5516      207792 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_INVALS;
    5517      207792 :         xl_invals.nmsgs = nmsgs;
    5518             :     }
    5519             : 
    5520      246346 :     if (TransactionIdIsValid(twophase_xid))
    5521             :     {
    5522          44 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
    5523          44 :         xl_twophase.xid = twophase_xid;
    5524             :         Assert(twophase_gid != NULL);
    5525             : 
    5526          44 :         if (XLogLogicalInfoActive())
    5527           4 :             xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
    5528             :     }
    5529             : 
    5530             :     /* dump transaction origin information */
    5531      246346 :     if (replorigin_session_origin != InvalidRepOriginId)
    5532             :     {
    5533         278 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
    5534             : 
    5535         278 :         xl_origin.origin_lsn = replorigin_session_origin_lsn;
    5536         278 :         xl_origin.origin_timestamp = replorigin_session_origin_timestamp;
    5537             :     }
    5538             : 
    5539      246346 :     if (xl_xinfo.xinfo != 0)
    5540      212514 :         info |= XLOG_XACT_HAS_INFO;
    5541             : 
    5542             :     /* Then include all the collected data into the commit record. */
    5543             : 
    5544      246346 :     XLogBeginInsert();
    5545             : 
    5546      246346 :     XLogRegisterData((char *) (&xlrec), sizeof(xl_xact_commit));
    5547             : 
    5548      246346 :     if (xl_xinfo.xinfo != 0)
    5549      212514 :         XLogRegisterData((char *) (&xl_xinfo.xinfo), sizeof(xl_xinfo.xinfo));
    5550             : 
    5551      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
    5552      208588 :         XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo));
    5553             : 
    5554      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
    5555             :     {
    5556         326 :         XLogRegisterData((char *) (&xl_subxacts),
    5557             :                          MinSizeOfXactSubxacts);
    5558         326 :         XLogRegisterData((char *) subxacts,
    5559         326 :                          nsubxacts * sizeof(TransactionId));
    5560             :     }
    5561             : 
    5562      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILENODES)
    5563             :     {
    5564       10124 :         XLogRegisterData((char *) (&xl_relfilenodes),
    5565             :                          MinSizeOfXactRelfilenodes);
    5566       10124 :         XLogRegisterData((char *) rels,
    5567       10124 :                          nrels * sizeof(RelFileNode));
    5568             :     }
    5569             : 
    5570      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS)
    5571             :     {
    5572      207792 :         XLogRegisterData((char *) (&xl_invals), MinSizeOfXactInvals);
    5573      207792 :         XLogRegisterData((char *) msgs,
    5574      207792 :                          nmsgs * sizeof(SharedInvalidationMessage));
    5575             :     }
    5576             : 
    5577      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
    5578             :     {
    5579          44 :         XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase));
    5580          44 :         if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
    5581           4 :             XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1);
    5582             :     }
    5583             : 
    5584      246346 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
    5585         278 :         XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
    5586             : 
    5587             :     /* we allow filtering by xacts */
    5588      246346 :     XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
    5589             : 
    5590      246346 :     return XLogInsert(RM_XACT_ID, info);
    5591             : }
    5592             : 
    5593             : /*
    5594             :  * Log the commit record for a plain or twophase transaction abort.
    5595             :  *
    5596             :  * A 2pc abort will be emitted when twophase_xid is valid, a plain one
    5597             :  * otherwise.
    5598             :  */
    5599             : XLogRecPtr
    5600        5556 : XactLogAbortRecord(TimestampTz abort_time,
    5601             :                    int nsubxacts, TransactionId *subxacts,
    5602             :                    int nrels, RelFileNode *rels,
    5603             :                    int xactflags, TransactionId twophase_xid,
    5604             :                    const char *twophase_gid)
    5605             : {
    5606             :     xl_xact_abort xlrec;
    5607             :     xl_xact_xinfo xl_xinfo;
    5608             :     xl_xact_subxacts xl_subxacts;
    5609             :     xl_xact_relfilenodes xl_relfilenodes;
    5610             :     xl_xact_twophase xl_twophase;
    5611             :     xl_xact_dbinfo xl_dbinfo;
    5612             :     xl_xact_origin xl_origin;
    5613             : 
    5614             :     uint8       info;
    5615             : 
    5616             :     Assert(CritSectionCount > 0);
    5617             : 
    5618        5556 :     xl_xinfo.xinfo = 0;
    5619             : 
    5620             :     /* decide between a plain and 2pc abort */
    5621        5556 :     if (!TransactionIdIsValid(twophase_xid))
    5622        5536 :         info = XLOG_XACT_ABORT;
    5623             :     else
    5624          20 :         info = XLOG_XACT_ABORT_PREPARED;
    5625             : 
    5626             : 
    5627             :     /* First figure out and collect all the information needed */
    5628             : 
    5629        5556 :     xlrec.xact_time = abort_time;
    5630             : 
    5631        5556 :     if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
    5632        2824 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
    5633             : 
    5634        5556 :     if (nsubxacts > 0)
    5635             :     {
    5636         170 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
    5637         170 :         xl_subxacts.nsubxacts = nsubxacts;
    5638             :     }
    5639             : 
    5640        5556 :     if (nrels > 0)
    5641             :     {
    5642         810 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILENODES;
    5643         810 :         xl_relfilenodes.nrels = nrels;
    5644             :     }
    5645             : 
    5646        5556 :     if (TransactionIdIsValid(twophase_xid))
    5647             :     {
    5648          20 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
    5649          20 :         xl_twophase.xid = twophase_xid;
    5650             :         Assert(twophase_gid != NULL);
    5651             : 
    5652          20 :         if (XLogLogicalInfoActive())
    5653           2 :             xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
    5654             :     }
    5655             : 
    5656        5556 :     if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive())
    5657             :     {
    5658           2 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
    5659           2 :         xl_dbinfo.dbId = MyDatabaseId;
    5660           2 :         xl_dbinfo.tsId = MyDatabaseTableSpace;
    5661             :     }
    5662             : 
    5663             :     /* dump transaction origin information only for abort prepared */
    5664        5556 :     if ((replorigin_session_origin != InvalidRepOriginId) &&
    5665           0 :         TransactionIdIsValid(twophase_xid) &&
    5666           0 :         XLogLogicalInfoActive())
    5667             :     {
    5668           0 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
    5669             : 
    5670           0 :         xl_origin.origin_lsn = replorigin_session_origin_lsn;
    5671           0 :         xl_origin.origin_timestamp = replorigin_session_origin_timestamp;
    5672             :     }
    5673             : 
    5674        5556 :     if (xl_xinfo.xinfo != 0)
    5675        2978 :         info |= XLOG_XACT_HAS_INFO;
    5676             : 
    5677             :     /* Then include all the collected data into the abort record. */
    5678             : 
    5679        5556 :     XLogBeginInsert();
    5680             : 
    5681        5556 :     XLogRegisterData((char *) (&xlrec), MinSizeOfXactAbort);
    5682             : 
    5683        5556 :     if (xl_xinfo.xinfo != 0)
    5684        2978 :         XLogRegisterData((char *) (&xl_xinfo), sizeof(xl_xinfo));
    5685             : 
    5686        5556 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
    5687           2 :         XLogRegisterData((char *) (&xl_dbinfo), sizeof(xl_dbinfo));
    5688             : 
    5689        5556 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
    5690             :     {
    5691         170 :         XLogRegisterData((char *) (&xl_subxacts),
    5692             :                          MinSizeOfXactSubxacts);
    5693         170 :         XLogRegisterData((char *) subxacts,
    5694         170 :                          nsubxacts * sizeof(TransactionId));
    5695             :     }
    5696             : 
    5697        5556 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILENODES)
    5698             :     {
    5699         810 :         XLogRegisterData((char *) (&xl_relfilenodes),
    5700             :                          MinSizeOfXactRelfilenodes);
    5701         810 :         XLogRegisterData((char *) rels,
    5702         810 :                          nrels * sizeof(RelFileNode));
    5703             :     }
    5704             : 
    5705        5556 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
    5706             :     {
    5707          20 :         XLogRegisterData((char *) (&xl_twophase), sizeof(xl_xact_twophase));
    5708          20 :         if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
    5709           2 :             XLogRegisterData(unconstify(char *, twophase_gid), strlen(twophase_gid) + 1);
    5710             :     }
    5711             : 
    5712        5556 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
    5713           0 :         XLogRegisterData((char *) (&xl_origin), sizeof(xl_xact_origin));
    5714             : 
    5715        5556 :     if (TransactionIdIsValid(twophase_xid))
    5716          20 :         XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
    5717             : 
    5718        5556 :     return XLogInsert(RM_XACT_ID, info);
    5719             : }
    5720             : 
    5721             : /*
    5722             :  * Before 9.0 this was a fairly short function, but now it performs many
    5723             :  * actions for which the order of execution is critical.
    5724             :  */
    5725             : static void
    5726        4212 : xact_redo_commit(xl_xact_parsed_commit *parsed,
    5727             :                  TransactionId xid,
    5728             :                  XLogRecPtr lsn,
    5729             :                  RepOriginId origin_id)
    5730             : {
    5731             :     TransactionId max_xid;
    5732             :     TimestampTz commit_time;
    5733             : 
    5734             :     Assert(TransactionIdIsValid(xid));
    5735             : 
    5736        4212 :     max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
    5737             : 
    5738             :     /* Make sure nextFullXid is beyond any XID mentioned in the record. */
    5739        4212 :     AdvanceNextFullTransactionIdPastXid(max_xid);
    5740             : 
    5741             :     Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
    5742             :            (origin_id == InvalidRepOriginId));
    5743             : 
    5744        4212 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
    5745           0 :         commit_time = parsed->origin_timestamp;
    5746             :     else
    5747        4212 :         commit_time = parsed->xact_time;
    5748             : 
    5749             :     /* Set the transaction commit timestamp and metadata */
    5750        4212 :     TransactionTreeSetCommitTsData(xid, parsed->nsubxacts, parsed->subxacts,
    5751             :                                    commit_time, origin_id, false);
    5752             : 
    5753        4212 :     if (standbyState == STANDBY_DISABLED)
    5754             :     {
    5755             :         /*
    5756             :          * Mark the transaction committed in pg_xact.
    5757             :          */
    5758        4062 :         TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
    5759             :     }
    5760             :     else
    5761             :     {
    5762             :         /*
    5763             :          * If a transaction completion record arrives that has as-yet
    5764             :          * unobserved subtransactions then this will not have been fully
    5765             :          * handled by the call to RecordKnownAssignedTransactionIds() in the
    5766             :          * main recovery loop in xlog.c. So we need to do bookkeeping again to
    5767             :          * cover that case. This is confusing and it is easy to think this
    5768             :          * call is irrelevant, which has happened three times in development
    5769             :          * already. Leave it in.
    5770             :          */
    5771         150 :         RecordKnownAssignedTransactionIds(max_xid);
    5772             : 
    5773             :         /*
    5774             :          * Mark the transaction committed in pg_xact. We use async commit
    5775             :          * protocol during recovery to provide information on database
    5776             :          * consistency for when users try to set hint bits. It is important
    5777             :          * that we do not set hint bits until the minRecoveryPoint is past
    5778             :          * this commit record. This ensures that if we crash we don't see hint
    5779             :          * bits set on changes made by transactions that haven't yet
    5780             :          * recovered. It's unlikely but it's good to be safe.
    5781             :          */
    5782         150 :         TransactionIdAsyncCommitTree(
    5783             :                                      xid, parsed->nsubxacts, parsed->subxacts, lsn);
    5784             : 
    5785             :         /*
    5786             :          * We must mark clog before we update the ProcArray.
    5787             :          */
    5788         150 :         ExpireTreeKnownAssignedTransactionIds(
    5789             :                                               xid, parsed->nsubxacts, parsed->subxacts, max_xid);
    5790             : 
    5791             :         /*
    5792             :          * Send any cache invalidations attached to the commit. We must
    5793             :          * maintain the same order of invalidation then release locks as
    5794             :          * occurs in CommitTransaction().
    5795             :          */
    5796         300 :         ProcessCommittedInvalidationMessages(
    5797             :                                              parsed->msgs, parsed->nmsgs,
    5798         150 :                                              XactCompletionRelcacheInitFileInval(parsed->xinfo),
    5799             :                                              parsed->dbId, parsed->tsId);
    5800             : 
    5801             :         /*
    5802             :          * Release locks, if any. We do this for both two phase and normal one
    5803             :          * phase transactions. In effect we are ignoring the prepare phase and
    5804             :          * just going straight to lock release.
    5805             :          */
    5806         150 :         if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
    5807          82 :             StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
    5808             :     }
    5809             : 
    5810        4212 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
    5811             :     {
    5812             :         /* recover apply progress */
    5813           0 :         replorigin_advance(origin_id, parsed->origin_lsn, lsn,
    5814             :                            false /* backward */ , false /* WAL */ );
    5815             :     }
    5816             : 
    5817             :     /* Make sure files supposed to be dropped are dropped */
    5818        4212 :     if (parsed->nrels > 0)
    5819             :     {
    5820             :         /*
    5821             :          * First update minimum recovery point to cover this WAL record. Once
    5822             :          * a relation is deleted, there's no going back. The buffer manager
    5823             :          * enforces the WAL-first rule for normal updates to relation files,
    5824             :          * so that the minimum recovery point is always updated before the
    5825             :          * corresponding change in the data file is flushed to disk, but we
    5826             :          * have to do the same here since we're bypassing the buffer manager.
    5827             :          *
    5828             :          * Doing this before deleting the files means that if a deletion fails
    5829             :          * for some reason, you cannot start up the system even after restart,
    5830             :          * until you fix the underlying situation so that the deletion will
    5831             :          * succeed. Alternatively, we could update the minimum recovery point
    5832             :          * after deletion, but that would leave a small window where the
    5833             :          * WAL-first rule would be violated.
    5834             :          */
    5835           6 :         XLogFlush(lsn);
    5836             : 
    5837             :         /* Make sure files supposed to be dropped are dropped */
    5838           6 :         DropRelationFiles(parsed->xnodes, parsed->nrels, true);
    5839             :     }
    5840             : 
    5841             :     /*
    5842             :      * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
    5843             :      * in normal operation. For example, in CREATE DATABASE, we copy all files
    5844             :      * from the template database, and then commit the transaction. If we
    5845             :      * crash after all the files have been copied but before the commit, you
    5846             :      * have files in the data directory without an entry in pg_database. To
    5847             :      * minimize the window for that, we use ForceSyncCommit() to rush the
    5848             :      * commit record to disk as quick as possible. We have the same window
    5849             :      * during recovery, and forcing an XLogFlush() (which updates
    5850             :      * minRecoveryPoint during recovery) helps to reduce that problem window,
    5851             :      * for any user that requested ForceSyncCommit().
    5852             :      */
    5853        4212 :     if (XactCompletionForceSyncCommit(parsed->xinfo))
    5854          12 :         XLogFlush(lsn);
    5855             : 
    5856             :     /*
    5857             :      * If asked by the primary (because someone is waiting for a synchronous
    5858             :      * commit = remote_apply), we will need to ask walreceiver to send a reply
    5859             :      * immediately.
    5860             :      */
    5861        4212 :     if (XactCompletionApplyFeedback(parsed->xinfo))
    5862           0 :         XLogRequestWalReceiverReply();
    5863        4212 : }
    5864             : 
    5865             : /*
    5866             :  * Be careful with the order of execution, as with xact_redo_commit().
    5867             :  * The two functions are similar but differ in key places.
    5868             :  *
    5869             :  * Note also that an abort can be for a subtransaction and its children,
    5870             :  * not just for a top level abort. That means we have to consider
    5871             :  * topxid != xid, whereas in commit we would find topxid == xid always
    5872             :  * because subtransaction commit is never WAL logged.
    5873             :  */
    5874             : static void
    5875           8 : xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid)
    5876             : {
    5877             :     TransactionId max_xid;
    5878             : 
    5879             :     Assert(TransactionIdIsValid(xid));
    5880             : 
    5881             :     /* Make sure nextFullXid is beyond any XID mentioned in the record. */
    5882           8 :     max_xid = TransactionIdLatest(xid,
    5883             :                                   parsed->nsubxacts,
    5884           8 :                                   parsed->subxacts);
    5885           8 :     AdvanceNextFullTransactionIdPastXid(max_xid);
    5886             : 
    5887           8 :     if (standbyState == STANDBY_DISABLED)
    5888             :     {
    5889             :         /* Mark the transaction aborted in pg_xact, no need for async stuff */
    5890           0 :         TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
    5891             :     }
    5892             :     else
    5893             :     {
    5894             :         /*
    5895             :          * If a transaction completion record arrives that has as-yet
    5896             :          * unobserved subtransactions then this will not have been fully
    5897             :          * handled by the call to RecordKnownAssignedTransactionIds() in the
    5898             :          * main recovery loop in xlog.c. So we need to do bookkeeping again to
    5899             :          * cover that case. This is confusing and it is easy to think this
    5900             :          * call is irrelevant, which has happened three times in development
    5901             :          * already. Leave it in.
    5902             :          */
    5903           8 :         RecordKnownAssignedTransactionIds(max_xid);
    5904             : 
    5905             :         /* Mark the transaction aborted in pg_xact, no need for async stuff */
    5906           8 :         TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
    5907             : 
    5908             :         /*
    5909             :          * We must update the ProcArray after we have marked clog.
    5910             :          */
    5911           8 :         ExpireTreeKnownAssignedTransactionIds(
    5912             :                                               xid, parsed->nsubxacts, parsed->subxacts, max_xid);
    5913             : 
    5914             :         /*
    5915             :          * There are no invalidation messages to send or undo.
    5916             :          */
    5917             : 
    5918             :         /*
    5919             :          * Release locks, if any. There are no invalidations to send.
    5920             :          */
    5921           8 :         if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
    5922           6 :             StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
    5923             :     }
    5924             : 
    5925             :     /* Make sure files supposed to be dropped are dropped */
    5926           8 :     DropRelationFiles(parsed->xnodes, parsed->nrels, true);
    5927           8 : }
    5928             : 
    5929             : void
    5930        4286 : xact_redo(XLogReaderState *record)
    5931             : {
    5932        4286 :     uint8       info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
    5933             : 
    5934             :     /* Backup blocks are not used in xact records */
    5935             :     Assert(!XLogRecHasAnyBlockRefs(record));
    5936             : 
    5937        4286 :     if (info == XLOG_XACT_COMMIT)
    5938             :     {
    5939        4174 :         xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
    5940             :         xl_xact_parsed_commit parsed;
    5941             : 
    5942        4174 :         ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
    5943        4174 :         xact_redo_commit(&parsed, XLogRecGetXid(record),
    5944        4174 :                          record->EndRecPtr, XLogRecGetOrigin(record));
    5945             :     }
    5946         112 :     else if (info == XLOG_XACT_COMMIT_PREPARED)
    5947             :     {
    5948          38 :         xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
    5949             :         xl_xact_parsed_commit parsed;
    5950             : 
    5951          38 :         ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
    5952          38 :         xact_redo_commit(&parsed, parsed.twophase_xid,
    5953          38 :                          record->EndRecPtr, XLogRecGetOrigin(record));
    5954             : 
    5955             :         /* Delete TwoPhaseState gxact entry and/or 2PC file. */
    5956          38 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    5957          38 :         PrepareRedoRemove(parsed.twophase_xid, false);
    5958          38 :         LWLockRelease(TwoPhaseStateLock);
    5959             :     }
    5960          74 :     else if (info == XLOG_XACT_ABORT)
    5961             :     {
    5962           2 :         xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
    5963             :         xl_xact_parsed_abort parsed;
    5964             : 
    5965           2 :         ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
    5966           2 :         xact_redo_abort(&parsed, XLogRecGetXid(record));
    5967             :     }
    5968          72 :     else if (info == XLOG_XACT_ABORT_PREPARED)
    5969             :     {
    5970           6 :         xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
    5971             :         xl_xact_parsed_abort parsed;
    5972             : 
    5973           6 :         ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
    5974           6 :         xact_redo_abort(&parsed, parsed.twophase_xid);
    5975             : 
    5976             :         /* Delete TwoPhaseState gxact entry and/or 2PC file. */
    5977           6 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    5978           6 :         PrepareRedoRemove(parsed.twophase_xid, false);
    5979           6 :         LWLockRelease(TwoPhaseStateLock);
    5980             :     }
    5981          66 :     else if (info == XLOG_XACT_PREPARE)
    5982             :     {
    5983             :         /*
    5984             :          * Store xid and start/end pointers of the WAL record in TwoPhaseState
    5985             :          * gxact entry.
    5986             :          */
    5987          56 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    5988          56 :         PrepareRedoAdd(XLogRecGetData(record),
    5989             :                        record->ReadRecPtr,
    5990             :                        record->EndRecPtr,
    5991          56 :                        XLogRecGetOrigin(record));
    5992          56 :         LWLockRelease(TwoPhaseStateLock);
    5993             :     }
    5994          10 :     else if (info == XLOG_XACT_ASSIGNMENT)
    5995             :     {
    5996          10 :         xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);
    5997             : 
    5998          10 :         if (standbyState >= STANDBY_INITIALIZED)
    5999          10 :             ProcArrayApplyXidAssignment(xlrec->xtop,
    6000          10 :                                         xlrec->nsubxacts, xlrec->xsub);
    6001             :     }
    6002             :     else
    6003           0 :         elog(PANIC, "xact_redo: unknown op code %u", info);
    6004        4286 : }

Generated by: LCOV version 1.13