diff options
Diffstat (limited to 'src/backend/utils/cache/lsyscache.c')
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 165 |
1 files changed, 111 insertions, 54 deletions
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 82031c1e8e5..c460a72b75d 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -207,10 +207,45 @@ get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, } /* + * get_opmethod_canorder + * Return amcanorder field for given index AM. + * + * To speed things up in the common cases, we're hardcoding the results from + * the built-in index types. Note that 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. + */ +static bool +get_opmethod_canorder(Oid amoid) +{ + switch (amoid) + { + case BTREE_AM_OID: + return true; + case HASH_AM_OID: + case GIST_AM_OID: + case GIN_AM_OID: + case SPGIST_AM_OID: + case BRIN_AM_OID: + return false; + default: + { + bool result; + IndexAmRoutine *amroutine = GetIndexAmRoutineByAmId(amoid, false); + + result = amroutine->amcanorder; + pfree(amroutine); + return result; + } + } +} + +/* * get_ordering_op_properties - * Given the OID of an ordering operator (a btree "<" or ">" operator), + * Given the OID of an ordering operator (a "<" or ">" operator), * determine its opfamily, its declared input datatype, and its - * strategy number (BTLessStrategyNumber or BTGreaterStrategyNumber). + * 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,7 +263,7 @@ 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, CompareType *cmptype) { bool result = false; CatCList *catlist; @@ -237,7 +272,7 @@ get_ordering_op_properties(Oid opno, /* ensure outputs are initialized on failure */ *opfamily = InvalidOid; *opcintype = InvalidOid; - *strategy = 0; + *cmptype = COMPARE_INVALID; /* * Search pg_amop to see if the target operator is registered as the "<" @@ -249,13 +284,18 @@ 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 ordering index */ + if (!get_opmethod_canorder(aform->amopmethod)) 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) @@ -263,7 +303,7 @@ get_ordering_op_properties(Oid opno, /* Found a suitable opfamily, return info */ *opfamily = aform->amopfamily; *opcintype = aform->amoplefttype; - *strategy = aform->amopstrategy; + *cmptype = am_cmptype; result = true; break; } @@ -277,7 +317,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 "<", @@ -292,19 +332,19 @@ get_equality_op_for_ordering_op(Oid opno, bool *reverse) Oid result = InvalidOid; Oid opfamily; Oid opcintype; - int16 strategy; + CompareType cmptype; /* Find the operator in pg_amop */ if (get_ordering_op_properties(opno, - &opfamily, &opcintype, &strategy)) + &opfamily, &opcintype, &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 +352,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 +381,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); + CompareType cmptype; - /* must be btree */ - if (aform->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!get_opmethod_canorder(aform->amopmethod)) 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 +414,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 +439,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,9 +448,12 @@ 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) + /* must be ordering index equality */ + if (get_opmethod_canorder(aform->amopmethod) && + IndexAmTranslateStrategy(aform->amopstrategy, + aform->amopmethod, + aform->amopfamily, + true) == COMPARE_EQ) result = lappend_oid(result, aform->amopfamily); } @@ -611,20 +659,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 +685,26 @@ 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; + CompareType cmptype; - /* must be btree */ - if (op_form->amopmethod != BTREE_AM_OID) + /* must be ordering index */ + if (!get_opmethod_canorder(op_form->amopmethod)) 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 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 +729,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 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); |