>From 0eba6c4ed89b1815ae28cc34db74f9c858d253ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Urba=C5=84ski?= <wulczer@wulczer.org>
Date: Wed, 19 Jan 2011 23:05:40 +0100
Subject: [PATCH 2/7] Factor out functions responsible for caching I/O routines.

This makes PLy_procedure_create a bit more manageable.
---
 src/pl/plpython/plpython.c |  241 +++++++++++++++++++++++---------------------
 1 files changed, 128 insertions(+), 113 deletions(-)

diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index bed5e70..f205768 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -1367,6 +1367,132 @@ PLy_procedure_get(Oid fn_oid, bool is_trigger)
 	return entry->proc;
 }
 
+/* Set up output conversion functions for a procedure */
+static void
+PLy_procedure_output_conversion(PLyProcedure *proc, Form_pg_proc procStruct)
+{
+	HeapTuple	rvTypeTup;
+	Form_pg_type rvTypeStruct;
+
+	/* Get the return type */
+	rvTypeTup = SearchSysCache1(TYPEOID,
+								ObjectIdGetDatum(procStruct->prorettype));
+	if (!HeapTupleIsValid(rvTypeTup))
+		elog(ERROR, "cache lookup failed for type %u",
+			 procStruct->prorettype);
+	rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
+
+	/* Disallow pseudotype result, except for void */
+	if (rvTypeStruct->typtype == TYPTYPE_PSEUDO &&
+		procStruct->prorettype != VOIDOID)
+	{
+		if (procStruct->prorettype == TRIGGEROID)
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("trigger functions can only be called as triggers")));
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("PL/Python functions cannot return type %s",
+							format_type_be(procStruct->prorettype))));
+	}
+
+	if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE)
+	{
+		/*
+		 * Tuple: set up later, during first call to
+		 * PLy_function_handler
+		 */
+		proc->result.out.d.typoid = procStruct->prorettype;
+		proc->result.is_rowtype = 2;
+	}
+	else
+	{
+		/* Do the real work */
+		PLy_output_datum_func(&proc->result, rvTypeTup);
+	}
+
+	ReleaseSysCache(rvTypeTup);
+}
+
+/* Set up output conversion functions for a procedure */
+static void
+PLy_procedure_input_conversion(PLyProcedure *proc, HeapTuple procTup,
+							   Form_pg_proc procStruct)
+{
+	Oid		*types;
+	char	**names,
+			*modes;
+	int		i,
+			pos,
+			total;
+
+	/* Extract argument type info from the pg_proc tuple */
+	total = get_func_arg_info(procTup, &types, &names, &modes);
+
+	/* Count number of in+inout args into proc->nargs */
+	if (modes == NULL)
+		proc->nargs = total;
+	else
+	{
+		/* proc->nargs was initialized to 0 above */
+		for (i = 0; i < total; i++)
+		{
+			if (modes[i] != PROARGMODE_OUT &&
+				modes[i] != PROARGMODE_TABLE)
+				(proc->nargs)++;
+		}
+	}
+
+	proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs);
+	for (i = pos = 0; i < total; i++)
+	{
+		HeapTuple	argTypeTup;
+		Form_pg_type argTypeStruct;
+
+		if (modes &&
+			(modes[i] == PROARGMODE_OUT ||
+			 modes[i] == PROARGMODE_TABLE))
+			continue;	/* skip OUT arguments */
+
+		Assert(types[i] == procStruct->proargtypes.values[pos]);
+
+		argTypeTup = SearchSysCache1(TYPEOID,
+									 ObjectIdGetDatum(types[i]));
+		if (!HeapTupleIsValid(argTypeTup))
+			elog(ERROR, "cache lookup failed for type %u", types[i]);
+		argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
+
+		/* Check argument type is OK, set up I/O function info */
+		switch (argTypeStruct->typtype)
+		{
+			case TYPTYPE_PSEUDO:
+				/* Disallow pseudotype argument */
+				ereport(ERROR,
+						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 errmsg("PL/Python functions cannot accept type %s",
+								format_type_be(types[i]))));
+				break;
+			case TYPTYPE_COMPOSITE:
+				/* We'll set IO funcs at first call */
+				proc->args[pos].is_rowtype = 2;
+				break;
+			default:
+				PLy_input_datum_func(&(proc->args[pos]),
+									 types[i],
+									 argTypeTup);
+				break;
+		}
+
+		/* Get argument name */
+		proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
+
+		ReleaseSysCache(argTypeTup);
+
+		pos++;
+	}
+}
+
 /*
  * Create a new PLyProcedure structure
  */
