PostgreSQL Source Code  git master
heapam_visibility.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/subtrans.h"
#include "access/tableam.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "storage/bufmgr.h"
#include "storage/procarray.h"
#include "utils/builtins.h"
#include "utils/combocid.h"
#include "utils/snapmgr.h"
Include dependency graph for heapam_visibility.c:

Go to the source code of this file.

Functions

static void SetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
 
void HeapTupleSetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
 
static bool HeapTupleSatisfiesSelf (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesAny (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesToast (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
TM_Result HeapTupleSatisfiesUpdate (HeapTuple htup, CommandId curcid, Buffer buffer)
 
static bool HeapTupleSatisfiesDirty (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
static bool HeapTupleSatisfiesMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
HTSV_Result HeapTupleSatisfiesVacuum (HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
 
HTSV_Result HeapTupleSatisfiesVacuumHorizon (HeapTuple htup, Buffer buffer, TransactionId *dead_after)
 
static bool HeapTupleSatisfiesNonVacuumable (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleIsSurelyDead (HeapTuple htup, GlobalVisState *vistest)
 
bool HeapTupleHeaderIsOnlyLocked (HeapTupleHeader tuple)
 
static bool TransactionIdInArray (TransactionId xid, TransactionId *xip, Size num)
 
static bool HeapTupleSatisfiesHistoricMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesVisibility (HeapTuple tup, Snapshot snapshot, Buffer buffer)
 

Function Documentation

◆ HeapTupleHeaderIsOnlyLocked()

bool HeapTupleHeaderIsOnlyLocked ( HeapTupleHeader  tuple)

Definition at line 1522 of file heapam_visibility.c.

References Assert, HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HEAP_XMAX_LOCK_ONLY, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderData::t_infomask, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_get_latest_tid(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), HeapTupleSatisfiesVacuumHorizon(), and rewrite_heap_tuple().

1523 {
1524  TransactionId xmax;
1525 
1526  /* if there's no valid Xmax, then there's obviously no update either */
1527  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1528  return true;
1529 
1530  if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
1531  return true;
1532 
1533  /* invalid xmax means no update */
1535  return true;
1536 
1537  /*
1538  * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this must
1539  * necessarily have been updated
1540  */
1541  if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
1542  return false;
1543 
1544  /* ... but if it's a multi, then perhaps the updating Xid aborted. */
1545  xmax = HeapTupleGetUpdateXid(tuple);
1546 
1547  /* not LOCKED_ONLY, so it has to have an xmax */
1549 
1551  return false;
1552  if (TransactionIdIsInProgress(xmax))
1553  return false;
1554  if (TransactionIdDidCommit(xmax))
1555  return false;
1556 
1557  /*
1558  * not current, not in progress, not committed -- must have aborted or
1559  * crashed
1560  */
1561  return true;
1562 }
#define HEAP_XMAX_LOCK_ONLY
Definition: htup_details.h:196
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define Assert(condition)
Definition: c.h:745
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleIsSurelyDead()

bool HeapTupleIsSurelyDead ( HeapTuple  htup,
GlobalVisState vistest 
)

Definition at line 1467 of file heapam_visibility.c.

References Assert, GlobalVisTestIsRemovableXid(), HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HeapTupleHeaderGetRawXmax, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, ItemPointerIsValid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, and true.

Referenced by heap_hot_search_buffer().

1468 {
1469  HeapTupleHeader tuple = htup->t_data;
1470 
1471  Assert(ItemPointerIsValid(&htup->t_self));
1472  Assert(htup->t_tableOid != InvalidOid);
1473 
1474  /*
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  */
1480  if (!HeapTupleHeaderXminCommitted(tuple))
1481  return HeapTupleHeaderXminInvalid(tuple) ? true : false;
1482 
1483  /*
1484  * If the inserting transaction committed, but any deleting transaction
1485  * aborted, the tuple is still alive.
1486  */
1487  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1488  return false;
1489 
1490  /*
1491  * If the XMAX is just a lock, the tuple is still alive.
1492  */
1494  return false;
1495 
1496  /*
1497  * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
1498  * know without checking pg_multixact.
1499  */
1500  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1501  return false;
1502 
1503  /* If deleter isn't known to have committed, assume it's still running. */
1504  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1505  return false;
1506 
1507  /* Deleter committed, so tuple is dead if the XID is old enough. */
1508  return GlobalVisTestIsRemovableXid(vistest,
1509  HeapTupleHeaderGetRawXmax(tuple));
1510 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4028
HeapTupleHeader t_data
Definition: htup.h:68
#define true
Definition: c.h:328
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
Oid t_tableOid
Definition: htup.h:66
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:745

◆ HeapTupleSatisfiesAny()

static bool HeapTupleSatisfiesAny ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 339 of file heapam_visibility.c.

Referenced by HeapTupleSatisfiesVisibility().

340 {
341  return true;
342 }

◆ HeapTupleSatisfiesDirty()

static bool HeapTupleSatisfiesDirty ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 745 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetSpeculativeToken, HeapTupleHeaderGetXvac, HeapTupleHeaderIsSpeculative, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), SnapshotData::speculativeToken, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), TransactionIdIsValid, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesVisibility().

747 {
748  HeapTupleHeader tuple = htup->t_data;
749 
751  Assert(htup->t_tableOid != InvalidOid);
752 
753  snapshot->xmin = snapshot->xmax = InvalidTransactionId;
754  snapshot->speculativeToken = 0;
755 
756  if (!HeapTupleHeaderXminCommitted(tuple))
757  {
758  if (HeapTupleHeaderXminInvalid(tuple))
759  return false;
760 
761  /* Used by pre-9.0 binary upgrades */
762  if (tuple->t_infomask & HEAP_MOVED_OFF)
763  {
765 
767  return false;
768  if (!TransactionIdIsInProgress(xvac))
769  {
770  if (TransactionIdDidCommit(xvac))
771  {
772  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
774  return false;
775  }
776  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
778  }
779  }
780  /* Used by pre-9.0 binary upgrades */
781  else if (tuple->t_infomask & HEAP_MOVED_IN)
782  {
784 
786  {
787  if (TransactionIdIsInProgress(xvac))
788  return false;
789  if (TransactionIdDidCommit(xvac))
790  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
792  else
793  {
794  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
796  return false;
797  }
798  }
799  }
801  {
802  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
803  return true;
804 
805  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
806  return true;
807 
808  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
809  {
810  TransactionId xmax;
811 
812  xmax = HeapTupleGetUpdateXid(tuple);
813 
814  /* not LOCKED_ONLY, so it has to have an xmax */
816 
817  /* updating subtransaction must have aborted */
819  return true;
820  else
821  return false;
822  }
823 
825  {
826  /* deleting subtransaction must have aborted */
827  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
829  return true;
830  }
831 
832  return false;
833  }
835  {
836  /*
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  */
842  if (HeapTupleHeaderIsSpeculative(tuple))
843  {
844  snapshot->speculativeToken =
846 
847  Assert(snapshot->speculativeToken != 0);
848  }
849 
850  snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
851  /* XXX shouldn't we fall through to look at xmax? */
852  return true; /* in insertion by other */
853  }
855  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
857  else
858  {
859  /* it must have aborted or crashed */
860  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
862  return false;
863  }
864  }
865 
866  /* by here, the inserting transaction has committed */
867 
868  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
869  return true;
870 
871  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
872  {
874  return true;
875  return false; /* updated by other */
876  }
877 
878  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
879  {
880  TransactionId xmax;
881 
883  return true;
884 
885  xmax = HeapTupleGetUpdateXid(tuple);
886 
887  /* not LOCKED_ONLY, so it has to have an xmax */
889 
891  return false;
892  if (TransactionIdIsInProgress(xmax))
893  {
894  snapshot->xmax = xmax;
895  return true;
896  }
897  if (TransactionIdDidCommit(xmax))
898  return false;
899  /* it must have aborted or crashed */
900  return true;
901  }
902 
904  {
906  return true;
907  return false;
908  }
909 
911  {
913  snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
914  return true;
915  }
916 
918  {
919  /* it must have aborted or crashed */
920  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
922  return true;
923  }
924 
925  /* xmax transaction committed */
926 
928  {
929  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
931  return true;
932  }
933 
934  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
936  return false; /* updated by other */
937 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
#define HeapTupleHeaderGetSpeculativeToken(tup)
Definition: htup_details.h:434
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:429
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
uint32 speculativeToken
Definition: snapshot.h:193
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesHistoricMVCC()

static bool HeapTupleSatisfiesHistoricMVCC ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 1589 of file heapam_visibility.c.

References Assert, SnapshotData::curcid, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawCommandId, HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetXmin, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, HistoricSnapshotGetTupleCids(), InvalidCommandId, InvalidOid, ItemPointerIsValid, ResolveCminCmaxDuringDecoding(), SnapshotData::subxcnt, SnapshotData::subxip, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdFollowsOrEquals(), TransactionIdInArray(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by HeapTupleSatisfiesVisibility().

1591 {
1592  HeapTupleHeader tuple = htup->t_data;
1593  TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
1595 
1596  Assert(ItemPointerIsValid(&htup->t_self));
1597  Assert(htup->t_tableOid != InvalidOid);
1598 
1599  /* inserting transaction aborted */
1600  if (HeapTupleHeaderXminInvalid(tuple))
1601  {
1603  return false;
1604  }
1605  /* check if it's one of our txids, toplevel is also in there */
1606  else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
1607  {
1608  bool resolved;
1610  CommandId cmax = InvalidCommandId;
1611 
1612  /*
1613  * another transaction might have (tried to) delete this tuple or
1614  * cmin/cmax was stored in a combocid. So we need to lookup the actual
1615  * values externally.
1616  */
1618  htup, buffer,
1619  &cmin, &cmax);
1620 
1621  /*
1622  * If we haven't resolved the combocid to cmin/cmax, that means we
1623  * have not decoded the combocid 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 combocids. 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 combocid
1635  * assigned, and error out based on this (when unable to resolve
1636  * combocid below that observed maximum value).
1637  */
1638  if (!resolved)
1639  return false;
1640 
1641  Assert(cmin != InvalidCommandId);
1642 
1643  if (cmin >= snapshot->curcid)
1644  return false; /* inserted after scan started */
1645  /* fall through */
1646  }
1647  /* committed before our xmin horizon. Do a normal visibility check. */
1648  else if (TransactionIdPrecedes(xmin, snapshot->xmin))
1649  {
1651  !TransactionIdDidCommit(xmin)));
1652 
1653  /* check for hint bit first, consult clog afterwards */
1654  if (!HeapTupleHeaderXminCommitted(tuple) &&
1655  !TransactionIdDidCommit(xmin))
1656  return false;
1657  /* fall through */
1658  }
1659  /* beyond our xmax horizon, i.e. invisible */
1660  else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
1661  {
1662  return false;
1663  }
1664  /* check if it's a committed transaction in [xmin, xmax) */
1665  else if (TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
1666  {
1667  /* fall through */
1668  }
1669 
1670  /*
1671  * none of the above, i.e. between [xmin, xmax) but hasn't committed. I.e.
1672  * invisible.
1673  */
1674  else
1675  {
1676  return false;
1677  }
1678 
1679  /* at this point we know xmin is visible, go on to check xmax */
1680 
1681  /* xid invalid or aborted */
1682  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1683  return true;
1684  /* locked tuples are always visible */
1685  else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1686  return true;
1687 
1688  /*
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  */
1692  else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1693  {
1694  xmax = HeapTupleGetUpdateXid(tuple);
1695  }
1696 
1697  /* check if it's one of our txids, toplevel is also in there */
1698  if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
1699  {
1700  bool resolved;
1701  CommandId cmin;
1703 
1704  /* Lookup actual cmin/cmax values */
1706  htup, buffer,
1707  &cmin, &cmax);
1708 
1709  /*
1710  * If we haven't resolved the combocid to cmin/cmax, that means we
1711  * have not decoded the combocid 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 combocids. 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 combocid
1723  * assigned, and error out based on this (when unable to resolve
1724  * combocid below that observed maximum value).
1725  */
1726  if (!resolved || cmax == InvalidCommandId)
1727  return true;
1728 
1729  if (cmax >= snapshot->curcid)
1730  return true; /* deleted after scan started */
1731  else
1732  return false; /* deleted before scan started */
1733  }
1734  /* below xmin horizon, normal transaction state is valid */
1735  else if (TransactionIdPrecedes(xmax, snapshot->xmin))
1736  {
1737  Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
1738  !TransactionIdDidCommit(xmax)));
1739 
1740  /* check hint bit first */
1741  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
1742  return false;
1743 
1744  /* check clog */
1745  return !TransactionIdDidCommit(xmax);
1746  }
1747  /* above xmax horizon, we cannot possibly see the deleting transaction */
1748  else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
1749  return true;
1750  /* xmax is between [xmin, xmax), check known committed array */
1751  else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
1752  return false;
1753  /* xmax is between [xmin, xmax), but known not to have committed yet */
1754  else
1755  return true;
1756 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 CommandId
Definition: c.h:534
uint32 TransactionId
Definition: c.h:520
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
Oid t_tableOid
Definition: htup.h:66
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:168
#define InvalidCommandId
Definition: c.h:537
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:187
#define Assert(condition)
Definition: c.h:745
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
static bool TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:391
HTAB * HistoricSnapshotGetTupleCids(void)
Definition: snapmgr.c:2060
uint32 xcnt
Definition: snapshot.h:169
TransactionId * subxip
Definition: snapshot.h:180
int32 subxcnt
Definition: snapshot.h:181
bool ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data, Snapshot snapshot, HeapTuple htup, Buffer buffer, CommandId *cmin, CommandId *cmax)

◆ HeapTupleSatisfiesMVCC()

static bool HeapTupleSatisfiesMVCC ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 962 of file heapam_visibility.c.

References Assert, SnapshotData::curcid, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminFrozen, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsValid, and XidInMVCCSnapshot().

Referenced by HeapTupleSatisfiesVisibility().

964 {
965  HeapTupleHeader tuple = htup->t_data;
966 
968  Assert(htup->t_tableOid != InvalidOid);
969 
970  if (!HeapTupleHeaderXminCommitted(tuple))
971  {
972  if (HeapTupleHeaderXminInvalid(tuple))
973  return false;
974 
975  /* Used by pre-9.0 binary upgrades */
976  if (tuple->t_infomask & HEAP_MOVED_OFF)
977  {
979 
981  return false;
982  if (!XidInMVCCSnapshot(xvac, snapshot))
983  {
984  if (TransactionIdDidCommit(xvac))
985  {
986  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
988  return false;
989  }
990  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
992  }
993  }
994  /* Used by pre-9.0 binary upgrades */
995  else if (tuple->t_infomask & HEAP_MOVED_IN)
996  {
998 
1000  {
1001  if (XidInMVCCSnapshot(xvac, snapshot))
1002  return false;
1003  if (TransactionIdDidCommit(xvac))
1004  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1006  else
1007  {
1008  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1010  return false;
1011  }
1012  }
1013  }
1015  {
1016  if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
1017  return false; /* inserted after scan started */
1018 
1019  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1020  return true;
1021 
1022  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
1023  return true;
1024 
1025  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1026  {
1027  TransactionId xmax;
1028 
1029  xmax = HeapTupleGetUpdateXid(tuple);
1030 
1031  /* not LOCKED_ONLY, so it has to have an xmax */
1033 
1034  /* updating subtransaction must have aborted */
1036  return true;
1037  else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1038  return true; /* updated after scan started */
1039  else
1040  return false; /* updated before scan started */
1041  }
1042 
1044  {
1045  /* deleting subtransaction must have aborted */
1046  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1048  return true;
1049  }
1050 
1051  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1052  return true; /* deleted after scan started */
1053  else
1054  return false; /* deleted before scan started */
1055  }
1056  else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1057  return false;
1059  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1060  HeapTupleHeaderGetRawXmin(tuple));
1061  else
1062  {
1063  /* it must have aborted or crashed */
1064  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1066  return false;
1067  }
1068  }
1069  else
1070  {
1071  /* xmin is committed, but maybe not according to our snapshot */
1072  if (!HeapTupleHeaderXminFrozen(tuple) &&
1073  XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1074  return false; /* treat as still in progress */
1075  }
1076 
1077  /* by here, the inserting transaction has committed */
1078 
1079  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
1080  return true;
1081 
1083  return true;
1084 
1085  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1086  {
1087  TransactionId xmax;
1088 
1089  /* already checked above */
1091 
1092  xmax = HeapTupleGetUpdateXid(tuple);
1093 
1094  /* not LOCKED_ONLY, so it has to have an xmax */
1096 
1098  {
1099  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1100  return true; /* deleted after scan started */
1101  else
1102  return false; /* deleted before scan started */
1103  }
1104  if (XidInMVCCSnapshot(xmax, snapshot))
1105  return true;
1106  if (TransactionIdDidCommit(xmax))
1107  return false; /* updating transaction committed */
1108  /* it must have aborted or crashed */
1109  return true;
1110  }
1111 
1112  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1113  {
1115  {
1116  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1117  return true; /* deleted after scan started */
1118  else
1119  return false; /* deleted before scan started */
1120  }
1121 
1122  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1123  return true;
1124 
1126  {
1127  /* it must have aborted or crashed */
1128  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1130  return true;
1131  }
1132 
1133  /* xmax transaction committed */
1134  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1135  HeapTupleHeaderGetRawXmax(tuple));
1136  }
1137  else
1138  {
1139  /* xmax is committed, but maybe not according to our snapshot */
1140  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1141  return true; /* treat as still in progress */
1142  }
1143 
1144  /* xmax transaction committed */
1145 
1146  return false;
1147 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: snapmgr.c:2238
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:104
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HeapTupleHeaderXminFrozen(tup)
Definition: htup_details.h:335
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:187
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:118
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesNonVacuumable()

static bool HeapTupleSatisfiesNonVacuumable ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 1431 of file heapam_visibility.c.

References Assert, GlobalVisTestIsRemovableXid(), HEAPTUPLE_DEAD, HEAPTUPLE_RECENTLY_DEAD, HeapTupleSatisfiesVacuumHorizon(), InvalidTransactionId, TransactionIdIsValid, and SnapshotData::vistest.

Referenced by HeapTupleSatisfiesVisibility().

1433 {
1434  TransactionId dead_after = InvalidTransactionId;
1435  HTSV_Result res;
1436 
1437  res = HeapTupleSatisfiesVacuumHorizon(htup, buffer, &dead_after);
1438 
1439  if (res == HEAPTUPLE_RECENTLY_DEAD)
1440  {
1441  Assert(TransactionIdIsValid(dead_after));
1442 
1443  if (GlobalVisTestIsRemovableXid(snapshot->vistest, dead_after))
1444  res = HEAPTUPLE_DEAD;
1445  }
1446  else
1447  Assert(!TransactionIdIsValid(dead_after));
1448 
1449  return res != HEAPTUPLE_DEAD;
1450 }
uint32 TransactionId
Definition: c.h:520
struct GlobalVisState * vistest
Definition: snapshot.h:199
bool GlobalVisTestIsRemovableXid(GlobalVisState *state, TransactionId xid)
Definition: procarray.c:4028
#define InvalidTransactionId
Definition: transam.h:31
HTSV_Result HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *dead_after)
#define Assert(condition)
Definition: c.h:745
HTSV_Result
Definition: heapam.h:87
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesSelf()

static bool HeapTupleSatisfiesSelf ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 169 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by HeapTupleSatisfiesVisibility().

170 {
171  HeapTupleHeader tuple = htup->t_data;
172 
174  Assert(htup->t_tableOid != InvalidOid);
175 
176  if (!HeapTupleHeaderXminCommitted(tuple))
177  {
178  if (HeapTupleHeaderXminInvalid(tuple))
179  return false;
180 
181  /* Used by pre-9.0 binary upgrades */
182  if (tuple->t_infomask & HEAP_MOVED_OFF)
183  {
185 
187  return false;
188  if (!TransactionIdIsInProgress(xvac))
189  {
190  if (TransactionIdDidCommit(xvac))
191  {
192  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
194  return false;
195  }
196  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
198  }
199  }
200  /* Used by pre-9.0 binary upgrades */
201  else if (tuple->t_infomask & HEAP_MOVED_IN)
202  {
204 
206  {
207  if (TransactionIdIsInProgress(xvac))
208  return false;
209  if (TransactionIdDidCommit(xvac))
210  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
212  else
213  {
214  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
216  return false;
217  }
218  }
219  }
221  {
222  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
223  return true;
224 
225  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
226  return true;
227 
228  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
229  {
230  TransactionId xmax;
231 
232  xmax = HeapTupleGetUpdateXid(tuple);
233 
234  /* not LOCKED_ONLY, so it has to have an xmax */
236 
237  /* updating subtransaction must have aborted */
239  return true;
240  else
241  return false;
242  }
243 
245  {
246  /* deleting subtransaction must have aborted */
247  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
249  return true;
250  }
251 
252  return false;
253  }
255  return false;
257  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
259  else
260  {
261  /* it must have aborted or crashed */
262  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
264  return false;
265  }
266  }
267 
268  /* by here, the inserting transaction has committed */
269 
270  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
271  return true;
272 
273  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
274  {
276  return true;
277  return false; /* updated by other */
278  }
279 
280  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
281  {
282  TransactionId xmax;
283 
285  return true;
286 
287  xmax = HeapTupleGetUpdateXid(tuple);
288 
289  /* not LOCKED_ONLY, so it has to have an xmax */
291 
293  return false;
294  if (TransactionIdIsInProgress(xmax))
295  return true;
296  if (TransactionIdDidCommit(xmax))
297  return false;
298  /* it must have aborted or crashed */
299  return true;
300  }
301 
303  {
305  return true;
306  return false;
307  }
308 
310  return true;
311 
313  {
314  /* it must have aborted or crashed */
315  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
317  return true;
318  }
319 
320  /* xmax transaction committed */
321 
323  {
324  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
326  return true;
327  }
328 
329  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
331  return false;
332 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesToast()

static bool HeapTupleSatisfiesToast ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)
static

Definition at line 361 of file heapam_visibility.c.

References Assert, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleHeaderGetXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by HeapTupleSatisfiesVisibility().

363 {
364  HeapTupleHeader tuple = htup->t_data;
365 
367  Assert(htup->t_tableOid != InvalidOid);
368 
369  if (!HeapTupleHeaderXminCommitted(tuple))
370  {
371  if (HeapTupleHeaderXminInvalid(tuple))
372  return false;
373 
374  /* Used by pre-9.0 binary upgrades */
375  if (tuple->t_infomask & HEAP_MOVED_OFF)
376  {
378 
380  return false;
381  if (!TransactionIdIsInProgress(xvac))
382  {
383  if (TransactionIdDidCommit(xvac))
384  {
385  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
387  return false;
388  }
389  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
391  }
392  }
393  /* Used by pre-9.0 binary upgrades */
394  else if (tuple->t_infomask & HEAP_MOVED_IN)
395  {
397 
399  {
400  if (TransactionIdIsInProgress(xvac))
401  return false;
402  if (TransactionIdDidCommit(xvac))
403  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
405  else
406  {
407  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
409  return false;
410  }
411  }
412  }
413 
414  /*
415  * An invalid Xmin can be left behind by a speculative insertion that
416  * is canceled by super-deleting the tuple. This also applies to
417  * TOAST tuples created during speculative insertion.
418  */
420  return false;
421  }
422 
423  /* otherwise assume the tuple is valid for TOAST. */
424  return true;
425 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:313
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesUpdate()

TM_Result HeapTupleSatisfiesUpdate ( HeapTuple  htup,
CommandId  curcid,
Buffer  buffer 
)

Definition at line 457 of file heapam_visibility.c.

References Assert, HEAP_LOCKED_UPGRADED, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderIndicatesMovedPartitions, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerEquals(), ItemPointerIsValid, MultiXactIdIsRunning(), SetHintBits(), HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TM_BeingModified, TM_Deleted, TM_Invisible, TM_Ok, TM_SelfModified, TM_Updated, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_delete(), heap_lock_tuple(), heap_update(), and pgrowlocks().

459 {
460  HeapTupleHeader tuple = htup->t_data;
461 
463  Assert(htup->t_tableOid != InvalidOid);
464 
465  if (!HeapTupleHeaderXminCommitted(tuple))
466  {
467  if (HeapTupleHeaderXminInvalid(tuple))
468  return TM_Invisible;
469 
470  /* Used by pre-9.0 binary upgrades */
471  if (tuple->t_infomask & HEAP_MOVED_OFF)
472  {
474 
476  return TM_Invisible;
477  if (!TransactionIdIsInProgress(xvac))
478  {
479  if (TransactionIdDidCommit(xvac))
480  {
481  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
483  return TM_Invisible;
484  }
485  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
487  }
488  }
489  /* Used by pre-9.0 binary upgrades */
490  else if (tuple->t_infomask & HEAP_MOVED_IN)
491  {
493 
495  {
496  if (TransactionIdIsInProgress(xvac))
497  return TM_Invisible;
498  if (TransactionIdDidCommit(xvac))
499  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
501  else
502  {
503  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
505  return TM_Invisible;
506  }
507  }
508  }
510  {
511  if (HeapTupleHeaderGetCmin(tuple) >= curcid)
512  return TM_Invisible; /* inserted after scan started */
513 
514  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
515  return TM_Ok;
516 
518  {
519  TransactionId xmax;
520 
521  xmax = HeapTupleHeaderGetRawXmax(tuple);
522 
523  /*
524  * Careful here: even though this tuple was created by our own
525  * transaction, it might be locked by other transactions, if
526  * the original version was key-share locked when we updated
527  * it.
528  */
529 
530  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
531  {
532  if (MultiXactIdIsRunning(xmax, true))
533  return TM_BeingModified;
534  else
535  return TM_Ok;
536  }
537 
538  /*
539  * If the locker is gone, then there is nothing of interest
540  * left in this Xmax; otherwise, report the tuple as
541  * locked/updated.
542  */
543  if (!TransactionIdIsInProgress(xmax))
544  return TM_Ok;
545  return TM_BeingModified;
546  }
547 
548  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
549  {
550  TransactionId xmax;
551 
552  xmax = HeapTupleGetUpdateXid(tuple);
553 
554  /* not LOCKED_ONLY, so it has to have an xmax */
556 
557  /* deleting subtransaction must have aborted */
559  {
561  false))
562  return TM_BeingModified;
563  return TM_Ok;
564  }
565  else
566  {
567  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
568  return TM_SelfModified; /* updated after scan started */
569  else
570  return TM_Invisible; /* updated before scan started */
571  }
572  }
573 
575  {
576  /* deleting subtransaction must have aborted */
577  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
579  return TM_Ok;
580  }
581 
582  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
583  return TM_SelfModified; /* updated after scan started */
584  else
585  return TM_Invisible; /* updated before scan started */
586  }
588  return TM_Invisible;
590  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
592  else
593  {
594  /* it must have aborted or crashed */
595  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
597  return TM_Invisible;
598  }
599  }
600 
601  /* by here, the inserting transaction has committed */
602 
603  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
604  return TM_Ok;
605 
606  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
607  {
609  return TM_Ok;
610  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
612  return TM_Updated; /* updated by other */
613  else
614  return TM_Deleted; /* deleted by other */
615  }
616 
617  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
618  {
619  TransactionId xmax;
620 
621  if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
622  return TM_Ok;
623 
625  {
627  return TM_BeingModified;
628 
630  return TM_Ok;
631  }
632 
633  xmax = HeapTupleGetUpdateXid(tuple);
634  if (!TransactionIdIsValid(xmax))
635  {
637  return TM_BeingModified;
638  }
639 
640  /* not LOCKED_ONLY, so it has to have an xmax */
642 
644  {
645  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
646  return TM_SelfModified; /* updated after scan started */
647  else
648  return TM_Invisible; /* updated before scan started */
649  }
650 
652  return TM_BeingModified;
653 
654  if (TransactionIdDidCommit(xmax))
655  {
656  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
658  return TM_Updated;
659  else
660  return TM_Deleted;
661  }
662 
663  /*
664  * By here, the update in the Xmax is either aborted or crashed, but
665  * what about the other members?
666  */
667 
669  {
670  /*
671  * There's no member, even just a locker, alive anymore, so we can
672  * mark the Xmax as invalid.
673  */
674  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
676  return TM_Ok;
677  }
678  else
679  {
680  /* There are lockers running */
681  return TM_BeingModified;
682  }
683  }
684 
686  {
688  return TM_BeingModified;
689  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
690  return TM_SelfModified; /* updated after scan started */
691  else
692  return TM_Invisible; /* updated before scan started */
693  }
694 
696  return TM_BeingModified;
697 
699  {
700  /* it must have aborted or crashed */
701  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
703  return TM_Ok;
704  }
705 
706  /* xmax transaction committed */
707 
709  {
710  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
712  return TM_Ok;
713  }
714 
715  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
717  if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid) ||
719  return TM_Updated; /* updated by other */
720  else
721  return TM_Deleted; /* deleted by other */
722 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:104
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:252
#define HeapTupleHeaderIndicatesMovedPartitions(tup)
Definition: htup_details.h:445
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_ctid
Definition: htup_details.h:160
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:118
Definition: tableam.h:76
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:551

