v20-0012-Use-CompareType-more-and-StrategyNumber-less.patch.no-cfbot
application/octet-stream
Filename: v20-0012-Use-CompareType-more-and-StrategyNumber-less.patch.no-cfbot
Type: application/octet-stream
Part: 1
From 00dc3e0cae56d8c6a9b38afb43ad4d8dd7ea4267 Mon Sep 17 00:00:00 2001
From: Andrew Dunstan <andrew@dunslane.net>
Date: Tue, 26 Nov 2024 08:53:22 -0500
Subject: [PATCH v20 12/16] Use CompareType more and StrategyNumber less
Reduce the number of places that hardcode a Btree strategy number by
instead using comparison types.
Rather than hardcoding BTREE_AM_OID in get_ordering_op_properties,
add a parameter to filter the index access methods to consider. For
mainline code, callers now pass BTREE_AM_OID for this filter, which
means the behavior (and the regression test expected output) is
unchanged.
Author: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
---
contrib/postgres_fdw/postgres_fdw.c | 4 +-
src/backend/commands/explain.c | 3 +-
src/backend/commands/indexcmds.c | 5 +-
src/backend/commands/matview.c | 6 +-
src/backend/executor/execExpr.c | 2 +
src/backend/executor/nodeIncrementalSort.c | 3 +-
src/backend/executor/nodeIndexscan.c | 14 +-
src/backend/executor/nodeMergejoin.c | 5 +-
src/backend/optimizer/path/allpaths.c | 25 ++--
src/backend/optimizer/path/costsize.c | 6 +
src/backend/optimizer/path/equivclass.c | 4 +-
src/backend/optimizer/path/indxpath.c | 26 +++-
src/backend/optimizer/path/pathkeys.c | 97 ++++++++++---
src/backend/optimizer/plan/createplan.c | 13 +-
src/backend/optimizer/plan/planagg.c | 4 +-
src/backend/optimizer/plan/planner.c | 13 +-
src/backend/optimizer/prep/prepunion.c | 19 ++-
src/backend/optimizer/util/plancat.c | 31 ++--
src/backend/optimizer/util/predtest.c | 18 ++-
src/backend/parser/parse_clause.c | 8 +-
src/backend/parser/parse_expr.c | 6 +-
src/backend/partitioning/partprune.c | 17 ++-
src/backend/utils/adt/network.c | 12 +-
src/backend/utils/adt/selfuncs.c | 120 +++++++--------
src/backend/utils/cache/lsyscache.c | 161 ++++++++++++++++-----
src/backend/utils/cache/typcache.c | 15 +-
src/backend/utils/sort/sortsupport.c | 9 +-
src/include/nodes/pathnodes.h | 10 +-
src/include/optimizer/paths.h | 8 +-
src/include/utils/lsyscache.h | 29 +++-
src/include/utils/selfuncs.h | 9 +-
src/tools/pgindent/typedefs.list | 2 +-
32 files changed, 475 insertions(+), 229 deletions(-)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index de43727a2a0..6db93fc4b29 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -994,8 +994,10 @@ 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,
+ get_opfamily_method(linitial_oid(cur_ec->ec_opfamilies)),
linitial_oid(cur_ec->ec_opfamilies),
- BTLessStrategyNumber,
+ InvalidStrategy,
+ COMPARE_LT,
false);
useful_pathkeys_list = lappend(useful_pathkeys_list,
list_make1(pathkey));
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index c0d614866a9..72354b9ec68 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -14,6 +14,7 @@
#include "postgres.h"
#include "access/xact.h"
+#include "catalog/pg_am.h" /* for BTREE_AM_OID */
#include "catalog/pg_type.h"
#include "commands/createas.h"
#include "commands/defrem.h"
@@ -3037,7 +3038,7 @@ show_sortorder_options(StringInfo buf, Node *sortexpr,
elog(ERROR, "cache lookup failed for operator %u", sortOperator);
appendStringInfo(buf, " USING %s", opname);
/* Determine whether operator would be considered ASC or DESC */
- (void) get_equality_op_for_ordering_op(sortOperator, &reverse);
+ (void) get_equality_op_for_ordering_op(sortOperator, BTREE_AM_OID, &reverse);
}
/* Add NULLS FIRST/LAST only if it wouldn't be default */
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index c92f5620ec1..87124b02d45 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -1057,10 +1057,11 @@ DefineIndex(Oid tableId,
Oid idx_eqop = InvalidOid;
if (stmt->unique && !stmt->iswithoutoverlaps)
- idx_eqop = get_opfamily_member(idx_opfamily,
+ idx_eqop = get_opmethod_member(InvalidOid,
+ idx_opfamily,
idx_opcintype,
idx_opcintype,
- BTEqualStrategyNumber);
+ COMPARE_EQ);
else if (exclusion)
idx_eqop = indexInfo->ii_ExclusionOps[j];
Assert(idx_eqop);
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index 0bfbc5ca6dc..3d93d62d213 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -779,11 +779,11 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
opcintype = cla_tup->opcintype;
ReleaseSysCache(cla_ht);
- op = get_opfamily_member(opfamily, opcintype, opcintype,
- BTEqualStrategyNumber);
+ op = get_opmethod_member(InvalidOid, opfamily, opcintype, opcintype,
+ COMPARE_EQ);
if (!OidIsValid(op))
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
- BTEqualStrategyNumber, opcintype, opcintype, opfamily);
+ COMPARE_EQ, opcintype, opcintype, opfamily);
/*
* If we find the same column with the same equality semantics
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 03566c4d181..dbf98383117 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2097,7 +2097,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
FunctionCallInfo fcinfo;
get_op_opfamily_properties(opno, opfamily, false,
+ NULL, /* don't need opmethod */
&strategy,
+ NULL, /* don't need cmptype */
&lefttype,
&righttype);
proc = get_opfamily_proc(opfamily,
diff --git a/src/backend/executor/nodeIncrementalSort.c b/src/backend/executor/nodeIncrementalSort.c
index 975b0397e7a..7d666eb2980 100644
--- a/src/backend/executor/nodeIncrementalSort.c
+++ b/src/backend/executor/nodeIncrementalSort.c
@@ -78,6 +78,7 @@
#include "postgres.h"
+#include "catalog/pg_am.h" /* for BTREE_AM_OID */
#include "executor/execdebug.h"
#include "executor/nodeIncrementalSort.h"
#include "miscadmin.h"
@@ -180,7 +181,7 @@ preparePresortedCols(IncrementalSortState *node)
key->attno = plannode->sort.sortColIdx[i];
equalityOp = get_equality_op_for_ordering_op(plannode->sort.sortOperators[i],
- NULL);
+ BTREE_AM_OID, NULL);
if (!OidIsValid(equalityOp))
elog(ERROR, "missing equality operator for ordering operator %u",
plannode->sort.sortOperators[i]);
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index c30b9c2c197..bab9e74fcad 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1180,6 +1180,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
RegProcedure opfuncid; /* operator proc id used in scan */
Oid opfamily; /* opfamily of index column */
int op_strategy; /* operator's strategy number */
+ CompareType op_cmptype;
Oid op_lefttype; /* operator's declared input types */
Oid op_righttype;
Expr *leftop; /* expr on lhs of operator */
@@ -1222,7 +1223,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
opfamily = index->rd_opfamily[varattno - 1];
get_op_opfamily_properties(opno, opfamily, isorderby,
+ NULL, /* don't need opmethod */
&op_strategy,
+ NULL, /* don't need cmptype */
&op_lefttype,
&op_righttype);
@@ -1340,11 +1343,13 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
opfamily = index->rd_opfamily[varattno - 1];
get_op_opfamily_properties(opno, opfamily, isorderby,
+ NULL, /* don't need opmethod */
&op_strategy,
+ &op_cmptype,
&op_lefttype,
&op_righttype);
- if (op_strategy != rc->cmptype)
+ if (op_cmptype != rc->cmptype)
elog(ERROR, "RowCompare index qualification contains wrong operator");
opfuncid = get_opfamily_proc(opfamily,
@@ -1421,7 +1426,10 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
MemSet(this_scan_key, 0, sizeof(ScanKeyData));
this_scan_key->sk_flags = SK_ROW_HEADER;
this_scan_key->sk_attno = first_sub_key->sk_attno;
- this_scan_key->sk_strategy = rc->cmptype;
+ this_scan_key->sk_strategy = IndexAmTranslateCompareType(rc->cmptype,
+ index->rd_rel->relam,
+ 0, // FIXME
+ false);
/* sk_subtype, sk_collation, sk_func not used in a header */
this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
}
@@ -1463,7 +1471,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
opfamily = index->rd_opfamily[varattno - 1];
get_op_opfamily_properties(opno, opfamily, isorderby,
+ NULL, /* don't need opmethod */
&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..84f92fb4f8a 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -196,6 +196,7 @@ MJExamineQuals(List *mergeclauses,
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 +218,12 @@ MJExamineQuals(List *mergeclauses,
/* Extract the operator's declared left/right datatypes */
get_op_opfamily_properties(qual->opno, opfamily, false,
+ NULL, /* don't need opmethod */
&op_strategy,
+ &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 b5bc9b602e2..e6050b492cf 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -2299,16 +2299,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
@@ -2325,8 +2324,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
@@ -2343,9 +2341,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
@@ -2369,19 +2367,20 @@ 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,
+ runoperator = get_opmethod_member(opinfo->opmethod,
+ opinfo->opfamily_id,
opinfo->oplefttype,
opinfo->oprighttype,
- newstrategy);
+ newcmptype);
break;
}
}
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 73d78617009..b7f6ab40dec 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3610,6 +3610,7 @@ initial_cost_mergejoin(PlannerInfo *root, JoinCostWorkspace *workspace,
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");
@@ -4096,7 +4097,10 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
cache->collation == pathkey->pk_eclass->ec_collation &&
cache->strategy == pathkey->pk_strategy &&
cache->nulls_first == pathkey->pk_nulls_first)
+ {
+ Assert(cache->cmptype == pathkey->pk_cmptype);
return cache;
+ }
}
/* Nope, do the computation */
@@ -4104,6 +4108,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
(Node *) rinfo->clause,
pathkey->pk_opfamily,
pathkey->pk_strategy,
+ pathkey->pk_cmptype,
pathkey->pk_nulls_first,
&leftstartsel,
&leftendsel,
@@ -4117,6 +4122,7 @@ cached_scansel(PlannerInfo *root, RestrictInfo *rinfo, PathKey *pathkey)
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..eb68413a321 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -1788,8 +1788,8 @@ 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_opmethod_member(InvalidOid, 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 9202d9a3697..e0971beb1d1 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3526,6 +3526,8 @@ expand_indexqual_rowcompare(PlannerInfo *root,
{
IndexClause *iclause = makeNode(IndexClause);
RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause;
+ CompareType op_cmptype;
+ Oid op_method;
int op_strategy;
Oid op_lefttype;
Oid op_righttype;
@@ -3553,7 +3555,9 @@ expand_indexqual_rowcompare(PlannerInfo *root,
}
get_op_opfamily_properties(expr_op, index->opfamily[indexcol], false,
+ &op_method,
&op_strategy,
+ &op_cmptype,
&op_lefttype,
&op_righttype);
@@ -3614,7 +3618,9 @@ expand_indexqual_rowcompare(PlannerInfo *root,
/* Add operator info to lists */
get_op_opfamily_properties(expr_op, index->opfamily[i], false,
+ &op_method,
&op_strategy,
+ &op_cmptype,
&op_lefttype,
&op_righttype);
expr_ops = lappend_oid(expr_ops, expr_op);
@@ -3647,8 +3653,7 @@ expand_indexqual_rowcompare(PlannerInfo *root,
/* very easy, just use the commuted operators */
new_ops = expr_ops;
}
- else if (op_strategy == BTLessEqualStrategyNumber ||
- op_strategy == BTGreaterEqualStrategyNumber)
+ else if (op_cmptype == COMPARE_LE || op_cmptype == COMPARE_GE)
{
/* easy, just use the same (possibly commuted) operators */
new_ops = list_truncate(expr_ops, matching_cols);
@@ -3659,10 +3664,16 @@ expand_indexqual_rowcompare(PlannerInfo *root,
ListCell *lefttypes_cell;
ListCell *righttypes_cell;
- if (op_strategy == BTLessStrategyNumber)
- op_strategy = BTLessEqualStrategyNumber;
- else if (op_strategy == BTGreaterStrategyNumber)
- op_strategy = BTGreaterEqualStrategyNumber;
+ if (op_cmptype == COMPARE_LT)
+ {
+ op_cmptype = COMPARE_LE;
+ op_strategy = IndexAmTranslateCompareType(op_cmptype, op_method, 0, true); // FIXME
+ }
+ else if (op_cmptype == COMPARE_GT)
+ {
+ op_cmptype = COMPARE_GE;
+ op_strategy = IndexAmTranslateCompareType(op_cmptype, op_method, 0, true); // FIXME
+ }
else
elog(ERROR, "unexpected strategy number %d", op_strategy);
new_ops = NIL;
@@ -3760,8 +3771,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..a0826ed5008 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -17,7 +17,9 @@
*/
#include "postgres.h"
+#include "access/amapi.h"
#include "access/stratnum.h"
+#include "catalog/pg_am.h" /* for BTREE_AM_OID */
#include "catalog/pg_opfamily.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/cost.h"
@@ -53,18 +55,40 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
* merging EquivalenceClasses.
*/
PathKey *
-make_canonical_pathkey(PlannerInfo *root,
- EquivalenceClass *eclass, Oid opfamily,
- int strategy, bool nulls_first)
+make_canonical_pathkey(PlannerInfo *root, EquivalenceClass *eclass,
+ Oid opmethod, Oid opfamily, int strategy,
+ CompareType cmptype, bool nulls_first)
{
PathKey *pk;
ListCell *lc;
MemoryContext oldcontext;
+ Assert(OidIsValid(opmethod));
+ Assert(OidIsValid(opfamily));
+ Assert(opmethod == get_opfamily_method(opfamily));
+
/* Can't make canonical pathkeys if the set of ECs might still change */
if (!root->ec_merging_done)
elog(ERROR, "too soon to build canonical pathkeys");
+ /*
+ * Can't make canonical pathkeys if neither the strategy nor the cmptype
+ * were supplied. For callers who only gave us one of them, help out
+ * by looking up the other. This simplifies the work the caller needs
+ * to do and reduces code duplication.
+ */
+ if (strategy == InvalidStrategy)
+ {
+ Assert(cmptype != COMPARE_INVALID);
+ Assert(OidIsValid(opfamily));
+ strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, false);
+ }
+ else if (cmptype == COMPARE_INVALID)
+ {
+ Assert(OidIsValid(opfamily));
+ cmptype = IndexAmTranslateStrategy(strategy, opmethod, opfamily, false);
+ }
+
/* The passed eclass might be non-canonical, so chase up to the top */
while (eclass->ec_merged)
eclass = eclass->ec_merged;
@@ -75,6 +99,7 @@ make_canonical_pathkey(PlannerInfo *root,
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;
}
@@ -89,6 +114,7 @@ make_canonical_pathkey(PlannerInfo *root,
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);
@@ -197,6 +223,7 @@ pathkey_is_redundant(PathKey *new_pathkey, List *pathkeys)
static PathKey *
make_pathkey_from_sortinfo(PlannerInfo *root,
Expr *expr,
+ Oid opmethod,
Oid opfamily,
Oid opcintype,
Oid collation,
@@ -206,12 +233,18 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
Relids rel,
bool create_it)
{
+ CompareType cmptype;
int16 strategy;
Oid equality_op;
List *opfamilies;
EquivalenceClass *eclass;
- strategy = reverse_sort ? BTGreaterStrategyNumber : BTLessStrategyNumber;
+ Assert(OidIsValid(opmethod));
+ Assert(OidIsValid(opfamily));
+ Assert(opmethod == get_opfamily_method(opfamily));
+
+ cmptype = reverse_sort ? COMPARE_GT : COMPARE_LT;
+ strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, false);
/*
* EquivalenceClasses need to contain opfamily lists based on the family
@@ -219,13 +252,14 @@ 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,
+ equality_op = get_opmethod_member(opmethod,
+ opfamily,
opcintype,
opcintype,
- BTEqualStrategyNumber);
+ 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",
@@ -241,8 +275,8 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
return NULL;
/* And finally we can find or create a PathKey node */
- return make_canonical_pathkey(root, eclass, opfamily,
- strategy, nulls_first);
+ return make_canonical_pathkey(root, eclass, opmethod, opfamily,
+ strategy, cmptype, nulls_first);
}
/*
@@ -255,20 +289,21 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
static PathKey *
make_pathkey_from_sortop(PlannerInfo *root,
Expr *expr,
+ Oid opmethodfilter,
Oid ordering_op,
bool reverse_sort,
bool nulls_first,
Index sortref,
bool create_it)
{
- Oid opfamily,
+ Oid opmethod,
+ 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))
+ if (!get_ordering_op_properties(ordering_op, opmethodfilter, &opmethod,
+ &opfamily, &opcintype, NULL, NULL))
elog(ERROR, "operator %u is not a valid ordering operator",
ordering_op);
@@ -277,6 +312,7 @@ make_pathkey_from_sortop(PlannerInfo *root,
return make_pathkey_from_sortinfo(root,
expr,
+ opmethod,
opfamily,
opcintype,
collation,
@@ -783,6 +819,7 @@ build_index_pathkeys(PlannerInfo *root,
*/
cpathkey = make_pathkey_from_sortinfo(root,
indexkey,
+ index->relam,
index->sortopfamily[i],
index->opcintype[i],
index->indexcollations[i],
@@ -942,6 +979,7 @@ build_partition_pathkeys(PlannerInfo *root, RelOptInfo *partrel,
*/
cpathkey = make_pathkey_from_sortinfo(root,
keyCol,
+ get_opfamily_method(partscheme->partopfamily[i]), /* TODO: OPMETHOD */
partscheme->partopfamily[i],
partscheme->partopcintype[i],
partscheme->partcollation[i],
@@ -1004,24 +1042,26 @@ build_expression_pathkey(PlannerInfo *root,
bool create_it)
{
List *pathkeys;
- Oid opfamily,
+ Oid opmethod,
+ 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))
+ if (!get_ordering_op_properties(opno, BTREE_AM_OID, &opmethod, &opfamily,
+ &opcintype, NULL, &cmptype))
elog(ERROR, "operator %u is not a valid ordering operator",
opno);
cpathkey = make_pathkey_from_sortinfo(root,
expr,
+ opmethod,
opfamily,
opcintype,
exprCollation((Node *) expr),
- (strategy == BTGreaterStrategyNumber),
- (strategy == BTGreaterStrategyNumber),
+ (cmptype == COMPARE_GT),
+ (cmptype == COMPARE_GT),
0,
rel,
create_it);
@@ -1117,8 +1157,10 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
best_pathkey =
make_canonical_pathkey(root,
outer_ec,
+ get_opfamily_method(sub_pathkey->pk_opfamily),
sub_pathkey->pk_opfamily,
sub_pathkey->pk_strategy,
+ sub_pathkey->pk_cmptype,
sub_pathkey->pk_nulls_first);
}
}
@@ -1199,8 +1241,10 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
outer_pk = make_canonical_pathkey(root,
outer_ec,
+ get_opfamily_method(sub_pathkey->pk_opfamily),
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;
@@ -1333,6 +1377,7 @@ build_join_pathkeys(PlannerInfo *root,
*/
List *
make_pathkeys_for_sortclauses(PlannerInfo *root,
+ Oid opmethodfilter,
List *sortclauses,
List *tlist)
{
@@ -1340,6 +1385,7 @@ make_pathkeys_for_sortclauses(PlannerInfo *root,
bool sortable;
result = make_pathkeys_for_sortclauses_extended(root,
+ opmethodfilter,
&sortclauses,
tlist,
false,
@@ -1378,6 +1424,7 @@ make_pathkeys_for_sortclauses(PlannerInfo *root,
*/
List *
make_pathkeys_for_sortclauses_extended(PlannerInfo *root,
+ Oid opmethodfilter,
List **sortclauses,
List *tlist,
bool remove_redundant,
@@ -1411,6 +1458,7 @@ make_pathkeys_for_sortclauses_extended(PlannerInfo *root,
}
pathkey = make_pathkey_from_sortop(root,
sortkey,
+ opmethodfilter,
sortcl->sortop,
sortcl->reverse_sort,
sortcl->nulls_first,
@@ -1815,8 +1863,10 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
scores[best_j] = -1;
pathkey = make_canonical_pathkey(root,
ec,
+ get_opfamily_method(linitial_oid(ec->ec_opfamilies)),
linitial_oid(ec->ec_opfamilies),
- BTLessStrategyNumber,
+ InvalidStrategy,
+ COMPARE_LT,
false);
/* can't be redundant because no duplicate ECs */
Assert(!pathkey_is_redundant(pathkey, pathkeys));
@@ -1908,8 +1958,10 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
else
pathkey = make_canonical_pathkey(root,
ieclass,
+ get_opfamily_method(opathkey->pk_opfamily),
opathkey->pk_opfamily,
opathkey->pk_strategy,
+ opathkey->pk_cmptype,
opathkey->pk_nulls_first);
/*
@@ -2134,12 +2186,13 @@ 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_strategy == query_pathkey->pk_strategy &&
+ 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 816a2b2a576..6a7a8d68db5 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -19,6 +19,7 @@
#include <math.h>
#include "access/sysattr.h"
+#include "catalog/pg_am.h" /* for BTREE_AM_OID */
#include "catalog/pg_class.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
@@ -1883,7 +1884,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
* cross-type operators then the equality operators are the ones
* for the IN clause operators' RHS datatype.
*/
- eqop = get_equality_op_for_ordering_op(sortop, NULL);
+ eqop = get_equality_op_for_ordering_op(sortop, BTREE_AM_OID, NULL);
if (!OidIsValid(eqop)) /* shouldn't happen */
elog(ERROR, "could not find equality operator for ordering operator %u",
sortop);
@@ -4751,13 +4752,14 @@ create_mergejoin_plan(PlannerInfo *root,
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++;
}
@@ -6906,13 +6908,14 @@ 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,
+ eqop = get_opmethod_member(InvalidOid,
+ pathkey->pk_opfamily,
pk_datatype,
pk_datatype,
- BTEqualStrategyNumber);
+ 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/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 64605be3178..d98f2ef91fe 100644
--- a/src/backend/optimizer/plan/planagg.c
+++ b/src/backend/optimizer/plan/planagg.c
@@ -30,6 +30,7 @@
#include "access/htup_details.h"
#include "catalog/pg_aggregate.h"
+#include "catalog/pg_am.h" /* for BTREE_AM_OID */
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
@@ -160,7 +161,7 @@ preprocess_minmax_aggregates(PlannerInfo *root)
* We'll need the equality operator that goes with the aggregate's
* ordering operator.
*/
- eqop = get_equality_op_for_ordering_op(mminfo->aggsortop, &reverse);
+ eqop = get_equality_op_for_ordering_op(mminfo->aggsortop, BTREE_AM_OID, &reverse);
if (!OidIsValid(eqop)) /* shouldn't happen */
elog(ERROR, "could not find equality operator for ordering operator %u",
mminfo->aggsortop);
@@ -485,6 +486,7 @@ minmax_qp_callback(PlannerInfo *root, void *extra)
root->sort_pathkeys =
make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
root->parse->sortClause,
root->parse->targetList);
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 36ee6dd43de..9527ab83a8d 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -23,6 +23,7 @@
#include "access/sysattr.h"
#include "access/table.h"
#include "catalog/pg_aggregate.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -1459,6 +1460,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction,
*/
Assert(parse->distinctClause == NIL);
root->sort_pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
parse->sortClause,
root->processed_tlist);
}
@@ -3232,7 +3234,9 @@ adjust_group_pathkeys_for_groupagg(PlannerInfo *root)
else
sortlist = aggref->aggorder;
- pathkeys = make_pathkeys_for_sortclauses(root, sortlist,
+ pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
+ sortlist,
aggref->args);
/*
@@ -3375,6 +3379,7 @@ standard_qp_callback(PlannerInfo *root, void *extra)
*/
root->group_pathkeys =
make_pathkeys_for_sortclauses_extended(root,
+ BTREE_AM_OID,
&groupClause,
tlist,
false,
@@ -3408,6 +3413,7 @@ standard_qp_callback(PlannerInfo *root, void *extra)
*/
root->group_pathkeys =
make_pathkeys_for_sortclauses_extended(root,
+ BTREE_AM_OID,
&root->processed_groupClause,
tlist,
true,
@@ -3460,6 +3466,7 @@ standard_qp_callback(PlannerInfo *root, void *extra)
root->processed_distinctClause = list_copy(parse->distinctClause);
root->distinct_pathkeys =
make_pathkeys_for_sortclauses_extended(root,
+ BTREE_AM_OID,
&root->processed_distinctClause,
tlist,
true,
@@ -3474,6 +3481,7 @@ standard_qp_callback(PlannerInfo *root, void *extra)
root->sort_pathkeys =
make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
parse->sortClause,
tlist);
@@ -3487,6 +3495,7 @@ standard_qp_callback(PlannerInfo *root, void *extra)
root->setop_pathkeys =
make_pathkeys_for_sortclauses_extended(root,
+ BTREE_AM_OID,
&groupClauses,
tlist,
false,
@@ -6146,6 +6155,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
bool sortable;
window_pathkeys = make_pathkeys_for_sortclauses_extended(root,
+ BTREE_AM_OID,
&wc->partitionClause,
tlist,
true,
@@ -6168,6 +6178,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
List *orderby_pathkeys;
orderby_pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
wc->orderClause,
tlist);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index eab44da65b8..e6d8b7c0a78 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -24,6 +24,7 @@
#include "postgres.h"
#include "access/htup_details.h"
+#include "catalog/pg_am.h"
#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
@@ -730,7 +731,9 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root,
{
try_sorted = true;
/* Determine the pathkeys for sorting by the whole target list */
- union_pathkeys = make_pathkeys_for_sortclauses(root, groupList,
+ union_pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
+ groupList,
tlist);
root->query_pathkeys = union_pathkeys;
@@ -926,7 +929,10 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root,
/* Try Sort -> Unique on the Append path */
if (groupList != NIL)
path = (Path *) create_sort_path(root, result_rel, path,
- make_pathkeys_for_sortclauses(root, groupList, tlist),
+ make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
+ groupList,
+ tlist),
-1.0);
path = (Path *) create_upper_unique_path(root,
@@ -943,7 +949,10 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root,
path = gpath;
path = (Path *) create_sort_path(root, result_rel, path,
- make_pathkeys_for_sortclauses(root, groupList, tlist),
+ make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
+ groupList,
+ tlist),
-1.0);
path = (Path *) create_upper_unique_path(root,
@@ -1075,7 +1084,7 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root,
if (can_sort)
{
/* Determine the pathkeys for sorting by the whole target list */
- nonunion_pathkeys = make_pathkeys_for_sortclauses(root, groupList,
+ nonunion_pathkeys = make_pathkeys_for_sortclauses(root, BTREE_AM_OID, groupList,
tlist);
root->query_pathkeys = nonunion_pathkeys;
@@ -1196,6 +1205,7 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root,
/* First the left input ... */
pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
groupList,
lpath_tlist);
if (pathkeys_contained_in(pathkeys, lpath->pathkeys))
@@ -1218,6 +1228,7 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root,
/* and now the same for the right. */
pathkeys = make_pathkeys_for_sortclauses(root,
+ BTREE_AM_OID,
groupList,
rpath_tlist);
if (pathkeys_contained_in(pathkeys, rpath->pathkeys))
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 71abb01f655..a4b0d3465e8 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -382,27 +382,36 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
{
int16 opt = indexRelation->rd_indoption[i];
Oid ltopr;
- Oid btopfamily;
- Oid btopcintype;
- int16 btstrategy;
+ Oid opmethod;
+ 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],
+ ltopr = get_opmethod_member(info->relam,
+ info->opfamily[i],
info->opcintype[i],
info->opcintype[i],
- BTLessStrategyNumber);
+ COMPARE_LT);
if (OidIsValid(ltopr) &&
get_ordering_op_properties(ltopr,
- &btopfamily,
- &btopcintype,
- &btstrategy) &&
- btopcintype == info->opcintype[i] &&
- btstrategy == BTLessStrategyNumber)
+ info->relam,
+ &opmethod,
+ &opfamily,
+ &opcintype,
+ NULL,
+ &cmptype) &&
+ opcintype == info->opcintype[i] &&
+ cmptype == COMPARE_LT)
{
/* Successful mapping */
- info->sortopfamily[i] = btopfamily;
+ Assert(info->relam == opmethod);
+ Assert(info->relam == get_opfamily_method(opfamily));
+ info->sortopfamily[i] = opfamily;
+
+ /* TODO: OPMETHOD: store opmethod here? */
}
else
{
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index b76fc81b08d..1aa07ffde7e 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -1613,7 +1613,7 @@ clause_is_strict_for(Node *clause, Node *subexpr, bool allow_false)
* 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
* two identical subexpressions and we want to know whether one operator
@@ -2165,20 +2165,20 @@ 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);
+ OpIndexInterpretation *clause_op_info = lfirst(lcc);
StrategyNumber pred_strategy,
clause_strategy,
test_strategy;
@@ -2187,7 +2187,8 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
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;
@@ -2221,10 +2222,11 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
*/
if (test_strategy == BTNE)
{
- test_op = get_opfamily_member(opfamily_id,
+ test_op = get_opmethod_member(InvalidOid,
+ opfamily_id,
pred_op_info->oprighttype,
clause_op_info->oprighttype,
- BTEqualStrategyNumber);
+ COMPARE_EQ);
if (OidIsValid(test_op))
test_op = get_negator(test_op);
}
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 2e64fcae7b2..7fee19dd1b6 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,
@@ -2926,9 +2925,12 @@ transformWindowDefinitions(ParseState *pstate,
sortkey = get_sortgroupclause_expr(sortcl, *targetlist);
/* Find the sort operator in pg_amop */
if (!get_ordering_op_properties(sortcl->sortop,
+ BTREE_AM_OID,
+ NULL,
&rangeopfamily,
&rangeopcintype,
- &rangestrategy))
+ NULL,
+ NULL))
elog(ERROR, "operator %u is not a valid ordering operator",
sortcl->sortop);
/* Record properties of sort ordering */
@@ -3455,7 +3457,7 @@ addTargetToSortList(ParseState *pstate, TargetEntry *tle,
* equality operator, and determine whether to consider it like
* ASC or DESC.
*/
- eqop = get_equality_op_for_ordering_op(sortop, &reverse);
+ eqop = get_equality_op_for_ordering_op(sortop, BTREE_AM_OID, &reverse);
if (!OidIsValid(eqop))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index bad1df732ea..2f04db30efb 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2902,7 +2902,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
Bitmapset *this_strats;
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
@@ -2911,7 +2911,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
this_strats = NULL;
foreach(j, opinfo_lists[i])
{
- OpBtreeInterpretation *opinfo = lfirst(j);
+ OpIndexInterpretation *opinfo = lfirst(j);
this_strats = bms_add_member(this_strats, opinfo->strategy);
}
@@ -2961,7 +2961,7 @@ 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)
{
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 48a35f763e9..f55648efb78 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -1454,7 +1454,9 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
get_op_opfamily_properties(pc->opno,
part_scheme->partopfamily[i],
false,
+ NULL, /* don't need opmethod */
&pc->op_strategy,
+ NULL, /* don't need cmptype */
&lefttype,
&righttype);
@@ -1982,7 +1984,10 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
if (op_in_opfamily(opno, partopfamily))
{
get_op_opfamily_properties(opno, partopfamily, false,
- &op_strategy, &op_lefttype,
+ NULL, /* don't need opmethod */
+ &op_strategy,
+ NULL, /* don't need cmptype */
+ &op_lefttype,
&op_righttype);
}
else
@@ -1996,7 +2001,10 @@ 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,
+ NULL, /* don't need opmethod */
+ &op_strategy,
+ NULL, /* don't need cmptype */
+ &op_lefttype,
&op_righttype);
if (op_strategy == BTEqualStrategyNumber)
is_opne_listp = true; /* bingo */
@@ -2211,7 +2219,10 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
righttype;
get_op_opfamily_properties(negator, partopfamily,
- false, &strategy,
+ false,
+ NULL, /* don't need opmethod */
+ &strategy,
+ NULL, /* don't need cmptype */
&lefttype, &righttype);
if (strategy != BTEqualStrategyNumber)
return PARTCLAUSE_NOMATCH;
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 450dacd031c..eedc72e7b1e 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -1114,15 +1114,15 @@ match_network_subset(Node *leftop,
*/
if (is_eq)
{
- opr1oid = get_opfamily_member(opfamily, datatype, datatype,
- BTGreaterEqualStrategyNumber);
+ opr1oid = get_opmethod_member(InvalidOid, opfamily, datatype, datatype,
+ COMPARE_GE);
if (opr1oid == InvalidOid)
elog(ERROR, "no >= operator for opfamily %u", opfamily);
}
else
{
- opr1oid = get_opfamily_member(opfamily, datatype, datatype,
- BTGreaterStrategyNumber);
+ opr1oid = get_opmethod_member(InvalidOid, opfamily, datatype, datatype,
+ COMPARE_GT);
if (opr1oid == InvalidOid)
elog(ERROR, "no > operator for opfamily %u", opfamily);
}
@@ -1140,8 +1140,8 @@ match_network_subset(Node *leftop,
/* create clause "key <= network_scan_last( rightopval )" */
- opr2oid = get_opfamily_member(opfamily, datatype, datatype,
- BTLessEqualStrategyNumber);
+ opr2oid = get_opmethod_member(InvalidOid, opfamily, datatype, datatype,
+ COMPARE_LE);
if (opr2oid == InvalidOid)
elog(ERROR, "no <= operator for opfamily %u", opfamily);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index c2918c9c831..7a832c3767e 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2953,8 +2953,8 @@ scalargejoinsel(PG_FUNCTION_ARGS)
* *rightstart, *rightend similarly for the right-hand variable.
*/
void
-mergejoinscansel(PlannerInfo *root, Node *clause,
- Oid opfamily, int strategy, bool nulls_first,
+mergejoinscansel(PlannerInfo *root, Node *clause, Oid opfamily, int strategy,
+ CompareType cmptype, bool nulls_first,
Selectivity *leftstart, Selectivity *leftend,
Selectivity *rightstart, Selectivity *rightend)
{
@@ -3003,7 +3003,9 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
/* Extract the operator's declared left/right datatypes */
get_op_opfamily_properties(opno, opfamily, false,
+ NULL, /* don't need opmethod */
&op_strategy,
+ NULL, /* don't need cmptype */
&op_lefttype,
&op_righttype);
Assert(op_strategy == BTEqualStrategyNumber);
@@ -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_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_LT);
+ leop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_LE);
lsortop = ltop;
rsortop = ltop;
lstatop = lsortop;
@@ -3037,75 +3037,61 @@ 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_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_LT);
+ leop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_LE);
+ lsortop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_lefttype, COMPARE_LT);
+ rsortop = get_opmethod_member(InvalidOid, 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_opmethod_member(InvalidOid, opfamily, op_righttype,
+ op_lefttype, COMPARE_LT);
+ revleop = get_opmethod_member(InvalidOid, 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_opmethod_member(InvalidOid,
+ opfamily, op_lefttype, op_righttype,
+ COMPARE_GT);
+ leop = get_opmethod_member(InvalidOid,
+ opfamily, op_lefttype, op_righttype,
+ COMPARE_GE);
lsortop = ltop;
rsortop = ltop;
- lstatop = get_opfamily_member(opfamily,
- op_lefttype, op_lefttype,
- BTLessStrategyNumber);
+ lstatop = get_opmethod_member(InvalidOid,
+ 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_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_GT);
+ leop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_righttype, COMPARE_GE);
+ lsortop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_lefttype, COMPARE_GT);
+ rsortop = get_opmethod_member(InvalidOid, opfamily, op_righttype,
+ op_righttype, COMPARE_GT);
+ lstatop = get_opmethod_member(InvalidOid, opfamily, op_lefttype,
+ op_lefttype, COMPARE_LT);
+ rstatop = get_opmethod_member(InvalidOid, opfamily, op_righttype,
+ op_righttype, COMPARE_LT);
+ revltop = get_opmethod_member(InvalidOid, opfamily, op_righttype,
+ op_lefttype, COMPARE_GT);
+ revleop = get_opmethod_member(InvalidOid, opfamily, op_righttype,
+ op_lefttype, COMPARE_GE);
}
break;
default:
@@ -7135,10 +7121,11 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
Oid sortop;
AttStatsSlot sslot;
- sortop = get_opfamily_member(index->opfamily[0],
+ sortop = get_opmethod_member(InvalidOid,
+ index->opfamily[0],
index->opcintype[0],
index->opcintype[0],
- BTLessStrategyNumber);
+ COMPARE_LT);
if (OidIsValid(sortop) &&
get_attstatsslot(&sslot, vardata.statsTuple,
STATISTIC_KIND_CORRELATION, sortop,
@@ -7369,7 +7356,10 @@ 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);
+ NULL, /* don't need opmethod */
+ &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 7bd476f3de7..83b180a37dd 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -32,6 +32,7 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_opfamily.h"
#include "catalog/pg_operator.h"
+#include "catalog/pg_opfamily.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_publication.h"
#include "catalog/pg_range.h"
@@ -135,7 +136,9 @@ get_op_opfamily_sortfamily(Oid opno, Oid opfamily)
*/
void
get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op,
+ Oid *opmethod,
int *strategy,
+ CompareType *cmptype,
Oid *lefttype,
Oid *righttype)
{
@@ -150,12 +153,45 @@ 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 (opmethod)
+ *opmethod = amop_tup->amopmethod;
+ 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);
}
+/*
+ * get_opmethod_member
+ * Get the OID of the operator that implements the specified row
+ * comparison with the specified datatypes for the specified opfamily.
+ *
+ * Returns InvalidOid if there is no pg_amop entry for the given keys.
+ */
+Oid
+get_opmethod_member(Oid opmethod, Oid opfamily, Oid lefttype, Oid righttype,
+ CompareType cmptype)
+{
+ StrategyNumber strategy;
+
+ if (!OidIsValid(opmethod))
+ {
+ Assert(OidIsValid(opfamily));
+ opmethod = get_opfamily_method(opfamily);
+ }
+
+ strategy = IndexAmTranslateCompareType(cmptype, opmethod, opfamily, false);
+ return get_opfamily_member(opfamily, lefttype, righttype, strategy);
+}
+
/*
* get_opfamily_member
* Get the OID of the operator that implements the specified strategy
@@ -186,9 +222,9 @@ get_opfamily_member(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.)
@@ -205,17 +241,26 @@ get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
* additional effort on ensuring consistency.
*/
bool
-get_ordering_op_properties(Oid opno,
- Oid *opfamily, Oid *opcintype, int16 *strategy)
+get_ordering_op_properties(Oid opno, Oid opmethodfilter,
+ Oid *opmethod, 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 (opmethod)
+ *opmethod = InvalidOid;
+ 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 "<"
@@ -227,21 +272,36 @@ 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)
+ /* must be acceptable to our opmethod filter */
+ if (OidIsValid(opmethodfilter) && aform->amopmethod != opmethodfilter)
continue;
- if (aform->amopstrategy == BTLessStrategyNumber ||
- aform->amopstrategy == BTGreaterStrategyNumber)
+ am_cmptype = IndexAmTranslateStrategy(aform->amopstrategy,
+ aform->amopmethod,
+ aform->amopfamily,
+ true);
+
+ 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 (opmethod)
+ *opmethod = aform->amopmethod;
+ 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;
}
@@ -265,24 +325,27 @@ get_ordering_op_properties(Oid opno,
* (This indicates that the operator is not a valid ordering operator.)
*/
Oid
-get_equality_op_for_ordering_op(Oid opno, bool *reverse)
+get_equality_op_for_ordering_op(Oid opno, Oid opmethodfilter, bool *reverse)
{
Oid result = InvalidOid;
+ Oid opmethod;
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, opmethodfilter, &opmethod, &opfamily,
+ &opcintype, &strategy, &cmptype))
{
/* Found a suitable opfamily, get matching equality operator */
- result = get_opfamily_member(opfamily,
+ result = get_opmethod_member(opmethod,
+ opfamily,
opcintype,
opcintype,
- BTEqualStrategyNumber);
+ COMPARE_EQ);
if (reverse)
- *reverse = (strategy == BTGreaterStrategyNumber);
+ *reverse = (cmptype == COMPARE_GT);
}
return result;
@@ -330,9 +393,10 @@ get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
Oid typid;
typid = use_lhs_type ? aform->amoplefttype : aform->amoprighttype;
- result = get_opfamily_member(aform->amopfamily,
+ result = get_opmethod_member(InvalidOid,
+ aform->amopfamily,
typid, typid,
- BTLessStrategyNumber);
+ COMPARE_LT);
if (OidIsValid(result))
break;
/* failure probably shouldn't happen, but keep looking if so */
@@ -589,20 +653,20 @@ get_op_hash_functions(Oid opno,
}
/*
- * get_op_btree_interpretation
+ * get_op_index_interpretation
* Given an operator's OID, find out which btree 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;
@@ -625,10 +689,15 @@ get_op_btree_interpretation(Oid opno)
op_strategy = (StrategyNumber) op_form->amopstrategy;
Assert(op_strategy >= 1 && op_strategy <= 5);
- thisresult = (OpBtreeInterpretation *)
- palloc(sizeof(OpBtreeInterpretation));
+ thisresult = (OpIndexInterpretation *)
+ palloc(sizeof(OpIndexInterpretation));
+ thisresult->opmethod = op_form->amopmethod;
thisresult->opfamily_id = op_form->amopfamily;
thisresult->strategy = op_strategy;
+ thisresult->cmptype = IndexAmTranslateStrategy(thisresult->strategy,
+ thisresult->opmethod,
+ thisresult->opfamily_id,
+ false);
thisresult->oplefttype = op_form->amoplefttype;
thisresult->oprighttype = op_form->amoprighttype;
result = lappend(result, thisresult);
@@ -668,8 +737,8 @@ get_op_btree_interpretation(Oid opno)
continue;
/* OK, report it with "strategy" COMPARE_NE */
- thisresult = (OpBtreeInterpretation *)
- palloc(sizeof(OpBtreeInterpretation));
+ thisresult = (OpIndexInterpretation *)
+ palloc(sizeof(OpIndexInterpretation));
thisresult->opfamily_id = op_form->amopfamily;
thisresult->strategy = COMPARE_NE;
thisresult->oplefttype = op_form->amoplefttype;
@@ -1180,6 +1249,30 @@ get_language_name(Oid langoid, bool missing_ok)
return NULL;
}
+/* ---------- OPFAMILY CACHE ---------- */
+
+/*
+ * get_opfamily_method
+ *
+ * Returns the OID of the operator method the opfamily belongs to.
+ */
+Oid
+get_opfamily_method(Oid opfamily)
+{
+ HeapTuple tp;
+ Form_pg_opfamily opf_tup;
+ Oid result;
+
+ tp = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamily));
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "cache lookup failed for opfamily %u", opfamily);
+ opf_tup = (Form_pg_opfamily) GETSTRUCT(tp);
+
+ result = opf_tup->opfmethod;
+ ReleaseSysCache(tp);
+ return result;
+}
+
/* ---------- OPCLASS CACHE ---------- */
/*
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 5a3b3788d02..92a780afa35 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -633,10 +633,11 @@ lookup_type_cache(Oid type_id, int flags)
Oid eq_opr = InvalidOid;
if (typentry->btree_opf != InvalidOid)
- eq_opr = get_opfamily_member(typentry->btree_opf,
+ eq_opr = get_opmethod_member(InvalidOid,
+ typentry->btree_opf,
typentry->btree_opintype,
typentry->btree_opintype,
- BTEqualStrategyNumber);
+ COMPARE_EQ);
if (eq_opr == InvalidOid &&
typentry->hash_opf != InvalidOid)
eq_opr = get_opfamily_member(typentry->hash_opf,
@@ -680,10 +681,11 @@ lookup_type_cache(Oid type_id, int flags)
Oid lt_opr = InvalidOid;
if (typentry->btree_opf != InvalidOid)
- lt_opr = get_opfamily_member(typentry->btree_opf,
+ lt_opr = get_opmethod_member(InvalidOid,
+ typentry->btree_opf,
typentry->btree_opintype,
typentry->btree_opintype,
- BTLessStrategyNumber);
+ COMPARE_LT);
/*
* As above, make sure array_cmp or record_cmp will succeed; but again
@@ -705,10 +707,11 @@ lookup_type_cache(Oid type_id, int flags)
Oid gt_opr = InvalidOid;
if (typentry->btree_opf != InvalidOid)
- gt_opr = get_opfamily_member(typentry->btree_opf,
+ gt_opr = get_opmethod_member(InvalidOid,
+ typentry->btree_opf,
typentry->btree_opintype,
typentry->btree_opintype,
- BTGreaterStrategyNumber);
+ COMPARE_GT);
/*
* As above, make sure array_cmp or record_cmp will succeed; but again
diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c
index 9b855be690e..8bbbf4c4578 100644
--- a/src/backend/utils/sort/sortsupport.c
+++ b/src/backend/utils/sort/sortsupport.c
@@ -135,17 +135,18 @@ 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))
+ if (!get_ordering_op_properties(orderingOp, BTREE_AM_OID, NULL, &opfamily,
+ &opcintype, NULL, &cmptype))
elog(ERROR, "operator %u is not a valid ordering operator",
orderingOp);
- ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
+ ssup->ssup_reverse = (cmptype == COMPARE_GT);
+ /* TODO: OPMETHOD: pass into FinishSortSupportFunction? */
FinishSortSupportFunction(opfamily, opcintype, ssup);
}
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index fbf05322c75..45a1f760f3b 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1501,8 +1501,9 @@ 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 */
+ int pk_strategy; /* sort direction as opmethod specific strategy */
+ CompareType pk_cmptype; /* sort direction (COMPARE_LT or COMPARE_GT) */
bool pk_nulls_first; /* do NULLs come before normal values? */
} PathKey;
@@ -2767,9 +2768,10 @@ 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) */
+ int strategy; /* sort direction as opmethod specific strategy */
+ CompareType cmptype; /* sort direction (COMPARE_LT or COMPARE_GT) */
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..79407df1781 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -238,9 +238,11 @@ extern List *build_join_pathkeys(PlannerInfo *root,
JoinType jointype,
List *outer_pathkeys);
extern List *make_pathkeys_for_sortclauses(PlannerInfo *root,
+ Oid opmethodfilter,
List *sortclauses,
List *tlist);
extern List *make_pathkeys_for_sortclauses_extended(PlannerInfo *root,
+ Oid opmethodfilter,
List **sortclauses,
List *tlist,
bool remove_redundant,
@@ -269,8 +271,10 @@ extern List *truncate_useless_pathkeys(PlannerInfo *root,
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);
+ EquivalenceClass *eclass, Oid opmethod,
+ Oid opfamily, int strategy,
+ 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 6fab7aa6009..912f82176ea 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -14,20 +14,23 @@
#define LSYSCACHE_H
#include "access/attnum.h"
+#include "access/cmptype.h"
#include "access/htup.h"
#include "nodes/pg_list.h"
/* 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 opmethod; /* index access method of opfamily */
Oid opfamily_id; /* btree opfamily containing operator */
int strategy; /* its strategy number */
+ CompareType cmptype; /* its generic row 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
@@ -68,22 +71,31 @@ extern PGDLLIMPORT get_attavgwidth_hook_type get_attavgwidth_hook;
extern bool op_in_opfamily(Oid opno, Oid opfamily);
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,
+extern void get_op_opfamily_properties(Oid opno,
+ Oid opfamily,
+ bool ordering_op,
+ Oid *opmethod,
int *strategy,
+ CompareType *cmptype,
Oid *lefttype,
Oid *righttype);
+extern Oid get_opmethod_member(Oid opmethod, Oid opfamily, Oid lefttype,
+ Oid righttype, CompareType cmptype);
extern Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype,
int16 strategy);
-extern bool get_ordering_op_properties(Oid opno,
- Oid *opfamily, Oid *opcintype, int16 *strategy);
-extern Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse);
+extern bool get_ordering_op_properties(Oid opno, Oid opmethodfilter,
+ Oid *opmethod, Oid *opfamily,
+ Oid *opcintype, int16 *strategy,
+ CompareType *cmptype);
+extern Oid get_equality_op_for_ordering_op(Oid opno, Oid opmethodfilter,
+ bool *reverse);
extern Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type);
extern List *get_mergejoin_opfamilies(Oid opno);
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,
@@ -103,6 +115,7 @@ extern Oid get_constraint_index(Oid conoid);
extern char get_constraint_type(Oid conoid);
extern char *get_language_name(Oid langoid, bool missing_ok);
+extern Oid get_opfamily_method(Oid opfamily);
extern Oid get_opclass_family(Oid opclass);
extern Oid get_opclass_input_type(Oid opclass);
extern bool get_opclass_opfamily_and_input_type(Oid opclass,
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index d35939651f3..ba4e0e9f97c 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.h
@@ -209,10 +209,11 @@ extern Selectivity rowcomparesel(PlannerInfo *root,
RowCompareExpr *clause,
int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo);
-extern void mergejoinscansel(PlannerInfo *root, Node *clause,
- Oid opfamily, int strategy, bool nulls_first,
- Selectivity *leftstart, Selectivity *leftend,
- Selectivity *rightstart, Selectivity *rightend);
+extern void mergejoinscansel(PlannerInfo *root, Node *clause, Oid opfamily,
+ int strategy, CompareType cmptype,
+ bool nulls_first, Selectivity *leftstart,
+ Selectivity *leftend, Selectivity *rightstart,
+ Selectivity *rightend);
extern double estimate_num_groups(PlannerInfo *root, List *groupExprs,
double input_rows, List **pgset,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index e3e09a2207e..3698a975921 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1764,11 +1764,11 @@ OnConflictAction
OnConflictClause
OnConflictExpr
OnConflictSetState
-OpBtreeInterpretation
OpClassCacheEnt
OpExpr
OpFamilyMember
OpFamilyOpFuncGroup
+OpIndexInterpretation
OpclassInfo
Operator
OperatorElement
--
2.48.1