diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index b545928d9b9536711f50330c784a8a0d41ea9937..b450b2ee546dd5facaeddab4b1088a9c4d9f79a6 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.27 2005/11/17 22:14:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.28 2005/12/28 18:11:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -628,6 +628,109 @@ get_type_func_class(Oid typid)
 }
 
 
+/*
+ * get_func_arg_info
+ *
+ * Fetch info about the argument types, names, and IN/OUT modes from the
+ * pg_proc tuple.  Return value is the total number of arguments.
+ * Other results are palloc'd.  *p_argtypes is always filled in, but
+ * *p_argnames and *p_argmodes will be set NULL in the default cases
+ * (no names, and all IN arguments, respectively).
+ *
+ * Note that this function simply fetches what is in the pg_proc tuple;
+ * it doesn't do any interpretation of polymorphic types.
+ */
+int
+get_func_arg_info(HeapTuple procTup,
+				  Oid **p_argtypes, char ***p_argnames, char **p_argmodes)
+{
+	Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
+	Datum		proallargtypes;
+	Datum		proargmodes;
+	Datum		proargnames;
+	bool		isNull;
+	ArrayType  *arr;
+	int			numargs;
+	Datum	   *elems;
+	int			nelems;
+	int			i;
+
+	/* First discover the total number of parameters and get their types */
+	proallargtypes = SysCacheGetAttr(PROCOID, procTup,
+									 Anum_pg_proc_proallargtypes,
+									 &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(proallargtypes);		/* ensure not toasted */
+		numargs = ARR_DIMS(arr)[0];
+		if (ARR_NDIM(arr) != 1 ||
+			numargs < 0 ||
+			ARR_HASNULL(arr) ||
+			ARR_ELEMTYPE(arr) != OIDOID)
+			elog(ERROR, "proallargtypes is not a 1-D Oid array");
+		Assert(numargs >= procStruct->pronargs);
+		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+		memcpy(*p_argtypes, ARR_DATA_PTR(arr),
+			   numargs * sizeof(Oid));
+	}
+	else
+	{
+		/* If no proallargtypes, use proargtypes */
+		numargs = procStruct->proargtypes.dim1;
+		Assert(numargs == procStruct->pronargs);
+		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
+		memcpy(*p_argtypes, procStruct->proargtypes.values,
+			   numargs * sizeof(Oid));
+	}
+
+	/* Get argument names, if available */
+	proargnames = SysCacheGetAttr(PROCOID, procTup,
+								  Anum_pg_proc_proargnames,
+								  &isNull);
+	if (isNull)
+		*p_argnames = NULL;
+	else
+	{
+		deconstruct_array(DatumGetArrayTypeP(proargnames),
+						  TEXTOID, -1, false, 'i',
+						  &elems, NULL, &nelems);
+		if (nelems != numargs)	/* should not happen */
+			elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
+		*p_argnames = (char **) palloc(sizeof(char *) * numargs);
+		for (i = 0; i < numargs; i++)
+			(*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
+																   elems[i]));
+	}
+
+	/* Get argument modes, if available */
+	proargmodes = SysCacheGetAttr(PROCOID, procTup,
+								  Anum_pg_proc_proargmodes,
+								  &isNull);
+	if (isNull)
+		*p_argmodes = NULL;
+	else
+	{
+		arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
+		if (ARR_NDIM(arr) != 1 ||
+			ARR_DIMS(arr)[0] != numargs ||
+			ARR_HASNULL(arr) ||
+			ARR_ELEMTYPE(arr) != CHAROID)
+			elog(ERROR, "proargmodes is not a 1-D char array");
+		*p_argmodes = (char *) palloc(numargs * sizeof(char));
+		memcpy(*p_argmodes, ARR_DATA_PTR(arr),
+			   numargs * sizeof(char));
+	}
+
+	return numargs;
+}
+
+
 /*
  * get_func_result_name
  *
diff --git a/src/include/funcapi.h b/src/include/funcapi.h
index 1f455d3eeaf6ed490e0fde974a8c9e8e31fb7df5..ccc61dfbf08cd14a511ecfbc1403944f414bc294 100644
--- a/src/include/funcapi.h
+++ b/src/include/funcapi.h
@@ -9,7 +9,7 @@
  *
  * Copyright (c) 2002-2005, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.21 2005/11/22 18:17:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/funcapi.h,v 1.22 2005/12/28 18:11:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -165,12 +165,16 @@ extern TypeFuncClass get_func_result_type(Oid functionId,
 					 Oid *resultTypeId,
 					 TupleDesc *resultTupleDesc);
 
-extern char *get_func_result_name(Oid functionId);
-
 extern bool resolve_polymorphic_argtypes(int numargs, Oid *argtypes,
 							 char *argmodes,
 							 Node *call_expr);
 
+extern int	get_func_arg_info(HeapTuple procTup,
+							  Oid **p_argtypes, char ***p_argnames,
+							  char **p_argmodes);
+
+extern char *get_func_result_name(Oid functionId);
+
 extern TupleDesc build_function_result_tupdesc_d(Datum proallargtypes,
 								Datum proargmodes,
 								Datum proargnames);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index b89f975981c7d9a1f7d2275caa676b5bae4a00f3..d9fa1f0e422bb141a54d9ba0a13d265ba7669856 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.97 2005/12/09 17:08:49 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.98 2005/12/28 18:11:25 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -123,9 +123,6 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
 		   HeapTuple procTup,
 		   PLpgSQL_func_hashkey *hashkey,
 		   bool forValidator);
-static int fetchArgInfo(HeapTuple procTup,
-			 Oid **p_argtypes, char ***p_argnames,
-			 char **p_argmodes);
 static PLpgSQL_row *build_row_from_class(Oid classOid);
 static PLpgSQL_row *build_row_from_vars(PLpgSQL_variable **vars, int numvars);
 static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
@@ -358,7 +355,8 @@ do_compile(FunctionCallInfo fcinfo,
 			 */
 			MemoryContextSwitchTo(compile_tmp_cxt);
 
