*** a/src/pl/plpython/plpy_cursorobject.c
--- b/src/pl/plpython/plpy_cursorobject.c
***************
*** 8,13 ****
--- 8,14 ----
  
  #include "access/xact.h"
  #include "mb/pg_wchar.h"
+ #include "utils/memutils.h"
  
  #include "plpython.h"
  
***************
*** 111,117 **** PLy_cursor_query(const char *query)
  		return NULL;
  	cursor->portalname = NULL;
  	cursor->closed = false;
! 	PLy_typeinfo_init(&cursor->result);
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
--- 112,124 ----
  		return NULL;
  	cursor->portalname = NULL;
  	cursor->closed = false;
! 
! 	cursor->mcxt = AllocSetContextCreate(TopMemoryContext,
! 					  "Pl python cursor context",
! 					  ALLOCSET_DEFAULT_MINSIZE,
! 					  ALLOCSET_DEFAULT_INITSIZE,
! 					  ALLOCSET_DEFAULT_MAXSIZE);
! 	PLy_typeinfo_init(&cursor->result, cursor->mcxt);
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
***************
*** 123,128 **** PLy_cursor_query(const char *query)
--- 130,136 ----
  		PLyExecutionContext *exec_ctx = PLy_current_execution_context();
  		SPIPlanPtr	plan;
  		Portal		portal;
+ 		MemoryContext 	oldcxt;
  
  		pg_verifymbstr(query, strlen(query), false);
  
***************
*** 139,145 **** PLy_cursor_query(const char *query)
  			elog(ERROR, "SPI_cursor_open() failed: %s",
  				 SPI_result_code_string(SPI_result));
  
! 		cursor->portalname = PLy_strdup(portal->name);
  
  		PLy_spi_subtransaction_commit(oldcontext, oldowner);
  	}
--- 147,155 ----
  			elog(ERROR, "SPI_cursor_open() failed: %s",
  				 SPI_result_code_string(SPI_result));
  
! 		oldcxt = MemoryContextSwitchTo(cursor->mcxt);
! 		cursor->portalname = pstrdup(portal->name);
! 		MemoryContextSwitchTo(oldcxt);
  
  		PLy_spi_subtransaction_commit(oldcontext, oldowner);
  	}
***************
*** 200,206 **** PLy_cursor_plan(PyObject *ob, PyObject *args)
  		return NULL;
  	cursor->portalname = NULL;
  	cursor->closed = false;
! 	PLy_typeinfo_init(&cursor->result);
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
--- 210,222 ----
  		return NULL;
  	cursor->portalname = NULL;
  	cursor->closed = false;
! 
! 	cursor->mcxt = AllocSetContextCreate(TopMemoryContext,
! 					  "Pl python cursor context",
! 					  ALLOCSET_DEFAULT_MINSIZE,
! 					  ALLOCSET_DEFAULT_INITSIZE,
! 					  ALLOCSET_DEFAULT_MAXSIZE);
! 	PLy_typeinfo_init(&cursor->result, cursor->mcxt);
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
***************
*** 213,218 **** PLy_cursor_plan(PyObject *ob, PyObject *args)
--- 229,235 ----
  		Portal		portal;
  		char	   *volatile nulls;
  		volatile int j;
+ 		MemoryContext oldcxt;
  
  		if (nargs > 0)
  			nulls = palloc(nargs * sizeof(char));
***************
*** 261,267 **** PLy_cursor_plan(PyObject *ob, PyObject *args)
  			elog(ERROR, "SPI_cursor_open() failed: %s",
  				 SPI_result_code_string(SPI_result));
  
! 		cursor->portalname = PLy_strdup(portal->name);
  
  		PLy_spi_subtransaction_commit(oldcontext, oldowner);
  	}
--- 278,286 ----
  			elog(ERROR, "SPI_cursor_open() failed: %s",
  				 SPI_result_code_string(SPI_result));
  
! 		oldcxt = MemoryContextSwitchTo(cursor->mcxt);
! 		cursor->portalname = pstrdup(portal->name);
! 		MemoryContextSwitchTo(oldcxt);
  
  		PLy_spi_subtransaction_commit(oldcontext, oldowner);
  	}
***************
*** 277,283 **** PLy_cursor_plan(PyObject *ob, PyObject *args)
  			{
  				pfree(DatumGetPointer(plan->values[k]));
  				plan->values[k] = PointerGetDatum(NULL);
! 			}
  		}
  
  		Py_DECREF(cursor);
--- 296,302 ----
  			{
  				pfree(DatumGetPointer(plan->values[k]));
  				plan->values[k] = PointerGetDatum(NULL);
! 		}
  		}
  
  		Py_DECREF(cursor);
***************
*** 317,326 **** PLy_cursor_dealloc(PyObject *arg)
  			SPI_cursor_close(portal);
  	}
  
! 	PLy_free(cursor->portalname);
  	cursor->portalname = NULL;
  
  	PLy_typeinfo_dealloc(&cursor->result);
  	arg->ob_type->tp_free(arg);
  }
  
--- 336,346 ----
  			SPI_cursor_close(portal);
  	}
  
! 	pfree(cursor->portalname);
  	cursor->portalname = NULL;
  
  	PLy_typeinfo_dealloc(&cursor->result);
+ 	MemoryContextDelete(cursor->mcxt);
  	arg->ob_type->tp_free(arg);
  }
  
