From 00dc3e0cae56d8c6a9b38afb43ad4d8dd7ea4267 Mon Sep 17 00:00:00 2001 From: Andrew Dunstan 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 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 #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