Commit 3d0a4636 authored by Andres Freund's avatar Andres Freund

Deduplicate choice of horizon for a relation procarray.c.

5a1e1d83 was a minimal bug fix for dc7420c2. To avoid future bugs of
that kind, deduplicate the choice of a relation's horizon into a new helper,
GlobalVisHorizonKindForRel().

As the code in question was only introduced in dc7420c2 it seems worth
backpatching this change as well, otherwise 14 will look different from all
other branches.

A different approach to this was suggested by Matthias van de Meent.

Author: Andres Freund
Discussion: https://postgr.es/m/20210621122919.2qhu3pfugxxp3cji@alap3.anarazel.de
Backpatch: 14, like 5a1e1d83
parent 712ba6b8
...@@ -246,6 +246,17 @@ typedef struct ComputeXidHorizonsResult ...@@ -246,6 +246,17 @@ typedef struct ComputeXidHorizonsResult
} ComputeXidHorizonsResult; } ComputeXidHorizonsResult;
/*
* Return value for GlobalVisHorizonKindForRel().
*/
typedef enum GlobalVisHorizonKind
{
VISHORIZON_SHARED,
VISHORIZON_CATALOG,
VISHORIZON_DATA,
VISHORIZON_TEMP
} GlobalVisHorizonKind;
static ProcArrayStruct *procArray; static ProcArrayStruct *procArray;
...@@ -1952,6 +1963,33 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h) ...@@ -1952,6 +1963,33 @@ ComputeXidHorizons(ComputeXidHorizonsResult *h)
GlobalVisUpdateApply(h); GlobalVisUpdateApply(h);
} }
/*
* Determine what kind of visibility horizon needs to be used for a
* relation. If rel is NULL, the most conservative horizon is used.
*/
static inline GlobalVisHorizonKind
GlobalVisHorizonKindForRel(Relation rel)
{
/*
* Other relkkinds currently don't contain xids, nor always the necessary
* logical decoding markers.
*/
Assert(!rel ||
rel->rd_rel->relkind == RELKIND_RELATION ||
rel->rd_rel->relkind == RELKIND_MATVIEW ||
rel->rd_rel->relkind == RELKIND_TOASTVALUE);
if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress())
return VISHORIZON_SHARED;
else if (IsCatalogRelation(rel) ||
RelationIsAccessibleInLogicalDecoding(rel))
return VISHORIZON_CATALOG;
else if (!RELATION_IS_LOCAL(rel))
return VISHORIZON_DATA;
else
return VISHORIZON_TEMP;
}
/* /*
* Return the oldest XID for which deleted tuples must be preserved in the * Return the oldest XID for which deleted tuples must be preserved in the
* passed table. * passed table.
...@@ -1970,16 +2008,19 @@ GetOldestNonRemovableTransactionId(Relation rel) ...@@ -1970,16 +2008,19 @@ GetOldestNonRemovableTransactionId(Relation rel)
ComputeXidHorizons(&horizons); ComputeXidHorizons(&horizons);
/* select horizon appropriate for relation */ switch (GlobalVisHorizonKindForRel(rel))
if (rel == NULL || rel->rd_rel->relisshared || RecoveryInProgress()) {
case VISHORIZON_SHARED:
return horizons.shared_oldest_nonremovable; return horizons.shared_oldest_nonremovable;
else if (IsCatalogRelation(rel) || case VISHORIZON_CATALOG:
RelationIsAccessibleInLogicalDecoding(rel))
return horizons.catalog_oldest_nonremovable; return horizons.catalog_oldest_nonremovable;
else if (RELATION_IS_LOCAL(rel)) case VISHORIZON_DATA:
return horizons.temp_oldest_nonremovable;
else
return horizons.data_oldest_nonremovable; return horizons.data_oldest_nonremovable;
case VISHORIZON_TEMP:
return horizons.temp_oldest_nonremovable;
}
return InvalidTransactionId;
} }
/* /*
...@@ -3986,37 +4027,26 @@ DisplayXidCache(void) ...@@ -3986,37 +4027,26 @@ DisplayXidCache(void)
GlobalVisState * GlobalVisState *
GlobalVisTestFor(Relation rel) GlobalVisTestFor(Relation rel)
{ {
bool need_shared;
bool need_catalog;
GlobalVisState *state; GlobalVisState *state;
/* XXX: we should assert that a snapshot is pushed or registered */ /* XXX: we should assert that a snapshot is pushed or registered */
Assert(RecentXmin); Assert(RecentXmin);
if (!rel) switch (GlobalVisHorizonKindForRel(rel))
need_shared = need_catalog = true;
else
{ {
/* case VISHORIZON_SHARED:
* Other kinds currently don't contain xids, nor always the necessary
* logical decoding markers.
*/
Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
rel->rd_rel->relkind == RELKIND_MATVIEW ||
rel->rd_rel->relkind == RELKIND_TOASTVALUE);
need_shared = rel->rd_rel->relisshared || RecoveryInProgress();
need_catalog = IsCatalogRelation(rel) || RelationIsAccessibleInLogicalDecoding(rel);
}
if (need_shared)
state = &GlobalVisSharedRels; state = &GlobalVisSharedRels;
else if (need_catalog) break;
case VISHORIZON_CATALOG:
state = &GlobalVisCatalogRels; state = &GlobalVisCatalogRels;
else if (RELATION_IS_LOCAL(rel)) break;
state = &GlobalVisTempRels; case VISHORIZON_DATA:
else
state = &GlobalVisDataRels; state = &GlobalVisDataRels;
break;
case VISHORIZON_TEMP:
state = &GlobalVisTempRels;
break;
}
Assert(FullTransactionIdIsValid(state->definitely_needed) && Assert(FullTransactionIdIsValid(state->definitely_needed) &&
FullTransactionIdIsValid(state->maybe_needed)); FullTransactionIdIsValid(state->maybe_needed));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment