On 20.03.25 12:59, Peter Eisentraut wrote:
v22-0006-Convert-from-StrategyNumber-to-CompareType.patch

This is all that remains now.  I think with a bit more polishing around the edges, some comment updates, etc., this is close to ready.

Here is an updated version of this patch. I have left out all the extra tests and WIP patches etc. from the series for now so that the focus is clear.

This patch is mostly unchanged from the above, except some small amount of updating comments, as well as the following.

I've done a fair bit of performance testing to make sure there are no noticeable regressions from this patch. I've found that the function get_mergejoin_opfamilies() is quite critical to the planning time of even simple queries (such as pgbench --select-only), so I played around with various caching schemes. In the end, I just settled on hardcoding information about the built-in index AM types. Which is of course ugly, but at least it's essentially the same as before. If we find other affected hotspots, we could apply similar workarounds, but so far I haven't found any.
From ec6fa0fbcb1fda3c1d95e0cc22a126da3f78ee69 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 1 Apr 2025 14:41:44 +0200
Subject: [PATCH v23] Convert from StrategyNumber to CompareType

Reduce the number of places that hardcode a btree strategy number by
instead using comparison types.

Generalize predicate tests beyond btree strategies.  Extend routines
which prove logical implications between predicate expressions to be
usable by more than just B-tree index strategies.

Allow non-btree indexes to participate in mergejoin.  Rather than
hardcoding a requirement that the index be of type btree, just require
that it provide ordering support.

A number of places in the code still had references to btree
strategies where not appropriate, so fix those.  Leave untouched such
strategy numbers in nbtree, spgist, and brin indexes, and also in
table partitioning.  Hardcoded hash and btree references in table
partitioning are part of the design of table partitioning; their
replacement, if even a good idea, is beyond the scope of this patch
series.

Author: Mark Dilger <mark.dil...@enterprisedb.com>
Co-authored-by: Peter Eisentraut <pe...@eisentraut.org>
Discussion: 
https://www.postgresql.org/message-id/flat/e72eaa49-354d-4c2e-8eb9-255197f55...@enterprisedb.com
---
 contrib/postgres_fdw/deparse.c          |  16 +-
 contrib/postgres_fdw/postgres_fdw.c     |   2 +-
 src/backend/executor/execExpr.c         |   1 +
 src/backend/executor/nodeIndexscan.c    |   3 +
 src/backend/executor/nodeMergejoin.c    |   7 +-
 src/backend/optimizer/path/allpaths.c   |  28 ++--
 src/backend/optimizer/path/costsize.c   |   8 +-
 src/backend/optimizer/path/equivclass.c |   3 +-
 src/backend/optimizer/path/indxpath.c   |   9 +-
 src/backend/optimizer/path/pathkeys.c   |  45 +++---
 src/backend/optimizer/plan/createplan.c |  34 ++--
 src/backend/optimizer/util/plancat.c    |  39 +++--
 src/backend/optimizer/util/predtest.c   | 119 +++++++-------
 src/backend/parser/parse_clause.c       |   4 +-
 src/backend/parser/parse_expr.c         |  34 ++--
 src/backend/partitioning/partprune.c    |  13 +-
 src/backend/utils/adt/selfuncs.c        | 133 ++++++++--------
 src/backend/utils/cache/lsyscache.c     | 196 ++++++++++++++++--------
 src/backend/utils/sort/sortsupport.c    |   6 +-
 src/include/nodes/pathnodes.h           |  12 +-
 src/include/optimizer/paths.h           |   2 +-
 src/include/utils/lsyscache.h           |  15 +-
 src/include/utils/selfuncs.h            |   2 +-
 src/tools/pgindent/typedefs.list        |   2 +-
 24 files changed, 399 insertions(+), 334 deletions(-)

diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 6e7dc3d2df9..d9970dd6753 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -3969,17 +3969,17 @@ appendOrderByClause(List *pathkeys, bool has_final_sort,
                        appendStringInfoString(buf, ", ");
 
                /*
-                * Lookup the operator corresponding to the strategy in the 
opclass.
-                * The datatype used by the opfamily is not necessarily the 
same as
-                * the expression type (for array types for example).
+                * Lookup the operator corresponding to the compare type in the
+                * opclass. The datatype used by the opfamily is not 
necessarily the
+                * same as the expression type (for array types for example).
                 */
-               oprid = get_opfamily_member(pathkey->pk_opfamily,
-                                                                       
em->em_datatype,
-                                                                       
em->em_datatype,
-                                                                       
pathkey->pk_strategy);
+               oprid = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
+                                                                               
                em->em_datatype,
+                                                                               
                em->em_datatype,
+                                                                               
                pathkey->pk_cmptype);
                if (!OidIsValid(oprid))
                        elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-                                pathkey->pk_strategy, em->em_datatype, 
em->em_datatype,
+                                pathkey->pk_cmptype, em->em_datatype, 
em->em_datatype,
                                 pathkey->pk_opfamily);
 
                deparseExpr(em_expr, context);
