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