◆ HeapTupleSatisfiesVacuum()

HTSV_Result HeapTupleSatisfiesVacuum ( HeapTuple  htup,
TransactionId  OldestXmin,
Buffer  buffer 
)

Definition at line 1164 of file heapam_visibility.c.

References Assert, HEAPTUPLE_DEAD, HEAPTUPLE_RECENTLY_DEAD, HeapTupleSatisfiesVacuumHorizon(), InvalidTransactionId, TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by heap_page_is_all_visible(), heapam_index_build_range_scan(), heapam_relation_copy_for_cluster(), heapam_scan_analyze_next_tuple(), HeapCheckForSerializableConflictOut(), lazy_scan_heap(), statapprox_heap(), and tuple_all_visible().

1166 {
1167  TransactionId dead_after = InvalidTransactionId;
1168  HTSV_Result res;
1169 
1170  res = HeapTupleSatisfiesVacuumHorizon(htup, buffer, &dead_after);
1171 
1172  if (res == HEAPTUPLE_RECENTLY_DEAD)
1173  {
1174  Assert(TransactionIdIsValid(dead_after));
1175 
1176  if (TransactionIdPrecedes(dead_after, OldestXmin))
1177  res = HEAPTUPLE_DEAD;
1178  }
1179  else
1180  Assert(!TransactionIdIsValid(dead_after));
1181 
1182  return res;
1183 }
uint32 TransactionId
Definition: c.h:520
#define InvalidTransactionId
Definition: transam.h:31
static TransactionId OldestXmin
Definition: vacuumlazy.c:335
HTSV_Result HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer, TransactionId *dead_after)
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:745
HTSV_Result
Definition: heapam.h:87
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesVacuumHorizon()

