From 5704b126123a71a41062b9ab502564842fc3ddc9 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 13 Apr 2025 14:10:28 -0400
Subject: [PATCH v1 5/5] Cache typlens of a SQL function's input arguments.

This gets rid of repetitive get_typlen() calls in postquel_sub_params,
which show up as costing 1% or so of the runtime in simple test cases.
---
 src/backend/executor/functions.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 135fddda3fc..e0bca7cb81c 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -116,6 +116,7 @@ typedef struct SQLFunctionHashEntry
 	char	   *src;			/* function body text (for error msgs) */
 
 	SQLFunctionParseInfoPtr pinfo;	/* data for parser callback hooks */
+	int16	   *argtyplen;		/* lengths of the input argument types */
 
 	Oid			rettype;		/* actual return type */
 	int16		typlen;			/* length of the return type */
@@ -1100,6 +1101,15 @@ sql_compile_callback(FunctionCallInfo fcinfo,
 											PG_GET_COLLATION());
 	MemoryContextSwitchTo(oldcontext);
 
+	/*
+	 * Now that we have the resolved argument types, collect their typlens for
+	 * use in postquel_sub_params.
+	 */
+	func->argtyplen = (int16 *)
+		MemoryContextAlloc(hcontext, func->pinfo->nargs * sizeof(int16));
+	for (int i = 0; i < func->pinfo->nargs; i++)
+		func->argtyplen[i] = get_typlen(func->pinfo->argtypes[i]);
+
 	/*
 	 * And of course we need the function body text.
 	 */
@@ -1427,6 +1437,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
 	{
 		ParamListInfo paramLI;
 		Oid		   *argtypes = fcache->func->pinfo->argtypes;
+		int16	   *argtyplen = fcache->func->argtyplen;
 
 		if (fcache->paramLI == NULL)
 		{
@@ -1463,7 +1474,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
 			prm->isnull = fcinfo->args[i].isnull;
 			prm->value = MakeExpandedObjectReadOnly(fcinfo->args[i].value,
 													prm->isnull,
-													get_typlen(argtypes[i]));
+													argtyplen[i]);
 			/* Allow the value to be substituted into custom plans */
 			prm->pflags = PARAM_FLAG_CONST;
 			prm->ptype = argtypes[i];
-- 
2.43.5

