LCOV - differential code coverage report
Current view: top level - src/backend/access/heap - heapam_visibility.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 68.5 % 607 416 28 111 52 16 223 8 169 122 209 1 10
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 16 16 15 1 16
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (180,240] days: 100.0 % 8 8 8
Legend: Lines: hit not hit (240..) days: 68.1 % 599 408 28 111 52 16 223 169 122 209
Function coverage date bins:
(180,240] days: 100.0 % 1 1 1
(240..) days: 48.4 % 31 15 15 16

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * heapam_visibility.c
                                  4                 :  *    Tuple visibility rules for tuples stored in heap.
                                  5                 :  *
                                  6                 :  * NOTE: all the HeapTupleSatisfies routines will update the tuple's
                                  7                 :  * "hint" status bits if we see that the inserting or deleting transaction
                                  8                 :  * has now committed or aborted (and it is safe to set the hint bits).
                                  9                 :  * If the hint bits are changed, MarkBufferDirtyHint is called on
                                 10                 :  * the passed-in buffer.  The caller must hold not only a pin, but at least
                                 11                 :  * shared buffer content lock on the buffer containing the tuple.
                                 12                 :  *
                                 13                 :  * NOTE: When using a non-MVCC snapshot, we must check
                                 14                 :  * TransactionIdIsInProgress (which looks in the PGPROC array) before
                                 15                 :  * TransactionIdDidCommit (which look in pg_xact).  Otherwise we have a race
                                 16                 :  * condition: we might decide that a just-committed transaction crashed,
                                 17                 :  * because none of the tests succeed.  xact.c is careful to record
                                 18                 :  * commit/abort in pg_xact before it unsets MyProc->xid in the PGPROC array.
                                 19                 :  * That fixes that problem, but it also means there is a window where
                                 20                 :  * TransactionIdIsInProgress and TransactionIdDidCommit will both return true.
                                 21                 :  * If we check only TransactionIdDidCommit, we could consider a tuple
                                 22                 :  * committed when a later GetSnapshotData call will still think the
                                 23                 :  * originating transaction is in progress, which leads to application-level
                                 24                 :  * inconsistency.  The upshot is that we gotta check TransactionIdIsInProgress
                                 25                 :  * first in all code paths, except for a few cases where we are looking at
                                 26                 :  * subtransactions of our own main transaction and so there can't be any race
                                 27                 :  * condition.
                                 28                 :  *
                                 29                 :  * We can't use TransactionIdDidAbort here because it won't treat transactions
                                 30                 :  * that were in progress during a crash as aborted.  We determine that
                                 31                 :  * transactions aborted/crashed through process of elimination instead.
                                 32                 :  *
                                 33                 :  * When using an MVCC snapshot, we rely on XidInMVCCSnapshot rather than
                                 34                 :  * TransactionIdIsInProgress, but the logic is otherwise the same: do not
                                 35                 :  * check pg_xact until after deciding that the xact is no longer in progress.
                                 36                 :  *
                                 37                 :  *
                                 38                 :  * Summary of visibility functions:
                                 39                 :  *
                                 40                 :  *   HeapTupleSatisfiesMVCC()
                                 41                 :  *        visible to supplied snapshot, excludes current command
                                 42                 :  *   HeapTupleSatisfiesUpdate()
                                 43                 :  *        visible to instant snapshot, with user-supplied command
                                 44                 :  *        counter and more complex result
                                 45                 :  *   HeapTupleSatisfiesSelf()
                                 46                 :  *        visible to instant snapshot and current command
                                 47                 :  *   HeapTupleSatisfiesDirty()
                                 48                 :  *        like HeapTupleSatisfiesSelf(), but includes open transactions
                                 49                 :  *   HeapTupleSatisfiesVacuum()
                                 50                 :  *        visible to any running transaction, used by VACUUM
                                 51                 :  *   HeapTupleSatisfiesNonVacuumable()
                                 52                 :  *        Snapshot-style API for HeapTupleSatisfiesVacuum
                                 53                 :  *   HeapTupleSatisfiesToast()
                                 54                 :  *        visible unless part of interrupted vacuum, used for TOAST
                                 55                 :  *   HeapTupleSatisfiesAny()
                                 56                 :  *        all tuples are visible
                                 57                 :  *
                                 58                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 59                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 60                 :  *
                                 61                 :  * IDENTIFICATION
                                 62                 :  *    src/backend/access/heap/heapam_visibility.c
                                 63                 :  *
                                 64                 :  *-------------------------------------------------------------------------
                                 65                 :  */
                                 66                 : 
                                 67                 : #include "postgres.h"
                                 68                 : 
                                 69                 : #include "access/heapam.h"
                                 70                 : #include "access/htup_details.h"
                                 71                 : #include "access/multixact.h"
                                 72                 : #include "access/subtrans.h"
                                 73                 : #include "access/tableam.h"
                                 74                 : #include "access/transam.h"
                                 75                 : #include "access/xact.h"
                                 76                 : #include "access/xlog.h"
                                 77                 : #include "storage/bufmgr.h"
                                 78                 : #include "storage/procarray.h"
                                 79                 : #include "utils/builtins.h"
                                 80                 : #include "utils/combocid.h"
                                 81                 : #include "utils/snapmgr.h"
                                 82                 : 
                                 83                 : 
                                 84                 : /*
                                 85                 :  * SetHintBits()
                                 86                 :  *
                                 87                 :  * Set commit/abort hint bits on a tuple, if appropriate at this time.
                                 88                 :  *
                                 89                 :  * It is only safe to set a transaction-committed hint bit if we know the
                                 90                 :  * transaction's commit record is guaranteed to be flushed to disk before the
                                 91                 :  * buffer, or if the table is temporary or unlogged and will be obliterated by
                                 92                 :  * a crash anyway.  We cannot change the LSN of the page here, because we may
                                 93                 :  * hold only a share lock on the buffer, so we can only use the LSN to
                                 94                 :  * interlock this if the buffer's LSN already is newer than the commit LSN;
                                 95                 :  * otherwise we have to just refrain from setting the hint bit until some
                                 96                 :  * future re-examination of the tuple.
                                 97                 :  *
                                 98                 :  * We can always set hint bits when marking a transaction aborted.  (Some
                                 99                 :  * code in heapam.c relies on that!)
                                100                 :  *
                                101                 :  * Also, if we are cleaning up HEAP_MOVED_IN or HEAP_MOVED_OFF entries, then
                                102                 :  * we can always set the hint bits, since pre-9.0 VACUUM FULL always used
                                103                 :  * synchronous commits and didn't move tuples that weren't previously
                                104                 :  * hinted.  (This is not known by this subroutine, but is applied by its
                                105                 :  * callers.)  Note: old-style VACUUM FULL is gone, but we have to keep this
                                106                 :  * module's support for MOVED_OFF/MOVED_IN flag bits for as long as we
                                107                 :  * support in-place update from pre-9.0 databases.
                                108                 :  *
                                109                 :  * Normal commits may be asynchronous, so for those we need to get the LSN
                                110                 :  * of the transaction and then check whether this is flushed.
                                111                 :  *
                                112                 :  * The caller should pass xid as the XID of the transaction to check, or
                                113                 :  * InvalidTransactionId if no check is needed.
                                114                 :  */
                                115                 : static inline void
 5717 tgl                       116 GIC    15836918 : SetHintBits(HeapTupleHeader tuple, Buffer buffer,
                                117                 :             uint16 infomask, TransactionId xid)
                                118                 : {
 5730 tgl                       119 CBC    15836918 :     if (TransactionIdIsValid(xid))
                                120                 :     {
                                121                 :         /* NB: xid must be known committed here! */
 5624 bruce                     122        15734950 :         XLogRecPtr  commitLSN = TransactionIdGetCommitLSN(xid);
                                123                 : 
 2610 andres                    124 GIC    15844070 :         if (BufferIsPermanent(buffer) && XLogNeedsFlush(commitLSN) &&
 2610 andres                    125 CBC      109120 :             BufferGetLSNAtomic(buffer) < commitLSN)
                                126                 :         {
 2610 andres                    127 ECB             :             /* not flushed and no LSN interlock, so don't set hint */
 2610 andres                    128 CBC       93945 :             return;
                                129                 :         }
                                130                 :     }
 5730 tgl                       131 ECB             : 
 5730 tgl                       132 GIC    15742973 :     tuple->t_infomask |= infomask;
 3583 jdavis                    133        15742973 :     MarkBufferDirtyHint(buffer, true);
                                134                 : }
 5730 tgl                       135 ECB             : 
 5717                           136                 : /*
                                137                 :  * HeapTupleSetHintBits --- exported version of SetHintBits()
                                138                 :  *
                                139                 :  * This must be separate because of C99's brain-dead notions about how to
                                140                 :  * implement inline functions.
                                141                 :  */
                                142                 : void
 5717 tgl                       143 GIC         158 : HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
                                144                 :                      uint16 infomask, TransactionId xid)
                                145                 : {
 5717 tgl                       146 CBC         158 :     SetHintBits(tuple, buffer, infomask, xid);
 5717 tgl                       147 GIC         158 : }
                                148                 : 
 5730 tgl                       149 ECB             : 
 9770 scrappy                   150                 : /*
                                151                 :  * HeapTupleSatisfiesSelf
                                152                 :  *      True iff heap tuple is valid "for itself".
                                153                 :  *
                                154                 :  * See SNAPSHOT_MVCC's definition for the intended behaviour.
                                155                 :  *
                                156                 :  * Note:
                                157                 :  *      Assumes heap tuple is valid.
                                158                 :  *
                                159                 :  * The satisfaction of "itself" requires the following:
                                160                 :  *
                                161                 :  * ((Xmin == my-transaction &&              the row was updated by the current transaction, and
                                162                 :  *      (Xmax is null                       it was not deleted
                                163                 :  *       [|| Xmax != my-transaction)])          [or it was deleted by another transaction]
                                164                 :  * ||
                                165                 :  *
                                166                 :  * (Xmin is committed &&                    the row was modified by a committed transaction, and
                                167                 :  *      (Xmax is null ||                    the row has not been deleted, or
                                168                 :  *          (Xmax != my-transaction &&          the row was deleted by another transaction
                                169                 :  *           Xmax is not committed)))           that has not been committed
                                170                 :  */
                                171                 : static bool
 3548 rhaas                     172 GIC        2372 : HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
                                173                 : {
                                174            2372 :     HeapTupleHeader tuple = htup->t_data;
 3260 bruce                     175 ECB             : 
 3548 rhaas                     176 GIC        2372 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                     177 CBC        2372 :     Assert(htup->t_tableOid != InvalidOid);
                                178                 : 
 3395                           179            2372 :     if (!HeapTupleHeaderXminCommitted(tuple))
 9345 bruce                     180 ECB             :     {
 3395 rhaas                     181 GIC        2339 :         if (HeapTupleHeaderXminInvalid(tuple))
 8986 bruce                     182 LBC           0 :             return false;
                                183                 : 
 4808 bruce                     184 ECB             :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   185 GBC        2339 :         if (tuple->t_infomask & HEAP_MOVED_OFF)
                                186                 :         {
 7228 bruce                     187 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     188 ECB             : 
 7228 bruce                     189 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                   190 UBC           0 :                 return false;
 7228 bruce                     191 UIC           0 :             if (!TransactionIdIsInProgress(xvac))
 7781 tgl                       192 EUB             :             {
 7228 bruce                     193 UBC           0 :                 if (TransactionIdDidCommit(xvac))
 7781 tgl                       194 EUB             :                 {
 5717 tgl                       195 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                       196 EUB             :                                 InvalidTransactionId);
 7781 tgl                       197 UIC           0 :                     return false;
 7781 tgl                       198 EUB             :                 }
 5717 tgl                       199 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       200 EUB             :                             InvalidTransactionId);
                                201                 :             }
 8778 vadim4o                   202                 :         }
                                203                 :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   204 GIC        2339 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                                205                 :         {
 7228 bruce                     206 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     207 ECB             : 
 7228 bruce                     208 UIC           0 :             if (!TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                   209 EUB             :             {
 7228 bruce                     210 UIC           0 :                 if (TransactionIdIsInProgress(xvac))
 7781 tgl                       211 UBC           0 :                     return false;
 7228 bruce                     212 UIC           0 :                 if (TransactionIdDidCommit(xvac))
 5717 tgl                       213 UBC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       214 EUB             :                                 InvalidTransactionId);
 7781                           215                 :                 else
                                216                 :                 {
 5717 tgl                       217 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                218                 :                                 InvalidTransactionId);
 7781                           219               0 :                     return false;
 7781 tgl                       220 EUB             :                 }
                                221                 :             }
 8778 vadim4o                   222                 :         }
 3395 rhaas                     223 GIC        2339 :         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                                224                 :         {
 9289 vadim4o                   225            2339 :             if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid */
 8986 bruce                     226 CBC        2278 :                 return true;
                                227                 : 
 3602                           228              61 :             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
 6555 tgl                       229              10 :                 return true;
                                230                 : 
 3728 alvherre                  231              51 :             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 3728 alvherre                  232 ECB             :             {
                                233                 :                 TransactionId xmax;
                                234                 : 
 3728 alvherre                  235 UIC           0 :                 xmax = HeapTupleGetUpdateXid(tuple);
                                236                 : 
                                237                 :                 /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  238 UBC           0 :                 Assert(TransactionIdIsValid(xmax));
                                239                 : 
                                240                 :                 /* updating subtransaction must have aborted */
 3728                           241               0 :                 if (!TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                  242 UIC           0 :                     return true;
                                243                 :                 else
 3728 alvherre                  244 UBC           0 :                     return false;
 3728 alvherre                  245 EUB             :             }
                                246                 : 
 3728 alvherre                  247 GBC          51 :             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                248                 :             {
                                249                 :                 /* deleting subtransaction must have aborted */
 5717 tgl                       250 CBC           9 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                251                 :                             InvalidTransactionId);
 6856 tgl                       252 GIC           9 :                 return true;
 6829 tgl                       253 ECB             :             }
                                254                 : 
 8881 vadim4o                   255 CBC          42 :             return false;
                                256                 :         }
 3395 rhaas                     257 UIC           0 :         else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
 8986 bruce                     258 LBC           0 :             return false;
 3395 rhaas                     259 UIC           0 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
 5717 tgl                       260 UBC           0 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 3395 rhaas                     261 EUB             :                         HeapTupleHeaderGetRawXmin(tuple));
 7781 tgl                       262                 :         else
 6750                           263                 :         {
                                264                 :             /* it must have aborted or crashed */
 5717 tgl                       265 UIC           0 :             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                266                 :                         InvalidTransactionId);
 6546                           267               0 :             return false;
 6750 tgl                       268 EUB             :         }
                                269                 :     }
 7781                           270                 : 
                                271                 :     /* by here, the inserting transaction has committed */
                                272                 : 
 9289 vadim4o                   273 GIC          33 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid or aborted */
 8986 bruce                     274              33 :         return true;
                                275                 : 
 9289 vadim4o                   276 LBC           0 :     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
 8881 vadim4o                   277 ECB             :     {
 3728 alvherre                  278 UIC           0 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 8881 vadim4o                   279 UBC           0 :             return true;
 8720 bruce                     280 UIC           0 :         return false;           /* updated by other */
 8881 vadim4o                   281 EUB             :     }
 9289                           282                 : 
 6555 tgl                       283 UBC           0 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                                284                 :     {
                                285                 :         TransactionId xmax;
 3728 alvherre                  286 EUB             : 
 3728 alvherre                  287 UIC           0 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                                288               0 :             return true;
                                289                 : 
 3728 alvherre                  290 UBC           0 :         xmax = HeapTupleGetUpdateXid(tuple);
 3418 alvherre                  291 EUB             : 
                                292                 :         /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  293 UBC           0 :         Assert(TransactionIdIsValid(xmax));
                                294                 : 
 3728 alvherre                  295 UIC           0 :         if (TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                  296 UBC           0 :             return false;
 3728 alvherre                  297 UIC           0 :         if (TransactionIdIsInProgress(xmax))
 3728 alvherre                  298 UBC           0 :             return true;
                                299               0 :         if (TransactionIdDidCommit(xmax))
                                300               0 :             return false;
 3418 alvherre                  301 EUB             :         /* it must have aborted or crashed */
 6555 tgl                       302 UBC           0 :         return true;
 6555 tgl                       303 EUB             :     }
                                304                 : 
 3728 alvherre                  305 UBC           0 :     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                306                 :     {
 3728 alvherre                  307 UIC           0 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 8881 vadim4o                   308 UBC           0 :             return true;
 8986 bruce                     309 UIC           0 :         return false;
 8881 vadim4o                   310 EUB             :     }
 9345 bruce                     311                 : 
 3728 alvherre                  312 UBC           0 :     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
 6546 tgl                       313 UIC           0 :         return true;
                                314                 : 
 3728 alvherre                  315 UBC           0 :     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
 9345 bruce                     316 EUB             :     {
                                317                 :         /* it must have aborted or crashed */
 5717 tgl                       318 UBC           0 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                319                 :                     InvalidTransactionId);
 8986 bruce                     320 UIC           0 :         return true;
 9345 bruce                     321 EUB             :     }
                                322                 : 
 7781 tgl                       323                 :     /* xmax transaction committed */
                                324                 : 
 3728 alvherre                  325 UIC           0 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                                326                 :     {
 5717 tgl                       327               0 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
 5717 tgl                       328 EUB             :                     InvalidTransactionId);
 8881 vadim4o                   329 UIC           0 :         return true;
 7228 bruce                     330 EUB             :     }
                                331                 : 
 5717 tgl                       332 UBC           0 :     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                                333                 :                 HeapTupleHeaderGetRawXmax(tuple));
 8986 bruce                     334 UIC           0 :     return false;
 9770 scrappy                   335 EUB             : }
                                336                 : 
 5859 tgl                       337                 : /*
                                338                 :  * HeapTupleSatisfiesAny
                                339                 :  *      Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
                                340                 :  */
                                341                 : static bool
 3548 rhaas                     342 GIC     7594353 : HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
                                343                 : {
 5859 tgl                       344         7594353 :     return true;
 5859 tgl                       345 ECB             : }
                                346                 : 
 7753                           347                 : /*
                                348                 :  * HeapTupleSatisfiesToast
                                349                 :  *      True iff heap tuple is valid as a TOAST row.
                                350                 :  *
                                351                 :  * See SNAPSHOT_TOAST's definition for the intended behaviour.
                                352                 :  *
                                353                 :  * This is a simplified version that only checks for VACUUM moving conditions.
                                354                 :  * It's appropriate for TOAST usage because TOAST really doesn't want to do
                                355                 :  * its own time qual checks; if you can see the main table row that contains
                                356                 :  * a TOAST reference, you should be able to see the TOASTed value.  However,
                                357                 :  * vacuuming a TOAST table is independent of the main table, and in case such
                                358                 :  * a vacuum fails partway through, we'd better do this much checking.
                                359                 :  *
                                360                 :  * Among other things, this means you can't do UPDATEs of rows in a TOAST
                                361                 :  * table.
                                362                 :  */
                                363                 : static bool
 3548 rhaas                     364 GIC      173572 : HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
                                365                 :                         Buffer buffer)
                                366                 : {
 3548 rhaas                     367 CBC      173572 :     HeapTupleHeader tuple = htup->t_data;
                                368                 : 
 3548 rhaas                     369 GIC      173572 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                     370 CBC      173572 :     Assert(htup->t_tableOid != InvalidOid);
                                371                 : 
 3395                           372          173572 :     if (!HeapTupleHeaderXminCommitted(tuple))
 7753 tgl                       373 ECB             :     {
 3395 rhaas                     374 GIC      161825 :         if (HeapTupleHeaderXminInvalid(tuple))
 7753 tgl                       375 LBC           0 :             return false;
                                376                 : 
 4808 bruce                     377 ECB             :         /* Used by pre-9.0 binary upgrades */
 7753 tgl                       378 GBC      161825 :         if (tuple->t_infomask & HEAP_MOVED_OFF)
                                379                 :         {
 7228 bruce                     380 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     381 ECB             : 
 7228 bruce                     382 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 7753 tgl                       383 UBC           0 :                 return false;
 7228 bruce                     384 UIC           0 :             if (!TransactionIdIsInProgress(xvac))
 7753 tgl                       385 EUB             :             {
 7228 bruce                     386 UBC           0 :                 if (TransactionIdDidCommit(xvac))
 7753 tgl                       387 EUB             :                 {
 5717 tgl                       388 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                       389 EUB             :                                 InvalidTransactionId);
 7753 tgl                       390 UIC           0 :                     return false;
 7753 tgl                       391 EUB             :                 }
 5717 tgl                       392 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       393 EUB             :                             InvalidTransactionId);
                                394                 :             }
 7753                           395                 :         }
                                396                 :         /* Used by pre-9.0 binary upgrades */
 7753 tgl                       397 GIC      161825 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                                398                 :         {
 7228 bruce                     399 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     400 ECB             : 
 7228 bruce                     401 UIC           0 :             if (!TransactionIdIsCurrentTransactionId(xvac))
 7753 tgl                       402 EUB             :             {
 7228 bruce                     403 UIC           0 :                 if (TransactionIdIsInProgress(xvac))
 7753 tgl                       404 UBC           0 :                     return false;
 7228 bruce                     405 UIC           0 :                 if (TransactionIdDidCommit(xvac))
 5717 tgl                       406 UBC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       407 EUB             :                                 InvalidTransactionId);
 7753                           408                 :                 else
                                409                 :                 {
 5717 tgl                       410 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                411                 :                                 InvalidTransactionId);
 7753                           412               0 :                     return false;
 7753 tgl                       413 EUB             :                 }
                                414                 :             }
                                415                 :         }
                                416                 : 
                                417                 :         /*
                                418                 :          * An invalid Xmin can be left behind by a speculative insertion that
                                419                 :          * is canceled by super-deleting the tuple.  This also applies to
                                420                 :          * TOAST tuples created during speculative insertion.
                                421                 :          */
 2893 andres                    422 GIC      161825 :         else if (!TransactionIdIsValid(HeapTupleHeaderGetXmin(tuple)))
 2893 andres                    423 UIC           0 :             return false;
                                424                 :     }
 7753 tgl                       425 ECB             : 
 7753 tgl                       426 EUB             :     /* otherwise assume the tuple is valid for TOAST. */
 7753 tgl                       427 GIC      173572 :     return true;
                                428                 : }
                                429                 : 
 7753 tgl                       430 ECB             : /*
                                431                 :  * HeapTupleSatisfiesUpdate
                                432                 :  *
                                433                 :  *  This function returns a more detailed result code than most of the
                                434                 :  *  functions in this file, since UPDATE needs to know more than "is it
                                435                 :  *  visible?".  It also allows for user-supplied CommandId rather than
                                436                 :  *  relying on CurrentCommandId.
                                437                 :  *
                                438                 :  *  The possible return codes are:
                                439                 :  *
                                440                 :  *  TM_Invisible: the tuple didn't exist at all when the scan started, e.g. it
                                441                 :  *  was created by a later CommandId.
                                442                 :  *
                                443                 :  *  TM_Ok: The tuple is valid and visible, so it may be updated.
                                444                 :  *
                                445                 :  *  TM_SelfModified: The tuple was updated by the current transaction, after
                                446                 :  *  the current scan started.
                                447                 :  *
                                448                 :  *  TM_Updated: The tuple was updated by a committed transaction (including
                                449                 :  *  the case where the tuple was moved into a different partition).
                                450                 :  *
                                451                 :  *  TM_Deleted: The tuple was deleted by a committed transaction.
                                452                 :  *
                                453                 :  *  TM_BeingModified: The tuple is being updated by an in-progress transaction
                                454                 :  *  other than the current transaction.  (Note: this includes the case where
                                455                 :  *  the tuple is share-locked by a MultiXact, even if the MultiXact includes
                                456                 :  *  the current transaction.  Callers that want to distinguish that case must
                                457                 :  *  test for it themselves.)
                                458                 :  */
                                459                 : TM_Result
 3548 rhaas                     460 GIC     1921671 : HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
                                461                 :                          Buffer buffer)
                                462                 : {
 3548 rhaas                     463 CBC     1921671 :     HeapTupleHeader tuple = htup->t_data;
                                464                 : 
 3548 rhaas                     465 GIC     1921671 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                     466 CBC     1921671 :     Assert(htup->t_tableOid != InvalidOid);
                                467                 : 
 3395                           468         1921671 :     if (!HeapTupleHeaderXminCommitted(tuple))
 8881 vadim4o                   469 ECB             :     {
 3395 rhaas                     470 GIC      227351 :         if (HeapTupleHeaderXminInvalid(tuple))
 1478 andres                    471 LBC           0 :             return TM_Invisible;
                                472                 : 
 4808 bruce                     473 ECB             :         /* Used by pre-9.0 binary upgrades */
 7781 tgl                       474 GBC      227351 :         if (tuple->t_infomask & HEAP_MOVED_OFF)
                                475                 :         {
 7228 bruce                     476 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     477 ECB             : 
 7228 bruce                     478 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 1478 andres                    479 UBC           0 :                 return TM_Invisible;
 7228 bruce                     480 UIC           0 :             if (!TransactionIdIsInProgress(xvac))
 7781 tgl                       481 EUB             :             {
 7228 bruce                     482 UBC           0 :                 if (TransactionIdDidCommit(xvac))
 7781 tgl                       483 EUB             :                 {
 5717 tgl                       484 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                       485 EUB             :                                 InvalidTransactionId);
 1478 andres                    486 UIC           0 :                     return TM_Invisible;
 7781 tgl                       487 EUB             :                 }
 5717 tgl                       488 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       489 EUB             :                             InvalidTransactionId);
                                490                 :             }
 8778 vadim4o                   491                 :         }
                                492                 :         /* Used by pre-9.0 binary upgrades */
 7781 tgl                       493 GIC      227351 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                                494                 :         {
 7228 bruce                     495 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     496 ECB             : 
 7228 bruce                     497 UIC           0 :             if (!TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                   498 EUB             :             {
 7228 bruce                     499 UIC           0 :                 if (TransactionIdIsInProgress(xvac))
 1478 andres                    500 UBC           0 :                     return TM_Invisible;
 7228 bruce                     501 UIC           0 :                 if (TransactionIdDidCommit(xvac))
 5717 tgl                       502 UBC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       503 EUB             :                                 InvalidTransactionId);
 7781                           504                 :                 else
                                505                 :                 {
 5717 tgl                       506 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                507                 :                                 InvalidTransactionId);
 1478 andres                    508               0 :                     return TM_Invisible;
 7781 tgl                       509 EUB             :                 }
                                510                 :             }
 8778 vadim4o                   511                 :         }
 3395 rhaas                     512 GIC      227351 :         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                                513                 :         {
 7603 bruce                     514          224965 :             if (HeapTupleHeaderGetCmin(tuple) >= curcid)
 1478 andres                    515 CBC          12 :                 return TM_Invisible;    /* inserted after scan started */
                                516                 : 
 7522 bruce                     517          224953 :             if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid */
 1478 andres                    518          184759 :                 return TM_Ok;
                                519                 : 
 3399 alvherre                  520           40194 :             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 3399 alvherre                  521 ECB             :             {
                                522                 :                 TransactionId xmax;
                                523                 : 
 3399 alvherre                  524 GIC       40184 :                 xmax = HeapTupleHeaderGetRawXmax(tuple);
                                525                 : 
                                526                 :                 /*
 3399 alvherre                  527 ECB             :                  * Careful here: even though this tuple was created by our own
                                528                 :                  * transaction, it might be locked by other transactions, if
                                529                 :                  * the original version was key-share locked when we updated
                                530                 :                  * it.
                                531                 :                  */
                                532                 : 
 3399 alvherre                  533 GIC       40184 :                 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                                534                 :                 {
 2921                           535              31 :                     if (MultiXactIdIsRunning(xmax, true))
 1478 andres                    536 CBC          31 :                         return TM_BeingModified;
                                537                 :                     else
 1478 andres                    538 LBC           0 :                         return TM_Ok;
 3399 alvherre                  539 ECB             :                 }
                                540                 : 
 2921 alvherre                  541 EUB             :                 /*
                                542                 :                  * If the locker is gone, then there is nothing of interest
                                543                 :                  * left in this Xmax; otherwise, report the tuple as
                                544                 :                  * locked/updated.
                                545                 :                  */
 3399 alvherre                  546 GIC       40153 :                 if (!TransactionIdIsInProgress(xmax))
 1478 andres                    547 UIC           0 :                     return TM_Ok;
 1478 andres                    548 GIC       40153 :                 return TM_BeingModified;
 3399 alvherre                  549 ECB             :             }
 6555 tgl                       550 EUB             : 
 3728 alvherre                  551 CBC          10 :             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                                552                 :             {
                                553                 :                 TransactionId xmax;
 3728 alvherre                  554 ECB             : 
 3728 alvherre                  555 GIC           7 :                 xmax = HeapTupleGetUpdateXid(tuple);
                                556                 : 
                                557                 :                 /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  558 CBC           7 :                 Assert(TransactionIdIsValid(xmax));
                                559                 : 
                                560                 :                 /* deleting subtransaction must have aborted */
 3728                           561               7 :                 if (!TransactionIdIsCurrentTransactionId(xmax))
                                562                 :                 {
 2921 alvherre                  563 GIC           7 :                     if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
 2878 bruce                     564 ECB             :                                              false))
 1478 andres                    565 GIC           7 :                         return TM_BeingModified;
 1478 andres                    566 LBC           0 :                     return TM_Ok;
                                567                 :                 }
 3728 alvherre                  568 ECB             :                 else
 3728 alvherre                  569 EUB             :                 {
 3728 alvherre                  570 UIC           0 :                     if (HeapTupleHeaderGetCmax(tuple) >= curcid)
 1478 andres                    571               0 :                         return TM_SelfModified; /* updated after scan started */
                                572                 :                     else
 1478 andres                    573 UBC           0 :                         return TM_Invisible;    /* updated before scan started */
 3728 alvherre                  574 EUB             :                 }
                                575                 :             }
 6555 tgl                       576                 : 
 3728 alvherre                  577 GIC           3 :             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                578                 :             {
                                579                 :                 /* deleting subtransaction must have aborted */
 5717 tgl                       580 LBC           0 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                581                 :                             InvalidTransactionId);
 1478 andres                    582 UIC           0 :                 return TM_Ok;
 6829 tgl                       583 EUB             :             }
                                584                 : 
 7603 bruce                     585 GBC           3 :             if (HeapTupleHeaderGetCmax(tuple) >= curcid)
 1478 andres                    586 GIC           3 :                 return TM_SelfModified; /* updated after scan started */
                                587                 :             else
 1478 andres                    588 LBC           0 :                 return TM_Invisible;    /* updated before scan started */
 8881 vadim4o                   589 ECB             :         }
 3395 rhaas                     590 GIC        2386 :         else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
 1478 andres                    591 UBC           0 :             return TM_Invisible;
 3395 rhaas                     592 GIC        2386 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
 5717 tgl                       593 CBC        2386 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 3395 rhaas                     594 EUB             :                         HeapTupleHeaderGetRawXmin(tuple));
 7781 tgl                       595 ECB             :         else
 6750                           596                 :         {
                                597                 :             /* it must have aborted or crashed */
 5717 tgl                       598 UIC           0 :             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                599                 :                         InvalidTransactionId);
 1478 andres                    600               0 :             return TM_Invisible;
 6750 tgl                       601 EUB             :         }
                                602                 :     }
 8881 vadim4o                   603                 : 
                                604                 :     /* by here, the inserting transaction has committed */
                                605                 : 
 7522 bruce                     606 GIC     1696706 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid or aborted */
 1478 andres                    607         1649725 :         return TM_Ok;
                                608                 : 
 7781 tgl                       609 CBC       46981 :     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
 8881 vadim4o                   610 ECB             :     {
 3728 alvherre                  611 GIC          99 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 1478 andres                    612 LBC           0 :             return TM_Ok;
  776 alvherre                  613 GIC          99 :         if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
 1478 andres                    614 CBC          98 :             return TM_Updated;  /* updated by other */
 1478 andres                    615 EUB             :         else
 1478 andres                    616 CBC           1 :             return TM_Deleted;  /* deleted by other */
 8881 vadim4o                   617 ECB             :     }
                                618                 : 
 6555 tgl                       619 CBC       46882 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                                620                 :     {
                                621                 :         TransactionId xmax;
 6555 tgl                       622 ECB             : 
 2480 alvherre                  623 GIC         586 :         if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
 1478 andres                    624 UIC           0 :             return TM_Ok;
                                625                 : 
 3728 alvherre                  626 CBC         586 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 3728 alvherre                  627 EUB             :         {
 2480 alvherre                  628 GIC         549 :             if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), true))
 1478 andres                    629 CBC          98 :                 return TM_BeingModified;
                                630                 : 
 3728 alvherre                  631             451 :             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
 1478 andres                    632             451 :             return TM_Ok;
                                633                 :         }
 3728 alvherre                  634 ECB             : 
 3728 alvherre                  635 CBC          37 :         xmax = HeapTupleGetUpdateXid(tuple);
 3176 alvherre                  636 GIC          37 :         if (!TransactionIdIsValid(xmax))
                                637                 :         {
 3176 alvherre                  638 LBC           0 :             if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
 1478 andres                    639               0 :                 return TM_BeingModified;
                                640                 :         }
 3728 alvherre                  641 EUB             : 
 3418                           642                 :         /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  643 GIC          37 :         Assert(TransactionIdIsValid(xmax));
                                644                 : 
 3728                           645              37 :         if (TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                  646 ECB             :         {
 3728 alvherre                  647 UIC           0 :             if (HeapTupleHeaderGetCmax(tuple) >= curcid)
 1478 andres                    648 LBC           0 :                 return TM_SelfModified; /* updated after scan started */
                                649                 :             else
 1478 andres                    650 UBC           0 :                 return TM_Invisible;    /* updated before scan started */
 3728 alvherre                  651 EUB             :         }
                                652                 : 
 3176 alvherre                  653 GBC          37 :         if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
 1478 andres                    654 GIC          31 :             return TM_BeingModified;
                                655                 : 
 3728 alvherre                  656 CBC           6 :         if (TransactionIdDidCommit(xmax))
 1478 andres                    657 ECB             :         {
  776 alvherre                  658 GIC           1 :             if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
 1478 andres                    659 LBC           0 :                 return TM_Updated;
                                660                 :             else
 1478 andres                    661 CBC           1 :                 return TM_Deleted;
 1478 andres                    662 EUB             :         }
                                663                 : 
 3412 alvherre                  664 ECB             :         /*
                                665                 :          * By here, the update in the Xmax is either aborted or crashed, but
                                666                 :          * what about the other members?
                                667                 :          */
                                668                 : 
 3176 alvherre                  669 GIC           5 :         if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
                                670                 :         {
                                671                 :             /*
 3412 alvherre                  672 ECB             :              * There's no member, even just a locker, alive anymore, so we can
                                673                 :              * mark the Xmax as invalid.
                                674                 :              */
 3418 alvherre                  675 GIC           5 :             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                676                 :                         InvalidTransactionId);
 1478 andres                    677               5 :             return TM_Ok;
 3412 alvherre                  678 ECB             :         }
                                679                 :         else
                                680                 :         {
                                681                 :             /* There are lockers running */
 1478 andres                    682 UIC           0 :             return TM_BeingModified;
                                683                 :         }
                                684                 :     }
 6555 tgl                       685 EUB             : 
 3728 alvherre                  686 GIC       46296 :     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                687                 :     {
                                688           41794 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 1478 andres                    689 CBC       41728 :             return TM_BeingModified;
 7603 bruce                     690 GIC          66 :         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
 1478 andres                    691 CBC          66 :             return TM_SelfModified; /* updated after scan started */
 8881 vadim4o                   692 ECB             :         else
 1478 andres                    693 LBC           0 :             return TM_Invisible;    /* updated before scan started */
 8881 vadim4o                   694 ECB             :     }
                                695                 : 
 3728 alvherre                  696 GBC        4502 :     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
 1478 andres                    697 GIC        1188 :         return TM_BeingModified;
                                698                 : 
 3728 alvherre                  699 CBC        3314 :     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
 8881 vadim4o                   700 ECB             :     {
                                701                 :         /* it must have aborted or crashed */
 5717 tgl                       702 CBC         120 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                703                 :                     InvalidTransactionId);
 1478 andres                    704 GIC         120 :         return TM_Ok;
 8881 vadim4o                   705 ECB             :     }
                                706                 : 
                                707                 :     /* xmax transaction committed */
                                708                 : 
 3728 alvherre                  709 GIC        3194 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                                710                 :     {
 5717 tgl                       711            3160 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
 5717 tgl                       712 ECB             :                     InvalidTransactionId);
 1478 andres                    713 GIC        3160 :         return TM_Ok;
 7228 bruce                     714 ECB             :     }
                                715                 : 
 5717 tgl                       716 CBC          34 :     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                                717                 :                 HeapTupleHeaderGetRawXmax(tuple));
  776 alvherre                  718 GIC          34 :     if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
 1478 andres                    719 CBC          34 :         return TM_Updated;      /* updated by other */
                                720                 :     else
 1478 andres                    721 LBC           0 :         return TM_Deleted;      /* deleted by other */
 8881 vadim4o                   722 ECB             : }
                                723                 : 
 7753 tgl                       724 EUB             : /*
                                725                 :  * HeapTupleSatisfiesDirty
                                726                 :  *      True iff heap tuple is valid including effects of open transactions.
                                727                 :  *
                                728                 :  * See SNAPSHOT_DIRTY's definition for the intended behaviour.
                                729                 :  *
                                730                 :  * This is essentially like HeapTupleSatisfiesSelf as far as effects of
                                731                 :  * the current transaction and committed/aborted xacts are concerned.
                                732                 :  * However, we also include the effects of other xacts still in progress.
                                733                 :  *
                                734                 :  * A special hack is that the passed-in snapshot struct is used as an
                                735                 :  * output argument to return the xids of concurrent xacts that affected the
                                736                 :  * tuple.  snapshot->xmin is set to the tuple's xmin if that is another
                                737                 :  * transaction that's still in progress; or to InvalidTransactionId if the
                                738                 :  * tuple's xmin is committed good, committed dead, or my own xact.
                                739                 :  * Similarly for snapshot->xmax and the tuple's xmax.  If the tuple was
                                740                 :  * inserted speculatively, meaning that the inserter might still back down
                                741                 :  * on the insertion without aborting the whole transaction, the associated
                                742                 :  * token is also returned in snapshot->speculativeToken.
                                743                 :  */
                                744                 : static bool
 3548 rhaas                     745 GIC     5994614 : HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
                                746                 :                         Buffer buffer)
                                747                 : {
 3548 rhaas                     748 CBC     5994614 :     HeapTupleHeader tuple = htup->t_data;
                                749                 : 
 3548 rhaas                     750 GIC     5994614 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                     751 CBC     5994614 :     Assert(htup->t_tableOid != InvalidOid);
                                752                 : 
 5859 tgl                       753         5994614 :     snapshot->xmin = snapshot->xmax = InvalidTransactionId;
 2893 andres                    754         5994614 :     snapshot->speculativeToken = 0;
                                755                 : 
 3395 rhaas                     756         5994614 :     if (!HeapTupleHeaderXminCommitted(tuple))
 8881 vadim4o                   757 ECB             :     {
 3395 rhaas                     758 GIC     5564070 :         if (HeapTupleHeaderXminInvalid(tuple))
 8881 vadim4o                   759 CBC         273 :             return false;
                                760                 : 
 4808 bruce                     761 ECB             :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   762 CBC     5563797 :         if (tuple->t_infomask & HEAP_MOVED_OFF)
                                763                 :         {
 7228 bruce                     764 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     765 ECB             : 
 7228 bruce                     766 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 8770 vadim4o                   767 UBC           0 :                 return false;
 7228 bruce                     768 UIC           0 :             if (!TransactionIdIsInProgress(xvac))
 8778 vadim4o                   769 EUB             :             {
 7228 bruce                     770 UBC           0 :                 if (TransactionIdDidCommit(xvac))
 7781 tgl                       771 EUB             :                 {
 5717 tgl                       772 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                       773 EUB             :                                 InvalidTransactionId);
 7781 tgl                       774 UIC           0 :                     return false;
 7781 tgl                       775 EUB             :                 }
 5717 tgl                       776 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       777 EUB             :                             InvalidTransactionId);
                                778                 :             }
 8778 vadim4o                   779                 :         }
                                780                 :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   781 GIC     5563797 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                                782                 :         {
 7228 bruce                     783 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     784 ECB             : 
 7228 bruce                     785 UIC           0 :             if (!TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                   786 EUB             :             {
 7228 bruce                     787 UIC           0 :                 if (TransactionIdIsInProgress(xvac))
 7781 tgl                       788 UBC           0 :                     return false;
 7228 bruce                     789 UIC           0 :                 if (TransactionIdDidCommit(xvac))
 5717 tgl                       790 UBC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       791 EUB             :                                 InvalidTransactionId);
 8763 vadim4o                   792                 :                 else
                                793                 :                 {
 5717 tgl                       794 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                795                 :                                 InvalidTransactionId);
 8763 vadim4o                   796               0 :                     return false;
 8763 vadim4o                   797 EUB             :                 }
                                798                 :             }
 8778                           799                 :         }
 3395 rhaas                     800 GIC     5563797 :         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                                801                 :         {
 8881 vadim4o                   802         5548925 :             if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid */
 8881 vadim4o                   803 CBC       30216 :                 return true;
                                804                 : 
 3602 bruce                     805         5518709 :             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
 6555 tgl                       806            5038 :                 return true;
                                807                 : 
 3728 alvherre                  808         5513671 :             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 3728 alvherre                  809 ECB             :             {
                                810                 :                 TransactionId xmax;
 6555 tgl                       811                 : 
 3728 alvherre                  812 GIC          16 :                 xmax = HeapTupleGetUpdateXid(tuple);
                                813                 : 
                                814                 :                 /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  815 CBC          16 :                 Assert(TransactionIdIsValid(xmax));
                                816                 : 
                                817                 :                 /* updating subtransaction must have aborted */
 3728                           818              16 :                 if (!TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                  819 UIC           0 :                     return true;
                                820                 :                 else
 3728 alvherre                  821 CBC          16 :                     return false;
 3728 alvherre                  822 EUB             :             }
                                823                 : 
 3728 alvherre                  824 CBC     5513655 :             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                825                 :             {
                                826                 :                 /* deleting subtransaction must have aborted */
 5717 tgl                       827 LBC           0 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                828                 :                             InvalidTransactionId);
 6856 tgl                       829 UIC           0 :                 return true;
 6829 tgl                       830 EUB             :             }
                                831                 : 
 8881 vadim4o                   832 GBC     5513655 :             return false;
                                833                 :         }
 3395 rhaas                     834 GIC       14872 :         else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
 8881 vadim4o                   835 ECB             :         {
                                836                 :             /*
 2878 bruce                     837                 :              * Return the speculative token to caller.  Caller can worry about
                                838                 :              * xmax, since it requires a conclusively locked row version, and
                                839                 :              * a concurrent update to this tuple is a conflict of its
                                840                 :              * purposes.
                                841                 :              */
 2893 andres                    842 GIC          55 :             if (HeapTupleHeaderIsSpeculative(tuple))
                                843                 :             {
                                844               2 :                 snapshot->speculativeToken =
 2893 andres                    845 CBC           2 :                     HeapTupleHeaderGetSpeculativeToken(tuple);
                                846                 : 
                                847               2 :                 Assert(snapshot->speculativeToken != 0);
 2893 andres                    848 ECB             :             }
                                849                 : 
 3395 rhaas                     850 CBC          55 :             snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
                                851                 :             /* XXX shouldn't we fall through to look at xmax? */
 8720 bruce                     852 GIC          55 :             return true;        /* in insertion by other */
 8881 vadim4o                   853 ECB             :         }
 3395 rhaas                     854 GIC       14817 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
 5717 tgl                       855 CBC       14580 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                                856                 :                         HeapTupleHeaderGetRawXmin(tuple));
 6546 tgl                       857 ECB             :         else
                                858                 :         {
                                859                 :             /* it must have aborted or crashed */
 5717 tgl                       860 GIC         237 :             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                                861                 :                         InvalidTransactionId);
 6546                           862             237 :             return false;
 6546 tgl                       863 ECB             :         }
                                864                 :     }
 8881 vadim4o                   865                 : 
                                866                 :     /* by here, the inserting transaction has committed */
                                867                 : 
 8881 vadim4o                   868 GIC      445124 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid or aborted */
                                869          132110 :         return true;
                                870                 : 
 8881 vadim4o                   871 CBC      313014 :     if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
 8881 vadim4o                   872 ECB             :     {
 3728 alvherre                  873 GIC       63766 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 8881 vadim4o                   874 LBC           0 :             return true;
 8720 bruce                     875 GIC       63766 :         return false;           /* updated by other */
 8881 vadim4o                   876 ECB             :     }
 8881 vadim4o                   877 EUB             : 
 6555 tgl                       878 CBC      249248 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                                879                 :     {
                                880                 :         TransactionId xmax;
 3728 alvherre                  881 ECB             : 
 3728 alvherre                  882 GIC          30 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                                883              13 :             return true;
                                884                 : 
 3728 alvherre                  885 CBC          17 :         xmax = HeapTupleGetUpdateXid(tuple);
 3418 alvherre                  886 ECB             : 
                                887                 :         /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                  888 CBC          17 :         Assert(TransactionIdIsValid(xmax));
                                889                 : 
 3728 alvherre                  890 GIC          17 :         if (TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                  891 CBC           1 :             return false;
 3728 alvherre                  892 GIC          16 :         if (TransactionIdIsInProgress(xmax))
 3728 alvherre                  893 ECB             :         {
 3728 alvherre                  894 LBC           0 :             snapshot->xmax = xmax;
                                895               0 :             return true;
                                896                 :         }
 3728 alvherre                  897 GBC          16 :         if (TransactionIdDidCommit(xmax))
                                898              16 :             return false;
                                899                 :         /* it must have aborted or crashed */
 6555 tgl                       900 LBC           0 :         return true;
 6555 tgl                       901 ECB             :     }
                                902                 : 
 3728 alvherre                  903 GBC      249218 :     if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                                904                 :     {
 3728 alvherre                  905 GIC      219375 :         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 8315 inoue                     906 CBC          22 :             return true;
 8881 vadim4o                   907 GIC      219353 :         return false;
 8315 inoue                     908 ECB             :     }
 8881 vadim4o                   909                 : 
 3728 alvherre                  910 CBC       29843 :     if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
                                911                 :     {
 3537 alvherre                  912 GIC          14 :         if (!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 3537 alvherre                  913 CBC          12 :             snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
 6546 tgl                       914 GIC          14 :         return true;
 6546 tgl                       915 ECB             :     }
                                916                 : 
 3728 alvherre                  917 CBC       29829 :     if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
                                918                 :     {
                                919                 :         /* it must have aborted or crashed */
 5717 tgl                       920               9 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                                921                 :                     InvalidTransactionId);
 6546 tgl                       922 GIC           9 :         return true;
 8881 vadim4o                   923 ECB             :     }
                                924                 : 
                                925                 :     /* xmax transaction committed */
                                926                 : 
 3728 alvherre                  927 GIC       29820 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                                928                 :     {
 5717 tgl                       929           13443 :         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
 5717 tgl                       930 ECB             :                     InvalidTransactionId);
 8881 vadim4o                   931 GIC       13443 :         return true;
 7228 bruce                     932 ECB             :     }
                                933                 : 
 5717 tgl                       934 CBC       16377 :     SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                                935                 :                 HeapTupleHeaderGetRawXmax(tuple));
 8720 bruce                     936 GIC       16377 :     return false;               /* updated by other */
 8881 vadim4o                   937 ECB             : }
                                938                 : 
 7753 tgl                       939                 : /*
                                940                 :  * HeapTupleSatisfiesMVCC
                                941                 :  *      True iff heap tuple is valid for the given MVCC snapshot.
                                942                 :  *
                                943                 :  * See SNAPSHOT_MVCC's definition for the intended behaviour.
                                944                 :  *
                                945                 :  * Notice that here, we will not update the tuple status hint bits if the
                                946                 :  * inserting/deleting transaction is still running according to our snapshot,
                                947                 :  * even if in reality it's committed or aborted by now.  This is intentional.
                                948                 :  * Checking the true transaction state would require access to high-traffic
                                949                 :  * shared data structures, creating contention we'd rather do without, and it
                                950                 :  * would not change the result of our visibility check anyway.  The hint bits
                                951                 :  * will be updated by the first visitor that has a snapshot new enough to see
                                952                 :  * the inserting/deleting transaction as done.  In the meantime, the cost of
                                953                 :  * leaving the hint bits unset is basically that each HeapTupleSatisfiesMVCC
                                954                 :  * call will need to run TransactionIdIsCurrentTransactionId in addition to
                                955                 :  * XidInMVCCSnapshot (but it would have to do the latter anyway).  In the old
                                956                 :  * coding where we tried to set the hint bits as soon as possible, we instead
                                957                 :  * did TransactionIdIsInProgress in each call --- to no avail, as long as the
                                958                 :  * inserting/deleting transaction was still running --- which was more cycles
                                959                 :  * and more contention on ProcArrayLock.
                                960                 :  */
                                961                 : static bool
 3548 rhaas                     962 GIC   203462247 : HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
                                963                 :                        Buffer buffer)
                                964                 : {
 3548 rhaas                     965 CBC   203462247 :     HeapTupleHeader tuple = htup->t_data;
                                966                 : 
 3548 rhaas                     967 GIC   203462247 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                     968 CBC   203462247 :     Assert(htup->t_tableOid != InvalidOid);
                                969                 : 
 3395                           970       203462247 :     if (!HeapTupleHeaderXminCommitted(tuple))
 8880 vadim4o                   971 ECB             :     {
 3395 rhaas                     972 GIC    20306498 :         if (HeapTupleHeaderXminInvalid(tuple))
 8880 vadim4o                   973 CBC      124778 :             return false;
                                974                 : 
 4808 bruce                     975 ECB             :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   976 CBC    20181720 :         if (tuple->t_infomask & HEAP_MOVED_OFF)
                                977                 :         {
 7228 bruce                     978 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     979 ECB             : 
 7228 bruce                     980 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                   981 UBC           0 :                 return false;
 2783 tgl                       982 UIC           0 :             if (!XidInMVCCSnapshot(xvac, snapshot))
 7781 tgl                       983 EUB             :             {
 7228 bruce                     984 UBC           0 :                 if (TransactionIdDidCommit(xvac))
 7781 tgl                       985 EUB             :                 {
 5717 tgl                       986 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                       987 EUB             :                                 InvalidTransactionId);
 7781 tgl                       988 UIC           0 :                     return false;
 7781 tgl                       989 EUB             :                 }
 5717 tgl                       990 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                       991 EUB             :                             InvalidTransactionId);
                                992                 :             }
 8778 vadim4o                   993                 :         }
                                994                 :         /* Used by pre-9.0 binary upgrades */
 8778 vadim4o                   995 GIC    20181720 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                                996                 :         {
 7228 bruce                     997 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                     998 ECB             : 
 7228 bruce                     999 UIC           0 :             if (!TransactionIdIsCurrentTransactionId(xvac))
 8778 vadim4o                  1000 EUB             :             {
 2783 tgl                      1001 UIC           0 :                 if (XidInMVCCSnapshot(xvac, snapshot))
 7781 tgl                      1002 UBC           0 :                     return false;
 7228 bruce                    1003 UIC           0 :                 if (TransactionIdDidCommit(xvac))
 5717 tgl                      1004 UBC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                      1005 EUB             :                                 InvalidTransactionId);
 7781                          1006                 :                 else
                               1007                 :                 {
 5717 tgl                      1008 UIC           0 :                     SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                               1009                 :                                 InvalidTransactionId);
 7781                          1010               0 :                     return false;
 7781 tgl                      1011 EUB             :                 }
                               1012                 :             }
 8778 vadim4o                  1013                 :         }
 3395 rhaas                    1014 GIC    20181720 :         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                               1015                 :         {
 7603 bruce                    1016        11576545 :             if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
 8880 vadim4o                  1017 CBC        8067 :                 return false;   /* inserted after scan started */
                               1018                 : 
                               1019        11568478 :             if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid */
                               1020         8698005 :                 return true;
                               1021                 : 
 3602 bruce                    1022         2870473 :             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
 6555 tgl                      1023            2129 :                 return true;
                               1024                 : 
 3728 alvherre                 1025         2868344 :             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 3728 alvherre                 1026 ECB             :             {
                               1027                 :                 TransactionId xmax;
                               1028                 : 
 3728 alvherre                 1029 GIC           7 :                 xmax = HeapTupleGetUpdateXid(tuple);
                               1030                 : 
                               1031                 :                 /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                 1032 CBC           7 :                 Assert(TransactionIdIsValid(xmax));
                               1033                 : 
                               1034                 :                 /* updating subtransaction must have aborted */
 3728                          1035               7 :                 if (!TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                 1036 GIC           7 :                     return true;
 3728 alvherre                 1037 UIC           0 :                 else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
 3728 alvherre                 1038 LBC           0 :                     return true;    /* updated after scan started */
 3728 alvherre                 1039 ECB             :                 else
 2118 tgl                      1040 UBC           0 :                     return false;   /* updated before scan started */
 3728 alvherre                 1041 EUB             :             }
                               1042                 : 
 3728 alvherre                 1043 GBC     2868337 :             if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
                               1044                 :             {
                               1045                 :                 /* deleting subtransaction must have aborted */
 5717 tgl                      1046 CBC          17 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                               1047                 :                             InvalidTransactionId);
 6856 tgl                      1048 GIC          17 :                 return true;
 6829 tgl                      1049 ECB             :             }
                               1050                 : 
 7603 bruce                    1051 CBC     2868320 :             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
 8880 vadim4o                  1052 GIC         688 :                 return true;    /* deleted after scan started */
                               1053                 :             else
 8880 vadim4o                  1054 CBC     2867632 :                 return false;   /* deleted before scan started */
 8880 vadim4o                  1055 ECB             :         }
 2783 tgl                      1056 GIC     8605175 :         else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
 8880 vadim4o                  1057 CBC        8078 :             return false;
 3395 rhaas                    1058 GIC     8597097 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
 5717 tgl                      1059 CBC     8547440 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 3395 rhaas                    1060 ECB             :                         HeapTupleHeaderGetRawXmin(tuple));
 7781 tgl                      1061                 :         else
 6750                          1062                 :         {
                               1063                 :             /* it must have aborted or crashed */
 5717 tgl                      1064 GIC       49657 :             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                               1065                 :                         InvalidTransactionId);
 6546                          1066           49657 :             return false;
 6750 tgl                      1067 ECB             :         }
                               1068                 :     }
 2783                          1069                 :     else
                               1070                 :     {
                               1071                 :         /* xmin is committed, but maybe not according to our snapshot */
 2783 tgl                      1072 GIC   364345088 :         if (!HeapTupleHeaderXminFrozen(tuple) &&
                               1073       181189339 :             XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
                               1074             826 :             return false;       /* treat as still in progress */
 2783 tgl                      1075 ECB             :     }
 8880 vadim4o                  1076                 : 
 2783 tgl                      1077                 :     /* by here, the inserting transaction has committed */
                               1078                 : 
 8880 vadim4o                  1079 GIC   191702363 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid or aborted */
                               1080       188247791 :         return true;
                               1081                 : 
 3728 alvherre                 1082 CBC     3454572 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 6555 tgl                      1083           42099 :         return true;
                               1084                 : 
                               1085         3412473 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 6555 tgl                      1086 ECB             :     {
                               1087                 :         TransactionId xmax;
 3728 alvherre                 1088                 : 
                               1089                 :         /* already checked above */
 3728 alvherre                 1090 GIC         151 :         Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
                               1091                 : 
                               1092             151 :         xmax = HeapTupleGetUpdateXid(tuple);
 3418 alvherre                 1093 ECB             : 
                               1094                 :         /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                 1095 CBC         151 :         Assert(TransactionIdIsValid(xmax));
                               1096                 : 
 3728 alvherre                 1097 GIC         151 :         if (TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                 1098 ECB             :         {
 3728 alvherre                 1099 GIC          23 :             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
 3728 alvherre                 1100 LBC           0 :                 return true;    /* deleted after scan started */
                               1101                 :             else
 3728 alvherre                 1102 CBC          23 :                 return false;   /* deleted before scan started */
 3728 alvherre                 1103 EUB             :         }
 2783 tgl                      1104 GIC         128 :         if (XidInMVCCSnapshot(xmax, snapshot))
 3728 alvherre                 1105 CBC          18 :             return true;
 3728 alvherre                 1106 GIC         110 :         if (TransactionIdDidCommit(xmax))
 2783 tgl                      1107 CBC         105 :             return false;       /* updating transaction committed */
 3418 alvherre                 1108 ECB             :         /* it must have aborted or crashed */
 8880 vadim4o                  1109 CBC           5 :         return true;
 6555 tgl                      1110 ECB             :     }
                               1111                 : 
 8880 vadim4o                  1112 CBC     3412322 :     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
                               1113                 :     {
 3728 alvherre                 1114 GIC      433793 :         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
 8880 vadim4o                  1115 ECB             :         {
 7603 bruce                    1116 GIC      106227 :             if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
 8720 bruce                    1117 CBC        1011 :                 return true;    /* deleted after scan started */
                               1118                 :             else
                               1119          105216 :                 return false;   /* deleted before scan started */
 8880 vadim4o                  1120 ECB             :         }
                               1121                 : 
 2783 tgl                      1122 CBC      327566 :         if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
 6546 tgl                      1123 GIC        4028 :             return true;
                               1124                 : 
 3728 alvherre                 1125 CBC      323538 :         if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
 8880 vadim4o                  1126 ECB             :         {
                               1127                 :             /* it must have aborted or crashed */
 5717 tgl                      1128 CBC        5363 :             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                               1129                 :                         InvalidTransactionId);
 8880 vadim4o                  1130 GIC        5363 :             return true;
 8880 vadim4o                  1131 ECB             :         }
                               1132                 : 
                               1133                 :         /* xmax transaction committed */
 5717 tgl                      1134 GIC      318175 :         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                               1135                 :                     HeapTupleHeaderGetRawXmax(tuple));
                               1136                 :     }
 2783 tgl                      1137 ECB             :     else
                               1138                 :     {
                               1139                 :         /* xmax is committed, but maybe not according to our snapshot */
 2783 tgl                      1140 GIC     2978529 :         if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
                               1141             147 :             return true;        /* treat as still in progress */
                               1142                 :     }
 8880 vadim4o                  1143 ECB             : 
 2783 tgl                      1144                 :     /* xmax transaction committed */
                               1145                 : 
 8880 vadim4o                  1146 GIC     3296557 :     return false;
                               1147                 : }
                               1148                 : 
 7941 tgl                      1149 ECB             : 
                               1150                 : /*
                               1151                 :  * HeapTupleSatisfiesVacuum
                               1152                 :  *
                               1153                 :  *  Determine the status of tuples for VACUUM purposes.  Here, what
                               1154                 :  *  we mainly want to know is if a tuple is potentially visible to *any*
                               1155                 :  *  running transaction.  If so, it can't be removed yet by VACUUM.
                               1156                 :  *
                               1157                 :  * OldestXmin is a cutoff XID (obtained from
                               1158                 :  * GetOldestNonRemovableTransactionId()).  Tuples deleted by XIDs >=
                               1159                 :  * OldestXmin are deemed "recently dead"; they might still be visible to some
                               1160                 :  * open transaction, so we can't remove them, even if we see that the deleting
                               1161                 :  * transaction has committed.
                               1162                 :  */
                               1163                 : HTSV_Result
 3548 rhaas                    1164 GIC    35342555 : HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
                               1165                 :                          Buffer buffer)
                               1166                 : {
  970 andres                   1167 CBC    35342555 :     TransactionId dead_after = InvalidTransactionId;
                               1168                 :     HTSV_Result res;
                               1169                 : 
                               1170        35342555 :     res = HeapTupleSatisfiesVacuumHorizon(htup, buffer, &dead_after);
                               1171                 : 
  970 andres                   1172 GIC    35342555 :     if (res == HEAPTUPLE_RECENTLY_DEAD)
  970 andres                   1173 ECB             :     {
  970 andres                   1174 GIC      669817 :         Assert(TransactionIdIsValid(dead_after));
  970 andres                   1175 ECB             : 
  970 andres                   1176 GIC      669817 :         if (TransactionIdPrecedes(dead_after, OldestXmin))
  970 andres                   1177 CBC       30543 :             res = HEAPTUPLE_DEAD;
                               1178                 :     }
  970 andres                   1179 ECB             :     else
  970 andres                   1180 CBC    34672738 :         Assert(!TransactionIdIsValid(dead_after));
                               1181                 : 
  970 andres                   1182 GIC    35342555 :     return res;
  970 andres                   1183 ECB             : }
                               1184                 : 
                               1185                 : /*
                               1186                 :  * Work horse for HeapTupleSatisfiesVacuum and similar routines.
                               1187                 :  *
                               1188                 :  * In contrast to HeapTupleSatisfiesVacuum this routine, when encountering a
                               1189                 :  * tuple that could still be visible to some backend, stores the xid that
                               1190                 :  * needs to be compared with the horizon in *dead_after, and returns
                               1191                 :  * HEAPTUPLE_RECENTLY_DEAD. The caller then can perform the comparison with
                               1192                 :  * the horizon.  This is e.g. useful when comparing with different horizons.
                               1193                 :  *
                               1194                 :  * Note: HEAPTUPLE_DEAD can still be returned here, e.g. if the inserting
                               1195                 :  * transaction aborted.
                               1196                 :  */
                               1197                 : HTSV_Result
  970 andres                   1198 GIC    50524567 : HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *dead_after)
                               1199                 : {
 3548 rhaas                    1200        50524567 :     HeapTupleHeader tuple = htup->t_data;
 3260 bruce                    1201 ECB             : 
 3548 rhaas                    1202 GIC    50524567 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                    1203 CBC    50524567 :     Assert(htup->t_tableOid != InvalidOid);
  970 andres                   1204 GIC    50524567 :     Assert(dead_after != NULL);
  970 andres                   1205 ECB             : 
  970 andres                   1206 CBC    50524567 :     *dead_after = InvalidTransactionId;
 3548 rhaas                    1207 ECB             : 
                               1208                 :     /*
 7941 tgl                      1209                 :      * Has inserting transaction committed?
                               1210                 :      *
                               1211                 :      * If the inserting transaction aborted, then the tuple was never visible
                               1212                 :      * to any other transaction, so we can delete it immediately.
                               1213                 :      */
 3395 rhaas                    1214 GIC    50524567 :     if (!HeapTupleHeaderXminCommitted(tuple))
                               1215                 :     {
                               1216         7564627 :         if (HeapTupleHeaderXminInvalid(tuple))
 7941 tgl                      1217 CBC        7510 :             return HEAPTUPLE_DEAD;
                               1218                 :         /* Used by pre-9.0 binary upgrades */
                               1219         7557117 :         else if (tuple->t_infomask & HEAP_MOVED_OFF)
 7941 tgl                      1220 ECB             :         {
 7228 bruce                    1221 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                    1222 ECB             : 
 7228 bruce                    1223 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 7781 tgl                      1224 UBC           0 :                 return HEAPTUPLE_DELETE_IN_PROGRESS;
 7228 bruce                    1225 UIC           0 :             if (TransactionIdIsInProgress(xvac))
 7781 tgl                      1226 UBC           0 :                 return HEAPTUPLE_DELETE_IN_PROGRESS;
 7228 bruce                    1227               0 :             if (TransactionIdDidCommit(xvac))
 7941 tgl                      1228 EUB             :             {
 5717 tgl                      1229 UBC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
 5717 tgl                      1230 EUB             :                             InvalidTransactionId);
 7941 tgl                      1231 UIC           0 :                 return HEAPTUPLE_DEAD;
 7941 tgl                      1232 EUB             :             }
 5717 tgl                      1233 UIC           0 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                      1234 EUB             :                         InvalidTransactionId);
                               1235                 :         }
 4808 bruce                    1236                 :         /* Used by pre-9.0 binary upgrades */
 7941 tgl                      1237 GIC     7557117 :         else if (tuple->t_infomask & HEAP_MOVED_IN)
                               1238                 :         {
 7228 bruce                    1239 UIC           0 :             TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
 7188 bruce                    1240 ECB             : 
 7228 bruce                    1241 UIC           0 :             if (TransactionIdIsCurrentTransactionId(xvac))
 7781 tgl                      1242 UBC           0 :                 return HEAPTUPLE_INSERT_IN_PROGRESS;
 7228 bruce                    1243 UIC           0 :             if (TransactionIdIsInProgress(xvac))
 7781 tgl                      1244 UBC           0 :                 return HEAPTUPLE_INSERT_IN_PROGRESS;
 7228 bruce                    1245               0 :             if (TransactionIdDidCommit(xvac))
 5717 tgl                      1246               0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
 5717 tgl                      1247 EUB             :                             InvalidTransactionId);
 7781                          1248                 :             else
 7941                          1249                 :             {
 5717 tgl                      1250 UIC           0 :                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                               1251                 :                             InvalidTransactionId);
 7941                          1252               0 :                 return HEAPTUPLE_DEAD;
 7941 tgl                      1253 EUB             :             }
                               1254                 :         }
 3231 andres                   1255 GBC     7557117 :         else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
                               1256                 :         {
 7139 tgl                      1257 GIC     2060018 :             if (tuple->t_infomask & HEAP_XMAX_INVALID)   /* xid invalid */
 7139 tgl                      1258 CBC     2023854 :                 return HEAPTUPLE_INSERT_IN_PROGRESS;
                               1259                 :             /* only locked? run infomask-only check first, for performance */
 3551 alvherre                 1260           64150 :             if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
                               1261           27986 :                 HeapTupleHeaderIsOnlyLocked(tuple))
 7139 tgl                      1262 GIC        8178 :                 return HEAPTUPLE_INSERT_IN_PROGRESS;
 7139 tgl                      1263 ECB             :             /* inserted and then deleted by same xact */
 3231 andres                   1264 CBC       27986 :             if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple)))
                               1265           27986 :                 return HEAPTUPLE_DELETE_IN_PROGRESS;
                               1266                 :             /* deleting subtransaction must have aborted */
 3231 andres                   1267 LBC           0 :             return HEAPTUPLE_INSERT_IN_PROGRESS;
 3231 andres                   1268 ECB             :         }
 3231 andres                   1269 GIC     5497099 :         else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
 3231 andres                   1270 EUB             :         {
                               1271                 :             /*
 3231 andres                   1272 ECB             :              * It'd be possible to discern between INSERT/DELETE in progress
                               1273                 :              * here by looking at xmax - but that doesn't seem beneficial for
                               1274                 :              * the majority of callers and even detrimental for some. We'd
                               1275                 :              * rather have callers look at/wait for xmin than xmax. It's
                               1276                 :              * always correct to return INSERT_IN_PROGRESS because that's
                               1277                 :              * what's happening from the view of other backends.
                               1278                 :              */
 3231 andres                   1279 GIC        3593 :             return HEAPTUPLE_INSERT_IN_PROGRESS;
                               1280                 :         }
 3395 rhaas                    1281         5493506 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
 5717 tgl                      1282 CBC     5478598 :             SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                               1283                 :                         HeapTupleHeaderGetRawXmin(tuple));
 7941 tgl                      1284 ECB             :         else
                               1285                 :         {
                               1286                 :             /*
                               1287                 :              * Not in Progress, Not Committed, so either Aborted or crashed
                               1288                 :              */
 5717 tgl                      1289 GIC       14908 :             SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                               1290                 :                         InvalidTransactionId);
 7941                          1291           14908 :             return HEAPTUPLE_DEAD;
 7941 tgl                      1292 ECB             :         }
                               1293                 : 
 5730                          1294                 :         /*
                               1295                 :          * At this point the xmin is known committed, but we might not have
                               1296                 :          * been able to set the hint bit yet; so we can no longer Assert that
                               1297                 :          * it's set.
                               1298                 :          */
                               1299                 :     }
                               1300                 : 
                               1301                 :     /*
                               1302                 :      * Okay, the inserter committed, so it was good at some point.  Now what
                               1303                 :      * about the deleting transaction?
                               1304                 :      */
 7941 tgl                      1305 GIC    48438538 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)
                               1306        45746096 :         return HEAPTUPLE_LIVE;
                               1307                 : 
 3728 alvherre                 1308 CBC     2692442 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 7781 tgl                      1309 ECB             :     {
                               1310                 :         /*
 6385 bruce                    1311                 :          * "Deleting" xact really only locked it, so the tuple is live in any
                               1312                 :          * case.  However, we should make sure that either XMAX_COMMITTED or
                               1313                 :          * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
                               1314                 :          * examining the tuple for future xacts.
                               1315                 :          */
 7758 tgl                      1316 GIC       13300 :         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
                               1317                 :         {
 6555                          1318           13300 :             if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 6555 tgl                      1319 ECB             :             {
                               1320                 :                 /*
 2480 alvherre                 1321                 :                  * If it's a pre-pg_upgrade tuple, the multixact cannot
                               1322                 :                  * possibly be running; otherwise have to check.
                               1323                 :                  */
 2480 alvherre                 1324 GIC         416 :                 if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
 3176                          1325             208 :                     MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
                               1326                 :                                          true))
 6555 tgl                      1327 CBC           6 :                     return HEAPTUPLE_LIVE;
 3728 alvherre                 1328             202 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
                               1329                 :             }
 6555 tgl                      1330 ECB             :             else
                               1331                 :             {
 3728 alvherre                 1332 GIC       13092 :                 if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
 6555 tgl                      1333 UIC           0 :                     return HEAPTUPLE_LIVE;
 3728 alvherre                 1334 GIC       13092 :                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
 3728 alvherre                 1335 ECB             :                             InvalidTransactionId);
 6555 tgl                      1336 EUB             :             }
 7758 tgl                      1337 ECB             :         }
                               1338                 : 
                               1339                 :         /*
                               1340                 :          * We don't really care whether xmax did commit, abort or crash. We
                               1341                 :          * know that xmax did lock the tuple, but it did not and will never
                               1342                 :          * actually update it.
                               1343                 :          */
                               1344                 : 
 7781 tgl                      1345 GIC       13294 :         return HEAPTUPLE_LIVE;
                               1346                 :     }
                               1347                 : 
 6555 tgl                      1348 CBC     2679142 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                               1349                 :     {
 1983 andres                   1350 GIC           6 :         TransactionId xmax = HeapTupleGetUpdateXid(tuple);
 3728 alvherre                 1351 ECB             : 
                               1352                 :         /* already checked above */
 1983 andres                   1353 CBC           6 :         Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
                               1354                 : 
                               1355                 :         /* not LOCKED_ONLY, so it has to have an xmax */
 3418 alvherre                 1356               6 :         Assert(TransactionIdIsValid(xmax));
                               1357                 : 
 1983 andres                   1358 GIC           6 :         if (TransactionIdIsInProgress(xmax))
 1983 andres                   1359 LBC           0 :             return HEAPTUPLE_DELETE_IN_PROGRESS;
 1983 andres                   1360 GIC           6 :         else if (TransactionIdDidCommit(xmax))
 3728 alvherre                 1361 ECB             :         {
 1983 andres                   1362 EUB             :             /*
  970 andres                   1363 ECB             :              * The multixact might still be running due to lockers.  Need to
                               1364                 :              * allow for pruning if below the xid horizon regardless --
                               1365                 :              * otherwise we could end up with a tuple where the updater has to
                               1366                 :              * be removed due to the horizon, but is not pruned away.  It's
                               1367                 :              * not a problem to prune that tuple, because any remaining
                               1368                 :              * lockers will also be present in newer tuple versions.
                               1369                 :              */
  970 andres                   1370 GIC           6 :             *dead_after = xmax;
                               1371               6 :             return HEAPTUPLE_RECENTLY_DEAD;
                               1372                 :         }
 1983 andres                   1373 LBC           0 :         else if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
 1983 andres                   1374 ECB             :         {
                               1375                 :             /*
 1983 andres                   1376 EUB             :              * Not in Progress, Not Committed, so either Aborted or crashed.
                               1377                 :              * Mark the Xmax as invalid.
                               1378                 :              */
 1983 andres                   1379 UIC           0 :             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
                               1380                 :         }
                               1381                 : 
 3418 alvherre                 1382 UBC           0 :         return HEAPTUPLE_LIVE;
                               1383                 :     }
                               1384                 : 
 7941 tgl                      1385 GBC     2679136 :     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
                               1386                 :     {
 3728 alvherre                 1387 GIC     1502890 :         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
 7937 tgl                      1388 CBC      144393 :             return HEAPTUPLE_DELETE_IN_PROGRESS;
 3728 alvherre                 1389 GIC     1358497 :         else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
 5717 tgl                      1390 CBC     1357256 :             SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
 3728 alvherre                 1391 ECB             :                         HeapTupleHeaderGetRawXmax(tuple));
 7941 tgl                      1392                 :         else
                               1393                 :         {
                               1394                 :             /*
                               1395                 :              * Not in Progress, Not Committed, so either Aborted or crashed
                               1396                 :              */
 5717 tgl                      1397 GIC        1241 :             SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                               1398                 :                         InvalidTransactionId);
 7941                          1399            1241 :             return HEAPTUPLE_LIVE;
 7941 tgl                      1400 ECB             :         }
                               1401                 : 
 5730                          1402                 :         /*
                               1403                 :          * At this point the xmax is known committed, but we might not have
                               1404                 :          * been able to set the hint bit yet; so we can no longer Assert that
                               1405                 :          * it's set.
                               1406                 :          */
                               1407                 :     }
                               1408                 : 
                               1409                 :     /*
                               1410                 :      * Deleter committed, allow caller to check if it was recent enough that
                               1411                 :      * some open transactions could still see the tuple.
                               1412                 :      */
  970 andres                   1413 GIC     2533502 :     *dead_after = HeapTupleHeaderGetRawXmax(tuple);
                               1414         2533502 :     return HEAPTUPLE_RECENTLY_DEAD;
                               1415                 : }
 7941 tgl                      1416 ECB             : 
 2040                          1417                 : 
                               1418                 : /*
                               1419                 :  * HeapTupleSatisfiesNonVacuumable
                               1420                 :  *
                               1421                 :  *  True if tuple might be visible to some transaction; false if it's
                               1422                 :  *  surely dead to everyone, ie, vacuumable.
                               1423                 :  *
                               1424                 :  *  See SNAPSHOT_NON_VACUUMABLE's definition for the intended behaviour.
                               1425                 :  *
                               1426                 :  *  This is an interface to HeapTupleSatisfiesVacuum that's callable via
                               1427                 :  *  HeapTupleSatisfiesSnapshot, so it can be used through a Snapshot.
                               1428                 :  *  snapshot->vistest must have been set up with the horizon to use.
                               1429                 :  */
                               1430                 : static bool
 2040 tgl                      1431 GIC      444270 : HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot,
                               1432                 :                                 Buffer buffer)
                               1433                 : {
  970 andres                   1434 CBC      444270 :     TransactionId dead_after = InvalidTransactionId;
                               1435                 :     HTSV_Result res;
                               1436                 : 
                               1437          444270 :     res = HeapTupleSatisfiesVacuumHorizon(htup, buffer, &dead_after);
                               1438                 : 
  970 andres                   1439 GIC      444270 :     if (res == HEAPTUPLE_RECENTLY_DEAD)
  970 andres                   1440 ECB             :     {
  970 andres                   1441 GIC       64035 :         Assert(TransactionIdIsValid(dead_after));
  970 andres                   1442 ECB             : 
  970 andres                   1443 GIC       64035 :         if (GlobalVisTestIsRemovableXid(snapshot->vistest, dead_after))
  970 andres                   1444 CBC       52041 :             res = HEAPTUPLE_DEAD;
                               1445                 :     }
  970 andres                   1446 ECB             :     else
  970 andres                   1447 CBC      380235 :         Assert(!TransactionIdIsValid(dead_after));
                               1448                 : 
  970 andres                   1449 GIC      444270 :     return res != HEAPTUPLE_DEAD;
 2040 tgl                      1450 ECB             : }
                               1451                 : 
                               1452                 : 
                               1453                 : /*
                               1454                 :  * HeapTupleIsSurelyDead
                               1455                 :  *
                               1456                 :  *  Cheaply determine whether a tuple is surely dead to all onlookers.
                               1457                 :  *  We sometimes use this in lieu of HeapTupleSatisfiesVacuum when the
                               1458                 :  *  tuple has just been tested by another visibility routine (usually
                               1459                 :  *  HeapTupleSatisfiesMVCC) and, therefore, any hint bits that can be set
                               1460                 :  *  should already be set.  We assume that if no hint bits are set, the xmin
                               1461                 :  *  or xmax transaction is still running.  This is therefore faster than
                               1462                 :  *  HeapTupleSatisfiesVacuum, because we consult neither procarray nor CLOG.
                               1463                 :  *  It's okay to return false when in doubt, but we must return true only
                               1464                 :  *  if the tuple is removable.
                               1465                 :  */
                               1466                 : bool
  970 andres                   1467 GIC     6466218 : HeapTupleIsSurelyDead(HeapTuple htup, GlobalVisState *vistest)
                               1468                 : {
 3548 rhaas                    1469         6466218 :     HeapTupleHeader tuple = htup->t_data;
 3260 bruce                    1470 ECB             : 
 3548 rhaas                    1471 GIC     6466218 :     Assert(ItemPointerIsValid(&htup->t_self));
 3548 rhaas                    1472 CBC     6466218 :     Assert(htup->t_tableOid != InvalidOid);
                               1473                 : 
 3994 rhaas                    1474 ECB             :     /*
 3955 bruce                    1475                 :      * If the inserting transaction is marked invalid, then it aborted, and
                               1476                 :      * the tuple is definitely dead.  If it's marked neither committed nor
                               1477                 :      * invalid, then we assume it's still alive (since the presumption is that
                               1478                 :      * all relevant hint bits were just set moments ago).
                               1479                 :      */
 3395 rhaas                    1480 GIC     6466218 :     if (!HeapTupleHeaderXminCommitted(tuple))
  578 michael                  1481         5647002 :         return HeapTupleHeaderXminInvalid(tuple);
                               1482                 : 
 3994 rhaas                    1483 ECB             :     /*
                               1484                 :      * If the inserting transaction committed, but any deleting transaction
                               1485                 :      * aborted, the tuple is still alive.
                               1486                 :      */
 3728 alvherre                 1487 GIC      819216 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)
                               1488               8 :         return false;
                               1489                 : 
 3728 alvherre                 1490 ECB             :     /*
                               1491                 :      * If the XMAX is just a lock, the tuple is still alive.
                               1492                 :      */
 3728 alvherre                 1493 GIC      819208 :     if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
 3728 alvherre                 1494 UIC           0 :         return false;
                               1495                 : 
 3728 alvherre                 1496 ECB             :     /*
 3728 alvherre                 1497 EUB             :      * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
                               1498                 :      * know without checking pg_multixact.
                               1499                 :      */
 3728 alvherre                 1500 GIC      819208 :     if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
 3994 rhaas                    1501              45 :         return false;
                               1502                 : 
 3994 rhaas                    1503 ECB             :     /* If deleter isn't known to have committed, assume it's still running. */
 3994 rhaas                    1504 CBC      819163 :     if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
 3994 rhaas                    1505 GIC      304104 :         return false;
                               1506                 : 
 3994 rhaas                    1507 ECB             :     /* Deleter committed, so tuple is dead if the XID is old enough. */
  970 andres                   1508 CBC      515059 :     return GlobalVisTestIsRemovableXid(vistest,
                               1509                 :                                        HeapTupleHeaderGetRawXmax(tuple));
                               1510                 : }
 7941 tgl                      1511 ECB             : 
                               1512                 : /*
                               1513                 :  * Is the tuple really only locked?  That is, is it not updated?
                               1514                 :  *
                               1515                 :  * It's easy to check just infomask bits if the locker is not a multi; but
                               1516                 :  * otherwise we need to verify that the updating transaction has not aborted.
                               1517                 :  *
                               1518                 :  * This function is here because it follows the same visibility rules laid out
                               1519                 :  * at the top of this file.
                               1520                 :  */
                               1521                 : bool
 3728 alvherre                 1522 GIC       61219 : HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
                               1523                 : {
                               1524                 :     TransactionId xmax;
 3728 alvherre                 1525 ECB             : 
                               1526                 :     /* if there's no valid Xmax, then there's obviously no update either */
 3728 alvherre                 1527 GIC       61219 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)
 3728 alvherre                 1528 UIC           0 :         return true;
                               1529                 : 
 3728 alvherre                 1530 CBC       61219 :     if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
 3728 alvherre                 1531 GBC         516 :         return true;
                               1532                 : 
 3728 alvherre                 1533 ECB             :     /* invalid xmax means no update */
 3728 alvherre                 1534 CBC       60703 :     if (!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
 3728 alvherre                 1535 UIC           0 :         return true;
                               1536                 : 
 3728 alvherre                 1537 ECB             :     /*
 3602 bruce                    1538 EUB             :      * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this must
                               1539                 :      * necessarily have been updated
                               1540                 :      */
 3728 alvherre                 1541 GIC       60703 :     if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
                               1542           60677 :         return false;
                               1543                 : 
 3728 alvherre                 1544 ECB             :     /* ... but if it's a multi, then perhaps the updating Xid aborted. */
 3728 alvherre                 1545 CBC          26 :     xmax = HeapTupleGetUpdateXid(tuple);
                               1546                 : 
                               1547                 :     /* not LOCKED_ONLY, so it has to have an xmax */
 3418                          1548              26 :     Assert(TransactionIdIsValid(xmax));
                               1549                 : 
 3728 alvherre                 1550 GIC          26 :     if (TransactionIdIsCurrentTransactionId(xmax))
 3728 alvherre                 1551 LBC           0 :         return false;
 3728 alvherre                 1552 GIC          26 :     if (TransactionIdIsInProgress(xmax))
 3728 alvherre                 1553 CBC           4 :         return false;
 3728 alvherre                 1554 GBC          22 :     if (TransactionIdDidCommit(xmax))
 3728 alvherre                 1555 CBC          11 :         return false;
 3728 alvherre                 1556 ECB             : 
                               1557                 :     /*
                               1558                 :      * not current, not in progress, not committed -- must have aborted or
                               1559                 :      * crashed
                               1560                 :      */
 3728 alvherre                 1561 GIC          11 :     return true;
                               1562                 : }
                               1563                 : 
 3324 rhaas                    1564 ECB             : /*
                               1565                 :  * check whether the transaction id 'xid' is in the pre-sorted array 'xip'.
                               1566                 :  */
                               1567                 : static bool
 3324 rhaas                    1568 GIC       34971 : TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
                               1569                 : {
  402 tgl                      1570           50017 :     return num > 0 &&
  402 tgl                      1571 CBC       15046 :         bsearch(&xid, xip, num, sizeof(TransactionId), xidComparator) != NULL;
                               1572                 : }
 3324 rhaas                    1573 ECB             : 
                               1574                 : /*
                               1575                 :  * See the comments for HeapTupleSatisfiesMVCC for the semantics this function
                               1576                 :  * obeys.
                               1577                 :  *
                               1578                 :  * Only usable on tuples from catalog tables!
                               1579                 :  *
                               1580                 :  * We don't need to support HEAP_MOVED_(IN|OFF) for now because we only support
                               1581                 :  * reading catalog pages which couldn't have been created in an older version.
                               1582                 :  *
                               1583                 :  * We don't set any hint bits in here as it seems unlikely to be beneficial as
                               1584                 :  * those should already be set by normal access and it seems to be too
                               1585                 :  * dangerous to do so as the semantics of doing so during timetravel are more
                               1586                 :  * complicated than when dealing "only" with the present.
                               1587                 :  */
                               1588                 : static bool
 3324 rhaas                    1589 GIC       27740 : HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
                               1590                 :                                Buffer buffer)
                               1591                 : {
 3324 rhaas                    1592 CBC       27740 :     HeapTupleHeader tuple = htup->t_data;
 3324 rhaas                    1593 GIC       27740 :     TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
                               1594           27740 :     TransactionId xmax = HeapTupleHeaderGetRawXmax(tuple);
 3324 rhaas                    1595 ECB             : 
 3324 rhaas                    1596 CBC       27740 :     Assert(ItemPointerIsValid(&htup->t_self));
                               1597           27740 :     Assert(htup->t_tableOid != InvalidOid);
                               1598                 : 
 3324 rhaas                    1599 ECB             :     /* inserting transaction aborted */
 3324 rhaas                    1600 CBC       27740 :     if (HeapTupleHeaderXminInvalid(tuple))
                               1601                 :     {
 3324 rhaas                    1602 GIC          75 :         Assert(!TransactionIdDidCommit(xmin));
 3324 rhaas                    1603 CBC          75 :         return false;
                               1604                 :     }
 3310 fujii                    1605 ECB             :     /* check if it's one of our txids, toplevel is also in there */
 3324 rhaas                    1606 CBC       27665 :     else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
                               1607                 :     {
                               1608                 :         bool        resolved;
                               1609             367 :         CommandId   cmin = HeapTupleHeaderGetRawCommandId(tuple);
 3324 rhaas                    1610 GIC         367 :         CommandId   cmax = InvalidCommandId;
                               1611                 : 
 3324 rhaas                    1612 ECB             :         /*
                               1613                 :          * another transaction might have (tried to) delete this tuple or
                               1614                 :          * cmin/cmax was stored in a combo CID. So we need to lookup the
                               1615                 :          * actual values externally.
                               1616                 :          */
 3324 rhaas                    1617 GIC         367 :         resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
                               1618                 :                                                  htup, buffer,
                               1619                 :                                                  &cmin, &cmax);
 3324 rhaas                    1620 ECB             : 
                               1621                 :         /*
                               1622                 :          * If we haven't resolved the combo CID to cmin/cmax, that means we
                               1623                 :          * have not decoded the combo CID yet. That means the cmin is
                               1624                 :          * definitely in the future, and we're not supposed to see the tuple
                               1625                 :          * yet.
                               1626                 :          *
                               1627                 :          * XXX This only applies to decoding of in-progress transactions. In
                               1628                 :          * regular logical decoding we only execute this code at commit time,
                               1629                 :          * at which point we should have seen all relevant combo CIDs. So
                               1630                 :          * ideally, we should error out in this case but in practice, this
                               1631                 :          * won't happen. If we are too worried about this then we can add an
                               1632                 :          * elog inside ResolveCminCmaxDuringDecoding.
                               1633                 :          *
                               1634                 :          * XXX For the streaming case, we can track the largest combo CID
                               1635                 :          * assigned, and error out based on this (when unable to resolve combo
                               1636                 :          * CID below that observed maximum value).
                               1637                 :          */
 3324 rhaas                    1638 GIC         367 :         if (!resolved)
  974 akapila                  1639              56 :             return false;
                               1640                 : 
 3324 rhaas                    1641 CBC         367 :         Assert(cmin != InvalidCommandId);
 3324 rhaas                    1642 ECB             : 
 3324 rhaas                    1643 GIC         367 :         if (cmin >= snapshot->curcid)
 3260 bruce                    1644 CBC          56 :             return false;       /* inserted after scan started */
                               1645                 :         /* fall through */
 3324 rhaas                    1646 ECB             :     }
                               1647                 :     /* committed before our xmin horizon. Do a normal visibility check. */
 3324 rhaas                    1648 GIC       27298 :     else if (TransactionIdPrecedes(xmin, snapshot->xmin))
                               1649                 :     {
                               1650           24462 :         Assert(!(HeapTupleHeaderXminCommitted(tuple) &&
 3324 rhaas                    1651 ECB             :                  !TransactionIdDidCommit(xmin)));
                               1652                 : 
                               1653                 :         /* check for hint bit first, consult clog afterwards */
 3324 rhaas                    1654 GIC       24462 :         if (!HeapTupleHeaderXminCommitted(tuple) &&
                               1655              36 :             !TransactionIdDidCommit(xmin))
 3324 rhaas                    1656 UIC           0 :             return false;
 3324 rhaas                    1657 ECB             :         /* fall through */
                               1658                 :     }
 3324 rhaas                    1659 EUB             :     /* beyond our xmax horizon, i.e. invisible */
 3324 rhaas                    1660 GIC        2836 :     else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
                               1661                 :     {
                               1662             105 :         return false;
 3324 rhaas                    1663 ECB             :     }
                               1664                 :     /* check if it's a committed transaction in [xmin, xmax) */
 3260 bruce                    1665 CBC        2731 :     else if (TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
                               1666                 :     {
                               1667                 :         /* fall through */
 3324 rhaas                    1668 ECB             :     }
                               1669                 : 
                               1670                 :     /*
                               1671                 :      * none of the above, i.e. between [xmin, xmax) but hasn't committed. I.e.
                               1672                 :      * invisible.
                               1673                 :      */
                               1674                 :     else
                               1675                 :     {
 3324 rhaas                    1676 UIC           0 :         return false;
                               1677                 :     }
                               1678                 : 
 3324 rhaas                    1679 EUB             :     /* at this point we know xmin is visible, go on to check xmax */
                               1680                 : 
                               1681                 :     /* xid invalid or aborted */
 3324 rhaas                    1682 GIC       27504 :     if (tuple->t_infomask & HEAP_XMAX_INVALID)
                               1683           23332 :         return true;
                               1684                 :     /* locked tuples are always visible */
 3324 rhaas                    1685 CBC        4172 :     else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
                               1686             928 :         return true;
                               1687                 : 
 3324 rhaas                    1688 ECB             :     /*
 3260 bruce                    1689                 :      * We can see multis here if we're looking at user tables or if somebody
                               1690                 :      * SELECT ... FOR SHARE/UPDATE a system table.
                               1691                 :      */
 3324 rhaas                    1692 GIC        3244 :     else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
                               1693                 :     {
                               1694              39 :         xmax = HeapTupleGetUpdateXid(tuple);
 3324 rhaas                    1695 ECB             :     }
                               1696                 : 
 3310 fujii                    1697                 :     /* check if it's one of our txids, toplevel is also in there */
 3324 rhaas                    1698 GIC        3244 :     if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
                               1699                 :     {
                               1700                 :         bool        resolved;
 3260 bruce                    1701 ECB             :         CommandId   cmin;
 3260 bruce                    1702 GIC         229 :         CommandId   cmax = HeapTupleHeaderGetRawCommandId(tuple);
                               1703                 : 
                               1704                 :         /* Lookup actual cmin/cmax values */
 3324 rhaas                    1705 CBC         229 :         resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
                               1706                 :                                                  htup, buffer,
                               1707                 :                                                  &cmin, &cmax);
 3324 rhaas                    1708 ECB             : 
                               1709                 :         /*
                               1710                 :          * If we haven't resolved the combo CID to cmin/cmax, that means we
                               1711                 :          * have not decoded the combo CID yet. That means the cmax is
                               1712                 :          * definitely in the future, and we're still supposed to see the
                               1713                 :          * tuple.
                               1714                 :          *
                               1715                 :          * XXX This only applies to decoding of in-progress transactions. In
                               1716                 :          * regular logical decoding we only execute this code at commit time,
                               1717                 :          * at which point we should have seen all relevant combo CIDs. So
                               1718                 :          * ideally, we should error out in this case but in practice, this
                               1719                 :          * won't happen. If we are too worried about this then we can add an
                               1720                 :          * elog inside ResolveCminCmaxDuringDecoding.
                               1721                 :          *
                               1722                 :          * XXX For the streaming case, we can track the largest combo CID
                               1723                 :          * assigned, and error out based on this (when unable to resolve combo
                               1724                 :          * CID below that observed maximum value).
                               1725                 :          */
  974 akapila                  1726 GIC         229 :         if (!resolved || cmax == InvalidCommandId)
                               1727               9 :             return true;
                               1728                 : 
 3324 rhaas                    1729 CBC         220 :         if (cmax >= snapshot->curcid)
 3260 bruce                    1730              72 :             return true;        /* deleted after scan started */
                               1731                 :         else
                               1732             148 :             return false;       /* deleted before scan started */
 3324 rhaas                    1733 ECB             :     }
                               1734                 :     /* below xmin horizon, normal transaction state is valid */
 3324 rhaas                    1735 CBC        3015 :     else if (TransactionIdPrecedes(xmax, snapshot->xmin))
                               1736                 :     {
 3324 rhaas                    1737 GIC        1470 :         Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
 3324 rhaas                    1738 ECB             :                  !TransactionIdDidCommit(xmax)));
                               1739                 : 
                               1740                 :         /* check hint bit first */
 3324 rhaas                    1741 GIC        1470 :         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
                               1742            1413 :             return false;
                               1743                 : 
 3324 rhaas                    1744 ECB             :         /* check clog */
 3324 rhaas                    1745 CBC          57 :         return !TransactionIdDidCommit(xmax);
                               1746                 :     }
                               1747                 :     /* above xmax horizon, we cannot possibly see the deleting transaction */
                               1748            1545 :     else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
 3324 rhaas                    1749 GIC         214 :         return true;
                               1750                 :     /* xmax is between [xmin, xmax), check known committed array */
 3324 rhaas                    1751 CBC        1331 :     else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
                               1752            1331 :         return false;
                               1753                 :     /* xmax is between [xmin, xmax), but known not to have committed yet */
 3324 rhaas                    1754 ECB             :     else
 3324 rhaas                    1755 LBC           0 :         return true;
                               1756                 : }
                               1757                 : 
 1539 andres                   1758 EUB             : /*
                               1759                 :  * HeapTupleSatisfiesVisibility
                               1760                 :  *      True iff heap tuple satisfies a time qual.
                               1761                 :  *
                               1762                 :  * Notes:
                               1763                 :  *  Assumes heap tuple is valid, and buffer at least share locked.
                               1764                 :  *
                               1765                 :  *  Hint bits in the HeapTuple's t_infomask may be updated as a side effect;
                               1766                 :  *  if so, the indicated buffer is marked dirty.
                               1767                 :  */
                               1768                 : bool
  202 pg                       1769 GNC   217699168 : HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, Buffer buffer)
                               1770                 : {
 1539 andres                   1771 GIC   217699168 :     switch (snapshot->snapshot_type)
 1539 andres                   1772 ECB             :     {
 1539 andres                   1773 GIC   203462247 :         case SNAPSHOT_MVCC:
  202 pg                       1774 GNC   203462247 :             return HeapTupleSatisfiesMVCC(htup, snapshot, buffer);
 1539 andres                   1775 CBC        2372 :         case SNAPSHOT_SELF:
  202 pg                       1776 GNC        2372 :             return HeapTupleSatisfiesSelf(htup, snapshot, buffer);
 1539 andres                   1777 CBC     7594353 :         case SNAPSHOT_ANY:
  202 pg                       1778 GNC     7594353 :             return HeapTupleSatisfiesAny(htup, snapshot, buffer);
 1539 andres                   1779 CBC      173572 :         case SNAPSHOT_TOAST:
  202 pg                       1780 GNC      173572 :             return HeapTupleSatisfiesToast(htup, snapshot, buffer);
 1539 andres                   1781 CBC     5994614 :         case SNAPSHOT_DIRTY:
  202 pg                       1782 GNC     5994614 :             return HeapTupleSatisfiesDirty(htup, snapshot, buffer);
 1539 andres                   1783 CBC       27740 :         case SNAPSHOT_HISTORIC_MVCC:
  202 pg                       1784 GNC       27740 :             return HeapTupleSatisfiesHistoricMVCC(htup, snapshot, buffer);
 1539 andres                   1785 GIC      444270 :         case SNAPSHOT_NON_VACUUMABLE:
  202 pg                       1786 GNC      444270 :             return HeapTupleSatisfiesNonVacuumable(htup, snapshot, buffer);
                               1787                 :     }
                               1788                 : 
 1539 andres                   1789 UIC           0 :     return false;               /* keep compiler quiet */
                               1790                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a