3333 * ENHANCEMENTS, OR MODIFICATIONS.
3434 *
3535 * IDENTIFICATION
36- * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.45 2004/07/01 20:50:22 joe Exp $
36+ * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.46 2004/07/12 14:31:04 momjian Exp $
3737 *
3838 **********************************************************************/
3939
@@ -80,6 +80,7 @@ typedef struct plperl_proc_desc
8080 CommandId fn_cmin ;
8181 bool lanpltrusted ;
8282 bool fn_retistuple ; /* true, if function returns tuple */
83+ bool fn_retisset ; /*true, if function returns set*/
8384 Oid ret_oid ; /* Oid of returning type */
8485 FmgrInfo result_in_func ;
8586 Oid result_typioparam ;
@@ -95,11 +96,13 @@ typedef struct plperl_proc_desc
9596 * Global data
9697 **********************************************************************/
9798static int plperl_firstcall = 1 ;
99+ static bool plperl_safe_init_done = false;
98100static PerlInterpreter * plperl_interp = NULL ;
99101static HV * plperl_proc_hash = NULL ;
100- AV * g_row_keys = NULL ;
101- AV * g_column_keys = NULL ;
102- int g_attr_num = 0 ;
102+ static AV * g_row_keys = NULL ;
103+ static AV * g_column_keys = NULL ;
104+ static SV * srf_perlret = NULL ; /*keep returned value*/
105+ static int g_attr_num = 0 ;
103106
104107/**********************************************************************
105108 * Forward declarations
@@ -215,11 +218,7 @@ plperl_init_interp(void)
215218 * no commas between the next lines please. They are supposed to be
216219 * one string
217220 */
218- "require Safe; SPI::bootstrap(); use vars qw(%_SHARED);"
219- "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
220- "$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
221- "$PLContainer->share(qw[&elog &spi_exec_query &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
222- "sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
221+ "SPI::bootstrap(); use vars qw(%_SHARED);"
223222 "sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
224223 };
225224
@@ -238,6 +237,41 @@ plperl_init_interp(void)
238237
239238}
240239
240+
241+ static void
242+ plperl_safe_init (void )
243+ {
244+ static char * safe_module =
245+ "require Safe; $Safe::VERSION" ;
246+
247+ static char * safe_ok =
248+ "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
249+ "$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
250+ "$PLContainer->share(qw[&elog &spi_exec_query &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
251+ "sub ::mksafefunc { return $PLContainer->reval(qq[sub { $_[0] $_[1]}]); }"
252+ ;
253+
254+ static char * safe_bad =
255+ "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
256+ "$PLContainer->permit_only(':default');$PLContainer->permit(':base_math');"
257+ "$PLContainer->share(qw[&elog &DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %SHARED ]);"
258+ "sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
259+ "elog(ERROR,'trusted perl functions disabled - please upgrade perl Safe module to at least 2.09');}]); }"
260+ ;
261+
262+ SV * res ;
263+
264+ float safe_version ;
265+
266+ res = eval_pv (safe_module ,FALSE); /* TRUE = croak if failure */
267+
268+ safe_version = SvNV (res );
269+
270+ eval_pv ((safe_version < 2.09 ? safe_bad : safe_ok ),FALSE);
271+
272+ plperl_safe_init_done = true;
273+ }
274+
241275/**********************************************************************
242276 * turn a tuple into a hash expression and add it to a list
243277 **********************************************************************/
@@ -596,6 +630,9 @@ plperl_create_sub(char *s, bool trusted)
596630 SV * subref ;
597631 int count ;
598632
633+ if (trusted && !plperl_safe_init_done )
634+ plperl_safe_init ();
635+
599636 ENTER ;
600637 SAVETMPS ;
601638 PUSHMARK (SP );
@@ -839,15 +876,22 @@ plperl_func_handler(PG_FUNCTION_ARGS)
839876 /* Find or compile the function */
840877 prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
841878 /************************************************************
842- * Call the Perl function
879+ * Call the Perl function if not returning set
843880 ************************************************************/
881+ if (!prodesc -> fn_retisset )
844882 perlret = plperl_call_perl_func (prodesc , fcinfo );
845- if ( prodesc -> fn_retistuple && SRF_IS_FIRSTCALL ())
883+ else
846884 {
847-
885+ if (SRF_IS_FIRSTCALL ()) /*call function only once*/
886+ srf_perlret = plperl_call_perl_func (prodesc , fcinfo );
887+ perlret = srf_perlret ;
888+ }
889+
890+ if (prodesc -> fn_retisset && SRF_IS_FIRSTCALL ())
891+ {
892+ if (prodesc -> fn_retistuple ) g_column_keys = newAV ();
848893 if (SvTYPE (perlret ) != SVt_RV )
849- elog (ERROR , "plperl: this function must return a reference" );
850- g_column_keys = newAV ();
894+ elog (ERROR , "plperl: set-returning function must return reference" );
851895 }
852896
853897 /************************************************************
@@ -882,14 +926,15 @@ plperl_func_handler(PG_FUNCTION_ARGS)
882926 char * * values = NULL ;
883927 ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
884928
885- if (!rsinfo )
929+ if (prodesc -> fn_retisset && !rsinfo )
886930 ereport (ERROR ,
887931 (errcode (ERRCODE_SYNTAX_ERROR ),
888932 errmsg ("returning a composite type is not allowed in this context" ),
889933 errhint ("This function is intended for use in the FROM clause." )));
890934
891935 if (SvTYPE (perlret ) != SVt_RV )
892- elog (ERROR , "plperl: this function must return a reference" );
936+ elog (ERROR , "plperl: composite-returning function must return a reference" );
937+
893938
894939 isset = plperl_is_set (perlret );
895940
@@ -997,6 +1042,53 @@ plperl_func_handler(PG_FUNCTION_ARGS)
9971042 SRF_RETURN_DONE (funcctx );
9981043 }
9991044 }
1045+ else if (prodesc -> fn_retisset )
1046+ {
1047+ FuncCallContext * funcctx ;
1048+
1049+ if (SRF_IS_FIRSTCALL ())
1050+ {
1051+ MemoryContext oldcontext ;
1052+ int i ;
1053+
1054+ funcctx = SRF_FIRSTCALL_INIT ();
1055+ oldcontext = MemoryContextSwitchTo (funcctx -> multi_call_memory_ctx );
1056+
1057+ if (SvTYPE (SvRV (perlret ))!= SVt_PVAV ) elog (ERROR , "plperl: set-returning function must return reference to array" );
1058+ else funcctx -> max_calls = av_len ((AV * )SvRV (perlret ))+ 1 ;
1059+ }
1060+
1061+ funcctx = SRF_PERCALL_SETUP ();
1062+
1063+ if (funcctx -> call_cntr < funcctx -> max_calls )
1064+ {
1065+ Datum result ;
1066+ AV * array ;
1067+ SV * * svp ;
1068+ int i ;
1069+
1070+ array = (AV * )SvRV (perlret );
1071+ svp = av_fetch (array , funcctx -> call_cntr , FALSE);
1072+
1073+ if (SvTYPE (* svp ) != SVt_NULL )
1074+ result = FunctionCall3 (& prodesc -> result_in_func ,
1075+ PointerGetDatum (SvPV (* svp , PL_na )),
1076+ ObjectIdGetDatum (prodesc -> result_typioparam ),
1077+ Int32GetDatum (-1 ));
1078+ else
1079+ {
1080+ fcinfo -> isnull = true;
1081+ result = (Datum ) 0 ;
1082+ }
1083+ SRF_RETURN_NEXT (funcctx , result );
1084+ fcinfo -> isnull = false;
1085+ }
1086+ else
1087+ {
1088+ if (perlret ) SvREFCNT_dec (perlret );
1089+ SRF_RETURN_DONE (funcctx );
1090+ }
1091+ }
10001092 else if (! fcinfo -> isnull )
10011093 {
10021094 retval = FunctionCall3 (& prodesc -> result_in_func ,
@@ -1249,6 +1341,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
12491341 }
12501342 }
12511343
1344+ prodesc -> fn_retisset = procStruct -> proretset ; /*true, if function returns set*/
1345+
12521346 if (typeStruct -> typtype == 'c' || procStruct -> prorettype == RECORDOID )
12531347 {
12541348 prodesc -> fn_retistuple = true;
0 commit comments