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.
35 **********************************************************************/
47 /* postgreSQL stuff */
48 #include "executor/spi.h"
49 #include "commands/trigger.h"
50 #include "utils/elog.h"
52 #include "access/heapam.h"
54 #include "tcop/tcopprot.h"
55 #include "utils/syscache.h"
56 #include "catalog/pg_proc.h"
57 #include "catalog/pg_type.h"
63 * both posgreSQL and perl try to do 'the right thing'
64 * and provide union semun if the platform doesn't define
65 * it in a system header.
66 * psql uses HAVE_UNION_SEMUN
67 * perl uses HAS_UNION_SEMUN
68 * together, they cause compile errors.
69 * If we need it, the psql headers above will provide it.
70 * So we tell perl that we have it.
72 #ifndef HAS_UNION_SEMUN
73 #define HAS_UNION_SEMUN
79 /**********************************************************************
80 * The information we cache about loaded procedures
81 **********************************************************************/
82 typedef struct plperl_proc_desc
85 FmgrInfo result_in_func;
89 FmgrInfo arg_out_func[FUNC_MAX_ARGS];
90 Oid arg_out_elem[FUNC_MAX_ARGS];
91 int arg_out_len[FUNC_MAX_ARGS];
92 int arg_is_rel[FUNC_MAX_ARGS];
97 /**********************************************************************
98 * The information we cache about prepared and saved plans
99 **********************************************************************/
100 typedef struct plperl_query_desc
106 FmgrInfo *arginfuncs;
113 /**********************************************************************
115 **********************************************************************/
116 static int plperl_firstcall = 1;
117 static int plperl_call_level = 0;
118 static int plperl_restart_in_progress = 0;
119 static PerlInterpreter *plperl_safe_interp = NULL;
120 static HV *plperl_proc_hash = NULL;
122 #if REALLYHAVEITONTHEBALL
123 static Tcl_HashTable *plperl_query_hash = NULL;
127 /**********************************************************************
128 * Forward declarations
129 **********************************************************************/
130 static void plperl_init_all(void);
131 static void plperl_init_safe_interp(void);
133 Datum plperl_call_handler(FmgrInfo *proinfo,
134 FmgrValues *proargs, bool *isNull);
136 static Datum plperl_func_handler(FmgrInfo *proinfo,
137 FmgrValues *proargs, bool *isNull);
139 static SV *plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc);
140 static void plperl_init_shared_libs(void);
142 #ifdef REALLYHAVEITONTHEBALL
143 static HeapTuple plperl_trigger_handler(FmgrInfo *proinfo);
145 static int plperl_elog(ClientData cdata, Tcl_Interp *interp,
146 int argc, char *argv[]);
147 static int plperl_quote(ClientData cdata, Tcl_Interp *interp,
148 int argc, char *argv[]);
150 static int plperl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
151 int argc, char *argv[]);
152 static int plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
153 int argc, char *argv[]);
154 static int plperl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
155 int argc, char *argv[]);
157 static void plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
158 int tupno, HeapTuple tuple, TupleDesc tupdesc);
163 /**********************************************************************
164 * plperl_init_all() - Initialize all
165 **********************************************************************/
167 plperl_init_all(void)
170 /************************************************************
171 * Do initialization only once
172 ************************************************************/
173 if (!plperl_firstcall)
177 /************************************************************
178 * Destroy the existing safe interpreter
179 ************************************************************/
180 if (plperl_safe_interp != NULL)
182 perl_destruct(plperl_safe_interp);
183 perl_free(plperl_safe_interp);
184 plperl_safe_interp = NULL;
187 /************************************************************
188 * Free the proc hash table
189 ************************************************************/
190 if (plperl_proc_hash != NULL)
192 hv_undef(plperl_proc_hash);
193 SvREFCNT_dec((SV *) plperl_proc_hash);
194 plperl_proc_hash = NULL;
197 /************************************************************
198 * Free the prepared query hash table
199 ************************************************************/
202 * if (plperl_query_hash != NULL) { }
205 /************************************************************
206 * Now recreate a new safe interpreter
207 ************************************************************/
208 plperl_init_safe_interp();
210 plperl_firstcall = 0;
215 /**********************************************************************
216 * plperl_init_safe_interp() - Create the safe Perl interpreter
217 **********************************************************************/
219 plperl_init_safe_interp(void)
222 char *embedding[] = {"", "-e", "use DynaLoader; require Safe; SPI::bootstrap()", "0"};
224 plperl_safe_interp = perl_alloc();
225 if (!plperl_safe_interp)
226 elog(ERROR, "plperl_init_safe_interp(): could not allocate perl interpreter");
228 perl_construct(plperl_safe_interp);
229 perl_parse(plperl_safe_interp, plperl_init_shared_libs, 3, embedding, NULL);
230 perl_run(plperl_safe_interp);
234 /************************************************************
235 * Initialize the proc and query hash tables
236 ************************* ***********************************/
237 plperl_proc_hash = newHV();
243 /**********************************************************************
244 * plperl_call_handler - This is the only visible function
245 * of the PL interpreter. The PostgreSQL
246 * function manager and trigger manager
247 * call this function for execution of
249 **********************************************************************/
251 /* keep non-static */
253 plperl_call_handler(FmgrInfo *proinfo,
259 /************************************************************
260 * Initialize interpreters on first call
261 ************************************************************/
262 if (plperl_firstcall)
265 /************************************************************
266 * Connect to SPI manager
267 ************************************************************/
268 if (SPI_connect() != SPI_OK_CONNECT)
269 elog(ERROR, "plperl: cannot connect to SPI manager");
270 /************************************************************
271 * Keep track about the nesting of Tcl-SPI-Tcl-... calls
272 ************************************************************/
275 /************************************************************
276 * Determine if called as function or trigger and
277 * call appropriate subhandler
278 ************************************************************/
279 if (CurrentTriggerData == NULL)
280 retval = plperl_func_handler(proinfo, proargs, isNull);
283 elog(ERROR, "plperl: can't use perl in triggers yet.");
286 * retval = (Datum) plperl_trigger_handler(proinfo);
288 /* make the compiler happy */
298 /**********************************************************************
299 * plperl_create_sub() - calls the perl interpreter to
300 * create the anonymous subroutine whose text is in the SV.
301 * Returns the SV containing the RV to the closure.
302 **********************************************************************/
305 plperl_create_sub(SV * s)
314 perl_eval_sv(s, G_SCALAR | G_EVAL | G_KEEPERR);
317 if (SvTRUE(GvSV(errgv)))
323 elog(ERROR, "creation of function failed : %s", SvPV(GvSV(errgv), na));
327 * need to make a deep copy of the return. it comes off the stack as a
330 subref = newSVsv(POPs);
339 * subref is our responsibility because it is not mortal
341 SvREFCNT_dec(subref);
342 elog(ERROR, "plperl_create_sub: didn't get a code ref");
351 /**********************************************************************
352 * plperl_init_shared_libs() -
354 * We cannot use the DynaLoader directly to get at the Opcode
355 * module (used by Safe.pm). So, we link Opcode into ourselves
356 * and do the initialization behind perl's back.
358 **********************************************************************/
360 extern void boot_DynaLoader _((CV * cv));
361 extern void boot_Opcode _((CV * cv));
362 extern void boot_SPI _((CV * cv));
365 plperl_init_shared_libs(void)
367 char *file = __FILE__;
369 newXS("DynaLoader::bootstrap", boot_DynaLoader, file);
370 newXS("Opcode::bootstrap", boot_Opcode, file);
371 newXS("SPI::bootstrap", boot_SPI, file);
374 /**********************************************************************
375 * plperl_call_perl_func() - calls a perl function through the RV
376 * stored in the prodesc structure. massages the input parms properly
377 **********************************************************************/
380 plperl_call_perl_func(plperl_proc_desc * desc, FmgrValues *pargs)
393 for (i = 0; i < desc->nargs; i++)
395 if (desc->arg_is_rel[i])
399 * plperl_build_tuple_argument better return a mortal SV.
401 SV *hashref = plperl_build_tuple_argument(
402 ((TupleTableSlot *) (pargs->data[i]))->val,
403 ((TupleTableSlot *) (pargs->data[i]))->ttc_tupleDescriptor);
409 char *tmp = (*fmgr_faddr(&(desc->arg_out_func[i])))
411 desc->arg_out_elem[i],
412 desc->arg_out_len[i]);
414 XPUSHs(sv_2mortal(newSVpv(tmp, 0)));
419 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL | G_KEEPERR);
428 elog(ERROR, "plperl : didn't get a return item from function");
431 if (SvTRUE(GvSV(errgv)))
437 elog(ERROR, "plperl : error from function : %s", SvPV(GvSV(errgv), na));
440 retval = newSVsv(POPs);
452 /**********************************************************************
453 * plperl_func_handler() - Handler for regular function calls
454 **********************************************************************/
456 plperl_func_handler(FmgrInfo *proinfo,
461 char internal_proname[512];
464 plperl_proc_desc *prodesc;
467 sigjmp_buf save_restart;
469 /************************************************************
470 * Build our internal proc name from the functions Oid
471 ************************************************************/
472 stroid = oidout(proinfo->fn_oid);
473 strcpy(internal_proname, "__PLperl_proc_");
474 strcat(internal_proname, stroid);
476 proname_len = strlen(internal_proname);
478 /************************************************************
479 * Lookup the internal proc name in the hashtable
480 ************************************************************/
481 if (!hv_exists(plperl_proc_hash, internal_proname, proname_len))
483 /************************************************************
484 * If we haven't found it in the hashtable, we analyze
485 * the functions arguments and returntype and store
486 * the in-/out-functions in the prodesc block and create
487 * a new hashtable entry for it.
489 * Then we load the procedure into the safe interpreter.
490 ************************************************************/
493 Form_pg_proc procStruct;
494 Form_pg_type typeStruct;
495 SV *proc_internal_def;
496 char proc_internal_args[4096];
499 /************************************************************
500 * Allocate a new procedure description block
501 ************************************************************/
502 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
503 prodesc->proname = malloc(strlen(internal_proname) + 1);
504 strcpy(prodesc->proname, internal_proname);
506 /************************************************************
507 * Lookup the pg_proc tuple by Oid
508 ************************************************************/
509 procTup = SearchSysCacheTuple(PROCOID,
510 ObjectIdGetDatum(proinfo->fn_oid),
512 if (!HeapTupleIsValid(procTup))
514 free(prodesc->proname);
516 elog(ERROR, "plperl: cache lookup for proc %u failed",
519 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
521 /************************************************************
522 * Get the required information for input conversion of the
524 ************************************************************/
525 typeTup = SearchSysCacheTuple(TYPEOID,
526 ObjectIdGetDatum(procStruct->prorettype),
528 if (!HeapTupleIsValid(typeTup))
530 free(prodesc->proname);
532 elog(ERROR, "plperl: cache lookup for return type %u failed",
533 procStruct->prorettype);
535 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
537 if (typeStruct->typrelid != InvalidOid)
539 free(prodesc->proname);
541 elog(ERROR, "plperl: return types of tuples not supported yet");
544 fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
545 prodesc->result_in_elem = (Oid) (typeStruct->typelem);
546 prodesc->result_in_len = typeStruct->typlen;
548 /************************************************************
549 * Get the required information for output conversion
550 * of all procedure arguments
551 ************************************************************/
552 prodesc->nargs = proinfo->fn_nargs;
553 proc_internal_args[0] = '\0';
554 for (i = 0; i < proinfo->fn_nargs; i++)
556 typeTup = SearchSysCacheTuple(TYPEOID,
557 ObjectIdGetDatum(procStruct->proargtypes[i]),
559 if (!HeapTupleIsValid(typeTup))
561 free(prodesc->proname);
563 elog(ERROR, "plperl: cache lookup for argument type %u failed",
564 procStruct->proargtypes[i]);
566 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
568 if (typeStruct->typrelid != InvalidOid)
569 prodesc->arg_is_rel[i] = 1;
571 prodesc->arg_is_rel[i] = 0;
573 fmgr_info(typeStruct->typoutput, &(prodesc->arg_out_func[i]));
574 prodesc->arg_out_elem[i] = (Oid) (typeStruct->typelem);
575 prodesc->arg_out_len[i] = typeStruct->typlen;
579 /************************************************************
580 * create the text of the anonymous subroutine.
581 * we do not use a named subroutine so that we can call directly
582 * through the reference.
584 ************************************************************/
585 proc_source = textout(&(procStruct->prosrc));
588 * the string has been split for readbility. please don't put
589 * commas between them. Hope everyone is ANSI
591 proc_internal_def = newSVpvf(
593 "$::x->permit_only(':default');"
594 "$::x->share(qw[&elog &DEBUG &NOTICE &NOIND &ERROR]);"
596 "return $::x->reval( q[ sub { %s } ]);", proc_source);
600 /************************************************************
601 * Create the procedure in the interpreter
602 ************************************************************/
603 prodesc->reference = plperl_create_sub(proc_internal_def);
604 if (!prodesc->reference)
606 free(prodesc->proname);
608 elog(ERROR, "plperl: cannot create internal procedure %s",
612 /************************************************************
613 * Add the proc description block to the hashtable
614 ************************************************************/
615 hv_store(plperl_proc_hash, internal_proname, proname_len,
616 newSViv((IV) prodesc), 0);
620 /************************************************************
621 * Found the proc description block in the hashtable
622 ************************************************************/
623 prodesc = (plperl_proc_desc *) SvIV(*hv_fetch(plperl_proc_hash,
624 internal_proname, proname_len, 0));
628 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
630 if (sigsetjmp(Warn_restart, 1) != 0)
632 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
633 plperl_restart_in_progress = 1;
634 if (--plperl_call_level == 0)
635 plperl_restart_in_progress = 0;
636 siglongjmp(Warn_restart, 1);
640 /************************************************************
641 * Call the Perl function
642 ************************************************************/
643 perlret = plperl_call_perl_func(prodesc, proargs);
645 /************************************************************
646 * Disconnect from SPI manager and then create the return
647 * values datum (if the input function does a palloc for it
648 * this must not be allocated in the SPI memory context
649 * because SPI_finish would free it).
650 ************************************************************/
651 if (SPI_finish() != SPI_OK_FINISH)
652 elog(ERROR, "plperl: SPI_finish() failed");
654 retval = (Datum) (*fmgr_faddr(&prodesc->result_in_func))
656 prodesc->result_in_elem,
657 prodesc->result_in_len);
659 SvREFCNT_dec(perlret);
661 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
662 if (plperl_restart_in_progress)
664 if (--plperl_call_level == 0)
665 plperl_restart_in_progress = 0;
666 siglongjmp(Warn_restart, 1);
673 #ifdef REALLYHAVEITONTHEBALL
674 /**********************************************************************
675 * plperl_trigger_handler() - Handler for trigger calls
676 **********************************************************************/
678 plperl_trigger_handler(FmgrInfo *proinfo)
680 TriggerData *trigdata;
681 char internal_proname[512];
683 Tcl_HashEntry *hashent;
685 plperl_proc_desc *prodesc;
689 Tcl_DString tcl_trigtup;
690 Tcl_DString tcl_newtup;
701 sigjmp_buf save_restart;
703 /************************************************************
704 * Save the current trigger data local
705 ************************************************************/
706 trigdata = CurrentTriggerData;
707 CurrentTriggerData = NULL;
709 /************************************************************
710 * Build our internal proc name from the functions Oid
711 ************************************************************/
712 stroid = oidout(proinfo->fn_oid);
713 strcpy(internal_proname, "__PLTcl_proc_");
714 strcat(internal_proname, stroid);
717 /************************************************************
718 * Lookup the internal proc name in the hashtable
719 ************************************************************/
720 hashent = Tcl_FindHashEntry(plperl_proc_hash, internal_proname);
723 /************************************************************
724 * If we haven't found it in the hashtable,
725 * we load the procedure into the safe interpreter.
726 ************************************************************/
727 Tcl_DString proc_internal_def;
728 Tcl_DString proc_internal_body;
730 Form_pg_proc procStruct;
733 /************************************************************
734 * Allocate a new procedure description block
735 ************************************************************/
736 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
737 memset(prodesc, 0, sizeof(plperl_proc_desc));
738 prodesc->proname = malloc(strlen(internal_proname) + 1);
739 strcpy(prodesc->proname, internal_proname);
741 /************************************************************
742 * Lookup the pg_proc tuple by Oid
743 ************************************************************/
744 procTup = SearchSysCacheTuple(PROCOID,
745 ObjectIdGetDatum(proinfo->fn_oid),
747 if (!HeapTupleIsValid(procTup))
749 free(prodesc->proname);
751 elog(ERROR, "plperl: cache lookup for proc %u failed",
754 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
756 /************************************************************
757 * Create the tcl command to define the internal
759 ************************************************************/
760 Tcl_DStringInit(&proc_internal_def);
761 Tcl_DStringInit(&proc_internal_body);
762 Tcl_DStringAppendElement(&proc_internal_def, "proc");
763 Tcl_DStringAppendElement(&proc_internal_def, internal_proname);
764 Tcl_DStringAppendElement(&proc_internal_def,
765 "TG_name TG_relid TG_relatts TG_when TG_level TG_op __PLTcl_Tup_NEW __PLTcl_Tup_OLD args");
767 /************************************************************
768 * prefix procedure body with
769 * upvar #0 <internal_procname> GD
770 * and with appropriate setting of NEW, OLD,
771 * and the arguments as numerical variables.
772 ************************************************************/
773 Tcl_DStringAppend(&proc_internal_body, "upvar #0 ", -1);
774 Tcl_DStringAppend(&proc_internal_body, internal_proname, -1);
775 Tcl_DStringAppend(&proc_internal_body, " GD\n", -1);
777 Tcl_DStringAppend(&proc_internal_body,
778 "array set NEW $__PLTcl_Tup_NEW\n", -1);
779 Tcl_DStringAppend(&proc_internal_body,
780 "array set OLD $__PLTcl_Tup_OLD\n", -1);
782 Tcl_DStringAppend(&proc_internal_body,
785 "foreach v $args {\n"
789 "unset i v\n\n", -1);
791 proc_source = textout(&(procStruct->prosrc));
792 Tcl_DStringAppend(&proc_internal_body, proc_source, -1);
794 Tcl_DStringAppendElement(&proc_internal_def,
795 Tcl_DStringValue(&proc_internal_body));
796 Tcl_DStringFree(&proc_internal_body);
798 /************************************************************
799 * Create the procedure in the safe interpreter
800 ************************************************************/
801 tcl_rc = Tcl_GlobalEval(plperl_safe_interp,
802 Tcl_DStringValue(&proc_internal_def));
803 Tcl_DStringFree(&proc_internal_def);
804 if (tcl_rc != TCL_OK)
806 free(prodesc->proname);
808 elog(ERROR, "plperl: cannot create internal procedure %s - %s",
809 internal_proname, plperl_safe_interp->result);
812 /************************************************************
813 * Add the proc description block to the hashtable
814 ************************************************************/
815 hashent = Tcl_CreateHashEntry(plperl_proc_hash,
816 prodesc->proname, &hashnew);
817 Tcl_SetHashValue(hashent, (ClientData) prodesc);
821 /************************************************************
822 * Found the proc description block in the hashtable
823 ************************************************************/
824 prodesc = (plperl_proc_desc *) Tcl_GetHashValue(hashent);
827 tupdesc = trigdata->tg_relation->rd_att;
829 /************************************************************
830 * Create the tcl command to call the internal
831 * proc in the safe interpreter
832 ************************************************************/
833 Tcl_DStringInit(&tcl_cmd);
834 Tcl_DStringInit(&tcl_trigtup);
835 Tcl_DStringInit(&tcl_newtup);
837 /************************************************************
838 * We call external functions below - care for elog(ERROR)
839 ************************************************************/
840 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
841 if (sigsetjmp(Warn_restart, 1) != 0)
843 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
844 Tcl_DStringFree(&tcl_cmd);
845 Tcl_DStringFree(&tcl_trigtup);
846 Tcl_DStringFree(&tcl_newtup);
847 plperl_restart_in_progress = 1;
848 if (--plperl_call_level == 0)
849 plperl_restart_in_progress = 0;
850 siglongjmp(Warn_restart, 1);
853 /* The procedure name */
854 Tcl_DStringAppendElement(&tcl_cmd, internal_proname);
856 /* The trigger name for argument TG_name */
857 Tcl_DStringAppendElement(&tcl_cmd, trigdata->tg_trigger->tgname);
859 /* The oid of the trigger relation for argument TG_relid */
860 stroid = oidout(trigdata->tg_relation->rd_id);
861 Tcl_DStringAppendElement(&tcl_cmd, stroid);
864 /* A list of attribute names for argument TG_relatts */
865 Tcl_DStringAppendElement(&tcl_trigtup, "");
866 for (i = 0; i < tupdesc->natts; i++)
867 Tcl_DStringAppendElement(&tcl_trigtup, tupdesc->attrs[i]->attname.data);
868 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
869 Tcl_DStringFree(&tcl_trigtup);
870 Tcl_DStringInit(&tcl_trigtup);
872 /* The when part of the event for TG_when */
873 if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
874 Tcl_DStringAppendElement(&tcl_cmd, "BEFORE");
875 else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
876 Tcl_DStringAppendElement(&tcl_cmd, "AFTER");
878 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
880 /* The level part of the event for TG_level */
881 if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
882 Tcl_DStringAppendElement(&tcl_cmd, "ROW");
883 else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
884 Tcl_DStringAppendElement(&tcl_cmd, "STATEMENT");
886 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
888 /* Build the data list for the trigtuple */
889 plperl_build_tuple_argument(trigdata->tg_trigtuple,
890 tupdesc, &tcl_trigtup);
893 * Now the command part of the event for TG_op and data for NEW and
896 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
898 Tcl_DStringAppendElement(&tcl_cmd, "INSERT");
900 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
901 Tcl_DStringAppendElement(&tcl_cmd, "");
903 rettup = trigdata->tg_trigtuple;
905 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
907 Tcl_DStringAppendElement(&tcl_cmd, "DELETE");
909 Tcl_DStringAppendElement(&tcl_cmd, "");
910 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
912 rettup = trigdata->tg_trigtuple;
914 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
916 Tcl_DStringAppendElement(&tcl_cmd, "UPDATE");
918 plperl_build_tuple_argument(trigdata->tg_newtuple,
919 tupdesc, &tcl_newtup);
921 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_newtup));
922 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
924 rettup = trigdata->tg_newtuple;
928 Tcl_DStringAppendElement(&tcl_cmd, "UNKNOWN");
930 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
931 Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
933 rettup = trigdata->tg_trigtuple;
936 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
937 Tcl_DStringFree(&tcl_trigtup);
938 Tcl_DStringFree(&tcl_newtup);
940 /************************************************************
941 * Finally append the arguments from CREATE TRIGGER
942 ************************************************************/
943 for (i = 0; i < trigdata->tg_trigger->tgnargs; i++)
944 Tcl_DStringAppendElement(&tcl_cmd, trigdata->tg_trigger->tgargs[i]);
946 /************************************************************
947 * Call the Tcl function
948 ************************************************************/
949 tcl_rc = Tcl_GlobalEval(plperl_safe_interp, Tcl_DStringValue(&tcl_cmd));
950 Tcl_DStringFree(&tcl_cmd);
952 /************************************************************
953 * Check the return code from Tcl and handle
954 * our special restart mechanism to get rid
955 * of all nested call levels on transaction
957 ************************************************************/
958 if (tcl_rc == TCL_ERROR || plperl_restart_in_progress)
960 if (!plperl_restart_in_progress)
962 plperl_restart_in_progress = 1;
963 if (--plperl_call_level == 0)
964 plperl_restart_in_progress = 0;
965 elog(ERROR, "plperl: %s", plperl_safe_interp->result);
967 if (--plperl_call_level == 0)
968 plperl_restart_in_progress = 0;
969 siglongjmp(Warn_restart, 1);
978 elog(ERROR, "plperl: unsupported TCL return code %d", tcl_rc);
981 /************************************************************
982 * The return value from the procedure might be one of
983 * the magic strings OK or SKIP or a list from array get
984 ************************************************************/
985 if (SPI_finish() != SPI_OK_FINISH)
986 elog(ERROR, "plperl: SPI_finish() failed");
988 if (strcmp(plperl_safe_interp->result, "OK") == 0)
990 if (strcmp(plperl_safe_interp->result, "SKIP") == 0)
992 return (HeapTuple) NULL;;
995 /************************************************************
996 * Convert the result value from the safe interpreter
997 * and setup structures for SPI_modifytuple();
998 ************************************************************/
999 if (Tcl_SplitList(plperl_safe_interp, plperl_safe_interp->result,
1000 &ret_numvals, &ret_values) != TCL_OK)
1002 elog(NOTICE, "plperl: cannot split return value from trigger");
1003 elog(ERROR, "plperl: %s", plperl_safe_interp->result);
1006 if (ret_numvals % 2 != 0)
1009 elog(ERROR, "plperl: invalid return list from trigger - must have even # of elements");
1012 modattrs = (int *) palloc(tupdesc->natts * sizeof(int));
1013 modvalues = (Datum *) palloc(tupdesc->natts * sizeof(Datum));
1014 for (i = 0; i < tupdesc->natts; i++)
1016 modattrs[i] = i + 1;
1017 modvalues[i] = (Datum) NULL;
1020 modnulls = palloc(tupdesc->natts + 1);
1021 memset(modnulls, 'n', tupdesc->natts);
1022 modnulls[tupdesc->natts] = '\0';
1024 /************************************************************
1025 * Care for possible elog(ERROR)'s below
1026 ************************************************************/
1027 if (sigsetjmp(Warn_restart, 1) != 0)
1029 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1031 plperl_restart_in_progress = 1;
1032 if (--plperl_call_level == 0)
1033 plperl_restart_in_progress = 0;
1034 siglongjmp(Warn_restart, 1);
1038 while (i < ret_numvals)
1046 /************************************************************
1047 * Ignore pseudo elements with a dot name
1048 ************************************************************/
1049 if (*(ret_values[i]) == '.')
1055 /************************************************************
1056 * Get the attribute number
1057 ************************************************************/
1058 attnum = SPI_fnumber(tupdesc, ret_values[i++]);
1059 if (attnum == SPI_ERROR_NOATTRIBUTE)
1060 elog(ERROR, "plperl: invalid attribute '%s'", ret_values[--i]);
1062 /************************************************************
1063 * Lookup the attribute type in the syscache
1064 * for the input function
1065 ************************************************************/
1066 typeTup = SearchSysCacheTuple(TYPEOID,
1067 ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid),
1069 if (!HeapTupleIsValid(typeTup))
1071 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
1073 tupdesc->attrs[attnum - 1]->atttypid);
1075 typinput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typinput);
1076 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
1078 /************************************************************
1079 * Set the attribute to NOT NULL and convert the contents
1080 ************************************************************/
1081 modnulls[attnum - 1] = ' ';
1082 fmgr_info(typinput, &finfo);
1083 modvalues[attnum - 1] = (Datum) (*fmgr_faddr(&finfo))
1086 (!VARLENA_FIXED_SIZE(tupdesc->attrs[attnum - 1]))
1087 ? tupdesc->attrs[attnum - 1]->attlen
1088 : 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] = (Datum) (*fmgr_faddr(&qdesc->arginfuncs[j]))
1829 qdesc->argtypelems[j],
1833 /************************************************************
1834 * Free the splitted argument value list
1835 ************************************************************/
1836 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1843 /************************************************************
1844 * Remember the index of the last processed call
1845 * argument - a loop body for SELECT might follow
1846 ************************************************************/
1849 /************************************************************
1850 * Prepare to start a controlled return through all
1851 * interpreter levels on transaction abort
1852 ************************************************************/
1853 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1854 if (sigsetjmp(Warn_restart, 1) != 0)
1856 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1857 for (j = 0; j < callnargs; j++)
1859 if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)
1861 pfree((char *) (qdesc->argvalues[j]));
1862 qdesc->argvalues[j] = (Datum) NULL;
1865 plperl_restart_in_progress = 1;
1866 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1870 /************************************************************
1872 ************************************************************/
1873 spi_rc = SPI_execp(qdesc->plan, qdesc->argvalues, nulls, count);
1874 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1876 /************************************************************
1877 * For varlena data types, free the argument values
1878 ************************************************************/
1879 for (j = 0; j < callnargs; j++)
1881 if (qdesc->arglen[j] < 0 && qdesc->argvalues[j] != (Datum) NULL)
1883 pfree((char *) (qdesc->argvalues[j]));
1884 qdesc->argvalues[j] = (Datum) NULL;
1888 /************************************************************
1889 * Check the return code from SPI_execp()
1890 ************************************************************/
1893 case SPI_OK_UTILITY:
1894 Tcl_SetResult(interp, "0", TCL_VOLATILE);
1897 case SPI_OK_SELINTO:
1901 sprintf(buf, "%d", SPI_processed);
1902 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1908 case SPI_ERROR_ARGUMENT:
1909 Tcl_SetResult(interp,
1910 "plperl: SPI_exec() failed - SPI_ERROR_ARGUMENT",
1914 case SPI_ERROR_UNCONNECTED:
1915 Tcl_SetResult(interp,
1916 "plperl: SPI_exec() failed - SPI_ERROR_UNCONNECTED",
1920 case SPI_ERROR_COPY:
1921 Tcl_SetResult(interp,
1922 "plperl: SPI_exec() failed - SPI_ERROR_COPY",
1926 case SPI_ERROR_CURSOR:
1927 Tcl_SetResult(interp,
1928 "plperl: SPI_exec() failed - SPI_ERROR_CURSOR",
1932 case SPI_ERROR_TRANSACTION:
1933 Tcl_SetResult(interp,
1934 "plperl: SPI_exec() failed - SPI_ERROR_TRANSACTION",
1938 case SPI_ERROR_OPUNKNOWN:
1939 Tcl_SetResult(interp,
1940 "plperl: SPI_exec() failed - SPI_ERROR_OPUNKNOWN",
1945 sprintf(buf, "%d", spi_rc);
1946 Tcl_AppendResult(interp, "plperl: SPI_exec() failed - ",
1947 "unknown RC ", buf, NULL);
1951 /************************************************************
1952 * Only SELECT queries fall through to here - remember the
1954 ************************************************************/
1956 ntuples = SPI_processed;
1959 tuples = SPI_tuptable->vals;
1960 tupdesc = SPI_tuptable->tupdesc;
1963 /************************************************************
1964 * Prepare to start a controlled return through all
1965 * interpreter levels on transaction abort during
1966 * the ouput conversions of the results
1967 ************************************************************/
1968 memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
1969 if (sigsetjmp(Warn_restart, 1) != 0)
1971 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1972 plperl_restart_in_progress = 1;
1973 Tcl_SetResult(interp, "Transaction abort", TCL_VOLATILE);
1977 /************************************************************
1978 * If there is no loop body given, just set the variables
1979 * from the first tuple (if any) and return the number of
1981 ************************************************************/
1982 if (loop_body >= argc)
1985 plperl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
1986 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
1987 sprintf(buf, "%d", ntuples);
1988 Tcl_SetResult(interp, buf, TCL_VOLATILE);
1992 /************************************************************
1993 * There is a loop body - process all tuples and evaluate
1995 ************************************************************/
1996 for (i = 0; i < ntuples; i++)
1998 plperl_set_tuple_values(interp, arrayname, i, tuples[i], tupdesc);
2000 loop_rc = Tcl_Eval(interp, argv[loop_body]);
2002 if (loop_rc == TCL_OK)
2004 if (loop_rc == TCL_CONTINUE)
2006 if (loop_rc == TCL_RETURN)
2008 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2011 if (loop_rc == TCL_BREAK)
2013 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2017 /************************************************************
2018 * Finally return the number of tuples
2019 ************************************************************/
2020 memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
2021 sprintf(buf, "%d", ntuples);
2022 Tcl_SetResult(interp, buf, TCL_VOLATILE);
2027 /**********************************************************************
2028 * plperl_set_tuple_values() - Set variables for all attributes
2030 **********************************************************************/
2032 plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
2033 int tupno, HeapTuple tuple, TupleDesc tupdesc)
2048 char *nullname = NULL;
2050 /************************************************************
2051 * Prepare pointers for Tcl_SetVar2() below and in array
2052 * mode set the .tupno element
2053 ************************************************************/
2054 if (arrayname == NULL)
2057 nameptr = &nullname;
2061 arrptr = &arrayname;
2063 sprintf(buf, "%d", tupno);
2064 Tcl_SetVar2(interp, arrayname, ".tupno", buf, 0);
2067 for (i = 0; i < tupdesc->natts; i++)
2069 /************************************************************
2070 * Get the attribute name
2071 ************************************************************/
2072 attname = tupdesc->attrs[i]->attname.data;
2074 /************************************************************
2075 * Get the attributes value
2076 ************************************************************/
2077 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
2079 /************************************************************
2080 * Lookup the attribute type in the syscache
2081 * for the output function
2082 ************************************************************/
2083 typeTup = SearchSysCacheTuple(TYPEOID,
2084 ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
2086 if (!HeapTupleIsValid(typeTup))
2088 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
2089 attname, tupdesc->attrs[i]->atttypid);
2092 typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput);
2093 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
2095 /************************************************************
2096 * If there is a value, set the variable
2099 * Hmmm - Null attributes will cause functions to
2100 * crash if they don't expect them - need something
2102 ************************************************************/
2103 if (!isnull && OidIsValid(typoutput))
2107 fmgr_info(typoutput, &finfo);
2109 outputstr = (*fmgr_faddr(&finfo))
2111 tupdesc->attrs[i]->attlen);
2113 Tcl_SetVar2(interp, *arrptr, *nameptr, outputstr, 0);
2117 Tcl_UnsetVar2(interp, *arrptr, *nameptr, 0);
2123 /**********************************************************************
2124 * plperl_build_tuple_argument() - Build a string for a ref to a hash
2125 * from all attributes of a given tuple
2126 **********************************************************************/
2128 plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
2141 output = sv_2mortal(newSVpv("{", 0));
2143 for (i = 0; i < tupdesc->natts; i++)
2145 /************************************************************
2146 * Get the attribute name
2147 ************************************************************/
2148 attname = tupdesc->attrs[i]->attname.data;
2150 /************************************************************
2151 * Get the attributes value
2152 ************************************************************/
2153 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
2155 /************************************************************
2156 * Lookup the attribute type in the syscache
2157 * for the output function
2158 ************************************************************/
2159 typeTup = SearchSysCacheTuple(TYPEOID,
2160 ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
2162 if (!HeapTupleIsValid(typeTup))
2164 elog(ERROR, "plperl: Cache lookup for attribute '%s' type %u failed",
2165 attname, tupdesc->attrs[i]->atttypid);
2168 typoutput = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typoutput);
2169 typelem = (Oid) (((Form_pg_type) GETSTRUCT(typeTup))->typelem);
2171 /************************************************************
2172 * If there is a value, append the attribute name and the
2173 * value to the list.
2174 * If it is null it will be set to undef.
2175 ************************************************************/
2176 if (!isnull && OidIsValid(typoutput))
2180 fmgr_info(typoutput, &finfo);
2182 outputstr = (*fmgr_faddr(&finfo))
2184 tupdesc->attrs[i]->attlen);
2186 sv_catpvf(output, "'%s' => '%s',", attname, outputstr);
2190 sv_catpvf(output, "'%s' => undef,", attname);
2192 sv_catpv(output, "}");
2193 output = perl_eval_pv(SvPV(output, na), TRUE);