PostgreSQL Source Code  git master
tqual.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/subtrans.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 "utils/tqual.h"
Include dependency graph for tqual.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)
 
bool HeapTupleSatisfiesSelf (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesAny (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesToast (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
HTSU_Result HeapTupleSatisfiesUpdate (HeapTuple htup, CommandId curcid, Buffer buffer)
 
bool HeapTupleSatisfiesDirty (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
HTSV_Result HeapTupleSatisfiesVacuum (HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
 
bool HeapTupleSatisfiesNonVacuumable (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleIsSurelyDead (HeapTuple htup, TransactionId OldestXmin)
 
bool XidInMVCCSnapshot (TransactionId xid, Snapshot snapshot)
 
bool HeapTupleHeaderIsOnlyLocked (HeapTupleHeader tuple)
 
static bool TransactionIdInArray (TransactionId xid, TransactionId *xip, Size num)
 
bool HeapTupleSatisfiesHistoricMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 

Variables

SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}
 
SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}
 

Function Documentation

◆ HeapTupleHeaderIsOnlyLocked()

bool HeapTupleHeaderIsOnlyLocked ( HeapTupleHeader  tuple)

Definition at line 1605 of file tqual.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(), HeapTupleSatisfiesVacuum(), and rewrite_heap_tuple().

1606 {
1607  TransactionId xmax;
1608 
1609  /* if there's no valid Xmax, then there's obviously no update either */
1610  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1611  return true;
1612 
1613  if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
1614  return true;
1615 
1616  /* invalid xmax means no update */
1618  return true;
1619 
1620  /*
1621  * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this must
1622  * necessarily have been updated
1623  */
1624  if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
1625  return false;
1626 
1627  /* ... but if it's a multi, then perhaps the updating Xid aborted. */
1628  xmax = HeapTupleGetUpdateXid(tuple);
1629 
1630  /* not LOCKED_ONLY, so it has to have an xmax */
1632 
1634  return false;
1635  if (TransactionIdIsInProgress(xmax))
1636  return false;
1637  if (TransactionIdDidCommit(xmax))
1638  return false;
1639 
1640  /*
1641  * not current, not in progress, not committed -- must have aborted or
1642  * crashed
1643  */
1644  return true;
1645 }
#define HEAP_XMAX_LOCK_ONLY
Definition: htup_details.h:187
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define Assert(condition)
Definition: c.h:670
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleIsSurelyDead()

bool HeapTupleIsSurelyDead ( HeapTuple  htup,
TransactionId  OldestXmin 
)

Definition at line 1429 of file tqual.c.

References Assert, 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, TransactionIdPrecedes(), and true.

Referenced by heap_hot_search_buffer().

1430 {
1431  HeapTupleHeader tuple = htup->t_data;
1432 
1433  Assert(ItemPointerIsValid(&htup->t_self));
1434  Assert(htup->t_tableOid != InvalidOid);
1435 
1436  /*
1437  * If the inserting transaction is marked invalid, then it aborted, and
1438  * the tuple is definitely dead. If it's marked neither committed nor
1439  * invalid, then we assume it's still alive (since the presumption is that
1440  * all relevant hint bits were just set moments ago).
1441  */
1442  if (!HeapTupleHeaderXminCommitted(tuple))
1443  return HeapTupleHeaderXminInvalid(tuple) ? true : false;
1444 
1445  /*
1446  * If the inserting transaction committed, but any deleting transaction
1447  * aborted, the tuple is still alive.
1448  */
1449  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1450  return false;
1451 
1452  /*
1453  * If the XMAX is just a lock, the tuple is still alive.
1454  */
1456  return false;
1457 
1458  /*
1459  * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
1460  * know without checking pg_multixact.
1461  */
1462  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1463  return false;
1464 
1465  /* If deleter isn't known to have committed, assume it's still running. */
1466  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1467  return false;
1468 
1469  /* Deleter committed, so tuple is dead if the XID is old enough. */
1471 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
HeapTupleHeader t_data
Definition: htup.h:67
#define true
Definition: c.h:251
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
Oid t_tableOid
Definition: htup.h:66
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:670

◆ HeapTupleSatisfiesAny()

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

Definition at line 346 of file tqual.c.

347 {
348  return true;
349 }

◆ HeapTupleSatisfiesDirty()

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

Definition at line 739 of file tqual.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.

741 {
742  HeapTupleHeader tuple = htup->t_data;
743 
745  Assert(htup->t_tableOid != InvalidOid);
746 
747  snapshot->xmin = snapshot->xmax = InvalidTransactionId;
748  snapshot->speculativeToken = 0;
749 
750  if (!HeapTupleHeaderXminCommitted(tuple))
751  {
752  if (HeapTupleHeaderXminInvalid(tuple))
753  return false;
754 
755  /* Used by pre-9.0 binary upgrades */
756  if (tuple->t_infomask & HEAP_MOVED_OFF)
757  {
759 
761  return false;
762  if (!TransactionIdIsInProgress(xvac))
763  {
764  if (TransactionIdDidCommit(xvac))
765  {
768  return false;
769  }
772  }
773  }
774  /* Used by pre-9.0 binary upgrades */
775  else if (tuple->t_infomask & HEAP_MOVED_IN)
776  {
778 
780  {
781  if (TransactionIdIsInProgress(xvac))
782  return false;
783  if (TransactionIdDidCommit(xvac))
786  else
787  {
790  return false;
791  }
792  }
793  }
795  {
796  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
797  return true;
798 
799  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
800  return true;
801 
802  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
803  {
804  TransactionId xmax;
805 
806  xmax = HeapTupleGetUpdateXid(tuple);
807 
808  /* not LOCKED_ONLY, so it has to have an xmax */
810 
811  /* updating subtransaction must have aborted */
813  return true;
814  else
815  return false;
816  }
817 
819  {
820  /* deleting subtransaction must have aborted */
823  return true;
824  }
825 
826  return false;
827  }
829  {
830  /*
831  * Return the speculative token to caller. Caller can worry about
832  * xmax, since it requires a conclusively locked row version, and
833  * a concurrent update to this tuple is a conflict of its
834  * purposes.
835  */
836  if (HeapTupleHeaderIsSpeculative(tuple))
837  {
838  snapshot->speculativeToken =
840 
841  Assert(snapshot->speculativeToken != 0);
842  }
843 
844  snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
845  /* XXX shouldn't we fall through to look at xmax? */
846  return true; /* in insertion by other */
847  }
851  else
852  {
853  /* it must have aborted or crashed */
856  return false;
857  }
858  }
859 
860  /* by here, the inserting transaction has committed */
861 
862  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
863  return true;
864 
865  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
866  {
868  return true;
869  return false; /* updated by other */
870  }
871 
872  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
873  {
874  TransactionId xmax;
875 
877  return true;
878 
879  xmax = HeapTupleGetUpdateXid(tuple);
880 
881  /* not LOCKED_ONLY, so it has to have an xmax */
883 
885  return false;
886  if (TransactionIdIsInProgress(xmax))
887  {
888  snapshot->xmax = xmax;
889  return true;
890  }
891  if (TransactionIdDidCommit(xmax))
892  return false;
893  /* it must have aborted or crashed */
894  return true;
895  }
896 
898  {
900  return true;
901  return false;
902  }
903 
905  {
907  snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
908  return true;
909  }
910 
912  {
913  /* it must have aborted or crashed */
916  return true;
917  }
918 
919  /* xmax transaction committed */
920 
922  {
925  return true;
926  }
927 
930  return false; /* updated by other */
931 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
#define HeapTupleHeaderGetSpeculativeToken(tup)
Definition: htup_details.h:433
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:428
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
Oid t_tableOid
Definition: htup.h:66
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
#define HEAP_MOVED_IN
Definition: htup_details.h:204
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
uint32 speculativeToken
Definition: snapshot.h:104
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesHistoricMVCC()

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

Definition at line 1672 of file tqual.c.

References Assert, SnapshotData::curcid, elog, ERROR, 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 SnapBuildBuildSnapshot(), SnapBuildFreeSnapshot(), and SnapBuildSnapDecRefcount().

1674 {
1675  HeapTupleHeader tuple = htup->t_data;
1676  TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
1678 
1679  Assert(ItemPointerIsValid(&htup->t_self));
1680  Assert(htup->t_tableOid != InvalidOid);
1681 
1682  /* inserting transaction aborted */
1683  if (HeapTupleHeaderXminInvalid(tuple))
1684  {
1686  return false;
1687  }
1688  /* check if it's one of our txids, toplevel is also in there */
1689  else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
1690  {
1691  bool resolved;
1693  CommandId cmax = InvalidCommandId;
1694 
1695  /*
1696  * another transaction might have (tried to) delete this tuple or
1697  * cmin/cmax was stored in a combocid. So we need to lookup the actual
1698  * values externally.
1699  */
1701  htup, buffer,
1702  &cmin, &cmax);
1703 
1704  if (!resolved)
1705  elog(ERROR, "could not resolve cmin/cmax of catalog tuple");
1706 
1707  Assert(cmin != InvalidCommandId);
1708 
1709  if (cmin >= snapshot->curcid)
1710  return false; /* inserted after scan started */
1711  /* fall through */
1712  }
1713  /* committed before our xmin horizon. Do a normal visibility check. */
1714  else if (TransactionIdPrecedes(xmin, snapshot->xmin))
1715  {
1717  !TransactionIdDidCommit(xmin)));
1718 
1719  /* check for hint bit first, consult clog afterwards */
1720  if (!HeapTupleHeaderXminCommitted(tuple) &&
1721  !TransactionIdDidCommit(xmin))
1722  return false;
1723  /* fall through */
1724  }
1725  /* beyond our xmax horizon, i.e. invisible */
1726  else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
1727  {
1728  return false;
1729  }
1730  /* check if it's a committed transaction in [xmin, xmax) */
1731  else if (TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
1732  {
1733  /* fall through */
1734  }
1735 
1736  /*
1737  * none of the above, i.e. between [xmin, xmax) but hasn't committed. I.e.
1738  * invisible.
1739  */
1740  else
1741  {
1742  return false;
1743  }
1744 
1745  /* at this point we know xmin is visible, go on to check xmax */
1746 
1747  /* xid invalid or aborted */
1748  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1749  return true;
1750  /* locked tuples are always visible */
1751  else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1752  return true;
1753 
1754  /*
1755  * We can see multis here if we're looking at user tables or if somebody
1756  * SELECT ... FOR SHARE/UPDATE a system table.
1757  */
1758  else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1759  {
1760  xmax = HeapTupleGetUpdateXid(tuple);
1761  }
1762 
1763  /* check if it's one of our txids, toplevel is also in there */
1764  if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
1765  {
1766  bool resolved;
1767  CommandId cmin;
1769 
1770  /* Lookup actual cmin/cmax values */
1772  htup, buffer,
1773  &cmin, &cmax);
1774 
1775  if (!resolved)
1776  elog(ERROR, "could not resolve combocid to cmax");
1777 
1778  Assert(cmax != InvalidCommandId);
1779 
1780  if (cmax >= snapshot->curcid)
1781  return true; /* deleted after scan started */
1782  else
1783  return false; /* deleted before scan started */
1784  }
1785  /* below xmin horizon, normal transaction state is valid */
1786  else if (TransactionIdPrecedes(xmax, snapshot->xmin))
1787  {
1788  Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
1789  !TransactionIdDidCommit(xmax)));
1790 
1791  /* check hint bit first */
1792  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
1793  return false;
1794 
1795  /* check clog */
1796  return !TransactionIdDidCommit(xmax);
1797  }
1798  /* above xmax horizon, we cannot possibly see the deleting transaction */
1799  else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
1800  return true;
1801  /* xmax is between [xmin, xmax), check known committed array */
1802  else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
1803  return false;
1804  /* xmax is between [xmin, xmax), but known not to have committed yet */
1805  else
1806  return true;
1807 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 CommandId
Definition: c.h:459
uint32 TransactionId
Definition: c.h:445
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define ERROR
Definition: elog.h:43
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
Oid t_tableOid
Definition: htup.h:66
static bool TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
Definition: tqual.c:1651
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:79
#define InvalidCommandId
Definition: c.h:462
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:98
#define Assert(condition)
Definition: c.h:670
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define HeapTupleHeaderGetRawCommandId(tup)
Definition: htup_details.h:390
HTAB * HistoricSnapshotGetTupleCids(void)
Definition: snapmgr.c:2032
uint32 xcnt
Definition: snapshot.h:80
#define elog
Definition: elog.h:219
TransactionId * subxip
Definition: snapshot.h:91
int32 subxcnt
Definition: snapshot.h:92
bool ResolveCminCmaxDuringDecoding(HTAB *tuplecid_data, Snapshot snapshot, HeapTuple htup, Buffer buffer, CommandId *cmin, CommandId *cmax)

◆ HeapTupleSatisfiesMVCC()

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

Definition at line 963 of file tqual.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 EstimateSnapshotSpace(), RestoreSnapshot(), and TestForOldSnapshot().

965 {
966  HeapTupleHeader tuple = htup->t_data;
967 
969  Assert(htup->t_tableOid != InvalidOid);
970 
971  if (!HeapTupleHeaderXminCommitted(tuple))
972  {
973  if (HeapTupleHeaderXminInvalid(tuple))
974  return false;
975 
976  /* Used by pre-9.0 binary upgrades */
977  if (tuple->t_infomask & HEAP_MOVED_OFF)
978  {
980 
982  return false;
983  if (!XidInMVCCSnapshot(xvac, snapshot))
984  {
985  if (TransactionIdDidCommit(xvac))
986  {
989  return false;
990  }
993  }
994  }
995  /* Used by pre-9.0 binary upgrades */
996  else if (tuple->t_infomask & HEAP_MOVED_IN)
997  {
999 
1001  {
1002  if (XidInMVCCSnapshot(xvac, snapshot))
1003  return false;
1004  if (TransactionIdDidCommit(xvac))
1007  else
1008  {
1011  return false;
1012  }
1013  }
1014  }
1016  {
1017  if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
1018  return false; /* inserted after scan started */
1019 
1020  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1021  return true;
1022 
1023  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
1024  return true;
1025 
1026  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1027  {
1028  TransactionId xmax;
1029 
1030  xmax = HeapTupleGetUpdateXid(tuple);
1031 
1032  /* not LOCKED_ONLY, so it has to have an xmax */
1034 
1035  /* updating subtransaction must have aborted */
1037  return true;
1038  else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1039  return true; /* updated after scan started */
1040  else
1041  return false; /* updated before scan started */
1042  }
1043 
1045  {
1046  /* deleting subtransaction must have aborted */
1049  return true;
1050  }
1051 
1052  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1053  return true; /* deleted after scan started */
1054  else
1055  return false; /* deleted before scan started */
1056  }
1057  else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1058  return false;
1061  HeapTupleHeaderGetRawXmin(tuple));
1062  else
1063  {
1064  /* it must have aborted or crashed */
1067  return false;
1068  }
1069  }
1070  else
1071  {
1072  /* xmin is committed, but maybe not according to our snapshot */
1073  if (!HeapTupleHeaderXminFrozen(tuple) &&
1074  XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1075  return false; /* treat as still in progress */
1076  }
1077 
1078  /* by here, the inserting transaction has committed */
1079 
1080  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
1081  return true;
1082 
1084  return true;
1085 
1086  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1087  {
1088  TransactionId xmax;
1089 
1090  /* already checked above */
1092 
1093  xmax = HeapTupleGetUpdateXid(tuple);
1094 
1095  /* not LOCKED_ONLY, so it has to have an xmax */
1097 
1099  {
1100  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1101  return true; /* deleted after scan started */
1102  else
1103  return false; /* deleted before scan started */
1104  }
1105  if (XidInMVCCSnapshot(xmax, snapshot))
1106  return true;
1107  if (TransactionIdDidCommit(xmax))
1108  return false; /* updating transaction committed */
1109  /* it must have aborted or crashed */
1110  return true;
1111  }
1112 
1113  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1114  {
1116  {
1117  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1118  return true; /* deleted after scan started */
1119  else
1120  return false; /* deleted before scan started */
1121  }
1122 
1123  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1124  return true;
1125 
1127  {
1128  /* it must have aborted or crashed */
1131  return true;
1132  }
1133 
1134  /* xmax transaction committed */
1136  HeapTupleHeaderGetRawXmax(tuple));
1137  }
1138  else
1139  {
1140  /* xmax is committed, but maybe not according to our snapshot */
1141  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1142  return true; /* treat as still in progress */
1143  }
1144 
1145  /* xmax transaction committed */
1146 
1147  return false;
1148 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:105
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:204
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HeapTupleHeaderXminFrozen(tup)
Definition: htup_details.h:334
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
CommandId curcid
Definition: snapshot.h:98
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: tqual.c:1484

◆ HeapTupleSatisfiesNonVacuumable()

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

Definition at line 1407 of file tqual.c.

References HEAPTUPLE_DEAD, HeapTupleSatisfiesVacuum(), and SnapshotData::xmin.

1409 {
1410  return HeapTupleSatisfiesVacuum(htup, snapshot->xmin, buffer)
1411  != HEAPTUPLE_DEAD;
1412 }
HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
Definition: tqual.c:1164
TransactionId xmin
Definition: snapshot.h:68
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214

◆ HeapTupleSatisfiesSelf()

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

Definition at line 176 of file tqual.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.

177 {
178  HeapTupleHeader tuple = htup->t_data;
179 
181  Assert(htup->t_tableOid != InvalidOid);
182 
183  if (!HeapTupleHeaderXminCommitted(tuple))
184  {
185  if (HeapTupleHeaderXminInvalid(tuple))
186  return false;
187 
188  /* Used by pre-9.0 binary upgrades */
189  if (tuple->t_infomask & HEAP_MOVED_OFF)
190  {
192 
194  return false;
195  if (!TransactionIdIsInProgress(xvac))
196  {
197  if (TransactionIdDidCommit(xvac))
198  {
201  return false;
202  }
205  }
206  }
207  /* Used by pre-9.0 binary upgrades */
208  else if (tuple->t_infomask & HEAP_MOVED_IN)
209  {
211 
213  {
214  if (TransactionIdIsInProgress(xvac))
215  return false;
216  if (TransactionIdDidCommit(xvac))
219  else
220  {
223  return false;
224  }
225  }
226  }
228  {
229  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
230  return true;
231 
232  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
233  return true;
234 
235  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
236  {
237  TransactionId xmax;
238 
239  xmax = HeapTupleGetUpdateXid(tuple);
240 
241  /* not LOCKED_ONLY, so it has to have an xmax */
243 
244  /* updating subtransaction must have aborted */
246  return true;
247  else
248  return false;
249  }
250 
252  {
253  /* deleting subtransaction must have aborted */
256  return true;
257  }
258 
259  return false;
260  }
262  return false;
266  else
267  {
268  /* it must have aborted or crashed */
271  return false;
272  }
273  }
274 
275  /* by here, the inserting transaction has committed */
276 
277  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
278  return true;
279 
280  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
281  {
283  return true;
284  return false; /* updated by other */
285  }
286 
287  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
288  {
289  TransactionId xmax;
290 
292  return true;
293 
294  xmax = HeapTupleGetUpdateXid(tuple);
295 
296  /* not LOCKED_ONLY, so it has to have an xmax */
298 
300  return false;
301  if (TransactionIdIsInProgress(xmax))
302  return true;
303  if (TransactionIdDidCommit(xmax))
304  return false;
305  /* it must have aborted or crashed */
306  return true;
307  }
308 
310  {
312  return true;
313  return false;
314  }
315 
317  return true;
318 
320  {
321  /* it must have aborted or crashed */
324  return true;
325  }
326 
327  /* xmax transaction committed */
328 
330  {
333  return true;
334  }
335 
338  return false;
339 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:204
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesToast()

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

Definition at line 366 of file tqual.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 TestForOldSnapshot().

368 {
369  HeapTupleHeader tuple = htup->t_data;
370 
372  Assert(htup->t_tableOid != InvalidOid);
373 
374  if (!HeapTupleHeaderXminCommitted(tuple))
375  {
376  if (HeapTupleHeaderXminInvalid(tuple))
377  return false;
378 
379  /* Used by pre-9.0 binary upgrades */
380  if (tuple->t_infomask & HEAP_MOVED_OFF)
381  {
383 
385  return false;
386  if (!TransactionIdIsInProgress(xvac))
387  {
388  if (TransactionIdDidCommit(xvac))
389  {
392  return false;
393  }
396  }
397  }
398  /* Used by pre-9.0 binary upgrades */
399  else if (tuple->t_infomask & HEAP_MOVED_IN)
400  {
402 
404  {
405  if (TransactionIdIsInProgress(xvac))
406  return false;
407  if (TransactionIdDidCommit(xvac))
410  else
411  {
414  return false;
415  }
416  }
417  }
418 
419  /*
420  * An invalid Xmin can be left behind by a speculative insertion that
421  * is canceled by super-deleting the tuple. This also applies to
422  * TOAST tuples created during speculative insertion.
423  */
425  return false;
426  }
427 
428  /* otherwise assume the tuple is valid for TOAST. */
429  return true;
430 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:204
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:312
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ HeapTupleSatisfiesUpdate()

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

Definition at line 460 of file tqual.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, HeapTupleBeingUpdated, HeapTupleGetUpdateXid(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderGetRawXmax, HeapTupleHeaderGetRawXmin, HeapTupleHeaderGetXvac, HeapTupleHeaderXminCommitted, HeapTupleHeaderXminInvalid, HeapTupleInvisible, HeapTupleMayBeUpdated, HeapTupleSelfUpdated, HeapTupleUpdated, 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_delete(), heap_lock_tuple(), heap_update(), and pgrowlocks().

462 {
463  HeapTupleHeader tuple = htup->t_data;
464 
466  Assert(htup->t_tableOid != InvalidOid);
467 
468  if (!HeapTupleHeaderXminCommitted(tuple))
469  {
470  if (HeapTupleHeaderXminInvalid(tuple))
471  return HeapTupleInvisible;
472 
473  /* Used by pre-9.0 binary upgrades */
474  if (tuple->t_infomask & HEAP_MOVED_OFF)
475  {
477 
479  return HeapTupleInvisible;
480  if (!TransactionIdIsInProgress(xvac))
481  {
482  if (TransactionIdDidCommit(xvac))
483  {
486  return HeapTupleInvisible;
487  }
490  }
491  }
492  /* Used by pre-9.0 binary upgrades */
493  else if (tuple->t_infomask & HEAP_MOVED_IN)
494  {
496 
498  {
499  if (TransactionIdIsInProgress(xvac))
500  return HeapTupleInvisible;
501  if (TransactionIdDidCommit(xvac))
504  else
505  {
508  return HeapTupleInvisible;
509  }
510  }
511  }
513  {
514  if (HeapTupleHeaderGetCmin(tuple) >= curcid)
515  return HeapTupleInvisible; /* inserted after scan started */
516 
517  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
518  return HeapTupleMayBeUpdated;
519 
521  {
522  TransactionId xmax;
523 
524  xmax = HeapTupleHeaderGetRawXmax(tuple);
525 
526  /*
527  * 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 
533  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
534  {
535  if (MultiXactIdIsRunning(xmax, true))
536  return HeapTupleBeingUpdated;
537  else
538  return HeapTupleMayBeUpdated;
539  }
540 
541  /*
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  */
546  if (!TransactionIdIsInProgress(xmax))
547  return HeapTupleMayBeUpdated;
548  return HeapTupleBeingUpdated;
549  }
550 
551  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
552  {
553  TransactionId xmax;
554 
555  xmax = HeapTupleGetUpdateXid(tuple);
556 
557  /* not LOCKED_ONLY, so it has to have an xmax */
559 
560  /* deleting subtransaction must have aborted */
562  {
564  false))
565  return HeapTupleBeingUpdated;
566  return HeapTupleMayBeUpdated;
567  }
568  else
569  {
570  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
571  return HeapTupleSelfUpdated; /* updated after scan
572  * started */
573  else
574  return HeapTupleInvisible; /* updated before scan
575  * started */
576  }
577  }
578 
580  {
581  /* deleting subtransaction must have aborted */
584  return HeapTupleMayBeUpdated;
585  }
586 
587  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
588  return HeapTupleSelfUpdated; /* updated after scan started */
589  else
590  return HeapTupleInvisible; /* updated before scan started */
591  }
593  return HeapTupleInvisible;
597  else
598  {
599  /* it must have aborted or crashed */
602  return HeapTupleInvisible;
603  }
604  }
605 
606  /* by here, the inserting transaction has committed */
607 
608  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
609  return HeapTupleMayBeUpdated;
610 
611  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
612  {
614  return HeapTupleMayBeUpdated;
615  return HeapTupleUpdated; /* updated by other */
616  }
617 
618  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
619  {
620  TransactionId xmax;
621 
622  if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
623  return HeapTupleMayBeUpdated;
624 
626  {
628  return HeapTupleBeingUpdated;
629 
631  return HeapTupleMayBeUpdated;
632  }
633 
634  xmax = HeapTupleGetUpdateXid(tuple);
635  if (!TransactionIdIsValid(xmax))
636  {
638  return HeapTupleBeingUpdated;
639  }
640 
641  /* not LOCKED_ONLY, so it has to have an xmax */
643 
645  {
646  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
647  return HeapTupleSelfUpdated; /* updated after scan started */
648  else
649  return HeapTupleInvisible; /* updated before scan started */
650  }
651 
653  return HeapTupleBeingUpdated;
654 
655  if (TransactionIdDidCommit(xmax))
656  return HeapTupleUpdated;
657 
658  /*
659  * By here, the update in the Xmax is either aborted or crashed, but
660  * what about the other members?
661  */
662 
664  {
665  /*
666  * There's no member, even just a locker, alive anymore, so we can
667  * mark the Xmax as invalid.
668  */
671  return HeapTupleMayBeUpdated;
672  }
673  else
674  {
675  /* There are lockers running */
676  return HeapTupleBeingUpdated;
677  }
678  }
679 
681  {
683  return HeapTupleBeingUpdated;
684  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
685  return HeapTupleSelfUpdated; /* updated after scan started */
686  else
687  return HeapTupleInvisible; /* updated before scan started */
688  }
689 
691  return HeapTupleBeingUpdated;
692 
694  {
695  /* it must have aborted or crashed */
698  return HeapTupleMayBeUpdated;
699  }
700 
701  /* xmax transaction committed */
702 
704  {
707  return HeapTupleMayBeUpdated;
708  }
709 
712  return HeapTupleUpdated; /* updated by other */
713 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:105
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:243
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:204
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
CommandId HeapTupleHeaderGetCmax(HeapTupleHeader tup)
Definition: combocid.c:119
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:549

◆ HeapTupleSatisfiesVacuum()

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

Definition at line 1164 of file tqual.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(), TransactionIdIsValid, and TransactionIdPrecedes().

Referenced by acquire_sample_rows(), CheckForSerializableConflictOut(), copy_heap_data(), heap_page_is_all_visible(), heap_prune_chain(), HeapTupleSatisfiesNonVacuumable(), IndexBuildHeapRangeScan(), lazy_scan_heap(), statapprox_heap(), and tuple_all_visible().

1166 {
1167  HeapTupleHeader tuple = htup->t_data;
1168 
1169  Assert(ItemPointerIsValid(&htup->t_self));
1170  Assert(htup->t_tableOid != InvalidOid);
1171 
1172  /*
1173  * Has inserting transaction committed?
1174  *
1175  * If the inserting transaction aborted, then the tuple was never visible
1176  * to any other transaction, so we can delete it immediately.
1177  */
1178  if (!HeapTupleHeaderXminCommitted(tuple))
1179  {
1180  if (HeapTupleHeaderXminInvalid(tuple))
1181  return HEAPTUPLE_DEAD;
1182  /* Used by pre-9.0 binary upgrades */
1183  else if (tuple->t_infomask & HEAP_MOVED_OFF)
1184  {
1185  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1186 
1189  if (TransactionIdIsInProgress(xvac))
1191  if (TransactionIdDidCommit(xvac))
1192  {
1195  return HEAPTUPLE_DEAD;
1196  }
1199  }
1200  /* Used by pre-9.0 binary upgrades */
1201  else if (tuple->t_infomask & HEAP_MOVED_IN)
1202  {
1203  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1204 
1207  if (TransactionIdIsInProgress(xvac))
1209  if (TransactionIdDidCommit(xvac))
1212  else
1213  {
1216  return HEAPTUPLE_DEAD;
1217  }
1218  }
1220  {
1221  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1223  /* only locked? run infomask-only check first, for performance */
1224  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
1227  /* inserted and then deleted by same xact */
1230  /* deleting subtransaction must have aborted */
1232  }
1234  {
1235  /*
1236  * It'd be possible to discern between INSERT/DELETE in progress
1237  * here by looking at xmax - but that doesn't seem beneficial for
1238  * the majority of callers and even detrimental for some. We'd
1239  * rather have callers look at/wait for xmin than xmax. It's
1240  * always correct to return INSERT_IN_PROGRESS because that's
1241  * what's happening from the view of other backends.
1242  */
1244  }
1247  HeapTupleHeaderGetRawXmin(tuple));
1248  else
1249  {
1250  /*
1251  * Not in Progress, Not Committed, so either Aborted or crashed
1252  */
1255  return HEAPTUPLE_DEAD;
1256  }
1257 
1258  /*
1259  * At this point the xmin is known committed, but we might not have
1260  * been able to set the hint bit yet; so we can no longer Assert that
1261  * it's set.
1262  */
1263  }
1264 
1265  /*
1266  * Okay, the inserter committed, so it was good at some point. Now what
1267  * about the deleting transaction?
1268  */
1269  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1270  return HEAPTUPLE_LIVE;
1271 
1273  {
1274  /*
1275  * "Deleting" xact really only locked it, so the tuple is live in any
1276  * case. However, we should make sure that either XMAX_COMMITTED or
1277  * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
1278  * examining the tuple for future xacts.
1279  */
1280  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1281  {
1282  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1283  {
1284  /*
1285  * If it's a pre-pg_upgrade tuple, the multixact cannot
1286  * possibly be running; otherwise have to check.
1287  */
1288  if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
1290  true))
1291  return HEAPTUPLE_LIVE;
1293  }
1294  else
1295  {
1297  return HEAPTUPLE_LIVE;
1300  }
1301  }
1302 
1303  /*
1304  * We don't really care whether xmax did commit, abort or crash. We
1305  * know that xmax did lock the tuple, but it did not and will never
1306  * actually update it.
1307  */
1308 
1309  return HEAPTUPLE_LIVE;
1310  }
1311 
1312  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1313  {
1314  TransactionId xmax;
1315 
1317  {
1318  /* already checked above */
1320 
1321  xmax = HeapTupleGetUpdateXid(tuple);
1322 
1323  /* not LOCKED_ONLY, so it has to have an xmax */
1325 
1326  if (TransactionIdIsInProgress(xmax))
1328  else if (TransactionIdDidCommit(xmax))
1329  /* there are still lockers around -- can't return DEAD here */
1330  return HEAPTUPLE_RECENTLY_DEAD;
1331  /* updating transaction aborted */
1332  return HEAPTUPLE_LIVE;
1333  }
1334 
1335  Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));
1336 
1337  xmax = HeapTupleGetUpdateXid(tuple);
1338 
1339  /* not LOCKED_ONLY, so it has to have an xmax */
1341 
1342  /* multi is not running -- updating xact cannot be */
1344  if (TransactionIdDidCommit(xmax))
1345  {
1346  if (!TransactionIdPrecedes(xmax, OldestXmin))
1347  return HEAPTUPLE_RECENTLY_DEAD;
1348  else
1349  return HEAPTUPLE_DEAD;
1350  }
1351 
1352  /*
1353  * Not in Progress, Not Committed, so either Aborted or crashed.
1354  * Remove the Xmax.
1355  */
1357  return HEAPTUPLE_LIVE;
1358  }
1359 
1360  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1361  {
1366  HeapTupleHeaderGetRawXmax(tuple));
1367  else
1368  {
1369  /*
1370  * Not in Progress, Not Committed, so either Aborted or crashed
1371  */
1374  return HEAPTUPLE_LIVE;
1375  }
1376 
1377  /*
1378  * At this point the xmax is known committed, but we might not have
1379  * been able to set the hint bit yet; so we can no longer Assert that
1380  * it's set.
1381  */
1382  }
1383 
1384  /*
1385  * Deleter committed, but perhaps it was recent enough that some open
1386  * transactions could still see the tuple.
1387  */
1389  return HEAPTUPLE_RECENTLY_DEAD;
1390 
1391  /* Otherwise, it's dead and removable */
1392  return HEAPTUPLE_DEAD;
1393 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:364
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1605
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:445
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:766
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6983
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:243
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:328
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:197
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:195
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:374
#define HEAP_XMAX_INVALID
Definition: htup_details.h:198
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:323
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:414
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:204
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:221
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
#define HEAP_MOVED_OFF
Definition: htup_details.h:201
#define Assert(condition)
Definition: c.h:670
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:549

◆ HeapTupleSetHintBits()

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

Definition at line 144 of file tqual.c.

References SetHintBits().

Referenced by UpdateXmaxHintBits().

146 {
147  SetHintBits(tuple, buffer, infomask, xid);
148 }
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:117
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214

◆ SetHintBits()

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

Definition at line 117 of file tqual.c.

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

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

119 {
120  if (TransactionIdIsValid(xid))
121  {
122  /* NB: xid must be known committed here! */
123  XLogRecPtr commitLSN = TransactionIdGetCommitLSN(xid);
124 
125  if (BufferIsPermanent(buffer) && XLogNeedsFlush(commitLSN) &&
126  BufferGetLSNAtomic(buffer) < commitLSN)
127  {
128  /* not flushed and no LSN interlock, so don't set hint */
129  return;
130  }
131  }
132 
133  tuple->t_infomask |= infomask;
135 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
bool XLogNeedsFlush(XLogRecPtr record)
Definition: xlog.c:3084
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:2832
bool BufferIsPermanent(Buffer buffer)
Definition: bufmgr.c:2802
XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid)
Definition: transam.c:402
uint64 XLogRecPtr
Definition: xlogdefs.h:21
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define TransactionIdIsValid(xid)
Definition: transam.h:41

◆ TransactionIdInArray()

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

