int32 res, \
cmp; \
\
- cmp = DatumGetInt32(DirectFunctionCall2WithCollation( \
+ cmp = DatumGetInt32(DirectFunctionCall2Coll( \
TypeInfo_##type.typecmp, \
DEFAULT_COLLATION_OID, \
(data->strategy == BTLessStrategyNumber || \
static bool
gbt_textgt(const void *a, const void *b)
{
- return (DatumGetBool(DirectFunctionCall2WithCollation(text_gt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_gt,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
gbt_textge(const void *a, const void *b)
{
- return (DatumGetBool(DirectFunctionCall2WithCollation(text_ge, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_ge,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
gbt_texteq(const void *a, const void *b)
{
- return (DatumGetBool(DirectFunctionCall2WithCollation(texteq, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(texteq,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
gbt_textle(const void *a, const void *b)
{
- return (DatumGetBool(DirectFunctionCall2WithCollation(text_le, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_le,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static bool
gbt_textlt(const void *a, const void *b)
{
- return (DatumGetBool(DirectFunctionCall2WithCollation(text_lt, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b))));
+ return DatumGetBool(DirectFunctionCall2Coll(text_lt,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static int32
gbt_textcmp(const bytea *a, const bytea *b)
{
- return DatumGetInt32(DirectFunctionCall2WithCollation(bttextcmp, DEFAULT_COLLATION_OID, PointerGetDatum(a), PointerGetDatum(b)));
+ return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
+ DEFAULT_COLLATION_OID,
+ PointerGetDatum(a),
+ PointerGetDatum(b)));
}
static gbtree_vinfo tinfo =
/* Can't use OidFunctionCallN because we might get a NULL result */
fmgr_info(amoptions, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 2, NULL, NULL);
+ InitFunctionCallInfoData(fcinfo, &flinfo, 2, InvalidOid, NULL, NULL);
fcinfo.arg[0] = reloptions;
fcinfo.arg[1] = BoolGetDatum(validate);
entry->sk_attno = attributeNumber;
entry->sk_strategy = strategy;
entry->sk_subtype = subtype;
+ entry->sk_collation = collation;
entry->sk_argument = argument;
if (RegProcedureIsValid(procedure))
{
fmgr_info(procedure, &entry->sk_func);
- entry->sk_func.fn_collation = collation;
}
else
{
entry->sk_attno = attributeNumber;
entry->sk_strategy = strategy;
entry->sk_subtype = InvalidOid;
+ entry->sk_collation = DEFAULT_COLLATION_OID;
entry->sk_argument = argument;
fmgr_info(procedure, &entry->sk_func);
- entry->sk_func.fn_collation = DEFAULT_COLLATION_OID;
}
/*
entry->sk_attno = attributeNumber;
entry->sk_strategy = strategy;
entry->sk_subtype = subtype;
+ entry->sk_collation = collation;
entry->sk_argument = argument;
fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext);
- entry->sk_func.fn_collation = collation;
}
*/
key->recheckCurItem = true;
- return DatumGetBool(FunctionCall8(&ginstate->consistentFn[key->attnum - 1],
- PointerGetDatum(key->entryRes),
- UInt16GetDatum(key->strategy),
- key->query,
- UInt32GetDatum(key->nuserentries),
- PointerGetDatum(key->extra_data),
- PointerGetDatum(&key->recheckCurItem),
- PointerGetDatum(key->queryValues),
- PointerGetDatum(key->queryCategories)));
+ return DatumGetBool(FunctionCall8Coll(&ginstate->consistentFn[key->attnum - 1],
+ ginstate->compareCollation[key->attnum - 1],
+ PointerGetDatum(key->entryRes),
+ UInt16GetDatum(key->strategy),
+ key->query,
+ UInt32GetDatum(key->nuserentries),
+ PointerGetDatum(key->extra_data),
+ PointerGetDatum(&key->recheckCurItem),
+ PointerGetDatum(key->queryValues),
+ PointerGetDatum(key->queryCategories)));
}
/*
* case cmp < 0 => not match and continue scan
*----------
*/
- cmp = DatumGetInt32(FunctionCall4(&btree->ginstate->comparePartialFn[attnum - 1],
- scanEntry->queryKey,
- idatum,
+ cmp = DatumGetInt32(FunctionCall4Coll(&btree->ginstate->comparePartialFn[attnum - 1],
+ btree->ginstate->compareCollation[attnum - 1],
+ scanEntry->queryKey,
+ idatum,
UInt16GetDatum(scanEntry->strategy),
PointerGetDatum(scanEntry->extra_data)));
* case cmp < 0 => not match and continue scan
*----------
*/
- cmp = DatumGetInt32(FunctionCall4(&ginstate->comparePartialFn[entry->attnum - 1],
- entry->queryKey,
- datum[off - 1],
+ cmp = DatumGetInt32(FunctionCall4Coll(&ginstate->comparePartialFn[entry->attnum - 1],
+ ginstate->compareCollation[entry->attnum - 1],
+ entry->queryKey,
+ datum[off - 1],
UInt16GetDatum(entry->strategy),
PointerGetDatum(entry->extra_data)));
if (cmp == 0)
fmgr_info_copy(&(state->compareFn[i]),
index_getprocinfo(index, i + 1, GIN_COMPARE_PROC),
CurrentMemoryContext);
-
- /*
- * If the index column has a specified collation, index_getprocinfo
- * will have installed it into the fmgr info, and we should honor it.
- * However, we may have a collatable storage type for a noncollatable
- * indexed data type (for instance, hstore uses text index entries).
- * If there's no index collation then specify default collation in
- * case the comparison function needs one. This is harmless if the
- * comparison function doesn't care about collation, so we just do it
- * unconditionally. (We could alternatively call get_typcollation,
- * but that seems like expensive overkill --- there aren't going to be
- * any cases where a GIN storage type has a nondefault collation.)
- */
- if (!OidIsValid(state->compareFn[i].fn_collation))
- fmgr_info_set_collation(DEFAULT_COLLATION_OID,
- &(state->compareFn[i]));
-
fmgr_info_copy(&(state->extractValueFn[i]),
index_getprocinfo(index, i + 1, GIN_EXTRACTVALUE_PROC),
CurrentMemoryContext);
fmgr_info_copy(&(state->comparePartialFn[i]),
index_getprocinfo(index, i + 1, GIN_COMPARE_PARTIAL_PROC),
CurrentMemoryContext);
-
- /* As above, install collation spec in case compare fn needs it */
- if (!OidIsValid(state->comparePartialFn[i].fn_collation))
- fmgr_info_set_collation(DEFAULT_COLLATION_OID,
- &(state->comparePartialFn[i]));
-
state->canPartialMatch[i] = true;
}
else
{
state->canPartialMatch[i] = false;
}
+
+ /*
+ * If the index column has a specified collation, we should honor that
+ * while doing comparisons. However, we may have a collatable storage
+ * type for a noncollatable indexed data type (for instance, hstore
+ * uses text index entries). If there's no index collation then
+ * specify default collation in case the comparison function needs
+ * collation. This is harmless if the comparison function doesn't
+ * care about collation, so we just do it unconditionally. (We could
+ * alternatively call get_typcollation, but that seems like expensive
+ * overkill --- there aren't going to be any cases where a GIN storage
+ * type has a nondefault collation.)
+ */
+ if (OidIsValid(index->rd_indcollation[i]))
+ state->compareCollation[i] = index->rd_indcollation[i];
+ else
+ state->compareCollation[i] = DEFAULT_COLLATION_OID;
}
}
return 0;
/* both not null, so safe to call the compareFn */
- return DatumGetInt32(FunctionCall2(&ginstate->compareFn[attnum - 1],
- a, b));
+ return DatumGetInt32(FunctionCall2Coll(&ginstate->compareFn[attnum - 1],
+ ginstate->compareCollation[attnum - 1],
+ a, b));
}
/*
typedef struct
{
FmgrInfo *cmpDatumFunc;
+ Oid collation;
bool haveDups;
} cmpEntriesArg;
else if (bb->isnull)
res = -1; /* not-NULL "<" NULL */
else
- res = DatumGetInt32(FunctionCall2(data->cmpDatumFunc,
- aa->datum, bb->datum));
+ res = DatumGetInt32(FunctionCall2Coll(data->cmpDatumFunc,
+ data->collation,
+ aa->datum, bb->datum));
/*
* Detect if we have any duplicates. If there are equal keys, qsort must
}
arg.cmpDatumFunc = &ginstate->compareFn[attnum - 1];
+ arg.collation = ginstate->compareCollation[attnum - 1];
arg.haveDups = false;
qsort_arg(keydata, *nentries, sizeof(keyEntryData),
cmpEntries, (void *) &arg);
*/
recheck = true;
- test = FunctionCall5(&key->sk_func,
- PointerGetDatum(&de),
- key->sk_argument,
- Int32GetDatum(key->sk_strategy),
- ObjectIdGetDatum(key->sk_subtype),
- PointerGetDatum(&recheck));
+ test = FunctionCall5Coll(&key->sk_func,
+ key->sk_collation,
+ PointerGetDatum(&de),
+ key->sk_argument,
+ Int32GetDatum(key->sk_strategy),
+ ObjectIdGetDatum(key->sk_subtype),
+ PointerGetDatum(&recheck));
if (!DatumGetBool(test))
return false;
* can't tolerate lossy distance calculations on leaf tuples;
* there is no opportunity to re-sort the tuples afterwards.
*/
- dist = FunctionCall4(&key->sk_func,
- PointerGetDatum(&de),
- key->sk_argument,
- Int32GetDatum(key->sk_strategy),
- ObjectIdGetDatum(key->sk_subtype));
+ dist = FunctionCall4Coll(&key->sk_func,
+ key->sk_collation,
+ PointerGetDatum(&de),
+ key->sk_argument,
+ Int32GetDatum(key->sk_strategy),
+ ObjectIdGetDatum(key->sk_subtype));
*distance_p = DatumGetFloat8(dist);
}
* comparisons. The original operator is passed to the Consistent
* function in the form of its strategy number, which is available
* from the sk_strategy field, and its subtype from the sk_subtype
- * field. Also, preserve sk_func.fn_collation which is the input
- * collation for the operator.
+ * field.
*
* Next, if any of keys is a NULL and that key is not marked with
* SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we
for (i = 0; i < scan->numberOfKeys; i++)
{
ScanKey skey = scan->keyData + i;
- Oid collation = skey->sk_func.fn_collation;
skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1];
- skey->sk_func.fn_collation = collation;
if (skey->sk_flags & SK_ISNULL)
{
* all comparisons. The original operator is passed to the Distance
* function in the form of its strategy number, which is available
* from the sk_strategy field, and its subtype from the sk_subtype
- * field. Also, preserve sk_func.fn_collation which is the input
- * collation for the operator.
+ * field.
*/
for (i = 0; i < scan->numberOfOrderBys; i++)
{
ScanKey skey = scan->orderByData + i;
- Oid collation = skey->sk_func.fn_collation;
skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1];
- skey->sk_func.fn_collation = collation;
/* Check we actually have a distance function ... */
if (!OidIsValid(skey->sk_func.fn_oid))
if (key->sk_flags & SK_ISNULL)
return false;
- test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
+ test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
+ datum, key->sk_argument);
if (!DatumGetBool(test))
return false;
procnum, attnum, RelationGetRelationName(irel));
fmgr_info_cxt(procId, locinfo, irel->rd_indexcxt);
- fmgr_info_set_collation(irel->rd_indcollation[attnum - 1], locinfo);
}
return locinfo;
if (isNull || (scankey->sk_flags & SK_ISNULL))
return false;
- result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
- datum,
- scankey->sk_argument));
+ result = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+ scankey->sk_collation,
+ datum,
+ scankey->sk_argument));
if (result != 0)
return false;
* to flip the sign of the comparison result. (Unless it's a DESC
* column, in which case we *don't* flip the sign.)
*/
- result = DatumGetInt32(FunctionCall2(&scankey->sk_func,
- datum,
- scankey->sk_argument));
+ result = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+ scankey->sk_collation,
+ datum,
+ scankey->sk_argument));
if (!(scankey->sk_flags & SK_BT_DESC))
result = -result;
cur->sk_attno,
InvalidStrategy,
cur->sk_subtype,
- cur->sk_func.fn_collation,
+ cur->sk_collation,
procinfo,
cur->sk_argument);
}
cur->sk_attno,
InvalidStrategy,
cur->sk_subtype,
- cur->sk_func.fn_collation,
+ cur->sk_collation,
cmp_proc,
cur->sk_argument);
}
}
else
{
- compare = DatumGetInt32(FunctionCall2(&entry->sk_func,
- attrDatum1,
- attrDatum2));
+ compare =
+ DatumGetInt32(FunctionCall2Coll(&entry->sk_func,
+ entry->sk_collation,
+ attrDatum1,
+ attrDatum2));
if (entry->sk_flags & SK_BT_DESC)
compare = -compare;
/*
* We can use the cached (default) support procs since no cross-type
- * comparison can be needed. The cached support proc entries have the
- * right collation for the index, too.
+ * comparison can be needed.
*/
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
arg = index_getattr(itup, i + 1, itupdesc, &null);
(AttrNumber) (i + 1),
InvalidStrategy,
InvalidOid,
- procinfo->fn_collation,
+ rel->rd_indcollation[i],
procinfo,
arg);
}
/*
* We can use the cached (default) support procs since no cross-type
- * comparison can be needed. The cached support proc entries have the
- * right collation for the index, too.
+ * comparison can be needed.
*/
procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
flags = SK_ISNULL | (indoption[i] << SK_BT_INDOPTION_SHIFT);
(AttrNumber) (i + 1),
InvalidStrategy,
InvalidOid,
- procinfo->fn_collation,
+ rel->rd_indcollation[i],
procinfo,
(Datum) 0);
}
*/
if (lefttype == opcintype && righttype == optype)
{
- *result = DatumGetBool(FunctionCall2(&op->sk_func,
- leftarg->sk_argument,
- rightarg->sk_argument));
+ *result = DatumGetBool(FunctionCall2Coll(&op->sk_func,
+ op->sk_collation,
+ leftarg->sk_argument,
+ rightarg->sk_argument));
return true;
}
if (RegProcedureIsValid(cmp_proc))
{
- *result = DatumGetBool(OidFunctionCall2(cmp_proc,
- leftarg->sk_argument,
- rightarg->sk_argument));
+ *result = DatumGetBool(OidFunctionCall2Coll(cmp_proc,
+ op->sk_collation,
+ leftarg->sk_argument,
+ rightarg->sk_argument));
return true;
}
}
* Likewise, "x IS NOT NULL" is supported. We treat that as either "less
* than NULL" in a NULLS LAST index, or "greater than NULL" in a NULLS
* FIRST index.
+ *
+ * Note: someday we might have to fill in sk_collation from the index
+ * column's collation. At the moment this is a non-issue because we'll
+ * never actually call the comparison operator on a NULL.
*/
if (skey->sk_flags & SK_ISNULL)
{
{
skey->sk_strategy = BTEqualStrategyNumber;
skey->sk_subtype = InvalidOid;
+ skey->sk_collation = InvalidOid;
}
else if (skey->sk_flags & SK_SEARCHNOTNULL)
{
else
skey->sk_strategy = BTLessStrategyNumber;
skey->sk_subtype = InvalidOid;
+ skey->sk_collation = InvalidOid;
}
else
{
return false;
}
- test = FunctionCall2(&key->sk_func, datum, key->sk_argument);
+ test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
+ datum, key->sk_argument);
if (!DatumGetBool(test))
{
}
/* Perform the test --- three-way comparison not bool operator */
- cmpresult = DatumGetInt32(FunctionCall2(&subkey->sk_func,
- datum,
- subkey->sk_argument));
+ cmpresult = DatumGetInt32(FunctionCall2Coll(&subkey->sk_func,
+ subkey->sk_collation,
+ datum,
+ subkey->sk_argument));
if (subkey->sk_flags & SK_BT_DESC)
cmpresult = -cmpresult;
track_cnt = 0;
fmgr_info(mystats->eqfunc, &f_cmpeq);
- /* We always use the default collation for statistics */
- fmgr_info_set_collation(DEFAULT_COLLATION_OID, &f_cmpeq);
for (i = 0; i < samplerows; i++)
{
firstcount1 = track_cnt;
for (j = 0; j < track_cnt; j++)
{
- if (DatumGetBool(FunctionCall2(&f_cmpeq, value, track[j].value)))
+ /* We always use the default collation for statistics */
+ if (DatumGetBool(FunctionCall2Coll(&f_cmpeq,
+ DEFAULT_COLLATION_OID,
+ value, track[j].value)))
{
match = true;
break;
SelectSortFunction(mystats->ltopr, false, &cmpFn, &cmpFlags);
fmgr_info(cmpFn, &f_cmpfn);
- /* We always use the default collation for statistics */
- fmgr_info_set_collation(DEFAULT_COLLATION_OID, &f_cmpfn);
/* Initial scan to find sortable values */
for (i = 0; i < samplerows; i++)
CompareScalarsContext *cxt = (CompareScalarsContext *) arg;
int32 compare;
+ /* We always use the default collation for statistics */
compare = ApplySortFunction(cxt->cmpFn, cxt->cmpFlags,
+ DEFAULT_COLLATION_OID,
da, false, db, false);
if (compare != 0)
return compare;
/*
* Call the function, passing no arguments but setting a context.
*/
- InitFunctionCallInfoData(fcinfo, finfo, 0, (Node *) trigdata, NULL);
+ InitFunctionCallInfoData(fcinfo, finfo, 0,
+ InvalidOid, (Node *) trigdata, NULL);
pgstat_init_function_usage(&fcinfo, &fcusage);
break;
case Anum_pg_ts_parser_prslextype:
nargs = 1;
+ /*
+ * Note: because the lextype method returns type internal, it must
+ * have an internal-type argument for security reasons. The
+ * argument is not actually used, but is just passed as a zero.
+ */
break;
default:
/* should not be here */
elog(ERROR, "method lextype isn't defined for text search parser %u",
prsId);
- /* OidFunctionCall0 is absent */
+ /* lextype takes one dummy argument */
list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
(Datum) 0));
* execGrouping.c
* executor utility routines for grouping, hashing, and aggregation
*
+ * Note: we currently assume that equality and hashing functions are not
+ * collation-sensitive, so the code in this file has no support for passing
+ * collation settings through from callers. That may have to change someday.
+ *
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
- fmgr_info_set_collation(input_collation, &(fcache->func));
fmgr_info_set_expr((Node *) fcache->xprstate.expr, &(fcache->func));
/* Initialize the function call parameter struct as well */
InitFunctionCallInfoData(fcache->fcinfo_data, &(fcache->func),
- list_length(fcache->args), NULL, NULL);
+ list_length(fcache->args),
+ input_collation, NULL, NULL);
/* If function returns set, prepare expected tuple descriptor */
if (fcache->func.fn_retset && needDescForSets)
returnsSet = fcache->func.fn_retset;
InitFunctionCallInfoData(fcinfo, &(fcache->func),
list_length(fcache->args),
+ fcache->fcinfo_data.fncollation,
NULL, (Node *) &rsinfo);
/*
{
/* Treat funcexpr as a generic expression */
direct_function_call = false;
- InitFunctionCallInfoData(fcinfo, NULL, 0, NULL, NULL);
+ InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
}
/*
FunctionCallInfoData locfcinfo;
InitFunctionCallInfoData(locfcinfo, &(rstate->funcs[i]), 2,
+ rstate->collations[i],
NULL, NULL);
locfcinfo.arg[0] = ExecEvalExpr(le, econtext,
&locfcinfo.argnull[0], NULL);
bool *isNull, ExprDoneCond *isDone)
{
Datum result = (Datum) 0;
- MinMaxOp op = ((MinMaxExpr *) minmaxExpr->xprstate.expr)->op;
+ MinMaxExpr *minmax = (MinMaxExpr *) minmaxExpr->xprstate.expr;
+ Oid collation = minmax->inputcollid;
+ MinMaxOp op = minmax->op;
FunctionCallInfoData locfcinfo;
ListCell *arg;
*isDone = ExprSingleResult;
*isNull = true; /* until we get a result */
- InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2, NULL, NULL);
+ InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2,
+ collation, NULL, NULL);
locfcinfo.argnull[0] = false;
locfcinfo.argnull[1] = false;
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc),
econtext->ecxt_per_query_memory);
- /* Note: coercion functions are assumed to not use collation */
fmgr_info_set_expr((Node *) acoerce, &(astate->elemfunc));
}
*
* We pass on the desttypmod and isExplicit flags whether or not the
* function wants them.
+ *
+ * Note: coercion functions are assumed to not use collation.
*/
InitFunctionCallInfoData(locfcinfo, &(astate->elemfunc), 3,
- NULL, NULL);
+ InvalidOid, NULL, NULL);
locfcinfo.arg[0] = PointerGetDatum(array);
locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod);
locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit);
rstate->rargs = outlist;
Assert(list_length(rcexpr->opfamilies) == nopers);
rstate->funcs = (FmgrInfo *) palloc(nopers * sizeof(FmgrInfo));
+ rstate->collations = (Oid *) palloc(nopers * sizeof(Oid));
i = 0;
forthree(l, rcexpr->opnos, l2, rcexpr->opfamilies, l3, rcexpr->inputcollids)
{
* does this code.
*/
fmgr_info(proc, &(rstate->funcs[i]));
- fmgr_info_set_collation(inputcollid, &(rstate->funcs[i]));
+ rstate->collations[i] = inputcollid;
i++;
}
state = (ExprState *) rstate;
* code.
*/
fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
- fmgr_info_set_collation(minmaxexpr->inputcollid,
- &(mstate->cfunc));
state = (ExprState *) mstate;
}
break;
if (existing_isnull[i])
return false;
- if (!DatumGetBool(OidFunctionCall2(constr_procs[i],
- existing_values[i],
- new_values[i])))
+ if (!DatumGetBool(OidFunctionCall2Coll(constr_procs[i],
+ index->rd_indcollation[i],
+ existing_values[i],
+ new_values[i])))
return false;
}
static List *init_execution_state(List *queryTree_list,
SQLFunctionCachePtr fcache,
bool lazyEvalOK);
-static void init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK);
+static void init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK);
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
static void postquel_end(execution_state *es);
* Initialize the SQLFunctionCache for a SQL function
*/
static void
-init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
+init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
{
Oid foid = finfo->fn_oid;
Oid rettype;
*/
fcache->pinfo = prepare_sql_fn_parse_info(procedureTuple,
finfo->fn_expr,
- finfo->fn_collation);
+ collation);
/*
* And of course we need the function body text.
fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
if (fcache == NULL)
{
- init_sql_fcache(fcinfo->flinfo, lazyEvalOK);
+ init_sql_fcache(fcinfo->flinfo, PG_GET_COLLATION(), lazyEvalOK);
fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
}
eslist = fcache->func_state;
FmgrInfo transfn;
FmgrInfo finalfn;
+ /* Input collation derived for aggregate */
+ Oid aggCollation;
+
/* number of sorting columns */
int numSortCols;
*/
InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
numArguments + 1,
+ peraggstate->aggCollation,
(void *) aggstate, NULL);
fcinfo->arg[0] = pergroupstate->transValue;
fcinfo->argnull[0] = pergroupstate->transValueIsNull;
/*
* If DISTINCT mode, and not distinct from prior, skip it.
+ *
+ * Note: we assume equality functions don't care about collation.
*/
if (isDistinct &&
haveOldVal &&
FunctionCallInfoData fcinfo;
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+ peraggstate->aggCollation,
(void *) aggstate, NULL);
fcinfo.arg[0] = pergroupstate->transValue;
fcinfo.argnull[0] = pergroupstate->transValueIsNull;
&finalfnexpr);
fmgr_info(transfn_oid, &peraggstate->transfn);
- fmgr_info_set_collation(aggref->inputcollid, &peraggstate->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
if (OidIsValid(finalfn_oid))
{
fmgr_info(finalfn_oid, &peraggstate->finalfn);
- fmgr_info_set_collation(aggref->inputcollid, &peraggstate->finalfn);
fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
}
+ peraggstate->aggCollation = aggref->inputcollid;
+
get_typlenbyval(aggref->aggtype,
&peraggstate->resulttypeLen,
&peraggstate->resulttypeByVal);
SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
- fmgr_info_set_collation(aggref->inputcollid,
- &peraggstate->equalfns[i]);
i++;
}
Assert(i == numDistinctCols);
this_scan_key->sk_flags = SK_ROW_HEADER;
this_scan_key->sk_attno = first_sub_key->sk_attno;
this_scan_key->sk_strategy = rc->rctype;
- /* sk_subtype, sk_func not used in a header */
+ /* sk_subtype, sk_collation, sk_func not used in a header */
this_scan_key->sk_argument = PointerGetDatum(first_sub_key);
}
else if (IsA(clause, ScalarArrayOpExpr))
}
else
{
- compare = DatumGetInt32(FunctionCall2(&scankey->sk_func,
- datum1, datum2));
+ compare = DatumGetInt32(FunctionCall2Coll(&scankey->sk_func,
+ scankey->sk_collation,
+ datum1, datum2));
if (compare != 0)
{
if (scankey->sk_flags & SK_BT_DESC)
/*
* The comparison strategy in use, and the lookup info to let us call the
- * btree comparison support function.
+ * btree comparison support function, and the collation to use.
*/
bool reverse; /* if true, negate the cmpfn's output */
bool nulls_first; /* if true, nulls sort low */
FmgrInfo cmpfinfo;
+ Oid collation;
} MergeJoinClauseData;
/* Result type for MJEvalOuterValues and MJEvalInnerValues */
/* Set up the fmgr lookup information */
fmgr_info(cmpproc, &(clause->cmpfinfo));
- fmgr_info_set_collation(collation, &(clause->cmpfinfo));
/* Fill the additional comparison-strategy flags */
if (opstrategy == BTLessStrategyNumber)
clause->nulls_first = nulls_first;
+ /* ... and the collation too */
+ clause->collation = collation;
+
iClause++;
}
* OK to call the comparison function.
*/
InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,
- NULL, NULL);
+ clause->collation, NULL, NULL);
fcinfo.arg[0] = clause->ldatum;
fcinfo.arg[1] = clause->rdatum;
fcinfo.argnull[0] = false;
/* Lookup the equality function (potentially cross-type) */
fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]);
- fmgr_info_set_collation(opexpr->inputcollid,
- &sstate->cur_eq_funcs[i - 1]);
fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]);
/* Look up the equality function for the RHS type */
elog(ERROR, "could not find compatible hash operator for operator %u",
opexpr->opno);
fmgr_info(get_opcode(rhs_eq_oper), &sstate->tab_eq_funcs[i - 1]);
- fmgr_info_set_collation(opexpr->inputcollid,
- &sstate->tab_eq_funcs[i - 1]);
/* Lookup the associated hash functions */
if (!get_op_hash_functions(opexpr->opno,
FmgrInfo flinfo; /* fmgr lookup data for window function */
+ Oid winCollation; /* collation derived for window function */
+
/*
* We need the len and byval info for the result of each function in order
* to know how to copy/delete values.
*/
InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
numArguments + 1,
+ perfuncstate->winCollation,
(void *) winstate, NULL);
fcinfo->arg[0] = peraggstate->transValue;
fcinfo->argnull[0] = peraggstate->transValueIsNull;
FunctionCallInfoData fcinfo;
InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+ perfuncstate->winCollation,
(void *) winstate, NULL);
fcinfo.arg[0] = peraggstate->transValue;
fcinfo.argnull[0] = peraggstate->transValueIsNull;
*/
InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo),
perfuncstate->numArguments,
+ perfuncstate->winCollation,
(void *) perfuncstate->winobj, NULL);
/* Just in case, make all the regular argument slots be null */
memset(fcinfo.argnull, true, perfuncstate->numArguments);
fmgr_info_cxt(wfunc->winfnoid, &perfuncstate->flinfo,
econtext->ecxt_per_query_memory);
- fmgr_info_set_collation(wfunc->inputcollid, &perfuncstate->flinfo);
fmgr_info_set_expr((Node *) wfunc, &perfuncstate->flinfo);
+ perfuncstate->winCollation = wfunc->inputcollid;
+
get_typlenbyval(wfunc->wintype,
&perfuncstate->resulttypeLen,
&perfuncstate->resulttypeByVal);
&finalfnexpr);
fmgr_info(transfn_oid, &peraggstate->transfn);
- fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
if (OidIsValid(finalfn_oid))
{
fmgr_info(finalfn_oid, &peraggstate->finalfn);
- fmgr_info_set_collation(wfunc->inputcollid, &peraggstate->finalfn);
fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
}
if (oproid == InvalidOid)
elog(ERROR, "no < operator for opfamily %u", opfamily);
fmgr_info(get_opcode(oproid), <proc);
- fmgr_info_set_collation(collation, <proc);
- greaterstr = make_greater_string(prefix_const, <proc);
+ greaterstr = make_greater_string(prefix_const, <proc, collation);
if (greaterstr)
{
expr = make_opclause(oproid, BOOLOID, false,
/*
* Prepare function call info block and insert arguments.
+ *
+ * Note: for now we pass collation = InvalidOid, so collation-sensitive
+ * functions can't be called this way. Perhaps we should pass
+ * DEFAULT_COLLATION_OID, instead?
*/
- InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, NULL, NULL);
+ InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);
st = (TSTokenTypeStorage *) palloc(sizeof(TSTokenTypeStorage));
st->cur = 0;
- /* OidFunctionCall0 is absent */
+ /* lextype takes one dummy argument */
st->list = (LexDescr *) DatumGetPointer(OidFunctionCall1(prs->lextypeOid,
(Datum) 0));
funcctx->user_fctx = (void *) st;
{
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);
* 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);
*/
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);
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;
* 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);
* 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);
* 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);
* 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));
{
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. */
{
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. */
{
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. */
* 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);
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)
* 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);
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));
}
while (i1 < ncolumns1 || i2 < ncolumns2)
{
TypeCacheEntry *typentry;
+ Oid collation;
FunctionCallInfoData locfcinfo;
int32 cmpresult;
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
*/
/* 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;
while (i1 < ncolumns1 || i2 < ncolumns2)
{
TypeCacheEntry *typentry;
+ Oid collation;
FunctionCallInfoData locfcinfo;
bool oprresult;
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
*/
/* 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;
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;
}
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
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];
}
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));
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)
/* 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);
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);
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));
{
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];
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));
{
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++;
FmgrInfo opproc;
fmgr_info(get_opcode(sortop), &opproc);
- fmgr_info_set_collation(DEFAULT_COLLATION_OID, &opproc);
for (i = 0; i < nvalues; i++)
{
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;
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,
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;
* 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
* 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;
{
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
{
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 */
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)
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,
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 */
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
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 */
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
* 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 */
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,
* 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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)
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;
}
-/*
- * 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;
}
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
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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)
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;
* do the fmgr_info() once and then use FunctionCallN().
*/
Datum
-OidFunctionCall0(Oid functionId)
+OidFunctionCall0Coll(Oid functionId, Oid collation)
{
FmgrInfo flinfo;
FunctionCallInfoData fcinfo;
fmgr_info(functionId, &flinfo);
- InitFunctionCallInfoData(fcinfo, &flinfo, 0, NULL, NULL);
+ InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL);
result = FunctionCallInvoke(&fcinfo);
}
Datum
-OidFunctionCall1(Oid functionId, Datum arg1)
+OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
{
FmgrInfo flinfo;
FunctionCallInfoData fcinfo;
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;
}
Datum
-OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2)
+OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
{
FmgrInfo flinfo;
FunctionCallInfoData fcinfo;
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;
}
Datum
-OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
Datum arg3)
{
FmgrInfo flinfo;
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;
}
Datum
-OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
+OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
Datum arg3, Datum arg4)
{
FmgrInfo flinfo;
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;
}
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;
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;
}
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)
{
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;
}
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)
{
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;
}
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)
{
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;
}
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)
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;
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);
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);
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;
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);
attNums[i],
InvalidStrategy,
InvalidOid,
- collations ? collations[i] : InvalidOid,
+ sortCollations[i],
sortFunction,
(Datum) 0);
}
}
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);
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);
}
/*
- * 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;
* 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)
{
}
else
{
- compare = DatumGetInt32(myFunctionCall2(sortFunction,
- datum1, datum2));
+ compare = DatumGetInt32(myFunctionCall2Coll(sortFunction, collation,
+ datum1, datum2));
if (sk_flags & SK_BT_DESC)
compare = -compare;
* 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);
}
/* 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)
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)
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)
compare = inlineApplySortFunction(&scanKey->sk_func,
scanKey->sk_flags,
+ scanKey->sk_collation,
datum1, isnull1,
datum2, isnull2);
if (compare != 0)
{
compare = inlineApplySortFunction(&scanKey->sk_func,
scanKey->sk_flags,
+ scanKey->sk_collation,
l_index_values[nkey],
l_index_isnull[nkey],
r_index_values[nkey],
/* 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)
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)
CHECK_FOR_INTERRUPTS();
return inlineApplySortFunction(&state->sortOpFn, state->sortFnFlags,
+ state->sortCollation,
a->datum1, a->isnull1,
b->datum1, b->isnull1);
}
FmgrInfo comparePartialFn[INDEX_MAX_KEYS]; /* optional method */
/* canPartialMatch[i] is true if comparePartialFn[i] is valid */
bool canPartialMatch[INDEX_MAX_KEYS];
+ /* Collations to supply to the compareFns and comparePartialFns */
+ Oid compareCollation[INDEX_MAX_KEYS];
} GinState;
/* XLog stuff */
* the operator. When using a ScanKey in a heap scan, these fields are not
* used and may be set to InvalidStrategy/InvalidOid.
*
- * If the operator is collation-sensitive, sk_func.fn_collation must be set
+ * If the operator is collation-sensitive, sk_collation must be set
* correctly as well.
*
* A ScanKey can also represent a condition "column IS NULL" or "column
* IS NOT NULL"; these cases are signaled by the SK_SEARCHNULL and
* SK_SEARCHNOTNULL flag bits respectively. The argument is always NULL,
- * and the sk_strategy, sk_subtype, and sk_func fields are not used (unless
- * set by the index AM). Currently, SK_SEARCHNULL and SK_SEARCHNOTNULL are
- * supported only for index scans, not heap scans; and not all index AMs
- * support them.
+ * and the sk_strategy, sk_subtype, sk_collation, and sk_func fields are
+ * not used (unless set by the index AM). Currently, SK_SEARCHNULL and
+ * SK_SEARCHNOTNULL are supported only for index scans, not heap scans;
+ * and not all index AMs support them.
*
* A ScanKey can also represent an ordering operator invocation, that is
* an ordering requirement "ORDER BY indexedcol op constant". This looks
*
* Note: in some places, ScanKeys are used as a convenient representation
* for the invocation of an access method support procedure. In this case
- * sk_strategy/sk_subtype are not meaningful, and sk_func may refer to a
- * function that returns something other than boolean.
+ * sk_strategy/sk_subtype are not meaningful (but sk_collation can be); and
+ * sk_func may refer to a function that returns something other than boolean.
*/
typedef struct ScanKeyData
{
AttrNumber sk_attno; /* table or index column number */
StrategyNumber sk_strategy; /* operator strategy number */
Oid sk_subtype; /* strategy subtype */
+ Oid sk_collation; /* collation to use, if needed */
FmgrInfo sk_func; /* lookup info for function to call */
Datum sk_argument; /* data to compare */
} ScanKeyData;
* sk_attno = index column number for leading column of row comparison
* sk_strategy = btree strategy code for semantics of row comparison
* (ie, < <= > or >=)
- * sk_subtype, sk_func: not used
+ * sk_subtype, sk_collation, sk_func: not used
* sk_argument: pointer to subsidiary ScanKey array
* If the header is part of a ScanKey array that's sorted by attno, it
* must be sorted according to the leading column number.
break; \
} \
\
- __test = FunctionCall2(&__cur_keys->sk_func, \
- __atp, __cur_keys->sk_argument); \
+ __test = FunctionCall2Coll(&__cur_keys->sk_func, \
+ __cur_keys->sk_collation, \
+ __atp, __cur_keys->sk_argument); \
\
if (!DatumGetBool(__test)) \
{ \
* to be called multiple times, the lookup need be done only once and the
* info struct saved for re-use.
*
- * Note that fn_collation and fn_expr really are parse-time-determined
- * information about the arguments, rather than about the function itself.
- * But it's convenient to store them here rather than in FunctionCallInfoData,
- * where they might more logically belong.
+ * Note that fn_expr really is parse-time-determined information about the
+ * arguments, rather than about the function itself. But it's convenient
+ * to store it here rather than in FunctionCallInfoData, where it might more
+ * logically belong.
*/
typedef struct FmgrInfo
{
bool fn_strict; /* function is "strict" (NULL in => NULL out) */
bool fn_retset; /* function returns a set */
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 */
fmNodePtr fn_expr; /* expression parse tree for call, or NULL */
FmgrInfo *flinfo; /* ptr to lookup info used for this call */
fmNodePtr context; /* pass info about context of call */
fmNodePtr 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 */
extern void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo,
MemoryContext mcxt);
-/* Macros for setting the fn_collation and fn_expr fields */
-#define fmgr_info_set_collation(collationId, finfo) \
- ((finfo)->fn_collation = (collationId))
+/* Convenience macro for setting the fn_expr field */
#define fmgr_info_set_expr(expr, finfo) \
((finfo)->fn_expr = (expr))
* explicitly set each required element to false, so we don't try to zero
* out the argnull[] array in the macro.
*/
-#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Context, Resultinfo) \
+#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo) \
do { \
(Fcinfo).flinfo = (Flinfo); \
(Fcinfo).context = (Context); \
(Fcinfo).resultinfo = (Resultinfo); \
+ (Fcinfo).fncollation = (Collation); \
(Fcinfo).isnull = false; \
(Fcinfo).nargs = (Nargs); \
} while (0)
/*
* Get collation function should use.
*/
-#define PG_GET_COLLATION() \
- (fcinfo->flinfo ? fcinfo->flinfo->fn_collation : InvalidOid)
+#define PG_GET_COLLATION() (fcinfo->fncollation)
/*
* Get number of arguments passed to function.
* directly-computed parameter list. Note that neither arguments nor result
* are allowed to be NULL.
*/
-extern Datum DirectFunctionCall1(PGFunction func, Datum arg1);
-extern Datum DirectFunctionCall2(PGFunction func, Datum arg1, Datum arg2);
-extern Datum DirectFunctionCall3(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation,
+ Datum arg1);
+extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3);
-extern Datum DirectFunctionCall4(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall4Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
-extern Datum DirectFunctionCall5(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall5Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
-extern Datum DirectFunctionCall6(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall6Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
-extern Datum DirectFunctionCall7(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall7Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
-extern Datum DirectFunctionCall8(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall8Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
-extern Datum DirectFunctionCall9(PGFunction func, Datum arg1, Datum arg2,
+extern Datum DirectFunctionCall9Coll(PGFunction func, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
-/* The same, but passing a collation to use */
-extern Datum DirectFunctionCall1WithCollation(PGFunction func, Oid collation,
- Datum arg1);
-extern Datum DirectFunctionCall2WithCollation(PGFunction func, Oid collation,
- Datum arg1, Datum arg2);
-
/* 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.
*/
-extern Datum FunctionCall1(FmgrInfo *flinfo, Datum arg1);
-extern Datum FunctionCall2(FmgrInfo *flinfo, Datum arg1, Datum arg2);
-extern Datum FunctionCall3(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1);
+extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3);
-extern Datum FunctionCall4(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall4Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
-extern Datum FunctionCall5(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall5Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
-extern Datum FunctionCall6(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall6Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
-extern Datum FunctionCall7(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall7Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
-extern Datum FunctionCall8(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall8Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
-extern Datum FunctionCall9(FmgrInfo *flinfo, Datum arg1, Datum arg2,
+extern Datum FunctionCall9Coll(FmgrInfo *flinfo, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
* by FunctionCallN(). If the same function is to be invoked repeatedly,
* do the FunctionLookup() once and then use FunctionCallN().
*/
-extern Datum OidFunctionCall0(Oid functionId);
-extern Datum OidFunctionCall1(Oid functionId, Datum arg1);
-extern Datum OidFunctionCall2(Oid functionId, Datum arg1, Datum arg2);
-extern Datum OidFunctionCall3(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall0Coll(Oid functionId, Oid collation);
+extern Datum OidFunctionCall1Coll(Oid functionId, Oid collation,
+ Datum arg1);
+extern Datum OidFunctionCall2Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2);
+extern Datum OidFunctionCall3Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3);
-extern Datum OidFunctionCall4(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall4Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4);
-extern Datum OidFunctionCall5(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall5Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5);
-extern Datum OidFunctionCall6(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall6Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6);
-extern Datum OidFunctionCall7(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall7Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7);
-extern Datum OidFunctionCall8(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall8Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8);
-extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
+extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
+ Datum arg1, Datum arg2,
Datum arg3, Datum arg4, Datum arg5,
Datum arg6, Datum arg7, Datum arg8,
Datum arg9);
+/* These macros allow the collation argument to be omitted (with a default of
+ * InvalidOid, ie, no collation). They exist mostly for backwards
+ * compatibility of source code.
+ */
+#define DirectFunctionCall1(func, arg1) \
+ DirectFunctionCall1Coll(func, InvalidOid, arg1)
+#define DirectFunctionCall2(func, arg1, arg2) \
+ DirectFunctionCall2Coll(func, InvalidOid, arg1, arg2)
+#define DirectFunctionCall3(func, arg1, arg2, arg3) \
+ DirectFunctionCall3Coll(func, InvalidOid, arg1, arg2, arg3)
+#define DirectFunctionCall4(func, arg1, arg2, arg3, arg4) \
+ DirectFunctionCall4Coll(func, InvalidOid, arg1, arg2, arg3, arg4)
+#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5) \
+ DirectFunctionCall5Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define DirectFunctionCall6(func, arg1, arg2, arg3, arg4, arg5, arg6) \
+ DirectFunctionCall6Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define DirectFunctionCall7(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ DirectFunctionCall7Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define DirectFunctionCall8(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ DirectFunctionCall8Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define DirectFunctionCall9(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ DirectFunctionCall9Coll(func, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define FunctionCall1(flinfo, arg1) \
+ FunctionCall1Coll(flinfo, InvalidOid, arg1)
+#define FunctionCall2(flinfo, arg1, arg2) \
+ FunctionCall2Coll(flinfo, InvalidOid, arg1, arg2)
+#define FunctionCall3(flinfo, arg1, arg2, arg3) \
+ FunctionCall3Coll(flinfo, InvalidOid, arg1, arg2, arg3)
+#define FunctionCall4(flinfo, arg1, arg2, arg3, arg4) \
+ FunctionCall4Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4)
+#define FunctionCall5(flinfo, arg1, arg2, arg3, arg4, arg5) \
+ FunctionCall5Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define FunctionCall6(flinfo, arg1, arg2, arg3, arg4, arg5, arg6) \
+ FunctionCall6Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define FunctionCall7(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ FunctionCall7Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define FunctionCall8(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ FunctionCall8Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define FunctionCall9(flinfo, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ FunctionCall9Coll(flinfo, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+#define OidFunctionCall0(functionId) \
+ OidFunctionCall0Coll(functionId, InvalidOid)
+#define OidFunctionCall1(functionId, arg1) \
+ OidFunctionCall1Coll(functionId, InvalidOid, arg1)
+#define OidFunctionCall2(functionId, arg1, arg2) \
+ OidFunctionCall2Coll(functionId, InvalidOid, arg1, arg2)
+#define OidFunctionCall3(functionId, arg1, arg2, arg3) \
+ OidFunctionCall3Coll(functionId, InvalidOid, arg1, arg2, arg3)
+#define OidFunctionCall4(functionId, arg1, arg2, arg3, arg4) \
+ OidFunctionCall4Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4)
+#define OidFunctionCall5(functionId, arg1, arg2, arg3, arg4, arg5) \
+ OidFunctionCall5Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5)
+#define OidFunctionCall6(functionId, arg1, arg2, arg3, arg4, arg5, arg6) \
+ OidFunctionCall6Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6)
+#define OidFunctionCall7(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ OidFunctionCall7Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define OidFunctionCall8(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ OidFunctionCall8Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+#define OidFunctionCall9(functionId, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \
+ OidFunctionCall9Coll(functionId, InvalidOid, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+
+
/* Special cases for convenient invocation of datatype I/O functions. */
extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
Oid typioparam, int32 typmod);
List *largs; /* the left-hand input arguments */
List *rargs; /* the right-hand input arguments */
FmgrInfo *funcs; /* array of comparison function info */
+ Oid *collations; /* array of collations to use */
} RowCompareExprState;
/* ----------------
Oid collation,
Const **prefix,
Const **rest);
-extern Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc);
+extern Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc,
+ Oid collation);
extern Datum eqsel(PG_FUNCTION_ARGS);
extern Datum neqsel(PG_FUNCTION_ARGS);
extern 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);
extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
Relation indexRel,
uint32 hash_mask,
int workMem, bool randomAccess);
extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
- Oid sortOperator, Oid sortCollation, bool nullsFirstFlag,
+ Oid sortOperator, Oid sortCollation,
+ bool nullsFirstFlag,
int workMem, bool randomAccess);
extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
* reverse-sort and NULLs-ordering properly.
*/
extern int32 ApplySortFunction(FmgrInfo *sortFunction, int sortFlags,
+ Oid collation,
Datum datum1, bool isNull1,
Datum datum2, bool isNull2);
function->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
function->fn_tid = procTup->t_self;
function->fn_is_trigger = is_trigger;
- function->fn_input_collation = fcinfo->flinfo->fn_collation;
+ function->fn_input_collation = fcinfo->fncollation;
function->fn_cxt = func_cxt;
function->out_param_varno = -1; /* set up for no OUT param */
function->resolve_option = plpgsql_variable_conflict;
}
/* get input collation, if known */
- hashkey->inputCollation = fcinfo->flinfo->fn_collation;
+ hashkey->inputCollation = fcinfo->fncollation;
if (procStruct->pronargs > 0)
{