Convert PathKey to use CompareType
authorPeter Eisentraut <[email protected]>
Fri, 4 Apr 2025 09:13:54 +0000 (11:13 +0200)
committerPeter Eisentraut <[email protected]>
Fri, 4 Apr 2025 09:22:20 +0000 (11:22 +0200)
Change the PathKey struct to use CompareType to record the sort
direction instead of hardcoding btree strategy numbers.  The
CompareType is then converted to the index-type-specific strategy when
the plan is created.

This reduces the number of places btree strategy numbers are
hardcoded, and it's a self-contained subset of a larger effort to
allow non-btree indexes to behave like btrees.

Author: Mark Dilger <[email protected]>
Co-authored-by: Peter Eisentraut <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com

contrib/postgres_fdw/deparse.c
contrib/postgres_fdw/postgres_fdw.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/pathkeys.c
src/backend/optimizer/plan/createplan.c
src/include/nodes/pathnodes.h
src/include/optimizer/paths.h

index 6e7dc3d2df9820bbcb7019879720a462a37a25c3..d9970dd6753364c83db076a9deb874b91b68aa16 100644 (file)
@@ -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);
index ac14c06c71518039e0cbb1f5d39a91e485d5c2dd..b4e0e60928b930b16962d51822e440c098503bd7 100644 (file)
@@ -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));
index c474c7a06af459f5bff91ae002879e2e666f4647..60b0fcfb6be542552903f00643de82ac1e91cb80 100644 (file)
@@ -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;
index 6386ce8225301d72271c9d3ba65ab931d9cbbc63..d8865f8c0c6fe47cc3fd693e2f5c35dfe8f714a6 100644 (file)
@@ -3817,8 +3817,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 */
index 154eb505d755a48019ff9c97010771f72c9c2251..6fac08cb0d9d9cec086721e60f2ed548c5ba8b28 100644 (file)
@@ -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
@@ -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);
 }
 
 /*
@@ -1118,7 +1118,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 +1200,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 +1816,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 +1909,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 +2134,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);
 }
 
 /*
index 75e2b0b9036006632b7f883f04cccbe9ac9dd197..359db4ba9ddf76730e6be64d330cc7109c96ee07 100644 (file)
@@ -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 */
index 6e03496089619ed030a25292ca4dfec13be6f81c..4c466f76778370294f83d819689290510fb767ab 100644 (file)
@@ -1506,9 +1506,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
 {
@@ -1518,8 +1516,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;
 
@@ -2784,9 +2782,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 */
index 16dc4d5ee8216de0216dd8315eaeb897f168ff96..b1a76816442334ca6335534f8ea079afdd9ffd76 100644 (file)
@@ -272,7 +272,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);