summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/selfuncs.c62
-rw-r--r--src/backend/utils/cache/lsyscache.c165
-rw-r--r--src/backend/utils/sort/sortsupport.c6
3 files changed, 151 insertions, 82 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 021ea7517d7..588d991fa57 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -2947,7 +2947,7 @@ scalargejoinsel(PG_FUNCTION_ARGS)
* first join pair is found, which will affect the join's startup time.
*
* clause should be a clause already known to be mergejoinable. opfamily,
- * strategy, and nulls_first specify the sort ordering being used.
+ * cmptype, and nulls_first specify the sort ordering being used.
*
* The outputs are:
* *leftstart is set to the fraction of the left-hand variable expected
@@ -2958,7 +2958,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)
{
@@ -2966,6 +2966,7 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
*right;
VariableStatData leftvar,
rightvar;
+ Oid opmethod;
int op_strategy;
Oid op_lefttype;
Oid op_righttype;
@@ -2979,6 +2980,10 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
leop,
revltop,
revleop;
+ StrategyNumber ltstrat,
+ lestrat,
+ gtstrat,
+ gestrat;
bool isgt;
Datum leftmin,
leftmax,
@@ -3005,12 +3010,14 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
examine_variable(root, left, 0, &leftvar);
examine_variable(root, right, 0, &rightvar);
+ opmethod = get_opfamily_method(opfamily);
+
/* Extract the operator's declared left/right datatypes */
get_op_opfamily_properties(opno, opfamily, false,
&op_strategy,
&op_lefttype,
&op_righttype);
- Assert(op_strategy == BTEqualStrategyNumber);
+ Assert(IndexAmTranslateStrategy(op_strategy, opmethod, opfamily, true) == COMPARE_EQ);
/*
* Look up the various operators we need. If we don't find them all, it
@@ -3019,19 +3026,21 @@ 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;
+ ltstrat = IndexAmTranslateCompareType(COMPARE_LT, opmethod, opfamily, true);
+ lestrat = IndexAmTranslateCompareType(COMPARE_LE, opmethod, opfamily, true);
if (op_lefttype == op_righttype)
{
/* easy case */
ltop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTLessStrategyNumber);
+ ltstrat);
leop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTLessEqualStrategyNumber);
+ lestrat);
lsortop = ltop;
rsortop = ltop;
lstatop = lsortop;
@@ -3043,43 +3052,46 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
{
ltop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTLessStrategyNumber);
+ ltstrat);
leop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTLessEqualStrategyNumber);
+ lestrat);
lsortop = get_opfamily_member(opfamily,
op_lefttype, op_lefttype,
- BTLessStrategyNumber);
+ ltstrat);
rsortop = get_opfamily_member(opfamily,
op_righttype, op_righttype,
- BTLessStrategyNumber);
+ ltstrat);
lstatop = lsortop;
rstatop = rsortop;
revltop = get_opfamily_member(opfamily,
op_righttype, op_lefttype,
- BTLessStrategyNumber);
+ ltstrat);
revleop = get_opfamily_member(opfamily,
op_righttype, op_lefttype,
- BTLessEqualStrategyNumber);
+ lestrat);
}
break;
- case BTGreaterStrategyNumber:
+ case COMPARE_GT:
/* descending-order case */
isgt = true;
+ ltstrat = IndexAmTranslateCompareType(COMPARE_LT, opmethod, opfamily, true);
+ gtstrat = IndexAmTranslateCompareType(COMPARE_GT, opmethod, opfamily, true);
+ gestrat = IndexAmTranslateCompareType(COMPARE_GE, opmethod, opfamily, true);
if (op_lefttype == op_righttype)
{
/* easy case */
ltop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTGreaterStrategyNumber);
+ gtstrat);
leop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTGreaterEqualStrategyNumber);
+ gestrat);
lsortop = ltop;
rsortop = ltop;
lstatop = get_opfamily_member(opfamily,
op_lefttype, op_lefttype,
- BTLessStrategyNumber);
+ ltstrat);
rstatop = lstatop;
revltop = ltop;
revleop = leop;
@@ -3088,28 +3100,28 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
{
ltop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTGreaterStrategyNumber);
+ gtstrat);
leop = get_opfamily_member(opfamily,
op_lefttype, op_righttype,
- BTGreaterEqualStrategyNumber);
+ gestrat);
lsortop = get_opfamily_member(opfamily,
op_lefttype, op_lefttype,
- BTGreaterStrategyNumber);
+ gtstrat);
rsortop = get_opfamily_member(opfamily,
op_righttype, op_righttype,
- BTGreaterStrategyNumber);
+ gtstrat);
lstatop = get_opfamily_member(opfamily,
op_lefttype, op_lefttype,
- BTLessStrategyNumber);
+ ltstrat);
rstatop = get_opfamily_member(opfamily,
op_righttype, op_righttype,
- BTLessStrategyNumber);
+ ltstrat);
revltop = get_opfamily_member(opfamily,
op_righttype, op_lefttype,
- BTGreaterStrategyNumber);
+ gtstrat);
revleop = get_opfamily_member(opfamily,
op_righttype, op_lefttype,
- BTGreaterEqualStrategyNumber);
+ gestrat);
}
break;
default:
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);
diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c
index 0b4f08ed2ec..e0f500b9aa2 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))
+ &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);
}