Index: src/backend/utils/cache/inval.c =================================================================== RCS file: /repositories/postgreshome/cvs/pgsql/src/backend/utils/cache/inval.c,v retrieving revision 1.79 diff -c -r1.79 inval.c *** src/backend/utils/cache/inval.c 5 Jan 2007 22:19:43 -0000 1.79 --- src/backend/utils/cache/inval.c 27 Mar 2007 07:17:33 -0000 *************** *** 596,601 **** --- 596,612 ---- */ databaseId = MyDatabaseId; } + else if (tupleRelId == IndexRelationId) + { + Form_pg_index indextup = (Form_pg_index) GETSTRUCT(tuple); + + /* + * When a pg_index row is updated, we should send SI invaliation + * to the index relation + */ + relationId = indextup->indexrelid; + databaseId = MyDatabaseId; + } else return; Index: src/backend/utils/cache/relcache.c =================================================================== RCS file: /repositories/postgreshome/cvs/pgsql/src/backend/utils/cache/relcache.c,v retrieving revision 1.258 diff -c -r1.258 relcache.c *** src/backend/utils/cache/relcache.c 19 Mar 2007 23:38:29 -0000 1.258 --- src/backend/utils/cache/relcache.c 27 Mar 2007 07:17:33 -0000 *************** *** 212,217 **** --- 212,218 ---- static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numStrats, StrategyNumber numSupport); + static void RelationReloadIndexInfo(Relation relation); /* *************** *** 1580,1592 **** /* * RelationReloadClassinfo - reload the pg_class row (only) * ! * 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, --- 1581,1597 ---- /* * RelationReloadClassinfo - reload the pg_class row (only) * ! * This function is used only for indexes. We used to 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. But for CREATE INDEX CONCURRENTLY ! * we need to change the pg_index attribute 'indisvalid' and update ! * pg_index row. In future, there might be similar requirements for ! * the existing and/or new attributes of pg_index to change. To ! * support that we now re-read the pg_index row and update one ! * or more fields selectively. We don't rebuild the entire the ! * entire information because that may not be even possible for ! * "nailed" indexes. * * 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, *************** *** 1634,1639 **** --- 1639,1651 ---- if (relation->rd_amcache) pfree(relation->rd_amcache); relation->rd_amcache = NULL; + + /* + * Before we mark the relation valid, re-read the pg_index row + * and update some of the fields selectively. + */ + RelationReloadIndexInfo(relation); + /* Okay, now it's valid again */ relation->rd_isvalid = true; } *************** *** 3747,3749 **** --- 3759,3817 ---- unlink(initfilename); /* ignore any error, since it might not be there at all */ } + + /* + * Reload index-access-method support data for an index relation + */ + static void + RelationReloadIndexInfo(Relation relation) + { + Form_pg_index index; + HeapTuple pg_index_tuple; + Relation pg_index_desc; + SysScanDesc pg_index_scan; + ScanKeyData key[1]; + bool indexOK; + + /* + * form a scan key + */ + ScanKeyInit(&key[0], + Anum_pg_index_indexrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); + /* + * Open pg_index and fetch a tuple. Force heap scan if we haven't yet + * built the critical relcache entries (this includes initdb and startup + * without a pg_internal.init file). + */ + indexOK = (RelationGetRelid(relation) != IndexRelidIndexId); + + pg_index_desc = heap_open(IndexRelationId, AccessShareLock); + pg_index_scan = systable_beginscan(pg_index_desc, IndexRelidIndexId, + indexOK && criticalRelcachesBuilt, + SnapshotNow, + 1, key); + + pg_index_tuple = systable_getnext(pg_index_scan); + + /* + * Must copy tuple before releasing buffer. + */ + if (HeapTupleIsValid(pg_index_tuple)) + pg_index_tuple = heap_copytuple(pg_index_tuple); + + /* all done */ + systable_endscan(pg_index_scan); + heap_close(pg_index_desc, AccessShareLock); + + index = (Form_pg_index) GETSTRUCT(pg_index_tuple); + + Assert(relation->rd_indextuple); + Assert(relation->rd_index); + + relation->rd_index->indisvalid = index->indisvalid; + + heap_freetuple(pg_index_tuple); + return; + }