diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index bccea5fa1737b7bc43ff5917166f4ade325c937e..975c193917590587af4a34240a8a8b7197b31349 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.236 2006/01/19 00:27:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.237 2006/01/19 20:28:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1436,11 +1436,13 @@ RelationClose(Relation relation) /* * RelationReloadClassinfo - reload the pg_class row (only) * - * This function is used only for nailed indexes. Since a REINDEX can - * change the relfilenode value for a nailed index, we have to reread - * the pg_class row anytime we get an SI invalidation on a nailed index - * (without throwing away the whole relcache entry, since we'd be unable - * to rebuild it). + * This function is used only for indexes. We currently allow only the + * pg_class row of an existing index to change (to support changes of + * owner, tablespace, or relfilenode), not its pg_index row or other + * subsidiary index schema information. Therefore it's sufficient to do + * this when we get an SI invalidation. Furthermore, there are cases + * where it's necessary not to throw away the index information, especially + * for "nailed" indexes which we are unable to rebuild on-the-fly. * * We can't necessarily reread the pg_class row right away; we might be * in a failed transaction when we receive the SI notification. If so, @@ -1455,9 +1457,11 @@ RelationReloadClassinfo(Relation relation) HeapTuple pg_class_tuple; Form_pg_class relp; - /* Should be called only for invalidated nailed indexes */ - Assert(relation->rd_isnailed && !relation->rd_isvalid && - relation->rd_rel->relkind == RELKIND_INDEX); + /* Should be called only for invalidated indexes */ + Assert(relation->rd_rel->relkind == RELKIND_INDEX && + !relation->rd_isvalid); + /* Should be closed at smgr level */ + Assert(relation->rd_smgr == NULL); /* * Read the pg_class row @@ -1468,13 +1472,14 @@ RelationReloadClassinfo(Relation relation) indexOK = (RelationGetRelid(relation) != ClassOidIndexId); pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK); if (!HeapTupleIsValid(pg_class_tuple)) - elog(ERROR, "could not find tuple for system relation %u", + elog(ERROR, "could not find pg_class tuple for index %u", RelationGetRelid(relation)); relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); - memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); - /* Now we can recalculate physical address */ - RelationInitPhysicalAddr(relation); + memcpy(relation->rd_rel, relp, CLASS_TUPLE_SIZE); heap_freetuple(pg_class_tuple); + /* We must recalculate physical address in case it changed */ + RelationInitPhysicalAddr(relation); + /* Make sure targblock is reset in case rel was truncated */ relation->rd_targblock = InvalidBlockNumber; /* Okay, now it's valid again */ relation->rd_isvalid = true; @@ -1529,6 +1534,22 @@ RelationClearRelation(Relation relation, bool rebuild) return; } + /* + * Even non-system indexes should not be blown away if they are open and + * have valid index support information. This avoids problems with active + * use of the index support information. As with nailed indexes, we + * re-read the pg_class row to handle possible physical relocation of + * the index. + */ + if (relation->rd_rel->relkind == RELKIND_INDEX && + relation->rd_refcnt > 0 && + relation->rd_indexcxt != NULL) + { + relation->rd_isvalid = false; /* needs to be revalidated */ + RelationReloadClassinfo(relation); + return; + } + /* * Remove relation from hash tables *