LCOV - differential code coverage report
Current view: top level - src/backend/access/transam - xact.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DCB
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 87.2 % 1900 1656 244 5 12 1639 9
Current Date: 2025-09-06 07:49:51 +0900 Functions: 93.6 % 109 102 7 1 3 98
Baseline: lcov-20250906-005545-baseline Branches: 62.2 % 1070 666 2 402 2 2 662
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 49 49 12 37
(360..) days: 86.8 % 1851 1607 244 5 1602
Function coverage date bins:
(360..) days: 93.6 % 109 102 7 1 3 98
Branch coverage date bins:
(30,360] days: 50.0 % 4 2 2 2
(360..) days: 62.3 % 1066 664 402 2 662

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

Generated by: LCOV version 2.4-beta