33
33
* ENHANCEMENTS, OR MODIFICATIONS.
34
34
*
35
35
* 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 $
37
37
*
38
38
**********************************************************************/
39
39
@@ -80,6 +80,7 @@ typedef struct plperl_proc_desc
80
80
CommandId fn_cmin ;
81
81
bool lanpltrusted ;
82
82
bool fn_retistuple ; /* true, if function returns tuple */
83
+ bool fn_retisset ; /*true, if function returns set*/
83
84
Oid ret_oid ; /* Oid of returning type */
84
85
FmgrInfo result_in_func ;
85
86
Oid result_typioparam ;
@@ -95,11 +96,13 @@ typedef struct plperl_proc_desc
95
96
* Global data
96
97
**********************************************************************/
97
98
static int plperl_firstcall = 1 ;
99
+ static bool plperl_safe_init_done = false;
98
100
static PerlInterpreter * plperl_interp = NULL ;
99
101
static 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 ;
103
106
104
107
/**********************************************************************
105
108
* Forward declarations
@@ -215,11 +218,7 @@ plperl_init_interp(void)
215
218
* no commas between the next lines please. They are supposed to be
216
219
* one string
217
220
*/
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);"
223
222
"sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
224
223
};
225
224
@@ -238,6 +237,41 @@ plperl_init_interp(void)
238
237
239
238
}
240
239
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
+
241
275
/**********************************************************************
242
276
* turn a tuple into a hash expression and add it to a list
243
277
**********************************************************************/
@@ -596,6 +630,9 @@ plperl_create_sub(char *s, bool trusted)
596
630
SV * subref ;
597
631
int count ;
598
632
633
+ if (trusted && !plperl_safe_init_done )
634
+ plperl_safe_init ();
635
+
599
636
ENTER ;
600
637
SAVETMPS ;
601
638
PUSHMARK (SP );
@@ -839,15 +876,22 @@ plperl_func_handler(PG_FUNCTION_ARGS)
839
876
/* Find or compile the function */
840
877
prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
841
878
/************************************************************
842
- * Call the Perl function
879
+ * Call the Perl function if not returning set
843
880
************************************************************/
881
+ if (!prodesc -> fn_retisset )
844
882
perlret = plperl_call_perl_func (prodesc , fcinfo );
845
- if ( prodesc -> fn_retistuple && SRF_IS_FIRSTCALL ())
883
+ else
846
884
{
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 ();
848
893
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" );
851
895
}
852
896
853
897
/************************************************************
@@ -882,14 +926,15 @@ plperl_func_handler(PG_FUNCTION_ARGS)
882
926
char * * values = NULL ;
883
927
ReturnSetInfo * rsinfo = (ReturnSetInfo * ) fcinfo -> resultinfo ;
884
928
885
- if (!rsinfo )
929
+ if (prodesc -> fn_retisset && !rsinfo )
886
930
ereport (ERROR ,
887
931
(errcode (ERRCODE_SYNTAX_ERROR ),
888
932
errmsg ("returning a composite type is not allowed in this context" ),
889
933
errhint ("This function is intended for use in the FROM clause." )));
890
934
891
935
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
+
893
938
894
939
isset = plperl_is_set (perlret );
895
940
@@ -997,6 +1042,53 @@ plperl_func_handler(PG_FUNCTION_ARGS)
997
1042
SRF_RETURN_DONE (funcctx );
998
1043
}
999
1044
}
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
+ }
1000
1092
else if (! fcinfo -> isnull )
1001
1093
{
1002
1094
retval = FunctionCall3 (& prodesc -> result_in_func ,
@@ -1249,6 +1341,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
1249
1341
}
1250
1342
}
1251
1343
1344
+ prodesc -> fn_retisset = procStruct -> proretset ; /*true, if function returns set*/
1345
+
1252
1346
if (typeStruct -> typtype == 'c' || procStruct -> prorettype == RECORDOID )
1253
1347
{
1254
1348
prodesc -> fn_retistuple = true;
0 commit comments