@ -734,71 +734,9 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
return entry ;
}
/*
* Returns true if the given index consists only of expressions such as :
* CREATE INDEX idx ON table ( foo ( col ) ) ;
*
* Returns false even if there is one column reference :
* CREATE INDEX idx ON table ( foo ( col ) , col_2 ) ;
*/
static bool
IsIndexOnlyOnExpression ( IndexInfo * indexInfo )
{
for ( int i = 0 ; i < indexInfo - > ii_NumIndexKeyAttrs ; i + + )
{
AttrNumber attnum = indexInfo - > ii_IndexAttrNumbers [ i ] ;
if ( AttributeNumberIsValid ( attnum ) )
return false ;
}
return true ;
}
/*
* Returns true if the attrmap contains the leftmost column of the index .
* Otherwise returns false .
*
* 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 or hash , 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
* columns that are marked as [ NULL ] or we are not interested in the [ NOT
* DEFERRABLE ] aspect of constraints here . It works for us because we always
* compare the tuples for non - PK / RI index scans . See
* RelationFindReplTupleByIndex ( ) .
*
* XXX : See IsIndexUsableForReplicaIdentityFull ( ) to know the challenges in
* supporting indexes other than btree and hash . 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 .
* the relation .
*
* We expect to call this function when REPLICA IDENTITY FULL is defined for
* the remote relation .
@ -815,19 +753,16 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
{
Oid idxoid = lfirst_oid ( lc ) ;
bool isUsableIdx ;
bool containsLeftMostCol ;
Relation idxRel ;
IndexInfo * idxInfo ;
idxRel = index_open ( idxoid , AccessShareLock ) ;
idxInfo = BuildIndexInfo ( idxRel ) ;
isUsableIdx = IsIndexUsableForReplicaIdentityFull ( idxInfo ) ;
containsLeftMostCol =
RemoteRelContainsLeftMostColumnOnIdx ( idxInfo , attrmap ) ;
isUsableIdx = IsIndexUsableForReplicaIdentityFull ( idxInfo , attrmap ) ;
index_close ( idxRel , AccessShareLock ) ;
/* Return the first eligible index found */
if ( isUsableIdx & & containsLeftMostCol )
if ( isUsableIdx )
return idxoid ;
}
@ -835,11 +770,24 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
}
/*
* Returns true if the index is usable for replica identity full . For details ,
* see FindUsableIndexForReplicaIdentityFull .
* Returns true if the index is usable for replica identity full .
*
* Currently , only Btree and Hash indexes can be returned as usable . This
* is due to following reasons :
* The index must be btree or hash , 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 .
*
* 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
* columns that are marked as [ NULL ] or we are not interested in the [ NOT
* DEFERRABLE ] aspect of constraints here . It works for us because we always
* compare the tuples for non - PK / RI index scans . See
* RelationFindReplTupleByIndex ( ) .
*
* The reasons why only Btree and Hash indexes can be considered as usable are :
*
* 1 ) Other index access methods don ' t have a fixed strategy for equality
* operation . Refer get_equal_strategy_number_for_am ( ) .
@ -851,16 +799,38 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
*
* XXX : Note that BRIN and GIN indexes do not implement " amgettuple " which
* will be used later to fetch the tuples . See RelationFindReplTupleByIndex ( ) .
*
* XXX : To support 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 .
*/
bool
IsIndexUsableForReplicaIdentityFull ( IndexInfo * indexInfo )
IsIndexUsableForReplicaIdentityFull ( IndexInfo * indexInfo , AttrMap * attrmap )
{
AttrNumber keycol ;
/* Ensure that the index access method has a valid equal strategy */
if ( get_equal_strategy_number_for_am ( indexInfo - > ii_Am ) = = InvalidStrategy )
return false ;
/* The index must not be a partial index */
if ( indexInfo - > ii_Predicate ! = NIL )
return false ;
if ( IsIndexOnlyOnExpression ( indexInfo ) )
Assert ( indexInfo - > ii_NumIndexAttrs > = 1 ) ;
/* The leftmost index field must not be an expression */
keycol = indexInfo - > ii_IndexAttrNumbers [ 0 ] ;
if ( ! AttributeNumberIsValid ( keycol ) )
return false ;
/*
* 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 .
*/
if ( attrmap - > maplen < = AttrNumberGetAttrOffset ( keycol ) | |
attrmap - > attnums [ AttrNumberGetAttrOffset ( keycol ) ] < 0 )
return false ;
# ifdef USE_ASSERT_CHECKING