diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c index 6e7dc3d2df98..d9970dd67533 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 ac14c06c7151..b4e0e60928b9 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 f1569879b529..4b9388af1548 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 7fcaa37fe625..82826c146ba4 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 f70239a2c9dd..c7b813ac0900 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 df3453f99f0f..905250b33252 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 f6f77b8fe193..c1bf67c95dc8 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 0f9ecf5ee8b2..0ae7c6d4f74d 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 6386ce822530..bdb05e7ce9d0 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 154eb505d755..5db7033e3a9a 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 75e2b0b90360..a8f22a8c154a 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 441684a72b11..4e24513ebcfa 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 b76fc81b08d0..9dcd0ffe81f9 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 2e64fcae7b23..bf50a0e656d9 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 9caf1e481a20..806ccb975371 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 48a35f763e90..12b5884bb9c0 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 5b35debc8ffd..8c722cf46ce2 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 82031c1e8e5e..9f55a97c93c2 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 0b4f08ed2ec5..bfa31fa2225c 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 ac3af528bc63..679845c9de35 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -1491,9 +1491,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 { @@ -1503,8 +1501,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; @@ -2769,9 +2767,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 bc5dfd7db417..17879fc461a9 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 d42380a0d46b..a7bdd2531dc7 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 82ac8c6d9dad..013049b3098a 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 8f28d8ff28eb..239e79b5eccd 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1791,11 +1791,11 @@ OnConflictAction OnConflictClause OnConflictExpr OnConflictSetState -OpBtreeInterpretation OpClassCacheEnt OpExpr OpFamilyMember OpFamilyOpFuncGroup +OpIndexInterpretation OpclassInfo Operator OperatorElement