@ -732,57 +732,51 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
}
/*
* Returns true if the given index consists only of expressions such as :
* CREATE INDEX idx ON table ( foo ( col ) ) ;
* Returns the oid of an index that can be used by the apply worker to scan
* the relation .
*
* Returns false even if there is one column reference :
* CREATE INDEX idx ON table ( foo ( col ) , col_2 ) ;
* We expect to call this function when REPLICA IDENTITY FULL is defined for
* the remote relation .
*
* If no suitable index is found , returns InvalidOid .
*/
static bool
IsIndexOnlyOnExpression ( IndexInfo * indexInfo )
static Oid
FindUsableIndexForReplicaIdentityFull ( Relation localrel , AttrMap * attrmap )
{
for ( int i = 0 ; i < indexInfo - > ii_NumIndexKeyAttrs ; i + + )
List * idxlist = RelationGetIndexList ( localrel ) ;
ListCell * lc ;
foreach ( lc , idxlist )
{
AttrNumber attnum = indexInfo - > ii_IndexAttrNumbers [ i ] ;
Oid idxoid = lfirst_oid ( lc ) ;
bool isUsableIdx ;
Relation idxRel ;
IndexInfo * idxInfo ;
if ( AttributeNumberIsValid ( attnum ) )
return false ;
idxRel = index_open ( idxoid , AccessShareLock ) ;
idxInfo = BuildIndexInfo ( idxRel ) ;
isUsableIdx = IsIndexUsableForReplicaIdentityFull ( idxInfo , attrmap ) ;
index_close ( idxRel , AccessShareLock ) ;
/* Return the first eligible index found */
if ( isUsableIdx )
return idxoid ;
}
return true ;
return InvalidOid ;
}
/*
* Returns true if the attrmap contains the leftmost column of the index .
* Otherwise returns false .
* Returns true if the index is usable for replica identity full .
*
* The index must be btree , non - partial , and the leftmost field must be a
* column ( not an expression ) that references the remote relation column .
* These limitations help to keep the index scan similar to PK / RI index
* scans .
*
* attrmap is a map of local attributes to remote ones . We can consult this
* map to check whether the local index attribute has a corresponding remote
* attribute .
*/
static bool
RemoteRelContainsLeftMostColumnOnIdx ( IndexInfo * indexInfo , AttrMap * attrmap )
{
AttrNumber keycol ;
Assert ( indexInfo - > ii_NumIndexAttrs > = 1 ) ;
keycol = indexInfo - > ii_IndexAttrNumbers [ 0 ] ;
if ( ! AttributeNumberIsValid ( keycol ) )
return false ;
if ( attrmap - > maplen < = AttrNumberGetAttrOffset ( keycol ) )
return false ;
return attrmap - > attnums [ AttrNumberGetAttrOffset ( keycol ) ] > = 0 ;
}
/*
* Returns the oid of an index that can be used by the apply worker to scan
* the relation . The index must be btree , non - partial , and the leftmost
* field must be a column ( not an expression ) that references the remote
* relation column . These limitations help to keep the index scan similar
* to PK / RI index scans .
*
* Note that the limitations of index scans for replica identity full only
* adheres to a subset of the limitations of PK / RI . For example , we support
@ -796,53 +790,37 @@ RemoteRelContainsLeftMostColumnOnIdx(IndexInfo *indexInfo, AttrMap *attrmap)
* For partial indexes , the required changes are likely to be larger . If
* none of the tuples satisfy the expression for the index scan , we fall - back
* to sequential execution , which might not be a good idea in some cases .
*
* We expect to call this function when REPLICA IDENTITY FULL is defined for
* the remote relation .
*
* If no suitable index is found , returns InvalidOid .
*/
static Oid
FindUsableIndexForReplicaIdentityFull ( Relation localrel , AttrMap * attrmap )
bool
IsIndexUsableForReplicaIdentityFull ( IndexInfo * indexInfo , AttrMap * attrmap )
{
List * idxlist = RelationGetIndexList ( localrel ) ;
ListCell * lc ;
AttrNumber keycol ;
foreach ( lc , idxlist )
{
Oid idxoid = lfirst_oid ( lc ) ;
bool isUsableIdx ;
bool containsLeftMostCol ;
Relation idxRel ;
IndexInfo * idxInfo ;
/* The index must be a Btree index */
if ( indexInfo - > ii_Am ! = BTREE_AM_OID )
return false ;
idxRel = index_open ( idxoid , AccessShareLock ) ;
idxInfo = BuildIndexInfo ( idxRel ) ;
isUsableIdx = IsIndexUsableForReplicaIdentityFull ( idxInfo ) ;
containsLeftMostCol =
RemoteRelContainsLeftMostColumnOnIdx ( idxInfo , attrmap ) ;
index_close ( idxRel , AccessShareLock ) ;
/* The index must not be a partial index */
if ( indexInfo - > ii_Predicate ! = NIL )
return false ;
/* Return the first eligible index found */
if ( isUsableIdx & & containsLeftMostCol )
return idxoid ;
}
Assert ( indexInfo - > ii_NumIndexAttrs > = 1 ) ;
return InvalidOid ;
}
/* The leftmost index field must not be an expression */
keycol = indexInfo - > ii_IndexAttrNumbers [ 0 ] ;
if ( ! AttributeNumberIsValid ( keycol ) )
return false ;
/*
* Returns true if the index is usable for replica identity full . For details ,
* see FindUsableIndexForReplicaIdentityFull .
* And the leftmost index field must reference the remote relation column .
* This is because if it doesn ' t , the sequential scan is favorable over
* index scan in most cases .
*/
bool
IsIndexUsableForReplicaIdentityFull ( IndexInfo * indexInfo )
{
bool is_btree = ( indexInfo - > ii_Am = = BTREE_AM_OID ) ;
bool is_partial = ( indexInfo - > ii_Predicate ! = NIL ) ;
bool is_only_on_expression = IsIndexOnlyOnExpression ( indexInfo ) ;
if ( attrmap - > maplen < = AttrNumberGetAttrOffset ( keycol ) | |
attrmap - > attnums [ AttrNumberGetAttrOffset ( keycol ) ] < 0 )
return false ;
return is_btree & & ! is_par tial & & ! is_only_on_exp ression ;
return true ;
}
/*