*** a/src/pl/plpython/plpy_cursorobject.h
--- b/src/pl/plpython/plpy_cursorobject.h
***************
*** 14,19 **** typedef struct PLyCursorObject
--- 14,20 ----
  	char	   *portalname;
  	PLyTypeInfo result;
  	bool		closed;
+ 	MemoryContext mcxt;
  } PLyCursorObject;
  
  extern void PLy_cursor_init_type(void);
*** a/src/pl/plpython/plpy_main.c
--- b/src/pl/plpython/plpy_main.c
***************
*** 265,270 **** plpython_inline_handler(PG_FUNCTION_ARGS)
--- 265,271 ----
  	PLyProcedure proc;
  	PLyExecutionContext *exec_ctx;
  	ErrorContextCallback plerrcontext;
+ 	MemoryContext oldcxt;
  
  	/* Note: SPI_finish() happens in plpy_exec.c, which is dubious design */
  	if (SPI_connect() != SPI_OK_CONNECT)
***************
*** 277,283 **** plpython_inline_handler(PG_FUNCTION_ARGS)
  	flinfo.fn_mcxt = CurrentMemoryContext;
  
  	MemSet(&proc, 0, sizeof(PLyProcedure));
! 	proc.pyname = PLy_strdup("__plpython_inline_block");
  	proc.langid = codeblock->langOid;
  	proc.result.out.d.typoid = VOIDOID;
  
--- 278,292 ----
  	flinfo.fn_mcxt = CurrentMemoryContext;
  
  	MemSet(&proc, 0, sizeof(PLyProcedure));
! 	proc.mcxt = AllocSetContextCreate(TopMemoryContext,
! 	            	             	 "Plpy procedure context",
!                         	         ALLOCSET_DEFAULT_MINSIZE,
!                                 	 ALLOCSET_DEFAULT_INITSIZE,
! 	                                 ALLOCSET_DEFAULT_MAXSIZE);
! 	oldcxt = MemoryContextSwitchTo(proc.mcxt); 
! 	proc.pyname = pstrdup("__plpython_inline_block");
! 	MemoryContextSwitchTo(oldcxt);
! 
  	proc.langid = codeblock->langOid;
  	proc.result.out.d.typoid = VOIDOID;
  
*** a/src/pl/plpython/plpy_planobject.c
--- b/src/pl/plpython/plpy_planobject.c
***************
*** 11,17 ****
  #include "plpy_planobject.h"
  
  #include "plpy_elog.h"
! 
  
  static void PLy_plan_dealloc(PyObject *arg);
  static PyObject *PLy_plan_status(PyObject *self, PyObject *args);
--- 11,17 ----
  #include "plpy_planobject.h"
  
  #include "plpy_elog.h"
! #include "utils/memutils.h"
  
  static void PLy_plan_dealloc(PyObject *arg);
  static PyObject *PLy_plan_status(PyObject *self, PyObject *args);
***************
*** 80,85 **** PLy_plan_new(void)
--- 80,86 ----
  	ob->types = NULL;
  	ob->values = NULL;
  	ob->args = NULL;
+ 	ob->mcxt = NULL;
  
  	return (PyObject *) ob;
  }
***************
*** 98,115 **** PLy_plan_dealloc(PyObject *arg)
  	if (ob->plan)
  		SPI_freeplan(ob->plan);
  	if (ob->types)
! 		PLy_free(ob->types);
  	if (ob->values)
! 		PLy_free(ob->values);
  	if (ob->args)
  	{
  		int			i;
  
  		for (i = 0; i < ob->nargs; i++)
  			PLy_typeinfo_dealloc(&ob->args[i]);
! 		PLy_free(ob->args);
  	}
  
  	arg->ob_type->tp_free(arg);
  }
  
--- 99,118 ----
  	if (ob->plan)
  		SPI_freeplan(ob->plan);
  	if (ob->types)
! 		pfree(ob->types);
  	if (ob->values)
! 		pfree(ob->values);
  	if (ob->args)
  	{
  		int			i;
  
  		for (i = 0; i < ob->nargs; i++)
  			PLy_typeinfo_dealloc(&ob->args[i]);
! 		pfree(ob->args);
  	}
  
+ 	if (ob->mcxt)
+ 		MemoryContextDelete(ob->mcxt);
  	arg->ob_type->tp_free(arg);
  }
  
*** a/src/pl/plpython/plpy_planobject.h
--- b/src/pl/plpython/plpy_planobject.h
***************
*** 17,22 **** typedef struct PLyPlanObject
--- 17,23 ----
  	Oid		   *types;
  	Datum	   *values;
  	PLyTypeInfo *args;
+ 	MemoryContext mcxt;
  } PLyPlanObject;
  
  extern void PLy_plan_init_type(void);
*** a/src/pl/plpython/plpy_procedure.c
--- b/src/pl/plpython/plpy_procedure.c
***************
*** 113,119 **** PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger)
  		{
  			/* Found it, but it's invalid, free and reuse the cache entry */
  			PLy_procedure_delete(proc);
- 			PLy_free(proc);
  			proc = PLy_procedure_create(procTup, fn_oid, is_trigger);
  			entry->proc = proc;
  		}
--- 113,118 ----
***************
*** 145,150 **** PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
--- 144,151 ----
  	char	   *volatile procSource = NULL;
  	Datum		prosrcdatum;
  	bool		isnull;
+ 	MemoryContext   cxt;
+ 	MemoryContext oldcxt;
  	int			i,
  				rv;
  
