Cache datatype-output-function lookup info across calls of concat().
Testing indicates this can save a third to a half of the runtime of the function. Pavel Stehule, reviewed by Alexander Kuzmenkov Discussion: https://postgr.es/m/CAFj8pRAT62pRgjoHbgTfJUc2uLmeQ4saUj+yVJAEZUiMwNCmdg@mail.gmail.com
This commit is contained in:
parent
890faaf195
commit
ed22fb8b00
@ -4733,11 +4733,48 @@ string_agg_finalfn(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare cache with fmgr info for the output functions of the datatypes of
|
||||||
|
* the arguments of a concat-like function, beginning with argument "argidx".
|
||||||
|
* (Arguments before that will have corresponding slots in the resulting
|
||||||
|
* FmgrInfo array, but we don't fill those slots.)
|
||||||
|
*/
|
||||||
|
static FmgrInfo *
|
||||||
|
build_concat_foutcache(FunctionCallInfo fcinfo, int argidx)
|
||||||
|
{
|
||||||
|
FmgrInfo *foutcache;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* We keep the info in fn_mcxt so it survives across calls */
|
||||||
|
foutcache = (FmgrInfo *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
||||||
|
PG_NARGS() * sizeof(FmgrInfo));
|
||||||
|
|
||||||
|
for (i = argidx; i < PG_NARGS(); i++)
|
||||||
|
{
|
||||||
|
Oid valtype;
|
||||||
|
Oid typOutput;
|
||||||
|
bool typIsVarlena;
|
||||||
|
|
||||||
|
valtype = get_fn_expr_argtype(fcinfo->flinfo, i);
|
||||||
|
if (!OidIsValid(valtype))
|
||||||
|
elog(ERROR, "could not determine data type of concat() input");
|
||||||
|
|
||||||
|
getTypeOutputInfo(valtype, &typOutput, &typIsVarlena);
|
||||||
|
fmgr_info_cxt(typOutput, &foutcache[i], fcinfo->flinfo->fn_mcxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
fcinfo->flinfo->fn_extra = foutcache;
|
||||||
|
|
||||||
|
return foutcache;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implementation of both concat() and concat_ws().
|
* Implementation of both concat() and concat_ws().
|
||||||
*
|
*
|
||||||
* sepstr is the separator string to place between values.
|
* sepstr is the separator string to place between values.
|
||||||
* argidx identifies the first argument to concatenate (counting from zero).
|
* argidx identifies the first argument to concatenate (counting from zero);
|
||||||
|
* note that this must be constant across any one series of calls.
|
||||||
|
*
|
||||||
* Returns NULL if result should be NULL, else text value.
|
* Returns NULL if result should be NULL, else text value.
|
||||||
*/
|
*/
|
||||||
static text *
|
static text *
|
||||||
@ -4746,6 +4783,7 @@ concat_internal(const char *sepstr, int argidx,
|
|||||||
{
|
{
|
||||||
text *result;
|
text *result;
|
||||||
StringInfoData str;
|
StringInfoData str;
|
||||||
|
FmgrInfo *foutcache;
|
||||||
bool first_arg = true;
|
bool first_arg = true;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -4787,14 +4825,16 @@ concat_internal(const char *sepstr, int argidx,
|
|||||||
/* Normal case without explicit VARIADIC marker */
|
/* Normal case without explicit VARIADIC marker */
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
/* Get output function info, building it if first time through */
|
||||||
|
foutcache = (FmgrInfo *) fcinfo->flinfo->fn_extra;
|
||||||
|
if (foutcache == NULL)
|
||||||
|
foutcache = build_concat_foutcache(fcinfo, argidx);
|
||||||
|
|
||||||
for (i = argidx; i < PG_NARGS(); i++)
|
for (i = argidx; i < PG_NARGS(); i++)
|
||||||
{
|
{
|
||||||
if (!PG_ARGISNULL(i))
|
if (!PG_ARGISNULL(i))
|
||||||
{
|
{
|
||||||
Datum value = PG_GETARG_DATUM(i);
|
Datum value = PG_GETARG_DATUM(i);
|
||||||
Oid valtype;
|
|
||||||
Oid typOutput;
|
|
||||||
bool typIsVarlena;
|
|
||||||
|
|
||||||
/* add separator if appropriate */
|
/* add separator if appropriate */
|
||||||
if (first_arg)
|
if (first_arg)
|
||||||
@ -4803,12 +4843,8 @@ concat_internal(const char *sepstr, int argidx,
|
|||||||
appendStringInfoString(&str, sepstr);
|
appendStringInfoString(&str, sepstr);
|
||||||
|
|
||||||
/* call the appropriate type output function, append the result */
|
/* call the appropriate type output function, append the result */
|
||||||
valtype = get_fn_expr_argtype(fcinfo->flinfo, i);
|
|
||||||
if (!OidIsValid(valtype))
|
|
||||||
elog(ERROR, "could not determine data type of concat() input");
|
|
||||||
getTypeOutputInfo(valtype, &typOutput, &typIsVarlena);
|
|
||||||
appendStringInfoString(&str,
|
appendStringInfoString(&str,
|
||||||
OidOutputFunctionCall(typOutput, value));
|
OutputFunctionCall(&foutcache[i], value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user