I've been trying to make pl/perl support 8.5's inline functions, with the
attached patch. The basics seem to be there, with at least one notable
exception, namely that plperl functions can do stuff only plperlu should do. I
presume this is because I really don't understand yet how plperl's trusted
interpreter initialization works, and have simply copied what looked like
important stuff from the original plperl call handler. I tested with this to
prove it:

    DO $$ qx{touch test.txt}; $$ language plperl;

This works both with plperl and plperlu. Hints, anyone? Comments?

--
Joshua Tolley / eggyknap
End Point Corporation
http://www.endpoint.com
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
index 5ef97df..8cdedb4 100644
*** a/src/include/catalog/pg_pltemplate.h
--- b/src/include/catalog/pg_pltemplate.h
*************** typedef FormData_pg_pltemplate *Form_pg_
*** 70,77 ****
  DATA(insert ( "plpgsql"		t t "plpgsql_call_handler" "plpgsql_inline_handler" "plpgsql_validator" "$libdir/plpgsql" _null_ ));
  DATA(insert ( "pltcl"		t t "pltcl_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
  DATA(insert ( "pltclu"		f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
! DATA(insert ( "plperl"		t t "plperl_call_handler" _null_ "plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plperlu"		f f "plperl_call_handler" _null_ "plperl_validator" "$libdir/plperl" _null_ ));
  DATA(insert ( "plpythonu"	f f "plpython_call_handler" _null_ _null_ "$libdir/plpython" _null_ ));
  
  #endif   /* PG_PLTEMPLATE_H */
--- 70,77 ----
  DATA(insert ( "plpgsql"		t t "plpgsql_call_handler" "plpgsql_inline_handler" "plpgsql_validator" "$libdir/plpgsql" _null_ ));
  DATA(insert ( "pltcl"		t t "pltcl_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
  DATA(insert ( "pltclu"		f f "pltclu_call_handler" _null_ _null_ "$libdir/pltcl" _null_ ));
! DATA(insert ( "plperl"		t t "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ ));
! DATA(insert ( "plperlu"		f f "plperl_call_handler" "plperl_inline_handler" "plperl_validator" "$libdir/plperl" _null_ ));
  DATA(insert ( "plpythonu"	f f "plpython_call_handler" _null_ _null_ "$libdir/plpython" _null_ ));
  
  #endif   /* PG_PLTEMPLATE_H */
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 4ed4f59..33ede1b 100644
*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
*************** static plperl_call_data *current_call_da
*** 144,149 ****
--- 144,150 ----
   * Forward declarations
   **********************************************************************/
  Datum		plperl_call_handler(PG_FUNCTION_ARGS);
+ Datum		plperl_inline_handler(PG_FUNCTION_ARGS);
  Datum		plperl_validator(PG_FUNCTION_ARGS);
  void		_PG_init(void);
  
*************** plperl_modify_tuple(HV *hvTD, TriggerDat
*** 862,870 ****
  
  
  /*
!  * 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.
   */
  PG_FUNCTION_INFO_V1(plperl_call_handler);
  
--- 863,872 ----
  
  
  /*
!  * plperl_call_handler and plperl_inline_handler are the only
!  * externally-visible parts of the plperl call interface.  The Postgres function
!  * and trigger managers call plperl_call_handler to execute a perl function, and
!  * call plperl_inline_handler to execute plperl code in a DO statement.
   */
  PG_FUNCTION_INFO_V1(plperl_call_handler);
  
*************** plperl_call_handler(PG_FUNCTION_ARGS)
*** 895,900 ****
--- 897,952 ----
  	return retval;
  }
  
+ PG_FUNCTION_INFO_V1(plperl_inline_handler);
+ 
+ Datum
+ plperl_inline_handler(PG_FUNCTION_ARGS)
+ {
+ 	InlineCodeBlock *codeblock = (InlineCodeBlock *) DatumGetPointer(PG_GETARG_DATUM(0));
+     FunctionCallInfoData fake_fcinfo;
+     FmgrInfo flinfo;
+     plperl_proc_desc desc;
+     HeapTuple	langTup;
+     Form_pg_language langStruct;
+ 
+     MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));                                                            
+     MemSet(&flinfo, 0, sizeof(flinfo));                                                                      
+     MemSet(&desc, 0, sizeof(desc));
+     fake_fcinfo.flinfo = &flinfo;                                                                            
+     flinfo.fn_oid = InvalidOid;                                                                              
+     flinfo.fn_mcxt = CurrentMemoryContext; 
+ 
+     desc.proname = "";
+     desc.fn_readonly = 0;
+ 
+     /************************************************************
+     * Lookup the pg_language tuple by Oid
+     ************************************************************/
+     langTup = SearchSysCache(LANGOID,
+                                 ObjectIdGetDatum(codeblock->langOid),
+                                 0, 0, 0);
+     if (!HeapTupleIsValid(langTup))
+     {
+         elog(ERROR, "cache lookup failed for language with OID %d",
+                 codeblock->langOid);
+     }
+     langStruct = (Form_pg_language) GETSTRUCT(langTup);
+     desc.lanpltrusted = langStruct->lanpltrusted;
+     ReleaseSysCache(langTup);
+     check_interp(desc.lanpltrusted);
+ 
+     desc.fn_retistuple = 0;
+     desc.fn_retisset = 0;
+     desc.fn_retisarray = 0;
+     desc.result_oid = VOIDOID;
+     desc.nargs = 0;
+     desc.reference = plperl_create_sub("", codeblock->source_text, 0);
+ 
+     plperl_call_perl_func(&desc, &fake_fcinfo);
+     PG_RETURN_VOID();
+ }
+ 
  /*
   * This is the other externally visible function - it is called when CREATE
   * FUNCTION is issued to validate the function being created/replaced.

Attachment: signature.asc
Description: Digital signature

Reply via email to