-			numargs = fetchArgInfo(procTup, &argtypes, &argnames, &argmodes);
+			numargs = get_func_arg_info(procTup,
+										&argtypes, &argnames, &argmodes);
 
 			plpgsql_resolve_polymorphic_argtypes(numargs, argtypes, argmodes,
 												 fcinfo->flinfo->fn_expr,
@@ -751,102 +749,6 @@ plpgsql_compile_error_callback(void *arg)
 }
 
 
-/*
- * Fetch info about the argument types, names, and IN/OUT modes from the
- * pg_proc tuple.  Return value is the number of arguments.
- * Other results are palloc'd.
- */
-static int
-fetchArgInfo(HeapTuple procTup, Oid **p_argtypes, char ***p_argnames,
-			 char **p_argmodes)
-{
-	Form_pg_proc procStruct = (Form_pg_proc) GETSTRUCT(procTup);
-	Datum		proallargtypes;
-	Datum		proargmodes;
-	Datum		proargnames;
-	bool		isNull;
-	ArrayType  *arr;
-	int			numargs;
-	Datum	   *elems;
-	int			nelems;
-	int			i;
-
-	/* First discover the total number of parameters and get their types */
-	proallargtypes = SysCacheGetAttr(PROCOID, procTup,
-									 Anum_pg_proc_proallargtypes,
-									 &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(proallargtypes);		/* ensure not toasted */
-		numargs = ARR_DIMS(arr)[0];
-		if (ARR_NDIM(arr) != 1 ||
-			numargs < 0 ||
-			ARR_HASNULL(arr) ||
-			ARR_ELEMTYPE(arr) != OIDOID)
-			elog(ERROR, "proallargtypes is not a 1-D Oid array");
-		Assert(numargs >= procStruct->pronargs);
-		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
-		memcpy(*p_argtypes, ARR_DATA_PTR(arr),
-			   numargs * sizeof(Oid));
-	}
-	else
-	{
-		/* If no proallargtypes, use proargtypes */
-		numargs = procStruct->proargtypes.dim1;
-		Assert(numargs == procStruct->pronargs);
-		*p_argtypes = (Oid *) palloc(numargs * sizeof(Oid));
-		memcpy(*p_argtypes, procStruct->proargtypes.values,
-			   numargs * sizeof(Oid));
-	}
-
-	/* Get argument names, if available */
-	proargnames = SysCacheGetAttr(PROCOID, procTup,
-								  Anum_pg_proc_proargnames,
-								  &isNull);
-	if (isNull)
-		*p_argnames = NULL;
-	else
-	{
-		deconstruct_array(DatumGetArrayTypeP(proargnames),
-						  TEXTOID, -1, false, 'i',
-						  &elems, NULL, &nelems);
-		if (nelems != numargs)	/* should not happen */
-			elog(ERROR, "proargnames must have the same number of elements as the function has arguments");
-		*p_argnames = (char **) palloc(sizeof(char *) * numargs);
-		for (i = 0; i < numargs; i++)
-			(*p_argnames)[i] = DatumGetCString(DirectFunctionCall1(textout,
-																   elems[i]));
-	}
-
-	/* Get argument modes, if available */
-	proargmodes = SysCacheGetAttr(PROCOID, procTup,
-								  Anum_pg_proc_proargmodes,
-								  &isNull);
-	if (isNull)
-		*p_argmodes = NULL;
-	else
-	{
-		arr = DatumGetArrayTypeP(proargmodes);	/* ensure not toasted */
-		if (ARR_NDIM(arr) != 1 ||
-			ARR_DIMS(arr)[0] != numargs ||
-			ARR_HASNULL(arr) ||
-			ARR_ELEMTYPE(arr) != CHAROID)
-			elog(ERROR, "proargmodes is not a 1-D char array");
-		*p_argmodes = (char *) palloc(numargs * sizeof(char));
-		memcpy(*p_argmodes, ARR_DATA_PTR(arr),
-			   numargs * sizeof(char));
-	}
-
-	return numargs;
-}
-
-
 /* ----------
  * plpgsql_parse_word		The scanner calls this to postparse
  *				any single word not found by a
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 69d128e8698316a812423c2160816914fbba0558..59e6acc7893a2722e5c5f603989ab95cef283860 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.26 2005/10/15 02:49:50 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.27 2005/12/28 18:11:25 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -41,6 +41,7 @@
 #include "access/heapam.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
+#include "funcapi.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -147,9 +148,11 @@ plpgsql_validator(PG_FUNCTION_ARGS)
 	HeapTuple	tuple;
 	Form_pg_proc proc;
 	char		functyptype;
+	int			numargs;
+	Oid		   *argtypes;
+	char	  **argnames;
+	char	   *argmodes;
 	bool		istrigger = false;
-	bool		haspolyresult;
-	bool		haspolyarg;
 	int			i;
 
 	/* perform initialization */
