/*-------------------------------------------------------------------------
*
* tqual.h
- * POSTGRES "time" qualification definitions.
+ * POSTGRES "time qualification" definitions, ie, tuple visibility rules.
*
* Should be moved/renamed... - vadim 07/28/98
*
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tqual.h,v 1.30 2001/01/24 19:43:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/tqual.h,v 1.69 2007/11/15 21:14:45 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#define TQUAL_H
#include "access/htup.h"
-#include "access/xact.h"
+#include "storage/buf.h"
+/*
+ * We use SnapshotData structures to represent both "regular" (MVCC)
+ * snapshots and "special" snapshots that have non-MVCC semantics.
+ * The specific semantics of a snapshot are encoded by the "satisfies"
+ * function.
+ */
+typedef struct SnapshotData *Snapshot;
+
+typedef bool (*SnapshotSatisfiesFunc) (HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+
typedef struct SnapshotData
{
- TransactionId xmin; /* XID < xmin are visible to me */
- TransactionId xmax; /* XID >= xmax are invisible to me */
- uint32 xcnt; /* # of xact below */
- TransactionId *xip; /* array of xacts in progress */
- ItemPointerData tid; /* required for Dirty snapshot -:( */
+ SnapshotSatisfiesFunc satisfies; /* tuple test function */
+
+ /*
+ * The remaining fields are used only for MVCC snapshots, and are normally
+ * just zeroes in special snapshots. (But xmin and xmax are used
+ * specially by HeapTupleSatisfiesDirty.)
+ *
+ * An MVCC snapshot can never see the effects of XIDs >= xmax. It can see
+ * the effects of all older XIDs except those listed in the snapshot.
+ * xmin is stored as an optimization to avoid needing to search the XID
+ * arrays for most tuples.
+ */
+ TransactionId xmin; /* all XID < xmin are visible to me */
+ TransactionId xmax; /* all XID >= xmax are invisible to me */
+ uint32 xcnt; /* # of xact ids in xip[] */
+ TransactionId *xip; /* array of xact IDs in progress */
+ /* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */
+ int32 subxcnt; /* # of xact ids in subxip[], -1 if overflow */
+ TransactionId *subxip; /* array of subxact IDs in progress */
+
+ /*
+ * note: all ids in subxip[] are >= xmin, but we don't bother filtering
+ * out any that are >= xmax
+ */
+ CommandId curcid; /* in my xact, CID < curcid are visible */
} SnapshotData;
-typedef SnapshotData *Snapshot;
+#define InvalidSnapshot ((Snapshot) NULL)
+
+/* Static variables representing various special snapshot semantics */
+extern PGDLLIMPORT SnapshotData SnapshotNowData;
+extern PGDLLIMPORT SnapshotData SnapshotSelfData;
+extern PGDLLIMPORT SnapshotData SnapshotAnyData;
+extern PGDLLIMPORT SnapshotData SnapshotToastData;
+
+#define SnapshotNow (&SnapshotNowData)
+#define SnapshotSelf (&SnapshotSelfData)
+#define SnapshotAny (&SnapshotAnyData)
+#define SnapshotToast (&SnapshotToastData)
-#define SnapshotNow ((Snapshot) 0x0)
-#define SnapshotSelf ((Snapshot) 0x1)
-#define SnapshotAny ((Snapshot) 0x2)
+/*
+ * We don't provide a static SnapshotDirty variable because it would be
+ * non-reentrant. Instead, users of that snapshot type should declare a
+ * local variable of type SnapshotData, and initialize it with this macro.
+ */
+#define InitDirtySnapshot(snapshotdata) \
+ ((snapshotdata).satisfies = HeapTupleSatisfiesDirty)
-extern Snapshot SnapshotDirty;
-extern Snapshot QuerySnapshot;
-extern Snapshot SerializableSnapshot;
+/* This macro encodes the knowledge of which snapshots are MVCC-safe */
+#define IsMVCCSnapshot(snapshot) \
+ ((snapshot)->satisfies == HeapTupleSatisfiesMVCC)
-extern bool ReferentialIntegritySnapshotOverride;
-#define IsSnapshotNow(snapshot) ((Snapshot) (snapshot) == SnapshotNow)
-#define IsSnapshotSelf(snapshot) ((Snapshot) (snapshot) == SnapshotSelf)
-#define IsSnapshotAny(snapshot) ((Snapshot) (snapshot) == SnapshotAny)
-#define IsSnapshotDirty(snapshot) ((Snapshot) (snapshot) == SnapshotDirty)
+extern PGDLLIMPORT Snapshot SerializableSnapshot;
+extern PGDLLIMPORT Snapshot LatestSnapshot;
+extern PGDLLIMPORT Snapshot ActiveSnapshot;
+extern TransactionId TransactionXmin;
+extern TransactionId RecentXmin;
+extern TransactionId RecentGlobalXmin;
/*
* HeapTupleSatisfiesVisibility
- * True iff heap tuple satsifies a time qual.
+ * True iff heap tuple satisfies a time qual.
*
* Notes:
- * Assumes heap tuple is valid.
- * Beware of multiple evaluations of arguments.
+ * Assumes heap tuple is valid.
+ * Beware of multiple evaluations of snapshot argument.
+ * Hint bits in the HeapTuple's t_infomask may be updated as a side effect;
+ * if so, the indicated buffer is marked dirty.
*/
-#define HeapTupleSatisfiesVisibility(tuple, snapshot) \
-( \
- TransactionIdEquals((tuple)->t_data->t_xmax, AmiTransactionId) ? \
- false \
- : \
- ( \
- IsSnapshotAny(snapshot) ? \
- true \
- : \
- (IsSnapshotSelf(snapshot) ? \
- HeapTupleSatisfiesItself((tuple)->t_data) \
- : \
- (IsSnapshotDirty(snapshot) ? \
- HeapTupleSatisfiesDirty((tuple)->t_data) \
- : \
- (IsSnapshotNow(snapshot) ? \
- HeapTupleSatisfiesNow((tuple)->t_data) \
- : \
- HeapTupleSatisfiesSnapshot((tuple)->t_data, snapshot) \
- ) \
- ) \
- ) \
- ) \
-)
-
-#define HeapTupleMayBeUpdated 0
-#define HeapTupleInvisible 1
-#define HeapTupleSelfUpdated 2
-#define HeapTupleUpdated 3
-#define HeapTupleBeingUpdated 4
-
-extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple,
- Snapshot snapshot);
-extern int HeapTupleSatisfiesUpdate(HeapTuple tuple);
-
-extern Snapshot GetSnapshotData(bool serializable);
-extern void SetQuerySnapshot(void);
+#define HeapTupleSatisfiesVisibility(tuple, snapshot, buffer) \
+ ((*(snapshot)->satisfies) ((tuple)->t_data, snapshot, buffer))
+
+/* Result codes for HeapTupleSatisfiesUpdate */
+typedef enum
+{
+ HeapTupleMayBeUpdated,
+ HeapTupleInvisible,
+ HeapTupleSelfUpdated,
+ HeapTupleUpdated,
+ HeapTupleBeingUpdated
+} HTSU_Result;
+
+/* Result codes for HeapTupleSatisfiesVacuum */
+typedef enum
+{
+ HEAPTUPLE_DEAD, /* tuple is dead and deletable */
+ HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
+ HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
+ HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
+ HEAPTUPLE_DELETE_IN_PROGRESS /* deleting xact is still in progress */
+} HTSV_Result;
+
+/* These are the "satisfies" test routines for the various snapshot types */
+extern bool HeapTupleSatisfiesMVCC(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+extern bool HeapTupleSatisfiesSelf(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+extern bool HeapTupleSatisfiesAny(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+extern bool HeapTupleSatisfiesToast(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+extern bool HeapTupleSatisfiesDirty(HeapTupleHeader tuple,
+ Snapshot snapshot, Buffer buffer);
+
+/* Special "satisfies" routines with different APIs */
+extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTupleHeader tuple,
+ CommandId curcid, Buffer buffer);
+extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
+ TransactionId OldestXmin, Buffer buffer);
+
+extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
+ uint16 infomask, TransactionId xid);
+
+extern Snapshot GetTransactionSnapshot(void);
+extern Snapshot GetLatestSnapshot(void);
+extern Snapshot CopySnapshot(Snapshot snapshot);
+extern void FreeSnapshot(Snapshot snapshot);
extern void FreeXactSnapshot(void);
-#endif /* TQUAL_H */
+/* in procarray.c; declared here to avoid including tqual.h in procarray.h: */
+extern Snapshot GetSnapshotData(Snapshot snapshot, bool serializable);
+
+#endif /* TQUAL_H */