diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 26 | ||||
-rw-r--r-- | src/backend/utils/adt/int.c | 3 | ||||
-rw-r--r-- | src/backend/utils/adt/like.c | 6 | ||||
-rw-r--r-- | src/backend/utils/adt/oid.c | 3 | ||||
-rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 5 | ||||
-rw-r--r-- | src/backend/utils/adt/rowtypes.c | 22 | ||||
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 114 | ||||
-rw-r--r-- | src/backend/utils/cache/catcache.c | 2 | ||||
-rw-r--r-- | src/backend/utils/fmgr/README | 21 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 172 | ||||
-rw-r--r-- | src/backend/utils/sort/tuplesort.c | 38 |
11 files changed, 200 insertions, 212 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 0869de66cef..a234f35eb8f 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3127,6 +3127,7 @@ array_eq(PG_FUNCTION_ARGS) { ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); + Oid collation = PG_GET_COLLATION(); int ndims1 = ARR_NDIM(array1); int ndims2 = ARR_NDIM(array2); int *dims1 = ARR_DIMS(array1); @@ -3184,7 +3185,7 @@ array_eq(PG_FUNCTION_ARGS) * apply the operator to each pair of array elements. */ InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, - NULL, NULL); + collation, NULL, NULL); /* Loop over source data */ nitems = ArrayGetNItems(ndims1, dims1); @@ -3367,8 +3368,7 @@ array_cmp(FunctionCallInfo fcinfo) */ typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra; if (typentry == NULL || - typentry->type_id != element_type || - typentry->cmp_proc_finfo.fn_collation != collation) + typentry->type_id != element_type) { typentry = lookup_type_cache(element_type, TYPECACHE_CMP_PROC_FINFO); @@ -3378,7 +3378,6 @@ array_cmp(FunctionCallInfo fcinfo) errmsg("could not identify a comparison function for type %s", format_type_be(element_type)))); fcinfo->flinfo->fn_extra = (void *) typentry; - typentry->cmp_proc_finfo.fn_collation = collation; } typlen = typentry->typlen; typbyval = typentry->typbyval; @@ -3388,7 +3387,7 @@ array_cmp(FunctionCallInfo fcinfo) * apply the operator to each pair of array elements. */ InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, - NULL, NULL); + collation, NULL, NULL); /* Loop over source data */ min_nitems = Min(nitems1, nitems2); @@ -3573,7 +3572,7 @@ hash_array(PG_FUNCTION_ARGS) * apply the hash function to each array element. */ InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1, - NULL, NULL); + InvalidOid, NULL, NULL); /* Loop over source data */ nitems = ArrayGetNItems(ndims, dims); @@ -3647,8 +3646,8 @@ hash_array(PG_FUNCTION_ARGS) * When matchall is false, return true if any members of array1 are in array2. */ static bool -array_contain_compare(ArrayType *array1, ArrayType *array2, bool matchall, - void **fn_extra) +array_contain_compare(ArrayType *array1, ArrayType *array2, Oid collation, + bool matchall, void **fn_extra) { bool result = matchall; Oid element_type = ARR_ELEMTYPE(array1); @@ -3707,7 +3706,7 @@ array_contain_compare(ArrayType *array1, ArrayType *array2, bool matchall, * Apply the comparison operator to each pair of array elements. */ InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, - NULL, NULL); + collation, NULL, NULL); /* Loop over source data */ nelems1 = ArrayGetNItems(ARR_NDIM(array1), ARR_DIMS(array1)); @@ -3811,9 +3810,10 @@ arrayoverlap(PG_FUNCTION_ARGS) { ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); + Oid collation = PG_GET_COLLATION(); bool result; - result = array_contain_compare(array1, array2, false, + result = array_contain_compare(array1, array2, collation, false, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ @@ -3828,9 +3828,10 @@ arraycontains(PG_FUNCTION_ARGS) { ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); + Oid collation = PG_GET_COLLATION(); bool result; - result = array_contain_compare(array2, array1, true, + result = array_contain_compare(array2, array1, collation, true, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ @@ -3845,9 +3846,10 @@ arraycontained(PG_FUNCTION_ARGS) { ArrayType *array1 = PG_GETARG_ARRAYTYPE_P(0); ArrayType *array2 = PG_GETARG_ARRAYTYPE_P(1); + Oid collation = PG_GET_COLLATION(); bool result; - result = array_contain_compare(array1, array2, true, + result = array_contain_compare(array1, array2, collation, true, &fcinfo->flinfo->fn_extra); /* Avoid leaking memory when handed toasted input. */ diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c index dcb31586b2b..019fcaaa36f 100644 --- a/src/backend/utils/adt/int.c +++ b/src/backend/utils/adt/int.c @@ -213,7 +213,8 @@ int2vectorrecv(PG_FUNCTION_ARGS) * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ - InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, + InvalidOid, NULL, NULL); locfcinfo.arg[0] = PointerGetDatum(buf); locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID); diff --git a/src/backend/utils/adt/like.c b/src/backend/utils/adt/like.c index 0934c69ebe5..09e8698af2c 100644 --- a/src/backend/utils/adt/like.c +++ b/src/backend/utils/adt/like.c @@ -174,10 +174,12 @@ Generic_Text_IC_like(text *str, text *pat, Oid collation) if (pg_database_encoding_max_length() > 1) { /* lower's result is never packed, so OK to use old macros here */ - pat = DatumGetTextP(DirectFunctionCall1WithCollation(lower, collation, PointerGetDatum(pat))); + pat = DatumGetTextP(DirectFunctionCall1Coll(lower, collation, + PointerGetDatum(pat))); p = VARDATA(pat); plen = (VARSIZE(pat) - VARHDRSZ); - str = DatumGetTextP(DirectFunctionCall1WithCollation(lower, collation, PointerGetDatum(str))); + str = DatumGetTextP(DirectFunctionCall1Coll(lower, collation, + PointerGetDatum(str))); s = VARDATA(str); slen = (VARSIZE(str) - VARHDRSZ); if (GetDatabaseEncoding() == PG_UTF8) diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c index b2152a2491c..495b6261e62 100644 --- a/src/backend/utils/adt/oid.c +++ b/src/backend/utils/adt/oid.c @@ -263,7 +263,8 @@ oidvectorrecv(PG_FUNCTION_ARGS) * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo * parameter. */ - InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, + InvalidOid, NULL, NULL); locfcinfo.arg[0] = PointerGetDatum(buf); locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID); diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 4e5dd4b772d..fde01a0f571 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -3963,7 +3963,10 @@ ri_AttributesEqual(Oid eq_opr, Oid typeid, BoolGetDatum(false)); /* implicit coercion */ } - /* Apply the comparison operator */ + /* + * Apply the comparison operator. We assume it doesn't + * care about collations. + */ return DatumGetBool(FunctionCall2(&entry->eq_opr_finfo, oldvalue, newvalue)); } diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c index 2c552e173bb..919ed9582a7 100644 --- a/src/backend/utils/adt/rowtypes.c +++ b/src/backend/utils/adt/rowtypes.c @@ -867,6 +867,7 @@ record_cmp(FunctionCallInfo fcinfo) while (i1 < ncolumns1 || i2 < ncolumns2) { TypeCacheEntry *typentry; + Oid collation; FunctionCallInfoData locfcinfo; int32 cmpresult; @@ -899,6 +900,14 @@ record_cmp(FunctionCallInfo fcinfo) j + 1))); /* + * If they're not same collation, we don't complain here, but the + * comparison function might. + */ + collation = tupdesc1->attrs[i1]->attcollation; + if (collation != tupdesc2->attrs[i2]->attcollation) + collation = InvalidOid; + + /* * Lookup the comparison function if not done already */ typentry = my_extra->columns[j].typentry; @@ -935,7 +944,7 @@ record_cmp(FunctionCallInfo fcinfo) /* Compare the pair of elements */ InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2, - NULL, NULL); + collation, NULL, NULL); locfcinfo.arg[0] = values1[i1]; locfcinfo.arg[1] = values2[i2]; locfcinfo.argnull[0] = false; @@ -1093,6 +1102,7 @@ record_eq(PG_FUNCTION_ARGS) while (i1 < ncolumns1 || i2 < ncolumns2) { TypeCacheEntry *typentry; + Oid collation; FunctionCallInfoData locfcinfo; bool oprresult; @@ -1125,6 +1135,14 @@ record_eq(PG_FUNCTION_ARGS) j + 1))); /* + * If they're not same collation, we don't complain here, but the + * equality function might. + */ + collation = tupdesc1->attrs[i1]->attcollation; + if (collation != tupdesc2->attrs[i2]->attcollation) + collation = InvalidOid; + + /* * Lookup the equality function if not done already */ typentry = my_extra->columns[j].typentry; @@ -1154,7 +1172,7 @@ record_eq(PG_FUNCTION_ARGS) /* Compare the pair of elements */ InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2, - NULL, NULL); + collation, NULL, NULL); locfcinfo.arg[0] = values1[i1]; locfcinfo.arg[1] = values2[i2]; locfcinfo.argnull[0] = false; diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index b046bc05e62..4d800f8a007 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -285,19 +285,20 @@ var_eq_const(VariableStatData *vardata, Oid operator, FmgrInfo eqproc; fmgr_info(get_opcode(operator), &eqproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc); for (i = 0; i < nvalues; i++) { /* be careful to apply operator right way 'round */ if (varonleft) - match = DatumGetBool(FunctionCall2(&eqproc, - values[i], - constval)); + match = DatumGetBool(FunctionCall2Coll(&eqproc, + DEFAULT_COLLATION_OID, + values[i], + constval)); else - match = DatumGetBool(FunctionCall2(&eqproc, - constval, - values[i])); + match = DatumGetBool(FunctionCall2Coll(&eqproc, + DEFAULT_COLLATION_OID, + constval, + values[i])); if (match) break; } @@ -515,7 +516,6 @@ scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, stats = (Form_pg_statistic) GETSTRUCT(vardata->statsTuple); fmgr_info(get_opcode(operator), &opproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc); /* * If we have most-common-values info, add up the fractions of the MCV @@ -598,12 +598,14 @@ mcv_selectivity(VariableStatData *vardata, FmgrInfo *opproc, for (i = 0; i < nvalues; i++) { if (varonleft ? - DatumGetBool(FunctionCall2(opproc, - values[i], - constval)) : - DatumGetBool(FunctionCall2(opproc, - constval, - values[i]))) + DatumGetBool(FunctionCall2Coll(opproc, + DEFAULT_COLLATION_OID, + values[i], + constval)) : + DatumGetBool(FunctionCall2Coll(opproc, + DEFAULT_COLLATION_OID, + constval, + values[i]))) mcv_selec += numbers[i]; sumcommon += numbers[i]; } @@ -678,12 +680,14 @@ histogram_selectivity(VariableStatData *vardata, FmgrInfo *opproc, for (i = n_skip; i < nvalues - n_skip; i++) { if (varonleft ? - DatumGetBool(FunctionCall2(opproc, - values[i], - constval)) : - DatumGetBool(FunctionCall2(opproc, - constval, - values[i]))) + DatumGetBool(FunctionCall2Coll(opproc, + DEFAULT_COLLATION_OID, + values[i], + constval)) : + DatumGetBool(FunctionCall2Coll(opproc, + DEFAULT_COLLATION_OID, + constval, + values[i]))) nmatch++; } result = ((double) nmatch) / ((double) (nvalues - 2 * n_skip)); @@ -802,9 +806,10 @@ ineq_histogram_selectivity(PlannerInfo *root, NULL, &values[probe]); - ltcmp = DatumGetBool(FunctionCall2(opproc, - values[probe], - constval)); + ltcmp = DatumGetBool(FunctionCall2Coll(opproc, + DEFAULT_COLLATION_OID, + values[probe], + constval)); if (isgt) ltcmp = !ltcmp; if (ltcmp) @@ -1255,7 +1260,6 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate) /* Try to use the histogram entries to get selectivity */ fmgr_info(get_opcode(operator), &opproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc); selec = histogram_selectivity(&vardata, &opproc, constval, true, 10, 1, &hist_size); @@ -1705,7 +1709,6 @@ scalararraysel(PlannerInfo *root, if (!oprsel) return (Selectivity) 0.5; fmgr_info(oprsel, &oprselproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &oprselproc); /* deconstruct the expression */ Assert(list_length(clause->args) == 2); @@ -2126,7 +2129,6 @@ eqjoinsel_inner(Oid operator, nmatches; fmgr_info(get_opcode(operator), &eqproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc); hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool)); hasmatch2 = (bool *) palloc0(nvalues2 * sizeof(bool)); @@ -2146,9 +2148,10 @@ eqjoinsel_inner(Oid operator, { if (hasmatch2[j]) continue; - if (DatumGetBool(FunctionCall2(&eqproc, - values1[i], - values2[j]))) + if (DatumGetBool(FunctionCall2Coll(&eqproc, + DEFAULT_COLLATION_OID, + values1[i], + values2[j]))) { hasmatch1[i] = hasmatch2[j] = true; matchprodfreq += numbers1[i] * numbers2[j]; @@ -2349,7 +2352,6 @@ eqjoinsel_semi(Oid operator, nmatches; fmgr_info(get_opcode(operator), &eqproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &eqproc); hasmatch1 = (bool *) palloc0(nvalues1 * sizeof(bool)); hasmatch2 = (bool *) palloc0(nvalues2 * sizeof(bool)); @@ -2368,9 +2370,10 @@ eqjoinsel_semi(Oid operator, { if (hasmatch2[j]) continue; - if (DatumGetBool(FunctionCall2(&eqproc, - values1[i], - values2[j]))) + if (DatumGetBool(FunctionCall2Coll(&eqproc, + DEFAULT_COLLATION_OID, + values1[i], + values2[j]))) { hasmatch1[i] = hasmatch2[j] = true; nmatches++; @@ -4503,7 +4506,6 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, FmgrInfo opproc; fmgr_info(get_opcode(sortop), &opproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc); for (i = 0; i < nvalues; i++) { @@ -4513,12 +4515,16 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata, Oid sortop, tmin_is_mcv = tmax_is_mcv = have_data = true; continue; } - if (DatumGetBool(FunctionCall2(&opproc, values[i], tmin))) + if (DatumGetBool(FunctionCall2Coll(&opproc, + DEFAULT_COLLATION_OID, + values[i], tmin))) { tmin = values[i]; tmin_is_mcv = true; } - if (DatumGetBool(FunctionCall2(&opproc, tmax, values[i]))) + if (DatumGetBool(FunctionCall2Coll(&opproc, + DEFAULT_COLLATION_OID, + tmax, values[i]))) { tmax = values[i]; tmax_is_mcv = true; @@ -5183,7 +5189,6 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata, if (cmpopr == InvalidOid) elog(ERROR, "no >= operator for opfamily %u", opfamily); fmgr_info(get_opcode(cmpopr), &opproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc); prefixsel = ineq_histogram_selectivity(root, vardata, &opproc, true, prefixcon->constvalue, @@ -5205,9 +5210,8 @@ prefix_selectivity(PlannerInfo *root, VariableStatData *vardata, if (cmpopr == InvalidOid) elog(ERROR, "no < operator for opfamily %u", opfamily); fmgr_info(get_opcode(cmpopr), &opproc); - fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc); - - greaterstrcon = make_greater_string(prefixcon, &opproc); + greaterstrcon = make_greater_string(prefixcon, &opproc, + DEFAULT_COLLATION_OID); if (greaterstrcon) { Selectivity topsel; @@ -5502,22 +5506,21 @@ pattern_selectivity(Const *patt, Pattern_Type ptype) * in the form of a Const node; else return NULL. * * The caller must provide the appropriate "less than" comparison function - * for testing the strings. In particular, ltproc->fn_collation specifies - * the locale for comparisons. + * for testing the strings, along with the collation to use. * * The key requirement here is that given a prefix string, say "foo", * we must be able to generate another string "fop" that is greater than * all strings "foobar" starting with "foo". We can test that we have - * generated a string greater than the prefix string, but in non-C locales + * generated a string greater than the prefix string, but in non-C collations * that is not a bulletproof guarantee that an extension of the string might * not sort after it; an example is that "foo " is less than "foo!", but it * is not clear that a "dictionary" sort ordering will consider "foo!" less * than "foo bar". CAUTION: Therefore, this function should be used only for - * estimation purposes when working in a non-C locale. + * estimation purposes when working in a non-C collation. * * To try to catch most cases where an extended string might otherwise sort * before the result value, we determine which of the strings "Z", "z", "y", - * and "9" is seen as largest by the locale, and append that to the given + * and "9" is seen as largest by the collation, and append that to the given * prefix before trying to find a string that compares as larger. * * If we max out the righthand byte, truncate off the last character @@ -5529,7 +5532,7 @@ pattern_selectivity(Const *patt, Pattern_Type ptype) * won't have to try more than one or two strings before succeeding. */ Const * -make_greater_string(const Const *str_const, FmgrInfo *ltproc) +make_greater_string(const Const *str_const, FmgrInfo *ltproc, Oid collation) { Oid datatype = str_const->consttype; char *workstr; @@ -5565,7 +5568,7 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc) { workstr = TextDatumGetCString(str_const->constvalue); len = strlen(workstr); - if (lc_collate_is_c(ltproc->fn_collation) || len == 0) + if (lc_collate_is_c(collation) || len == 0) cmpstr = str_const->constvalue; else { @@ -5573,19 +5576,19 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc) static char suffixchar = 0; static Oid suffixcollation = 0; - if (!suffixchar || suffixcollation != ltproc->fn_collation) + if (!suffixchar || suffixcollation != collation) { char *best; best = "Z"; - if (varstr_cmp(best, 1, "z", 1, ltproc->fn_collation) < 0) + if (varstr_cmp(best, 1, "z", 1, collation) < 0) best = "z"; - if (varstr_cmp(best, 1, "y", 1, ltproc->fn_collation) < 0) + if (varstr_cmp(best, 1, "y", 1, collation) < 0) best = "y"; - if (varstr_cmp(best, 1, "9", 1, ltproc->fn_collation) < 0) + if (varstr_cmp(best, 1, "9", 1, collation) < 0) best = "9"; suffixchar = *best; - suffixcollation = ltproc->fn_collation; + suffixcollation = collation; } /* And build the string to compare to */ @@ -5621,9 +5624,10 @@ make_greater_string(const Const *str_const, FmgrInfo *ltproc) else workstr_const = string_to_bytea_const(workstr, len); - if (DatumGetBool(FunctionCall2(ltproc, - cmpstr, - workstr_const->constvalue))) + if (DatumGetBool(FunctionCall2Coll(ltproc, + collation, + cmpstr, + workstr_const->constvalue))) { /* Successfully made a string larger than cmpstr */ if (cmptxt) diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 5caa53d4d25..350e040474b 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -935,7 +935,7 @@ CatalogCacheInitializeCache(CatCache *cache) cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber; cache->cc_skey[i].sk_subtype = InvalidOid; /* Currently, there are no catcaches on collation-aware data types */ - cache->cc_skey[i].sk_func.fn_collation = InvalidOid; + cache->cc_skey[i].sk_collation = InvalidOid; CACHE4_elog(DEBUG2, "CatalogCacheInitializeCache %s %d %p", cache->cc_relname, diff --git a/src/backend/utils/fmgr/README b/src/backend/utils/fmgr/README index 6647fe95f72..a650eb14a37 100644 --- a/src/backend/utils/fmgr/README +++ b/src/backend/utils/fmgr/README @@ -71,7 +71,6 @@ typedef struct bool fn_strict; /* function is "strict" (NULL in => NULL out) */ bool fn_retset; /* function returns a set (over multiple calls) */ unsigned char fn_stats; /* collect stats if track_functions > this */ - Oid fn_collation; /* collation that function should use */ void *fn_extra; /* extra space for use by handler */ MemoryContext fn_mcxt; /* memory context to store fn_extra in */ Node *fn_expr; /* expression parse tree for call, or NULL */ @@ -92,14 +91,12 @@ these values come from the function's pg_proc entry. fn_stats is also set up to control whether or not to track runtime statistics for calling this function. -fn_collation supplies the collation to use for collation-sensitive -functions. If the function is being called as part of a SQL expression, -fn_expr will point to the expression parse tree for the function call; this -can be used to extract parse-time knowledge about the actual arguments. -Note that these two fields really are information about the arguments -rather than information about the function, but it's proven to be more -convenient to keep them in FmgrInfo than in FunctionCallInfoData where -they might more logically go. +If the function is being called as part of a SQL expression, fn_expr will +point to the expression parse tree for the function call; this can be used +to extract parse-time knowledge about the actual arguments. Note that this +field really is information about the arguments rather than information +about the function, but it's proven to be more convenient to keep it in +FmgrInfo than in FunctionCallInfoData where it might more logically go. During a call of a function, the following data structure is created @@ -110,6 +107,7 @@ typedef struct FmgrInfo *flinfo; /* ptr to lookup info used for this call */ Node *context; /* pass info about context of call */ Node *resultinfo; /* pass or return extra info about result */ + Oid fncollation; /* collation for function to use */ bool isnull; /* function must set true if result is NULL */ short nargs; /* # arguments actually passed */ Datum arg[FUNC_MAX_ARGS]; /* Arguments passed to function */ @@ -137,6 +135,11 @@ function that returns a set, as discussed below.) Like the context field, resultinfo is a hook for expansion; fmgr itself doesn't constrain the use of the field. +fncollation is the input collation derived by the parser, or InvalidOid +when there are no inputs of collatable types or they don't share a common +collation. This is effectively a hidden additional argument, which +collation-sensitive functions can use to determine their behavior. + nargs, arg[], and argnull[] hold the arguments being passed to the function. Notice that all the arguments passed to a function (as well as its result value) will now uniformly be of type Datum. As discussed below, callers diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 0288fbab4bc..ffa19d5a2d2 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -192,7 +192,6 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt, * elogs. */ finfo->fn_oid = InvalidOid; - finfo->fn_collation = InvalidOid; /* caller may set this later */ finfo->fn_extra = NULL; finfo->fn_mcxt = mcxt; finfo->fn_expr = NULL; /* caller may set this later */ @@ -901,7 +900,6 @@ fmgr_security_definer(PG_FUNCTION_ARGS) fmgr_info_cxt_security(fcinfo->flinfo->fn_oid, &fcache->flinfo, fcinfo->flinfo->fn_mcxt, true); - fcache->flinfo.fn_collation = fcinfo->flinfo->fn_collation; fcache->flinfo.fn_expr = fcinfo->flinfo->fn_expr; tuple = SearchSysCache1(PROCOID, @@ -1012,12 +1010,12 @@ fmgr_security_definer(PG_FUNCTION_ARGS) * look at FmgrInfo, since there won't be any. */ Datum -DirectFunctionCall1(PGFunction func, Datum arg1) +DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 1, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.argnull[0] = false; @@ -1032,12 +1030,12 @@ DirectFunctionCall1(PGFunction func, Datum arg1) } Datum -DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2) +DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 2, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1054,13 +1052,13 @@ DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2) } Datum -DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 3, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1079,13 +1077,13 @@ DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 4, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1106,13 +1104,13 @@ DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 5, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1135,14 +1133,14 @@ DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 6, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1167,14 +1165,14 @@ DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 7, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1201,14 +1199,14 @@ DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 8, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1237,7 +1235,7 @@ DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2, } Datum -DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2, +DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9) @@ -1245,7 +1243,7 @@ DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2, FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, NULL, 9, NULL, NULL); + InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1277,71 +1275,17 @@ DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2, /* - * These are the same as DirectFunctionCallN except that a nonzero - * collation can be specified. No other fields of FmgrInfo are made valid. - */ -Datum -DirectFunctionCall1WithCollation(PGFunction func, Oid collation, Datum arg1) -{ - FunctionCallInfoData fcinfo; - FmgrInfo flinfo; - Datum result; - - MemSet(&flinfo, 0, sizeof(flinfo)); - flinfo.fn_collation = collation; - InitFunctionCallInfoData(fcinfo, &flinfo, 1, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.argnull[0] = false; - - result = (*func) (&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %p returned NULL", (void *) func); - - return result; -} - -Datum -DirectFunctionCall2WithCollation(PGFunction func, Oid collation, - Datum arg1, Datum arg2) -{ - FunctionCallInfoData fcinfo; - FmgrInfo flinfo; - Datum result; - - MemSet(&flinfo, 0, sizeof(flinfo)); - flinfo.fn_collation = collation; - InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL); - - fcinfo.arg[0] = arg1; - fcinfo.arg[1] = arg2; - fcinfo.argnull[0] = false; - fcinfo.argnull[1] = false; - - result = (*func) (&fcinfo); - - /* Check for null result, since caller is clearly not expecting one */ - if (fcinfo.isnull) - elog(ERROR, "function %p returned NULL", (void *) func); - - return result; -} - - -/* * These are for invocation of a previously-looked-up function with a * directly-computed parameter list. Note that neither arguments nor result * are allowed to be NULL. */ Datum -FunctionCall1(FmgrInfo *flinfo, Datum arg1) +FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 1, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.argnull[0] = false; @@ -1356,7 +1300,7 @@ FunctionCall1(FmgrInfo *flinfo, Datum arg1) } Datum -FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2) +FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { /* * XXX if you change this routine, see also the inlined version in @@ -1365,7 +1309,7 @@ FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2) FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 2, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1382,13 +1326,13 @@ FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2) } Datum -FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1407,13 +1351,13 @@ FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 4, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1434,13 +1378,13 @@ FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 5, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1463,14 +1407,14 @@ FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 6, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1495,14 +1439,14 @@ FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 7, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1529,14 +1473,14 @@ FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 8, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1565,7 +1509,7 @@ FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2, } Datum -FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2, +FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9) @@ -1573,7 +1517,7 @@ FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2, FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 9, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1612,7 +1556,7 @@ FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2, * do the fmgr_info() once and then use FunctionCallN(). */ Datum -OidFunctionCall0(Oid functionId) +OidFunctionCall0Coll(Oid functionId, Oid collation) { FmgrInfo flinfo; FunctionCallInfoData fcinfo; @@ -1620,7 +1564,7 @@ OidFunctionCall0(Oid functionId) fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 0, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL); result = FunctionCallInvoke(&fcinfo); @@ -1632,7 +1576,7 @@ OidFunctionCall0(Oid functionId) } Datum -OidFunctionCall1(Oid functionId, Datum arg1) +OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1) { FmgrInfo flinfo; FunctionCallInfoData fcinfo; @@ -1640,7 +1584,7 @@ OidFunctionCall1(Oid functionId, Datum arg1) fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 1, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.argnull[0] = false; @@ -1655,7 +1599,7 @@ OidFunctionCall1(Oid functionId, Datum arg1) } Datum -OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2) +OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2) { FmgrInfo flinfo; FunctionCallInfoData fcinfo; @@ -1663,7 +1607,7 @@ OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2) fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1680,7 +1624,7 @@ OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2) } Datum -OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3) { FmgrInfo flinfo; @@ -1689,7 +1633,7 @@ OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1708,7 +1652,7 @@ OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4) { FmgrInfo flinfo; @@ -1717,7 +1661,7 @@ OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 4, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1738,7 +1682,7 @@ OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5) { FmgrInfo flinfo; @@ -1747,7 +1691,7 @@ OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 5, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1770,7 +1714,7 @@ OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6) { @@ -1780,7 +1724,7 @@ OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 6, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1805,7 +1749,7 @@ OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7) { @@ -1815,7 +1759,7 @@ OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 7, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1842,7 +1786,7 @@ OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8) { @@ -1852,7 +1796,7 @@ OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 8, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1881,7 +1825,7 @@ OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2, } Datum -OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2, +OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2, Datum arg3, Datum arg4, Datum arg5, Datum arg6, Datum arg7, Datum arg8, Datum arg9) @@ -1892,7 +1836,7 @@ OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2, fmgr_info(functionId, &flinfo); - InitFunctionCallInfoData(fcinfo, &flinfo, 9, NULL, NULL); + InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -1953,7 +1897,7 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod) pushed = SPI_push_conditional(); - InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL); fcinfo.arg[0] = CStringGetDatum(str); fcinfo.arg[1] = ObjectIdGetDatum(typioparam); @@ -2028,7 +1972,7 @@ ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, pushed = SPI_push_conditional(); - InitFunctionCallInfoData(fcinfo, flinfo, 3, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL); fcinfo.arg[0] = PointerGetDatum(buf); fcinfo.arg[1] = ObjectIdGetDatum(typioparam); diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index bd5b4b0a7d7..dcfb8f957a9 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -373,6 +373,7 @@ struct Tuplesortstate Oid datumType; FmgrInfo sortOpFn; /* cached lookup data for sortOperator */ int sortFnFlags; /* equivalent to sk_flags */ + Oid sortCollation; /* equivalent to sk_collation */ /* we need typelen and byval in order to know how to copy the Datums. */ int datumTypeLen; bool datumTypeByVal; @@ -582,7 +583,8 @@ tuplesort_begin_common(int workMem, bool randomAccess) Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, - Oid *sortOperators, Oid *collations, bool *nullsFirstFlags, + Oid *sortOperators, Oid *sortCollations, + bool *nullsFirstFlags, int workMem, bool randomAccess) { Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess); @@ -647,7 +649,7 @@ tuplesort_begin_heap(TupleDesc tupDesc, attNums[i], InvalidStrategy, InvalidOid, - collations ? collations[i] : InvalidOid, + sortCollations[i], sortFunction, (Datum) 0); } @@ -795,8 +797,8 @@ tuplesort_begin_index_hash(Relation indexRel, } Tuplesortstate * -tuplesort_begin_datum(Oid datumType, - Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, +tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, + bool nullsFirstFlag, int workMem, bool randomAccess) { Tuplesortstate *state = tuplesort_begin_common(workMem, randomAccess); @@ -837,12 +839,12 @@ tuplesort_begin_datum(Oid datumType, elog(ERROR, "operator %u is not a valid ordering operator", sortOperator); fmgr_info(sortFunction, &state->sortOpFn); - fmgr_info_set_collation(sortCollation, &state->sortOpFn); - /* set ordering flags */ + /* set ordering flags and collation */ state->sortFnFlags = reverse ? SK_BT_DESC : 0; if (nullsFirstFlag) state->sortFnFlags |= SK_BT_NULLS_FIRST; + state->sortCollation = sortCollation; /* lookup necessary attributes of the datum type */ get_typlenbyval(datumType, &typlen, &typbyval); @@ -2630,15 +2632,15 @@ SelectSortFunction(Oid sortOperator, } /* - * Inline-able copy of FunctionCall2() to save some cycles in sorting. + * Inline-able copy of FunctionCall2Coll() to save some cycles in sorting. */ static inline Datum -myFunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2) +myFunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2) { FunctionCallInfoData fcinfo; Datum result; - InitFunctionCallInfoData(fcinfo, flinfo, 2, NULL, NULL); + InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL); fcinfo.arg[0] = arg1; fcinfo.arg[1] = arg2; @@ -2661,7 +2663,7 @@ myFunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2) * NULLS_FIRST options are encoded in sk_flags the same way btree does it. */ static inline int32 -inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, +inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, Oid collation, Datum datum1, bool isNull1, Datum datum2, bool isNull2) { @@ -2685,8 +2687,8 @@ inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, } else { - compare = DatumGetInt32(myFunctionCall2(sortFunction, - datum1, datum2)); + compare = DatumGetInt32(myFunctionCall2Coll(sortFunction, collation, + datum1, datum2)); if (sk_flags & SK_BT_DESC) compare = -compare; @@ -2700,11 +2702,11 @@ inlineApplySortFunction(FmgrInfo *sortFunction, int sk_flags, * C99's brain-dead notions about how to implement inline functions... */ int32 -ApplySortFunction(FmgrInfo *sortFunction, int sortFlags, +ApplySortFunction(FmgrInfo *sortFunction, int sortFlags, Oid collation, Datum datum1, bool isNull1, Datum datum2, bool isNull2) { - return inlineApplySortFunction(sortFunction, sortFlags, + return inlineApplySortFunction(sortFunction, sortFlags, collation, datum1, isNull1, datum2, isNull2); } @@ -2729,6 +2731,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state) /* Compare the leading sort key */ compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, a->datum1, a->isnull1, b->datum1, b->isnull1); if (compare != 0) @@ -2753,6 +2756,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state) datum2 = heap_getattr(&rtup, attno, tupDesc, &isnull2); compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, datum1, isnull1, datum2, isnull2); if (compare != 0) @@ -2874,6 +2878,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b, if (state->indexInfo->ii_KeyAttrNumbers[0] != 0) { compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, a->datum1, a->isnull1, b->datum1, b->isnull1); if (compare != 0 || state->nKeys == 1) @@ -2910,6 +2915,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b, compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, datum1, isnull1, datum2, isnull2); if (compare != 0) @@ -2947,6 +2953,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b, { compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, l_index_values[nkey], l_index_isnull[nkey], r_index_values[nkey], @@ -3060,6 +3067,7 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b, /* Compare the leading sort key */ compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, a->datum1, a->isnull1, b->datum1, b->isnull1); if (compare != 0) @@ -3086,6 +3094,7 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b, datum2 = index_getattr(tuple2, nkey, tupDes, &isnull2); compare = inlineApplySortFunction(&scanKey->sk_func, scanKey->sk_flags, + scanKey->sk_collation, datum1, isnull1, datum2, isnull2); if (compare != 0) @@ -3293,6 +3302,7 @@ comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state) CHECK_FOR_INTERRUPTS(); return inlineApplySortFunction(&state->sortOpFn, state->sortFnFlags, + state->sortCollation, a->datum1, a->isnull1, b->datum1, b->isnull1); } |