***************
*** 156,183 **** PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
  	if (rv >= sizeof(procName) || rv < 0)
  		elog(ERROR, "procedure name would overrun buffer");
  
! 	proc = PLy_malloc(sizeof(PLyProcedure));
! 	proc->proname = PLy_strdup(NameStr(procStruct->proname));
! 	proc->pyname = PLy_strdup(procName);
  	proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
  	proc->fn_tid = procTup->t_self;
  	/* Remember if function is STABLE/IMMUTABLE */
  	proc->fn_readonly =
  		(procStruct->provolatile != PROVOLATILE_VOLATILE);
! 	PLy_typeinfo_init(&proc->result);
  	for (i = 0; i < FUNC_MAX_ARGS; i++)
! 		PLy_typeinfo_init(&proc->args[i]);
  	proc->nargs = 0;
  	proc->langid = procStruct->prolang;
  	{
- 		MemoryContext oldcxt;
- 
  		Datum		protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
  										  Anum_pg_proc_protrftypes, &isnull);
  
- 		oldcxt = MemoryContextSwitchTo(TopMemoryContext);
  		proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
- 		MemoryContextSwitchTo(oldcxt);
  	}
  	proc->code = proc->statics = NULL;
  	proc->globals = NULL;
--- 157,190 ----
  	if (rv >= sizeof(procName) || rv < 0)
  		elog(ERROR, "procedure name would overrun buffer");
  
! 	cxt = AllocSetContextCreate(TopMemoryContext,
! 				  "Plpy procedure context",
! 				  ALLOCSET_DEFAULT_MINSIZE,
! 				  ALLOCSET_DEFAULT_INITSIZE,
! 				  ALLOCSET_DEFAULT_MAXSIZE); 
! 
! 	oldcxt = MemoryContextSwitchTo(cxt);
! 
! 	proc = palloc(sizeof(PLyProcedure));
! 	proc->mcxt = cxt;
! 
! 	proc->proname = pstrdup(NameStr(procStruct->proname));
! 	proc->pyname = pstrdup(procName);
  	proc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
  	proc->fn_tid = procTup->t_self;
  	/* Remember if function is STABLE/IMMUTABLE */
  	proc->fn_readonly =
  		(procStruct->provolatile != PROVOLATILE_VOLATILE);
! 	PLy_typeinfo_init(&proc->result, proc->mcxt);
  	for (i = 0; i < FUNC_MAX_ARGS; i++)
! 		PLy_typeinfo_init(&proc->args[i], proc->mcxt);
  	proc->nargs = 0;
  	proc->langid = procStruct->prolang;
  	{
  		Datum		protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
  										  Anum_pg_proc_protrftypes, &isnull);
  
  		proc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
  	}
  	proc->code = proc->statics = NULL;
  	proc->globals = NULL;
***************
*** 271,277 **** PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
  				}
  			}
  
! 			proc->argnames = (char **) PLy_malloc0(sizeof(char *) * proc->nargs);
  			for (i = pos = 0; i < total; i++)
  			{
  				HeapTuple	argTypeTup;
--- 278,284 ----
  				}
  			}
  
! 			proc->argnames = (char **) palloc0(sizeof(char *) * proc->nargs);
  			for (i = pos = 0; i < total; i++)
  			{
  				HeapTuple	argTypeTup;
***************
*** 314,320 **** PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
  				}
  
  				/* get argument name */
! 				proc->argnames[pos] = names ? PLy_strdup(names[i]) : NULL;
  
  				ReleaseSysCache(argTypeTup);
  
--- 321,327 ----
  				}
  
  				/* get argument name */
! 				proc->argnames[pos] = names ? pstrdup(names[i]) : NULL;
  
  				ReleaseSysCache(argTypeTup);
  
***************
*** 346,351 **** PLy_procedure_create(HeapTuple procTup, Oid fn_oid, bool is_trigger)
--- 353,359 ----
  	}
  	PG_END_TRY();
  
+ 	MemoryContextSwitchTo(oldcxt);
  	return proc;
  }
  