@@ -173,32 +176,30 @@ plpgsql_validator(PG_FUNCTION_ARGS)
 		if (proc->prorettype == TRIGGEROID ||
 			(proc->prorettype == OPAQUEOID && proc->pronargs == 0))
 			istrigger = true;
-		else if (proc->prorettype == ANYARRAYOID ||
-				 proc->prorettype == ANYELEMENTOID)
-			haspolyresult = true;
 		else if (proc->prorettype != RECORDOID &&
-				 proc->prorettype != VOIDOID)
+				 proc->prorettype != VOIDOID &&
+				 proc->prorettype != ANYARRAYOID &&
+				 proc->prorettype != ANYELEMENTOID)
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("plpgsql functions cannot return type %s",
 							format_type_be(proc->prorettype))));
 	}
 
-	/* Disallow pseudotypes in arguments */
+	/* Disallow pseudotypes in arguments (either IN or OUT) */
 	/* except for ANYARRAY or ANYELEMENT */
-	haspolyarg = false;
-	for (i = 0; i < proc->pronargs; i++)
+	numargs = get_func_arg_info(tuple,
+								&argtypes, &argnames, &argmodes);
+	for (i = 0; i < numargs; i++)
 	{
-		if (get_typtype(proc->proargtypes.values[i]) == 'p')
+		if (get_typtype(argtypes[i]) == 'p')
 		{
-			if (proc->proargtypes.values[i] == ANYARRAYOID ||
-				proc->proargtypes.values[i] == ANYELEMENTOID)
-				haspolyarg = true;
-			else
+			if (argtypes[i] != ANYARRAYOID &&
+				argtypes[i] != ANYELEMENTOID)
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 						 errmsg("plpgsql functions cannot take type %s",
-							  format_type_be(proc->proargtypes.values[i]))));
+							  format_type_be(argtypes[i]))));
 		}
 	}