PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tqual.h File Reference
#include "utils/snapshot.h"
#include "access/xlogdefs.h"
Include dependency graph for tqual.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SnapshotSelf   (&SnapshotSelfData)
 
#define SnapshotAny   (&SnapshotAnyData)
 
#define IsMVCCSnapshot(snapshot)
 
#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer)   ((*(snapshot)->satisfies) (tuple, snapshot, buffer))
 
#define InitDirtySnapshot(snapshotdata)   ((snapshotdata).satisfies = HeapTupleSatisfiesDirty)
 
#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon)
 
#define InitToastSnapshot(snapshotdata, l, w)
 

Enumerations

enum  HTSV_Result {
  HEAPTUPLE_DEAD, HEAPTUPLE_LIVE, HEAPTUPLE_RECENTLY_DEAD, HEAPTUPLE_INSERT_IN_PROGRESS,
  HEAPTUPLE_DELETE_IN_PROGRESS
}
 

Functions

bool HeapTupleSatisfiesMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesSelf (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesAny (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesToast (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesDirty (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesNonVacuumable (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
bool HeapTupleSatisfiesHistoricMVCC (HeapTuple htup, Snapshot snapshot, Buffer buffer)
 
HTSU_Result HeapTupleSatisfiesUpdate (HeapTuple htup, CommandId curcid, Buffer buffer)
 
HTSV_Result HeapTupleSatisfiesVacuum (HeapTuple htup, TransactionId OldestXmin, Buffer buffer)
 
bool HeapTupleIsSurelyDead (HeapTuple htup, TransactionId OldestXmin)
 
void HeapTupleSetHintBits (HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
 
bool HeapTupleHeaderIsOnlyLocked (HeapTupleHeader tuple)
 
bool ResolveCminCmaxDuringDecoding (struct HTAB *tuplecid_data, Snapshot snapshot, HeapTuple htup, Buffer buffer, CommandId *cmin, CommandId *cmax)
 

Variables

PGDLLIMPORT SnapshotData SnapshotSelfData
 
PGDLLIMPORT SnapshotData SnapshotAnyData
 
PGDLLIMPORT SnapshotData CatalogSnapshotData
 

Macro Definition Documentation

#define HeapTupleSatisfiesVisibility (   tuple,
  snapshot,
  buffer 
)    ((*(snapshot)->satisfies) (tuple, snapshot, buffer))
#define InitDirtySnapshot (   snapshotdata)    ((snapshotdata).satisfies = HeapTupleSatisfiesDirty)
#define InitNonVacuumableSnapshot (   snapshotdata,
  xmin_horizon 
)
Value:
((snapshotdata).satisfies = HeapTupleSatisfiesNonVacuumable, \
(snapshotdata).xmin = (xmin_horizon))
bool HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:1409

Definition at line 109 of file tqual.h.

Referenced by get_actual_variable_range().

#define InitToastSnapshot (   snapshotdata,
  l,
 
)
Value:
((snapshotdata).satisfies = HeapTupleSatisfiesToast, \
(snapshotdata).lsn = (l), \
(snapshotdata).whenTaken = (w))
bool HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:368

Definition at line 117 of file tqual.h.

Referenced by init_toast_snapshot().

#define IsMVCCSnapshot (   snapshot)
Value:
((snapshot)->satisfies == HeapTupleSatisfiesMVCC || \
(snapshot)->satisfies == HeapTupleSatisfiesHistoricMVCC)
bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:1674
bool HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer)
Definition: tqual.c:965

Definition at line 31 of file tqual.h.

Referenced by _bt_drop_lock_and_maybe_pin(), ExecInitBitmapHeapScan(), heap_beginscan_internal(), heap_rescan_set_params(), heap_update_snapshot(), index_fetch_heap(), index_restrpos(), SerializationNeededForRead(), and systable_recheck_tuple().

Enumeration Type Documentation

Enumerator
HEAPTUPLE_DEAD 
HEAPTUPLE_LIVE 
HEAPTUPLE_RECENTLY_DEAD 
HEAPTUPLE_INSERT_IN_PROGRESS 
HEAPTUPLE_DELETE_IN_PROGRESS 

Definition at line 49 of file tqual.h.

50 {
51  HEAPTUPLE_DEAD, /* tuple is dead and deletable */
52  HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
53  HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
54  HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
55  HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
56 } HTSV_Result;
HTSV_Result
Definition: tqual.h:49

Function Documentation

bool HeapTupleHeaderIsOnlyLocked ( HeapTupleHeader  tuple)

Definition at line 1607 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().

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

Definition at line 1431 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, and TransactionIdPrecedes().

Referenced by heap_hot_search_buffer().

1432 {
1433  HeapTupleHeader tuple = htup->t_data;
1434 
1435  Assert(ItemPointerIsValid(&htup->t_self));
1436  Assert(htup->t_tableOid != InvalidOid);
1437 
1438  /*
1439  * If the inserting transaction is marked invalid, then it aborted, and
1440  * the tuple is definitely dead. If it's marked neither committed nor
1441  * invalid, then we assume it's still alive (since the presumption is that
1442  * all relevant hint bits were just set moments ago).
1443  */
1444  if (!HeapTupleHeaderXminCommitted(tuple))
1445  return HeapTupleHeaderXminInvalid(tuple) ? true : false;
1446 
1447  /*
1448  * If the inserting transaction committed, but any deleting transaction
1449  * aborted, the tuple is still alive.
1450  */
1451  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1452  return false;
1453 
1454  /*
1455  * If the XMAX is just a lock, the tuple is still alive.
1456  */
1458  return false;
1459 
1460  /*
1461  * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
1462  * know without checking pg_multixact.
1463  */
1464  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1465  return false;
1466 
1467  /* If deleter isn't known to have committed, assume it's still running. */
1468  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1469  return false;
1470 
1471  /* Deleter committed, so tuple is dead if the XID is old enough. */
1473 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
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:216
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:664
bool HeapTupleSatisfiesAny ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 348 of file tqual.c.

349 {
350  return true;
351 }
bool HeapTupleSatisfiesDirty ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 741 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.

743 {
744  HeapTupleHeader tuple = htup->t_data;
745 
747  Assert(htup->t_tableOid != InvalidOid);
748 
749  snapshot->xmin = snapshot->xmax = InvalidTransactionId;
750  snapshot->speculativeToken = 0;
751 
752  if (!HeapTupleHeaderXminCommitted(tuple))
753  {
754  if (HeapTupleHeaderXminInvalid(tuple))
755  return false;
756 
757  /* Used by pre-9.0 binary upgrades */
758  if (tuple->t_infomask & HEAP_MOVED_OFF)
759  {
761 
763  return false;
764  if (!TransactionIdIsInProgress(xvac))
765  {
766  if (TransactionIdDidCommit(xvac))
767  {
770  return false;
771  }
774  }
775  }
776  /* Used by pre-9.0 binary upgrades */
777  else if (tuple->t_infomask & HEAP_MOVED_IN)
778  {
780 
782  {
783  if (TransactionIdIsInProgress(xvac))
784  return false;
785  if (TransactionIdDidCommit(xvac))
788  else
789  {
792  return false;
793  }
794  }
795  }
797  {
798  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
799  return true;
800 
801  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
802  return true;
803 
804  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
805  {
806  TransactionId xmax;
807 
808  xmax = HeapTupleGetUpdateXid(tuple);
809 
810  /* not LOCKED_ONLY, so it has to have an xmax */
812 
813  /* updating subtransaction must have aborted */
815  return true;
816  else
817  return false;
818  }
819 
821  {
822  /* deleting subtransaction must have aborted */
825  return true;
826  }
827 
828  return false;
829  }
831  {
832  /*
833  * Return the speculative token to caller. Caller can worry about
834  * xmax, since it requires a conclusively locked row version, and
835  * a concurrent update to this tuple is a conflict of its
836  * purposes.
837  */
838  if (HeapTupleHeaderIsSpeculative(tuple))
839  {
840  snapshot->speculativeToken =
842 
843  Assert(snapshot->speculativeToken != 0);
844  }
845 
846  snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
847  /* XXX shouldn't we fall through to look at xmax? */
848  return true; /* in insertion by other */
849  }
853  else
854  {
855  /* it must have aborted or crashed */
858  return false;
859  }
860  }
861 
862  /* by here, the inserting transaction has committed */
863 
864  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
865  return true;
866 
867  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
868  {
870  return true;
871  return false; /* updated by other */
872  }
873 
874  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
875  {
876  TransactionId xmax;
877 
879  return true;
880 
881  xmax = HeapTupleGetUpdateXid(tuple);
882 
883  /* not LOCKED_ONLY, so it has to have an xmax */
885 
887  return false;
888  if (TransactionIdIsInProgress(xmax))
889  {
890  snapshot->xmax = xmax;
891  return true;
892  }
893  if (TransactionIdDidCommit(xmax))
894  return false;
895  /* it must have aborted or crashed */
896  return true;
897  }
898 
900  {
902  return true;
903  return false;
904  }
905 
907  {
909  snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
910  return true;
911  }
912 
914  {
915  /* it must have aborted or crashed */
918  return true;
919  }
920 
921  /* xmax transaction committed */
922 
924  {
927  return true;
928  }
929 
932  return false; /* updated by other */
933 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
#define HeapTupleHeaderGetSpeculativeToken(tup)
Definition: htup_details.h:428
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6981
#define HeapTupleHeaderIsSpeculative(tup)
Definition: htup_details.h:423
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
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:199
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
uint32 speculativeToken
Definition: snapshot.h:104
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool HeapTupleSatisfiesHistoricMVCC ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 1674 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().

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

Definition at line 965 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().

967 {
968  HeapTupleHeader tuple = htup->t_data;
969 
971  Assert(htup->t_tableOid != InvalidOid);
972 
973  if (!HeapTupleHeaderXminCommitted(tuple))
974  {
975  if (HeapTupleHeaderXminInvalid(tuple))
976  return false;
977 
978  /* Used by pre-9.0 binary upgrades */
979  if (tuple->t_infomask & HEAP_MOVED_OFF)
980  {
982 
984  return false;
985  if (!XidInMVCCSnapshot(xvac, snapshot))
986  {
987  if (TransactionIdDidCommit(xvac))
988  {
991  return false;
992  }
995  }
996  }
997  /* Used by pre-9.0 binary upgrades */
998  else if (tuple->t_infomask & HEAP_MOVED_IN)
999  {
1000  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1001 
1003  {
1004  if (XidInMVCCSnapshot(xvac, snapshot))
1005  return false;
1006  if (TransactionIdDidCommit(xvac))
1009  else
1010  {
1013  return false;
1014  }
1015  }
1016  }
1018  {
1019  if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
1020  return false; /* inserted after scan started */
1021 
1022  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1023  return true;
1024 
1025  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
1026  return true;
1027 
1028  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1029  {
1030  TransactionId xmax;
1031 
1032  xmax = HeapTupleGetUpdateXid(tuple);
1033 
1034  /* not LOCKED_ONLY, so it has to have an xmax */
1036 
1037  /* updating subtransaction must have aborted */
1039  return true;
1040  else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1041  return true; /* updated after scan started */
1042  else
1043  return false; /* updated before scan started */
1044  }
1045 
1047  {
1048  /* deleting subtransaction must have aborted */
1051  return true;
1052  }
1053 
1054  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1055  return true; /* deleted after scan started */
1056  else
1057  return false; /* deleted before scan started */
1058  }
1059  else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1060  return false;
1063  HeapTupleHeaderGetRawXmin(tuple));
1064  else
1065  {
1066  /* it must have aborted or crashed */
1069  return false;
1070  }
1071  }
1072  else
1073  {
1074  /* xmin is committed, but maybe not according to our snapshot */
1075  if (!HeapTupleHeaderXminFrozen(tuple) &&
1076  XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1077  return false; /* treat as still in progress */
1078  }
1079 
1080  /* by here, the inserting transaction has committed */
1081 
1082  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
1083  return true;
1084 
1086  return true;
1087 
1088  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1089  {
1090  TransactionId xmax;
1091 
1092  /* already checked above */
1094 
1095  xmax = HeapTupleGetUpdateXid(tuple);
1096 
1097  /* not LOCKED_ONLY, so it has to have an xmax */
1099 
1101  {
1102  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1103  return true; /* deleted after scan started */
1104  else
1105  return false; /* deleted before scan started */
1106  }
1107  if (XidInMVCCSnapshot(xmax, snapshot))
1108  return true;
1109  if (TransactionIdDidCommit(xmax))
1110  return false; /* updating transaction committed */
1111  /* it must have aborted or crashed */
1112  return true;
1113  }
1114 
1115  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1116  {
1118  {
1119  if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1120  return true; /* deleted after scan started */
1121  else
1122  return false; /* deleted before scan started */
1123  }
1124 
1125  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1126  return true;
1127 
1129  {
1130  /* it must have aborted or crashed */
1133  return true;
1134  }
1135 
1136  /* xmax transaction committed */
1138  HeapTupleHeaderGetRawXmax(tuple));
1139  }
1140  else
1141  {
1142  /* xmax is committed, but maybe not according to our snapshot */
1143  if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1144  return true; /* treat as still in progress */
1145  }
1146 
1147  /* xmax transaction committed */
1148 
1149  return false;
1150 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6981
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:105
static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
Definition: tqual.c:1486
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:199
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
#define HeapTupleHeaderXminFrozen(tup)
Definition: htup_details.h:329
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#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:119
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
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:302
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool HeapTupleSatisfiesNonVacuumable ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 1409 of file tqual.c.

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

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

Definition at line 178 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.

179 {
180  HeapTupleHeader tuple = htup->t_data;
181 
183  Assert(htup->t_tableOid != InvalidOid);
184 
185  if (!HeapTupleHeaderXminCommitted(tuple))
186  {
187  if (HeapTupleHeaderXminInvalid(tuple))
188  return false;
189 
190  /* Used by pre-9.0 binary upgrades */
191  if (tuple->t_infomask & HEAP_MOVED_OFF)
192  {
194 
196  return false;
197  if (!TransactionIdIsInProgress(xvac))
198  {
199  if (TransactionIdDidCommit(xvac))
200  {
203  return false;
204  }
207  }
208  }
209  /* Used by pre-9.0 binary upgrades */
210  else if (tuple->t_infomask & HEAP_MOVED_IN)
211  {
213 
215  {
216  if (TransactionIdIsInProgress(xvac))
217  return false;
218  if (TransactionIdDidCommit(xvac))
221  else
222  {
225  return false;
226  }
227  }
228  }
230  {
231  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
232  return true;
233 
234  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */
235  return true;
236 
237  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
238  {
239  TransactionId xmax;
240 
241  xmax = HeapTupleGetUpdateXid(tuple);
242 
243  /* not LOCKED_ONLY, so it has to have an xmax */
245 
246  /* updating subtransaction must have aborted */
248  return true;
249  else
250  return false;
251  }
252 
254  {
255  /* deleting subtransaction must have aborted */
258  return true;
259  }
260 
261  return false;
262  }
264  return false;
268  else
269  {
270  /* it must have aborted or crashed */
273  return false;
274  }
275  }
276 
277  /* by here, the inserting transaction has committed */
278 
279  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
280  return true;
281 
282  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
283  {
285  return true;
286  return false; /* updated by other */
287  }
288 
289  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
290  {
291  TransactionId xmax;
292 
294  return true;
295 
296  xmax = HeapTupleGetUpdateXid(tuple);
297 
298  /* not LOCKED_ONLY, so it has to have an xmax */
300 
302  return false;
303  if (TransactionIdIsInProgress(xmax))
304  return true;
305  if (TransactionIdDidCommit(xmax))
306  return false;
307  /* it must have aborted or crashed */
308  return true;
309  }
310 
312  {
314  return true;
315  return false;
316  }
317 
319  return true;
320 
322  {
323  /* it must have aborted or crashed */
326  return true;
327  }
328 
329  /* xmax transaction committed */
330 
332  {
335  return true;
336  }
337 
340  return false;
341 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6981
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:199
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool HeapTupleSatisfiesToast ( HeapTuple  htup,
Snapshot  snapshot,
Buffer  buffer 
)

Definition at line 368 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().

370 {
371  HeapTupleHeader tuple = htup->t_data;
372 
374  Assert(htup->t_tableOid != InvalidOid);
375 
376  if (!HeapTupleHeaderXminCommitted(tuple))
377  {
378  if (HeapTupleHeaderXminInvalid(tuple))
379  return false;
380 
381  /* Used by pre-9.0 binary upgrades */
382  if (tuple->t_infomask & HEAP_MOVED_OFF)
383  {
385 
387  return false;
388  if (!TransactionIdIsInProgress(xvac))
389  {
390  if (TransactionIdDidCommit(xvac))
391  {
394  return false;
395  }
398  }
399  }
400  /* Used by pre-9.0 binary upgrades */
401  else if (tuple->t_infomask & HEAP_MOVED_IN)
402  {
404 
406  {
407  if (TransactionIdIsInProgress(xvac))
408  return false;
409  if (TransactionIdDidCommit(xvac))
412  else
413  {
416  return false;
417  }
418  }
419  }
420 
421  /*
422  * An invalid Xmin can be left behind by a speculative insertion that
423  * is canceled by super-deleting the tuple. This also applies to
424  * TOAST tuples created during speculative insertion.
425  */
427  return false;
428  }
429 
430  /* otherwise assume the tuple is valid for TOAST. */
431  return true;
432 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:199
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetXmin(tup)
Definition: htup_details.h:307
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HTSU_Result HeapTupleSatisfiesUpdate ( HeapTuple  htup,
CommandId  curcid,
Buffer  buffer 
)

Definition at line 462 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().

464 {
465  HeapTupleHeader tuple = htup->t_data;
466 
468  Assert(htup->t_tableOid != InvalidOid);
469 
470  if (!HeapTupleHeaderXminCommitted(tuple))
471  {
472  if (HeapTupleHeaderXminInvalid(tuple))
473  return HeapTupleInvisible;
474 
475  /* Used by pre-9.0 binary upgrades */
476  if (tuple->t_infomask & HEAP_MOVED_OFF)
477  {
479 
481  return HeapTupleInvisible;
482  if (!TransactionIdIsInProgress(xvac))
483  {
484  if (TransactionIdDidCommit(xvac))
485  {
488  return HeapTupleInvisible;
489  }
492  }
493  }
494  /* Used by pre-9.0 binary upgrades */
495  else if (tuple->t_infomask & HEAP_MOVED_IN)
496  {
498 
500  {
501  if (TransactionIdIsInProgress(xvac))
502  return HeapTupleInvisible;
503  if (TransactionIdDidCommit(xvac))
506  else
507  {
510  return HeapTupleInvisible;
511  }
512  }
513  }
515  {
516  if (HeapTupleHeaderGetCmin(tuple) >= curcid)
517  return HeapTupleInvisible; /* inserted after scan started */
518 
519  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
520  return HeapTupleMayBeUpdated;
521 
523  {
524  TransactionId xmax;
525 
526  xmax = HeapTupleHeaderGetRawXmax(tuple);
527 
528  /*
529  * Careful here: even though this tuple was created by our own
530  * transaction, it might be locked by other transactions, if
531  * the original version was key-share locked when we updated
532  * it.
533  */
534 
535  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
536  {
537  if (MultiXactIdIsRunning(xmax, true))
538  return HeapTupleBeingUpdated;
539  else
540  return HeapTupleMayBeUpdated;
541  }
542 
543  /*
544  * If the locker is gone, then there is nothing of interest
545  * left in this Xmax; otherwise, report the tuple as
546  * locked/updated.
547  */
548  if (!TransactionIdIsInProgress(xmax))
549  return HeapTupleMayBeUpdated;
550  return HeapTupleBeingUpdated;
551  }
552 
553  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
554  {
555  TransactionId xmax;
556 
557  xmax = HeapTupleGetUpdateXid(tuple);
558 
559  /* not LOCKED_ONLY, so it has to have an xmax */
561 
562  /* deleting subtransaction must have aborted */
564  {
566  false))
567  return HeapTupleBeingUpdated;
568  return HeapTupleMayBeUpdated;
569  }
570  else
571  {
572  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
573  return HeapTupleSelfUpdated; /* updated after scan
574  * started */
575  else
576  return HeapTupleInvisible; /* updated before scan
577  * started */
578  }
579  }
580 
582  {
583  /* deleting subtransaction must have aborted */
586  return HeapTupleMayBeUpdated;
587  }
588 
589  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
590  return HeapTupleSelfUpdated; /* updated after scan started */
591  else
592  return HeapTupleInvisible; /* updated before scan started */
593  }
595  return HeapTupleInvisible;
599  else
600  {
601  /* it must have aborted or crashed */
604  return HeapTupleInvisible;
605  }
606  }
607 
608  /* by here, the inserting transaction has committed */
609 
610  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
611  return HeapTupleMayBeUpdated;
612 
613  if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
614  {
616  return HeapTupleMayBeUpdated;
617  return HeapTupleUpdated; /* updated by other */
618  }
619 
620  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
621  {
622  TransactionId xmax;
623 
624  if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
625  return HeapTupleMayBeUpdated;
626 
628  {
630  return HeapTupleBeingUpdated;
631 
633  return HeapTupleMayBeUpdated;
634  }
635 
636  xmax = HeapTupleGetUpdateXid(tuple);
637  if (!TransactionIdIsValid(xmax))
638  {
640  return HeapTupleBeingUpdated;
641  }
642 
643  /* not LOCKED_ONLY, so it has to have an xmax */
645 
647  {
648  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
649  return HeapTupleSelfUpdated; /* updated after scan started */
650  else
651  return HeapTupleInvisible; /* updated before scan started */
652  }
653 
655  return HeapTupleBeingUpdated;
656 
657  if (TransactionIdDidCommit(xmax))
658  return HeapTupleUpdated;
659 
660  /*
661  * By here, the update in the Xmax is either aborted or crashed, but
662  * what about the other members?
663  */
664 
666  {
667  /*
668  * There's no member, even just a locker, alive anymore, so we can
669  * mark the Xmax as invalid.
670  */
673  return HeapTupleMayBeUpdated;
674  }
675  else
676  {
677  /* There are lockers running */
678  return HeapTupleBeingUpdated;
679  }
680  }
681 
683  {
685  return HeapTupleBeingUpdated;
686  if (HeapTupleHeaderGetCmax(tuple) >= curcid)
687  return HeapTupleSelfUpdated; /* updated after scan started */
688  else
689  return HeapTupleInvisible; /* updated before scan started */
690  }
691 
693  return HeapTupleBeingUpdated;
694 
696  {
697  /* it must have aborted or crashed */
700  return HeapTupleMayBeUpdated;
701  }
702 
703  /* xmax transaction committed */
704 
706  {
709  return HeapTupleMayBeUpdated;
710  }
711 
714  return HeapTupleUpdated; /* updated by other */
715 }
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6981
CommandId HeapTupleHeaderGetCmin(HeapTupleHeader tup)
Definition: combocid.c:105
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:238
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:199
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
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:302
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:549
HTSV_Result HeapTupleSatisfiesVacuum ( HeapTuple  htup,
TransactionId  OldestXmin,
Buffer  buffer 
)

Definition at line 1166 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().

1168 {
1169  HeapTupleHeader tuple = htup->t_data;
1170 
1171  Assert(ItemPointerIsValid(&htup->t_self));
1172  Assert(htup->t_tableOid != InvalidOid);
1173 
1174  /*
1175  * Has inserting transaction committed?
1176  *
1177  * If the inserting transaction aborted, then the tuple was never visible
1178  * to any other transaction, so we can delete it immediately.
1179  */
1180  if (!HeapTupleHeaderXminCommitted(tuple))
1181  {
1182  if (HeapTupleHeaderXminInvalid(tuple))
1183  return HEAPTUPLE_DEAD;
1184  /* Used by pre-9.0 binary upgrades */
1185  else if (tuple->t_infomask & HEAP_MOVED_OFF)
1186  {
1187  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1188 
1191  if (TransactionIdIsInProgress(xvac))
1193  if (TransactionIdDidCommit(xvac))
1194  {
1197  return HEAPTUPLE_DEAD;
1198  }
1201  }
1202  /* Used by pre-9.0 binary upgrades */
1203  else if (tuple->t_infomask & HEAP_MOVED_IN)
1204  {
1205  TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1206 
1209  if (TransactionIdIsInProgress(xvac))
1211  if (TransactionIdDidCommit(xvac))
1214  else
1215  {
1218  return HEAPTUPLE_DEAD;
1219  }
1220  }
1222  {
1223  if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
1225  /* only locked? run infomask-only check first, for performance */
1226  if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
1229  /* inserted and then deleted by same xact */
1232  /* deleting subtransaction must have aborted */
1234  }
1236  {
1237  /*
1238  * It'd be possible to discern between INSERT/DELETE in progress
1239  * here by looking at xmax - but that doesn't seem beneficial for
1240  * the majority of callers and even detrimental for some. We'd
1241  * rather have callers look at/wait for xmin than xmax. It's
1242  * always correct to return INSERT_IN_PROGRESS because that's
1243  * what's happening from the view of other backends.
1244  */
1246  }
1249  HeapTupleHeaderGetRawXmin(tuple));
1250  else
1251  {
1252  /*
1253  * Not in Progress, Not Committed, so either Aborted or crashed
1254  */
1257  return HEAPTUPLE_DEAD;
1258  }
1259 
1260  /*
1261  * At this point the xmin is known committed, but we might not have
1262  * been able to set the hint bit yet; so we can no longer Assert that
1263  * it's set.
1264  */
1265  }
1266 
1267  /*
1268  * Okay, the inserter committed, so it was good at some point. Now what
1269  * about the deleting transaction?
1270  */
1271  if (tuple->t_infomask & HEAP_XMAX_INVALID)
1272  return HEAPTUPLE_LIVE;
1273 
1275  {
1276  /*
1277  * "Deleting" xact really only locked it, so the tuple is live in any
1278  * case. However, we should make sure that either XMAX_COMMITTED or
1279  * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
1280  * examining the tuple for future xacts.
1281  */
1282  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1283  {
1284  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1285  {
1286  /*
1287  * If it's a pre-pg_upgrade tuple, the multixact cannot
1288  * possibly be running; otherwise have to check.
1289  */
1290  if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
1292  true))
1293  return HEAPTUPLE_LIVE;
1295  }
1296  else
1297  {
1299  return HEAPTUPLE_LIVE;
1302  }
1303  }
1304 
1305  /*
1306  * We don't really care whether xmax did commit, abort or crash. We
1307  * know that xmax did lock the tuple, but it did not and will never
1308  * actually update it.
1309  */
1310 
1311  return HEAPTUPLE_LIVE;
1312  }
1313 
1314  if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1315  {
1316  TransactionId xmax;
1317 
1319  {
1320  /* already checked above */
1322 
1323  xmax = HeapTupleGetUpdateXid(tuple);
1324 
1325  /* not LOCKED_ONLY, so it has to have an xmax */
1327 
1328  if (TransactionIdIsInProgress(xmax))
1330  else if (TransactionIdDidCommit(xmax))
1331  /* there are still lockers around -- can't return DEAD here */
1332  return HEAPTUPLE_RECENTLY_DEAD;
1333  /* updating transaction aborted */
1334  return HEAPTUPLE_LIVE;
1335  }
1336 
1337  Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));
1338 
1339  xmax = HeapTupleGetUpdateXid(tuple);
1340 
1341  /* not LOCKED_ONLY, so it has to have an xmax */
1343 
1344  /* multi is not running -- updating xact cannot be */
1346  if (TransactionIdDidCommit(xmax))
1347  {
1348  if (!TransactionIdPrecedes(xmax, OldestXmin))
1349  return HEAPTUPLE_RECENTLY_DEAD;
1350  else
1351  return HEAPTUPLE_DEAD;
1352  }
1353 
1354  /*
1355  * Not in Progress, Not Committed, so either Aborted or crashed.
1356  * Remove the Xmax.
1357  */
1359  return HEAPTUPLE_LIVE;
1360  }
1361 
1362  if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1363  {
1368  HeapTupleHeaderGetRawXmax(tuple));
1369  else
1370  {
1371  /*
1372  * Not in Progress, Not Committed, so either Aborted or crashed
1373  */
1376  return HEAPTUPLE_LIVE;
1377  }
1378 
1379  /*
1380  * At this point the xmax is known committed, but we might not have
1381  * been able to set the hint bit yet; so we can no longer Assert that
1382  * it's set.
1383  */
1384  }
1385 
1386  /*
1387  * Deleter committed, but perhaps it was recent enough that some open
1388  * transactions could still see the tuple.
1389  */
1391  return HEAPTUPLE_RECENTLY_DEAD;
1392 
1393  /* Otherwise, it's dead and removable */
1394  return HEAPTUPLE_DEAD;
1395 }
#define HeapTupleHeaderGetUpdateXid(tup)
Definition: htup_details.h:359
bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
Definition: tqual.c:1607
#define ItemPointerIsValid(pointer)
Definition: itemptr.h:60
uint32 TransactionId
Definition: c.h:391
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:774
bool TransactionIdIsInProgress(TransactionId xid)
Definition: procarray.c:999
TransactionId HeapTupleGetUpdateXid(HeapTupleHeader tuple)
Definition: heapam.c:6981
#define HEAP_LOCKED_UPGRADED(infomask)
Definition: htup_details.h:238
#define HeapTupleHeaderXminInvalid(tup)
Definition: htup_details.h:323
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:192
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
HeapTupleHeader t_data
Definition: htup.h:67
#define HEAP_XMIN_INVALID
Definition: htup_details.h:190
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:369
#define HEAP_XMAX_INVALID
Definition: htup_details.h:193
ItemPointerData t_self
Definition: htup.h:65
#define HeapTupleHeaderXminCommitted(tup)
Definition: htup_details.h:318
#define InvalidTransactionId
Definition: transam.h:31
#define HeapTupleHeaderGetXvac(tup)
Definition: htup_details.h:409
static TransactionId OldestXmin
Definition: vacuumlazy.c:138
Oid t_tableOid
Definition: htup.h:66
#define HEAP_MOVED_IN
Definition: htup_details.h:199
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define HEAP_XMAX_IS_LOCKED_ONLY(infomask)
Definition: htup_details.h:216
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:194
#define HEAP_XMIN_COMMITTED
Definition: htup_details.h:189
#define InvalidOid
Definition: postgres_ext.h:36
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
#define HEAP_MOVED_OFF
Definition: htup_details.h:196
#define Assert(condition)
Definition: c.h:664
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define HeapTupleHeaderGetRawXmin(tup)
Definition: htup_details.h:302
#define TransactionIdIsValid(xid)
Definition: transam.h:41
bool MultiXactIdIsRunning(MultiXactId multi, bool isLockOnly)
Definition: multixact.c:549
void HeapTupleSetHintBits ( HeapTupleHeader  tuple,
Buffer  buffer,
uint16  infomask,
TransactionId  xid 
)