diff --git a/contrib/postgres_fdw/postgres_fdw.c 
b/contrib/postgres_fdw/postgres_fdw.c
index ac14c06c715..b4e0e60928b 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -999,7 +999,7 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, 
RelOptInfo *rel)
                /* Looks like we can generate a pathkey, so let's do it. */
                pathkey = make_canonical_pathkey(root, cur_ec,
                                                                                
 linitial_oid(cur_ec->ec_opfamilies),
-                                                                               
 BTLessStrategyNumber,
+                                                                               
 COMPARE_LT,
                                                                                
 false);
                useful_pathkeys_list = lappend(useful_pathkeys_list,
                                                                           
list_make1(pathkey));
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index f1569879b52..4b9388af154 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2098,6 +2098,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
                                        get_op_opfamily_properties(opno, 
opfamily, false,
                                                                                
           &strategy,
+                                                                               
           NULL,        /* don't need cmptype */
                                                                                
           &lefttype,
                                                                                
           &righttype);
                                        proc = get_opfamily_proc(opfamily,
diff --git a/src/backend/executor/nodeIndexscan.c 
b/src/backend/executor/nodeIndexscan.c
index 7fcaa37fe62..82826c146ba 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1246,6 +1246,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation 
index,
 
                        get_op_opfamily_properties(opno, opfamily, isorderby,
                                                                           
&op_strategy,
+                                                                          
NULL,        /* don't need cmptype */
                                                                           
&op_lefttype,
                                                                           
&op_righttype);
 
@@ -1364,6 +1365,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation 
index,
 
                                get_op_opfamily_properties(opno, opfamily, 
isorderby,
                                                                                
   &op_strategy,
+                                                                               
   NULL,        /* don't need cmptype */
                                                                                
   &op_lefttype,
                                                                                
   &op_righttype);
 
@@ -1487,6 +1489,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation 
index,
 
                        get_op_opfamily_properties(opno, opfamily, isorderby,
                                                                           
&op_strategy,
+                                                                          
NULL,        /* don't need cmptype */
                                                                           
&op_lefttype,
                                                                           
&op_righttype);
 
diff --git a/src/backend/executor/nodeMergejoin.c 
b/src/backend/executor/nodeMergejoin.c
index f70239a2c9d..c7b813ac090 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -195,7 +195,7 @@ MJExamineQuals(List *mergeclauses,
                Oid                     collation = mergecollations[iClause];
                bool            reversed = mergereversals[iClause];
                bool            nulls_first = mergenullsfirst[iClause];
-               int                     op_strategy;
+               CompareType op_cmptype;
                Oid                     op_lefttype;
                Oid                     op_righttype;
                Oid                     sortfunc;
@@ -217,10 +217,11 @@ MJExamineQuals(List *mergeclauses,
 
                /* Extract the operator's declared left/right datatypes */
                get_op_opfamily_properties(qual->opno, opfamily, false,
-                                                                  &op_strategy,
+                                                                  NULL,
+                                                                  &op_cmptype,
                                                                   &op_lefttype,
                                                                   
&op_righttype);
-               if (op_strategy != BTEqualStrategyNumber)       /* should not 
happen */
+               if (op_cmptype != COMPARE_EQ)   /* should not happen */
                        elog(ERROR, "cannot merge using non-equality operator 
%u",
                                 qual->opno);
 
diff --git a/src/backend/optimizer/path/allpaths.c 
b/src/backend/optimizer/path/allpaths.c
index df3453f99f0..905250b3325 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -2313,16 +2313,15 @@ find_window_run_conditions(Query *subquery, 
RangeTblEntry *rte, Index rti,
 
        runopexpr = NULL;
        runoperator = InvalidOid;
-       opinfos = get_op_btree_interpretation(opexpr->opno);
+       opinfos = get_op_index_interpretation(opexpr->opno);
 
        foreach(lc, opinfos)
        {
-               OpBtreeInterpretation *opinfo = (OpBtreeInterpretation *) 
lfirst(lc);
-               int                     strategy = opinfo->strategy;
+               OpIndexInterpretation *opinfo = (OpIndexInterpretation *) 
lfirst(lc);
+               CompareType cmptype = opinfo->cmptype;
 
                /* handle < / <= */
-               if (strategy == BTLessStrategyNumber ||
-                       strategy == BTLessEqualStrategyNumber)
+               if (cmptype == COMPARE_LT || cmptype == COMPARE_LE)
                {
                        /*
                         * < / <= is supported for monotonically increasing 
functions in
@@ -2339,8 +2338,7 @@ find_window_run_conditions(Query *subquery, RangeTblEntry 
*rte, Index rti,
                        break;
                }
                /* handle > / >= */
-               else if (strategy == BTGreaterStrategyNumber ||
-                                strategy == BTGreaterEqualStrategyNumber)
+               else if (cmptype == COMPARE_GT || cmptype == COMPARE_GE)
                {
                        /*
                         * > / >= is supported for monotonically decreasing 
functions in
@@ -2357,9 +2355,9 @@ find_window_run_conditions(Query *subquery, RangeTblEntry 
*rte, Index rti,
                        break;
                }
                /* handle = */
-               else if (strategy == BTEqualStrategyNumber)
+               else if (cmptype == COMPARE_EQ)
                {
-                       int16           newstrategy;
+                       CompareType newcmptype;
 
                        /*
                         * When both monotonically increasing and decreasing 
then the
@@ -2383,19 +2381,19 @@ find_window_run_conditions(Query *subquery, 
RangeTblEntry *rte, Index rti,
                         * below the value in the equality condition.
                         */
                        if (res->monotonic & MONOTONICFUNC_INCREASING)
-                               newstrategy = wfunc_left ? 
BTLessEqualStrategyNumber : BTGreaterEqualStrategyNumber;
+                               newcmptype = wfunc_left ? COMPARE_LE : 
COMPARE_GE;
                        else
-                               newstrategy = wfunc_left ? 
BTGreaterEqualStrategyNumber : BTLessEqualStrategyNumber;
+                               newcmptype = wfunc_left ? COMPARE_GE : 
COMPARE_LE;
 
                        /* We must keep the original equality qual */
                        *keep_original = true;
                        runopexpr = opexpr;
 
                        /* determine the operator to use for the 
WindowFuncRunCondition */
-                       runoperator = get_opfamily_member(opinfo->opfamily_id,
-                                                                               
          opinfo->oplefttype,
-                                                                               
          opinfo->oprighttype,
-                                                                               
          newstrategy);
+                       runoperator = 
get_opfamily_member_for_cmptype(opinfo->opfamily_id,
+                                                                               
                                  opinfo->oplefttype,
+                                                                               
                                  opinfo->oprighttype,
+                                                                               
                                  newcmptype);
                        break;
                }
        }
diff --git a/src/backend/optimizer/path/costsize.c 
b/src/backend/optimizer/path/costsize.c
index f6f77b8fe19..c1bf67c95dc 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3608,7 +3608,7 @@ initial_cost_mergejoin(PlannerInfo *root, 
JoinCostWorkspace *workspace,
                /* debugging check */
                if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
                        opathkey->pk_eclass->ec_collation != 
ipathkey->pk_eclass->ec_collation ||
-                       opathkey->pk_strategy != ipathkey->pk_strategy ||
+                       opathkey->pk_cmptype != ipathkey->pk_cmptype ||
                        opathkey->pk_nulls_first != ipathkey->pk_nulls_first)
                        elog(ERROR, "left and right pathkeys do not match in 
mergejoin");
 
@@ -4093,7 +4093,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, 
PathKey *pathkey)
                cache = (MergeScanSelCache *) lfirst(lc);
                if (cache->opfamily == pathkey->pk_opfamily &&
                        cache->collation == pathkey->pk_eclass->ec_collation &&
-                       cache->strategy == pathkey->pk_strategy &&
+                       cache->cmptype == pathkey->pk_cmptype &&
                        cache->nulls_first == pathkey->pk_nulls_first)
                        return cache;
        }
@@ -4102,7 +4102,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, 
PathKey *pathkey)
        mergejoinscansel(root,
                                         (Node *) rinfo->clause,
                                         pathkey->pk_opfamily,
-                                        pathkey->pk_strategy,
+                                        pathkey->pk_cmptype,
                                         pathkey->pk_nulls_first,
                                         &leftstartsel,
                                         &leftendsel,
@@ -4115,7 +4115,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, 
PathKey *pathkey)
        cache = (MergeScanSelCache *) palloc(sizeof(MergeScanSelCache));
        cache->opfamily = pathkey->pk_opfamily;
        cache->collation = pathkey->pk_eclass->ec_collation;
-       cache->strategy = pathkey->pk_strategy;
+       cache->cmptype = pathkey->pk_cmptype;
        cache->nulls_first = pathkey->pk_nulls_first;
        cache->leftstartsel = leftstartsel;
        cache->leftendsel = leftendsel;
diff --git a/src/backend/optimizer/path/equivclass.c 
b/src/backend/optimizer/path/equivclass.c
index 0f9ecf5ee8b..0ae7c6d4f74 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1788,8 +1788,7 @@ select_equality_operator(EquivalenceClass *ec, Oid 
lefttype, Oid righttype)
                Oid                     opfamily = lfirst_oid(lc);
                Oid                     opno;
 
-               opno = get_opfamily_member(opfamily, lefttype, righttype,
-                                                                  
BTEqualStrategyNumber);
+               opno = get_opfamily_member_for_cmptype(opfamily, lefttype, 
righttype, COMPARE_EQ);
                if (!OidIsValid(opno))
                        continue;
                /* If no barrier quals in query, don't worry about leaky 
operators */
diff --git a/src/backend/optimizer/path/indxpath.c 
b/src/backend/optimizer/path/indxpath.c
index 6386ce82253..bdb05e7ce9d 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3611,6 +3611,7 @@ expand_indexqual_rowcompare(PlannerInfo *root,
 
        get_op_opfamily_properties(expr_op, index->opfamily[indexcol], false,
                                                           &op_strategy,
+                                                          NULL,        /* 
don't need cmptype */
                                                           &op_lefttype,
                                                           &op_righttype);
 
@@ -3672,6 +3673,7 @@ expand_indexqual_rowcompare(PlannerInfo *root,
                /* Add operator info to lists */
                get_op_opfamily_properties(expr_op, index->opfamily[i], false,
                                                                   &op_strategy,
+                                                                  NULL,        
/* don't need cmptype */
                                                                   &op_lefttype,
                                                                   
&op_righttype);
                expr_ops = lappend_oid(expr_ops, expr_op);
@@ -3745,6 +3747,10 @@ expand_indexqual_rowcompare(PlannerInfo *root,
                {
                        RowCompareExpr *rc = makeNode(RowCompareExpr);
 
+                       /*
+                        * XXX This assumes that CompareType values match btree 
strategy
+                        * numbers; see cmptype.h.
+                        */
                        rc->cmptype = (CompareType) op_strategy;
                        rc->opnos = new_ops;
                        rc->opfamilies = list_copy_head(clause->opfamilies,
@@ -3817,8 +3823,7 @@ match_pathkeys_to_index(IndexOptInfo *index, List 
*pathkeys,
 
 
                /* Pathkey must request default sort order for the target 
opfamily */
-               if (pathkey->pk_strategy != BTLessStrategyNumber ||
-                       pathkey->pk_nulls_first)
+               if (pathkey->pk_cmptype != COMPARE_LT || 
pathkey->pk_nulls_first)
                        return;
 
                /* If eclass is volatile, no hope of using an indexscan */
diff --git a/src/backend/optimizer/path/pathkeys.c 
b/src/backend/optimizer/path/pathkeys.c
index 154eb505d75..5db7033e3a9 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -55,7 +55,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey 
*pathkey);
 PathKey *
 make_canonical_pathkey(PlannerInfo *root,
                                           EquivalenceClass *eclass, Oid 
opfamily,
-                                          int strategy, bool nulls_first)
+                                          CompareType cmptype, bool 
nulls_first)
 {
        PathKey    *pk;
        ListCell   *lc;
@@ -74,7 +74,7 @@ make_canonical_pathkey(PlannerInfo *root,
                pk = (PathKey *) lfirst(lc);
                if (eclass == pk->pk_eclass &&
                        opfamily == pk->pk_opfamily &&
-                       strategy == pk->pk_strategy &&
+                       cmptype == pk->pk_cmptype &&
                        nulls_first == pk->pk_nulls_first)
                        return pk;
        }
@@ -88,7 +88,7 @@ make_canonical_pathkey(PlannerInfo *root,
        pk = makeNode(PathKey);
        pk->pk_eclass = eclass;
        pk->pk_opfamily = opfamily;
-       pk->pk_strategy = strategy;
+       pk->pk_cmptype = cmptype;
        pk->pk_nulls_first = nulls_first;
 
        root->canon_pathkeys = lappend(root->canon_pathkeys, pk);
@@ -206,12 +206,12 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
                                                   Relids rel,
                                                   bool create_it)
 {
-       int16           strategy;
+       CompareType cmptype;
        Oid                     equality_op;
        List       *opfamilies;
        EquivalenceClass *eclass;
 
-       strategy = reverse_sort ? BTGreaterStrategyNumber : 
BTLessStrategyNumber;
+       cmptype = reverse_sort ? COMPARE_GT : COMPARE_LT;
 
        /*
         * EquivalenceClasses need to contain opfamily lists based on the family
@@ -219,13 +219,13 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
         * more than one opfamily.  So we have to look up the opfamily's 
equality
         * operator and get its membership.
         */
-       equality_op = get_opfamily_member(opfamily,
-                                                                         
opcintype,
-                                                                         
opcintype,
-                                                                         
BTEqualStrategyNumber);
+       equality_op = get_opfamily_member_for_cmptype(opfamily,
+                                                                               
                  opcintype,
+                                                                               
                  opcintype,
+                                                                               
                  COMPARE_EQ);
        if (!OidIsValid(equality_op))   /* shouldn't happen */
                elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-                        BTEqualStrategyNumber, opcintype, opcintype, opfamily);
+                        COMPARE_EQ, opcintype, opcintype, opfamily);
        opfamilies = get_mergejoin_opfamilies(equality_op);
        if (!opfamilies)                        /* certainly should find some */
                elog(ERROR, "could not find opfamilies for equality operator 
%u",
@@ -242,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
 
        /* And finally we can find or create a PathKey node */
        return make_canonical_pathkey(root, eclass, opfamily,
-                                                                 strategy, 
nulls_first);
+                                                                 cmptype, 
nulls_first);
 }
 
 /*
@@ -264,11 +264,10 @@ make_pathkey_from_sortop(PlannerInfo *root,
        Oid                     opfamily,
                                opcintype,
                                collation;
-       int16           strategy;
 
        /* Find the operator in pg_amop --- failure shouldn't happen */
        if (!get_ordering_op_properties(ordering_op,
-                                                                       
&opfamily, &opcintype, &strategy))
+                                                                       
&opfamily, &opcintype, NULL, NULL))
                elog(ERROR, "operator %u is not a valid ordering operator",
                         ordering_op);
 
@@ -1006,12 +1005,12 @@ build_expression_pathkey(PlannerInfo *root,
        List       *pathkeys;
        Oid                     opfamily,
                                opcintype;
-       int16           strategy;
+       CompareType cmptype;
        PathKey    *cpathkey;
 
        /* Find the operator in pg_amop --- failure shouldn't happen */
        if (!get_ordering_op_properties(opno,
-                                                                       
&opfamily, &opcintype, &strategy))
+                                                                       
&opfamily, &opcintype, NULL, &cmptype))
                elog(ERROR, "operator %u is not a valid ordering operator",
                         opno);
 
@@ -1020,8 +1019,8 @@ build_expression_pathkey(PlannerInfo *root,
                                                                                
  opfamily,
                                                                                
  opcintype,
                                                                                
  exprCollation((Node *) expr),
-                                                                               
  (strategy == BTGreaterStrategyNumber),
-                                                                               
  (strategy == BTGreaterStrategyNumber),
+                                                                               
  (cmptype == COMPARE_GT),
+                                                                               
  (cmptype == COMPARE_GT),
                                                                                
  0,
                                                                                
  rel,
                                                                                
  create_it);
@@ -1118,7 +1117,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo 
*rel,
                                                make_canonical_pathkey(root,
                                                                                
           outer_ec,
                                                                                
           sub_pathkey->pk_opfamily,
-                                                                               
           sub_pathkey->pk_strategy,
+                                                                               
           sub_pathkey->pk_cmptype,
                                                                                
           sub_pathkey->pk_nulls_first);
                        }
                }
@@ -1200,7 +1199,7 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo 
*rel,
                                        outer_pk = make_canonical_pathkey(root,
                                                                                
                          outer_ec,
                                                                                
                          sub_pathkey->pk_opfamily,
-                                                                               
                          sub_pathkey->pk_strategy,
+                                                                               
                          sub_pathkey->pk_cmptype,
                                                                                
                          sub_pathkey->pk_nulls_first);
                                        /* score = # of equivalence peers */
                                        score = 
list_length(outer_ec->ec_members) - 1;
@@ -1816,7 +1815,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
                pathkey = make_canonical_pathkey(root,
                                                                                
 ec,
                                                                                
 linitial_oid(ec->ec_opfamilies),
-                                                                               
 BTLessStrategyNumber,
+                                                                               
 COMPARE_LT,
                                                                                
 false);
                /* can't be redundant because no duplicate ECs */
                Assert(!pathkey_is_redundant(pathkey, pathkeys));
@@ -1909,7 +1908,7 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
                        pathkey = make_canonical_pathkey(root,
                                                                                
         ieclass,
                                                                                
         opathkey->pk_opfamily,
-                                                                               
         opathkey->pk_strategy,
+                                                                               
         opathkey->pk_cmptype,
                                                                                
         opathkey->pk_nulls_first);
 
                /*
@@ -2134,12 +2133,12 @@ right_merge_direction(PlannerInfo *root, PathKey 
*pathkey)
                         * want to prefer only one of the two possible 
directions, and we
                         * might as well use this one.
                         */
-                       return (pathkey->pk_strategy == 
query_pathkey->pk_strategy);
+                       return (pathkey->pk_cmptype == 
query_pathkey->pk_cmptype);
                }
        }
 
        /* If no matching ORDER BY request, prefer the ASC direction */