***************
*** 357,362 **** PLy_procedure_compile(PLyProcedure *proc, const char *src)
--- 365,371 ----
  {
  	PyObject   *crv = NULL;
  	char	   *msrc;
+ 	MemoryContext oldcxt;
  
  	proc->globals = PyDict_Copy(PLy_interp_globals);
  
***************
*** 372,378 **** PLy_procedure_compile(PLyProcedure *proc, const char *src)
  	 */
  	msrc = PLy_procedure_munge_source(proc->pyname, src);
  	/* Save the mangled source for later inclusion in tracebacks */
! 	proc->src = PLy_strdup(msrc);
  	crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
  	pfree(msrc);
  
--- 381,390 ----
  	 */
  	msrc = PLy_procedure_munge_source(proc->pyname, src);
  	/* Save the mangled source for later inclusion in tracebacks */
! 	oldcxt = MemoryContextSwitchTo(proc->mcxt);
! 	proc->src = pstrdup(msrc);
! 	MemoryContextSwitchTo(oldcxt);
! 
  	crv = PyRun_String(msrc, Py_file_input, proc->globals, NULL);
  	pfree(msrc);
  
***************
*** 410,434 **** PLy_procedure_delete(PLyProcedure *proc)
  	Py_XDECREF(proc->statics);
  	Py_XDECREF(proc->globals);
  	if (proc->proname)
! 		PLy_free(proc->proname);
  	if (proc->pyname)
! 		PLy_free(proc->pyname);
  	for (i = 0; i < proc->nargs; i++)
  	{
  		if (proc->args[i].is_rowtype == 1)
  		{
  			if (proc->args[i].in.r.atts)
! 				PLy_free(proc->args[i].in.r.atts);
  			if (proc->args[i].out.r.atts)
! 				PLy_free(proc->args[i].out.r.atts);
  		}
  		if (proc->argnames && proc->argnames[i])
! 			PLy_free(proc->argnames[i]);
  	}
  	if (proc->src)
! 		PLy_free(proc->src);
  	if (proc->argnames)
! 		PLy_free(proc->argnames);
  }
  
  /*
--- 422,448 ----
  	Py_XDECREF(proc->statics);
  	Py_XDECREF(proc->globals);
  	if (proc->proname)
! 		pfree(proc->proname);
  	if (proc->pyname)
! 		pfree(proc->pyname);
  	for (i = 0; i < proc->nargs; i++)
  	{
  		if (proc->args[i].is_rowtype == 1)
  		{
  			if (proc->args[i].in.r.atts)
! 				pfree(proc->args[i].in.r.atts);
  			if (proc->args[i].out.r.atts)
! 				pfree(proc->args[i].out.r.atts);
  		}
  		if (proc->argnames && proc->argnames[i])
! 			pfree(proc->argnames[i]);
  	}
  	if (proc->src)
! 		pfree(proc->src);
  	if (proc->argnames)
! 		pfree(proc->argnames);
! 
! 	MemoryContextDelete(proc->mcxt);
  }
  
  /*
*** a/src/pl/plpython/plpy_procedure.h
--- b/src/pl/plpython/plpy_procedure.h
***************
*** 32,37 **** typedef struct PLyProcedure
--- 32,39 ----
  	PyObject   *code;			/* compiled procedure code */
  	PyObject   *statics;		/* data saved across calls, local scope */
  	PyObject   *globals;		/* data saved across calls, global scope */
+ 	MemoryContext mcxt;		/* Context to store the plyprocedure and it's input
+ 					 * or output data. */
  } PLyProcedure;
  
  /* the procedure cache key */
*** a/src/pl/plpython/plpy_spi.c
--- b/src/pl/plpython/plpy_spi.c
***************
*** 60,72 **** PLy_spi_prepare(PyObject *self, PyObject *args)
  
  	if ((plan = (PLyPlanObject *) PLy_plan_new()) == NULL)
  		return NULL;
  
  	nargs = list ? PySequence_Length(list) : 0;
  
  	plan->nargs = nargs;
! 	plan->types = nargs ? PLy_malloc(sizeof(Oid) * nargs) : NULL;
! 	plan->values = nargs ? PLy_malloc(sizeof(Datum) * nargs) : NULL;
! 	plan->args = nargs ? PLy_malloc(sizeof(PLyTypeInfo) * nargs) : NULL;
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
--- 60,81 ----
  
  	if ((plan = (PLyPlanObject *) PLy_plan_new()) == NULL)
  		return NULL;
+ 	
+ 	plan->mcxt = AllocSetContextCreate(TopMemoryContext,
+                  	                 "PL python plan context",
+                         	          ALLOCSET_DEFAULT_MINSIZE,
+                                 	  ALLOCSET_DEFAULT_INITSIZE,
+ 	                                  ALLOCSET_DEFAULT_MAXSIZE);
+ 	oldcontext = MemoryContextSwitchTo(plan->mcxt);
  
  	nargs = list ? PySequence_Length(list) : 0;
  
  	plan->nargs = nargs;
! 	plan->types = nargs ? palloc(sizeof(Oid) * nargs) : NULL;
! 	plan->values = nargs ? palloc(sizeof(Datum) * nargs) : NULL;
! 	plan->args = nargs ? palloc(sizeof(PLyTypeInfo) * nargs) : NULL;
! 
! 	MemoryContextSwitchTo(oldcontext);
  
  	oldcontext = CurrentMemoryContext;
  	oldowner = CurrentResourceOwner;
***************
*** 84,90 **** PLy_spi_prepare(PyObject *self, PyObject *args)
  		 */
  		for (i = 0; i < nargs; i++)
  		{
! 			PLy_typeinfo_init(&plan->args[i]);
  			plan->values[i] = PointerGetDatum(NULL);
  		}
  
--- 93,99 ----
  		 */
  		for (i = 0; i < nargs; i++)
  		{
! 			PLy_typeinfo_init(&plan->args[i], plan->mcxt);
  			plan->values[i] = PointerGetDatum(NULL);
  		}
  
