LCOV - differential code coverage report
Current view: top level - src/backend/access/transam - xact.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 87.0 % 1904 1656 22 226 1 64 1591 16 34
Current Date: 2024-04-14 14:21:10 Functions: 93.6 % 109 102 1 6 25 77
Baseline: 16@8cea358b128 Branches: 62.4 % 1090 680 45 1 1 363 3 1 45 631 3 1
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed [..60] days: 72.8 % 81 59 22 59
(120,180] days: 100.0 % 6 6 5 1
(240..) days: 87.6 % 1817 1591 226 1 1590
Function coverage date bins:
[..60] days: 100.0 % 2 2 2
(240..) days: 93.5 % 107 100 1 6 23 77
Branch coverage date bins:
[..60] days: 50.0 % 90 45 45 45
(240..) days: 63.2 % 1004 635 1 1 363 3 1 631 3 1

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

Generated by: LCOV version 2.1-beta2-3-g6141622