(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot reindex temporary tables of other sessions")));
+ /*
+ * Don't allow reindex of an invalid index on TOAST table. This is a
+ * leftover from a failed REINDEX CONCURRENTLY, and if rebuilt it would
+ * not be possible to drop it anymore.
+ */
+ if (IsToastNamespace(RelationGetNamespace(iRel)) &&
+ !get_index_isvalid(indexId))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex invalid index on TOAST table")));
+
/*
* Also check for active uses of the index in the current transaction; we
* don't want to reindex underneath an open indexscan.
foreach(indexId, indexIds)
{
Oid indexOid = lfirst_oid(indexId);
+ Oid indexNamespaceId = get_rel_namespace(indexOid);
+
+ /*
+ * Skip any invalid indexes on a TOAST table. These can only be
+ * duplicate leftovers from a failed REINDEX CONCURRENTLY, and if
+ * rebuilt it would not be possible to drop them anymore.
+ */
+ if (IsToastNamespace(indexNamespaceId) &&
+ !get_index_isvalid(indexOid))
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping",
+ get_namespace_name(indexNamespaceId),
+ get_rel_name(indexOid))));
+ continue;
+ }
reindex_index(indexOid, !(flags & REINDEX_REL_CHECK_CONSTRAINTS),
persistence, options);
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot reindex system catalogs concurrently")));
+ /*
+ * Don't allow reindex for an invalid index on TOAST table, as
+ * if rebuild it would not be possible to drop it.
+ */
+ if (IsToastNamespace(get_rel_namespace(relationOid)) &&
+ !get_index_isvalid(relationOid))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot reindex invalid index on TOAST table concurrently")));
+
/* Save the list of relation OIDs in private context */
oldcontext = MemoryContextSwitchTo(private_context);
return opclass;
}
+
+/*
+ * get_index_isvalid
+ *
+ * Given the index OID, return pg_index.indisvalid.
+ */
+bool
+get_index_isvalid(Oid index_oid)
+{
+ bool isvalid;
+ HeapTuple tuple;
+ Form_pg_index rd_index;
+
+ tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for index %u", index_oid);
+
+ rd_index = (Form_pg_index) GETSTRUCT(tuple);
+ isvalid = rd_index->indisvalid;
+ ReleaseSysCache(tuple);
+
+ return isvalid;
+}
extern Oid get_range_subtype(Oid rangeOid);
extern Oid get_range_collation(Oid rangeOid);
extern Oid get_index_column_opclass(Oid index_oid, int attno);
+extern bool get_index_isvalid(Oid index_oid);
#define type_is_array(typid) (get_element_type(typid) != InvalidOid)
/* type_is_array_domain accepts both plain arrays and domains over arrays */