Definition at line 1651 of file tqual.c.

References xidComparator().

Referenced by HeapTupleSatisfiesHistoricMVCC().

1652 {
1653  return bsearch(&xid, xip, num,
1654  sizeof(TransactionId), xidComparator) != NULL;
1655 }
uint32 TransactionId
Definition: c.h:445
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:138

◆ XidInMVCCSnapshot()

bool XidInMVCCSnapshot ( TransactionId  xid,
Snapshot  snapshot 
)

Definition at line 1484 of file tqual.c.

References i, SnapshotData::suboverflowed, SubTransGetTopmostTransaction(), SnapshotData::subxcnt, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdEquals, TransactionIdFollowsOrEquals(), TransactionIdPrecedes(), SnapshotData::xcnt, SnapshotData::xip, SnapshotData::xmax, and SnapshotData::xmin.

Referenced by asyncQueueProcessPageEntries(), and HeapTupleSatisfiesMVCC().

1485 {
1486  uint32 i;
1487 
1488  /*
1489  * Make a quick range check to eliminate most XIDs without looking at the
1490  * xip arrays. Note that this is OK even if we convert a subxact XID to
1491  * its parent below, because a subxact with XID < xmin has surely also got
1492  * a parent with XID < xmin, while one with XID >= xmax must belong to a
1493  * parent that was not yet committed at the time of this snapshot.
1494  */
1495 
1496  /* Any xid < xmin is not in-progress */
1497  if (TransactionIdPrecedes(xid, snapshot->xmin))
1498  return false;
1499  /* Any xid >= xmax is in-progress */
1500  if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1501  return true;
1502 
1503  /*
1504  * Snapshot information is stored slightly differently in snapshots taken
1505  * during recovery.
1506  */
1507  if (!snapshot->takenDuringRecovery)
1508  {
1509  /*
1510  * If the snapshot contains full subxact data, the fastest way to
1511  * check things is just to compare the given XID against both subxact
1512  * XIDs and top-level XIDs. If the snapshot overflowed, we have to
1513  * use pg_subtrans to convert a subxact XID to its parent XID, but
1514  * then we need only look at top-level XIDs not subxacts.
1515  */
1516  if (!snapshot->suboverflowed)
1517  {
1518  /* we have full data, so search subxip */
1519  int32 j;
1520 
1521  for (j = 0; j < snapshot->subxcnt; j++)
1522  {
1523  if (TransactionIdEquals(xid, snapshot->subxip[j]))
1524  return true;
1525  }
1526 
1527  /* not there, fall through to search xip[] */
1528  }
1529  else
1530  {
1531  /*
1532  * Snapshot overflowed, so convert xid to top-level. This is safe
1533  * because we eliminated too-old XIDs above.
1534  */
1535  xid = SubTransGetTopmostTransaction(xid);
1536 
1537  /*
1538  * If xid was indeed a subxact, we might now have an xid < xmin,
1539  * so recheck to avoid an array scan. No point in rechecking
1540  * xmax.
1541  */
1542  if (TransactionIdPrecedes(xid, snapshot->xmin))
1543  return false;
1544  }
1545 
1546  for (i = 0; i < snapshot->xcnt; i++)
1547  {
1548  if (TransactionIdEquals(xid, snapshot->xip[i]))
1549  return true;
1550  }
1551  }
1552  else
1553  {
1554  int32 j;
1555 
1556  /*
1557  * In recovery we store all xids in the subxact array because it is by
1558  * far the bigger array, and we mostly don't know which xids are
1559  * top-level and which are subxacts. The xip array is empty.
1560  *
1561  * We start by searching subtrans, if we overflowed.
1562  */
1563  if (snapshot->suboverflowed)
1564  {
1565  /*
1566  * Snapshot overflowed, so convert xid to top-level. This is safe
1567  * because we eliminated too-old XIDs above.
1568  */
1569  xid = SubTransGetTopmostTransaction(xid);
1570 
1571  /*
1572  * If xid was indeed a subxact, we might now have an xid < xmin,
1573  * so recheck to avoid an array scan. No point in rechecking
1574  * xmax.
1575  */
1576  if (TransactionIdPrecedes(xid, snapshot->xmin))
1577  return false;
1578  }
1579 
1580  /*
1581  * We now have either a top-level xid higher than xmin or an
1582  * indeterminate xid. We don't know whether it's top level or subxact
1583  * but it doesn't matter. If it's present, the xid is visible.
1584  */
1585  for (j = 0; j < snapshot->subxcnt; j++)
1586  {
1587  if (TransactionIdEquals(xid, snapshot->subxip[j]))
1588  return true;
1589  }
1590  }
1591 
1592  return false;
1593 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:349
bool suboverflowed
Definition: snapshot.h:93
signed int int32
Definition: c.h:284
unsigned int uint32
Definition: c.h:296
TransactionId xmax
Definition: snapshot.h:69
TransactionId xmin
Definition: snapshot.h:68
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
TransactionId * xip
Definition: snapshot.h:79
bool takenDuringRecovery
Definition: snapshot.h:95
uint32 xcnt
Definition: snapshot.h:80
int i
TransactionId * subxip
Definition: snapshot.h:91
int32 subxcnt
Definition: snapshot.h:92

Variable Documentation

◆ SnapshotAnyData

SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny}

Definition at line 82 of file tqual.c.

◆ SnapshotSelfData

SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf}

Definition at line 81 of file tqual.c.