-       return (pathkey->pk_strategy == BTLessStrategyNumber);
+       return (pathkey->pk_cmptype == COMPARE_LT);
 }
 
 /*
diff --git a/src/backend/optimizer/plan/createplan.c 
b/src/backend/optimizer/plan/createplan.c
index 75e2b0b9036..a8f22a8c154 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -3129,13 +3129,13 @@ create_indexscan_plan(PlannerInfo *root,
                        Oid                     sortop;
 
                        /* Get sort operator from opfamily */
-                       sortop = get_opfamily_member(pathkey->pk_opfamily,
-                                                                               
 exprtype,
-                                                                               
 exprtype,
-                                                                               
 pathkey->pk_strategy);
+                       sortop = 
get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
+                                                                               
                         exprtype,
+                                                                               
                         exprtype,
+                                                                               
                         pathkey->pk_cmptype);
                        if (!OidIsValid(sortop))
                                elog(ERROR, "missing operator %d(%u,%u) in 
opfamily %u",
-                                        pathkey->pk_strategy, exprtype, 
exprtype, pathkey->pk_opfamily);
+                                        pathkey->pk_cmptype, exprtype, 
exprtype, pathkey->pk_opfamily);
                        indexorderbyops = lappend_oid(indexorderbyops, sortop);
                }
        }
