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

Generated by: LCOV version 2.0-1