From b8001f469e83df048e972dcd17120929996ba5fa Mon Sep 17 00:00:00 2001
From: Nikita Glukhov <n.gluhov@postgrespro.ru>
Date: Wed, 31 Aug 2022 22:28:44 +0300
Subject: [PATCH 4/5] Introduce InputFunctionCallOptError()

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

diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index a9dd068095b..fbea0df61df 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -1511,11 +1511,14 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
  * function anyway if it's not strict.  So this is almost but not quite
  * the same as FunctionCall3.
  */
-Datum
-InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
+static inline Datum
+InputFunctionCallInternal(FmgrInfo *flinfo, char *str,
+						  Oid typioparam, int32 typmod,
+						  ErrorData **edata)
 {
 	LOCAL_FCINFO(fcinfo, 3);
 	Datum		result;
+	FuncCallError *fcerror;
 
 	if (str == NULL && flinfo->fn_strict)
 		return (Datum) 0;		/* just return null result */
@@ -1529,8 +1532,22 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 	fcinfo->args[2].value = Int32GetDatum(typmod);
 	fcinfo->args[2].isnull = false;
 
+	if (edata)
+	{
+		fcerror = makeNode(FuncCallError);
+		fcinfo->context = (Node *) fcerror;
+	}
+
 	result = FunctionCallInvoke(fcinfo);
 
+	if (edata)
+	{
+		*edata = fcerror->error;
+		pfree(fcerror);
+		if (*edata)
+			return (Datum) 0;
+	}
+
 	/* Should get null result if and only if str is NULL */
 	if (str == NULL)
 	{
@@ -1548,6 +1565,23 @@ InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 	return result;
 }
 
+Datum
+InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
+{
+	return InputFunctionCallInternal(flinfo, str, typioparam, typmod, NULL);
+}
+
+Datum
+InputFunctionCallOptError(FmgrInfo *flinfo, char *str, Oid typioparam,
+						  int32 typmod, ErrorData **edata)
+{
+	if (edata)
+		return InputFunctionCallInternal(flinfo, str, typioparam, typmod, edata);
+	else
+		return InputFunctionCall(flinfo, str, typioparam, typmod);
+}
+
+
 /*
  * Call a previously-looked-up datatype output function.
  *
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 380a82b9de3..8f18f2408e1 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -711,6 +711,9 @@ extern Datum OidReceiveFunctionCall(Oid functionId, fmStringInfo buf,
 extern bytea *SendFunctionCall(FmgrInfo *flinfo, Datum val);
 extern bytea *OidSendFunctionCall(Oid functionId, Datum val);
 
+extern Datum InputFunctionCallOptError(FmgrInfo *flinfo, char *str,
+									   Oid typioparam, int32 typmod,
+									   ErrorData **edata);
 
 /*
  * Routines in fmgr.c
-- 
2.25.1

