1 /**********************************************************************
2 * plperl.c - perl as a procedural language for PostgreSQL
6 * This software is copyrighted by Mark Hollomon
7 * but is shameless cribbed from pltcl.c by Jan Wieck.
9 * The author hereby grants permission to use, copy, modify,
10 * distribute, and license this software and its documentation
11 * for any purpose, provided that existing copyright notices are
12 * retained in all copies and that this notice is included
13 * verbatim in any distributions. No written agreement, license,
14 * or royalty fee is required for any of the authorized uses.
15 * Modifications to this software may be copyrighted by their
16 * author and need not follow the licensing terms described
17 * here, provided that the new terms are clearly indicated on
18 * the first page of each file where they apply.
20 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
21 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
22 * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
23 * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
24 * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
27 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
30 * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
31 * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
32 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
33 * ENHANCEMENTS, OR MODIFICATIONS.
36 * $PostgreSQL: pgsql/src/pl/plperl/plperl.c,v 1.80 2005/07/06 22:33:39 momjian Exp $
38 **********************************************************************/
49 /* postgreSQL stuff */
50 #include "commands/trigger.h"
51 #include "executor/spi.h"
53 #include "utils/lsyscache.h"
54 #include "utils/memutils.h"
55 #include "utils/typcache.h"
56 #include "miscadmin.h"
57 #include "mb/pg_wchar.h"
65 /* just in case these symbols aren't provided */
72 /**********************************************************************
73 * The information we cache about loaded procedures
74 **********************************************************************/
75 typedef struct plperl_proc_desc
78 TransactionId fn_xmin;
82 bool fn_retistuple; /* true, if function returns tuple */
83 bool fn_retisset; /* true, if function returns set */
84 Oid result_oid; /* Oid of result type */
85 FmgrInfo result_in_func; /* I/O function and arg for result type */
86 Oid result_typioparam;
88 FmgrInfo arg_out_func[FUNC_MAX_ARGS];
89 bool arg_is_rowtype[FUNC_MAX_ARGS];
91 FunctionCallInfo caller_info;
92 Tuplestorestate *tuple_store;
97 /**********************************************************************
99 **********************************************************************/
100 static int plperl_firstcall = 1;
101 static bool plperl_safe_init_done = false;
102 static PerlInterpreter *plperl_interp = NULL;
103 static HV *plperl_proc_hash = NULL;
105 static bool plperl_use_strict = false;
107 /* this is saved and restored by plperl_call_handler */
108 static plperl_proc_desc *plperl_current_prodesc = NULL;
110 /**********************************************************************
111 * Forward declarations
112 **********************************************************************/
113 static void plperl_init_all(void);
114 static void plperl_init_interp(void);
116 Datum plperl_call_handler(PG_FUNCTION_ARGS);
117 Datum plperl_validator(PG_FUNCTION_ARGS);
118 void plperl_init(void);
120 HV *plperl_spi_exec(char *query, int limit);
122 static Datum plperl_func_handler(PG_FUNCTION_ARGS);
124 static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
125 static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger);
127 static SV *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc);
128 static void plperl_init_shared_libs(pTHX);
129 static HV *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
131 void plperl_return_next(SV *);
134 * This routine is a crock, and so is everyplace that calls it. The problem
135 * is that the cached form of plperl functions/queries is allocated permanently
136 * (mostly via malloc()) and never released until backend exit. Subsidiary
137 * data structures such as fmgr info records therefore must live forever
138 * as well. A better implementation would store all this stuff in a per-
139 * function memory context that could be reclaimed at need. In the meantime,
140 * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
141 * it might allocate, and whatever the eventual function might allocate using
142 * fn_mcxt, will live forever too.
145 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
147 fmgr_info_cxt(functionId, finfo, TopMemoryContext);
151 /* Perform initialization during postmaster startup. */
156 if (!plperl_firstcall)
159 DefineCustomBoolVariable(
161 "If true, will compile trusted and untrusted perl code in strict mode",
167 EmitWarningsOnPlaceholders("plperl");
169 plperl_init_interp();
170 plperl_firstcall = 0;
174 /* Perform initialization during backend startup. */
177 plperl_init_all(void)
179 if (plperl_firstcall)
182 /* We don't need to do anything yet when a new backend starts. */
187 plperl_init_interp(void)
189 static char *loose_embedding[3] = {
191 /* all one string follows (no commas please) */
192 "SPI::bootstrap(); use vars qw(%_SHARED);"
193 "sub ::plperl_warn { my $msg = shift; &elog(&NOTICE, $msg); } "
194 "$SIG{__WARN__} = \\&::plperl_warn; "
195 "sub ::mkunsafefunc {return eval(qq[ sub { $_[0] $_[1] } ]); }"
198 static char *strict_embedding[3] = {
200 /* all one string follows (no commas please) */
201 "SPI::bootstrap(); use vars qw(%_SHARED);"
202 "sub ::plperl_warn { my $msg = shift; &elog(&NOTICE, $msg); } "
203 "$SIG{__WARN__} = \\&::plperl_warn; "
204 "sub ::mkunsafefunc {return eval("
205 "qq[ sub { use strict; $_[0] $_[1] } ]); }"
208 plperl_interp = perl_alloc();
210 elog(ERROR, "could not allocate Perl interpreter");
212 perl_construct(plperl_interp);
213 perl_parse(plperl_interp, plperl_init_shared_libs, 3 ,
214 (plperl_use_strict ? strict_embedding : loose_embedding), NULL);
215 perl_run(plperl_interp);
217 plperl_proc_hash = newHV();
222 plperl_safe_init(void)
224 static char *safe_module =
225 "require Safe; $Safe::VERSION";
227 static char *common_safe_ok =
228 "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
229 "$PLContainer->permit_only(':default');"
230 "$PLContainer->permit(qw[:base_math !:base_io sort time]);"
231 "$PLContainer->share(qw[&elog &spi_exec_query &return_next "
232 "&DEBUG &LOG &INFO &NOTICE &WARNING &ERROR %_SHARED ]);"
235 static char * strict_safe_ok =
236 "$PLContainer->permit('require');$PLContainer->reval('use strict;');"
237 "$PLContainer->deny('require');"
238 "sub ::mksafefunc { return $PLContainer->reval(qq[ "
239 " sub { BEGIN { strict->import(); } $_[0] $_[1]}]); }"
242 static char * loose_safe_ok =
243 "sub ::mksafefunc { return $PLContainer->reval(qq[ "
244 " sub { $_[0] $_[1]}]); }"
247 static char *safe_bad =
248 "use vars qw($PLContainer); $PLContainer = new Safe('PLPerl');"
249 "$PLContainer->permit_only(':default');"
250 "$PLContainer->share(qw[&elog &ERROR ]);"
251 "sub ::mksafefunc { return $PLContainer->reval(qq[sub { "
252 "elog(ERROR,'trusted Perl functions disabled - "
253 "please upgrade Perl Safe module to version 2.09 or later');}]); }"
259 res = eval_pv(safe_module, FALSE); /* TRUE = croak if failure */
261 safe_version = SvNV(res);
264 * We actually want to reject safe_version < 2.09, but it's risky to
265 * assume that floating-point comparisons are exact, so use a slightly
266 * smaller comparison value.
268 if (safe_version < 2.0899 )
270 /* not safe, so disallow all trusted funcs */
271 eval_pv(safe_bad, FALSE);
275 eval_pv(common_safe_ok, FALSE);
276 eval_pv((plperl_use_strict ? strict_safe_ok : loose_safe_ok), FALSE);
279 plperl_safe_init_done = true;
284 * Perl likes to put a newline after its error messages; clean up such
287 strip_trailing_ws(const char *msg)
289 char *res = pstrdup(msg);
290 int len = strlen(res);
292 while (len > 0 && isspace((unsigned char) res[len-1]))
298 /* Build a tuple from a hash. */
301 plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
303 TupleDesc td = attinmeta->tupdesc;
310 values = (char **) palloc0(td->natts * sizeof(char *));
312 hv_iterinit(perlhash);
313 while ((val = hv_iternextsv(perlhash, &key, &klen)))
315 int attn = SPI_fnumber(td, key);
317 if (attn <= 0 || td->attrs[attn - 1]->attisdropped)
319 (errcode(ERRCODE_UNDEFINED_COLUMN),
320 errmsg("Perl hash contains nonexistent column \"%s\"",
322 if (SvOK(val) && SvTYPE(val) != SVt_NULL)
323 values[attn - 1] = SvPV(val, PL_na);
325 hv_iterinit(perlhash);
327 tup = BuildTupleFromCStrings(attinmeta, values);
333 /* Set up the arguments for a trigger call. */
336 plperl_trigger_build_args(FunctionCallInfo fcinfo)
349 tdata = (TriggerData *) fcinfo->context;
350 tupdesc = tdata->tg_relation->rd_att;
352 relid = DatumGetCString(
353 DirectFunctionCall1(oidout,
354 ObjectIdGetDatum(tdata->tg_relation->rd_id)
358 hv_store(hv, "name", 4, newSVpv(tdata->tg_trigger->tgname, 0), 0);
359 hv_store(hv, "relid", 5, newSVpv(relid, 0), 0);
361 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
364 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
365 hv_store(hv, "new", 3,
366 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
369 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
372 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
373 hv_store(hv, "old", 3,
374 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
377 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
380 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
382 hv_store(hv, "old", 3,
383 plperl_hash_from_tuple(tdata->tg_trigtuple, tupdesc),
385 hv_store(hv, "new", 3,
386 plperl_hash_from_tuple(tdata->tg_newtuple, tupdesc),
393 hv_store(hv, "event", 5, newSVpv(event, 0), 0);
394 hv_store(hv, "argc", 4, newSViv(tdata->tg_trigger->tgnargs), 0);
396 if (tdata->tg_trigger->tgnargs > 0)
399 for (i=0; i < tdata->tg_trigger->tgnargs; i++)
400 av_push(av, newSVpv(tdata->tg_trigger->tgargs[i], 0));
401 hv_store(hv, "args", 4, newRV_noinc((SV *)av), 0);
404 hv_store(hv, "relname", 7,
405 newSVpv(SPI_getrelname(tdata->tg_relation), 0), 0);
407 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
409 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
413 hv_store(hv, "when", 4, newSVpv(when, 0), 0);
415 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
417 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
421 hv_store(hv, "level", 5, newSVpv(level, 0), 0);
423 return newRV_noinc((SV*)hv);
427 /* Set up the new tuple returned from a trigger. */
430 plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
445 tupdesc = tdata->tg_relation->rd_att;
447 svp = hv_fetch(hvTD, "new", 3, FALSE);
450 (errcode(ERRCODE_UNDEFINED_COLUMN),
451 errmsg("$_TD->{new} does not exist")));
452 if (!SvOK(*svp) || SvTYPE(*svp) != SVt_RV || SvTYPE(SvRV(*svp)) != SVt_PVHV)
454 (errcode(ERRCODE_DATATYPE_MISMATCH),
455 errmsg("$_TD->{new} is not a hash reference")));
456 hvNew = (HV *) SvRV(*svp);
458 modattrs = palloc(tupdesc->natts * sizeof(int));
459 modvalues = palloc(tupdesc->natts * sizeof(Datum));
460 modnulls = palloc(tupdesc->natts * sizeof(char));
464 while ((val = hv_iternextsv(hvNew, &key, &klen)))
466 int attn = SPI_fnumber(tupdesc, key);
468 if (attn <= 0 || tupdesc->attrs[attn - 1]->attisdropped)
470 (errcode(ERRCODE_UNDEFINED_COLUMN),
471 errmsg("Perl hash contains nonexistent column \"%s\"",
473 if (SvOK(val) && SvTYPE(val) != SVt_NULL)
479 /* XXX would be better to cache these lookups */
480 getTypeInputInfo(tupdesc->attrs[attn - 1]->atttypid,
481 &typinput, &typioparam);
482 fmgr_info(typinput, &finfo);
483 modvalues[slotsused] = FunctionCall3(&finfo,
484 CStringGetDatum(SvPV(val, PL_na)),
485 ObjectIdGetDatum(typioparam),
486 Int32GetDatum(tupdesc->attrs[attn - 1]->atttypmod));
487 modnulls[slotsused] = ' ';
491 modvalues[slotsused] = (Datum) 0;
492 modnulls[slotsused] = 'n';
494 modattrs[slotsused] = attn;
499 rtup = SPI_modifytuple(tdata->tg_relation, otup, slotsused,
500 modattrs, modvalues, modnulls);
507 elog(ERROR, "SPI_modifytuple failed: %s",
508 SPI_result_code_string(SPI_result));
515 * This is the only externally-visible part of the plperl call interface.
516 * The Postgres function and trigger managers call it to execute a
519 PG_FUNCTION_INFO_V1(plperl_call_handler);
522 plperl_call_handler(PG_FUNCTION_ARGS)
525 plperl_proc_desc *save_prodesc;
529 save_prodesc = plperl_current_prodesc;
533 if (CALLED_AS_TRIGGER(fcinfo))
534 retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
536 retval = plperl_func_handler(fcinfo);
540 plperl_current_prodesc = save_prodesc;
545 plperl_current_prodesc = save_prodesc;
551 * This is the other externally visible function - it is called when CREATE
552 * FUNCTION is issued to validate the function being created/replaced.
554 PG_FUNCTION_INFO_V1(plperl_validator);
557 plperl_validator(PG_FUNCTION_ARGS)
559 Oid funcoid = PG_GETARG_OID(0);
562 bool istrigger = false;
563 plperl_proc_desc *prodesc;
567 /* Get the new function's pg_proc entry */
568 tuple = SearchSysCache(PROCOID,
569 ObjectIdGetDatum(funcoid),
571 if (!HeapTupleIsValid(tuple))
572 elog(ERROR, "cache lookup failed for function %u", funcoid);
573 proc = (Form_pg_proc) GETSTRUCT(tuple);
575 /* we assume OPAQUE with no arguments means a trigger */
576 if (proc->prorettype == TRIGGEROID ||
577 (proc->prorettype == OPAQUEOID && proc->pronargs == 0))
580 ReleaseSysCache(tuple);
582 prodesc = compile_plperl_function(funcoid, istrigger);
584 /* the result of a validator is ignored */
589 /* Uses mksafefunc/mkunsafefunc to create an anonymous sub whose text is
590 * supplied in s, and returns a reference to the closure. */
593 plperl_create_sub(char *s, bool trusted)
599 if (trusted && !plperl_safe_init_done)
608 XPUSHs(sv_2mortal(newSVpv("my $_TD=$_[0]; shift;", 0)));
609 XPUSHs(sv_2mortal(newSVpv(s, 0)));
613 * G_KEEPERR seems to be needed here, else we don't recognize compile
614 * errors properly. Perhaps it's because there's another level of
615 * eval inside mksafefunc?
617 count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"),
618 G_SCALAR | G_EVAL | G_KEEPERR);
626 elog(ERROR, "didn't get a return item from mksafefunc");
636 (errcode(ERRCODE_SYNTAX_ERROR),
637 errmsg("creation of Perl function failed: %s",
638 strip_trailing_ws(SvPV(ERRSV, PL_na)))));
642 * need to make a deep copy of the return. it comes off the stack as a
645 subref = newSVsv(POPs);
647 if (!SvROK(subref) || SvTYPE(SvRV(subref)) != SVt_PVCV)
654 * subref is our responsibility because it is not mortal
656 SvREFCNT_dec(subref);
657 elog(ERROR, "didn't get a code ref");
668 /**********************************************************************
669 * plperl_init_shared_libs() -
671 * We cannot use the DynaLoader directly to get at the Opcode
672 * module (used by Safe.pm). So, we link Opcode into ourselves
673 * and do the initialization behind perl's back.
675 **********************************************************************/
677 EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
678 EXTERN_C void boot_SPI(pTHX_ CV *cv);
681 plperl_init_shared_libs(pTHX)
683 char *file = __FILE__;
685 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
686 newXS("SPI::bootstrap", boot_SPI, file);
691 plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
704 XPUSHs(&PL_sv_undef); /* no trigger data */
706 for (i = 0; i < desc->nargs; i++)
708 if (fcinfo->argnull[i])
709 XPUSHs(&PL_sv_undef);
710 else if (desc->arg_is_rowtype[i])
716 HeapTupleData tmptup;
719 td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
720 /* Extract rowtype info and find a tupdesc */
721 tupType = HeapTupleHeaderGetTypeId(td);
722 tupTypmod = HeapTupleHeaderGetTypMod(td);
723 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
724 /* Build a temporary HeapTuple control structure */
725 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
728 hashref = plperl_hash_from_tuple(&tmptup, tupdesc);
729 XPUSHs(sv_2mortal(hashref));
735 tmp = DatumGetCString(FunctionCall1(&(desc->arg_out_func[i]),
737 sv = newSVpv(tmp, 0);
738 #if PERL_BCDVERSION >= 0x5006000L
739 if (GetDatabaseEncoding() == PG_UTF8) SvUTF8_on(sv);
741 XPUSHs(sv_2mortal(sv));
747 /* Do NOT use G_KEEPERR here */
748 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
757 elog(ERROR, "didn't get a return item from function");
766 /* XXX need to find a way to assign an errcode here */
768 (errmsg("error from Perl function: %s",
769 strip_trailing_ws(SvPV(ERRSV, PL_na)))));
772 retval = newSVsv(POPs);
783 plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
799 tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
800 for (i = 0; i < tg_trigger->tgnargs; i++)
801 XPUSHs(sv_2mortal(newSVpv(tg_trigger->tgargs[i], 0)));
804 /* Do NOT use G_KEEPERR here */
805 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
814 elog(ERROR, "didn't get a return item from trigger function");
823 /* XXX need to find a way to assign an errcode here */
825 (errmsg("error from Perl trigger function: %s",
826 strip_trailing_ws(SvPV(ERRSV, PL_na)))));
829 retval = newSVsv(POPs);
840 plperl_func_handler(PG_FUNCTION_ARGS)
842 plperl_proc_desc *prodesc;
847 if (SPI_connect() != SPI_OK_CONNECT)
848 elog(ERROR, "could not connect to SPI manager");
850 prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
852 plperl_current_prodesc = prodesc;
853 prodesc->caller_info = fcinfo;
854 prodesc->tuple_store = 0;
855 prodesc->tuple_desc = 0;
857 perlret = plperl_call_perl_func(prodesc, fcinfo);
859 /************************************************************
860 * Disconnect from SPI manager and then create the return
861 * values datum (if the input function does a palloc for it
862 * this must not be allocated in the SPI memory context
863 * because SPI_finish would free it).
864 ************************************************************/
865 if (SPI_finish() != SPI_OK_FINISH)
866 elog(ERROR, "SPI_finish() failed");
868 rsi = (ReturnSetInfo *)fcinfo->resultinfo;
870 if (prodesc->fn_retisset) {
871 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
872 (rsi->allowedModes & SFRM_Materialize) == 0 ||
873 rsi->expectedDesc == NULL)
876 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
877 errmsg("set-valued function called in context that "
878 "cannot accept a set")));
881 /* If the Perl function returned an arrayref, we pretend that it
882 * called return_next() for each element of the array, to handle
883 * old SRFs that didn't know about return_next(). Any other sort
884 * of return value is an error. */
885 if (SvTYPE(perlret) == SVt_RV &&
886 SvTYPE(SvRV(perlret)) == SVt_PVAV)
890 AV *rav = (AV *)SvRV(perlret);
891 while ((svp = av_fetch(rav, i, FALSE)) != NULL) {
892 plperl_return_next(*svp);
896 else if (SvTYPE(perlret) != SVt_NULL)
899 (errcode(ERRCODE_DATATYPE_MISMATCH),
900 errmsg("set-returning Perl function must return "
901 "reference to array or use return_next")));
904 rsi->returnMode = SFRM_Materialize;
905 if (prodesc->tuple_store) {
906 rsi->setResult = prodesc->tuple_store;
907 rsi->setDesc = prodesc->tuple_desc;
911 else if (SvTYPE(perlret) == SVt_NULL)
913 /* Return NULL if Perl code returned undef */
914 if (rsi && IsA(rsi, ReturnSetInfo))
915 rsi->isDone = ExprEndResult;
916 fcinfo->isnull = true;
919 else if (prodesc->fn_retistuple)
921 /* Return a perl hash converted to a Datum */
923 AttInMetadata *attinmeta;
926 if (!SvOK(perlret) || SvTYPE(perlret) != SVt_RV ||
927 SvTYPE(SvRV(perlret)) != SVt_PVHV)
930 (errcode(ERRCODE_DATATYPE_MISMATCH),
931 errmsg("composite-returning Perl function "
932 "must return reference to hash")));
935 /* XXX should cache the attinmeta data instead of recomputing */
936 if (get_call_result_type(fcinfo, NULL, &td) != TYPEFUNC_COMPOSITE)
939 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
940 errmsg("function returning record called in context "
941 "that cannot accept type record")));
944 attinmeta = TupleDescGetAttInMetadata(td);
945 tup = plperl_build_tuple_result((HV *)SvRV(perlret), attinmeta);
946 retval = HeapTupleGetDatum(tup);
950 /* Return a perl string converted to a Datum */
951 char *val = SvPV(perlret, PL_na);
952 retval = FunctionCall3(&prodesc->result_in_func,
953 CStringGetDatum(val),
954 ObjectIdGetDatum(prodesc->result_typioparam),
958 SvREFCNT_dec(perlret);
964 plperl_trigger_handler(PG_FUNCTION_ARGS)
966 plperl_proc_desc *prodesc;
972 /* Connect to SPI manager */
973 if (SPI_connect() != SPI_OK_CONNECT)
974 elog(ERROR, "could not connect to SPI manager");
976 /* Find or compile the function */
977 prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);
979 plperl_current_prodesc = prodesc;
981 svTD = plperl_trigger_build_args(fcinfo);
982 perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
983 hvTD = (HV *) SvRV(svTD);
985 /************************************************************
986 * Disconnect from SPI manager and then create the return
987 * values datum (if the input function does a palloc for it
988 * this must not be allocated in the SPI memory context
989 * because SPI_finish would free it).
990 ************************************************************/
991 if (SPI_finish() != SPI_OK_FINISH)
992 elog(ERROR, "SPI_finish() failed");
994 if (!(perlret && SvOK(perlret) && SvTYPE(perlret) != SVt_NULL))
996 /* undef result means go ahead with original tuple */
997 TriggerData *trigdata = ((TriggerData *) fcinfo->context);
999 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
1000 retval = (Datum) trigdata->tg_trigtuple;
1001 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
1002 retval = (Datum) trigdata->tg_newtuple;
1003 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
1004 retval = (Datum) trigdata->tg_trigtuple;
1006 retval = (Datum) 0; /* can this happen? */
1013 tmp = SvPV(perlret, PL_na);
1015 if (pg_strcasecmp(tmp, "SKIP") == 0)
1017 else if (pg_strcasecmp(tmp, "MODIFY") == 0)
1019 TriggerData *trigdata = (TriggerData *) fcinfo->context;
1021 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
1022 trv = plperl_modify_tuple(hvTD, trigdata,
1023 trigdata->tg_trigtuple);
1024 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
1025 trv = plperl_modify_tuple(hvTD, trigdata,
1026 trigdata->tg_newtuple);
1030 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1031 errmsg("ignoring modified tuple in DELETE trigger")));
1038 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1039 errmsg("result of Perl trigger function must be undef, "
1040 "\"SKIP\" or \"MODIFY\"")));
1043 retval = PointerGetDatum(trv);
1048 SvREFCNT_dec(perlret);
1054 static plperl_proc_desc *
1055 compile_plperl_function(Oid fn_oid, bool is_trigger)
1058 Form_pg_proc procStruct;
1059 char internal_proname[64];
1061 plperl_proc_desc *prodesc = NULL;
1065 /* We'll need the pg_proc tuple in any case... */
1066 procTup = SearchSysCache(PROCOID,
1067 ObjectIdGetDatum(fn_oid),
1069 if (!HeapTupleIsValid(procTup))
1070 elog(ERROR, "cache lookup failed for function %u", fn_oid);
1071 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
1073 /************************************************************
1074 * Build our internal proc name from the functions Oid
1075 ************************************************************/
1077 sprintf(internal_proname, "__PLPerl_proc_%u", fn_oid);
1079 sprintf(internal_proname, "__PLPerl_proc_%u_trigger", fn_oid);
1081 proname_len = strlen(internal_proname);
1083 /************************************************************
1084 * Lookup the internal proc name in the hashtable
1085 ************************************************************/
1086 svp = hv_fetch(plperl_proc_hash, internal_proname, proname_len, FALSE);
1091 prodesc = (plperl_proc_desc *) SvIV(*svp);
1093 /************************************************************
1094 * If it's present, must check whether it's still up to date.
1095 * This is needed because CREATE OR REPLACE FUNCTION can modify the
1096 * function's pg_proc entry without changing its OID.
1097 ************************************************************/
1098 uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
1099 prodesc->fn_cmin == HeapTupleHeaderGetCmin(procTup->t_data));
1103 /* need we delete old entry? */
1108 /************************************************************
1109 * If we haven't found it in the hashtable, we analyze
1110 * the functions arguments and returntype and store
1111 * the in-/out-functions in the prodesc block and create
1112 * a new hashtable entry for it.
1114 * Then we load the procedure into the Perl interpreter.
1115 ************************************************************/
1116 if (prodesc == NULL)
1120 Form_pg_language langStruct;
1121 Form_pg_type typeStruct;
1126 /************************************************************
1127 * Allocate a new procedure description block
1128 ************************************************************/
1129 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
1130 if (prodesc == NULL)
1132 (errcode(ERRCODE_OUT_OF_MEMORY),
1133 errmsg("out of memory")));
1134 MemSet(prodesc, 0, sizeof(plperl_proc_desc));
1135 prodesc->proname = strdup(internal_proname);
1136 prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
1137 prodesc->fn_cmin = HeapTupleHeaderGetCmin(procTup->t_data);
1139 /* Remember if function is STABLE/IMMUTABLE */
1140 prodesc->fn_readonly =
1141 (procStruct->provolatile != PROVOLATILE_VOLATILE);
1143 /************************************************************
1144 * Lookup the pg_language tuple by Oid
1145 ************************************************************/
1146 langTup = SearchSysCache(LANGOID,
1147 ObjectIdGetDatum(procStruct->prolang),
1149 if (!HeapTupleIsValid(langTup))
1151 free(prodesc->proname);
1153 elog(ERROR, "cache lookup failed for language %u",
1154 procStruct->prolang);
1156 langStruct = (Form_pg_language) GETSTRUCT(langTup);
1157 prodesc->lanpltrusted = langStruct->lanpltrusted;
1158 ReleaseSysCache(langTup);
1160 /************************************************************
1161 * Get the required information for input conversion of the
1163 ************************************************************/
1166 typeTup = SearchSysCache(TYPEOID,
1167 ObjectIdGetDatum(procStruct->prorettype),
1169 if (!HeapTupleIsValid(typeTup))
1171 free(prodesc->proname);
1173 elog(ERROR, "cache lookup failed for type %u",
1174 procStruct->prorettype);
1176 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1178 /* Disallow pseudotype result, except VOID or RECORD */
1179 if (typeStruct->typtype == 'p')
1181 if (procStruct->prorettype == VOIDOID ||
1182 procStruct->prorettype == RECORDOID)
1184 else if (procStruct->prorettype == TRIGGEROID)
1186 free(prodesc->proname);
1189 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1190 errmsg("trigger functions may only be called "
1195 free(prodesc->proname);
1198 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1199 errmsg("plperl functions cannot return type %s",
1200 format_type_be(procStruct->prorettype))));
1204 prodesc->result_oid = procStruct->prorettype;
1205 prodesc->fn_retisset = procStruct->proretset;
1206 prodesc->fn_retistuple = (typeStruct->typtype == 'c' ||
1207 procStruct->prorettype == RECORDOID);
1209 perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
1210 prodesc->result_typioparam = getTypeIOParam(typeTup);
1212 ReleaseSysCache(typeTup);
1215 /************************************************************
1216 * Get the required information for output conversion
1217 * of all procedure arguments
1218 ************************************************************/
1221 prodesc->nargs = procStruct->pronargs;
1222 for (i = 0; i < prodesc->nargs; i++)
1224 typeTup = SearchSysCache(TYPEOID,
1225 ObjectIdGetDatum(procStruct->proargtypes.values[i]),
1227 if (!HeapTupleIsValid(typeTup))
1229 free(prodesc->proname);
1231 elog(ERROR, "cache lookup failed for type %u",
1232 procStruct->proargtypes.values[i]);
1234 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
1236 /* Disallow pseudotype argument */
1237 if (typeStruct->typtype == 'p')
1239 free(prodesc->proname);
1242 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1243 errmsg("plperl functions cannot take type %s",
1244 format_type_be(procStruct->proargtypes.values[i]))));
1247 if (typeStruct->typtype == 'c')
1248 prodesc->arg_is_rowtype[i] = true;
1251 prodesc->arg_is_rowtype[i] = false;
1252 perm_fmgr_info(typeStruct->typoutput,
1253 &(prodesc->arg_out_func[i]));
1256 ReleaseSysCache(typeTup);
1260 /************************************************************
1261 * create the text of the anonymous subroutine.
1262 * we do not use a named subroutine so that we can call directly
1263 * through the reference.
1264 ************************************************************/
1265 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
1266 Anum_pg_proc_prosrc, &isnull);
1268 elog(ERROR, "null prosrc");
1269 proc_source = DatumGetCString(DirectFunctionCall1(textout,
1272 /************************************************************
1273 * Create the procedure in the interpreter
1274 ************************************************************/
1275 prodesc->reference = plperl_create_sub(proc_source, prodesc->lanpltrusted);
1277 if (!prodesc->reference) /* can this happen? */
1279 free(prodesc->proname);
1281 elog(ERROR, "could not create internal procedure \"%s\"",
1285 hv_store(plperl_proc_hash, internal_proname, proname_len,
1286 newSViv((IV) prodesc), 0);
1289 ReleaseSysCache(procTup);
1295 /* Build a hash from all attributes of a given tuple. */
1298 plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
1305 for (i = 0; i < tupdesc->natts; i++)
1316 if (tupdesc->attrs[i]->attisdropped)
1319 attname = NameStr(tupdesc->attrs[i]->attname);
1320 namelen = strlen(attname);
1321 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1324 /* Store (attname => undef) and move on. */
1325 hv_store(hv, attname, namelen, newSV(0), 0);
1329 /* XXX should have a way to cache these lookups */
1331 getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
1332 &typoutput, &typisvarlena);
1334 outputstr = DatumGetCString(OidFunctionCall1(typoutput, attr));
1336 sv = newSVpv(outputstr, 0);
1337 #if PERL_BCDVERSION >= 0x5006000L
1338 if (GetDatabaseEncoding() == PG_UTF8)
1341 hv_store(hv, attname, namelen, sv, 0);
1346 return newRV_noinc((SV *) hv);
1351 plperl_spi_exec(char *query, int limit)
1356 * Execute the query inside a sub-transaction, so we can cope with
1359 MemoryContext oldcontext = CurrentMemoryContext;
1360 ResourceOwner oldowner = CurrentResourceOwner;
1362 BeginInternalSubTransaction(NULL);
1363 /* Want to run inside function's memory context */
1364 MemoryContextSwitchTo(oldcontext);
1370 spi_rv = SPI_execute(query, plperl_current_prodesc->fn_readonly,
1372 ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
1375 /* Commit the inner transaction, return to outer xact context */
1376 ReleaseCurrentSubTransaction();
1377 MemoryContextSwitchTo(oldcontext);
1378 CurrentResourceOwner = oldowner;
1380 * AtEOSubXact_SPI() should not have popped any SPI context,
1381 * but just in case it did, make sure we remain connected.
1383 SPI_restore_connection();
1389 /* Save error info */
1390 MemoryContextSwitchTo(oldcontext);
1391 edata = CopyErrorData();
1394 /* Abort the inner transaction */
1395 RollbackAndReleaseCurrentSubTransaction();
1396 MemoryContextSwitchTo(oldcontext);
1397 CurrentResourceOwner = oldowner;
1400 * If AtEOSubXact_SPI() popped any SPI context of the subxact,
1401 * it will have left us in a disconnected state. We need this
1402 * hack to return to connected state.
1404 SPI_restore_connection();
1406 /* Punt the error to Perl */
1407 croak("%s", edata->message);
1409 /* Can't get here, but keep compiler quiet */
1419 plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
1426 hv_store(result, "status", strlen("status"),
1427 newSVpv((char *) SPI_result_code_string(status), 0), 0);
1428 hv_store(result, "processed", strlen("processed"),
1429 newSViv(processed), 0);
1431 if (status == SPI_OK_SELECT)
1438 for (i = 0; i < processed; i++)
1440 row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
1443 hv_store(result, "rows", strlen("rows"),
1444 newRV_noinc((SV *) rows), 0);
1447 SPI_freetuptable(tuptable);
1454 plperl_return_next(SV *sv)
1456 plperl_proc_desc *prodesc = plperl_current_prodesc;
1457 FunctionCallInfo fcinfo = prodesc->caller_info;
1458 ReturnSetInfo *rsi = (ReturnSetInfo *)fcinfo->resultinfo;
1466 if (!prodesc->fn_retisset)
1469 (errcode(ERRCODE_SYNTAX_ERROR),
1470 errmsg("cannot use return_next in a non-SETOF function")));
1473 if (prodesc->fn_retistuple &&
1474 !(SvOK(sv) && SvTYPE(sv) == SVt_RV && SvTYPE(SvRV(sv)) == SVt_PVHV))
1477 (errcode(ERRCODE_DATATYPE_MISMATCH),
1478 errmsg("setof-composite-returning Perl function "
1479 "must call return_next with reference to hash")));
1482 cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
1484 if (!prodesc->tuple_store)
1485 prodesc->tuple_store = tuplestore_begin_heap(true, false, work_mem);
1487 if (prodesc->fn_retistuple)
1489 TypeFuncClass rettype;
1490 AttInMetadata *attinmeta;
1492 rettype = get_call_result_type(fcinfo, NULL, &tupdesc);
1493 tupdesc = CreateTupleDescCopy(tupdesc);
1494 attinmeta = TupleDescGetAttInMetadata(tupdesc);
1495 tuple = plperl_build_tuple_result((HV *)SvRV(sv), attinmeta);
1502 tupdesc = CreateTupleDescCopy(rsi->expectedDesc);
1504 if (SvOK(sv) && SvTYPE(sv) != SVt_NULL)
1506 char *val = SvPV(sv, PL_na);
1507 ret = FunctionCall3(&prodesc->result_in_func,
1508 PointerGetDatum(val),
1509 ObjectIdGetDatum(prodesc->result_typioparam),
1518 tuple = heap_form_tuple(tupdesc, &ret, &isNull);
1521 if (!prodesc->tuple_desc)
1522 prodesc->tuple_desc = tupdesc;
1524 tuplestore_puttuple(prodesc->tuple_store, tuple);
1525 heap_freetuple(tuple);
1526 MemoryContextSwitchTo(cxt);