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;
+ }