@@ -1415,46 +1541,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
 		 * but only if this isn't a trigger.
 		 */
 		if (!is_trigger)
-		{
-			HeapTuple	rvTypeTup;
-			Form_pg_type rvTypeStruct;
-
-			rvTypeTup = SearchSysCache1(TYPEOID,
-								   ObjectIdGetDatum(procStruct->prorettype));
-			if (!HeapTupleIsValid(rvTypeTup))
-				elog(ERROR, "cache lookup failed for type %u",
-					 procStruct->prorettype);
-			rvTypeStruct = (Form_pg_type) GETSTRUCT(rvTypeTup);
-
-			/* Disallow pseudotype result, except for void */
-			if (rvTypeStruct->typtype == TYPTYPE_PSEUDO &&
-				procStruct->prorettype != VOIDOID)
-			{
-				if (procStruct->prorettype == TRIGGEROID)
-					ereport(ERROR,
-							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-							 errmsg("trigger functions can only be called as triggers")));
-				else
-					ereport(ERROR,
-							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						  errmsg("PL/Python functions cannot return type %s",
-								 format_type_be(procStruct->prorettype))));
-			}
-
-			if (rvTypeStruct->typtype == TYPTYPE_COMPOSITE)
-			{
-				/*
-				 * Tuple: set up later, during first call to
-				 * PLy_function_handler
-				 */
-				proc->result.out.d.typoid = procStruct->prorettype;
-				proc->result.is_rowtype = 2;
-			}
-			else
-				PLy_output_datum_func(&proc->result, rvTypeTup);
-
-			ReleaseSysCache(rvTypeTup);
-		}
+			PLy_procedure_output_conversion(proc, procStruct);
 
 		/*
 		 * Now get information required for input conversion of the
@@ -1464,79 +1551,7 @@ PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
 		 * arguments.
 		 */
 		if (procStruct->pronargs)
-		{
-			Oid		   *types;
-			char	  **names,
-					   *modes;
-			int			i,
-						pos,
-						total;
-
-			/* extract argument type info from the pg_proc tuple */
-			total = get_func_arg_info(procTup, &types, &names, &modes);
-
-			/* count number of in+inout args into proc->nargs */
-			if (modes == NULL)
-				proc->nargs = total;
-			else
-			{
-				/* proc->nargs was initialized to 0 above */
-				for (i = 0; i < total; i++)
-				{
-					if (modes[i] != PROARGMODE_OUT &&
-						modes[i] != PROARGMODE_TABLE)
-						(proc->nargs)++;
-				}
-			}
-
-			proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs);
-			for (i = pos = 0; i < total; i++)
-			{
-				HeapTuple	argTypeTup;
-				Form_pg_type argTypeStruct;
-
-				if (modes &&
-					(modes[i] == PROARGMODE_OUT ||
-					 modes[i] == PROARGMODE_TABLE))
-					continue;	/* skip OUT arguments */
-
-				Assert(types[i] == procStruct->proargtypes.values[pos]);
-
-				argTypeTup = SearchSysCache1(TYPEOID,
-											 ObjectIdGetDatum(types[i]));
-				if (!HeapTupleIsValid(argTypeTup))
-					elog(ERROR, "cache lookup failed for type %u", types[i]);
-				argTypeStruct = (Form_pg_type) GETSTRUCT(argTypeTup);
-
-				/* check argument type is OK, set up I/O function info */
-				switch (argTypeStruct->typtype)
-				{
-					case TYPTYPE_PSEUDO:
-						/* Disallow pseudotype argument */
-						ereport(ERROR,
-								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-						  errmsg("PL/Python functions cannot accept type %s",
-								 format_type_be(types[i]))));
-						break;
-					case TYPTYPE_COMPOSITE:
-						/* we'll set IO funcs at first call */
-						proc->args[pos].is_rowtype = 2;
-						break;
-					default:
-						PLy_input_datum_func(&(proc->args[pos]),
-											 types[i],
-											 argTypeTup);
-						break;
-				}
-
-				/* get argument name */
-				proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
-
-				ReleaseSysCache(argTypeTup);
-
-				pos++;
-			}
-		}
+			PLy_procedure_input_conversion(proc, procTup, procStruct);
 
 		/*
 		 * get the text of the function.
-- 
1.7.2.3

