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:
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
2
src/backend/utils/cache/catcache.c
vendored
2
src/backend/utils/cache/catcache.c
vendored
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user