@@ -734,71 +734,9 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
734734 return entry ;
735735}
736736
737- /*
738- * Returns true if the given index consists only of expressions such as:
739- * CREATE INDEX idx ON table(foo(col));
740- *
741- * Returns false even if there is one column reference:
742- * CREATE INDEX idx ON table(foo(col), col_2);
743- */
744- static bool
745- IsIndexOnlyOnExpression (IndexInfo * indexInfo )
746- {
747- for (int i = 0 ; i < indexInfo -> ii_NumIndexKeyAttrs ; i ++ )
748- {
749- AttrNumber attnum = indexInfo -> ii_IndexAttrNumbers [i ];
750-
751- if (AttributeNumberIsValid (attnum ))
752- return false;
753- }
754-
755- return true;
756- }
757-
758- /*
759- * Returns true if the attrmap contains the leftmost column of the index.
760- * Otherwise returns false.
761- *
762- * attrmap is a map of local attributes to remote ones. We can consult this
763- * map to check whether the local index attribute has a corresponding remote
764- * attribute.
765- */
766- static bool
767- RemoteRelContainsLeftMostColumnOnIdx (IndexInfo * indexInfo , AttrMap * attrmap )
768- {
769- AttrNumber keycol ;
770-
771- Assert (indexInfo -> ii_NumIndexAttrs >= 1 );
772-
773- keycol = indexInfo -> ii_IndexAttrNumbers [0 ];
774- if (!AttributeNumberIsValid (keycol ))
775- return false;
776-
777- if (attrmap -> maplen <= AttrNumberGetAttrOffset (keycol ))
778- return false;
779-
780- return attrmap -> attnums [AttrNumberGetAttrOffset (keycol )] >= 0 ;
781- }
782-
783737/*
784738 * Returns the oid of an index that can be used by the apply worker to scan
785- * the relation. The index must be btree or hash, non-partial, and the leftmost
786- * field must be a column (not an expression) that references the remote
787- * relation column. These limitations help to keep the index scan similar
788- * to PK/RI index scans.
789- *
790- * Note that the limitations of index scans for replica identity full only
791- * adheres to a subset of the limitations of PK/RI. For example, we support
792- * columns that are marked as [NULL] or we are not interested in the [NOT
793- * DEFERRABLE] aspect of constraints here. It works for us because we always
794- * compare the tuples for non-PK/RI index scans. See
795- * RelationFindReplTupleByIndex().
796- *
797- * XXX: See IsIndexUsableForReplicaIdentityFull() to know the challenges in
798- * supporting indexes other than btree and hash. For partial indexes, the
799- * required changes are likely to be larger. If none of the tuples satisfy
800- * the expression for the index scan, we fall-back to sequential execution,
801- * which might not be a good idea in some cases.
739+ * the relation.
802740 *
803741 * We expect to call this function when REPLICA IDENTITY FULL is defined for
804742 * the remote relation.
@@ -815,31 +753,41 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
815753 {
816754 Oid idxoid = lfirst_oid (lc );
817755 bool isUsableIdx ;
818- bool containsLeftMostCol ;
819756 Relation idxRel ;
820757 IndexInfo * idxInfo ;
821758
822759 idxRel = index_open (idxoid , AccessShareLock );
823760 idxInfo = BuildIndexInfo (idxRel );
824- isUsableIdx = IsIndexUsableForReplicaIdentityFull (idxInfo );
825- containsLeftMostCol =
826- RemoteRelContainsLeftMostColumnOnIdx (idxInfo , attrmap );
761+ isUsableIdx = IsIndexUsableForReplicaIdentityFull (idxInfo , attrmap );
827762 index_close (idxRel , AccessShareLock );
828763
829764 /* Return the first eligible index found */
830- if (isUsableIdx && containsLeftMostCol )
765+ if (isUsableIdx )
831766 return idxoid ;
832767 }
833768
834769 return InvalidOid ;
835770}
836771
837772/*
838- * Returns true if the index is usable for replica identity full. For details,
839- * see FindUsableIndexForReplicaIdentityFull.
773+ * Returns true if the index is usable for replica identity full.
840774 *
841- * Currently, only Btree and Hash indexes can be returned as usable. This
842- * is due to following reasons:
775+ * The index must be btree or hash, non-partial, and the leftmost field must be
776+ * a column (not an expression) that references the remote relation column. These
777+ * limitations help to keep the index scan similar to PK/RI index scans.
778+ *
779+ * attrmap is a map of local attributes to remote ones. We can consult this
780+ * map to check whether the local index attribute has a corresponding remote
781+ * attribute.
782+ *
783+ * Note that the limitations of index scans for replica identity full only
784+ * adheres to a subset of the limitations of PK/RI. For example, we support
785+ * columns that are marked as [NULL] or we are not interested in the [NOT
786+ * DEFERRABLE] aspect of constraints here. It works for us because we always
787+ * compare the tuples for non-PK/RI index scans. See
788+ * RelationFindReplTupleByIndex().
789+ *
790+ * The reasons why only Btree and Hash indexes can be considered as usable are:
843791 *
844792 * 1) Other index access methods don't have a fixed strategy for equality
845793 * operation. Refer get_equal_strategy_number_for_am().
@@ -851,16 +799,38 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
851799 *
852800 * XXX: Note that BRIN and GIN indexes do not implement "amgettuple" which
853801 * will be used later to fetch the tuples. See RelationFindReplTupleByIndex().
802+ *
803+ * XXX: To support partial indexes, the required changes are likely to be larger.
804+ * If none of the tuples satisfy the expression for the index scan, we fall-back
805+ * to sequential execution, which might not be a good idea in some cases.
854806 */
855807bool
856- IsIndexUsableForReplicaIdentityFull (IndexInfo * indexInfo )
808+ IsIndexUsableForReplicaIdentityFull (IndexInfo * indexInfo , AttrMap * attrmap )
857809{
810+ AttrNumber keycol ;
811+
858812 /* Ensure that the index access method has a valid equal strategy */
859813 if (get_equal_strategy_number_for_am (indexInfo -> ii_Am ) == InvalidStrategy )
860814 return false;
815+
816+ /* The index must not be a partial index */
861817 if (indexInfo -> ii_Predicate != NIL )
862818 return false;
863- if (IsIndexOnlyOnExpression (indexInfo ))
819+
820+ Assert (indexInfo -> ii_NumIndexAttrs >= 1 );
821+
822+ /* The leftmost index field must not be an expression */
823+ keycol = indexInfo -> ii_IndexAttrNumbers [0 ];
824+ if (!AttributeNumberIsValid (keycol ))
825+ return false;
826+
827+ /*
828+ * And the leftmost index field must reference the remote relation column.
829+ * This is because if it doesn't, the sequential scan is favorable over
830+ * index scan in most cases.
831+ */
832+ if (attrmap -> maplen <= AttrNumberGetAttrOffset (keycol ) ||
833+ attrmap -> attnums [AttrNumberGetAttrOffset (keycol )] < 0 )
864834 return false;
865835
866836#ifdef USE_ASSERT_CHECKING
0 commit comments