Definition at line 146 of file tqual.c.

References SetHintBits().

Referenced by UpdateXmaxHintBits().

148 {
149  SetHintBits(tuple, buffer, infomask, xid);
150 }
static void SetHintBits(HeapTupleHeader tuple, Buffer buffer, uint16 infomask, TransactionId xid)
Definition: tqual.c:119
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
bool ResolveCminCmaxDuringDecoding ( struct HTAB tuplecid_data,
Snapshot  snapshot,
HeapTuple  htup,
Buffer  buffer,
CommandId cmin,
CommandId cmax 
)

Definition at line 3241 of file reorderbuffer.c.

References Assert, BufferGetTag(), BufferIsLocal, ReorderBufferTupleCidEnt::cmax, ReorderBufferTupleCidEnt::cmin, HASH_FIND, hash_search(), ItemPointerCopy, ItemPointerGetBlockNumber, MAIN_FORKNUM, ReorderBufferTupleCidKey::relnode, HeapTupleData::t_self, HeapTupleData::t_tableOid, ReorderBufferTupleCidKey::tid, and UpdateLogicalMappings().

Referenced by HeapTupleSatisfiesHistoricMVCC().

3245 {
3248  ForkNumber forkno;
3249  BlockNumber blockno;
3250  bool updated_mapping = false;
3251 
3252  /* be careful about padding */
3253  memset(&key, 0, sizeof(key));
3254 
3256 
3257  /*
3258  * get relfilenode from the buffer, no convenient way to access it other
3259  * than that.
3260  */
3261  BufferGetTag(buffer, &key.relnode, &forkno, &blockno);
3262 
3263  /* tuples can only be in the main fork */
3264  Assert(forkno == MAIN_FORKNUM);
3265  Assert(blockno == ItemPointerGetBlockNumber(&htup->t_self));
3266 
3267  ItemPointerCopy(&htup->t_self,
3268  &key.tid);
3269 
3270 restart:
3271  ent = (ReorderBufferTupleCidEnt *)
3272  hash_search(tuplecid_data,
3273  (void *) &key,
3274  HASH_FIND,
3275  NULL);
3276 
3277  /*
3278  * failed to find a mapping, check whether the table was rewritten and
3279  * apply mapping if so, but only do that once - there can be no new
3280  * mappings while we are in here since we have to hold a lock on the
3281  * relation.
3282  */
3283  if (ent == NULL && !updated_mapping)
3284  {
3285  UpdateLogicalMappings(tuplecid_data, htup->t_tableOid, snapshot);
3286  /* now check but don't update for a mapping again */
3287  updated_mapping = true;
3288  goto restart;
3289  }
3290  else if (ent == NULL)
3291  return false;
3292 
3293  if (cmin)
3294  *cmin = ent->cmin;
3295  if (cmax)
3296  *cmax = ent->cmax;
3297  return true;
3298 }
uint32 BlockNumber
Definition: block.h:31
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
ItemPointerData t_self
Definition: htup.h:65
Oid t_tableOid
Definition: htup.h:66
ForkNumber
Definition: relpath.h:24
#define Assert(condition)
Definition: c.h:664
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define BufferIsLocal(buffer)
Definition: buf.h:37
static void UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
#define ItemPointerGetBlockNumber(pointer)
Definition: itemptr.h:76
void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:2626
#define ItemPointerCopy(fromPointer, toPointer)
Definition: itemptr.h:139

Variable Documentation

PGDLLIMPORT SnapshotData CatalogSnapshotData

Definition at line 146 of file snapmgr.c.

PGDLLIMPORT SnapshotData SnapshotAnyData

Definition at line 82 of file tqual.c.

PGDLLIMPORT SnapshotData SnapshotSelfData

Definition at line 81 of file tqual.c.