@ -1901,6 +1901,8 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
}
list_free ( relation - > rd_indexlist ) ;
bms_free ( relation - > rd_indexattr ) ;
bms_free ( relation - > rd_keyattr ) ;
bms_free ( relation - > rd_idattr ) ;
FreeTriggerDesc ( relation - > trigdesc ) ;
if ( relation - > rd_options )
pfree ( relation - > rd_options ) ;
@ -2547,6 +2549,7 @@ AtEOXact_cleanup(Relation relation, bool isCommit)
list_free ( relation - > rd_indexlist ) ;
relation - > rd_indexlist = NIL ;
relation - > rd_oidindex = InvalidOid ;
relation - > rd_replidindex = InvalidOid ;
relation - > rd_indexvalid = 0 ;
}
}
@ -2645,6 +2648,7 @@ AtEOSubXact_cleanup(Relation relation, bool isCommit,
list_free ( relation - > rd_indexlist ) ;
relation - > rd_indexlist = NIL ;
relation - > rd_oidindex = InvalidOid ;
relation - > rd_replidindex = InvalidOid ;
relation - > rd_indexvalid = 0 ;
}
}
@ -3596,6 +3600,10 @@ CheckConstraintFetch(Relation relation)
* of the index list . rd_oidindex is valid when rd_indexvalid isn ' t zero ;
* it is the pg_class OID of a unique index on OID when the relation has one ,
* and InvalidOid if there is no such index .
*
* In exactly the same way , we update rd_replidindex , which is the pg_class
* OID of an index to be used as the relation ' s replication identity index ,
* or InvalidOid if there is no such index .
*/
List *
RelationGetIndexList ( Relation relation )
@ -3667,8 +3675,8 @@ RelationGetIndexList(Relation relation)
/*
* Invalid , non - unique , non - immediate or predicate indexes aren ' t
* interesting for n either oid indexes n or replication identity
* indexes , so don ' t check them .
* interesting for either oid indexes or replication identity indexes ,
* so don ' t check them .
*/
if ( ! IndexIsValid ( index ) | | ! index - > indisunique | |
! index - > indimmediate | |
@ -3681,35 +3689,29 @@ RelationGetIndexList(Relation relation)
indclass - > values [ 0 ] = = OID_BTREE_OPS_OID )
oidIndex = index - > indexrelid ;
/* always prefer primary keys */
/* remember primary key index if any */
if ( index - > indisprimary )
pkeyIndex = index - > indexrelid ;
/* explicitly chosen index */
/* remember explicitly chosen replica index */
if ( index - > indisreplident )
candidateIndex = index - > indexrelid ;
}
systable_endscan ( indscan ) ;
/* primary key */
if ( replident = = REPLICA_IDENTITY_DEFAULT & &
OidIsValid ( pkeyIndex ) )
relation - > rd_replidindex = pkeyIndex ;
/* explicitly chosen index */
else if ( replident = = REPLICA_IDENTITY_INDEX & &
OidIsValid ( candidateIndex ) )
relation - > rd_replidindex = candidateIndex ;
/* nothing */
else
relation - > rd_replidindex = InvalidOid ;
heap_close ( indrel , AccessShareLock ) ;
/* Now save a copy of the completed list in the relcache entry. */
oldcxt = MemoryContextSwitchTo ( CacheMemoryContext ) ;
relation - > rd_indexlist = list_copy ( result ) ;
relation - > rd_oidindex = oidIndex ;
if ( replident = = REPLICA_IDENTITY_DEFAULT & & OidIsValid ( pkeyIndex ) )
relation - > rd_replidindex = pkeyIndex ;
else if ( replident = = REPLICA_IDENTITY_INDEX & & OidIsValid ( candidateIndex ) )
relation - > rd_replidindex = candidateIndex ;
else
relation - > rd_replidindex = InvalidOid ;
relation - > rd_indexvalid = 1 ;
MemoryContextSwitchTo ( oldcxt ) ;
@ -3767,7 +3769,8 @@ insert_ordered_oid(List *list, Oid datum)
* correctly with respect to the full index set . It is up to the caller
* to ensure that a correct rd_indexattr set has been cached before first
* calling RelationSetIndexList ; else a subsequent inquiry might cause a
* wrong rd_indexattr set to get computed and cached .
* wrong rd_indexattr set to get computed and cached . Likewise , we do not
* touch rd_keyattr or rd_idattr .
*/
void
RelationSetIndexList ( Relation relation , List * indexIds , Oid oidIndex )
@ -3783,6 +3786,8 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
list_free ( relation - > rd_indexlist ) ;
relation - > rd_indexlist = indexIds ;
relation - > rd_oidindex = oidIndex ;
/* For the moment, assume the target rel hasn't got a replica index */
relation - > rd_replidindex = InvalidOid ;
relation - > rd_indexvalid = 2 ; /* mark list as forced */
/* Flag relation as needing eoxact cleanup (to reset the list) */
EOXactListAdd ( relation ) ;
@ -3816,6 +3821,27 @@ RelationGetOidIndex(Relation relation)
return relation - > rd_oidindex ;
}
/*
* RelationGetReplicaIndex - - get OID of the relation ' s replica identity index
*
* Returns InvalidOid if there is no such index .
*/
Oid
RelationGetReplicaIndex ( Relation relation )
{
List * ilist ;
if ( relation - > rd_indexvalid = = 0 )
{
/* RelationGetIndexList does the heavy lifting. */
ilist = RelationGetIndexList ( relation ) ;
list_free ( ilist ) ;
Assert ( relation - > rd_indexvalid ! = 0 ) ;
}
return relation - > rd_replidindex ;
}
/*
* RelationGetIndexExpressions - - get the index expressions for an index
*
@ -3954,8 +3980,8 @@ RelationGetIndexPredicate(Relation relation)
* predicates . )
*
* Depending on attrKind , a bitmap covering the attnums for all index columns ,
* for all key columns or for all the columns the configured replica identity
* are returned .
* for all potential foreign key columns , or for all columns in the configured
* replica identity index is returned .
*
* Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
* we can include system attributes ( e . g . , OID ) in the bitmap representation .
@ -3974,22 +4000,25 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
Bitmapset * uindexattrs ; /* columns in unique indexes */
Bitmapset * idindexattrs ; /* columns in the replica identity */
List * indexoidlist ;
Oid relreplindex ;
ListCell * l ;
MemoryContext oldcxt ;
/* Quick exit if we already computed the result. */
if ( relation - > rd_indexattr ! = NULL )
{
switch ( attrKind )
{
case INDEX_ATTR_BITMAP_IDENTITY_KEY :
return bms_copy ( relation - > rd_idattr ) ;
case INDEX_ATTR_BITMAP_KEY :
return bms_copy ( relation - > rd_keyattr ) ;
case INDEX_ATTR_BITMAP_ALL :
return bms_copy ( relation - > rd_indexattr ) ;
case INDEX_ATTR_BITMAP_KEY :
return bms_copy ( relation - > rd_keyattr ) ;
case INDEX_ATTR_BITMAP_IDENTITY_KEY :
return bms_copy ( relation - > rd_idattr ) ;
default :
elog ( ERROR , " unknown attrKind %u " , attrKind ) ;
}
}
/* Fast path if definitely no indexes */
if ( ! RelationGetForm ( relation ) - > relhasindex )
@ -4004,6 +4033,15 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
if ( indexoidlist = = NIL )
return NULL ;
/*
* Copy the rd_replidindex value computed by RelationGetIndexList before
* proceeding . This is needed because a relcache flush could occur inside
* index_open below , resetting the fields managed by RelationGetIndexList .
* ( The values we ' re computing will still be valid , assuming that caller
* has a sufficient lock on the relation . )
*/
relreplindex = relation - > rd_replidindex ;
/*
* For each index , add referenced attributes to indexattrs .
*
@ -4026,7 +4064,6 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
bool isKey ; /* candidate key */
bool isIDKey ; /* replica identity index */
indexDesc = index_open ( indexOid , AccessShareLock ) ;
/* Extract index key information from the index's pg_index row */
@ -4038,7 +4075,7 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
indexInfo - > ii_Predicate = = NIL ;
/* Is this index the configured (or default) replica identity? */
isIDKey = indexOid = = relation - > rd_replidindex ;
isIDKey = ( indexOid = = relreplindex ) ;
/* Collect simple attribute references */
for ( i = 0 ; i < indexInfo - > ii_NumIndexAttrs ; i + + )
@ -4050,13 +4087,13 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
indexattrs = bms_add_member ( indexattrs ,
attrnum - FirstLowInvalidHeapAttributeNumber ) ;
if ( isIDKey )
idindexattrs = bms_add_member ( idindexattrs ,
attrnum - FirstLowInvalidHeapAttributeNumber ) ;
if ( isKey )
uindexattrs = bms_add_member ( uindexattrs ,
attrnum - FirstLowInvalidHeapAttributeNumber ) ;
if ( isIDKey )
idindexattrs = bms_add_member ( idindexattrs ,
attrnum - FirstLowInvalidHeapAttributeNumber ) ;
}
}
@ -4071,22 +4108,28 @@ RelationGetIndexAttrBitmap(Relation relation, IndexAttrBitmapKind attrKind)
list_free ( indexoidlist ) ;
/* Now save a copy of the bitmap in the relcache entry. */
/*
* Now save copies of the bitmaps in the relcache entry . We intentionally
* set rd_indexattr last , because that ' s the one that signals validity of
* the values ; if we run out of memory before making that copy , we won ' t
* leave the relcache entry looking like the other ones are valid but
* empty .
*/
oldcxt = MemoryContextSwitchTo ( CacheMemoryContext ) ;
relation - > rd_indexattr = bms_copy ( indexattrs ) ;
relation - > rd_keyattr = bms_copy ( uindexattrs ) ;
relation - > rd_idattr = bms_copy ( idindexattrs ) ;
relation - > rd_indexattr = bms_copy ( indexattrs ) ;
MemoryContextSwitchTo ( oldcxt ) ;
/* We return our original working copy for caller to play with */
switch ( attrKind )
{
case INDEX_ATTR_BITMAP_IDENTITY_KEY :
return idindexattrs ;
case INDEX_ATTR_BITMAP_KEY :
return uindexattrs ;
case INDEX_ATTR_BITMAP_ALL :
return indexattrs ;
case INDEX_ATTR_BITMAP_KEY :
return uindexattrs ;
case INDEX_ATTR_BITMAP_IDENTITY_KEY :
return idindexattrs ;
default :
elog ( ERROR , " unknown attrKind %u " , attrKind ) ;
return NULL ;
@ -4630,8 +4673,11 @@ load_relcache_init_file(bool shared)
rel - > rd_refcnt = 0 ;
rel - > rd_indexvalid = 0 ;
rel - > rd_indexlist = NIL ;
rel - > rd_indexattr = NULL ;
rel - > rd_oidindex = InvalidOid ;
rel - > rd_replidindex = InvalidOid ;
rel - > rd_indexattr = NULL ;
rel - > rd_keyattr = NULL ;
rel - > rd_idattr = NULL ;
rel - > rd_createSubid = InvalidSubTransactionId ;
rel - > rd_newRelfilenodeSubid = InvalidSubTransactionId ;
rel - > rd_amcache = NULL ;