diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 56943f2..a0647cf 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -5074,7 +5074,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, HeapTuple tup; Datum values[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS]; - SnapshotData SnapshotDirty; + SnapshotData SnapshotNonVacuumable; estate = CreateExecutorState(); econtext = GetPerTupleExprContext(estate); @@ -5097,7 +5097,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel)); econtext->ecxt_scantuple = slot; get_typlenbyval(vardata->atttype, &typLen, &typByVal); - InitDirtySnapshot(SnapshotDirty); + InitNonVacuumableSnapshot(SnapshotNonVacuumable); /* set up an IS NOT NULL scan key so that we ignore nulls */ ScanKeyEntryInitialize(&scankeys[0], @@ -5129,7 +5129,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, * extreme value has been deleted; that case motivates not * using SnapshotAny here. */ - index_scan = index_beginscan(heapRel, indexRel, &SnapshotDirty, + index_scan = index_beginscan(heapRel, indexRel, &SnapshotNonVacuumable, 1, 0); index_rescan(index_scan, scankeys, 1, NULL, 0); @@ -5161,7 +5161,7 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata, /* If max is requested, and we didn't find the index is empty */ if (max && have_data) { - index_scan = index_beginscan(heapRel, indexRel, &SnapshotDirty, + index_scan = index_beginscan(heapRel, indexRel, &SnapshotNonVacuumable, 1, 0); index_rescan(index_scan, scankeys, 1, NULL, 0); diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c index c1df062..bbab8a2 100644 --- a/src/backend/utils/time/tqual.c +++ b/src/backend/utils/time/tqual.c @@ -1392,6 +1392,15 @@ HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin, return HEAPTUPLE_DEAD; } +bool +HeapTupleSatisfiesNonVacuumable(HeapTuple htup, Snapshot snapshot, + Buffer buffer) +{ + return HeapTupleSatisfiesVacuum(htup, snapshot->xmin, buffer) + != HEAPTUPLE_DEAD; +} + + /* * HeapTupleIsSurelyDead * diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h index fafe1bd..88fcf95 100644 --- a/src/include/utils/tqual.h +++ b/src/include/utils/tqual.h @@ -16,6 +16,7 @@ #define TQUAL_H #include "utils/snapshot.h" +#include "utils/snapmgr.h" #include "access/xlogdefs.h" @@ -68,6 +69,8 @@ extern bool HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot, Buffer buffer); extern bool HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot, Buffer buffer); +extern bool HeapTupleSatisfiesNonVacuumable(HeapTuple htup, + Snapshot snapshot, Buffer buffer); /* Special "satisfies" routines with different APIs */ extern HTSU_Result HeapTupleSatisfiesUpdate(HeapTuple htup, @@ -100,6 +103,12 @@ extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data, #define InitDirtySnapshot(snapshotdata) \ ((snapshotdata).satisfies = HeapTupleSatisfiesDirty) +#define InitNonVacuumableSnapshot(snapshotdata) \ + do { \ + (snapshotdata).satisfies = HeapTupleSatisfiesNonVacuumable; \ + (snapshotdata).xmin = RecentGlobalDataXmin; \ + } while(0) + /* * Similarly, some initialization is required for SnapshotToast. We need * to set lsn and whenTaken correctly to support snapshot_too_old.