@@ -4739,14 +4739,14 @@ create_mergejoin_plan(PlannerInfo *root,
                        opathkey->pk_eclass->ec_collation != 
ipathkey->pk_eclass->ec_collation)
                        elog(ERROR, "left and right pathkeys do not match in 
mergejoin");
                if (first_inner_match &&
-                       (opathkey->pk_strategy != ipathkey->pk_strategy ||
+                       (opathkey->pk_cmptype != ipathkey->pk_cmptype ||
                         opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
                        elog(ERROR, "left and right pathkeys do not match in 
mergejoin");
 
                /* OK, save info for executor */
                mergefamilies[i] = opathkey->pk_opfamily;
                mergecollations[i] = opathkey->pk_eclass->ec_collation;
-               mergereversals[i] = (opathkey->pk_strategy == 
BTGreaterStrategyNumber ? true : false);
+               mergereversals[i] = (opathkey->pk_cmptype == COMPARE_GT ? true 
: false);
                mergenullsfirst[i] = opathkey->pk_nulls_first;
                i++;
        }
@@ -6374,13 +6374,13 @@ prepare_sort_from_pathkeys(Plan *lefttree, List 
*pathkeys,
                 * Look up the correct sort operator from the PathKey's slightly
                 * abstracted representation.
                 */
-               sortop = get_opfamily_member(pathkey->pk_opfamily,
-                                                                        
pk_datatype,
-                                                                        
pk_datatype,
-                                                                        
pathkey->pk_strategy);
+               sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
+                                                                               
                 pk_datatype,
+                                                                               
                 pk_datatype,
+                                                                               
                 pathkey->pk_cmptype);
                if (!OidIsValid(sortop))        /* should not happen */
                        elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-                                pathkey->pk_strategy, pk_datatype, pk_datatype,
+                                pathkey->pk_cmptype, pk_datatype, pk_datatype,
                                 pathkey->pk_opfamily);
 
                /* Add the column to the sort arrays */
@@ -6893,13 +6893,13 @@ make_unique_from_pathkeys(Plan *lefttree, List 
*pathkeys, int numCols)
                 * Look up the correct equality operator from the PathKey's 
slightly
                 * abstracted representation.
                 */
-               eqop = get_opfamily_member(pathkey->pk_opfamily,
-                                                                  pk_datatype,
-                                                                  pk_datatype,
-                                                                  
BTEqualStrategyNumber);
+               eqop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
+                                                                               
           pk_datatype,
+                                                                               
           pk_datatype,
+                                                                               
           COMPARE_EQ);
                if (!OidIsValid(eqop))  /* should not happen */
                        elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-                                BTEqualStrategyNumber, pk_datatype, 
pk_datatype,
+                                COMPARE_EQ, pk_datatype, pk_datatype,
                                 pathkey->pk_opfamily);
 
                uniqColIdx[keyno] = tle->resno;
diff --git a/src/backend/optimizer/util/plancat.c 
b/src/backend/optimizer/util/plancat.c
index 0489ad36644..0a1c030d277 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -365,14 +365,10 @@ get_relation_info(PlannerInfo *root, Oid 
relationObjectId, bool inhparent,
                                         * Since "<" uniquely defines the 
behavior of a sort
                                         * order, this is a sufficient test.
                                         *
-                                        * XXX This method is rather slow and 
also requires the
-                                        * undesirable assumption that the 
other index AM numbers
-                                        * its strategies the same as btree.  
It'd be better to
-                                        * have a way to explicitly declare the 
corresponding
-                                        * btree opfamily for each opfamily of 
the other index
-                                        * type.  But given the lack of current 
or foreseeable
-                                        * amcanorder index types, it's not 
worth expending more
-                                        * effort on now.
+                                        * XXX This method is rather slow and 
complicated.  It'd
+                                        * be better to have a way to 
explicitly declare the
+                                        * corresponding btree opfamily for 
each opfamily of the
+                                        * other index type.
                                         */
                                        info->sortopfamily = (Oid *) 
palloc(sizeof(Oid) * nkeycolumns);
                                        info->reverse_sort = (bool *) 
palloc(sizeof(bool) * nkeycolumns);
@@ -382,27 +378,28 @@ get_relation_info(PlannerInfo *root, Oid 
relationObjectId, bool inhparent,
                                        {
                                                int16           opt = 
indexRelation->rd_indoption[i];
                                                Oid                     ltopr;
-                                               Oid                     
btopfamily;
-                                               Oid                     
btopcintype;
-                                               int16           btstrategy;
+                                               Oid                     
opfamily;
+                                               Oid                     
opcintype;
+                                               CompareType cmptype;
 
                                                info->reverse_sort[i] = (opt & 
INDOPTION_DESC) != 0;
                                                info->nulls_first[i] = (opt & 
INDOPTION_NULLS_FIRST) != 0;
 
-                                               ltopr = 
get_opfamily_member(info->opfamily[i],
-                                                                               
                        info->opcintype[i],
-                                                                               
                        info->opcintype[i],
-                                                                               
                        BTLessStrategyNumber);
+                                               ltopr = 
get_opfamily_member_for_cmptype(info->opfamily[i],
+                                                                               
                                                info->opcintype[i],
+                                                                               
                                                info->opcintype[i],
+                                                                               
                                                COMPARE_LT);
                                                if (OidIsValid(ltopr) &&
                                                        
get_ordering_op_properties(ltopr,
-                                                                               
                           &btopfamily,
-                                                                               
                           &btopcintype,
-                                                                               
                           &btstrategy) &&
-                                                       btopcintype == 
info->opcintype[i] &&
-                                                       btstrategy == 
BTLessStrategyNumber)
+                                                                               
                           &opfamily,
+                                                                               
                           &opcintype,
+                                                                               
                           NULL,
+                                                                               
                           &cmptype) &&
+                                                       opcintype == 
info->opcintype[i] &&
+                                                       cmptype == COMPARE_LT)
                                                {
                                                        /* Successful mapping */
-                                                       info->sortopfamily[i] = 
btopfamily;
+                                                       info->sortopfamily[i] = 
opfamily;
                                                }
                                                else
                                                {
diff --git a/src/backend/optimizer/util/predtest.c 
b/src/backend/optimizer/util/predtest.c
index b76fc81b08d..9dcd0ffe81f 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1605,36 +1605,36 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool 
allow_false)
 
 
 /*
- * Define "operator implication tables" for btree operators ("strategies"),
+ * Define "operator implication tables" for index operators ("cmptypes"),
  * and similar tables for refutation.
  *
- * The strategy numbers defined by btree indexes (see access/stratnum.h) are:
- *             1 <             2 <=    3 =             4 >=    5 >
+ * The row compare numbers defined by indexes (see access/cmptype.h) are:
+ *             1 <             2 <=    3 =             4 >=    5 >             
6 <>
  * and in addition we use 6 to represent <>.  <> is not a btree-indexable
  * operator, but we assume here that if an equality operator of a btree
  * opfamily has a negator operator, the negator behaves as <> for the opfamily.
- * (This convention is also known to get_op_btree_interpretation().)
+ * (This convention is also known to get_op_index_interpretation().)
  *
- * BT_implies_table[] and BT_refutes_table[] are used for cases where we have
+ * RC_implies_table[] and RC_refutes_table[] are used for cases where we have
  * two identical subexpressions and we want to know whether one operator
  * expression implies or refutes the other.  That is, if the "clause" is
  * EXPR1 clause_op EXPR2 and the "predicate" is EXPR1 pred_op EXPR2 for the
  * same two (immutable) subexpressions:
- *             BT_implies_table[clause_op-1][pred_op-1]
+ *             RC_implies_table[clause_op-1][pred_op-1]
  *                     is true if the clause implies the predicate
- *             BT_refutes_table[clause_op-1][pred_op-1]
+ *             RC_refutes_table[clause_op-1][pred_op-1]
  *                     is true if the clause refutes the predicate
- * where clause_op and pred_op are strategy numbers (from 1 to 6) in the
- * same btree opfamily.  For example, "x < y" implies "x <= y" and refutes
+ * where clause_op and pred_op are cmptype numbers (from 1 to 6) in the
+ * same opfamily.  For example, "x < y" implies "x <= y" and refutes
  * "x > y".
  *
- * BT_implic_table[] and BT_refute_table[] are used where we have two
+ * RC_implic_table[] and RC_refute_table[] are used where we have two
  * constants that we need to compare.  The interpretation of:
  *
- *             test_op = BT_implic_table[clause_op-1][pred_op-1]
+ *             test_op = RC_implic_table[clause_op-1][pred_op-1]
  *
- * where test_op, clause_op and pred_op are strategy numbers (from 1 to 6)
- * of btree operators, is as follows:
+ * where test_op, clause_op and pred_op are cmptypes (from 1 to 6)
+ * of index operators, is as follows:
  *
  *      If you know, for some EXPR, that "EXPR clause_op CONST1" is true, and 
you
  *      want to determine whether "EXPR pred_op CONST2" must also be true, then
@@ -1645,7 +1645,7 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool 
allow_false)
  * For example, if clause is "Quantity > 10" and pred is "Quantity > 5"
  * then we test "5 <= 10" which evals to true, so clause implies pred.
  *
- * Similarly, the interpretation of a BT_refute_table entry is:
+ * Similarly, the interpretation of a RC_refute_table entry is:
  *
  *      If you know, for some EXPR, that "EXPR clause_op CONST1" is true, and 
you
  *      want to determine whether "EXPR pred_op CONST2" must be false, then
@@ -1659,17 +1659,17 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool 
allow_false)
  * An entry where test_op == 0 means the implication cannot be determined.
  */
 
-#define BTLT BTLessStrategyNumber
-#define BTLE BTLessEqualStrategyNumber
-#define BTEQ BTEqualStrategyNumber
-#define BTGE BTGreaterEqualStrategyNumber
-#define BTGT BTGreaterStrategyNumber
-#define BTNE COMPARE_NE
+#define RCLT COMPARE_LT
+#define RCLE COMPARE_LE
+#define RCEQ COMPARE_EQ
+#define RCGE COMPARE_GE
+#define RCGT COMPARE_GT
+#define RCNE COMPARE_NE
 
 /* We use "none" for 0/false to make the tables align nicely */
 #define none 0
 
-static const bool BT_implies_table[6][6] = {
+static const bool RC_implies_table[6][6] = {
 /*
  *                     The predicate operator:
  *      LT    LE        EQ    GE        GT    NE
@@ -1682,7 +1682,7 @@ static const bool BT_implies_table[6][6] = {
        {none, none, none, none, none, true}    /* NE */
 };
 
-static const bool BT_refutes_table[6][6] = {
+static const bool RC_refutes_table[6][6] = {
 /*
  *                     The predicate operator:
  *      LT    LE        EQ    GE        GT    NE
@@ -1695,30 +1695,30 @@ static const bool BT_refutes_table[6][6] = {
        {none, none, true, none, none, none}    /* NE */
 };
 
-static const StrategyNumber BT_implic_table[6][6] = {
+static const CompareType RC_implic_table[6][6] = {
 /*
  *                     The predicate operator:
  *      LT    LE        EQ    GE        GT    NE
  */
-       {BTGE, BTGE, none, none, none, BTGE},   /* LT */
-       {BTGT, BTGE, none, none, none, BTGT},   /* LE */
-       {BTGT, BTGE, BTEQ, BTLE, BTLT, BTNE},   /* EQ */
-       {none, none, none, BTLE, BTLT, BTLT},   /* GE */
-       {none, none, none, BTLE, BTLE, BTLE},   /* GT */
-       {none, none, none, none, none, BTEQ}    /* NE */
+       {RCGE, RCGE, none, none, none, RCGE},   /* LT */
+       {RCGT, RCGE, none, none, none, RCGT},   /* LE */
+       {RCGT, RCGE, RCEQ, RCLE, RCLT, RCNE},   /* EQ */
+       {none, none, none, RCLE, RCLT, RCLT},   /* GE */
+       {none, none, none, RCLE, RCLE, RCLE},   /* GT */
+       {none, none, none, none, none, RCEQ}    /* NE */
 };
 
-static const StrategyNumber BT_refute_table[6][6] = {
+static const CompareType RC_refute_table[6][6] = {
 /*
  *                     The predicate operator:
  *      LT    LE        EQ    GE        GT    NE
  */
-       {none, none, BTGE, BTGE, BTGE, none},   /* LT */
-       {none, none, BTGT, BTGT, BTGE, none},   /* LE */
-       {BTLE, BTLT, BTNE, BTGT, BTGE, BTEQ},   /* EQ */
-       {BTLE, BTLT, BTLT, none, none, none},   /* GE */
-       {BTLE, BTLE, BTLE, none, none, none},   /* GT */
-       {none, none, BTEQ, none, none, none}    /* NE */
+       {none, none, RCGE, RCGE, RCGE, none},   /* LT */
+       {none, none, RCGT, RCGT, RCGE, none},   /* LE */
+       {RCLE, RCLT, RCNE, RCGT, RCGE, RCEQ},   /* EQ */
+       {RCLE, RCLT, RCLT, none, none, none},   /* GE */
+       {RCLE, RCLE, RCLE, none, none, none},   /* GT */
+       {none, none, RCEQ, none, none, none}    /* NE */
 };
 
 
@@ -2165,66 +2165,67 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool 
refute_it)
         * operator.  This can happen in cases with incomplete sets of 
cross-type
         * comparison operators.
         */
-       clause_op_infos = get_op_btree_interpretation(clause_op);
+       clause_op_infos = get_op_index_interpretation(clause_op);
        if (clause_op_infos)
-               pred_op_infos = get_op_btree_interpretation(pred_op);
+               pred_op_infos = get_op_index_interpretation(pred_op);
        else                                            /* no point in looking 
*/
                pred_op_infos = NIL;
 
        foreach(lcp, pred_op_infos)
        {
-               OpBtreeInterpretation *pred_op_info = lfirst(lcp);
+               OpIndexInterpretation *pred_op_info = lfirst(lcp);
                Oid                     opfamily_id = pred_op_info->opfamily_id;
 
                foreach(lcc, clause_op_infos)
                {
-                       OpBtreeInterpretation *clause_op_info = lfirst(lcc);
-                       StrategyNumber pred_strategy,
-                                               clause_strategy,
-                                               test_strategy;
+                       OpIndexInterpretation *clause_op_info = lfirst(lcc);
+                       CompareType pred_cmptype,
+                                               clause_cmptype,
+                                               test_cmptype;
 
                        /* Must find them in same opfamily */
                        if (opfamily_id != clause_op_info->opfamily_id)
                                continue;
                        /* Lefttypes should match */
-                       Assert(clause_op_info->oplefttype == 
pred_op_info->oplefttype);
+                       if (clause_op_info->oplefttype != 
pred_op_info->oplefttype)
+                               continue;
 
-                       pred_strategy = pred_op_info->strategy;
-                       clause_strategy = clause_op_info->strategy;
+                       pred_cmptype = pred_op_info->cmptype;
+                       clause_cmptype = clause_op_info->cmptype;
 
                        /*
                         * Check to see if we can make a proof for 
same-subexpressions
                         * cases based on the operators' relationship in this 
opfamily.
                         */
                        if (refute_it)
-                               same_subexprs |= 
BT_refutes_table[clause_strategy - 1][pred_strategy - 1];
+                               same_subexprs |= 
RC_refutes_table[clause_cmptype - 1][pred_cmptype - 1];
                        else
-                               same_subexprs |= 
BT_implies_table[clause_strategy - 1][pred_strategy - 1];
+                               same_subexprs |= 
RC_implies_table[clause_cmptype - 1][pred_cmptype - 1];
 
                        /*
-                        * Look up the "test" strategy number in the 
implication table
+                        * Look up the "test" cmptype number in the implication 
table
                         */
                        if (refute_it)
-                               test_strategy = BT_refute_table[clause_strategy 
- 1][pred_strategy - 1];
+                               test_cmptype = RC_refute_table[clause_cmptype - 
1][pred_cmptype - 1];
                        else
-                               test_strategy = BT_implic_table[clause_strategy 
- 1][pred_strategy - 1];
+                               test_cmptype = RC_implic_table[clause_cmptype - 
1][pred_cmptype - 1];
 
-                       if (test_strategy == 0)
+                       if (test_cmptype == 0)
                        {
                                /* Can't determine implication using this 
interpretation */
                                continue;
                        }
 
                        /*
-                        * See if opfamily has an operator for the test 
strategy and the
+                        * See if opfamily has an operator for the test cmptype 
and the
                         * datatypes.
                         */
-                       if (test_strategy == BTNE)
+                       if (test_cmptype == RCNE)
                        {
-                               test_op = get_opfamily_member(opfamily_id,
-                                                                               
          pred_op_info->oprighttype,
-                                                                               
          clause_op_info->oprighttype,
-                                                                               
          BTEqualStrategyNumber);
+                               test_op = 
get_opfamily_member_for_cmptype(opfamily_id,
+                                                                               
                                  pred_op_info->oprighttype,
+                                                                               
                                  clause_op_info->oprighttype,
+                                                                               
                                  COMPARE_EQ);
                                if (OidIsValid(test_op))
                                        test_op = get_negator(test_op);
                        }
@@ -2233,7 +2234,7 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool 
refute_it)
                                test_op = get_opfamily_member(opfamily_id,
                                                                                
          pred_op_info->oprighttype,
                                                                                
          clause_op_info->oprighttype,
-                                                                               
          test_strategy);
+                                                                               
          test_cmptype);
                        }
 
                        if (!OidIsValid(test_op))
diff --git a/src/backend/parser/parse_clause.c 
b/src/backend/parser/parse_clause.c
index 2e64fcae7b2..bf50a0e656d 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -2915,7 +2915,6 @@ transformWindowDefinitions(ParseState *pstate,
                {
                        SortGroupClause *sortcl;
                        Node       *sortkey;
-                       int16           rangestrategy;
 
                        if (list_length(wc->orderClause) != 1)
                                ereport(ERROR,
@@ -2928,7 +2927,8 @@ transformWindowDefinitions(ParseState *pstate,
                        if (!get_ordering_op_properties(sortcl->sortop,
                                                                                
        &rangeopfamily,
                                                                                
        &rangeopcintype,
-                                                                               
        &rangestrategy))
+                                                                               
        NULL,
+                                                                               
        NULL))
                                elog(ERROR, "operator %u is not a valid 
ordering operator",
                                         sortcl->sortop);
                        /* Record properties of sort ordering */
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 9caf1e481a2..806ccb97537 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2832,7 +2832,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
        ListCell   *l,
                           *r;
        List      **opinfo_lists;
-       Bitmapset  *strats;
+       Bitmapset  *cmptypes;
        int                     nopers;
        int                     i;
 
@@ -2897,45 +2897,45 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 
        /*
         * Now we must determine which row comparison semantics (= <> < <= > >=)
-        * apply to this set of operators.  We look for btree opfamilies
-        * containing the operators, and see which interpretations (strategy
-        * numbers) exist for each operator.
+        * apply to this set of operators.  We look for opfamilies containing 
the
+        * operators, and see which interpretations (cmptypes) exist for each
+        * operator.
         */
        opinfo_lists = (List **) palloc(nopers * sizeof(List *));
-       strats = NULL;
+       cmptypes = NULL;
        i = 0;
        foreach(l, opexprs)
        {
                Oid                     opno = ((OpExpr *) lfirst(l))->opno;
-               Bitmapset  *this_strats;
+               Bitmapset  *this_cmptypes;
                ListCell   *j;
 
-               opinfo_lists[i] = get_op_btree_interpretation(opno);
+               opinfo_lists[i] = get_op_index_interpretation(opno);
 
                /*
-                * convert strategy numbers into a Bitmapset to make the 
intersection
+                * convert comparison types into a Bitmapset to make the 
intersection
                 * calculation easy.
                 */
-               this_strats = NULL;
+               this_cmptypes = NULL;
                foreach(j, opinfo_lists[i])
                {
-                       OpBtreeInterpretation *opinfo = lfirst(j);
+                       OpIndexInterpretation *opinfo = lfirst(j);
 
-                       this_strats = bms_add_member(this_strats, 
opinfo->strategy);
+                       this_cmptypes = bms_add_member(this_cmptypes, 
opinfo->cmptype);
                }
                if (i == 0)
-                       strats = this_strats;
+                       cmptypes = this_cmptypes;
                else
-                       strats = bms_int_members(strats, this_strats);
+                       cmptypes = bms_int_members(cmptypes, this_cmptypes);
                i++;
        }
 
        /*
         * If there are multiple common interpretations, we may use any one of
-        * them ... this coding arbitrarily picks the lowest btree strategy
+        * them ... this coding arbitrarily picks the lowest comparison type
         * number.
         */
-       i = bms_next_member(strats, -1);
+       i = bms_next_member(cmptypes, -1);
        if (i < 0)
        {
                /* No common interpretation, so fail */
@@ -2969,9 +2969,9 @@ make_row_comparison_op(ParseState *pstate, List *opname,
 
                foreach(j, opinfo_lists[i])
                {
-                       OpBtreeInterpretation *opinfo = lfirst(j);
+                       OpIndexInterpretation *opinfo = lfirst(j);
 
-                       if (opinfo->strategy == cmptype)
+                       if (opinfo->cmptype == cmptype)
                        {
                                opfamily = opinfo->opfamily_id;
                                break;
diff --git a/src/backend/partitioning/partprune.c 
b/src/backend/partitioning/partprune.c
index 48a35f763e9..12b5884bb9c 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -1455,6 +1455,7 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext 
*context,
                                                                                
   part_scheme->partopfamily[i],
                                                                                
   false,
                                                                                
   &pc->op_strategy,
+                                                                               
   NULL,        /* don't need cmptype */
                                                                                
   &lefttype,
                                                                                
   &righttype);
 
@@ -1982,7 +1983,9 @@ match_clause_to_partition_key(GeneratePruningStepsContext 
*context,
                if (op_in_opfamily(opno, partopfamily))
                {
                        get_op_opfamily_properties(opno, partopfamily, false,
-                                                                          
&op_strategy, &op_lefttype,
+                                                                          
&op_strategy,
+                                                                          
NULL,        /* don't need cmptype */
+                                                                          
&op_lefttype,
                                                                           
&op_righttype);
                }
                else
@@ -1996,7 +1999,9 @@ match_clause_to_partition_key(GeneratePruningStepsContext 
*context,
                        if (OidIsValid(negator) && op_in_opfamily(negator, 
partopfamily))
                        {
                                get_op_opfamily_properties(negator, 
partopfamily, false,
-                                                                               
   &op_strategy, &op_lefttype,
+                                                                               
   &op_strategy,
+                                                                               
   NULL,        /* don't need cmptype */
+                                                                               
   &op_lefttype,
                                                                                
   &op_righttype);
                                if (op_strategy == BTEqualStrategyNumber)
                                        is_opne_listp = true;   /* bingo */
@@ -2211,7 +2216,9 @@ match_clause_to_partition_key(GeneratePruningStepsContext 
*context,
                                                        righttype;
 
                                get_op_opfamily_properties(negator, 
partopfamily,
-                                                                               
   false, &strategy,
+                                                                               
   false,
+                                                                               
   &strategy,
+                                                                               
   NULL,        /* don't need cmptype */
                                                                                
   &lefttype, &righttype);
                                if (strategy != BTEqualStrategyNumber)
                                        return PARTCLAUSE_NOMATCH;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 5b35debc8ff..8c722cf46ce 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2954,7 +2954,7 @@ scalargejoinsel(PG_FUNCTION_ARGS)
  */
 void
 mergejoinscansel(PlannerInfo *root, Node *clause,
-                                Oid opfamily, int strategy, bool nulls_first,
+                                Oid opfamily, CompareType cmptype, bool 
nulls_first,
                                 Selectivity *leftstart, Selectivity *leftend,
                                 Selectivity *rightstart, Selectivity *rightend)
 {
@@ -2963,6 +2963,7 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
        VariableStatData leftvar,
                                rightvar;
        int                     op_strategy;
+       CompareType op_cmptype;
        Oid                     op_lefttype;
        Oid                     op_righttype;
        Oid                     opno,
@@ -3004,9 +3005,10 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
        /* Extract the operator's declared left/right datatypes */
        get_op_opfamily_properties(opno, opfamily, false,
                                                           &op_strategy,
+                                                          &op_cmptype,
                                                           &op_lefttype,
                                                           &op_righttype);
-       Assert(op_strategy == BTEqualStrategyNumber);
+       Assert(op_cmptype == COMPARE_EQ);
 
        /*
         * Look up the various operators we need.  If we don't find them all, it
@@ -3015,19 +3017,17 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
         * Note: we expect that pg_statistic histograms will be sorted by the 
'<'
         * operator, regardless of which sort direction we are considering.
         */
-       switch (strategy)
+       switch (cmptype)
        {
-               case BTLessStrategyNumber:
+               case COMPARE_LT:
                        isgt = false;
                        if (op_lefttype == op_righttype)
                        {
                                /* easy case */
-                               ltop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTLessStrategyNumber);
-                               leop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTLessEqualStrategyNumber);
+                               ltop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_LT);
+                               leop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_LE);
                                lsortop = ltop;
                                rsortop = ltop;
                                lstatop = lsortop;
@@ -3037,75 +3037,58 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
                        }
                        else
                        {
-                               ltop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTLessStrategyNumber);
-                               leop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTLessEqualStrategyNumber);
-                               lsortop = get_opfamily_member(opfamily,
-                                                                               
          op_lefttype, op_lefttype,
-                                                                               
          BTLessStrategyNumber);
-                               rsortop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_righttype,
-                                                                               
          BTLessStrategyNumber);
+                               ltop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_LT);
+                               leop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_LE);
+                               lsortop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                                  op_lefttype, COMPARE_LT);
+                               rsortop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_righttype, COMPARE_LT);
                                lstatop = lsortop;
                                rstatop = rsortop;
-                               revltop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_lefttype,
-                                                                               
          BTLessStrategyNumber);
-                               revleop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_lefttype,
-                                                                               
          BTLessEqualStrategyNumber);
+                               revltop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_lefttype, COMPARE_LT);
+                               revleop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_lefttype, COMPARE_LE);
                        }
                        break;
