aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execGrouping.c4
-rw-r--r--src/backend/executor/execQual.c25
-rw-r--r--src/backend/executor/execUtils.c7
-rw-r--r--src/backend/executor/functions.c8
-rw-r--r--src/backend/executor/nodeAgg.c13
-rw-r--r--src/backend/executor/nodeIndexscan.c2
-rw-r--r--src/backend/executor/nodeMergeAppend.c5
-rw-r--r--src/backend/executor/nodeMergejoin.c9
-rw-r--r--src/backend/executor/nodeSubplan.c4
-rw-r--r--src/backend/executor/nodeWindowAgg.c10
10 files changed, 53 insertions, 34 deletions
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 1f02428a5b3..bfb8cbb303c 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -3,6 +3,10 @@
* execGrouping.c
* executor utility routines for grouping, hashing, and aggregation
*
+ * Note: we currently assume that equality and hashing functions are not
+ * collation-sensitive, so the code in this file has no support for passing
+ * collation settings through from callers. That may have to change someday.
+ *
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 5f0b58f43b7..80f08d8b92e 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -1202,12 +1202,12 @@ init_fcache(Oid foid, Oid input_collation, FuncExprState *fcache,
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
- fmgr_info_set_collation(input_collation, &(fcache->func));
fmgr_info_set_expr((Node *) fcache->xprstate.expr, &(fcache->func));
/* Initialize the function call parameter struct as well */
InitFunctionCallInfoData(fcache->fcinfo_data, &(fcache->func),
- list_length(fcache->args), NULL, NULL);
+ list_length(fcache->args),
+ input_collation, NULL, NULL);
/* If function returns set, prepare expected tuple descriptor */
if (fcache->func.fn_retset && needDescForSets)
@@ -1980,6 +1980,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
returnsSet = fcache->func.fn_retset;
InitFunctionCallInfoData(fcinfo, &(fcache->func),
list_length(fcache->args),
+ fcache->fcinfo_data.fncollation,
NULL, (Node *) &rsinfo);
/*
@@ -2017,7 +2018,7 @@ ExecMakeTableFunctionResult(ExprState *funcexpr,
{
/* Treat funcexpr as a generic expression */
direct_function_call = false;
- InitFunctionCallInfoData(fcinfo, NULL, 0, NULL, NULL);
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
}
/*
@@ -3154,6 +3155,7 @@ ExecEvalRowCompare(RowCompareExprState *rstate,
FunctionCallInfoData locfcinfo;
InitFunctionCallInfoData(locfcinfo, &(rstate->funcs[i]), 2,
+ rstate->collations[i],
NULL, NULL);
locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
&locfcinfo.argnull[0], NULL);
@@ -3234,7 +3236,9 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
Datum result = (Datum) 0;
- MinMaxOp op = ((MinMaxExpr *) minmaxExpr->xprstate.expr)->op;
+ MinMaxExpr *minmax = (MinMaxExpr *) minmaxExpr->xprstate.expr;
+ Oid collation = minmax->inputcollid;
+ MinMaxOp op = minmax->op;
FunctionCallInfoData locfcinfo;
ListCell *arg;
@@ -3242,7 +3246,8 @@ ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
*isDone = ExprSingleResult;
*isNull = true; /* until we get a result */
- InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2, NULL, NULL);
+ InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2,
+ collation, NULL, NULL);
locfcinfo.argnull[0] = false;
locfcinfo.argnull[1] = false;
@@ -4115,7 +4120,6 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc),
econtext->ecxt_per_query_memory);
- /* Note: coercion functions are assumed to not use collation */
fmgr_info_set_expr((Node *) acoerce, &(astate->elemfunc));
}
@@ -4124,9 +4128,11 @@ ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
*
* We pass on the desttypmod and isExplicit flags whether or not the
* function wants them.
+ *
+ * Note: coercion functions are assumed to not use collation.
*/
InitFunctionCallInfoData(locfcinfo, &(astate->elemfunc), 3,
- NULL, NULL);
+ InvalidOid, NULL, NULL);
locfcinfo.arg[0] = PointerGetDatum(array);
locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
@@ -4699,6 +4705,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
rstate->rargs = outlist;
Assert(list_length(rcexpr->opfamilies) == nopers);
rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
+ rstate->collations = (Oid *) palloc(nopers * sizeof(Oid));
i = 0;
forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids)
{
@@ -4726,7 +4733,7 @@ ExecInitExpr(Expr *node, PlanState *parent)
* does this code.
*/
fmgr_info(proc, &(rstate->funcs[i]));
- fmgr_info_set_collation(inputcollid, &(rstate->funcs[i]));
+ rstate->collations[i] = inputcollid;
i++;
}
state = (ExprState *) rstate;
@@ -4786,8 +4793,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
* code.
*/
fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
- fmgr_info_set_collation(minmaxexpr->inputcollid,
- &(mstate->cfunc));
state = (ExprState *) mstate;
}
break;
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 0cbbe04d3bd..073ef8d23b3 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -1349,9 +1349,10 @@ index_recheck_constraint(Relation index, Oid *constr_procs,
if (existing_isnull[i])
return false;
- if (!DatumGetBool(OidFunctionCall2(constr_procs[i],
- existing_values[i],
- new_values[i])))
+ if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
+ index->rd_indcollation[i],
+ existing_values[i],
+ new_values[i])))
return false;
}
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 9c867bbae20..13946cab23d 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -127,7 +127,7 @@ static Node *sql_fn_param_ref(ParseState *pstate, ParamRef *pref);
static List *init_execution_state(List *queryTree_list,
SQLFunctionCachePtr fcache,
bool lazyEvalOK);
-static void init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK);
+static void init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK);
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
static void postquel_end(execution_state *es);
@@ -363,7 +363,7 @@ init_execution_state(List *queryTree_list,
* Initialize the SQLFunctionCache for a SQL function
*/
static void
-init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
+init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
{
Oid foid = finfo->fn_oid;
Oid rettype;
@@ -428,7 +428,7 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
*/
fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple,
finfo->fn_expr,
- finfo->fn_collation);
+ collation);
/*
* And of course we need the function body text.
@@ -798,7 +798,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
if (fcache == NULL)
{
- init_sql_fcache(fcinfo->flinfo, lazyEvalOK);
+ init_sql_fcache(fcinfo->flinfo, PG_GET_COLLATION(), lazyEvalOK);
fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
}
eslist = fcache->func_state;
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 47555bab55b..13d77234801 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -130,6 +130,9 @@ typedef struct AggStatePerAggData
FmgrInfo transfn;
FmgrInfo finalfn;
+ /* Input collation derived for aggregate */
+ Oid aggCollation;
+
/* number of sorting columns */
int numSortCols;
@@ -430,6 +433,7 @@ advance_transition_function(AggState *aggstate,
*/
InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
numArguments + 1,
+ peraggstate->aggCollation,
(void *) aggstate, NULL);
fcinfo->arg[0] = pergroupstate->transValue;
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
@@ -597,6 +601,8 @@ process_ordered_aggregate_single(AggState *aggstate,
/*
* If DISTINCT mode, and not distinct from prior, skip it.
+ *
+ * Note: we assume equality functions don't care about collation.
*/
if (isDistinct &&
haveOldVal &&
@@ -737,6 +743,7 @@ finalize_aggregate(AggState *aggstate,
FunctionCallInfoData fcinfo;
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+ peraggstate->aggCollation,
(void *) aggstate, NULL);
fcinfo.arg[0] = pergroupstate->transValue;
fcinfo.argnull[0] = pergroupstate->transValueIsNull;
@@ -1676,16 +1683,16 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
&finalfnexpr);
fmgr_info(transfn_oid, &peraggstate->transfn);
- fmgr_info_set_collation(aggref->inputcollid, &peraggstate->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
if (OidIsValid(finalfn_oid))
{
fmgr_info(finalfn_oid, &peraggstate->finalfn);
- fmgr_info_set_collation(aggref->inputcollid, &peraggstate->finalfn);
fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
}
+ peraggstate->aggCollation = aggref->inputcollid;
+
get_typlenbyval(aggref->aggtype,
&peraggstate->resulttypeLen,
&peraggstate->resulttypeByVal);
@@ -1833,8 +1840,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
- fmgr_info_set_collation(aggref->inputcollid,
- &peraggstate->equalfns[i]);
i++;
}
Assert(i == numDistinctCols);
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index d8e59ca39e5..dbc1467d5be 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -973,7 +973,7 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index, Index scanrelid,
this_scan_key->sk_flags = SK_ROW_HEADER;
this_scan_key->sk_attno = first_sub_key->sk_attno;
this_scan_key->sk_strategy = rc->rctype;
- /* sk_subtype, sk_func not used in a header */
+ /* sk_subtype, sk_collation, sk_func not used in a header */
this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
}
else if (IsA(clause, ScalarArrayOpExpr))
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 4ebe0cbe033..43059664b93 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -327,8 +327,9 @@ heap_compare_slots(MergeAppendState *node, SlotNumber slot1, SlotNumber slot2)
}
else
{
- compare = DatumGetInt32(FunctionCall2(&scankey->sk_func,
- datum1, datum2));
+ compare = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+ scankey->sk_collation,
+ datum1, datum2));
if (compare != 0)
{
if (scankey->sk_flags & SK_BT_DESC)
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index d6245e61874..208c0fb76ac 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -138,11 +138,12 @@ typedef struct MergeJoinClauseData
/*
* The comparison strategy in use, and the lookup info to let us call the
- * btree comparison support function.
+ * btree comparison support function, and the collation to use.
*/
bool reverse; /* if true, negate the cmpfn's output */
bool nulls_first; /* if true, nulls sort low */
FmgrInfo cmpfinfo;
+ Oid collation;
} MergeJoinClauseData;
/* Result type for MJEvalOuterValues and MJEvalInnerValues */
@@ -242,7 +243,6 @@ MJExamineQuals(List *mergeclauses,
/* Set up the fmgr lookup information */
fmgr_info(cmpproc, &(clause->cmpfinfo));
- fmgr_info_set_collation(collation, &(clause->cmpfinfo));
/* Fill the additional comparison-strategy flags */
if (opstrategy == BTLessStrategyNumber)
@@ -254,6 +254,9 @@ MJExamineQuals(List *mergeclauses,
clause->nulls_first = nulls_first;
+ /* ... and the collation too */
+ clause->collation = collation;
+
iClause++;
}
@@ -429,7 +432,7 @@ MJCompare(MergeJoinState *mergestate)
* OK to call the comparison function.
*/
InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
- NULL, NULL);
+ clause->collation, NULL, NULL);
fcinfo.arg[0] = clause->ldatum;
fcinfo.arg[1] = clause->rdatum;
fcinfo.argnull[0] = false;
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 08a3017e614..4fcb66bbb03 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -831,8 +831,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
/* Lookup the equality function (potentially cross-type) */
fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
- fmgr_info_set_collation(opexpr->inputcollid,
- &sstate->cur_eq_funcs[i - 1]);
fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]);
/* Look up the equality function for the RHS type */
@@ -841,8 +839,6 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
elog(ERROR, "could not find compatible hash operator for operator %u",
opexpr->opno);
fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]);
- fmgr_info_set_collation(opexpr->inputcollid,
- &sstate->tab_eq_funcs[i - 1]);
/* Lookup the associated hash functions */
if (!get_op_hash_functions(opexpr->opno,
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 25d9298cefc..c90d40506f9 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -81,6 +81,8 @@ typedef struct WindowStatePerFuncData
FmgrInfo flinfo; /* fmgr lookup data for window function */
+ Oid winCollation; /* collation derived for window function */
+
/*
* We need the len and byval info for the result of each function in order
* to know how to copy/delete values.
@@ -289,6 +291,7 @@ advance_windowaggregate(WindowAggState *winstate,
*/
InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
numArguments + 1,
+ perfuncstate->winCollation,
(void *) winstate, NULL);
fcinfo->arg[0] = peraggstate->transValue;
fcinfo->argnull[0] = peraggstate->transValueIsNull;
@@ -340,6 +343,7 @@ finalize_windowaggregate(WindowAggState *winstate,
FunctionCallInfoData fcinfo;
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+ perfuncstate->winCollation,
(void *) winstate, NULL);
fcinfo.arg[0] = peraggstate->transValue;
fcinfo.argnull[0] = peraggstate->transValueIsNull;
@@ -627,6 +631,7 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
*/
InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo),
perfuncstate->numArguments,
+ perfuncstate->winCollation,
(void *) perfuncstate->winobj, NULL);
/* Just in case, make all the regular argument slots be null */
memset(fcinfo.argnull, true, perfuncstate->numArguments);
@@ -1561,9 +1566,10 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo,
econtext->ecxt_per_query_memory);
- fmgr_info_set_collation(wfunc->inputcollid, &perfuncstate->flinfo);
fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo);
+ perfuncstate->winCollation = wfunc->inputcollid;
+
get_typlenbyval(wfunc->wintype,
&perfuncstate->resulttypeLen,
&perfuncstate->resulttypeByVal);
@@ -1801,13 +1807,11 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
&finalfnexpr);
fmgr_info(transfn_oid, &peraggstate->transfn);
- fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
if (OidIsValid(finalfn_oid))
{
fmgr_info(finalfn_oid, &peraggstate->finalfn);
- fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->finalfn);
fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
}