#include "storage/lmgr.h"
#include "utils/memutils.h"
#include "utils/snapmgr.h"
-#include "utils/tqual.h"
PG_MODULE_MAGIC;
#include "commands/seclabel.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
#include "sepgsql.h"
/*
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/snapmgr.h"
#include "utils/syscache.h"
-#include "utils/tqual.h"
#include "sepgsql.h"
#include "utils/catcache.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
+#include "utils/snapmgr.h"
#include "utils/syscache.h"
-#include "utils/tqual.h"
#include "sepgsql.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
#include "sepgsql.h"
#include "utils/rel.h"
#include "utils/sortsupport.h"
#include "utils/tuplesort.h"
-#include "utils/tqual.h"
/* Magic numbers for parallel state sharing */
#include "utils/fmgroids.h"
#include "utils/fmgrprotos.h"
#include "utils/rel.h"
+#include "utils/snapmgr.h"
#include "utils/syscache.h"
-#include "utils/tqual.h"
/*
#include "utils/ps_status.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
-#include "utils/tqual.h"
/*
#include "executor/executor.h"
#include "utils/builtins.h"
#include "utils/rel.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
/*
#include "executor/executor.h"
#include "nodes/nodeFuncs.h"
#include "storage/lmgr.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
/* waitMode argument to check_exclusion_or_unique_constraint() */
typedef enum
#include "utils/pg_lsn.h"
#include "utils/rel.h"
#include "utils/syscache.h"
-#include "utils/tqual.h"
+#include "utils/snapmgr.h"
/*
* Replay progress of a single remote node.
#include "utils/memutils.h"
#include "utils/snapshot.h"
#include "utils/snapmgr.h"
-#include "utils/tqual.h"
#include "storage/block.h" /* debugging output */
#include "storage/fd.h"
#include "utils/spccache.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
-#include "utils/tqual.h"
#include "utils/typcache.h"
#include "utils/varlena.h"
#include <sys/stat.h>
#include <unistd.h>
+#include "access/subtrans.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
-#include "utils/tqual.h"
/*
static SnapshotData CurrentSnapshotData = {SNAPSHOT_MVCC};
static SnapshotData SecondarySnapshotData = {SNAPSHOT_MVCC};
SnapshotData CatalogSnapshotData = {SNAPSHOT_MVCC};
+SnapshotData SnapshotSelfData = {SNAPSHOT_SELF};
+SnapshotData SnapshotAnyData = {SNAPSHOT_ANY};
/* Pointers to valid snapshots */
static Snapshot CurrentSnapshot = NULL;
{
SetTransactionSnapshot(snapshot, NULL, InvalidPid, master_pgproc);
}
+
+/*
+ * XidInMVCCSnapshot
+ * Is the given XID still-in-progress according to the snapshot?
+ *
+ * Note: GetSnapshotData never stores either top xid or subxids of our own
+ * backend into a snapshot, so these xids will not be reported as "running"
+ * by this function. This is OK for current uses, because we always check
+ * TransactionIdIsCurrentTransactionId first, except when it's known the
+ * XID could not be ours anyway.
+ */
+bool
+XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
+{
+ uint32 i;
+
+ /*
+ * Make a quick range check to eliminate most XIDs without looking at the
+ * xip arrays. Note that this is OK even if we convert a subxact XID to
+ * its parent below, because a subxact with XID < xmin has surely also got
+ * a parent with XID < xmin, while one with XID >= xmax must belong to a
+ * parent that was not yet committed at the time of this snapshot.
+ */
+
+ /* Any xid < xmin is not in-progress */
+ if (TransactionIdPrecedes(xid, snapshot->xmin))
+ return false;
+ /* Any xid >= xmax is in-progress */
+ if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
+ return true;
+
+ /*
+ * Snapshot information is stored slightly differently in snapshots taken
+ * during recovery.
+ */
+ if (!snapshot->takenDuringRecovery)
+ {
+ /*
+ * If the snapshot contains full subxact data, the fastest way to
+ * check things is just to compare the given XID against both subxact
+ * XIDs and top-level XIDs. If the snapshot overflowed, we have to
+ * use pg_subtrans to convert a subxact XID to its parent XID, but
+ * then we need only look at top-level XIDs not subxacts.
+ */
+ if (!snapshot->suboverflowed)
+ {
+ /* we have full data, so search subxip */
+ int32 j;
+
+ for (j = 0; j < snapshot->subxcnt; j++)
+ {
+ if (TransactionIdEquals(xid, snapshot->subxip[j]))
+ return true;
+ }
+
+ /* not there, fall through to search xip[] */
+ }
+ else
+ {
+ /*
+ * Snapshot overflowed, so convert xid to top-level. This is safe
+ * because we eliminated too-old XIDs above.
+ */
+ xid = SubTransGetTopmostTransaction(xid);
+
+ /*
+ * If xid was indeed a subxact, we might now have an xid < xmin,
+ * so recheck to avoid an array scan. No point in rechecking
+ * xmax.
+ */
+ if (TransactionIdPrecedes(xid, snapshot->xmin))
+ return false;
+ }
+
+ for (i = 0; i < snapshot->xcnt; i++)
+ {
+ if (TransactionIdEquals(xid, snapshot->xip[i]))
+ return true;
+ }
+ }
+ else
+ {
+ int32 j;
+
+ /*
+ * In recovery we store all xids in the subxact array because it is by
+ * far the bigger array, and we mostly don't know which xids are
+ * top-level and which are subxacts. The xip array is empty.
+ *
+ * We start by searching subtrans, if we overflowed.
+ */
+ if (snapshot->suboverflowed)
+ {
+ /*
+ * Snapshot overflowed, so convert xid to top-level. This is safe
+ * because we eliminated too-old XIDs above.
+ */
+ xid = SubTransGetTopmostTransaction(xid);
+
+ /*
+ * If xid was indeed a subxact, we might now have an xid < xmin,
+ * so recheck to avoid an array scan. No point in rechecking
+ * xmax.
+ */
+ if (TransactionIdPrecedes(xid, snapshot->xmin))
+ return false;
+ }
+
+ /*
+ * We now have either a top-level xid higher than xmin or an
+ * indeterminate xid. We don't know whether it's top level or subxact
+ * but it doesn't matter. If it's present, the xid is visible.
+ */
+ for (j = 0; j < snapshot->subxcnt; j++)
+ {
+ if (TransactionIdEquals(xid, snapshot->subxip[j]))
+ return true;
+ }
+ }
+
+ return false;
+}
#include "utils/tqual.h"
-/* Static variables representing various special snapshot semantics */
-SnapshotData SnapshotSelfData = {SNAPSHOT_SELF};
-SnapshotData SnapshotAnyData = {SNAPSHOT_ANY};
-
-
/*
* SetHintBits()
*
return TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin);
}
-/*
- * XidInMVCCSnapshot
- * Is the given XID still-in-progress according to the snapshot?
- *
- * Note: GetSnapshotData never stores either top xid or subxids of our own
- * backend into a snapshot, so these xids will not be reported as "running"
- * by this function. This is OK for current uses, because we always check
- * TransactionIdIsCurrentTransactionId first, except when it's known the
- * XID could not be ours anyway.
- */
-bool
-XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
-{
- uint32 i;
-
- /*
- * Make a quick range check to eliminate most XIDs without looking at the
- * xip arrays. Note that this is OK even if we convert a subxact XID to
- * its parent below, because a subxact with XID < xmin has surely also got
- * a parent with XID < xmin, while one with XID >= xmax must belong to a
- * parent that was not yet committed at the time of this snapshot.
- */
-
- /* Any xid < xmin is not in-progress */
- if (TransactionIdPrecedes(xid, snapshot->xmin))
- return false;
- /* Any xid >= xmax is in-progress */
- if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
- return true;
-
- /*
- * Snapshot information is stored slightly differently in snapshots taken
- * during recovery.
- */
- if (!snapshot->takenDuringRecovery)
- {
- /*
- * If the snapshot contains full subxact data, the fastest way to
- * check things is just to compare the given XID against both subxact
- * XIDs and top-level XIDs. If the snapshot overflowed, we have to
- * use pg_subtrans to convert a subxact XID to its parent XID, but
- * then we need only look at top-level XIDs not subxacts.
- */
- if (!snapshot->suboverflowed)
- {
- /* we have full data, so search subxip */
- int32 j;
-
- for (j = 0; j < snapshot->subxcnt; j++)
- {
- if (TransactionIdEquals(xid, snapshot->subxip[j]))
- return true;
- }
-
- /* not there, fall through to search xip[] */
- }
- else
- {
- /*
- * Snapshot overflowed, so convert xid to top-level. This is safe
- * because we eliminated too-old XIDs above.
- */
- xid = SubTransGetTopmostTransaction(xid);
-
- /*
- * If xid was indeed a subxact, we might now have an xid < xmin,
- * so recheck to avoid an array scan. No point in rechecking
- * xmax.
- */
- if (TransactionIdPrecedes(xid, snapshot->xmin))
- return false;
- }
-
- for (i = 0; i < snapshot->xcnt; i++)
- {
- if (TransactionIdEquals(xid, snapshot->xip[i]))
- return true;
- }
- }
- else
- {
- int32 j;
-
- /*
- * In recovery we store all xids in the subxact array because it is by
- * far the bigger array, and we mostly don't know which xids are
- * top-level and which are subxacts. The xip array is empty.
- *
- * We start by searching subtrans, if we overflowed.
- */
- if (snapshot->suboverflowed)
- {
- /*
- * Snapshot overflowed, so convert xid to top-level. This is safe
- * because we eliminated too-old XIDs above.
- */
- xid = SubTransGetTopmostTransaction(xid);
-
- /*
- * If xid was indeed a subxact, we might now have an xid < xmin,
- * so recheck to avoid an array scan. No point in rechecking
- * xmax.
- */
- if (TransactionIdPrecedes(xid, snapshot->xmin))
- return false;
- }
-
- /*
- * We now have either a top-level xid higher than xmin or an
- * indeterminate xid. We don't know whether it's top level or subxact
- * but it doesn't matter. If it's present, the xid is visible.
- */
- for (j = 0; j < snapshot->subxcnt; j++)
- {
- if (TransactionIdEquals(xid, snapshot->subxip[j]))
- return true;
- }
- }
-
- return false;
-}
-
/*
* Is the tuple really only locked? That is, is it not updated?
*
extern PGDLLIMPORT TransactionId RecentGlobalXmin;
extern PGDLLIMPORT TransactionId RecentGlobalDataXmin;
+/* Variables representing various special snapshot semantics */
+extern PGDLLIMPORT SnapshotData SnapshotSelfData;
+extern PGDLLIMPORT SnapshotData SnapshotAnyData;
+extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
+
+#define SnapshotSelf (&SnapshotSelfData)
+#define SnapshotAny (&SnapshotAnyData)
+
+/*
+ * 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).snapshot_type = SNAPSHOT_DIRTY)
+
+/*
+ * Similarly, some initialization is required for a NonVacuumable snapshot.
+ * The caller must supply the xmin horizon to use (e.g., RecentGlobalXmin).
+ */
+#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
+ (snapshotdata).xmin = (xmin_horizon))
+
+/*
+ * Similarly, some initialization is required for SnapshotToast. We need
+ * to set lsn and whenTaken correctly to support snapshot_too_old.
+ */
+#define InitToastSnapshot(snapshotdata, l, w) \
+ ((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
+ (snapshotdata).lsn = (l), \
+ (snapshotdata).whenTaken = (w))
+
+/* This macro encodes the knowledge of which snapshots are MVCC-safe */
+#define IsMVCCSnapshot(snapshot) \
+ ((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
+ (snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
+
+
extern Snapshot GetTransactionSnapshot(void);
extern Snapshot GetLatestSnapshot(void);
extern void SnapshotSetCommandId(CommandId curcid);
extern char *ExportSnapshot(Snapshot snapshot);
+/*
+ * Utility functions for implementing visibility routines in table AMs.
+ */
+extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
+
/* Support for catalog timetravel for logical decoding */
struct HTAB;
extern struct HTAB *HistoricSnapshotGetTupleCids(void);
#include "utils/snapshot.h"
-
-/* Static variables representing various special snapshot semantics */
-extern PGDLLIMPORT SnapshotData SnapshotSelfData;
-extern PGDLLIMPORT SnapshotData SnapshotAnyData;
-extern PGDLLIMPORT SnapshotData CatalogSnapshotData;
-
-#define SnapshotSelf (&SnapshotSelfData)
-#define SnapshotAny (&SnapshotAnyData)
-
-/* This macro encodes the knowledge of which snapshots are MVCC-safe */
-#define IsMVCCSnapshot(snapshot) \
- ((snapshot)->snapshot_type == SNAPSHOT_MVCC || \
- (snapshot)->snapshot_type == SNAPSHOT_HISTORIC_MVCC)
-
extern bool HeapTupleSatisfiesVisibility(HeapTuple stup, Snapshot snapshot,
Buffer buffer);
TransactionId OldestXmin, Buffer buffer);
extern bool HeapTupleIsSurelyDead(HeapTuple htup,
TransactionId OldestXmin);
-extern bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
uint16 infomask, TransactionId xid);
Buffer buffer,
CommandId *cmin, CommandId *cmax);
-/*
- * 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).snapshot_type = SNAPSHOT_DIRTY)
-
-/*
- * Similarly, some initialization is required for a NonVacuumable snapshot.
- * The caller must supply the xmin horizon to use (e.g., RecentGlobalXmin).
- */
-#define InitNonVacuumableSnapshot(snapshotdata, xmin_horizon) \
- ((snapshotdata).snapshot_type = SNAPSHOT_NON_VACUUMABLE, \
- (snapshotdata).xmin = (xmin_horizon))
-
-/*
- * Similarly, some initialization is required for SnapshotToast. We need
- * to set lsn and whenTaken correctly to support snapshot_too_old.
- */
-#define InitToastSnapshot(snapshotdata, l, w) \
- ((snapshotdata).snapshot_type = SNAPSHOT_TOAST, \
- (snapshotdata).lsn = (l), \
- (snapshotdata).whenTaken = (w))
-
#endif /* TQUAL_H */