aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/pgstattuple/pgstatindex.c26
-rw-r--r--contrib/pgstattuple/pgstattuple.c7
-rw-r--r--src/backend/access/brin/brin.c27
-rw-r--r--src/backend/access/gin/ginfast.c23
4 files changed, 74 insertions, 9 deletions
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index d69ac1c93df..8e5a4d6a663 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -238,6 +238,18 @@ pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
errmsg("cannot access temporary tables of other sessions")));
/*
+ * A !indisready index could lead to ERRCODE_DATA_CORRUPTED later, so exit
+ * early. We're capable of assessing an indisready&&!indisvalid index,
+ * but the results could be confusing. For example, the index's size
+ * could be too low for a valid index of the table.
+ */
+ if (!rel->rd_index->indisvalid)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(rel))));
+
+ /*
* Read metapage
*/
{
@@ -523,6 +535,13 @@ pgstatginindex_internal(Oid relid, FunctionCallInfo fcinfo)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary indexes of other sessions")));
+ /* see pgstatindex_impl */
+ if (!rel->rd_index->indisvalid)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(rel))));
+
/*
* Read metapage
*/
@@ -600,6 +619,13 @@ pgstathashindex(PG_FUNCTION_ARGS)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary indexes of other sessions")));
+ /* see pgstatindex_impl */
+ if (!rel->rd_index->indisvalid)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(rel))));
+
/* Get the information we need from the metapage. */
memset(&stats, 0, sizeof(stats));
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 93b7834b774..3bd8b96197f 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -259,6 +259,13 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
}
else if (rel->rd_rel->relkind == RELKIND_INDEX)
{
+ /* see pgstatindex_impl */
+ if (!rel->rd_index->indisvalid)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(rel))));
+
switch (rel->rd_rel->relam)
{
case BTREE_AM_OID:
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index af392bc032b..25338a90e29 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -1100,8 +1100,14 @@ brin_summarize_range(PG_FUNCTION_ARGS)
errmsg("could not open parent table of index \"%s\"",
RelationGetRelationName(indexRel))));
- /* OK, do it */
- brinsummarize(indexRel, heapRel, heapBlk, true, &numSummarized, NULL);
+ /* see gin_clean_pending_list() */
+ if (indexRel->rd_index->indisvalid)
+ brinsummarize(indexRel, heapRel, heapBlk, true, &numSummarized, NULL);
+ else
+ ereport(DEBUG1,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(indexRel))));
/* Roll back any GUC changes executed by index functions */
AtEOXact_GUC(false, save_nestlevel);
@@ -1183,12 +1189,21 @@ brin_desummarize_range(PG_FUNCTION_ARGS)
errmsg("could not open parent table of index \"%s\"",
RelationGetRelationName(indexRel))));
- /* the revmap does the hard work */
- do
+ /* see gin_clean_pending_list() */
+ if (indexRel->rd_index->indisvalid)
{
- done = brinRevmapDesummarizeRange(indexRel, heapBlk);
+ /* the revmap does the hard work */
+ do
+ {
+ done = brinRevmapDesummarizeRange(indexRel, heapBlk);
+ }
+ while (!done);
}
- while (!done);
+ else
+ ereport(DEBUG1,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(indexRel))));
relation_close(indexRel, ShareUpdateExclusiveLock);
relation_close(heapRel, ShareUpdateExclusiveLock);
diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c
index c8fe7c78a7a..8798fbe9635 100644
--- a/src/backend/access/gin/ginfast.c
+++ b/src/backend/access/gin/ginfast.c
@@ -1033,7 +1033,6 @@ gin_clean_pending_list(PG_FUNCTION_ARGS)
Oid indexoid = PG_GETARG_OID(0);
Relation indexRel = index_open(indexoid, RowExclusiveLock);
IndexBulkDeleteResult stats;
- GinState ginstate;
if (RecoveryInProgress())
ereport(ERROR,
@@ -1065,8 +1064,26 @@ gin_clean_pending_list(PG_FUNCTION_ARGS)
RelationGetRelationName(indexRel));
memset(&stats, 0, sizeof(stats));
- initGinState(&ginstate, indexRel);
- ginInsertCleanup(&ginstate, true, true, true, &stats);
+
+ /*
+ * Can't assume anything about the content of an !indisready index. Make
+ * those a no-op, not an error, so users can just run this function on all
+ * indexes of the access method. Since an indisready&&!indisvalid index
+ * is merely awaiting missed aminsert calls, we're capable of processing
+ * it. Decline to do so, out of an abundance of caution.
+ */
+ if (indexRel->rd_index->indisvalid)
+ {
+ GinState ginstate;
+
+ initGinState(&ginstate, indexRel);
+ ginInsertCleanup(&ginstate, true, true, true, &stats);
+ }
+ else
+ ereport(DEBUG1,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("index \"%s\" is not valid",
+ RelationGetRelationName(indexRel))));
index_close(indexRel, RowExclusiveLock);