-               case BTGreaterStrategyNumber:
+               case COMPARE_GT:
                        /* descending-order case */
                        isgt = true;
                        if (op_lefttype == op_righttype)
                        {
                                /* easy case */
-                               ltop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTGreaterStrategyNumber);
-                               leop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTGreaterEqualStrategyNumber);
+                               ltop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype, op_righttype,
+                                                                               
                           COMPARE_GT);
+                               leop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype, op_righttype,
+                                                                               
                           COMPARE_GE);
                                lsortop = ltop;
                                rsortop = ltop;
-                               lstatop = get_opfamily_member(opfamily,
-                                                                               
          op_lefttype, op_lefttype,
-                                                                               
          BTLessStrategyNumber);
+                               lstatop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype, op_lefttype,
+                                                                               
                                  COMPARE_LT);
                                rstatop = lstatop;
                                revltop = ltop;
                                revleop = leop;
                        }
                        else
                        {
-                               ltop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTGreaterStrategyNumber);
-                               leop = get_opfamily_member(opfamily,
-                                                                               
   op_lefttype, op_righttype,
-                                                                               
   BTGreaterEqualStrategyNumber);
-                               lsortop = get_opfamily_member(opfamily,
-                                                                               
          op_lefttype, op_lefttype,
-                                                                               
          BTGreaterStrategyNumber);
-                               rsortop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_righttype,
-                                                                               
          BTGreaterStrategyNumber);
-                               lstatop = get_opfamily_member(opfamily,
-                                                                               
          op_lefttype, op_lefttype,
-                                                                               
          BTLessStrategyNumber);
-                               rstatop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_righttype,
-                                                                               
          BTLessStrategyNumber);
-                               revltop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_lefttype,
-                                                                               
          BTGreaterStrategyNumber);
-                               revleop = get_opfamily_member(opfamily,
-                                                                               
          op_righttype, op_lefttype,
-                                                                               
          BTGreaterEqualStrategyNumber);
+                               ltop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_GT);
+                               leop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                           op_righttype, COMPARE_GE);
+                               lsortop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                                  op_lefttype, COMPARE_GT);
+                               rsortop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_righttype, COMPARE_GT);
+                               lstatop = 
get_opfamily_member_for_cmptype(opfamily, op_lefttype,
+                                                                               
                                  op_lefttype, COMPARE_LT);
+                               rstatop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_righttype, COMPARE_LT);
+                               revltop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_lefttype, COMPARE_GT);
+                               revleop = 
get_opfamily_member_for_cmptype(opfamily, op_righttype,
+                                                                               
                                  op_lefttype, COMPARE_GE);
                        }
                        break;
                default:
