aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/plancat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r--src/backend/optimizer/util/plancat.c113
1 files changed, 72 insertions, 41 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 908b4f7205d..2ab272552be 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -189,19 +189,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
RelationGetForm(indexRelation)->reltablespace;
info->rel = rel;
info->ncolumns = ncolumns = index->indnatts;
-
- /*
- * Allocate per-column info arrays. To save a few palloc cycles
- * we allocate all the Oid-type arrays in one request. We must
- * pre-zero the sortop and nulls_first arrays in case the index is
- * unordered.
- */
info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
- info->opfamily = (Oid *) palloc0(sizeof(Oid) * (4 * ncolumns));
- info->opcintype = info->opfamily + ncolumns;
- info->fwdsortop = info->opcintype + ncolumns;
- info->revsortop = info->fwdsortop + ncolumns;
- info->nulls_first = (bool *) palloc0(sizeof(bool) * ncolumns);
+ info->opfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
+ info->opcintype = (Oid *) palloc(sizeof(Oid) * ncolumns);
for (i = 0; i < ncolumns; i++)
{
@@ -219,49 +209,90 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->amhasgetbitmap = OidIsValid(indexRelation->rd_am->amgetbitmap);
/*
- * Fetch the ordering operators associated with the index, if any.
- * We expect that all ordering-capable indexes use btree's
- * strategy numbers for the ordering operators.
+ * Fetch the ordering information for the index, if any.
*/
- if (indexRelation->rd_am->amcanorder)
+ if (info->relam == BTREE_AM_OID)
{
- int nstrat = indexRelation->rd_am->amstrategies;
+ /*
+ * If it's a btree index, we can use its opfamily OIDs
+ * directly as the sort ordering opfamily OIDs.
+ */
+ Assert(indexRelation->rd_am->amcanorder);
+
+ info->sortopfamily = info->opfamily;
+ info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
+ info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
for (i = 0; i < ncolumns; i++)
{
int16 opt = indexRelation->rd_indoption[i];
- int fwdstrat;
- int revstrat;
- if (opt & INDOPTION_DESC)
- {
- fwdstrat = BTGreaterStrategyNumber;
- revstrat = BTLessStrategyNumber;
- }
- else
- {
- fwdstrat = BTLessStrategyNumber;
- revstrat = BTGreaterStrategyNumber;
- }
+ info->reverse_sort[i] = (opt & INDOPTION_DESC) != 0;
+ info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
+ }
+ }
+ else if (indexRelation->rd_am->amcanorder)
+ {
+ /*
+ * Otherwise, identify the corresponding btree opfamilies by
+ * trying to map this index's "<" operators into btree. 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.
+ */
+ info->sortopfamily = (Oid *) palloc(sizeof(Oid) * ncolumns);
+ info->reverse_sort = (bool *) palloc(sizeof(bool) * ncolumns);
+ info->nulls_first = (bool *) palloc(sizeof(bool) * ncolumns);
+
+ for (i = 0; i < ncolumns; i++)
+ {
+ int16 opt = indexRelation->rd_indoption[i];
+ Oid ltopr;
+ Oid btopfamily;
+ Oid btopcintype;
+ int16 btstrategy;
- /*
- * Index AM must have a fixed set of strategies for it to
- * make sense to specify amcanorder, so we need not allow
- * the case amstrategies == 0.
- */
- if (fwdstrat > 0)
+ 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);
+ if (OidIsValid(ltopr) &&
+ get_ordering_op_properties(ltopr,
+ &btopfamily,
+ &btopcintype,
+ &btstrategy) &&
+ btopcintype == info->opcintype[i] &&
+ btstrategy == BTLessStrategyNumber)
{
- Assert(fwdstrat <= nstrat);
- info->fwdsortop[i] = indexRelation->rd_operator[i * nstrat + fwdstrat - 1];
+ /* Successful mapping */
+ info->sortopfamily[i] = btopfamily;
}
- if (revstrat > 0)
+ else
{
- Assert(revstrat <= nstrat);
- info->revsortop[i] = indexRelation->rd_operator[i * nstrat + revstrat - 1];
+ /* Fail ... quietly treat index as unordered */
+ info->sortopfamily = NULL;
+ info->reverse_sort = NULL;
+ info->nulls_first = NULL;
+ break;
}
- info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
}
}
+ else
+ {
+ info->sortopfamily = NULL;
+ info->reverse_sort = NULL;
+ info->nulls_first = NULL;
+ }
/*
* Fetch the index expressions and predicate, if any. We must