***************
*** 391,400 **** PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
  	{
  		PLyTypeInfo args;
  		int			i;
  
  		Py_DECREF(result->nrows);
  		result->nrows = PyInt_FromLong(rows);
! 		PLy_typeinfo_init(&args);
  
  		oldcontext = CurrentMemoryContext;
  		PG_TRY();
--- 400,416 ----
  	{
  		PLyTypeInfo args;
  		int			i;
+ 		MemoryContext cxt;
  
  		Py_DECREF(result->nrows);
  		result->nrows = PyInt_FromLong(rows);
! 
! 		cxt = AllocSetContextCreate(CurrentMemoryContext,
! 					  "Pl python temp context",
! 					  ALLOCSET_DEFAULT_MINSIZE,
! 					  ALLOCSET_DEFAULT_INITSIZE,
! 					  ALLOCSET_DEFAULT_MAXSIZE);
! 		PLy_typeinfo_init(&args, cxt);
  
  		oldcontext = CurrentMemoryContext;
  		PG_TRY();
***************
*** 433,444 **** PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
--- 449,462 ----
  		{
  			MemoryContextSwitchTo(oldcontext);
  			PLy_typeinfo_dealloc(&args);
+ 			MemoryContextDelete(cxt);
  			Py_DECREF(result);
  			PG_RE_THROW();
  		}
  		PG_END_TRY();
  
  		PLy_typeinfo_dealloc(&args);
+ 		MemoryContextDelete(cxt);
  		SPI_freetuptable(tuptable);
  	}
  
*** a/src/pl/plpython/plpy_typeio.c
--- b/src/pl/plpython/plpy_typeio.c
***************
*** 29,36 ****
  
  
  /* I/O function caching */
! static void PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes);
! static void PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup, Oid langid, List *trftypes);
  
  /* conversion from Datums to Python objects */
  static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
--- 29,36 ----
  
  
  /* I/O function caching */
! static void PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes);
! static void PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes);
  
  /* conversion from Datums to Python objects */
  static PyObject *PLyBool_FromBool(PLyDatumToOb *arg, Datum d);
***************
*** 60,70 **** static Datum PLyMapping_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject
  static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence);
  static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object);
  
- /* make allocations in the TopMemoryContext */
- static void perm_fmgr_info(Oid functionId, FmgrInfo *finfo);
- 
  void
! PLy_typeinfo_init(PLyTypeInfo *arg)
  {
  	arg->is_rowtype = -1;
  	arg->in.r.natts = arg->out.r.natts = 0;
--- 60,67 ----
  static Datum PLySequence_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *sequence);
  static Datum PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object);
  
  void
! PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
  {
  	arg->is_rowtype = -1;
  	arg->in.r.natts = arg->out.r.natts = 0;
***************
*** 73,78 **** PLy_typeinfo_init(PLyTypeInfo *arg)
--- 70,76 ----
  	arg->typ_relid = InvalidOid;
  	arg->typrel_xmin = InvalidTransactionId;
  	ItemPointerSetInvalid(&arg->typrel_tid);
+ 	arg->mcxt = mcxt;
  }
  
  void
***************
*** 85,101 **** PLy_typeinfo_dealloc(PLyTypeInfo *arg)
  		for (i = 0; i < arg->in.r.natts; i++)
  		{
  			if (arg->in.r.atts[i].elm != NULL)
! 				PLy_free(arg->in.r.atts[i].elm);
  		}
  		if (arg->in.r.atts)
! 			PLy_free(arg->in.r.atts);
  		for (i = 0; i < arg->out.r.natts; i++)
  		{
  			if (arg->out.r.atts[i].elm != NULL)
! 				PLy_free(arg->out.r.atts[i].elm);
  		}
  		if (arg->out.r.atts)
! 			PLy_free(arg->out.r.atts);
  	}
  }
  
--- 83,99 ----
  		for (i = 0; i < arg->in.r.natts; i++)
  		{
  			if (arg->in.r.atts[i].elm != NULL)
! 				pfree(arg->in.r.atts[i].elm);
  		}
  		if (arg->in.r.atts)
! 			pfree(arg->in.r.atts);
  		for (i = 0; i < arg->out.r.natts; i++)
  		{
  			if (arg->out.r.atts[i].elm != NULL)
! 				pfree(arg->out.r.atts[i].elm);
  		}
  		if (arg->out.r.atts)
! 			pfree(arg->out.r.atts);
  	}
  }
  
***************
*** 109,115 **** PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langi
  	if (arg->is_rowtype > 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
  	arg->is_rowtype = 0;
! 	PLy_input_datum_func2(&(arg->in.d), typeOid, typeTup, langid, trftypes);
  }
  
  void
--- 107,113 ----
  	if (arg->is_rowtype > 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for Tuple");
  	arg->is_rowtype = 0;
! 	PLy_input_datum_func2(&(arg->in.d), arg->mcxt, typeOid, typeTup, langid, trftypes);
  }
  
  void
***************
*** 118,124 **** PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trf
  	if (arg->is_rowtype > 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
  	arg->is_rowtype = 0;
! 	PLy_output_datum_func2(&(arg->out.d), typeTup, langid, trftypes);
  }
  
  void
--- 116,122 ----
  	if (arg->is_rowtype > 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for a Tuple");
  	arg->is_rowtype = 0;
! 	PLy_output_datum_func2(&(arg->out.d), arg->mcxt, typeTup, langid, trftypes);
  }
  
  void
***************
*** 126,131 **** PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
--- 124,132 ----
  {
  	int			i;
  	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
+ 	MemoryContext		oldcxt;
+ 
+ 	oldcxt = MemoryContextSwitchTo(arg->mcxt);
  
  	if (arg->is_rowtype == 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
***************
*** 134,142 **** PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
  	if (arg->in.r.natts != desc->natts)
  	{
  		if (arg->in.r.atts)
! 			PLy_free(arg->in.r.atts);
  		arg->in.r.natts = desc->natts;
! 		arg->in.r.atts = PLy_malloc0(desc->natts * sizeof(PLyDatumToOb));
  	}
  
  	/* Can this be an unnamed tuple? If not, then an Assert would be enough */
--- 135,143 ----
  	if (arg->in.r.natts != desc->natts)
  	{
  		if (arg->in.r.atts)
! 			pfree(arg->in.r.atts);
  		arg->in.r.natts = desc->natts;
! 		arg->in.r.atts = palloc0(desc->natts * sizeof(PLyDatumToOb));
  	}
  
  	/* Can this be an unnamed tuple? If not, then an Assert would be enough */
***************
*** 182,188 **** PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
  			elog(ERROR, "cache lookup failed for type %u",
  				 desc->attrs[i]->atttypid);
  
! 		PLy_input_datum_func2(&(arg->in.r.atts[i]),
  							  desc->attrs[i]->atttypid,
  							  typeTup,
  							  exec_ctx->curr_proc->langid,
--- 183,189 ----
  			elog(ERROR, "cache lookup failed for type %u",
  				 desc->attrs[i]->atttypid);
  
! 		PLy_input_datum_func2(&(arg->in.r.atts[i]), arg->mcxt,
  							  desc->attrs[i]->atttypid,
  							  typeTup,
  							  exec_ctx->curr_proc->langid,
***************
*** 190,195 **** PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
--- 191,198 ----
  
  		ReleaseSysCache(typeTup);
  	}
+ 	
+ 	MemoryContextSwitchTo(oldcxt);
  }
  
  void
***************
*** 197,202 **** PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
--- 200,208 ----
  {
  	int			i;
  	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
+ 	MemoryContext		oldcxt;
+ 
+ 	oldcxt = MemoryContextSwitchTo(arg->mcxt);
  
  	if (arg->is_rowtype == 0)
  		elog(ERROR, "PLyTypeInfo struct is initialized for a Datum");
***************
*** 205,213 **** PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
  	if (arg->out.r.natts != desc->natts)
  	{
  		if (arg->out.r.atts)
! 			PLy_free(arg->out.r.atts);
  		arg->out.r.natts = desc->natts;
! 		arg->out.r.atts = PLy_malloc0(desc->natts * sizeof(PLyObToDatum));
  	}
  
  	Assert(OidIsValid(desc->tdtypeid));
--- 211,219 ----
  	if (arg->out.r.natts != desc->natts)
  	{
  		if (arg->out.r.atts)
! 			pfree(arg->out.r.atts);
  		arg->out.r.natts = desc->natts;
! 		arg->out.r.atts = palloc0(desc->natts * sizeof(PLyObToDatum));
  	}
  
  	Assert(OidIsValid(desc->tdtypeid));
***************
*** 249,260 **** PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
  			elog(ERROR, "cache lookup failed for type %u",
  				 desc->attrs[i]->atttypid);
  
! 		PLy_output_datum_func2(&(arg->out.r.atts[i]), typeTup,
  							   exec_ctx->curr_proc->langid,
  							   exec_ctx->curr_proc->trftypes);
  
  		ReleaseSysCache(typeTup);
  	}
  }
  
  void
--- 255,268 ----
  			elog(ERROR, "cache lookup failed for type %u",
  				 desc->attrs[i]->atttypid);
  
! 		PLy_output_datum_func2(&(arg->out.r.atts[i]), arg->mcxt, typeTup,
  							   exec_ctx->curr_proc->langid,
  							   exec_ctx->curr_proc->trftypes);
  
  		ReleaseSysCache(typeTup);
  	}
+ 	
+ 	MemoryContextSwitchTo(oldcxt);
  }
  
  void
***************
*** 370,383 **** PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv)
  }
  
  static void
! PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup, Oid langid, List *trftypes)
  {
  	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
  	Oid			element_type;
  	Oid			base_type;
  	Oid			funcid;
  
! 	perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
  	arg->typoid = HeapTupleGetOid(typeTup);
  	arg->typmod = -1;
  	arg->typioparam = getTypeIOParam(typeTup);
--- 378,394 ----
  }
  
  static void