@@ -6327,10 +6310,7 @@ get_actual_variable_range(PlannerInfo *root, 
VariableStatData *vardata,
        {
                IndexOptInfo *index = (IndexOptInfo *) lfirst(lc);
                ScanDirection indexscandir;
-
-               /* Ignore non-btree indexes */
-               if (index->relam != BTREE_AM_OID)
-                       continue;
+               StrategyNumber strategy;
 
                /*
                 * Ignore partial indexes --- we only want stats that cover the 
entire
@@ -6354,15 +6334,16 @@ get_actual_variable_range(PlannerInfo *root, 
VariableStatData *vardata,
                        continue;                       /* test first 'cause 
it's cheapest */
                if (!match_index_to_operand(vardata->var, 0, index))
                        continue;
-               switch (get_op_opfamily_strategy(sortop, 
index->sortopfamily[0]))
+               strategy = get_op_opfamily_strategy(sortop, 
index->sortopfamily[0]);
+               switch (IndexAmTranslateStrategy(strategy, index->relam, 
index->sortopfamily[0], true))
                {
-                       case BTLessStrategyNumber:
+                       case COMPARE_LT:
                                if (index->reverse_sort[0])
                                        indexscandir = BackwardScanDirection;
                                else
                                        indexscandir = ForwardScanDirection;
                                break;
-                       case BTGreaterStrategyNumber:
+                       case COMPARE_GT:
                                if (index->reverse_sort[0])
                                        indexscandir = ForwardScanDirection;
                                else
@@ -6602,13 +6583,17 @@ get_actual_variable_endpoint(Relation heapRel,
                }
 
                /*
-                * We expect that btree will return data in IndexTuple not 
HeapTuple
-                * format.  It's not lossy either.
+                * We expect that the index will return data in IndexTuple not
+                * HeapTuple format.
                 */
                if (!index_scan->xs_itup)
                        elog(ERROR, "no data returned for index-only scan");
+
+               /*
+                * We do not yet support recheck here.
+                */
                if (index_scan->xs_recheck)
-                       elog(ERROR, "unexpected recheck indication from btree");
+                       break;
 
                /* OK to deconstruct the index tuple */
                index_deform_tuple(index_scan->xs_itup,
@@ -7544,7 +7529,9 @@ gincost_pattern(IndexOptInfo *index, int indexcol,
         * find a matching pg_amop entry.)
         */
        get_op_opfamily_properties(clause_op, index->opfamily[indexcol], false,
-                                                          &strategy_op, 
&lefttype, &righttype);
+                                                          &strategy_op,
+                                                          NULL,        /* 
don't need cmptype */
+                                                          &lefttype, 
&righttype);
 
        /*
         * GIN always uses the "default" support functions, which are those with
diff --git a/src/backend/utils/cache/lsyscache.c 
b/src/backend/utils/cache/lsyscache.c
index 82031c1e8e5..9f55a97c93c 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -136,6 +136,7 @@ get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
 void
 get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
                                                   int *strategy,
+                                                  CompareType *cmptype,
                                                   Oid *lefttype,
                                                   Oid *righttype)
 {
@@ -150,9 +151,17 @@ get_op_opfamily_properties(Oid opno, Oid opfamily, bool 
ordering_op,
                elog(ERROR, "operator %u is not a member of opfamily %u",
                         opno, opfamily);
        amop_tup = (Form_pg_amop) GETSTRUCT(tp);
-       *strategy = amop_tup->amopstrategy;
-       *lefttype = amop_tup->amoplefttype;
-       *righttype = amop_tup->amoprighttype;
+       if (strategy)
+               *strategy = amop_tup->amopstrategy;
+       if (cmptype)
+               *cmptype = IndexAmTranslateStrategy(amop_tup->amopstrategy,
+                                                                               
        amop_tup->amopmethod,
+                                                                               
        opfamily,
+                                                                               
        true);
+       if (lefttype)
+               *lefttype = amop_tup->amoplefttype;
+       if (righttype)
+               *righttype = amop_tup->amoprighttype;
        ReleaseSysCache(tp);
 }
 
@@ -208,9 +217,9 @@ get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, 
Oid righttype,
 
 /*
  * get_ordering_op_properties
- *             Given the OID of an ordering operator (a btree "<" or ">" 
operator),
- *             determine its opfamily, its declared input datatype, and its
- *             strategy number (BTLessStrategyNumber or 
BTGreaterStrategyNumber).
+ *             Given the OID of an ordering operator (a "<" or ">" operator),
+ *             determine its opmethod, its opfamily, its declared input 
datatype, its
+ *             strategy number, and its row comparison type.
  *
  * Returns true if successful, false if no matching pg_amop entry exists.
  * (This indicates that the operator is not a valid ordering operator.)
@@ -228,16 +237,21 @@ get_opfamily_member_for_cmptype(Oid opfamily, Oid 
lefttype, Oid righttype,
  */
 bool
 get_ordering_op_properties(Oid opno,
-                                                  Oid *opfamily, Oid 
*opcintype, int16 *strategy)
+                                                  Oid *opfamily, Oid 
*opcintype, int16 *strategy, CompareType *cmptype)
 {
        bool            result = false;
        CatCList   *catlist;
        int                     i;
 
        /* ensure outputs are initialized on failure */
-       *opfamily = InvalidOid;
-       *opcintype = InvalidOid;
-       *strategy = 0;
+       if (opfamily)
+               *opfamily = InvalidOid;
+       if (opcintype)
+               *opcintype = InvalidOid;
+       if (strategy)
+               *strategy = InvalidStrategy;
+       if (cmptype)
+               *cmptype = COMPARE_INVALID;
 
        /*
         * Search pg_amop to see if the target operator is registered as the "<"
@@ -249,21 +263,30 @@ get_ordering_op_properties(Oid opno,
        {
                HeapTuple       tuple = &catlist->members[i]->tuple;
                Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
+               CompareType am_cmptype;
 
-               /* must be btree */
-               if (aform->amopmethod != BTREE_AM_OID)
-                       continue;
+               am_cmptype = IndexAmTranslateStrategy(aform->amopstrategy,
+                                                                               
          aform->amopmethod,
+                                                                               
          aform->amopfamily,
+                                                                               
          true);
 
-               if (aform->amopstrategy == BTLessStrategyNumber ||
-                       aform->amopstrategy == BTGreaterStrategyNumber)
+               if (am_cmptype == COMPARE_LT || am_cmptype == COMPARE_GT)
                {
                        /* Found it ... should have consistent input types */
                        if (aform->amoplefttype == aform->amoprighttype)
                        {
                                /* Found a suitable opfamily, return info */
-                               *opfamily = aform->amopfamily;
-                               *opcintype = aform->amoplefttype;
-                               *strategy = aform->amopstrategy;
+                               if (opfamily)
+                                       *opfamily = aform->amopfamily;
+                               if (opcintype)
+                                       *opcintype = aform->amoplefttype;
+                               if (strategy)
+                                       *strategy = aform->amopstrategy;
+                               if (cmptype)
+                                       *cmptype = 
IndexAmTranslateStrategy(aform->amopstrategy,
+                                                                               
                                aform->amopmethod,
+                                                                               
                                aform->amopfamily,
+                                                                               
                                false);
                                result = true;
                                break;
                        }
@@ -277,7 +300,7 @@ get_ordering_op_properties(Oid opno,
 
 /*
  * get_equality_op_for_ordering_op
- *             Get the OID of the datatype-specific btree equality operator
+ *             Get the OID of the datatype-specific equality operator
  *             associated with an ordering operator (a "<" or ">" operator).
  *
  * If "reverse" isn't NULL, also set *reverse to false if the operator is "<",
@@ -293,18 +316,19 @@ get_equality_op_for_ordering_op(Oid opno, bool *reverse)
        Oid                     opfamily;
        Oid                     opcintype;
        int16           strategy;
+       CompareType cmptype;
 
        /* Find the operator in pg_amop */
-       if (get_ordering_op_properties(opno,
-                                                                  &opfamily, 
&opcintype, &strategy))
+       if (get_ordering_op_properties(opno, &opfamily,
+                                                                  &opcintype, 
&strategy, &cmptype))
        {
                /* Found a suitable opfamily, get matching equality operator */
-               result = get_opfamily_member(opfamily,
-                                                                        
opcintype,
-                                                                        
opcintype,
-                                                                        
BTEqualStrategyNumber);
+               result = get_opfamily_member_for_cmptype(opfamily,
+                                                                               
                 opcintype,
+                                                                               
                 opcintype,
+                                                                               
                 COMPARE_EQ);
                if (reverse)
-                       *reverse = (strategy == BTGreaterStrategyNumber);
+                       *reverse = (cmptype == COMPARE_GT);
        }
 
        return result;
@@ -312,7 +336,7 @@ get_equality_op_for_ordering_op(Oid opno, bool *reverse)
 
 /*
  * get_ordering_op_for_equality_op
- *             Get the OID of a datatype-specific btree "less than" ordering 
operator
+ *             Get the OID of a datatype-specific "less than" ordering operator
  *             associated with an equality operator.  (If there are multiple
  *             possibilities, assume any one will do.)
  *
@@ -341,20 +365,25 @@ get_ordering_op_for_equality_op(Oid opno, bool 
use_lhs_type)
        {
                HeapTuple       tuple = &catlist->members[i]->tuple;
                Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
+               IndexAmRoutine *amroutine = 
GetIndexAmRoutineByAmId(aform->amopmethod, false);
+               CompareType cmptype;
 
-               /* must be btree */
-               if (aform->amopmethod != BTREE_AM_OID)
+               if (!amroutine->amcanorder)
                        continue;
 
-               if (aform->amopstrategy == BTEqualStrategyNumber)
+               cmptype = IndexAmTranslateStrategy(aform->amopstrategy,
+                                                                               
   aform->amopmethod,
+                                                                               
   aform->amopfamily,
+                                                                               
   true);
+               if (cmptype == COMPARE_EQ)
                {
                        /* Found a suitable opfamily, get matching ordering 
operator */
                        Oid                     typid;
 
                        typid = use_lhs_type ? aform->amoplefttype : 
aform->amoprighttype;
-                       result = get_opfamily_member(aform->amopfamily,
-                                                                               
 typid, typid,
-                                                                               
 BTLessStrategyNumber);
+                       result = 
get_opfamily_member_for_cmptype(aform->amopfamily,
+                                                                               
                         typid, typid,
+                                                                               
                         COMPARE_LT);
                        if (OidIsValid(result))
                                break;
                        /* failure probably shouldn't happen, but keep looking 
if so */
@@ -369,7 +398,7 @@ get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
 /*
  * get_mergejoin_opfamilies
  *             Given a putatively mergejoinable operator, return a list of the 
OIDs
- *             of the btree opfamilies in which it represents equality.
+ *             of the amcanorder opfamilies in which it represents equality.
  *
  * It is possible (though at present unusual) for an operator to be equality
  * in more than one opfamily, hence the result is a list.  This also lets us
@@ -394,7 +423,7 @@ get_mergejoin_opfamilies(Oid opno)
 
        /*
         * Search pg_amop to see if the target operator is registered as the "="
-        * operator of any btree opfamily.
+        * operator of any opfamily of an ordering index type.
         */
        catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno));
 
@@ -403,10 +432,39 @@ get_mergejoin_opfamilies(Oid opno)
                HeapTuple       tuple = &catlist->members[i]->tuple;
                Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
 
-               /* must be btree equality */
-               if (aform->amopmethod == BTREE_AM_OID &&
-                       aform->amopstrategy == BTEqualStrategyNumber)
-                       result = lappend_oid(result, aform->amopfamily);
+               /*
+                * This function is quite performance-critical to planning even 
the
+                * most basic queries.  So we're hardcoding the results from the
+                * built-in index types.  Note that to get that effect we also 
need to
+                * hardcode the negative results from the built-in non-btree 
index
+                * types, since you'll usually get a few hits for those as 
well.  It
+                * would be nice to organize and cache this a bit differently 
to avoid
+                * the hardcoding.
+                */
+               switch (aform->amopmethod)
+               {
+                       case BTREE_AM_OID:
+                               if (aform->amopstrategy == 
BTEqualStrategyNumber)
+                                       result = lappend_oid(result, 
aform->amopfamily);
+                               break;
+                       case HASH_AM_OID:
+                       case GIST_AM_OID:
+                       case GIN_AM_OID:
+                       case SPGIST_AM_OID:
+                       case BRIN_AM_OID:
+                               break;
+                       default:
+                               {
+                                       IndexAmRoutine *amroutine = 
GetIndexAmRoutineByAmId(aform->amopmethod, false);
+
+                                       if (amroutine->amcanorder &&
+                                               
IndexAmTranslateStrategy(aform->amopstrategy,
+                                                                               
                 aform->amopmethod,
+                                                                               
                 aform->amopfamily,
+                                                                               
                 true) == COMPARE_EQ)
+                                               result = lappend_oid(result, 
aform->amopfamily);
+                               }
+               }
        }
 
        ReleaseSysCacheList(catlist);
@@ -611,20 +669,20 @@ get_op_hash_functions(Oid opno,
 }
 
 /*
- * get_op_btree_interpretation
- *             Given an operator's OID, find out which btree opfamilies it 
belongs to,
+ * get_op_index_interpretation
+ *             Given an operator's OID, find out which amcanorder opfamilies 
it belongs to,
  *             and what properties it has within each one.  The results are 
returned
- *             as a palloc'd list of OpBtreeInterpretation structs.
+ *             as a palloc'd list of OpIndexInterpretation structs.
  *
  * In addition to the normal btree operators, we consider a <> operator to be
  * a "member" of an opfamily if its negator is an equality operator of the
  * opfamily.  COMPARE_NE is returned as the strategy number for this case.
  */
 List *
-get_op_btree_interpretation(Oid opno)
+get_op_index_interpretation(Oid opno)
 {
        List       *result = NIL;
-       OpBtreeInterpretation *thisresult;
+       OpIndexInterpretation *thisresult;
        CatCList   *catlist;
        int                     i;
 
@@ -637,20 +695,27 @@ get_op_btree_interpretation(Oid opno)
        {
                HeapTuple       op_tuple = &catlist->members[i]->tuple;
                Form_pg_amop op_form = (Form_pg_amop) GETSTRUCT(op_tuple);
-               StrategyNumber op_strategy;
+               IndexAmRoutine *amroutine = 
GetIndexAmRoutineByAmId(op_form->amopmethod, false);
+               CompareType cmptype;
 
-               /* must be btree */
-               if (op_form->amopmethod != BTREE_AM_OID)
+               /* must be ordering index */
+               if (!amroutine->amcanorder)
                        continue;
 
-               /* Get the operator's btree strategy number */
-               op_strategy = (StrategyNumber) op_form->amopstrategy;
-               Assert(op_strategy >= 1 && op_strategy <= 5);
+               /* Get the operator's row comparision type */
+               cmptype = IndexAmTranslateStrategy(op_form->amopstrategy,
+                                                                               
   op_form->amopmethod,
+                                                                               
   op_form->amopfamily,
+                                                                               
   true);
+
+               /* should not happen */
+               if (cmptype == COMPARE_INVALID)
+                       continue;
 
-               thisresult = (OpBtreeInterpretation *)
-                       palloc(sizeof(OpBtreeInterpretation));
+               thisresult = (OpIndexInterpretation *)
+                       palloc(sizeof(OpIndexInterpretation));
                thisresult->opfamily_id = op_form->amopfamily;
-               thisresult->strategy = op_strategy;
+               thisresult->cmptype = cmptype;
                thisresult->oplefttype = op_form->amoplefttype;
                thisresult->oprighttype = op_form->amoprighttype;
                result = lappend(result, thisresult);
@@ -675,25 +740,28 @@ get_op_btree_interpretation(Oid opno)
                        {
                                HeapTuple       op_tuple = 
&catlist->members[i]->tuple;
                                Form_pg_amop op_form = (Form_pg_amop) 
GETSTRUCT(op_tuple);
-                               StrategyNumber op_strategy;
+                               IndexAmRoutine *amroutine = 
GetIndexAmRoutineByAmId(op_form->amopmethod, false);
+                               CompareType cmptype;
 
-                               /* must be btree */
-                               if (op_form->amopmethod != BTREE_AM_OID)
+                               /* must be ordering index */
+                               if (!amroutine->amcanorder)
                                        continue;
 
-                               /* Get the operator's btree strategy number */
-                               op_strategy = (StrategyNumber) 
op_form->amopstrategy;
-                               Assert(op_strategy >= 1 && op_strategy <= 5);
+                               /* Get the operator's row comparision type */
+                               cmptype = 
IndexAmTranslateStrategy(op_form->amopstrategy,
+                                                                               
                   op_form->amopmethod,
+                                                                               
                   op_form->amopfamily,
+                                                                               
                   true);
 
                                /* Only consider negators that are = */
-                               if (op_strategy != BTEqualStrategyNumber)
+                               if (cmptype != COMPARE_EQ)
                                        continue;
 
-                               /* OK, report it with "strategy" COMPARE_NE */
-                               thisresult = (OpBtreeInterpretation *)
-                                       palloc(sizeof(OpBtreeInterpretation));
+                               /* OK, report it as COMPARE_NE */
+                               thisresult = (OpIndexInterpretation *)
+                                       palloc(sizeof(OpIndexInterpretation));
                                thisresult->opfamily_id = op_form->amopfamily;
-                               thisresult->strategy = COMPARE_NE;
+                               thisresult->cmptype = COMPARE_NE;
                                thisresult->oplefttype = op_form->amoplefttype;
                                thisresult->oprighttype = 
op_form->amoprighttype;
                                result = lappend(result, thisresult);
diff --git a/src/backend/utils/sort/sortsupport.c 
b/src/backend/utils/sort/sortsupport.c
index 0b4f08ed2ec..bfa31fa2225 100644
--- a/src/backend/utils/sort/sortsupport.c
+++ b/src/backend/utils/sort/sortsupport.c
@@ -135,16 +135,16 @@ PrepareSortSupportFromOrderingOp(Oid orderingOp, 
SortSupport ssup)
 {
        Oid                     opfamily;
        Oid                     opcintype;
-       int16           strategy;
+       CompareType cmptype;
 
        Assert(ssup->comparator == NULL);
 
        /* Find the operator in pg_amop */
        if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype,
-                                                                       
&strategy))
+                                                                       NULL, 
&cmptype))
                elog(ERROR, "operator %u is not a valid ordering operator",
                         orderingOp);
-       ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
+       ssup->ssup_reverse = (cmptype == COMPARE_GT);
 
        FinishSortSupportFunction(opfamily, opcintype, ssup);
 }
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index c24a1fc8514..9525ad0b150 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1492,9 +1492,7 @@ typedef struct EquivalenceMember
  * equivalent and closely-related orderings. (See optimizer/README for more
  * information.)
  *
- * Note: pk_strategy is either BTLessStrategyNumber (for ASC) or
- * BTGreaterStrategyNumber (for DESC).  We assume that all ordering-capable
- * index types will use btree-compatible strategy numbers.
+ * Note: pk_strategy is either COMPARE_LT (for ASC) or COMPARE_GT (for DESC).
  */
 typedef struct PathKey
 {
@@ -1504,8 +1502,8 @@ typedef struct PathKey
 
        /* the value that is ordered */
        EquivalenceClass *pk_eclass pg_node_attr(copy_as_scalar, 
equal_as_scalar);
-       Oid                     pk_opfamily;    /* btree opfamily defining the 
ordering */
-       int                     pk_strategy;    /* sort direction (ASC or DESC) 
*/
+       Oid                     pk_opfamily;    /* index opfamily defining the 
ordering */
+       CompareType pk_cmptype;         /* sort direction (ASC or DESC) */
        bool            pk_nulls_first; /* do NULLs come before normal values? 
*/
 } PathKey;
 
@@ -2770,9 +2768,9 @@ typedef struct RestrictInfo
 typedef struct MergeScanSelCache
 {
        /* Ordering details (cache lookup key) */
-       Oid                     opfamily;               /* btree opfamily 
defining the ordering */
+       Oid                     opfamily;               /* index opfamily 
defining the ordering */
        Oid                     collation;              /* collation for the 
ordering */
-       int                     strategy;               /* sort direction (ASC 
or DESC) */
+       CompareType cmptype;            /* sort direction (ASC or DESC) */
        bool            nulls_first;    /* do NULLs come before normal values? 
*/
        /* Results */
        Selectivity leftstartsel;       /* first-join fraction for clause left 
side */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index bc5dfd7db41..17879fc461a 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -270,7 +270,7 @@ extern bool has_useful_pathkeys(PlannerInfo *root, 
RelOptInfo *rel);
 extern List *append_pathkeys(List *target, List *source);
 extern PathKey *make_canonical_pathkey(PlannerInfo *root,
                                                                           
EquivalenceClass *eclass, Oid opfamily,
-                                                                          int 
strategy, bool nulls_first);
+                                                                          
CompareType cmptype, bool nulls_first);
 extern void add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
                                                                        List 
*live_childrels);
 
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index d42380a0d46..a7bdd2531dc 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -21,14 +21,14 @@
 /* avoid including subscripting.h here */
 struct SubscriptRoutines;
 
-/* Result list element for get_op_btree_interpretation */
-typedef struct OpBtreeInterpretation
+/* Result list element for get_op_index_interpretation */
+typedef struct OpIndexInterpretation
 {
-       Oid                     opfamily_id;    /* btree opfamily containing 
operator */
-       int                     strategy;               /* its strategy number 
*/
+       Oid                     opfamily_id;    /* opfamily containing operator 
*/
+       CompareType cmptype;            /* its generic comparison type */
        Oid                     oplefttype;             /* declared left input 
datatype */
        Oid                     oprighttype;    /* declared right input 
datatype */
-} OpBtreeInterpretation;
+} OpIndexInterpretation;
 
 /* I/O function selector for get_type_io_data */
 typedef enum IOFuncSelector
