commit 7a0139a3d82b0d71682c317ff560799254986504
Author: Pavel Stehule <pavel.stehule@gooddata.com>
Date:   Wed Apr 8 09:50:30 2015 +0200

    fix \sf when function has trf types

diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3ee3b57..5ffb712 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -306,6 +306,7 @@ static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
 static int print_function_arguments(StringInfo buf, HeapTuple proctup,
 						 bool print_table_args, bool print_defaults);
 static void print_function_rettype(StringInfo buf, HeapTuple proctup);
+static void print_function_trftypes(StringInfo buf, HeapTuple proctup);
 static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
 				 Bitmapset *rels_used);
 static bool refname_is_unique(char *refname, deparse_namespace *dpns,
@@ -1945,6 +1946,9 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
 	(void) print_function_arguments(&buf, proctup, false, true);
 	appendStringInfoString(&buf, ")\n RETURNS ");
 	print_function_rettype(&buf, proctup);
+
+	print_function_trftypes(&buf, proctup);
+
 	appendStringInfo(&buf, "\n LANGUAGE %s\n",
 					 quote_identifier(get_language_name(proc->prolang, false)));
 
@@ -2342,6 +2346,30 @@ is_input_argument(int nth, const char *argmodes)
 }
 
 /*
+ * Append used transformated types to specified buffer
+ */
+static void
+print_function_trftypes(StringInfo buf, HeapTuple proctup)
+{
+	Oid	*trftypes;
+	int	ntypes;
+
+	ntypes = get_func_trftypes(proctup, &trftypes);
+	if (ntypes > 0)
+	{
+		int	i;
+
+		appendStringInfoString(buf, "\n TRANSFORM ");
+		for (i = 0; i < ntypes; i++)
+		{
+			if (i != 0)
+				appendStringInfoString(buf, ", ");
+				appendStringInfo(buf, "FOR TYPE %s", format_type_be(trftypes[i]));
+		}
+	}
+}
+
+/*
  * Get textual representation of a function argument's default value.  The
  * second argument of this function is the argument number among all arguments
  * (i.e. proallargtypes, *not* proargtypes), starting with 1, because that's
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 204e124..ebd7ddd 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -877,6 +877,50 @@ get_func_arg_info(HeapTuple procTup,
 	return numargs;
 }
 
+/*
+ * get_func_trftypes
+ *
+ * Returns a number of transformated types used by function.
+ */
+int
+get_func_trftypes(HeapTuple procTup,
+				  Oid **p_trftypes)
+{
+
+	Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
+	Datum		protrftypes;
+	ArrayType  *arr;
+	int			nelems;
+	bool			isNull;
+
+	protrftypes = SysCacheGetAttr(PROCOID, procTup,
+									 Anum_pg_proc_protrftypes,
+									 &isNull);
+	if (!isNull)
+	{
+		/*
+		 * We expect the arrays to be 1-D arrays of the right types; verify
+		 * that.  For the OID and char arrays, we don't need to use
+		 * deconstruct_array() since the array data is just going to look like
+		 * a C array of values.
+		 */
+		arr = DatumGetArrayTypeP(protrftypes);		/* ensure not toasted */
+		nelems = ARR_DIMS(arr)[0];
+		if (ARR_NDIM(arr) != 1 ||
+			nelems < 0 ||
+			ARR_HASNULL(arr) ||
+			ARR_ELEMTYPE(arr) != OIDOID)
+			elog(ERROR, "protrftypes is not a 1-D Oid array");
+		Assert(nelems >= procStruct->pronargs);
+		*p_trftypes = (Oid *) palloc(nelems * sizeof(Oid));
+		memcpy(*p_trftypes, ARR_DATA_PTR(arr),
+			   nelems * sizeof(Oid));
+
+		return nelems;
+	}
+	else
+		return 0;
+}
 
 /*
  * get_func_input_arg_names
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index 38d1451..9031b09 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -176,6 +176,8 @@ extern int get_func_arg_info(HeapTuple procTup,
 extern int get_func_input_arg_names(Datum proargnames, Datum proargmodes,
 						 char ***arg_names);
 
+extern int get_func_trftypes(HeapTuple procTup,
+					    Oid **p_trftypes);
 extern char *get_func_result_name(Oid functionId);
 
 extern TupleDesc build_function_result_tupdesc_d(Datum proallargtypes,
