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 Weick.
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 * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.11 2000/06/05 07:29:11 tgl Exp $
38 **********************************************************************/
50 /* postgreSQL stuff */
51 #include "executor/spi.h"
52 #include "commands/trigger.h"
53 #include "utils/elog.h"
55 #include "access/heapam.h"
57 #include "tcop/tcopprot.h"
58 #include "utils/syscache.h"
59 #include "catalog/pg_proc.h"
60 #include "catalog/pg_type.h"
66 * both posgreSQL and perl try to do 'the right thing'
67 * and provide union semun if the platform doesn't define
68 * it in a system header.
69 * psql uses HAVE_UNION_SEMUN
70 * perl uses HAS_UNION_SEMUN
71 * together, they cause compile errors.
72 * If we need it, the psql headers above will provide it.
73 * So we tell perl that we have it.
75 #ifndef HAS_UNION_SEMUN
76 #define HAS_UNION_SEMUN
82 /**********************************************************************
83 * The information we cache about loaded procedures
84 **********************************************************************/
85 typedef struct plperl_proc_desc
88 FmgrInfo result_in_func;
92 FmgrInfo arg_out_func[FUNC_MAX_ARGS];
93 Oid arg_out_elem[FUNC_MAX_ARGS];
94 int arg_out_len[FUNC_MAX_ARGS];
95 int arg_is_rel[FUNC_MAX_ARGS];
100 /**********************************************************************
101 * The information we cache about prepared and saved plans
102 **********************************************************************/
103 typedef struct plperl_query_desc
109 FmgrInfo *arginfuncs;
116 /**********************************************************************
118 **********************************************************************/
119 static int plperl_firstcall = 1;
120 static int plperl_call_level = 0;
121 static int plperl_restart_in_progress = 0;
122 static PerlInterpreter *plperl_safe_interp = NULL;
123 static HV *plperl_proc_hash = NULL;
125 #if REALLYHAVEITONTHEBALL
126 static Tcl_HashTable *plperl_query_hash = NULL;
130 /**********************************************************************
131 * Forward declarations
132 **********************************************************************/
133 static void plperl_init_all(void);
134 static void plperl_init_safe_interp(void);
136 Datum plperl_call_handler(PG_FUNCTION_ARGS);
138 static Datum plperl_func_handler(PG_FUNCTION_ARGS);
140 static SV *plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
141 static void plperl_init_shared_libs(void);
143 #ifdef REALLYHAVEITONTHEBALL
144 static HeapTuple plperl_trigger_handler(PG_FUNCTION_ARGS);
146 static int plperl_elog(ClientData cdata, Tcl_Interp *interp,
147 int argc, char *argv[]);
148 static int plperl_quote(ClientData cdata, Tcl_Interp *interp,
149 int argc, char *argv[]);
151 static int plperl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
152 int argc, char *argv[]);
153 static int plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
154 int argc, char *argv[]);
155 static int plperl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
156 int argc, char *argv[]);
158 static void plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
159 int tupno, HeapTuple tuple, TupleDesc tupdesc);
164 /**********************************************************************
165 * plperl_init_all() - Initialize all
166 **********************************************************************/
168 plperl_init_all(void)
171 /************************************************************
172 * Do initialization only once
173 ************************************************************/
174 if (!plperl_firstcall)
178 /************************************************************
179 * Destroy the existing safe interpreter
180 ************************************************************/
181 if (plperl_safe_interp != NULL)
183 perl_destruct(plperl_safe_interp);
184 perl_free(plperl_safe_interp);
185 plperl_safe_interp = NULL;
188 /************************************************************
189 * Free the proc hash table
190 ************************************************************/
191 if (plperl_proc_hash != NULL)
193 hv_undef(plperl_proc_hash);
194 SvREFCNT_dec((SV *) plperl_proc_hash);
195 plperl_proc_hash = NULL;
198 /************************************************************
199 * Free the prepared query hash table
200 ************************************************************/
203 * if (plperl_query_hash != NULL) { }
206 /************************************************************
207 * Now recreate a new safe interpreter
208 ************************************************************/
209 plperl_init_safe_interp();
211 plperl_firstcall = 0;
216 /**********************************************************************
217 * plperl_init_safe_interp() - Create the safe Perl interpreter
218 **********************************************************************/
220 plperl_init_safe_interp(void)
223 char *embedding[3] = {
225 /* no commas between the next 4 please. They are supposed to be one string
227 "require Safe; SPI::bootstrap();"
228 "sub ::mksafefunc { my $x = new Safe; $x->permit_only(':default');"
229 "$x->share(qw[&elog &DEBUG &NOTICE &NOIND &ERROR]);"
230 " return $x->reval(qq[sub { $_[0] }]); }"
233 plperl_safe_interp = perl_alloc();
234 if (!plperl_safe_interp)
235 elog(ERROR, "plperl_init_safe_interp(): could not allocate perl interpreter");
237 perl_construct(plperl_safe_interp);
238 perl_parse(plperl_safe_interp, plperl_init_shared_libs, 3, embedding, NULL);
239 perl_run(plperl_safe_interp);
243 /************************************************************
244 * Initialize the proc and query hash tables
245 ************************* ***********************************/
246 plperl_proc_hash = newHV();
252 /**********************************************************************
253 * plperl_call_handler - This is the only visible function
254 * of the PL interpreter. The PostgreSQL
255 * function manager and trigger manager
256 * call this function for execution of
258 **********************************************************************/
260 /* keep non-static */
262 plperl_call_handler(PG_FUNCTION_ARGS)
266 /************************************************************
267 * Initialize interpreters on first call
268 ************************************************************/
269 if (plperl_firstcall)
272 /************************************************************
273 * Connect to SPI manager
274 ************************************************************/
275 if (SPI_connect() != SPI_OK_CONNECT)
276 elog(ERROR, "plperl: cannot connect to SPI manager");
277 /************************************************************
278 * Keep track about the nesting of Tcl-SPI-Tcl-... calls
279 ************************************************************/
282 /************************************************************
283 * Determine if called as function or trigger and
284 * call appropriate subhandler
285 ************************************************************/
286 if (CALLED_AS_TRIGGER(fcinfo))
288 elog(ERROR, "plperl: can't use perl in triggers yet.");
291 * retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
293 /* make the compiler happy */
297 retval = plperl_func_handler(fcinfo);
305 /**********************************************************************
306 * plperl_create_sub() - calls the perl interpreter to
307 * create the anonymous subroutine whose text is in the SV.
308 * Returns the SV containing the RV to the closure.
309 **********************************************************************/
312 plperl_create_sub(char * s)
322 XPUSHs(sv_2mortal(newSVpv(s,0)));
324 count = perl_call_pv("mksafefunc", G_SCALAR | G_EVAL | G_KEEPERR);
327 if (SvTRUE(GvSV(errgv)))
333 elog(ERROR, "creation of function failed : %s", SvPV(GvSV(errgv), na));
337 elog(ERROR, "creation of function failed - no return from mksafefunc");
341 * need to make a deep copy of the return. it comes off the stack as a
344 subref = newSVsv(POPs);
353 * subref is our responsibility because it is not mortal
355 SvREFCNT_dec(subref);
356 elog(ERROR, "plperl_create_sub: didn't get a code ref");
365 /**********************************************************************
366 * plperl_init_shared_libs() -
368 * We cannot use the DynaLoader directly to get at the Opcode
369 * module (used by Safe.pm). So, we link Opcode into ourselves
370 * and do the initialization behind perl's back.
372 **********************************************************************/
374 extern void boot_Opcode _((CV * cv));
375 extern void boot_SPI _((CV * cv));
378 plperl_init_shared_libs(void)
380 char *file = __FILE__;
382 newXS("Opcode::bootstrap", boot_Opcode, file);
383 newXS("SPI::bootstrap", boot_SPI, file);
386 /**********************************************************************
387 * plperl_call_perl_func() - calls a perl function through the RV
388 * stored in the prodesc structure. massages the input parms properly
389 **********************************************************************/
392 plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
405 for (i = 0; i < desc->nargs; i++)
407 if (desc->arg_is_rel[i])
409 TupleTableSlot *slot = (TupleTableSlot *) fcinfo->arg[i];
412 Assert(slot != NULL && ! fcinfo->argnull[i]);
414 * plperl_build_tuple_argument better return a mortal SV.
416 hashref = plperl_build_tuple_argument(slot->val,
417 slot->ttc_tupleDescriptor);
422 if (fcinfo->argnull[i])
424 XPUSHs(&PL_sv_undef);
430 tmp = DatumGetCString(FunctionCall3(&(desc->arg_out_func[i]),
432 ObjectIdGetDatum(desc->arg_out_elem[i]),
433 Int32GetDatum(desc->arg_out_len[i])));
434 XPUSHs(sv_2mortal(newSVpv(tmp, 0)));
440 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL | G_KEEPERR);
449 elog(ERROR, "plperl : didn't get a return item from function");
452 if (SvTRUE(GvSV(errgv)))
458 elog(ERROR, "plperl : error from function : %s", SvPV(GvSV(errgv), na));
461 retval = newSVsv(POPs);
473 /**********************************************************************
474 * plperl_func_handler() - Handler for regular function calls
475 **********************************************************************/
477 plperl_func_handler(PG_FUNCTION_ARGS)
480 char internal_proname[512];
482 plperl_proc_desc *prodesc;
485 sigjmp_buf save_restart;
487 /************************************************************
488 * Build our internal proc name from the functions Oid
489 ************************************************************/
490 sprintf(internal_proname, "__PLPerl_proc_%u", fcinfo->flinfo->fn_oid);
491 proname_len = strlen(internal_proname);
493 /************************************************************
494 * Lookup the internal proc name in the hashtable
495 ************************************************************/
496 if (!hv_exists(plperl_proc_hash, internal_proname, proname_len))
498 /************************************************************
499 * If we haven't found it in the hashtable, we analyze
500 * the functions arguments and returntype and store
501 * the in-/out-functions in the prodesc block and create
502 * a new hashtable entry for it.
504 * Then we load the procedure into the safe interpreter.
505 ************************************************************/
508 Form_pg_proc procStruct;
509 Form_pg_type typeStruct;
512 /************************************************************
513 * Allocate a new procedure description block
514 ************************************************************/
515 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
516 prodesc->proname = malloc(strlen(internal_proname) + 1);
517 strcpy(prodesc->proname, internal_proname);
519 /************************************************************
520 * Lookup the pg_proc tuple by Oid
521 ************************************************************/
522 procTup = SearchSysCacheTuple(PROCOID,
523 ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
525 if (!HeapTupleIsValid(procTup))
527 free(prodesc->proname);
529 elog(ERROR, "plperl: cache lookup for proc %u failed",
530 fcinfo->flinfo->fn_oid);
532 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
534 /************************************************************
535 * Get the required information for input conversion of the
537 ************************************************************/
538 typeTup = SearchSysCacheTuple(TYPEOID,
539 ObjectIdGetDatum(procStruct->prorettype),
541 if (!HeapTupleIsValid(typeTup))
543 free(prodesc->proname);
545 elog(ERROR, "plperl: cache lookup for return type %u failed",
546 procStruct->prorettype);
548 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
550 if (typeStruct->typrelid != InvalidOid)
552 free(prodesc->proname);
554 elog(ERROR, "plperl: return types of tuples not supported yet");
557 fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
558 prodesc->result_in_elem = (Oid) (typeStruct->typelem);
559 prodesc->result_in_len = typeStruct->typlen;
561 /************************************************************
562 * Get the required information for output conversion
563 * of all procedure arguments
564 ************************************************************/
565 prodesc->nargs = procStruct->pronargs;
566 for (i = 0; i < prodesc->nargs; i++)
568 typeTup = SearchSysCacheTuple(TYPEOID,
569 ObjectIdGetDatum(procStruct->proargtypes[i]),
571 if (!HeapTupleIsValid(typeTup))
573 free(prodesc->proname);
575 elog(ERROR, "plperl: cache lookup for argument type %u failed",
576 procStruct->proargtypes[i]);
578 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
580 if (typeStruct->typrelid != InvalidOid)
581 prodesc->arg_is_rel[i] = 1;
583 prodesc->arg_is_rel[i] = 0;
585 fmgr_info(typeStruct->typoutput, &(prodesc->arg_out_func[i]));
586 prodesc->arg_out_elem[i] = (Oid) (typeStruct->typelem);
587 prodesc->arg_out_len[i] = typeStruct->typlen;
591 /************************************************************
592 * create the text of the anonymous subroutine.
593 * we do not use a named subroutine so that we can call directly
594 * through the reference.
596 ************************************************************/
597 proc_source = textout(&(procStruct->prosrc));
600 /************************************************************
601 * Create the procedure in the interpreter
602 ************************************************************/
603 prodesc->reference = plperl_create_sub(proc_source);
605 if (!prodesc->reference)
607 free(prodesc->proname);
609 elog(ERROR, "plperl: cannot create internal procedure %s",
613 /************************************************************
614 * Add the proc description block to the hashtable
615 ************************************************************/
616 hv_store(plperl_proc_hash, internal_proname, proname_len,
617 newSViv((IV) prodesc), 0);
621 /************************************************************
622 * Found the proc description block in the hashtable
623 ************************************************************/
624 prodesc = (plperl_proc_desc *) SvIV(*hv_fetch(plperl_proc_hash,
625 internal_proname, proname_len, 0));
629 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
631 if (sigsetjmp(Warn_restart, 1) != 0)
633 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
634 plperl_restart_in_progress = 1;
635 if (--plperl_call_level == 0)
636 plperl_restart_in_progress = 0;
637 siglongjmp(Warn_restart, 1);
641 /************************************************************
642 * Call the Perl function
643 ************************************************************/
644 perlret = plperl_call_perl_func(prodesc, fcinfo);
646 /************************************************************
647 * Disconnect from SPI manager and then create the return
648 * values datum (if the input function does a palloc for it
649 * this must not be allocated in the SPI memory context
650 * because SPI_finish would free it).
651 ************************************************************/
652 if (SPI_finish() != SPI_OK_FINISH)
653 elog(ERROR, "plperl: SPI_finish() failed");
655 /* XXX is this the approved way to check for an undef result? */
656 if (perlret == &PL_sv_undef)
659 fcinfo->isnull = true;
663 retval = FunctionCall3(&prodesc->result_in_func,
664 PointerGetDatum(SvPV(perlret, na)),
665 ObjectIdGetDatum(prodesc->result_in_elem),
666 Int32GetDatum(prodesc->result_in_len));
669 SvREFCNT_dec(perlret);
671 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
672 if (plperl_restart_in_progress)
674 if (--plperl_call_level == 0)
675 plperl_restart_in_progress = 0;
676 siglongjmp(Warn_restart, 1);
683 #ifdef REALLYHAVEITONTHEBALL
684 /**********************************************************************
685 * plperl_trigger_handler() - Handler for trigger calls
686 **********************************************************************/
688 plperl_trigger_handler(PG_FUNCTION_ARGS)
690 TriggerData *trigdata = (TriggerData *) fcinfo->context;
691 char internal_proname[512];
693 Tcl_HashEntry *hashent;
695 plperl_proc_desc *prodesc;
699 Tcl_DString tcl_trigtup;
700 Tcl_DString tcl_newtup;
711 sigjmp_buf save_restart;
713 /************************************************************
714 * Build our internal proc name from the functions Oid
715 ************************************************************/
716 sprintf(internal_proname, "__PLPerl_proc_%u", fcinfo->flinfo->fn_oid);
718 /************************************************************
719 * Lookup the internal proc name in the hashtable
720 ************************************************************/
721 hashent = Tcl_FindHashEntry(plperl_proc_hash, internal_proname);
724 /************************************************************
725 * If we haven't found it in the hashtable,
726 * we load the procedure into the safe interpreter.
727 ************************************************************/
728 Tcl_DString proc_internal_def;
729 Tcl_DString proc_internal_body;
731 Form_pg_proc procStruct;
734 /************************************************************
735 * Allocate a new procedure description block
736 ************************************************************/
737 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
738 memset(prodesc, 0, sizeof(plperl_proc_desc));
739 prodesc->proname = malloc(strlen(internal_proname) + 1);
740 strcpy(prodesc->proname, internal_proname);
742 /************************************************************
743 * Lookup the pg_proc tuple by Oid
744 ************************************************************/
745 procTup = SearchSysCacheTuple(PROCOID,
746 ObjectIdGetDatum(fcinfo->flinfo->fn_oid),
748 if (!HeapTupleIsValid(procTup))
750 free(prodesc->proname);
752 elog(ERROR, "plperl: cache lookup for proc %u failed",
753 fcinfo->flinfo->fn_oid);
755 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
757 /************************************************************
758 * Create the tcl command to define the internal
760 ************************************************************/
761 Tcl_DStringInit(&proc_internal_def);
762 Tcl_DStringInit(&proc_internal_body);
763 Tcl_DStringAppendElement(&proc_internal_def, "proc");
764 Tcl_DStringAppendElement(&proc_internal_def, internal_proname);
765 Tcl_DStringAppendElement(&proc_internal_def,
766 "TG_name TG_relid TG_relatts TG_when TG_level TG_op __PLTcl_Tup_NEW __PLTcl_Tup_OLD args");
768 /************************************************************
769 * prefix procedure body with
770 * upvar #0 <internal_procname> GD
771 * and with appropriate setting of NEW, OLD,
772 * and the arguments as numerical variables.
773 ************************************************************/
774 Tcl_DStringAppend(&proc_internal_body, "upvar #0 ", -1);
775 Tcl_DStringAppend(&proc_internal_body, internal_proname, -1);
776 Tcl_DStringAppend(&proc_internal_body, " GD\n", -1);
778 Tcl_DStringAppend(&proc_internal_body,
779 "array set NEW $__PLTcl_Tup_NEW\n", -1);
780 Tcl_DStringAppend(&proc_internal_body,
781 "array set OLD $__PLTcl_Tup_OLD\n", -1);
783 Tcl_DStringAppend(&proc_internal_body,
786 "foreach v $args {\n"
790 "unset i v\n\n", -1);
792 proc_source = textout(&(procStruct->prosrc));
793 Tcl_DStringAppend(&proc_internal_body, proc_source, -1);
795 Tcl_DStringAppendElement(&proc_internal_def,
796 Tcl_DStringValue(&proc_internal_body));
797 Tcl_DStringFree(&proc_internal_body);
799 /************************************************************
800 * Create the procedure in the safe interpreter
801 ************************************************************/
802 tcl_rc = Tcl_GlobalEval(plperl_safe_interp,
803 Tcl_DStringValue(&proc_internal_def));
804 Tcl_DStringFree(&proc_internal_def);
805 if (tcl_rc != TCL_OK)
807 free(prodesc->proname);
809 elog(ERROR, "plperl: cannot create internal procedure %s - %s",
810 internal_proname, plperl_safe_interp->result);
813 /************************************************************
814 * Add the proc description block to the hashtable
815 ************************************************************/
816 hashent = Tcl_CreateHashEntry(plperl_proc_hash,
817 prodesc->proname, &hashnew);
818 Tcl_SetHashValue(hashent, (ClientData) prodesc);
822 /************************************************************
823 * Found the proc description block in the hashtable
824 ************************************************************/
825 prodesc = (plperl_proc_desc *) Tcl_GetHashValue(hashent);
828 tupdesc = trigdata->tg_relation->rd_att;
830 /************************************************************
831 * Create the tcl command to call the internal
832 * proc in the safe interpreter
833 ************************************************************/
834 Tcl_DStringInit(&tcl_cmd);
835 Tcl_DStringInit(&tcl_trigtup);
836 Tcl_DStringInit(&tcl_newtup);
838 /************************************************************
839 * We call external functions below - care for elog(ERROR)
840 ************************************************************/
841 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
842 if (sigsetjmp(Warn_restart, 1) != 0)
844 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
845 Tcl_DStringFree(&tcl_cmd);
846 Tcl_DStringFree(&tcl_trigtup);
847 Tcl_DStringFree(&tcl_newtup);
848 plperl_restart_in_progress = 1;
849 if (--plperl_call_level == 0)
850 plperl_restart_in_progress = 0;
851 siglongjmp(Warn_restart, 1);
854 /* The procedure name */
855 Tcl_DStringAppendElement(&tcl_cmd, internal_proname);
857 /* The trigger name for argument TG_name */
858 Tcl_DStringAppendElement(&tcl_cmd, trigdata->tg_trigger->tgname);
860 /* The oid of the trigger relation for argument TG_relid */
861 stroid = DatumGetCString(DirectFunctionCall1(oidout,
862 ObjectIdGetDatum(trigdata->tg_relation->rd_id)));
863 Tcl_DStringAppendElement(&tcl_cmd, stroid);
866 /* A list of attribute names for argument TG_relatts */
867 Tcl_DStringAppendElement(&tcl_trigtup, "");
868 for (i = 0; i < tupdesc->natts; i++)
869 Tcl_DStringAppendElement(&tcl_trigtup, tupdesc->attrs[i]->attname.data);
870 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
871 Tcl_DStringFree(&tcl_trigtup);
872 Tcl_DStringInit(&tcl_trigtup);
874 /* The when part of the event for TG_when */
875 if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
876 Tcl_DStringAppendElement(&tcl_cmd, "BEFORE");
877 else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
878 Tcl_DStringAppendElement(&tcl_cmd, "AFTER");
880 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
882 /* The level part of the event for TG_level */
883 if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
884 Tcl_DStringAppendElement(&tcl_cmd, "ROW");
885 else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
886 Tcl_DStringAppendElement(&tcl_cmd, "STATEMENT");
888 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
890 /* Build the data list for the trigtuple */
891 plperl_build_tuple_argument(trigdata->tg_trigtuple,
892 tupdesc, &tcl_trigtup);
895 * Now the command part of the event for TG_op and data for NEW and
898 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
900 Tcl_DStringAppendElement(&tcl_cmd, "INSERT");
902 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
903 Tcl_DStringAppendElement(&tcl_cmd, "");
905 rettup = trigdata->tg_trigtuple;
907 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
909 Tcl_DStringAppendElement(&tcl_cmd, "DELETE");
911 Tcl_DStringAppendElement(&tcl_cmd, "");
912 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
914 rettup = trigdata->tg_trigtuple;
916 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
918 Tcl_DStringAppendElement(&tcl_cmd, "UPDATE");
920 plperl_build_tuple_argument(trigdata->tg_newtuple,
921 tupdesc, &tcl_newtup);
923 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_newtup));
924 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
926 rettup = trigdata->tg_newtuple;
930 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
932 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
933 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
935 rettup = trigdata->tg_trigtuple;
938 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
939 Tcl_DStringFree(&tcl_trigtup);
940 Tcl_DStringFree(&tcl_newtup);
942 /************************************************************
943 * Finally append the arguments from CREATE TRIGGER
944 ************************************************************/
945 for (i = 0; i < trigdata->tg_trigger->tgnargs; i++)
946 Tcl_DStringAppendElement(&tcl_cmd, trigdata->tg_trigger->tgargs[i]);
948 /************************************************************
949 * Call the Tcl function
950 ************************************************************/
951 tcl_rc = Tcl_GlobalEval(plperl_safe_interp, Tcl_DStringValue(&tcl_cmd));
952 Tcl_DStringFree(&tcl_cmd);
954 /************************************************************
955 * Check the return code from Tcl and handle
956 * our special restart mechanism to get rid
957 * of all nested call levels on transaction
959 ************************************************************/
960 if (tcl_rc == TCL_ERROR || plperl_restart_in_progress)
962 if (!plperl_restart_in_progress)
964 plperl_restart_in_progress = 1;
965 if (--plperl_call_level == 0)
966 plperl_restart_in_progress = 0;
967 elog(ERROR, "plperl: %s", plperl_safe_interp->result);
969 if (--plperl_call_level == 0)
970 plperl_restart_in_progress = 0;
971 siglongjmp(Warn_restart, 1);
980 elog(ERROR, "plperl: unsupported TCL return code %d", tcl_rc);
983 /************************************************************
984 * The return value from the procedure might be one of
985 * the magic strings OK or SKIP or a list from array get
986 ************************************************************/
987 if (SPI_finish() != SPI_OK_FINISH)
988 elog(ERROR, "plperl: SPI_finish() failed");
990 if (strcmp(plperl_safe_interp->result, "OK") == 0)
992 if (strcmp(plperl_safe_interp->result, "SKIP") == 0)
994 return (HeapTuple) NULL;;
997 /************************************************************
998 * Convert the result value from the safe interpreter
999 * and setup structures for SPI_modifytuple();
1000 ************************************************************/
1001 if (Tcl_SplitList(plperl_safe_interp, plperl_safe_interp->result,
1002 &ret_numvals, &ret_values) != TCL_OK)
1004 elog(NOTICE, "plperl: cannot split return value from trigger");
1005 elog(ERROR, "plperl: %s", plperl_safe_interp->result);
1008 if (ret_numvals % 2 != 0)
1011 elog(ERROR, "plperl: invalid return list from trigger - must have even # of elements");
1014 modattrs = (int *) palloc(tupdesc->natts * sizeof(int));
1015 modvalues = (Datum *) palloc(tupdesc->natts * sizeof(Datum));
1016 for (i = 0; i < tupdesc->natts; i++)
1018 modattrs[i] = i + 1;
1019 modvalues[i] = (Datum) NULL;
1022 modnulls = palloc(tupdesc->natts + 1);
1023 memset(modnulls, 'n', tupdesc->natts);
1024 modnulls[tupdesc->natts] = '\0';
1026 /************************************************************
1027 * Care for possible elog(ERROR)'s below
1028 ************************************************************/
1029 if (sigsetjmp(Warn_restart, 1) != 0)
1031 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1033 plperl_restart_in_progress = 1;
1034 if (--plperl_call_level == 0)
1035 plperl_restart_in_progress = 0;
1036 siglongjmp(Warn_restart, 1);
1040 while (i < ret_numvals)
1048 /************************************************************
1049 * Ignore pseudo elements with a dot name
1050 ************************************************************/
1051 if (*(ret_values[i]) == '.')
1057 /************************************************************
1058 * Get the attribute number
1059 ************************************************************/
1060 attnum = SPI_fnumber(tupdesc, ret_values[i++]);
1061 if (attnum == SPI_ERROR_NOATTRIBUTE)
1062 elog(ERROR, "plperl: invalid attribute '%s'", ret_values[--i]);
1064 /************************************************************
1065 * Lookup the attribute type in the syscache
1066 * for the input function
1067 ************************************************************/
1068 typeTup = SearchSysCacheTuple(TYPEOID,
1069 ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid),
1071 if (!HeapTupleIsValid(typeTup))
1073 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
1075 tupdesc->attrs[attnum - 1]->atttypid);
1077 typinput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typinput);
1078 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
1080 /************************************************************
1081 * Set the attribute to NOT NULL and convert the contents
1082 ************************************************************/
1083 modnulls[attnum - 1] = ' ';
1084 fmgr_info(typinput, &finfo);
1085 modvalues[attnum - 1] =
1086 FunctionCall3(&finfo,
1087 CStringGetDatum(ret_values[i++]),
1088 ObjectIdGetDatum(typelem),
1089 Int32GetDatum(tupdesc->attrs[attnum-1]->atttypmod));
1093 rettup = SPI_modifytuple(trigdata->tg_relation, rettup, tupdesc->natts,
1094 modattrs, modvalues, modnulls);
1101 elog(ERROR, "plperl: SPI_modifytuple() failed - RC = %d\n", SPI_result);
1104 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1110 /**********************************************************************
1111 * plperl_elog() - elog() support for PLTcl
1112 **********************************************************************/
1114 plperl_elog(ClientData cdata, Tcl_Interp *interp,
1115 int argc, char *argv[])
1118 sigjmp_buf save_restart;
1120 /************************************************************
1121 * Suppress messages during the restart process
1122 ************************************************************/
1123 if (plperl_restart_in_progress)
1126 /************************************************************
1127 * Catch the restart longjmp and begin a controlled
1128 * return though all interpreter levels if it happens
1129 ************************************************************/
1130 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1131 if (sigsetjmp(Warn_restart, 1) != 0)
1133 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1134 plperl_restart_in_progress = 1;
1140 Tcl_SetResult(interp, "syntax error - 'elog level msg'",
1145 if (strcmp(argv[1], "NOTICE") == 0)
1147 else if (strcmp(argv[1], "WARN") == 0)
1149 else if (strcmp(argv[1], "ERROR") == 0)
1151 else if (strcmp(argv[1], "FATAL") == 0)
1153 else if (strcmp(argv[1], "DEBUG") == 0)
1155 else if (strcmp(argv[1], "NOIND") == 0)
1159 Tcl_AppendResult(interp, "Unknown elog level '", argv[1],
1161 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1165 /************************************************************
1166 * Call elog(), restore the original restart address
1167 * and return to the caller (if not catched)
1168 ************************************************************/
1169 elog(level, argv[2]);
1170 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1175 /**********************************************************************
1176 * plperl_quote() - quote literal strings that are to
1177 * be used in SPI_exec query strings
1178 **********************************************************************/
1180 plperl_quote(ClientData cdata, Tcl_Interp *interp,
1181 int argc, char *argv[])
1187 /************************************************************
1189 ************************************************************/
1192 Tcl_SetResult(interp, "syntax error - 'quote string'", TCL_VOLATILE);
1196 /************************************************************
1197 * Allocate space for the maximum the string can
1198 * grow to and initialize pointers
1199 ************************************************************/
1200 tmp = palloc(strlen(argv[1]) * 2 + 1);
1204 /************************************************************
1205 * Walk through string and double every quote and backslash
1206 ************************************************************/
1219 /************************************************************
1220 * Terminate the string and set it as result
1221 ************************************************************/
1223 Tcl_SetResult(interp, tmp, TCL_VOLATILE);
1229 /**********************************************************************
1230 * plperl_SPI_exec() - The builtin SPI_exec command
1231 * for the safe interpreter
1232 **********************************************************************/
1234 plperl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
1235 int argc, char *argv[])
1240 char *arrayname = NULL;
1246 TupleDesc tupdesc = NULL;
1247 sigjmp_buf save_restart;
1249 char *usage = "syntax error - 'SPI_exec "
1251 "?-array name? query ?loop body?";
1253 /************************************************************
1254 * Don't do anything if we are already in restart mode
1255 ************************************************************/
1256 if (plperl_restart_in_progress)
1259 /************************************************************
1260 * Check the call syntax and get the count option
1261 ************************************************************/
1264 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1271 if (strcmp(argv[i], "-array") == 0)
1275 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1278 arrayname = argv[i++];
1282 if (strcmp(argv[i], "-count") == 0)
1286 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1289 if (Tcl_GetInt(interp, argv[i++], &count) != TCL_OK)
1298 if (query_idx >= argc)
1300 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1304 /************************************************************
1305 * Prepare to start a controlled return through all
1306 * interpreter levels on transaction abort
1307 ************************************************************/
1308 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1309 if (sigsetjmp(Warn_restart, 1) != 0)
1311 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1312 plperl_restart_in_progress = 1;
1313 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1317 /************************************************************
1318 * Execute the query and handle return codes
1319 ************************************************************/
1320 spi_rc = SPI_exec(argv[query_idx], count);
1321 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1325 case SPI_OK_UTILITY:
1326 Tcl_SetResult(interp, "0", TCL_VOLATILE);
1329 case SPI_OK_SELINTO:
1333 sprintf(buf, "%d", SPI_processed);
1334 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1340 case SPI_ERROR_ARGUMENT:
1341 Tcl_SetResult(interp,
1342 "plperl: SPI_exec() failed - SPI_ERROR_ARGUMENT",
1346 case SPI_ERROR_UNCONNECTED:
1347 Tcl_SetResult(interp,
1348 "plperl: SPI_exec() failed - SPI_ERROR_UNCONNECTED",
1352 case SPI_ERROR_COPY:
1353 Tcl_SetResult(interp,
1354 "plperl: SPI_exec() failed - SPI_ERROR_COPY",
1358 case SPI_ERROR_CURSOR:
1359 Tcl_SetResult(interp,
1360 "plperl: SPI_exec() failed - SPI_ERROR_CURSOR",
1364 case SPI_ERROR_TRANSACTION:
1365 Tcl_SetResult(interp,
1366 "plperl: SPI_exec() failed - SPI_ERROR_TRANSACTION",
1370 case SPI_ERROR_OPUNKNOWN:
1371 Tcl_SetResult(interp,
1372 "plperl: SPI_exec() failed - SPI_ERROR_OPUNKNOWN",
1377 sprintf(buf, "%d", spi_rc);
1378 Tcl_AppendResult(interp, "plperl: SPI_exec() failed - ",
1379 "unknown RC ", buf, NULL);
1383 /************************************************************
1384 * Only SELECT queries fall through to here - remember the
1386 ************************************************************/
1388 ntuples = SPI_processed;
1391 tuples = SPI_tuptable->vals;
1392 tupdesc = SPI_tuptable->tupdesc;
1395 /************************************************************
1396 * Again prepare for elog(ERROR)
1397 ************************************************************/
1398 if (sigsetjmp(Warn_restart, 1) != 0)
1400 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1401 plperl_restart_in_progress = 1;
1402 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1406 /************************************************************
1407 * If there is no loop body given, just set the variables
1408 * from the first tuple (if any) and return the number of
1410 ************************************************************/
1411 if (argc == query_idx + 1)
1414 plperl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
1415 sprintf(buf, "%d", ntuples);
1416 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1417 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1421 /************************************************************
1422 * There is a loop body - process all tuples and evaluate
1424 ************************************************************/
1426 for (i = 0; i < ntuples; i++)
1428 plperl_set_tuple_values(interp, arrayname, i, tuples[i], tupdesc);
1430 loop_rc = Tcl_Eval(interp, argv[query_idx]);
1432 if (loop_rc == TCL_OK)
1434 if (loop_rc == TCL_CONTINUE)
1436 if (loop_rc == TCL_RETURN)
1438 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1441 if (loop_rc == TCL_BREAK)
1443 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1447 /************************************************************
1448 * Finally return the number of tuples
1449 ************************************************************/
1450 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1451 sprintf(buf, "%d", ntuples);
1452 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1457 /**********************************************************************
1458 * plperl_SPI_prepare() - Builtin support for prepared plans
1459 * The Tcl command SPI_prepare
1460 * allways saves the plan using
1461 * SPI_saveplan and returns a key for
1462 * access. There is no chance to prepare
1463 * and not save the plan currently.
1464 **********************************************************************/
1466 plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
1467 int argc, char *argv[])
1471 plperl_query_desc *qdesc;
1475 Tcl_HashEntry *hashent;
1477 sigjmp_buf save_restart;
1479 /************************************************************
1480 * Don't do anything if we are already in restart mode
1481 ************************************************************/
1482 if (plperl_restart_in_progress)
1485 /************************************************************
1486 * Check the call syntax
1487 ************************************************************/
1490 Tcl_SetResult(interp, "syntax error - 'SPI_prepare query argtypes'",
1495 /************************************************************
1496 * Split the argument type list
1497 ************************************************************/
1498 if (Tcl_SplitList(interp, argv[2], &nargs, &args) != TCL_OK)
1501 /************************************************************
1502 * Allocate the new querydesc structure
1503 ************************************************************/
1504 qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
1505 sprintf(qdesc->qname, "%lx", (long) qdesc);
1506 qdesc->nargs = nargs;
1507 qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
1508 qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
1509 qdesc->argtypelems = (Oid *) malloc(nargs * sizeof(Oid));
1510 qdesc->argvalues = (Datum *) malloc(nargs * sizeof(Datum));
1511 qdesc->arglen = (int *) malloc(nargs * sizeof(int));
1513 /************************************************************
1514 * Prepare to start a controlled return through all
1515 * interpreter levels on transaction abort
1516 ************************************************************/
1517 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1518 if (sigsetjmp(Warn_restart, 1) != 0)
1520 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1521 plperl_restart_in_progress = 1;
1522 free(qdesc->argtypes);
1523 free(qdesc->arginfuncs);
1524 free(qdesc->argtypelems);
1525 free(qdesc->argvalues);
1526 free(qdesc->arglen);
1532 /************************************************************
1533 * Lookup the argument types by name in the system cache
1534 * and remember the required information for input conversion
1535 ************************************************************/
1536 for (i = 0; i < nargs; i++)
1538 typeTup = SearchSysCacheTuple(TYPNAME,
1539 PointerGetDatum(args[i]),
1541 if (!HeapTupleIsValid(typeTup))
1542 elog(ERROR, "plperl: Cache lookup of type %s failed", args[i]);
1543 qdesc->argtypes[i] = typeTup->t_data->t_oid;
1544 fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
1545 &(qdesc->arginfuncs[i]));
1546 qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
1547 qdesc->argvalues[i] = (Datum) NULL;
1548 qdesc->arglen[i] = (int) (((Form_pg_type) GETSTRUCT(typeTup))->typlen);
1551 /************************************************************
1552 * Prepare the plan and check for errors
1553 ************************************************************/
1554 plan = SPI_prepare(argv[1], nargs, qdesc->argtypes);
1561 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1565 case SPI_ERROR_ARGUMENT:
1566 reason = "SPI_ERROR_ARGUMENT";
1569 case SPI_ERROR_UNCONNECTED:
1570 reason = "SPI_ERROR_UNCONNECTED";
1573 case SPI_ERROR_COPY:
1574 reason = "SPI_ERROR_COPY";
1577 case SPI_ERROR_CURSOR:
1578 reason = "SPI_ERROR_CURSOR";
1581 case SPI_ERROR_TRANSACTION:
1582 reason = "SPI_ERROR_TRANSACTION";
1585 case SPI_ERROR_OPUNKNOWN:
1586 reason = "SPI_ERROR_OPUNKNOWN";
1590 sprintf(buf, "unknown RC %d", SPI_result);
1596 elog(ERROR, "plperl: SPI_prepare() failed - %s", reason);
1599 /************************************************************
1601 ************************************************************/
1602 qdesc->plan = SPI_saveplan(plan);
1603 if (qdesc->plan == NULL)
1608 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1612 case SPI_ERROR_ARGUMENT:
1613 reason = "SPI_ERROR_ARGUMENT";
1616 case SPI_ERROR_UNCONNECTED:
1617 reason = "SPI_ERROR_UNCONNECTED";
1621 sprintf(buf, "unknown RC %d", SPI_result);
1627 elog(ERROR, "plperl: SPI_saveplan() failed - %s", reason);
1630 /************************************************************
1631 * Insert a hashtable entry for the plan and return
1632 * the key to the caller
1633 ************************************************************/
1634 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1635 hashent = Tcl_CreateHashEntry(plperl_query_hash, qdesc->qname, &hashnew);
1636 Tcl_SetHashValue(hashent, (ClientData) qdesc);
1638 Tcl_SetResult(interp, qdesc->qname, TCL_VOLATILE);
1643 /**********************************************************************
1644 * plperl_SPI_execp() - Execute a prepared plan
1645 **********************************************************************/
1647 plperl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
1648 int argc, char *argv[])
1655 Tcl_HashEntry *hashent;
1656 plperl_query_desc *qdesc;
1658 char *arrayname = NULL;
1661 static char **callargs = NULL;
1664 HeapTuple *tuples = NULL;
1665 TupleDesc tupdesc = NULL;
1666 sigjmp_buf save_restart;
1668 char *usage = "syntax error - 'SPI_execp "
1669 "?-nulls string? ?-count n? "
1670 "?-array name? query ?args? ?loop body?";
1672 /************************************************************
1673 * Tidy up from an earlier abort
1674 ************************************************************/
1675 if (callargs != NULL)
1681 /************************************************************
1682 * Don't do anything if we are already in restart mode
1683 ************************************************************/
1684 if (plperl_restart_in_progress)
1687 /************************************************************
1688 * Get the options and check syntax
1689 ************************************************************/
1693 if (strcmp(argv[i], "-array") == 0)
1697 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1700 arrayname = argv[i++];
1703 if (strcmp(argv[i], "-nulls") == 0)
1707 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1713 if (strcmp(argv[i], "-count") == 0)
1717 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1720 if (Tcl_GetInt(interp, argv[i++], &count) != TCL_OK)
1728 /************************************************************
1729 * Check minimum call arguments
1730 ************************************************************/
1733 Tcl_SetResult(interp, usage, TCL_VOLATILE);
1737 /************************************************************
1738 * Get the prepared plan descriptor by it's key
1739 ************************************************************/
1740 hashent = Tcl_FindHashEntry(plperl_query_hash, argv[i++]);
1741 if (hashent == NULL)
1743 Tcl_AppendResult(interp, "invalid queryid '", argv[--i], "'", NULL);
1746 qdesc = (plperl_query_desc *) Tcl_GetHashValue(hashent);
1748 /************************************************************
1749 * If a nulls string is given, check for correct length
1750 ************************************************************/
1753 if (strlen(nulls) != qdesc->nargs)
1755 Tcl_SetResult(interp,
1756 "length of nulls string doesn't match # of arguments",
1762 /************************************************************
1763 * If there was a argtype list on preparation, we need
1764 * an argument value list now
1765 ************************************************************/
1766 if (qdesc->nargs > 0)
1770 Tcl_SetResult(interp, "missing argument list", TCL_VOLATILE);
1774 /************************************************************
1775 * Split the argument values
1776 ************************************************************/
1777 if (Tcl_SplitList(interp, argv[i++], &callnargs, &callargs) != TCL_OK)
1780 /************************************************************
1781 * Check that the # of arguments matches
1782 ************************************************************/
1783 if (callnargs != qdesc->nargs)
1785 Tcl_SetResult(interp,
1786 "argument list length doesn't match # of arguments for query",
1788 if (callargs != NULL)
1796 /************************************************************
1797 * Prepare to start a controlled return through all
1798 * interpreter levels on transaction abort during the
1799 * parse of the arguments
1800 ************************************************************/
1801 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1802 if (sigsetjmp(Warn_restart, 1) != 0)
1804 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1805 for (j = 0; j < callnargs; j++)
1807 if (qdesc->arglen[j] < 0 &&
1808 qdesc->argvalues[j] != (Datum) NULL)
1810 pfree((char *) (qdesc->argvalues[j]));
1811 qdesc->argvalues[j] = (Datum) NULL;
1816 plperl_restart_in_progress = 1;
1817 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1821 /************************************************************
1822 * Setup the value array for the SPI_execp() using
1823 * the type specific input functions
1824 ************************************************************/
1825 for (j = 0; j < callnargs; j++)
1827 qdesc->argvalues[j] =
1828 FunctionCall3(&qdesc->arginfuncs[j],
1829 CStringGetDatum(callargs[j]),
1830 ObjectIdGetDatum(qdesc->argtypelems[j]),
1831 Int32GetDatum(qdesc->arglen[j]));
1834 /************************************************************
1835 * Free the splitted argument value list
1836 ************************************************************/
1837 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1844 /************************************************************
1845 * Remember the index of the last processed call
1846 * argument - a loop body for SELECT might follow
1847 ************************************************************/
1850 /************************************************************
1851 * Prepare to start a controlled return through all
1852 * interpreter levels on transaction abort
1853 ************************************************************/
1854 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1855 if (sigsetjmp(Warn_restart, 1) != 0)
1857 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1858 for (j = 0; j < callnargs; j++)
1860 if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)
1862 pfree((char *) (qdesc->argvalues[j]));
1863 qdesc->argvalues[j] = (Datum) NULL;
1866 plperl_restart_in_progress = 1;
1867 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1871 /************************************************************
1873 ************************************************************/
1874 spi_rc = SPI_execp(qdesc->plan, qdesc->argvalues, nulls, count);
1875 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1877 /************************************************************
1878 * For varlena data types, free the argument values
1879 ************************************************************/
1880 for (j = 0; j < callnargs; j++)
1882 if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)
1884 pfree((char *) (qdesc->argvalues[j]));
1885 qdesc->argvalues[j] = (Datum) NULL;
1889 /************************************************************
1890 * Check the return code from SPI_execp()
1891 ************************************************************/
1894 case SPI_OK_UTILITY:
1895 Tcl_SetResult(interp, "0", TCL_VOLATILE);
1898 case SPI_OK_SELINTO:
1902 sprintf(buf, "%d", SPI_processed);
1903 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1909 case SPI_ERROR_ARGUMENT:
1910 Tcl_SetResult(interp,
1911 "plperl: SPI_exec() failed - SPI_ERROR_ARGUMENT",
1915 case SPI_ERROR_UNCONNECTED:
1916 Tcl_SetResult(interp,
1917 "plperl: SPI_exec() failed - SPI_ERROR_UNCONNECTED",
1921 case SPI_ERROR_COPY:
1922 Tcl_SetResult(interp,
1923 "plperl: SPI_exec() failed - SPI_ERROR_COPY",
1927 case SPI_ERROR_CURSOR:
1928 Tcl_SetResult(interp,
1929 "plperl: SPI_exec() failed - SPI_ERROR_CURSOR",
1933 case SPI_ERROR_TRANSACTION:
1934 Tcl_SetResult(interp,
1935 "plperl: SPI_exec() failed - SPI_ERROR_TRANSACTION",
1939 case SPI_ERROR_OPUNKNOWN:
1940 Tcl_SetResult(interp,
1941 "plperl: SPI_exec() failed - SPI_ERROR_OPUNKNOWN",
1946 sprintf(buf, "%d", spi_rc);
1947 Tcl_AppendResult(interp, "plperl: SPI_exec() failed - ",
1948 "unknown RC ", buf, NULL);
1952 /************************************************************
1953 * Only SELECT queries fall through to here - remember the
1955 ************************************************************/
1957 ntuples = SPI_processed;
1960 tuples = SPI_tuptable->vals;
1961 tupdesc = SPI_tuptable->tupdesc;
1964 /************************************************************
1965 * Prepare to start a controlled return through all
1966 * interpreter levels on transaction abort during
1967 * the ouput conversions of the results
1968 ************************************************************/
1969 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1970 if (sigsetjmp(Warn_restart, 1) != 0)
1972 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1973 plperl_restart_in_progress = 1;
1974 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1978 /************************************************************
1979 * If there is no loop body given, just set the variables
1980 * from the first tuple (if any) and return the number of
1982 ************************************************************/
1983 if (loop_body >= argc)
1986 plperl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
1987 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1988 sprintf(buf, "%d", ntuples);
1989 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1993 /************************************************************
1994 * There is a loop body - process all tuples and evaluate
1996 ************************************************************/
1997 for (i = 0; i < ntuples; i++)
1999 plperl_set_tuple_values(interp, arrayname, i, tuples[i], tupdesc);
2001 loop_rc = Tcl_Eval(interp, argv[loop_body]);
2003 if (loop_rc == TCL_OK)
2005 if (loop_rc == TCL_CONTINUE)
2007 if (loop_rc == TCL_RETURN)
2009 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2012 if (loop_rc == TCL_BREAK)
2014 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2018 /************************************************************
2019 * Finally return the number of tuples
2020 ************************************************************/
2021 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2022 sprintf(buf, "%d", ntuples);
2023 Tcl_SetResult(interp, buf, TCL_VOLATILE);
2028 /**********************************************************************
2029 * plperl_set_tuple_values() - Set variables for all attributes
2031 **********************************************************************/
2033 plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
2034 int tupno, HeapTuple tuple, TupleDesc tupdesc)
2049 char *nullname = NULL;
2051 /************************************************************
2052 * Prepare pointers for Tcl_SetVar2() below and in array
2053 * mode set the .tupno element
2054 ************************************************************/
2055 if (arrayname == NULL)
2058 nameptr = &nullname;
2062 arrptr = &arrayname;
2064 sprintf(buf, "%d", tupno);
2065 Tcl_SetVar2(interp, arrayname, ".tupno", buf, 0);
2068 for (i = 0; i < tupdesc->natts; i++)
2070 /************************************************************
2071 * Get the attribute name
2072 ************************************************************/
2073 attname = tupdesc->attrs[i]->attname.data;
2075 /************************************************************
2076 * Get the attributes value
2077 ************************************************************/
2078 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
2080 /************************************************************
2081 * Lookup the attribute type in the syscache
2082 * for the output function
2083 ************************************************************/
2084 typeTup = SearchSysCacheTuple(TYPEOID,
2085 ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
2087 if (!HeapTupleIsValid(typeTup))
2089 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
2090 attname, tupdesc->attrs[i]->atttypid);
2093 typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput);
2094 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
2096 /************************************************************
2097 * If there is a value, set the variable
2100 * Hmmm - Null attributes will cause functions to
2101 * crash if they don't expect them - need something
2103 ************************************************************/
2104 if (!isnull && OidIsValid(typoutput))
2106 outputstr = DatumGetCString(OidFunctionCall3(typoutput,
2108 ObjectIdGetDatum(typelem),
2109 Int32GetDatum(tupdesc->attrs[i]->attlen)));
2110 Tcl_SetVar2(interp, *arrptr, *nameptr, outputstr, 0);
2114 Tcl_UnsetVar2(interp, *arrptr, *nameptr, 0);
2120 /**********************************************************************
2121 * plperl_build_tuple_argument() - Build a string for a ref to a hash
2122 * from all attributes of a given tuple
2123 **********************************************************************/
2125 plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
2138 output = sv_2mortal(newSVpv("{", 0));
2140 for (i = 0; i < tupdesc->natts; i++)
2142 /************************************************************
2143 * Get the attribute name
2144 ************************************************************/
2145 attname = tupdesc->attrs[i]->attname.data;
2147 /************************************************************
2148 * Get the attributes value
2149 ************************************************************/
2150 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
2152 /************************************************************
2153 * Lookup the attribute type in the syscache
2154 * for the output function
2155 ************************************************************/
2156 typeTup = SearchSysCacheTuple(TYPEOID,
2157 ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
2159 if (!HeapTupleIsValid(typeTup))
2161 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
2162 attname, tupdesc->attrs[i]->atttypid);
2165 typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput);
2166 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
2168 /************************************************************
2169 * If there is a value, append the attribute name and the
2170 * value to the list.
2171 * If it is null it will be set to undef.
2172 ************************************************************/
2173 if (!isnull && OidIsValid(typoutput))
2175 outputstr = DatumGetCString(OidFunctionCall3(typoutput,
2177 ObjectIdGetDatum(typelem),
2178 Int32GetDatum(tupdesc->attrs[i]->attlen)));
2179 sv_catpvf(output, "'%s' => '%s',", attname, outputstr);
2183 sv_catpvf(output, "'%s' => undef,", attname);
2185 sv_catpv(output, "}");
2186 output = perl_eval_pv(SvPV(output, na), TRUE);