diff options
-rw-r--r-- | contrib/pgstattuple/pgstatindex.c | 26 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple.c | 7 | ||||
-rw-r--r-- | src/backend/access/brin/brin.c | 27 | ||||
-rw-r--r-- | src/backend/access/gin/ginfast.c | 23 |
4 files changed, 74 insertions, 9 deletions
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c index 2c807537266..ff099727f6f 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 */ { @@ -538,6 +550,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 */ @@ -615,6 +634,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 70af43ebd5a..e063ad83ff4 100644 --- a/contrib/pgstattuple/pgstattuple.c +++ b/contrib/pgstattuple/pgstattuple.c @@ -260,6 +260,13 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo) case RELKIND_SEQUENCE: return pgstat_heap(rel, fcinfo); case 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 eb318303c7d..81f819ecc45 100644 --- a/src/backend/access/brin/brin.c +++ b/src/backend/access/brin/brin.c @@ -1039,8 +1039,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); @@ -1125,12 +1131,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 4dcfdf2ac63..39eb9e14cd4 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -1041,7 +1041,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, @@ -1073,8 +1072,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); |