Index: plperl.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plperl/plperl.c,v
retrieving revision 1.76
diff -c -r1.76 plperl.c
*** plperl.c	5 Jun 2005 03:16:35 -0000	1.76
--- plperl.c	21 Jun 2005 23:09:48 -0000
***************
*** 113,118 ****
--- 114,120 ----
  static void plperl_init_interp(void);
  
  Datum		plperl_call_handler(PG_FUNCTION_ARGS);
+ Datum		plperl_validator(PG_FUNCTION_ARGS);
  void		plperl_init(void);
  
  HV		   *plperl_spi_exec(char *query, int limit);
***************
*** 505,511 ****
  }
  
  
! /* This is the only externally-visible part of the plperl interface.
   * The Postgres function and trigger managers call it to execute a
   * perl function. */
  
--- 586,592 ----
  }
  
  
! /* This is the only externally-visible part of the plperl call interface.
   * The Postgres function and trigger managers call it to execute a
   * perl function. */
  
***************
*** 540,545 ****
--- 621,676 ----
  	return retval;
  }
  
+ /*
+  * This is the other externally visible function - it is called when CREATE OR
+  * REPLACE FUNCTION is issued to validate the function being created/replaced.
+  *
+  * Some code copied from plpgsql's validator, but in our case most of the
+  * checking is built into the compile routine, so we need to do less work here.
+  */
+ 
+ PG_FUNCTION_INFO_V1(plperl_validator);
+ 
+ Datum
+ plperl_validator(PG_FUNCTION_ARGS)
+ {
+ 
+ 	Oid funcoid;
+     HeapTuple   tuple;
+     Form_pg_proc proc;
+     char        functyptype;
+     bool        istrigger = false;
+ 	plperl_proc_desc *prodesc;
+ 
+ 	plperl_init_all();
+ 
+ 	funcoid = PG_GETARG_OID(0);
+ 
+     /* Get the new function's pg_proc entry */
+     tuple = SearchSysCache(PROCOID,
+                            ObjectIdGetDatum(funcoid),
+                            0, 0, 0);
+     if (!HeapTupleIsValid(tuple))
+         elog(ERROR, "cache lookup failed for function %u", funcoid);
+     proc = (Form_pg_proc) GETSTRUCT(tuple);
+ 
+     functyptype = get_typtype(proc->prorettype);
+ 
+     if (functyptype == 'p')
+     {
+         /* we assume OPAQUE with no arguments means a trigger */
+         istrigger = (proc->prorettype == TRIGGEROID ||
+ 					 (proc->prorettype == OPAQUEOID && proc->pronargs == 0));
+ 	}
+ 
+ 	prodesc = compile_plperl_function(funcoid,istrigger);
+ 
+ 	ReleaseSysCache(tuple);
+ 
+ 	/* the result of a validator is ignored */
+ 	PG_RETURN_VOID();
+ }
+ 
  
  /* Uses mksafefunc/mkunsafefunc to create an anonymous sub whose text is
   * supplied in s, and returns a reference to the closure. */
***************
*** 599,605 ****
  	 */
  	subref = newSVsv(POPs);
  
! 	if (!SvROK(subref))
  	{
  		PUTBACK;
  		FREETMPS;
--- 730,736 ----
  	 */
  	subref = newSVsv(POPs);
  
! 	if (!SvROK(subref) || SvTYPE(SvRV(subref)) != SVt_PVCV)
  	{
  		PUTBACK;
  		FREETMPS;
