*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
***************
*** 189,194 **** typedef struct plperl_query_desc
--- 189,195 ----
  	Oid		   *argtypes;
  	FmgrInfo   *arginfuncs;
  	Oid		   *argtypioparams;
+ 	MemoryContext plan_ctx;
  } plperl_query_desc;
  
  /* hash table entry for query desc	*/
***************
*** 3211,3216 **** plperl_spi_prepare(char *query, int argc, SV **argv)
--- 3212,3218 ----
  {
  	plperl_query_desc *qdesc;
  	plperl_query_entry *hash_entry;
+ 	MemoryContext       plan_ctx;
  	bool		found;
  	SPIPlanPtr	plan;
  	int			i;
***************
*** 3220,3238 **** plperl_spi_prepare(char *query, int argc, SV **argv)
  
  	check_spi_usage_allowed();
  
! 	BeginInternalSubTransaction(NULL);
! 	MemoryContextSwitchTo(oldcontext);
  
  	/************************************************************
  	 * Allocate the new querydesc structure
  	 ************************************************************/
! 	qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
! 	MemSet(qdesc, 0, sizeof(plperl_query_desc));
  	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
  	qdesc->nargs = argc;
! 	qdesc->argtypes = (Oid *) malloc(argc * sizeof(Oid));
! 	qdesc->arginfuncs = (FmgrInfo *) malloc(argc * sizeof(FmgrInfo));
! 	qdesc->argtypioparams = (Oid *) malloc(argc * sizeof(Oid));
  
  	PG_TRY();
  	{
--- 3222,3248 ----
  
  	check_spi_usage_allowed();
  
! 	CHECK_FOR_INTERRUPTS();
  
  	/************************************************************
  	 * Allocate the new querydesc structure
  	 ************************************************************/
! 	plan_ctx = AllocSetContextCreate(TopMemoryContext,
! 								  "PL/Perl spi_prepare cxt",
! 								  ALLOCSET_DEFAULT_MINSIZE,
! 								  ALLOCSET_DEFAULT_INITSIZE,
! 								  ALLOCSET_DEFAULT_MAXSIZE);
! 	MemoryContextSwitchTo(plan_ctx);
! 	qdesc = (plperl_query_desc *) palloc0(sizeof(plperl_query_desc));
  	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
  	qdesc->nargs = argc;
! 	qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
! 	qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
! 	qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
! 	qdesc->plan_ctx = plan_ctx;
! 
! 	BeginInternalSubTransaction(NULL);
! 	MemoryContextSwitchTo(oldcontext);
  
  	PG_TRY();
  	{
***************
*** 3256,3262 **** plperl_spi_prepare(char *query, int argc, SV **argv)
  			getTypeInputInfo(typId, &typInput, &typIOParam);
  
  			qdesc->argtypes[i] = typId;
! 			perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
  			qdesc->argtypioparams[i] = typIOParam;
  		}
  
--- 3266,3272 ----
  			getTypeInputInfo(typId, &typInput, &typIOParam);
  
  			qdesc->argtypes[i] = typId;
! 			fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_ctx);
  			qdesc->argtypioparams[i] = typIOParam;
  		}
  
***************
*** 3295,3304 **** plperl_spi_prepare(char *query, int argc, SV **argv)
  	{
  		ErrorData  *edata;
  
! 		free(qdesc->argtypes);
! 		free(qdesc->arginfuncs);
! 		free(qdesc->argtypioparams);
! 		free(qdesc);
  
  		/* Save error info */
  		MemoryContextSwitchTo(oldcontext);
--- 3305,3311 ----
  	{
  		ErrorData  *edata;
  
! 		MemoryContextDelete(plan_ctx);
  
  		/* Save error info */
  		MemoryContextSwitchTo(oldcontext);
***************
*** 3329,3335 **** plperl_spi_prepare(char *query, int argc, SV **argv)
  	 * Insert a hashtable entry for the plan and return
  	 * the key to the caller.
  	 ************************************************************/
- 
  	hash_entry = hash_search(plperl_active_interp->query_hash, qdesc->qname,
  							 HASH_ENTER, &found);
  	hash_entry->query_data = qdesc;
--- 3336,3341 ----
***************
*** 3619,3630 **** plperl_spi_freeplan(char *query)
  	hash_entry = hash_search(plperl_active_interp->query_hash, query,
  							 HASH_FIND, NULL);
  	if (hash_entry == NULL)
! 		elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
  
  	qdesc = hash_entry->query_data;
  
  	if (qdesc == NULL)
! 		elog(ERROR, "spi_exec_freeplan: panic - plperl query_hash value vanished");
  
  	/*
  	 * free all memory before SPI_freeplan, so if it dies, nothing will be
--- 3625,3636 ----
  	hash_entry = hash_search(plperl_active_interp->query_hash, query,
  							 HASH_FIND, NULL);
  	if (hash_entry == NULL)
! 		elog(ERROR, "spi_freeplan: Invalid prepared query passed");
  
  	qdesc = hash_entry->query_data;
  
  	if (qdesc == NULL)
! 		elog(ERROR, "spi_freeplan: panic - plperl query_hash value vanished");
  
  	/*
  	 * free all memory before SPI_freeplan, so if it dies, nothing will be
***************
*** 3634,3643 **** plperl_spi_freeplan(char *query)
  				HASH_REMOVE, NULL);
  
  	plan = qdesc->plan;
! 	free(qdesc->argtypes);
! 	free(qdesc->arginfuncs);
! 	free(qdesc->argtypioparams);
! 	free(qdesc);
  
  	SPI_freeplan(plan);
  }
--- 3640,3646 ----
  				HASH_REMOVE, NULL);
  
  	plan = qdesc->plan;
! 	MemoryContextDelete(qdesc->plan_ctx);
  
  	SPI_freeplan(plan);
  }