! PLy_output_datum_func2(PLyObToDatum *arg, MemoryContext arg_mcxt, HeapTuple typeTup, Oid langid, List *trftypes)
  {
  	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
  	Oid			element_type;
  	Oid			base_type;
  	Oid			funcid;
+ 	MemoryContext		oldcxt;
+ 
+ 	oldcxt = MemoryContextSwitchTo(arg_mcxt);
  
! 	fmgr_info_cxt(typeStruct->typinput, &arg->typfunc, arg_mcxt);
  	arg->typoid = HeapTupleGetOid(typeTup);
  	arg->typmod = -1;
  	arg->typioparam = getTypeIOParam(typeTup);
***************
*** 394,400 **** PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup, Oid langid, List *t
  	if ((funcid = get_transform_tosql(base_type, langid, trftypes)))
  	{
  		arg->func = PLyObject_ToTransform;
! 		perm_fmgr_info(funcid, &arg->typtransform);
  	}
  	else if (typeStruct->typtype == TYPTYPE_COMPOSITE)
  	{
--- 405,411 ----
  	if ((funcid = get_transform_tosql(base_type, langid, trftypes)))
  	{
  		arg->func = PLyObject_ToTransform;
! 		fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
  	}
  	else if (typeStruct->typtype == TYPTYPE_COMPOSITE)
  	{
***************
*** 422,428 **** PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup, Oid langid, List *t
  		if (type_is_rowtype(element_type))
  			arg->func = PLyObject_ToComposite;
  
! 		arg->elm = PLy_malloc0(sizeof(*arg->elm));
  		arg->elm->func = arg->func;
  		arg->elm->typtransform = arg->typtransform;
  		arg->func = PLySequence_ToArray;
--- 433,439 ----
  		if (type_is_rowtype(element_type))
  			arg->func = PLyObject_ToComposite;
  
! 		arg->elm = palloc0(sizeof(*arg->elm));
  		arg->elm->func = arg->func;
  		arg->elm->typtransform = arg->typtransform;
  		arg->func = PLySequence_ToArray;
***************
*** 432,451 **** PLy_output_datum_func2(PLyObToDatum *arg, HeapTuple typeTup, Oid langid, List *t
  		get_type_io_data(element_type, IOFunc_input,
  						 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
  						 &arg->elm->typioparam, &funcid);
! 		perm_fmgr_info(funcid, &arg->elm->typfunc);
  	}
  }
  
  static void
! PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
  {
  	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
  	Oid			element_type;
  	Oid			base_type;
  	Oid			funcid;
  
  	/* Get the type's conversion information */
! 	perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
  	arg->typoid = HeapTupleGetOid(typeTup);
  	arg->typmod = -1;
  	arg->typioparam = getTypeIOParam(typeTup);
--- 443,467 ----
  		get_type_io_data(element_type, IOFunc_input,
  						 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
  						 &arg->elm->typioparam, &funcid);
! 		fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
  	}
+ 
+ 	MemoryContextSwitchTo(oldcxt);
  }
  
  static void
! PLy_input_datum_func2(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes)
  {
  	Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
  	Oid			element_type;
  	Oid			base_type;
  	Oid			funcid;
+ 	MemoryContext		oldcxt;
+ 
+ 	oldcxt = MemoryContextSwitchTo(arg_mcxt);
  
  	/* Get the type's conversion information */
! 	fmgr_info_cxt(typeStruct->typoutput, &arg->typfunc, arg_mcxt);
  	arg->typoid = HeapTupleGetOid(typeTup);
  	arg->typmod = -1;
  	arg->typioparam = getTypeIOParam(typeTup);
***************
*** 461,467 **** PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup, Oid lan
  	if ((funcid = get_transform_fromsql(base_type, langid, trftypes)))
  	{
  		arg->func = PLyObject_FromTransform;
! 		perm_fmgr_info(funcid, &arg->typtransform);
  	}
  	else
  		switch (base_type)
--- 477,483 ----
  	if ((funcid = get_transform_fromsql(base_type, langid, trftypes)))
  	{
  		arg->func = PLyObject_FromTransform;
! 		fmgr_info_cxt(funcid, &arg->typtransform, arg_mcxt);
  	}
  	else
  		switch (base_type)
***************
*** 503,509 **** PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup, Oid lan
  		char		dummy_delim;
  		Oid			funcid;
  
! 		arg->elm = PLy_malloc0(sizeof(*arg->elm));
  		arg->elm->func = arg->func;
  		arg->elm->typtransform = arg->typtransform;
  		arg->func = PLyList_FromArray;
--- 519,525 ----
  		char		dummy_delim;
  		Oid			funcid;
  
! 		arg->elm = palloc0(sizeof(*arg->elm));
  		arg->elm->func = arg->func;
  		arg->elm->typtransform = arg->typtransform;
  		arg->func = PLyList_FromArray;
***************
*** 512,519 **** PLy_input_datum_func2(PLyDatumToOb *arg, Oid typeOid, HeapTuple typeTup, Oid lan
  		get_type_io_data(element_type, IOFunc_output,
  						 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
  						 &arg->elm->typioparam, &funcid);
! 		perm_fmgr_info(funcid, &arg->elm->typfunc);
  	}
  }
  
  static PyObject *
--- 528,537 ----
  		get_type_io_data(element_type, IOFunc_output,
  						 &arg->elm->typlen, &arg->elm->typbyval, &arg->elm->typalign, &dummy_delim,
  						 &arg->elm->typioparam, &funcid);
! 		fmgr_info_cxt(funcid, &arg->elm->typfunc, arg_mcxt);
  	}
+ 
+ 	MemoryContextSwitchTo(oldcxt);
  }
  
  static PyObject *
***************
*** 752,764 **** PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
  	Datum		rv;
  	PLyTypeInfo info;
  	TupleDesc	desc;
  
  	if (typmod != -1)
  		elog(ERROR, "received unnamed record type as input");
  
  	/* Create a dummy PLyTypeInfo */
  	MemSet(&info, 0, sizeof(PLyTypeInfo));
! 	PLy_typeinfo_init(&info);
  	/* Mark it as needing output routines lookup */
  	info.is_rowtype = 2;
  
--- 770,789 ----
  	Datum		rv;
  	PLyTypeInfo info;
  	TupleDesc	desc;
+ 	MemoryContext cxt;
  
  	if (typmod != -1)
  		elog(ERROR, "received unnamed record type as input");
  
+ 	cxt = AllocSetContextCreate(CurrentMemoryContext,
+ 				  "PL python temp context",
+ 				  ALLOCSET_DEFAULT_MINSIZE,
+ 				  ALLOCSET_DEFAULT_INITSIZE,
+ 				  ALLOCSET_DEFAULT_MAXSIZE);
+ 
  	/* Create a dummy PLyTypeInfo */
  	MemSet(&info, 0, sizeof(PLyTypeInfo));
! 	PLy_typeinfo_init(&info, cxt);
  	/* Mark it as needing output routines lookup */
  	info.is_rowtype = 2;
  