HTSV_Result HeapTupleSatisfiesVacuumHorizon ( HeapTuple  htup,
Buffer  buffer,
TransactionId dead_after 
)

Definition at line 1198 of file heapam_visibility.c.

References Assert, HEAP_LOCKED_UPGRADED, HEAP_MOVED_IN, HEAP_MOVED_OFF, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_LOCKED_ONLY, HEAP_XMAX_IS_MULTI, HEAP_XMIN_COMMITTED, HEAP_XMIN_INVALID, HEAPTUPLE_DEAD, HEAPTUPLE_DELETE_IN_PROGRESS, HEAPTUPLE_INSERT_IN_PROGRESS, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HeapTupleGetUpdateXid(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetUpdateXid, HeapTupleHeaderGetXvac, HeapTupleHeaderIsOnlyLocked(), HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, InvalidOid, InvalidTransactionId, ItemPointerIsValid, MultiXactIdIsRunning(), SetHintBits(), HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_self, HeapTupleData::t_tableOid, TransactionIdDidCommit(), TransactionIdIsCurrentTransactionId(), TransactionIdIsInProgress(), and TransactionIdIsValid.

Referenced by heap_prune_satisfies_vacuum(), HeapTupleSatisfiesNonVacuumable(), and HeapTupleSatisfiesVacuum().

1199 {
1200  HeapTupleHeader tuple = htup->t_data;
1201 
1202  Assert(ItemPointerIsValid(&htup->t_self));
1203  Assert(htup->t_tableOid != InvalidOid);
1204  Assert(dead_after != NULL);
1205 
1206  *dead_after = InvalidTransactionId;
1207 
1208  /*
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  */
1214  if (!HeapTupleHeaderXminCommitted(tuple))
1215  {
1216  if (HeapTupleHeaderXminInvalid(tuple))
1217  return HEAPTUPLE_DEAD;
1218  /* Used by pre-9.0 binary upgrades */
1219  else if (tuple->t_infomask & HEAP_MOVED_OFF)
1220  {
1221  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1222 
1225  if (TransactionIdIsInProgress(xvac))
1227  if (TransactionIdDidCommit(xvac))
1228  {
1229  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1231  return HEAPTUPLE_DEAD;
1232  }
1233  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1235  }
1236  /* Used by pre-9.0 binary upgrades */
1237  else if (tuple->t_infomask & HEAP_MOVED_IN)
1238  {
1239  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1240 
1243  if (TransactionIdIsInProgress(xvac))
1245  if (TransactionIdDidCommit(xvac))
1246  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1248  else
1249  {
1250  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1252  return HEAPTUPLE_DEAD;
1253  }
1254  }
1256  {
1257  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1259  /* only locked? run infomask-only check first, for performance */
1260  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
1263  /* inserted and then deleted by same xact */
1266  /* deleting subtransaction must have aborted */
1268  }
1270  {
1271  /*
1272  * 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  */
1280  }
1282  SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1283  HeapTupleHeaderGetRawXmin(tuple));
1284  else
1285  {
1286  /*
1287  * Not in Progress, Not Committed, so either Aborted or crashed
1288  */
1289  SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1291  return HEAPTUPLE_DEAD;
1292  }
1293 
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  */
1305  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1306  return HEAPTUPLE_LIVE;
1307 
1309  {
1310  /*
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  */
1316  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1317  {
1318  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1319  {
1320  /*
1321  * If it's a pre-pg_upgrade tuple, the multixact cannot
1322  * possibly be running; otherwise have to check.
1323  */
1324  if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
1326  true))
1327  return HEAPTUPLE_LIVE;
1329  }
1330  else
1331  {
1333  return HEAPTUPLE_LIVE;
1334  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1336  }
1337  }
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 
1345  return HEAPTUPLE_LIVE;
1346  }
1347 
1348  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1349  {
1350  TransactionId xmax = HeapTupleGetUpdateXid(tuple);
1351 
1352  /* already checked above */
1354 
1355  /* not LOCKED_ONLY, so it has to have an xmax */
1357 
1358  if (TransactionIdIsInProgress(xmax))
1360  else if (TransactionIdDidCommit(xmax))
1361  {
1362  /*
1363  * 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  */
1370  *dead_after = xmax;
1371  return HEAPTUPLE_RECENTLY_DEAD;
1372  }
1373  else if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
1374  {
1375  /*
1376  * Not in Progress, Not Committed, so either Aborted or crashed.
1377  * Mark the Xmax as invalid.
1378  */
1380  }
1381 
1382  return HEAPTUPLE_LIVE;
1383  }
1384 
1385  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1386  {
1390  SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1391  HeapTupleHeaderGetRawXmax(tuple));
1392  else
1393  {
1394  /*
1395  * Not in Progress, Not Committed, so either Aborted or crashed
1396  */
1397  SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1399  return HEAPTUPLE_LIVE;
1400  }
1401 
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  */
1413  *dead_after = HeapTupleHeaderGetRawXmax(tuple);
1414  return HEAPTUPLE_RECENTLY_DEAD;
1415 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:365
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:82
uint32 TransactionId
Definition: c.h:520
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:1305
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6540
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:252
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:206
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:68
#define HEAP_XMIN_INVALID
Definition: htup_details.h:204
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:375
#define HEAP_XMAX_INVALID
Definition: htup_details.h:207
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:324
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:415
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:213
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:230
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:208
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:203
#define InvalidOid
Definition: postgres_ext.h:36
#define HEAP_MOVED_OFF
Definition: htup_details.h:210
#define Assert(condition)
Definition: c.h:745
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:308
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:551

