diff options
Diffstat (limited to 'src/backend/replication/logical/relation.c')
-rw-r--r-- | src/backend/replication/logical/relation.c | 128 |
1 files changed, 53 insertions, 75 deletions
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c index c545b90636f..6edbd5643ae 100644 --- a/src/backend/replication/logical/relation.c +++ b/src/backend/replication/logical/relation.c @@ -732,70 +732,8 @@ 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 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, 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: There are no fundamental problems for supporting non-btree indexes. - * We mostly need to relax the limitations in RelationFindReplTupleByIndex(). - * 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. @@ -812,19 +750,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; } @@ -832,17 +767,60 @@ 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. + * + * 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. + * + * 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: There are no fundamental problems for supporting non-btree indexes. + * We mostly need to relax the limitations in RelationFindReplTupleByIndex(). + * 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. */ bool -IsIndexUsableForReplicaIdentityFull(IndexInfo *indexInfo) +IsIndexUsableForReplicaIdentityFull(IndexInfo *indexInfo, AttrMap *attrmap) { - bool is_btree = (indexInfo->ii_Am == BTREE_AM_OID); - bool is_partial = (indexInfo->ii_Predicate != NIL); - bool is_only_on_expression = IsIndexOnlyOnExpression(indexInfo); + AttrNumber keycol; + + /* The index must be a Btree index */ + if (indexInfo->ii_Am != BTREE_AM_OID) + return false; + + /* The index must not be a partial index */ + if (indexInfo->ii_Predicate != NIL) + return false; + + Assert(indexInfo->ii_NumIndexAttrs >= 1); - return is_btree && !is_partial && !is_only_on_expression; + /* 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; + + return true; } /* |