From b6b277f5dd3837ab9ac2df819f4e67f39d790d1f Mon Sep 17 00:00:00 2001
From: Andrew Dunstan <andrew@dunslane.net>
Date: Wed, 30 Nov 2022 10:46:03 -0500
Subject: [PATCH 2/5] Add InputFunctionCallContext()

---
 src/backend/utils/fmgr/fmgr.c | 50 +++++++++++++++++++++++++++++++++++
 src/include/fmgr.h            |  3 +++
 2 files changed, 53 insertions(+)

diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 3c210297aa..bd91ae1dac 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -24,6 +24,7 @@
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "nodes/primnodes.h"
 #include "pgstat.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
@@ -1548,6 +1549,55 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 	return result;
 }
 
+Datum
+InputFunctionCallContext(FmgrInfo *flinfo, char *str,
+						 Oid typioparam, int32 typmod,
+						 void * ctxt)
+{
+	LOCAL_FCINFO(fcinfo, 3);
+	Datum		result;
+
+	if (str == NULL && flinfo->fn_strict)
+		return (Datum) 0;		/* just return null result */
+
+	InitFunctionCallInfoData(*fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
+
+	fcinfo->args[0].value = CStringGetDatum(str);
+	fcinfo->args[0].isnull = false;
+	fcinfo->args[1].value = ObjectIdGetDatum(typioparam);
+	fcinfo->args[1].isnull = false;
+	fcinfo->args[2].value = Int32GetDatum(typmod);
+	fcinfo->args[2].isnull = false;
+
+	fcinfo->context = ctxt;
+
+	result = FunctionCallInvoke(fcinfo);
+
+	/* NULL is OK if we found an error and expect the caller to handle it */
+	if (ctxt && IsA(ctxt, IOCallContext))
+	{
+		IOCallContext *ioc = (IOCallContext *) ctxt;
+		if (ioc->no_error_throw && ioc->error_found)
+			return result;
+	}
+
+	/* Otherwise should get null result if and only if str is NULL */
+	if (str == NULL)
+	{
+		if (!fcinfo->isnull)
+			elog(ERROR, "input function %u returned non-NULL",
+				 flinfo->fn_oid);
+	}
+	else
+	{
+		if (fcinfo->isnull)
+			elog(ERROR, "input function %u returned NULL",
+				 flinfo->fn_oid);
+	}
+
+	return result;
+}
+
 /*
  * Call a previously-looked-up datatype output function.
  *
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 380a82b9de..4d7cb34441 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -702,6 +702,9 @@ extern Datum InputFunctionCall(FmgrInfo *flinfo, char *str,
 							   Oid typioparam, int32 typmod);
 extern Datum OidInputFunctionCall(Oid functionId, char *str,
 								  Oid typioparam, int32 typmod);
+extern Datum InputFunctionCallContext(FmgrInfo *flinfo, char *str,
+									  Oid typioparam, int32 typmod,
+									  void * ctxt);
 extern char *OutputFunctionCall(FmgrInfo *flinfo, Datum val);
 extern char *OidOutputFunctionCall(Oid functionId, Datum val);
 extern Datum ReceiveFunctionCall(FmgrInfo *flinfo, fmStringInfo buf,
-- 
2.34.1