◆ HeapTupleSatisfiesVisibility()

bool HeapTupleSatisfiesVisibility ( HeapTuple  tup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 1769 of file heapam_visibility.c.

References HeapTupleSatisfiesAny(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesHistoricMVCC(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesNonVacuumable(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), SNAPSHOT_ANY, SNAPSHOT_DIRTY, SNAPSHOT_HISTORIC_MVCC, SNAPSHOT_MVCC, SNAPSHOT_NON_VACUUMABLE, SNAPSHOT_SELF, SNAPSHOT_TOAST, and SnapshotData::snapshot_type.

Referenced by heap_delete(), heap_fetch(), heap_get_latest_tid(), heap_hot_search_buffer(), heap_update(), heapam_scan_bitmap_next_block(), heapam_tuple_satisfies_snapshot(), heapgetpage(), heapgettup(), pgstat_heap(), and SampleHeapTupleVisible().

1770 {
1771  switch (snapshot->snapshot_type)
1772  {
1773  case SNAPSHOT_MVCC:
1774  return HeapTupleSatisfiesMVCC(tup, snapshot, buffer);
1775  break;
1776  case SNAPSHOT_SELF:
1777  return HeapTupleSatisfiesSelf(tup, snapshot, buffer);
1778  break;
1779  case SNAPSHOT_ANY:
1780  return HeapTupleSatisfiesAny(tup, snapshot, buffer);
1781  break;
1782  case SNAPSHOT_TOAST:
1783  return HeapTupleSatisfiesToast(tup, snapshot, buffer);
1784  break;
1785  case SNAPSHOT_DIRTY:
1786  return HeapTupleSatisfiesDirty(tup, snapshot, buffer);
1787  break;
1789  return HeapTupleSatisfiesHistoricMVCC(tup, snapshot, buffer);
1790  break;
1792  return HeapTupleSatisfiesNonVacuumable(tup, snapshot, buffer);
1793  break;
1794  }
1795 
1796  return false; /* keep compiler quiet */
1797 }
static bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
SnapshotType snapshot_type
Definition: snapshot.h:144
static bool HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static bool HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot, Buffer buffer)

◆ HeapTupleSetHintBits()

void HeapTupleSetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)

Definition at line 140 of file heapam_visibility.c.

References SetHintBits().

Referenced by UpdateXmaxHintBits().

142 {
143  SetHintBits(tuple, buffer, infomask, xid);
144 }
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)

◆ SetHintBits()

static void SetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)
inlinestatic

Definition at line 113 of file heapam_visibility.c.

References BufferGetLSNAtomic(), BufferIsPermanent(), MarkBufferDirtyHint(), HeapTupleHeaderData::t_infomask, TransactionIdGetCommitLSN(), TransactionIdIsValid, and XLogNeedsFlush().

Referenced by HeapTupleSatisfiesDirty(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuumHorizon(), and HeapTupleSetHintBits().

115 {
116  if (TransactionIdIsValid(xid))
117  {
118  /* NB: xid must be known committed here! */
119  XLogRecPtr commitLSN = TransactionIdGetCommitLSN(xid);
120 
121  if (BufferIsPermanent(buffer) && XLogNeedsFlush(commitLSN) &&
122  BufferGetLSNAtomic(buffer) < commitLSN)
123  {
124  /* not flushed and no LSN interlock, so don't set hint */
125  return;
126  }
127  }
128 
129  tuple->t_infomask |= infomask;
130  MarkBufferDirtyHint(buffer, true);
131 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3581
bool XLogNeedsFlush(XLogRecPtr record)
Definition: xlog.c:3166
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:2924
bool BufferIsPermanent(Buffer buffer)
Definition: bufmgr.c:2894
XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid)
Definition: transam.c:402
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ TransactionIdInArray()

static bool TransactionIdInArray ( TransactionId  xid,
TransactionId xip,
Size  num 
)
static

Definition at line 1568 of file heapam_visibility.c.

References xidComparator().

Referenced by HeapTupleSatisfiesHistoricMVCC().

1569 {
1570  return bsearch(&xid, xip, num,
1571  sizeof(TransactionId), xidComparator) != NULL;
1572 }
uint32 TransactionId
Definition: c.h:520
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:139