aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/selfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/selfuncs.c')
-rw-r--r--src/backend/utils/adt/selfuncs.c148
1 files changed, 83 insertions, 65 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 230ce549f3b..73e82cd5e01 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.215 2006/12/15 18:42:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.216 2006/12/23 00:43:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -76,7 +76,7 @@
#include <ctype.h>
#include <math.h>
-#include "catalog/pg_opclass.h"
+#include "catalog/pg_opfamily.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
@@ -128,7 +128,7 @@ static double convert_timevalue_to_scalar(Datum value, Oid typid);
static bool get_variable_maximum(PlannerInfo *root, VariableStatData *vardata,
Oid sortop, Datum *max);
static Selectivity prefix_selectivity(VariableStatData *vardata,
- Oid opclass, Const *prefixcon);
+ Oid vartype, Oid opfamily, Const *prefixcon);
static Selectivity pattern_selectivity(Const *patt, Pattern_Type ptype);
static Datum string_to_datum(const char *str, Oid datatype);
static Const *string_to_const(const char *str, Oid datatype);
@@ -911,7 +911,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
Datum constval;
Oid consttype;
Oid vartype;
- Oid opclass;
+ Oid opfamily;
Pattern_Prefix_Status pstatus;
Const *patt = NULL;
Const *prefix = NULL;
@@ -960,9 +960,9 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
* Similarly, the exposed type of the left-hand side should be one of
* those we know. (Do not look at vardata.atttype, which might be
* something binary-compatible but different.) We can use it to choose
- * the index opclass from which we must draw the comparison operators.
+ * the index opfamily from which we must draw the comparison operators.
*
- * NOTE: It would be more correct to use the PATTERN opclasses than the
+ * NOTE: It would be more correct to use the PATTERN opfamilies than the
* simple ones, but at the moment ANALYZE will not generate statistics for
* the PATTERN operators. But our results are so approximate anyway that
* it probably hardly matters.
@@ -972,19 +972,16 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
switch (vartype)
{
case TEXTOID:
- opclass = TEXT_BTREE_OPS_OID;
- break;
- case VARCHAROID:
- opclass = VARCHAR_BTREE_OPS_OID;
+ opfamily = TEXT_BTREE_FAM_OID;
break;
case BPCHAROID:
- opclass = BPCHAR_BTREE_OPS_OID;
+ opfamily = BPCHAR_BTREE_FAM_OID;
break;
case NAMEOID:
- opclass = NAME_BTREE_OPS_OID;
+ opfamily = NAME_BTREE_FAM_OID;
break;
case BYTEAOID:
- opclass = BYTEA_BTREE_OPS_OID;
+ opfamily = BYTEA_BTREE_FAM_OID;
break;
default:
ReleaseVariableStats(vardata);
@@ -1028,12 +1025,12 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
/*
* Pattern specifies an exact match, so pretend operator is '='
*/
- Oid eqopr = get_opclass_member(opclass, InvalidOid,
- BTEqualStrategyNumber);
+ Oid eqopr = get_opfamily_member(opfamily, vartype, vartype,
+ BTEqualStrategyNumber);
List *eqargs;
if (eqopr == InvalidOid)
- elog(ERROR, "no = operator for opclass %u", opclass);
+ elog(ERROR, "no = operator for opfamily %u", opfamily);
eqargs = list_make2(variable, prefix);
result = DatumGetFloat8(DirectFunctionCall4(eqsel,
PointerGetDatum(root),
@@ -1074,7 +1071,8 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
Selectivity restsel;
if (pstatus == Pattern_Prefix_Partial)
- prefixsel = prefix_selectivity(&vardata, opclass, prefix);
+ prefixsel = prefix_selectivity(&vardata, vartype,
+ opfamily, prefix);
else
prefixsel = 1.0;
restsel = pattern_selectivity(rest, ptype);
@@ -2114,7 +2112,8 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
* we can estimate how much of the input will actually be read. This
* can have a considerable impact on the cost when using indexscans.
*
- * clause should be a clause already known to be mergejoinable.
+ * clause should be a clause already known to be mergejoinable. opfamily and
+ * strategy specify the sort ordering being used.
*
* *leftscan is set to the fraction of the left-hand variable expected
* to be scanned (0 to 1), and similarly *rightscan for the right-hand
@@ -2122,6 +2121,7 @@ icnlikejoinsel(PG_FUNCTION_ARGS)
*/
void
mergejoinscansel(PlannerInfo *root, Node *clause,
+ Oid opfamily, int strategy,
Selectivity *leftscan,
Selectivity *rightscan)
{
@@ -2129,15 +2129,14 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
*right;
VariableStatData leftvar,
rightvar;
- Oid lefttype,
- righttype;
+ int op_strategy;
+ Oid op_lefttype;
+ Oid op_righttype;
+ bool op_recheck;
Oid opno,
lsortop,
rsortop,
- ltop,
- gtop,
leop,
- revgtop,
revleop;
Datum leftmax,
rightmax;
@@ -2159,15 +2158,51 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
examine_variable(root, left, 0, &leftvar);
examine_variable(root, right, 0, &rightvar);
- /* Get the direct input types of the operator */
- lefttype = exprType(left);
- righttype = exprType(right);
+ /* Extract the operator's declared left/right datatypes */
+ get_op_opfamily_properties(opno, opfamily,
+ &op_strategy,
+ &op_lefttype,
+ &op_righttype,
+ &op_recheck);
+ Assert(op_strategy == BTEqualStrategyNumber);
+ Assert(!op_recheck);
+
+ /*
+ * Look up the various operators we need. If we don't find them all,
+ * it probably means the opfamily is broken, but we cope anyway.
+ */
+ switch (strategy)
+ {
+ case BTLessStrategyNumber:
+ lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype,
+ BTLessStrategyNumber);
+ rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype,
+ BTLessStrategyNumber);
+ leop = get_opfamily_member(opfamily, op_lefttype, op_righttype,
+ BTLessEqualStrategyNumber);
+ revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype,
+ BTLessEqualStrategyNumber);
+ break;
+ case BTGreaterStrategyNumber:
+ /* descending-order case */
+ lsortop = get_opfamily_member(opfamily, op_lefttype, op_lefttype,
+ BTGreaterStrategyNumber);
+ rsortop = get_opfamily_member(opfamily, op_righttype, op_righttype,
+ BTGreaterStrategyNumber);
+ leop = get_opfamily_member(opfamily, op_lefttype, op_righttype,
+ BTGreaterEqualStrategyNumber);
+ revleop = get_opfamily_member(opfamily, op_righttype, op_lefttype,
+ BTGreaterEqualStrategyNumber);
+ break;
+ default:
+ goto fail; /* shouldn't get here */
+ }
- /* Verify mergejoinability and get left and right "<" operators */
- if (!op_mergejoinable(opno,
- &lsortop,
- &rsortop))
- goto fail; /* shouldn't happen */
+ if (!OidIsValid(lsortop) ||
+ !OidIsValid(rsortop) ||
+ !OidIsValid(leop) ||
+ !OidIsValid(revleop))
+ goto fail; /* insufficient info in catalogs */
/* Try to get maximum values of both inputs */
if (!get_variable_maximum(root, &leftvar, lsortop, &leftmax))
@@ -2176,37 +2211,19 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
if (!get_variable_maximum(root, &rightvar, rsortop, &rightmax))
goto fail; /* no max available from stats */
- /* Look up the "left < right" and "left > right" operators */
- op_mergejoin_crossops(opno, &ltop, &gtop, NULL, NULL);
-
- /* Look up the "left <= right" operator */
- leop = get_negator(gtop);
- if (!OidIsValid(leop))
- goto fail; /* insufficient info in catalogs */
-
- /* Look up the "right > left" operator */
- revgtop = get_commutator(ltop);
- if (!OidIsValid(revgtop))
- goto fail; /* insufficient info in catalogs */
-
- /* Look up the "right <= left" operator */
- revleop = get_negator(revgtop);
- if (!OidIsValid(revleop))
- goto fail; /* insufficient info in catalogs */
-
/*
* Now, the fraction of the left variable that will be scanned is the
* fraction that's <= the right-side maximum value. But only believe
* non-default estimates, else stick with our 1.0.
*/
selec = scalarineqsel(root, leop, false, &leftvar,
- rightmax, righttype);
+ rightmax, op_righttype);
if (selec != DEFAULT_INEQ_SEL)
*leftscan = selec;
/* And similarly for the right variable. */
selec = scalarineqsel(root, revleop, false, &rightvar,
- leftmax, lefttype);
+ leftmax, op_lefttype);
if (selec != DEFAULT_INEQ_SEL)
*rightscan = selec;
@@ -3486,7 +3503,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
* statistics.
*
* XXX it's conceivable that there are multiple matches with different
- * index opclasses; if so, we need to pick one that matches the
+ * index opfamilies; if so, we need to pick one that matches the
* operator we are estimating for. FIXME later.
*/
ListCell *ilist;
@@ -4100,7 +4117,7 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
* population represented by the histogram --- the caller must fold this
* together with info about MCVs and NULLs.
*
- * We use the >= and < operators from the specified btree opclass to do the
+ * We use the >= and < operators from the specified btree opfamily to do the
* estimation. The given variable and Const must be of the associated
* datatype.
*
@@ -4110,17 +4127,18 @@ pattern_fixed_prefix(Const *patt, Pattern_Type ptype,
* more useful to use the upper-bound code than not.
*/
static Selectivity
-prefix_selectivity(VariableStatData *vardata, Oid opclass, Const *prefixcon)
+prefix_selectivity(VariableStatData *vardata,
+ Oid vartype, Oid opfamily, Const *prefixcon)
{
Selectivity prefixsel;
Oid cmpopr;
FmgrInfo opproc;
Const *greaterstrcon;
- cmpopr = get_opclass_member(opclass, InvalidOid,
- BTGreaterEqualStrategyNumber);
+ cmpopr = get_opfamily_member(opfamily, vartype, vartype,
+ BTGreaterEqualStrategyNumber);
if (cmpopr == InvalidOid)
- elog(ERROR, "no >= operator for opclass %u", opclass);
+ elog(ERROR, "no >= operator for opfamily %u", opfamily);
fmgr_info(get_opcode(cmpopr), &opproc);
prefixsel = ineq_histogram_selectivity(vardata, &opproc, true,
@@ -4143,10 +4161,10 @@ prefix_selectivity(VariableStatData *vardata, Oid opclass, Const *prefixcon)
{
Selectivity topsel;
- cmpopr = get_opclass_member(opclass, InvalidOid,
- BTLessStrategyNumber);
+ cmpopr = get_opfamily_member(opfamily, vartype, vartype,
+ BTLessStrategyNumber);
if (cmpopr == InvalidOid)
- elog(ERROR, "no < operator for opclass %u", opclass);
+ elog(ERROR, "no < operator for opfamily %u", opfamily);
fmgr_info(get_opcode(cmpopr), &opproc);
topsel = ineq_histogram_selectivity(vardata, &opproc, false,
@@ -4921,7 +4939,7 @@ btcostestimate(PG_FUNCTION_ARGS)
}
else if (match_index_to_operand(rightop, indexcol, index))
{
- /* Must flip operator to get the opclass member */
+ /* Must flip operator to get the opfamily member */
clause_op = get_commutator(clause_op);
}
else
@@ -4937,7 +4955,7 @@ btcostestimate(PG_FUNCTION_ARGS)
}
else if (match_index_to_operand(rightop, indexcol, index))
{
- /* Must flip operator to get the opclass member */
+ /* Must flip operator to get the opfamily member */
clause_op = get_commutator(clause_op);
}
else
@@ -4946,9 +4964,9 @@ btcostestimate(PG_FUNCTION_ARGS)
break;
}
}
- op_strategy = get_op_opclass_strategy(clause_op,
- index->classlist[indexcol]);
- Assert(op_strategy != 0); /* not a member of opclass?? */
+ op_strategy = get_op_opfamily_strategy(clause_op,
+ index->opfamily[indexcol]);
+ Assert(op_strategy != 0); /* not a member of opfamily?? */
if (op_strategy == BTEqualStrategyNumber)
eqQualHere = true;
/* count up number of SA scans induced by indexBoundQuals only */