aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/path/clausesel.c10
-rw-r--r--src/backend/optimizer/util/plancat.c26
-rw-r--r--src/backend/utils/adt/selfuncs.c96
-rw-r--r--src/include/optimizer/plancat.h2
4 files changed, 83 insertions, 51 deletions
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index ca068991c16..b9e97d414d8 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -579,6 +579,7 @@ clause_selectivity(PlannerInfo *root,
list_make2(var,
makeBoolConst(true,
false)),
+ InvalidOid,
varRelid);
}
}
@@ -650,13 +651,15 @@ clause_selectivity(PlannerInfo *root,
}
else if (is_opclause(clause) || IsA(clause, DistinctExpr))
{
- Oid opno = ((OpExpr *) clause)->opno;
+ OpExpr *opclause = (OpExpr *) clause;
+ Oid opno = opclause->opno;
if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
{
/* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno,
- ((OpExpr *) clause)->args,
+ opclause->args,
+ opclause->inputcollid,
jointype,
sjinfo);
}
@@ -664,7 +667,8 @@ clause_selectivity(PlannerInfo *root,
{
/* Estimate selectivity for a restriction clause. */
s1 = restriction_selectivity(root, opno,
- ((OpExpr *) clause)->args,
+ opclause->args,
+ opclause->inputcollid,
varRelid);
}
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index a92d2485289..77e701d2fc9 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -907,6 +907,7 @@ Selectivity
restriction_selectivity(PlannerInfo *root,
Oid operatorid,
List *args,
+ Oid inputcollid,
int varRelid)
{
RegProcedure oprrest = get_oprrest(operatorid);
@@ -919,11 +920,12 @@ restriction_selectivity(PlannerInfo *root,
if (!oprrest)
return (Selectivity) 0.5;
- result = DatumGetFloat8(OidFunctionCall4(oprrest,
- PointerGetDatum(root),
- ObjectIdGetDatum(operatorid),
- PointerGetDatum(args),
- Int32GetDatum(varRelid)));
+ result = DatumGetFloat8(OidFunctionCall4Coll(oprrest,
+ inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operatorid),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "invalid restriction selectivity: %f", result);
@@ -942,6 +944,7 @@ Selectivity
join_selectivity(PlannerInfo *root,
Oid operatorid,
List *args,
+ Oid inputcollid,
JoinType jointype,
SpecialJoinInfo *sjinfo)
{
@@ -955,12 +958,13 @@ join_selectivity(PlannerInfo *root,
if (!oprjoin)
return (Selectivity) 0.5;
- result = DatumGetFloat8(OidFunctionCall5(oprjoin,
- PointerGetDatum(root),
- ObjectIdGetDatum(operatorid),
- PointerGetDatum(args),
- Int16GetDatum(jointype),
- PointerGetDatum(sjinfo)));
+ result = DatumGetFloat8(OidFunctionCall5Coll(oprjoin,
+ inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operatorid),
+ PointerGetDatum(args),
+ Int16GetDatum(jointype),
+ PointerGetDatum(sjinfo)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "invalid join selectivity: %f", result);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index d700b86b934..acbdad95624 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -83,6 +83,15 @@
* joins, however, the selectivity is defined as the fraction of the left-hand
* side relation's rows that are expected to have a match (ie, at least one
* row with a TRUE result) in the right-hand side.
+ *
+ * For both oprrest and oprjoin functions, the operator's input collation OID
+ * (if any) is passed using the standard fmgr mechanism, so that the estimator
+ * function can fetch it with PG_GET_COLLATION(). Note, however, that all
+ * statistics in pg_statistic are currently built using the database's default
+ * collation. Thus, in most cases where we are looking at statistics, we
+ * should ignore the actual operator collation and use DEFAULT_COLLATION_OID.
+ * We expect that the error induced by doing this is usually not large enough
+ * to justify complicating matters.
*----------
*/
@@ -1087,6 +1096,7 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
Oid operator = PG_GETARG_OID(1);
List *args = (List *) PG_GETARG_POINTER(2);
int varRelid = PG_GETARG_INT32(3);
+ Oid collation = PG_GET_COLLATION();
VariableStatData vardata;
Node *other;
bool varonleft;
@@ -1187,12 +1197,15 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
}
/*
- * Divide pattern into fixed prefix and remainder. XXX we have to assume
- * default collation here, because we don't have access to the actual
- * input collation for the operator. FIXME ...
+ * Divide pattern into fixed prefix and remainder. Unlike many of the
+ * other functions in this file, we use the pattern operator's actual
+ * collation for this step. This is not because we expect the collation
+ * to make a big difference in the selectivity estimate (it seldom would),
+ * but because we want to be sure we cache compiled regexps under the
+ * right cache key, so that they can be re-used at runtime.
*/
patt = (Const *) other;
- pstatus = pattern_fixed_prefix(patt, ptype, DEFAULT_COLLATION_OID,
+ pstatus = pattern_fixed_prefix(patt, ptype, collation,
&prefix, &rest);
/*
@@ -1776,18 +1789,20 @@ scalararraysel(PlannerInfo *root,
elem_nulls[i],
elmbyval));
if (is_join_clause)
- s2 = DatumGetFloat8(FunctionCall5(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int16GetDatum(jointype),
- PointerGetDatum(sjinfo)));
+ s2 = DatumGetFloat8(FunctionCall5Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int16GetDatum(jointype),
+ PointerGetDatum(sjinfo)));
else
- s2 = DatumGetFloat8(FunctionCall4(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int32GetDatum(varRelid)));
+ s2 = DatumGetFloat8(FunctionCall4Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
if (useOr)
s1 = s1 + s2 - s1 * s2;
else
@@ -1818,18 +1833,20 @@ scalararraysel(PlannerInfo *root,
*/
args = list_make2(leftop, elem);
if (is_join_clause)
- s2 = DatumGetFloat8(FunctionCall5(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int16GetDatum(jointype),
- PointerGetDatum(sjinfo)));
+ s2 = DatumGetFloat8(FunctionCall5Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int16GetDatum(jointype),
+ PointerGetDatum(sjinfo)));
else
- s2 = DatumGetFloat8(FunctionCall4(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int32GetDatum(varRelid)));
+ s2 = DatumGetFloat8(FunctionCall4Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
if (useOr)
s1 = s1 + s2 - s1 * s2;
else
@@ -1854,18 +1871,20 @@ scalararraysel(PlannerInfo *root,
dummyexpr->collation = clause->inputcollid;
args = list_make2(leftop, dummyexpr);
if (is_join_clause)
- s2 = DatumGetFloat8(FunctionCall5(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int16GetDatum(jointype),
- PointerGetDatum(sjinfo)));
+ s2 = DatumGetFloat8(FunctionCall5Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int16GetDatum(jointype),
+ PointerGetDatum(sjinfo)));
else
- s2 = DatumGetFloat8(FunctionCall4(&oprselproc,
- PointerGetDatum(root),
- ObjectIdGetDatum(operator),
- PointerGetDatum(args),
- Int32GetDatum(varRelid)));
+ s2 = DatumGetFloat8(FunctionCall4Coll(&oprselproc,
+ clause->inputcollid,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
s1 = useOr ? 0.0 : 1.0;
/*
@@ -1937,6 +1956,7 @@ rowcomparesel(PlannerInfo *root,
{
Selectivity s1;
Oid opno = linitial_oid(clause->opnos);
+ Oid inputcollid = linitial_oid(clause->inputcollids);
List *opargs;
bool is_join_clause;
@@ -1977,6 +1997,7 @@ rowcomparesel(PlannerInfo *root,
/* Estimate selectivity for a join clause. */
s1 = join_selectivity(root, opno,
opargs,
+ inputcollid,
jointype,
sjinfo);
}
@@ -1985,6 +2006,7 @@ rowcomparesel(PlannerInfo *root,
/* Estimate selectivity for a restriction clause. */
s1 = restriction_selectivity(root, opno,
opargs,
+ inputcollid,
varRelid);
}
diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h
index c0b8eda8137..5138a8d97c7 100644
--- a/src/include/optimizer/plancat.h
+++ b/src/include/optimizer/plancat.h
@@ -43,11 +43,13 @@ extern bool has_unique_index(RelOptInfo *rel, AttrNumber attno);
extern Selectivity restriction_selectivity(PlannerInfo *root,
Oid operatorid,
List *args,
+ Oid inputcollid,
int varRelid);
extern Selectivity join_selectivity(PlannerInfo *root,
Oid operatorid,
List *args,
+ Oid inputcollid,
JoinType jointype,
SpecialJoinInfo *sjinfo);