@@ -71,6 +71,7 @@ extern int    get_op_opfamily_strategy(Oid opno, Oid 
opfamily);
 extern Oid     get_op_opfamily_sortfamily(Oid opno, Oid opfamily);
 extern void get_op_opfamily_properties(Oid opno, Oid opfamily, bool 
ordering_op,
                                                                           int 
*strategy,
+                                                                          
CompareType *cmptype,
                                                                           Oid 
*lefttype,
                                                                           Oid 
*righttype);
 extern Oid     get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
@@ -78,7 +79,7 @@ extern Oid    get_opfamily_member(Oid opfamily, Oid lefttype, 
Oid righttype,
 extern Oid     get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid 
righttype,
                                                                                
        CompareType cmptype);
 extern bool get_ordering_op_properties(Oid opno,
-                                                                          Oid 
*opfamily, Oid *opcintype, int16 *strategy);
+                                                                          Oid 
*opfamily, Oid *opcintype, int16 *strategy, CompareType *cmptype);
 extern Oid     get_equality_op_for_ordering_op(Oid opno, bool *reverse);
 extern Oid     get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type);
 extern List *get_mergejoin_opfamilies(Oid opno);
@@ -86,7 +87,7 @@ extern bool get_compatible_hash_operators(Oid opno,
                                                                                
  Oid *lhs_opno, Oid *rhs_opno);
 extern bool get_op_hash_functions(Oid opno,
                                                                  RegProcedure 
*lhs_procno, RegProcedure *rhs_procno);
-extern List *get_op_btree_interpretation(Oid opno);
+extern List *get_op_index_interpretation(Oid opno);
 extern bool equality_ops_are_compatible(Oid opno1, Oid opno2);
 extern bool comparison_ops_are_compatible(Oid opno1, Oid opno2);
 extern Oid     get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index 82ac8c6d9da..013049b3098 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.h
@@ -210,7 +210,7 @@ extern Selectivity rowcomparesel(PlannerInfo *root,
                                                                 int varRelid, 
JoinType jointype, SpecialJoinInfo *sjinfo);
 
 extern void mergejoinscansel(PlannerInfo *root, Node *clause,
-                                                        Oid opfamily, int 
strategy, bool nulls_first,
+                                                        Oid opfamily, 
CompareType cmptype, bool nulls_first,
                                                         Selectivity 
*leftstart, Selectivity *leftend,
                                                         Selectivity 
*rightstart, Selectivity *rightend);
 
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index b66cecd8799..00877ead7df 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1785,11 +1785,11 @@ OnConflictAction
 OnConflictClause
 OnConflictExpr
 OnConflictSetState
-OpBtreeInterpretation
 OpClassCacheEnt
 OpExpr
 OpFamilyMember
 OpFamilyOpFuncGroup
+OpIndexInterpretation
 OpclassInfo
 Operator
 OperatorElement

base-commit: af0c248557aecb335462d980cb7319bdf85a5c66
-- 
2.49.0

Reply via email to