diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 201242e796..640c506dd5 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -845,6 +845,7 @@ lookup_agg_function(List *fnName,
 	int			nvargs;
 	Oid			vatype;
 	Oid		   *true_oid_array;
+	Oid			support_func;
 	FuncDetailCode fdresult;
 	AclResult	aclresult;
 	int			i;
@@ -860,7 +861,8 @@ lookup_agg_function(List *fnName,
 							   nargs, input_types, false, false,
 							   &fnOid, rettype, &retset,
 							   &nvargs, &vatype,
-							   &true_oid_array, NULL);
+							   &true_oid_array, NULL,
+							   &support_func);
 
 	/* only valid case is a normal function not returning a set */
 	if (fdresult != FUNCDETAIL_NORMAL || !OidIsValid(fnOid))
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 8e926539e6..5974744668 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -22,6 +22,7 @@
 #include "lib/stringinfo.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "nodes/supportnodes.h"
 #include "parser/parse_agg.h"
 #include "parser/parse_clause.h"
 #include "parser/parse_coerce.h"
@@ -111,6 +112,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 	bool		retset;
 	int			nvargs;
 	Oid			vatype;
+	Oid			support_func;
 	FuncDetailCode fdresult;
 	char		aggkind = 0;
 	ParseCallbackState pcbstate;
@@ -265,7 +267,8 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 							   !func_variadic, true,
 							   &funcid, &rettype, &retset,
 							   &nvargs, &vatype,
-							   &declared_arg_types, &argdefaults);
+							   &declared_arg_types, &argdefaults,
+							   &support_func);
 
 	cancel_parser_errposition_callback(&pcbstate);
 
@@ -666,6 +669,31 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
 	/* perform the necessary typecasting of arguments */
 	make_fn_arguments(pstate, fargs, actual_arg_types, declared_arg_types);
 
+	/*
+	 * When rettype is ANYOID we can call support function SupportRequestRettype if
+	 * it is available to get real type.
+	 */
+	if (rettype == ANYOID && OidIsValid(support_func))
+	{
+		SupportRequestRettype		req;
+		SupportRequestRettype	   *result;
+
+		req.type = T_SupportRequestRettype;
+		req.funcname = funcname;
+		req.fargs = fargs;
+		req.actual_arg_types = actual_arg_types;
+		req.declared_arg_types = declared_arg_types;
+		req.nargs = nargsplusdefs;
+
+		result = (SupportRequestRettype *)
+					DatumGetPointer(OidFunctionCall1(support_func,
+													 PointerGetDatum(&req)));
+
+		/* use result when it is valid */
+		if (result == &req)
+			rettype = result->rettype;
+	}
+
 	/*
 	 * If the function isn't actually variadic, forget any VARIADIC decoration
 	 * on the call.  (Perhaps we should throw an error instead, but
@@ -1392,7 +1420,8 @@ func_get_detail(List *funcname,
 				int *nvargs,	/* return value */
 				Oid *vatype,	/* return value */
 				Oid **true_typeids, /* return value */
-				List **argdefaults) /* optional return value */
+				List **argdefaults, /* optional return value */
+				Oid *support_func) /* return value */
 {
 	FuncCandidateList raw_candidates;
 	FuncCandidateList best_candidate;
@@ -1407,6 +1436,7 @@ func_get_detail(List *funcname,
 	*nvargs = 0;
 	*vatype = InvalidOid;
 	*true_typeids = NULL;
+	*support_func = InvalidOid;
 	if (argdefaults)
 		*argdefaults = NIL;
 
@@ -1519,6 +1549,7 @@ func_get_detail(List *funcname,
 					*nvargs = 0;
 					*vatype = InvalidOid;
 					*true_typeids = argtypes;
+					*support_func = InvalidOid;
 					return FUNCDETAIL_COERCION;
 				}
 			}
@@ -1616,6 +1647,7 @@ func_get_detail(List *funcname,
 		*rettype = pform->prorettype;
 		*retset = pform->proretset;
 		*vatype = pform->provariadic;
+		*support_func = pform->prosupport;
 		/* fetch default args if caller wants 'em */
 		if (argdefaults && best_candidate->ndargs > 0)
 		{
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 13d5d542f9..a406f9c699 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -10868,6 +10868,7 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
 	int			p_nvargs;
 	Oid			p_vatype;
 	Oid		   *p_true_typeids;
+	Oid			p_support_func;
 	bool		force_qualify = false;
 
 	proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
@@ -10922,7 +10923,8 @@ generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes,
 								   !use_variadic, true,
 								   &p_funcid, &p_rettype,
 								   &p_retset, &p_nvargs, &p_vatype,
-								   &p_true_typeids, NULL);
+								   &p_true_typeids, NULL,
+								   &p_support_func);
 	else
 	{
 		p_result = FUNCDETAIL_NOTFOUND;
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 4e2fb39105..e2fb1cb83a 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -512,7 +512,8 @@ typedef enum NodeTag
 	T_SupportRequestSelectivity,	/* in nodes/supportnodes.h */
 	T_SupportRequestCost,		/* in nodes/supportnodes.h */
 	T_SupportRequestRows,		/* in nodes/supportnodes.h */
-	T_SupportRequestIndexCondition	/* in nodes/supportnodes.h */
+	T_SupportRequestIndexCondition,	/* in nodes/supportnodes.h */
+	T_SupportRequestRettype		/* in nodes/supportnodes.h */
 } NodeTag;
 
 /*
diff --git a/src/include/nodes/supportnodes.h b/src/include/nodes/supportnodes.h
index 460d75bd2d..abaf42cf96 100644
--- a/src/include/nodes/supportnodes.h
+++ b/src/include/nodes/supportnodes.h
@@ -239,4 +239,25 @@ typedef struct SupportRequestIndexCondition
 								 * equivalent of the function call */
 } SupportRequestIndexCondition;
 
+/*
+ * The SupportRequestRettype request type allows to calculate result type for
+ * functions that returns "any" type. It is designed for procedural specification
+ * return type.
+ */
+typedef struct SupportRequestRettype
+{
+	NodeTag		type;
+
+	/* Input fields */
+	List	   *funcname;
+	List	   *fargs;
+	Oid		   *actual_arg_types;
+	Oid		   *declared_arg_types;
+	int			nargs;
+
+	/* Output fields */
+	Oid			rettype;
+
+} SupportRequestRettype;
+
 #endif							/* SUPPORTNODES_H */
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
index 5a3b287eaf..7fc2ef1d37 100644
--- a/src/include/parser/parse_func.h
+++ b/src/include/parser/parse_func.h
@@ -41,7 +41,8 @@ extern FuncDetailCode func_get_detail(List *funcname,
 									  bool expand_variadic, bool expand_defaults,
 									  Oid *funcid, Oid *rettype,
 									  bool *retset, int *nvargs, Oid *vatype,
-									  Oid **true_typeids, List **argdefaults);
+									  Oid **true_typeids, List **argdefaults,
+									  Oid *support_func);
 
 extern int	func_match_argtypes(int nargs,
 								Oid *input_typeids,
