@ -1601,6 +1601,7 @@ RelationIdGetRelation(Oid relationId)
RelationReloadIndexInfo ( rd ) ;
RelationReloadIndexInfo ( rd ) ;
else
else
RelationClearRelation ( rd , true ) ;
RelationClearRelation ( rd , true ) ;
Assert ( rd - > rd_isvalid ) ;
}
}
return rd ;
return rd ;
}
}
@ -1712,8 +1713,9 @@ RelationReloadIndexInfo(Relation relation)
/* Should be called only for invalidated indexes */
/* Should be called only for invalidated indexes */
Assert ( relation - > rd_rel - > relkind = = RELKIND_INDEX & &
Assert ( relation - > rd_rel - > relkind = = RELKIND_INDEX & &
! relation - > rd_isvalid ) ;
! relation - > rd_isvalid ) ;
/* Should be closed at smgr level */
Assert ( relation - > rd_smgr = = NULL ) ;
/* Ensure it's closed at smgr level */
RelationCloseSmgr ( relation ) ;
/* Must free any AM cached data upon relcache flush */
/* Must free any AM cached data upon relcache flush */
if ( relation - > rd_amcache )
if ( relation - > rd_amcache )
@ -1892,12 +1894,11 @@ RelationClearRelation(Relation relation, bool rebuild)
* be unable to recover . However , we must redo RelationInitPhysicalAddr
* be unable to recover . However , we must redo RelationInitPhysicalAddr
* in case it is a mapped relation whose mapping changed .
* in case it is a mapped relation whose mapping changed .
*
*
* If it ' s a nailed index , then we need to re - read the pg_class row to see
* If it ' s a nailed - but - not - mapped index , then we need to re - read the
* if its relfilenode changed . We can ' t necessarily do that here , because
* pg_class row to see if its relfilenode changed . We do that immediately
* we might be in a failed transaction . We assume it ' s okay to do it if
* if we ' re inside a valid transaction and the relation is open ( not
* there are open references to the relcache entry ( cf notes for
* counting the nailed refcount ) . Otherwise just mark the entry as
* AtEOXact_RelationCache ) . Otherwise just mark the entry as possibly
* possibly invalid , and it ' ll be fixed when next opened .
* invalid , and it ' ll be fixed when next opened .
*/
*/
if ( relation - > rd_isnailed )
if ( relation - > rd_isnailed )
{
{
@ -1906,7 +1907,7 @@ RelationClearRelation(Relation relation, bool rebuild)
if ( relation - > rd_rel - > relkind = = RELKIND_INDEX )
if ( relation - > rd_rel - > relkind = = RELKIND_INDEX )
{
{
relation - > rd_isvalid = false ; /* needs to be revalidated */
relation - > rd_isvalid = false ; /* needs to be revalidated */
if ( relation - > rd_refcnt > 1 )
if ( relation - > rd_refcnt > 1 & & IsTransactionState ( ) )
RelationReloadIndexInfo ( relation ) ;
RelationReloadIndexInfo ( relation ) ;
}
}
return ;
return ;
@ -1924,7 +1925,8 @@ RelationClearRelation(Relation relation, bool rebuild)
relation - > rd_indexcxt ! = NULL )
relation - > rd_indexcxt ! = NULL )
{
{
relation - > rd_isvalid = false ; /* needs to be revalidated */
relation - > rd_isvalid = false ; /* needs to be revalidated */
RelationReloadIndexInfo ( relation ) ;
if ( IsTransactionState ( ) )
RelationReloadIndexInfo ( relation ) ;
return ;
return ;
}
}
@ -1945,6 +1947,29 @@ RelationClearRelation(Relation relation, bool rebuild)
/* And release storage */
/* And release storage */
RelationDestroyRelation ( relation ) ;
RelationDestroyRelation ( relation ) ;
}
}
else if ( ! IsTransactionState ( ) )
{
/*
* If we ' re not inside a valid transaction , we can ' t do any catalog
* access so it ' s not possible to rebuild yet . Just exit , leaving
* rd_isvalid = false so that the rebuild will occur when the entry is
* next opened .
*
* Note : it ' s possible that we come here during subtransaction abort ,
* and the reason for wanting to rebuild is that the rel is open in
* the outer transaction . In that case it might seem unsafe to not
* rebuild immediately , since whatever code has the rel already open
* will keep on using the relcache entry as - is . However , in such a
* case the outer transaction should be holding a lock that ' s
* sufficient to prevent any significant change in the rel ' s schema ,
* so the existing entry contents should be good enough for its
* purposes ; at worst we might be behind on statistics updates or the
* like . ( See also CheckTableNotInUse ( ) and its callers . ) These same
* remarks also apply to the cases above where we exit without having
* done RelationReloadIndexInfo ( ) yet .
*/
return ;
}
else
else
{
{
/*
/*
@ -2057,6 +2082,7 @@ RelationClearRelation(Relation relation, bool rebuild)
* RelationFlushRelation
* RelationFlushRelation
*
*
* Rebuild the relation if it is open ( refcount > 0 ) , else blow it away .
* Rebuild the relation if it is open ( refcount > 0 ) , else blow it away .
* This is used when we receive a cache invalidation event for the rel .
*/
*/
static void
static void
RelationFlushRelation ( Relation relation )
RelationFlushRelation ( Relation relation )