@@ -734,71 +734,9 @@ logicalrep_partition_open(LogicalRepRelMapEntry *root,
734
734
return entry ;
735
735
}
736
736
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
-
783
737
/*
784
738
* 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.
802
740
*
803
741
* We expect to call this function when REPLICA IDENTITY FULL is defined for
804
742
* the remote relation.
@@ -815,31 +753,41 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
815
753
{
816
754
Oid idxoid = lfirst_oid (lc );
817
755
bool isUsableIdx ;
818
- bool containsLeftMostCol ;
819
756
Relation idxRel ;
820
757
IndexInfo * idxInfo ;
821
758
822
759
idxRel = index_open (idxoid , AccessShareLock );
823
760
idxInfo = BuildIndexInfo (idxRel );
824
- isUsableIdx = IsIndexUsableForReplicaIdentityFull (idxInfo );
825
- containsLeftMostCol =
826
- RemoteRelContainsLeftMostColumnOnIdx (idxInfo , attrmap );
761
+ isUsableIdx = IsIndexUsableForReplicaIdentityFull (idxInfo , attrmap );
827
762
index_close (idxRel , AccessShareLock );
828
763
829
764
/* Return the first eligible index found */
830
- if (isUsableIdx && containsLeftMostCol )
765
+ if (isUsableIdx )
831
766
return idxoid ;
832
767
}
833
768
834
769
return InvalidOid ;
835
770
}
836
771
837
772
/*
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.
840
774
*
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:
843
791
*
844
792
* 1) Other index access methods don't have a fixed strategy for equality
845
793
* operation. Refer get_equal_strategy_number_for_am().
@@ -851,16 +799,38 @@ FindUsableIndexForReplicaIdentityFull(Relation localrel, AttrMap *attrmap)
851
799
*
852
800
* XXX: Note that BRIN and GIN indexes do not implement "amgettuple" which
853
801
* 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.
854
806
*/
855
807
bool
856
- IsIndexUsableForReplicaIdentityFull (IndexInfo * indexInfo )
808
+ IsIndexUsableForReplicaIdentityFull (IndexInfo * indexInfo , AttrMap * attrmap )
857
809
{
810
+ AttrNumber keycol ;
811
+
858
812
/* Ensure that the index access method has a valid equal strategy */
859
813
if (get_equal_strategy_number_for_am (indexInfo -> ii_Am ) == InvalidStrategy )
860
814
return false;
815
+
816
+ /* The index must not be a partial index */
861
817
if (indexInfo -> ii_Predicate != NIL )
862
818
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 )
864
834
return false;
865
835
866
836
#ifdef USE_ASSERT_CHECKING
0 commit comments