Hi
Now concat is 2x times slower than || operator. With cached FmgrInfo for
output function it will be only 5%.
Regards
Pavel
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index be399f4..d3f04f8 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -4718,6 +4718,28 @@ string_agg_finalfn(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
+static void
+rebuildConcatCache(FmgrInfo *typcache, FunctionCallInfo fcinfo, int argidx)
+{
+ int i;
+
+ Assert(typcache != NULL);
+
+ 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, &typcache[i-argidx], fcinfo->flinfo->fn_mcxt);
+ }
+}
+
/*
* Implementation of both concat() and concat_ws().
*
@@ -4733,6 +4755,7 @@ concat_internal(const char *sepstr, int argidx,
StringInfoData str;
bool first_arg = true;
int i;
+ FmgrInfo *typcache;
/*
* concat(VARIADIC some-array) is essentially equivalent to
@@ -4772,14 +4795,20 @@ concat_internal(const char *sepstr, int argidx,
/* Normal case without explicit VARIADIC marker */
initStringInfo(&str);
+ typcache = (FmgrInfo *) fcinfo->flinfo->fn_extra;
+ if (typcache == NULL)
+ {
+ fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
+ PG_NARGS() * sizeof(FmgrInfo));
+ typcache = (FmgrInfo *) fcinfo->flinfo->fn_extra;
+ rebuildConcatCache(typcache, fcinfo, argidx);
+ }
+
for (i = argidx; i < PG_NARGS(); i++)
{
if (!PG_ARGISNULL(i))
{
Datum value = PG_GETARG_DATUM(i);
- Oid valtype;
- Oid typOutput;
- bool typIsVarlena;
/* add separator if appropriate */
if (first_arg)
@@ -4787,13 +4816,8 @@ concat_internal(const char *sepstr, int argidx,
else
appendStringInfoString(&str, sepstr);
- /* 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,
- OidOutputFunctionCall(typOutput, value));
+ OutputFunctionCall(&typcache[i-argidx], value));
}
}
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers