1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-29 23:43:17 +03:00

Pass collations to functions in FunctionCallInfoData, not FmgrInfo.

Since collation is effectively an argument, not a property of the function,
FmgrInfo is really the wrong place for it; and this becomes critical in
cases where a cached FmgrInfo is used for varying purposes that might need
different collation settings.  Fix by passing it in FunctionCallInfoData
instead.  In particular this allows a clean fix for bug #5970 (record_cmp
not working).  This requires touching a bit more code than the original
method, but nobody ever thought that collations would not be an invasive
patch...
This commit is contained in:
Tom Lane
2011-04-12 19:19:24 -04:00
parent 88543ecfec
commit d64713df7e
49 changed files with 552 additions and 418 deletions

View File

@@ -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. */

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -867,6 +867,7 @@ record_cmp(FunctionCallInfo fcinfo)
while (i1 < ncolumns1 || i2 < ncolumns2)
{
TypeCacheEntry *typentry;
Oid collation;
FunctionCallInfoData locfcinfo;
int32 cmpresult;
@@ -898,6 +899,14 @@ record_cmp(FunctionCallInfo fcinfo)
format_type_be(tupdesc2->attrs[i2]->atttypid),
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
*/
@@ -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;
@@ -1124,6 +1134,14 @@ record_eq(PG_FUNCTION_ARGS)
format_type_be(tupdesc2->attrs[i2]->atttypid),
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
*/
@@ -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;

View File

@@ -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)

View File

@@ -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,

View File

@@ -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

View File

@@ -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;
@@ -1276,72 +1274,18 @@ 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);

View File

@@ -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);
}