Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ed22fb8

Browse files
committed
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
1 parent 890faaf commit ed22fb8

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

src/backend/utils/adt/varlena.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4733,11 +4733,48 @@ string_agg_finalfn(PG_FUNCTION_ARGS)
47334733
PG_RETURN_NULL();
47344734
}
47354735

4736+
/*
4737+
* Prepare cache with fmgr info for the output functions of the datatypes of
4738+
* the arguments of a concat-like function, beginning with argument "argidx".
4739+
* (Arguments before that will have corresponding slots in the resulting
4740+
* FmgrInfo array, but we don't fill those slots.)
4741+
*/
4742+
static FmgrInfo *
4743+
build_concat_foutcache(FunctionCallInfo fcinfo, int argidx)
4744+
{
4745+
FmgrInfo *foutcache;
4746+
int i;
4747+
4748+
/* We keep the info in fn_mcxt so it survives across calls */
4749+
foutcache = (FmgrInfo *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
4750+
PG_NARGS() * sizeof(FmgrInfo));
4751+
4752+
for (i = argidx; i < PG_NARGS(); i++)
4753+
{
4754+
Oid valtype;
4755+
Oid typOutput;
4756+
bool typIsVarlena;
4757+
4758+
valtype = get_fn_expr_argtype(fcinfo->flinfo, i);
4759+
if (!OidIsValid(valtype))
4760+
elog(ERROR, "could not determine data type of concat() input");
4761+
4762+
getTypeOutputInfo(valtype, &typOutput, &typIsVarlena);
4763+
fmgr_info_cxt(typOutput, &foutcache[i], fcinfo->flinfo->fn_mcxt);
4764+
}
4765+
4766+
fcinfo->flinfo->fn_extra = foutcache;
4767+
4768+
return foutcache;
4769+
}
4770+
47364771
/*
47374772
* Implementation of both concat() and concat_ws().
47384773
*
47394774
* sepstr is the separator string to place between values.
4740-
* argidx identifies the first argument to concatenate (counting from zero).
4775+
* argidx identifies the first argument to concatenate (counting from zero);
4776+
* note that this must be constant across any one series of calls.
4777+
*
47414778
* Returns NULL if result should be NULL, else text value.
47424779
*/
47434780
static text *
@@ -4746,6 +4783,7 @@ concat_internal(const char *sepstr, int argidx,
47464783
{
47474784
text *result;
47484785
StringInfoData str;
4786+
FmgrInfo *foutcache;
47494787
bool first_arg = true;
47504788
int i;
47514789

@@ -4787,14 +4825,16 @@ concat_internal(const char *sepstr, int argidx,
47874825
/* Normal case without explicit VARIADIC marker */
47884826
initStringInfo(&str);
47894827

4828+
/* Get output function info, building it if first time through */
4829+
foutcache = (FmgrInfo *) fcinfo->flinfo->fn_extra;
4830+
if (foutcache == NULL)
4831+
foutcache = build_concat_foutcache(fcinfo, argidx);
4832+
47904833
for (i = argidx; i < PG_NARGS(); i++)
47914834
{
47924835
if (!PG_ARGISNULL(i))
47934836
{
47944837
Datum value = PG_GETARG_DATUM(i);
4795-
Oid valtype;
4796-
Oid typOutput;
4797-
bool typIsVarlena;
47984838

47994839
/* add separator if appropriate */
48004840
if (first_arg)
@@ -4803,12 +4843,8 @@ concat_internal(const char *sepstr, int argidx,
48034843
appendStringInfoString(&str, sepstr);
48044844

48054845
/* call the appropriate type output function, append the result */
4806-
valtype = get_fn_expr_argtype(fcinfo->flinfo, i);
4807-
if (!OidIsValid(valtype))
4808-
elog(ERROR, "could not determine data type of concat() input");
4809-
getTypeOutputInfo(valtype, &typOutput, &typIsVarlena);
48104846
appendStringInfoString(&str,
4811-
OidOutputFunctionCall(typOutput, value));
4847+
OutputFunctionCall(&foutcache[i], value));
48124848
}
48134849
}
48144850

0 commit comments

Comments
 (0)