***************
*** 775,780 **** PLyObject_ToComposite(PLyObToDatum *arg, int32 typmod, PyObject *plrv)
--- 800,806 ----
  	ReleaseTupleDesc(desc);
  
  	PLy_typeinfo_dealloc(&info);
+ 	MemoryContextDelete(cxt);
  
  	return rv;
  }
***************
*** 916,931 **** PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string)
  	HeapTuple	typeTup;
  	PLyTypeInfo locinfo;
  	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
  
  	/* Create a dummy PLyTypeInfo */
  	MemSet(&locinfo, 0, sizeof(PLyTypeInfo));
! 	PLy_typeinfo_init(&locinfo);
  
  	typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
  	if (!HeapTupleIsValid(typeTup))
  		elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
  
! 	PLy_output_datum_func2(&locinfo.out.d, typeTup,
  						   exec_ctx->curr_proc->langid,
  						   exec_ctx->curr_proc->trftypes);
  
--- 942,964 ----
  	HeapTuple	typeTup;
  	PLyTypeInfo locinfo;
  	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
+ 	MemoryContext 	cxt;
+ 
+ 	cxt = AllocSetContextCreate(CurrentMemoryContext,
+                                   "PL python temp context",
+                                   ALLOCSET_DEFAULT_MINSIZE,
+                                   ALLOCSET_DEFAULT_INITSIZE,
+                                   ALLOCSET_DEFAULT_MAXSIZE);
  
  	/* Create a dummy PLyTypeInfo */
  	MemSet(&locinfo, 0, sizeof(PLyTypeInfo));
! 	PLy_typeinfo_init(&locinfo, cxt);
  
  	typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(desc->tdtypeid));
  	if (!HeapTupleIsValid(typeTup))
  		elog(ERROR, "cache lookup failed for type %u", desc->tdtypeid);
  
! 	PLy_output_datum_func2(&locinfo.out.d, locinfo.mcxt, typeTup,
  						   exec_ctx->curr_proc->langid,
  						   exec_ctx->curr_proc->trftypes);
  
***************
*** 934,939 **** PLyString_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *string)
--- 967,973 ----
  	result = PLyObject_ToDatum(&locinfo.out.d, desc->tdtypmod, string);
  
  	PLy_typeinfo_dealloc(&locinfo);
+ 	MemoryContextDelete(cxt);
  
  	return result;
  }
***************
*** 1178,1196 **** PLyGenericObject_ToComposite(PLyTypeInfo *info, TupleDesc desc, PyObject *object
  	return result;
  }
  
- /*
-  * This routine is a crock, and so is everyplace that calls it.  The problem
-  * is that the cached form of plpython functions/queries is allocated permanently
-  * (mostly via malloc()) and never released until backend exit.  Subsidiary
-  * data structures such as fmgr info records therefore must live forever
-  * as well.  A better implementation would store all this stuff in a per-
-  * function memory context that could be reclaimed at need.  In the meantime,
-  * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
-  * it might allocate, and whatever the eventual function might allocate using
-  * fn_mcxt, will live forever too.
-  */
- static void
- perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
- {
- 	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
- }
--- 1212,1214 ----
*** a/src/pl/plpython/plpy_typeio.h
--- b/src/pl/plpython/plpy_typeio.h
***************
*** 88,96 **** typedef struct PLyTypeInfo
  	Oid			typ_relid;
  	TransactionId typrel_xmin;
  	ItemPointerData typrel_tid;
  } PLyTypeInfo;
  
! extern void PLy_typeinfo_init(PLyTypeInfo *arg);
  extern void PLy_typeinfo_dealloc(PLyTypeInfo *arg);
  
  extern void PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes);
--- 88,98 ----
  	Oid			typ_relid;
  	TransactionId typrel_xmin;
  	ItemPointerData typrel_tid;
+ 
+ 	MemoryContext mcxt;
  } PLyTypeInfo;
  
! extern void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt);
  extern void PLy_typeinfo_dealloc(PLyTypeInfo *arg);
  
  extern void PLy_input_datum_func(PLyTypeInfo *arg, Oid typeOid, HeapTuple typeTup, Oid langid, List *trftypes);
*** a/src/pl/plpython/plpy_util.c
--- b/src/pl/plpython/plpy_util.c
***************
*** 24,51 **** PLy_malloc(size_t bytes)
  	return MemoryContextAlloc(TopMemoryContext, bytes);
  }
  
- void *
- PLy_malloc0(size_t bytes)
- {
- 	void	   *ptr = PLy_malloc(bytes);
- 
- 	MemSet(ptr, 0, bytes);
- 	return ptr;
- }
- 
- char *
- PLy_strdup(const char *str)
- {
- 	char	   *result;
- 	size_t		len;
- 
- 	len = strlen(str) + 1;
- 	result = PLy_malloc(len);
- 	memcpy(result, str, len);
- 
- 	return result;
- }
- 
  /* define this away */
  void
  PLy_free(void *ptr)
--- 24,29 ----
*** a/src/pl/plpython/plpy_util.h
--- b/src/pl/plpython/plpy_util.h
***************
*** 7,14 ****
  #define PLPY_UTIL_H
  
  extern void *PLy_malloc(size_t bytes);
- extern void *PLy_malloc0(size_t bytes);
- extern char *PLy_strdup(const char *str);
  extern void PLy_free(void *ptr);
  
  extern PyObject *PLyUnicode_Bytes(PyObject *unicode);
--- 7,12 ----
