00001
00002
00003
00004
00005
00006
00007
00008 #include "postgres.h"
00009
00010 #undef _
00011
00012
00013 #include <ctype.h>
00014 #include <fcntl.h>
00015 #include <unistd.h>
00016 #include <locale.h>
00017
00018
00019 #include "access/htup_details.h"
00020 #include "access/xact.h"
00021 #include "catalog/pg_language.h"
00022 #include "catalog/pg_proc.h"
00023 #include "catalog/pg_type.h"
00024 #include "commands/trigger.h"
00025 #include "executor/spi.h"
00026 #include "funcapi.h"
00027 #include "mb/pg_wchar.h"
00028 #include "miscadmin.h"
00029 #include "nodes/makefuncs.h"
00030 #include "parser/parse_type.h"
00031 #include "storage/ipc.h"
00032 #include "tcop/tcopprot.h"
00033 #include "utils/builtins.h"
00034 #include "utils/fmgroids.h"
00035 #include "utils/guc.h"
00036 #include "utils/hsearch.h"
00037 #include "utils/lsyscache.h"
00038 #include "utils/memutils.h"
00039 #include "utils/rel.h"
00040 #include "utils/syscache.h"
00041 #include "utils/typcache.h"
00042
00043
00044 #undef TEXTDOMAIN
00045 #define TEXTDOMAIN PG_TEXTDOMAIN("plperl")
00046
00047
00048 #include "plperl.h"
00049 #include "plperl_helpers.h"
00050
00051
00052 #include "perlchunks.h"
00053
00054 #include "plperl_opmask.h"
00055
00056 EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
00057 EXTERN_C void boot_PostgreSQL__InServer__Util(pTHX_ CV *cv);
00058 EXTERN_C void boot_PostgreSQL__InServer__SPI(pTHX_ CV *cv);
00059
00060 PG_MODULE_MAGIC;
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 typedef struct plperl_interp_desc
00089 {
00090 Oid user_id;
00091 PerlInterpreter *interp;
00092 HTAB *query_hash;
00093 } plperl_interp_desc;
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 typedef struct plperl_proc_desc
00105 {
00106 char *proname;
00107 TransactionId fn_xmin;
00108 ItemPointerData fn_tid;
00109 int refcount;
00110 SV *reference;
00111 plperl_interp_desc *interp;
00112 bool fn_readonly;
00113 bool lanpltrusted;
00114 bool fn_retistuple;
00115 bool fn_retisset;
00116 bool fn_retisarray;
00117
00118 Oid result_oid;
00119 FmgrInfo result_in_func;
00120 Oid result_typioparam;
00121
00122 int nargs;
00123 FmgrInfo arg_out_func[FUNC_MAX_ARGS];
00124 bool arg_is_rowtype[FUNC_MAX_ARGS];
00125 Oid arg_arraytype[FUNC_MAX_ARGS];
00126 } plperl_proc_desc;
00127
00128 #define increment_prodesc_refcount(prodesc) \
00129 ((prodesc)->refcount++)
00130 #define decrement_prodesc_refcount(prodesc) \
00131 do { \
00132 if (--((prodesc)->refcount) <= 0) \
00133 free_plperl_function(prodesc); \
00134 } while(0)
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 typedef struct plperl_proc_key
00150 {
00151 Oid proc_id;
00152
00153
00154
00155
00156
00157 Oid is_trigger;
00158 Oid user_id;
00159 } plperl_proc_key;
00160
00161 typedef struct plperl_proc_ptr
00162 {
00163 plperl_proc_key proc_key;
00164 plperl_proc_desc *proc_ptr;
00165 } plperl_proc_ptr;
00166
00167
00168
00169
00170
00171 typedef struct plperl_call_data
00172 {
00173 plperl_proc_desc *prodesc;
00174 FunctionCallInfo fcinfo;
00175 Tuplestorestate *tuple_store;
00176 TupleDesc ret_tdesc;
00177 MemoryContext tmp_cxt;
00178 } plperl_call_data;
00179
00180
00181
00182
00183 typedef struct plperl_query_desc
00184 {
00185 char qname[24];
00186 MemoryContext plan_cxt;
00187 SPIPlanPtr plan;
00188 int nargs;
00189 Oid *argtypes;
00190 FmgrInfo *arginfuncs;
00191 Oid *argtypioparams;
00192 } plperl_query_desc;
00193
00194
00195
00196 typedef struct plperl_query_entry
00197 {
00198 char query_name[NAMEDATALEN];
00199 plperl_query_desc *query_data;
00200 } plperl_query_entry;
00201
00202
00203
00204
00205 typedef struct plperl_array_info
00206 {
00207 int ndims;
00208 bool elem_is_rowtype;
00209 Datum *elements;
00210 bool *nulls;
00211 int *nelems;
00212 FmgrInfo proc;
00213 } plperl_array_info;
00214
00215
00216
00217
00218
00219 static HTAB *plperl_interp_hash = NULL;
00220 static HTAB *plperl_proc_hash = NULL;
00221 static plperl_interp_desc *plperl_active_interp = NULL;
00222
00223
00224 static PerlInterpreter *plperl_held_interp = NULL;
00225
00226
00227 static bool plperl_use_strict = false;
00228 static char *plperl_on_init = NULL;
00229 static char *plperl_on_plperl_init = NULL;
00230 static char *plperl_on_plperlu_init = NULL;
00231
00232 static bool plperl_ending = false;
00233 static OP *(*pp_require_orig) (pTHX) = NULL;
00234 static char plperl_opmask[MAXO];
00235
00236
00237 static plperl_call_data *current_call_data = NULL;
00238
00239
00240
00241
00242 Datum plperl_call_handler(PG_FUNCTION_ARGS);
00243 Datum plperl_inline_handler(PG_FUNCTION_ARGS);
00244 Datum plperl_validator(PG_FUNCTION_ARGS);
00245 Datum plperlu_call_handler(PG_FUNCTION_ARGS);
00246 Datum plperlu_inline_handler(PG_FUNCTION_ARGS);
00247 Datum plperlu_validator(PG_FUNCTION_ARGS);
00248 void _PG_init(void);
00249
00250 static PerlInterpreter *plperl_init_interp(void);
00251 static void plperl_destroy_interp(PerlInterpreter **);
00252 static void plperl_fini(int code, Datum arg);
00253 static void set_interp_require(bool trusted);
00254
00255 static Datum plperl_func_handler(PG_FUNCTION_ARGS);
00256 static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
00257
00258 static void free_plperl_function(plperl_proc_desc *prodesc);
00259
00260 static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger);
00261
00262 static SV *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc);
00263 static SV *plperl_hash_from_datum(Datum attr);
00264 static SV *plperl_ref_from_pg_array(Datum arg, Oid typid);
00265 static SV *split_array(plperl_array_info *info, int first, int last, int nest);
00266 static SV *make_array_ref(plperl_array_info *info, int first, int last);
00267 static SV *get_perl_array_ref(SV *sv);
00268 static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
00269 FunctionCallInfo fcinfo,
00270 FmgrInfo *finfo, Oid typioparam,
00271 bool *isnull);
00272 static void _sv_to_datum_finfo(Oid typid, FmgrInfo *finfo, Oid *typioparam);
00273 static Datum plperl_array_to_datum(SV *src, Oid typid, int32 typmod);
00274 static ArrayBuildState *array_to_datum_internal(AV *av, ArrayBuildState *astate,
00275 int *ndims, int *dims, int cur_depth,
00276 Oid arraytypid, Oid elemtypid, int32 typmod,
00277 FmgrInfo *finfo, Oid typioparam);
00278 static Datum plperl_hash_to_datum(SV *src, TupleDesc td);
00279
00280 static void plperl_init_shared_libs(pTHX);
00281 static void plperl_trusted_init(void);
00282 static void plperl_untrusted_init(void);
00283 static HV *plperl_spi_execute_fetch_result(SPITupleTable *, int, int);
00284 static char *hek2cstr(HE *he);
00285 static SV **hv_store_string(HV *hv, const char *key, SV *val);
00286 static SV **hv_fetch_string(HV *hv, const char *key);
00287 static void plperl_create_sub(plperl_proc_desc *desc, char *s, Oid fn_oid);
00288 static SV *plperl_call_perl_func(plperl_proc_desc *desc,
00289 FunctionCallInfo fcinfo);
00290 static void plperl_compile_callback(void *arg);
00291 static void plperl_exec_callback(void *arg);
00292 static void plperl_inline_callback(void *arg);
00293 static char *strip_trailing_ws(const char *msg);
00294 static OP *pp_require_safe(pTHX);
00295 static void activate_interpreter(plperl_interp_desc *interp_desc);
00296
00297 #ifdef WIN32
00298 static char *setlocale_perl(int category, char *locale);
00299 #endif
00300
00301
00302
00303
00304 static char *
00305 hek2cstr(HE *he)
00306 {
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 SV *sv = HeSVKEY_force(he);
00332
00333 if (HeUTF8(he))
00334 SvUTF8_on(sv);
00335 return sv2cstr(sv);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 static void
00350 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
00351 {
00352 fmgr_info_cxt(functionId, finfo, TopMemoryContext);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361 void
00362 _PG_init(void)
00363 {
00364
00365
00366
00367
00368
00369
00370
00371
00372 static bool inited = false;
00373 HASHCTL hash_ctl;
00374
00375 if (inited)
00376 return;
00377
00378
00379
00380
00381 pg_bindtextdomain(TEXTDOMAIN);
00382
00383
00384
00385
00386 DefineCustomBoolVariable("plperl.use_strict",
00387 gettext_noop("If true, trusted and untrusted Perl code will be compiled in strict mode."),
00388 NULL,
00389 &plperl_use_strict,
00390 false,
00391 PGC_USERSET, 0,
00392 NULL, NULL, NULL);
00393
00394
00395
00396
00397
00398
00399
00400 DefineCustomStringVariable("plperl.on_init",
00401 gettext_noop("Perl initialization code to execute when a Perl interpreter is initialized."),
00402 NULL,
00403 &plperl_on_init,
00404 NULL,
00405 PGC_SIGHUP, 0,
00406 NULL, NULL, NULL);
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 DefineCustomStringVariable("plperl.on_plperl_init",
00423 gettext_noop("Perl initialization code to execute once when plperl is first used."),
00424 NULL,
00425 &plperl_on_plperl_init,
00426 NULL,
00427 PGC_SUSET, 0,
00428 NULL, NULL, NULL);
00429
00430 DefineCustomStringVariable("plperl.on_plperlu_init",
00431 gettext_noop("Perl initialization code to execute once when plperlu is first used."),
00432 NULL,
00433 &plperl_on_plperlu_init,
00434 NULL,
00435 PGC_SUSET, 0,
00436 NULL, NULL, NULL);
00437
00438 EmitWarningsOnPlaceholders("plperl");
00439
00440
00441
00442
00443 memset(&hash_ctl, 0, sizeof(hash_ctl));
00444 hash_ctl.keysize = sizeof(Oid);
00445 hash_ctl.entrysize = sizeof(plperl_interp_desc);
00446 hash_ctl.hash = oid_hash;
00447 plperl_interp_hash = hash_create("PL/Perl interpreters",
00448 8,
00449 &hash_ctl,
00450 HASH_ELEM | HASH_FUNCTION);
00451
00452 memset(&hash_ctl, 0, sizeof(hash_ctl));
00453 hash_ctl.keysize = sizeof(plperl_proc_key);
00454 hash_ctl.entrysize = sizeof(plperl_proc_ptr);
00455 hash_ctl.hash = tag_hash;
00456 plperl_proc_hash = hash_create("PL/Perl procedures",
00457 32,
00458 &hash_ctl,
00459 HASH_ELEM | HASH_FUNCTION);
00460
00461
00462
00463
00464 PLPERL_SET_OPMASK(plperl_opmask);
00465
00466
00467
00468
00469 plperl_held_interp = plperl_init_interp();
00470
00471 inited = true;
00472 }
00473
00474
00475 static void
00476 set_interp_require(bool trusted)
00477 {
00478 if (trusted)
00479 {
00480 PL_ppaddr[OP_REQUIRE] = pp_require_safe;
00481 PL_ppaddr[OP_DOFILE] = pp_require_safe;
00482 }
00483 else
00484 {
00485 PL_ppaddr[OP_REQUIRE] = pp_require_orig;
00486 PL_ppaddr[OP_DOFILE] = pp_require_orig;
00487 }
00488 }
00489
00490
00491
00492
00493
00494 static void
00495 plperl_fini(int code, Datum arg)
00496 {
00497 HASH_SEQ_STATUS hash_seq;
00498 plperl_interp_desc *interp_desc;
00499
00500 elog(DEBUG3, "plperl_fini");
00501
00502
00503
00504
00505
00506
00507
00508 plperl_ending = true;
00509
00510
00511 if (code)
00512 {
00513 elog(DEBUG3, "plperl_fini: skipped");
00514 return;
00515 }
00516
00517
00518 plperl_destroy_interp(&plperl_held_interp);
00519
00520
00521 hash_seq_init(&hash_seq, plperl_interp_hash);
00522 while ((interp_desc = hash_seq_search(&hash_seq)) != NULL)
00523 {
00524 if (interp_desc->interp)
00525 {
00526 activate_interpreter(interp_desc);
00527 plperl_destroy_interp(&interp_desc->interp);
00528 }
00529 }
00530
00531 elog(DEBUG3, "plperl_fini: done");
00532 }
00533
00534
00535
00536
00537
00538 static void
00539 select_perl_context(bool trusted)
00540 {
00541 Oid user_id;
00542 plperl_interp_desc *interp_desc;
00543 bool found;
00544 PerlInterpreter *interp = NULL;
00545
00546
00547 if (trusted)
00548 user_id = GetUserId();
00549 else
00550 user_id = InvalidOid;
00551
00552 interp_desc = hash_search(plperl_interp_hash, &user_id,
00553 HASH_ENTER,
00554 &found);
00555 if (!found)
00556 {
00557
00558 interp_desc->interp = NULL;
00559 interp_desc->query_hash = NULL;
00560 }
00561
00562
00563 if (interp_desc->query_hash == NULL)
00564 {
00565 HASHCTL hash_ctl;
00566
00567 memset(&hash_ctl, 0, sizeof(hash_ctl));
00568 hash_ctl.keysize = NAMEDATALEN;
00569 hash_ctl.entrysize = sizeof(plperl_query_entry);
00570 interp_desc->query_hash = hash_create("PL/Perl queries",
00571 32,
00572 &hash_ctl,
00573 HASH_ELEM);
00574 }
00575
00576
00577
00578
00579 if (interp_desc->interp)
00580 {
00581 activate_interpreter(interp_desc);
00582 return;
00583 }
00584
00585
00586
00587
00588 if (plperl_held_interp != NULL)
00589 {
00590
00591 interp = plperl_held_interp;
00592
00593
00594
00595
00596
00597 plperl_held_interp = NULL;
00598
00599 if (trusted)
00600 plperl_trusted_init();
00601 else
00602 plperl_untrusted_init();
00603
00604
00605 on_proc_exit(plperl_fini, 0);
00606 }
00607 else
00608 {
00609 #ifdef MULTIPLICITY
00610
00611
00612
00613
00614
00615
00616
00617
00618 plperl_active_interp = NULL;
00619
00620
00621 interp = plperl_init_interp();
00622
00623 if (trusted)
00624 plperl_trusted_init();
00625 else
00626 plperl_untrusted_init();
00627 #else
00628 elog(ERROR,
00629 "cannot allocate multiple Perl interpreters on this platform");
00630 #endif
00631 }
00632
00633 set_interp_require(trusted);
00634
00635
00636
00637
00638
00639
00640
00641
00642 newXS("PostgreSQL::InServer::SPI::bootstrap",
00643 boot_PostgreSQL__InServer__SPI, __FILE__);
00644
00645 eval_pv("PostgreSQL::InServer::SPI::bootstrap()", FALSE);
00646 if (SvTRUE(ERRSV))
00647 ereport(ERROR,
00648 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00649 errcontext("while executing PostgreSQL::InServer::SPI::bootstrap")));
00650
00651
00652 interp_desc->interp = interp;
00653
00654
00655 plperl_active_interp = interp_desc;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664 static void
00665 activate_interpreter(plperl_interp_desc *interp_desc)
00666 {
00667 if (interp_desc && plperl_active_interp != interp_desc)
00668 {
00669 Assert(interp_desc->interp);
00670 PERL_SET_CONTEXT(interp_desc->interp);
00671
00672 set_interp_require(OidIsValid(interp_desc->user_id));
00673 plperl_active_interp = interp_desc;
00674 }
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 static PerlInterpreter *
00686 plperl_init_interp(void)
00687 {
00688 PerlInterpreter *plperl;
00689
00690 static char *embedding[3 + 2] = {
00691 "", "-e", PLC_PERLBOOT
00692 };
00693 int nargs = 3;
00694
00695 #ifdef WIN32
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717 char *loc;
00718 char *save_collate,
00719 *save_ctype,
00720 *save_monetary,
00721 *save_numeric,
00722 *save_time;
00723
00724 loc = setlocale(LC_COLLATE, NULL);
00725 save_collate = loc ? pstrdup(loc) : NULL;
00726 loc = setlocale(LC_CTYPE, NULL);
00727 save_ctype = loc ? pstrdup(loc) : NULL;
00728 loc = setlocale(LC_MONETARY, NULL);
00729 save_monetary = loc ? pstrdup(loc) : NULL;
00730 loc = setlocale(LC_NUMERIC, NULL);
00731 save_numeric = loc ? pstrdup(loc) : NULL;
00732 loc = setlocale(LC_TIME, NULL);
00733 save_time = loc ? pstrdup(loc) : NULL;
00734
00735 #define PLPERL_RESTORE_LOCALE(name, saved) \
00736 STMT_START { \
00737 if (saved != NULL) { setlocale_perl(name, saved); pfree(saved); } \
00738 } STMT_END
00739 #endif
00740
00741 if (plperl_on_init && *plperl_on_init)
00742 {
00743 embedding[nargs++] = "-e";
00744 embedding[nargs++] = plperl_on_init;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 #if defined(PERL_SYS_INIT3) && !defined(MYMALLOC)
00757 {
00758 static int perl_sys_init_done;
00759
00760
00761 if (!perl_sys_init_done)
00762 {
00763 char *dummy_env[1] = {NULL};
00764
00765 PERL_SYS_INIT3(&nargs, (char ***) &embedding, (char ***) &dummy_env);
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 pqsignal(SIGFPE, FloatExceptionHandler);
00777
00778 perl_sys_init_done = 1;
00779
00780 dummy_env[0] = NULL;
00781 }
00782 }
00783 #endif
00784
00785 plperl = perl_alloc();
00786 if (!plperl)
00787 elog(ERROR, "could not allocate Perl interpreter");
00788
00789 PERL_SET_CONTEXT(plperl);
00790 perl_construct(plperl);
00791
00792
00793 PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
00794
00795
00796
00797
00798
00799
00800 if (!pp_require_orig)
00801 pp_require_orig = PL_ppaddr[OP_REQUIRE];
00802 else
00803 {
00804 PL_ppaddr[OP_REQUIRE] = pp_require_orig;
00805 PL_ppaddr[OP_DOFILE] = pp_require_orig;
00806 }
00807
00808 #ifdef PLPERL_ENABLE_OPMASK_EARLY
00809
00810
00811
00812
00813
00814
00815
00816 PL_op_mask = plperl_opmask;
00817 #endif
00818
00819 if (perl_parse(plperl, plperl_init_shared_libs,
00820 nargs, embedding, NULL) != 0)
00821 ereport(ERROR,
00822 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00823 errcontext("while parsing Perl initialization")));
00824
00825 if (perl_run(plperl) != 0)
00826 ereport(ERROR,
00827 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00828 errcontext("while running Perl initialization")));
00829
00830 #ifdef PLPERL_RESTORE_LOCALE
00831 PLPERL_RESTORE_LOCALE(LC_COLLATE, save_collate);
00832 PLPERL_RESTORE_LOCALE(LC_CTYPE, save_ctype);
00833 PLPERL_RESTORE_LOCALE(LC_MONETARY, save_monetary);
00834 PLPERL_RESTORE_LOCALE(LC_NUMERIC, save_numeric);
00835 PLPERL_RESTORE_LOCALE(LC_TIME, save_time);
00836 #endif
00837
00838 return plperl;
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849 static OP *
00850 pp_require_safe(pTHX)
00851 {
00852 dVAR;
00853 dSP;
00854 SV *sv,
00855 **svp;
00856 char *name;
00857 STRLEN len;
00858
00859 sv = POPs;
00860 name = SvPV(sv, len);
00861 if (!(name && len > 0 && *name))
00862 RETPUSHNO;
00863
00864 svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
00865 if (svp && *svp != &PL_sv_undef)
00866 RETPUSHYES;
00867
00868 DIE(aTHX_ "Unable to load %s into plperl", name);
00869
00870
00871
00872
00873
00874
00875
00876
00877 return NULL;
00878 }
00879
00880
00881
00882
00883
00884
00885
00886 static void
00887 plperl_destroy_interp(PerlInterpreter **interp)
00888 {
00889 if (interp && *interp)
00890 {
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903 if (PL_exit_flags & PERL_EXIT_DESTRUCT_END)
00904 {
00905 dJMPENV;
00906 int x = 0;
00907
00908 JMPENV_PUSH(x);
00909 PERL_UNUSED_VAR(x);
00910 if (PL_endav && !PL_minus_c)
00911 call_list(PL_scopestack_ix, PL_endav);
00912 JMPENV_POP;
00913 }
00914 LEAVE;
00915 FREETMPS;
00916
00917 *interp = NULL;
00918 }
00919 }
00920
00921
00922
00923
00924 static void
00925 plperl_trusted_init(void)
00926 {
00927 HV *stash;
00928 SV *sv;
00929 char *key;
00930 I32 klen;
00931
00932
00933 PL_ppaddr[OP_REQUIRE] = pp_require_orig;
00934 PL_ppaddr[OP_DOFILE] = pp_require_orig;
00935
00936 eval_pv(PLC_TRUSTED, FALSE);
00937 if (SvTRUE(ERRSV))
00938 ereport(ERROR,
00939 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00940 errcontext("while executing PLC_TRUSTED")));
00941
00942
00943
00944
00945
00946
00947 eval_pv("my $a=chr(0x100); return $a =~ /\\xa9/i", FALSE);
00948 if (SvTRUE(ERRSV))
00949 ereport(ERROR,
00950 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00951 errcontext("while executing utf8fix")));
00952
00953
00954
00955
00956
00957
00958 PL_ppaddr[OP_REQUIRE] = pp_require_safe;
00959 PL_ppaddr[OP_DOFILE] = pp_require_safe;
00960
00961
00962
00963
00964
00965 PL_op_mask = plperl_opmask;
00966
00967
00968 stash = gv_stashpv("DynaLoader", GV_ADDWARN);
00969 hv_iterinit(stash);
00970 while ((sv = hv_iternextsv(stash, &key, &klen)))
00971 {
00972 if (!isGV_with_GP(sv) || !GvCV(sv))
00973 continue;
00974 SvREFCNT_dec(GvCV(sv));
00975 GvCV_set(sv, NULL);
00976 }
00977 hv_clear(stash);
00978
00979
00980 ++PL_sub_generation;
00981 hv_clear(PL_stashcache);
00982
00983
00984
00985
00986 if (plperl_on_plperl_init && *plperl_on_plperl_init)
00987 {
00988 eval_pv(plperl_on_plperl_init, FALSE);
00989 if (SvTRUE(ERRSV))
00990 ereport(ERROR,
00991 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
00992 errcontext("while executing plperl.on_plperl_init")));
00993
00994 }
00995 }
00996
00997
00998
00999
01000
01001 static void
01002 plperl_untrusted_init(void)
01003 {
01004
01005
01006
01007 if (plperl_on_plperlu_init && *plperl_on_plperlu_init)
01008 {
01009 eval_pv(plperl_on_plperlu_init, FALSE);
01010 if (SvTRUE(ERRSV))
01011 ereport(ERROR,
01012 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
01013 errcontext("while executing plperl.on_plperlu_init")));
01014 }
01015 }
01016
01017
01018
01019
01020
01021 static char *
01022 strip_trailing_ws(const char *msg)
01023 {
01024 char *res = pstrdup(msg);
01025 int len = strlen(res);
01026
01027 while (len > 0 && isspace((unsigned char) res[len - 1]))
01028 res[--len] = '\0';
01029 return res;
01030 }
01031
01032
01033
01034
01035 static HeapTuple
01036 plperl_build_tuple_result(HV *perlhash, TupleDesc td)
01037 {
01038 Datum *values;
01039 bool *nulls;
01040 HE *he;
01041 HeapTuple tup;
01042
01043 values = palloc0(sizeof(Datum) * td->natts);
01044 nulls = palloc(sizeof(bool) * td->natts);
01045 memset(nulls, true, sizeof(bool) * td->natts);
01046
01047 hv_iterinit(perlhash);
01048 while ((he = hv_iternext(perlhash)))
01049 {
01050 SV *val = HeVAL(he);
01051 char *key = hek2cstr(he);
01052 int attn = SPI_fnumber(td, key);
01053
01054 if (attn <= 0 || td->attrs[attn - 1]->attisdropped)
01055 ereport(ERROR,
01056 (errcode(ERRCODE_UNDEFINED_COLUMN),
01057 errmsg("Perl hash contains nonexistent column \"%s\"",
01058 key)));
01059
01060 values[attn - 1] = plperl_sv_to_datum(val,
01061 td->attrs[attn - 1]->atttypid,
01062 td->attrs[attn - 1]->atttypmod,
01063 NULL,
01064 NULL,
01065 InvalidOid,
01066 &nulls[attn - 1]);
01067
01068 pfree(key);
01069 }
01070 hv_iterinit(perlhash);
01071
01072 tup = heap_form_tuple(td, values, nulls);
01073 pfree(values);
01074 pfree(nulls);
01075 return tup;
01076 }
01077
01078
01079 static Datum
01080 plperl_hash_to_datum(SV *src, TupleDesc td)
01081 {
01082 HeapTuple tup = plperl_build_tuple_result((HV *) SvRV(src), td);
01083
01084 return HeapTupleGetDatum(tup);
01085 }
01086
01087
01088
01089
01090
01091 static SV *
01092 get_perl_array_ref(SV *sv)
01093 {
01094 if (SvOK(sv) && SvROK(sv))
01095 {
01096 if (SvTYPE(SvRV(sv)) == SVt_PVAV)
01097 return sv;
01098 else if (sv_isa(sv, "PostgreSQL::InServer::ARRAY"))
01099 {
01100 HV *hv = (HV *) SvRV(sv);
01101 SV **sav = hv_fetch_string(hv, "array");
01102
01103 if (*sav && SvOK(*sav) && SvROK(*sav) &&
01104 SvTYPE(SvRV(*sav)) == SVt_PVAV)
01105 return *sav;
01106
01107 elog(ERROR, "could not get array reference from PostgreSQL::InServer::ARRAY object");
01108 }
01109 }
01110 return NULL;
01111 }
01112
01113
01114
01115
01116 static ArrayBuildState *
01117 array_to_datum_internal(AV *av, ArrayBuildState *astate,
01118 int *ndims, int *dims, int cur_depth,
01119 Oid arraytypid, Oid elemtypid, int32 typmod,
01120 FmgrInfo *finfo, Oid typioparam)
01121 {
01122 int i;
01123 int len = av_len(av) + 1;
01124
01125 for (i = 0; i < len; i++)
01126 {
01127
01128 SV **svp = av_fetch(av, i, FALSE);
01129
01130
01131 SV *sav = svp ? get_perl_array_ref(*svp) : NULL;
01132
01133
01134 if (sav)
01135 {
01136 AV *nav = (AV *) SvRV(sav);
01137
01138
01139 if (cur_depth + 1 > MAXDIM)
01140 ereport(ERROR,
01141 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
01142 errmsg("number of array dimensions (%d) exceeds the maximum allowed (%d)",
01143 cur_depth + 1, MAXDIM)));
01144
01145
01146 if (i == 0 && *ndims == cur_depth)
01147 {
01148 dims[*ndims] = av_len(nav) + 1;
01149 (*ndims)++;
01150 }
01151 else if (av_len(nav) + 1 != dims[cur_depth])
01152 ereport(ERROR,
01153 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
01154 errmsg("multidimensional arrays must have array expressions with matching dimensions")));
01155
01156
01157 astate = array_to_datum_internal(nav, astate,
01158 ndims, dims, cur_depth + 1,
01159 arraytypid, elemtypid, typmod,
01160 finfo, typioparam);
01161 }
01162 else
01163 {
01164 Datum dat;
01165 bool isnull;
01166
01167
01168 if (*ndims != cur_depth)
01169 ereport(ERROR,
01170 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
01171 errmsg("multidimensional arrays must have array expressions with matching dimensions")));
01172
01173 dat = plperl_sv_to_datum(svp ? *svp : NULL,
01174 elemtypid,
01175 typmod,
01176 NULL,
01177 finfo,
01178 typioparam,
01179 &isnull);
01180
01181 astate = accumArrayResult(astate, dat, isnull,
01182 elemtypid, CurrentMemoryContext);
01183 }
01184 }
01185
01186 return astate;
01187 }
01188
01189
01190
01191
01192 static Datum
01193 plperl_array_to_datum(SV *src, Oid typid, int32 typmod)
01194 {
01195 ArrayBuildState *astate;
01196 Oid elemtypid;
01197 FmgrInfo finfo;
01198 Oid typioparam;
01199 int dims[MAXDIM];
01200 int lbs[MAXDIM];
01201 int ndims = 1;
01202 int i;
01203
01204 elemtypid = get_element_type(typid);
01205 if (!elemtypid)
01206 ereport(ERROR,
01207 (errcode(ERRCODE_DATATYPE_MISMATCH),
01208 errmsg("cannot convert Perl array to non-array type %s",
01209 format_type_be(typid))));
01210
01211 _sv_to_datum_finfo(elemtypid, &finfo, &typioparam);
01212
01213 memset(dims, 0, sizeof(dims));
01214 dims[0] = av_len((AV *) SvRV(src)) + 1;
01215
01216 astate = array_to_datum_internal((AV *) SvRV(src), NULL,
01217 &ndims, dims, 1,
01218 typid, elemtypid, typmod,
01219 &finfo, typioparam);
01220
01221 if (!astate)
01222 return PointerGetDatum(construct_empty_array(elemtypid));
01223
01224 for (i = 0; i < ndims; i++)
01225 lbs[i] = 1;
01226
01227 return makeMdArrayResult(astate, ndims, dims, lbs,
01228 CurrentMemoryContext, true);
01229 }
01230
01231
01232 static void
01233 _sv_to_datum_finfo(Oid typid, FmgrInfo *finfo, Oid *typioparam)
01234 {
01235 Oid typinput;
01236
01237
01238 getTypeInputInfo(typid,
01239 &typinput, typioparam);
01240 fmgr_info(typinput, finfo);
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 static Datum
01256 plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
01257 FunctionCallInfo fcinfo,
01258 FmgrInfo *finfo, Oid typioparam,
01259 bool *isnull)
01260 {
01261 FmgrInfo tmp;
01262
01263
01264 check_stack_depth();
01265
01266 *isnull = false;
01267
01268
01269
01270
01271
01272
01273 if (!sv || !SvOK(sv) || typid == VOIDOID)
01274 {
01275
01276 if (!finfo)
01277 {
01278 _sv_to_datum_finfo(typid, &tmp, &typioparam);
01279 finfo = &tmp;
01280 }
01281 *isnull = true;
01282
01283 return InputFunctionCall(finfo, NULL, typioparam, typmod);
01284 }
01285 else if (SvROK(sv))
01286 {
01287
01288 SV *sav = get_perl_array_ref(sv);
01289
01290 if (sav)
01291 {
01292
01293 return plperl_array_to_datum(sav, typid, typmod);
01294 }
01295 else if (SvTYPE(SvRV(sv)) == SVt_PVHV)
01296 {
01297
01298 Datum ret;
01299 TupleDesc td;
01300
01301 if (!type_is_rowtype(typid))
01302 ereport(ERROR,
01303 (errcode(ERRCODE_DATATYPE_MISMATCH),
01304 errmsg("cannot convert Perl hash to non-composite type %s",
01305 format_type_be(typid))));
01306
01307 td = lookup_rowtype_tupdesc_noerror(typid, typmod, true);
01308 if (td == NULL)
01309 {
01310
01311 if (fcinfo == NULL ||
01312 get_call_result_type(fcinfo, NULL, &td) != TYPEFUNC_COMPOSITE)
01313 ereport(ERROR,
01314 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01315 errmsg("function returning record called in context "
01316 "that cannot accept type record")));
01317 }
01318
01319 ret = plperl_hash_to_datum(sv, td);
01320
01321
01322 ReleaseTupleDesc(td);
01323
01324 return ret;
01325 }
01326
01327
01328 ereport(ERROR,
01329 (errcode(ERRCODE_DATATYPE_MISMATCH),
01330 errmsg("PL/Perl function must return reference to hash or array")));
01331 return (Datum) 0;
01332 }
01333 else
01334 {
01335
01336 Datum ret;
01337 char *str = sv2cstr(sv);
01338
01339
01340 if (!finfo)
01341 {
01342 _sv_to_datum_finfo(typid, &tmp, &typioparam);
01343 finfo = &tmp;
01344 }
01345
01346 ret = InputFunctionCall(finfo, str, typioparam, typmod);
01347 pfree(str);
01348
01349 return ret;
01350 }
01351 }
01352
01353
01354 char *
01355 plperl_sv_to_literal(SV *sv, char *fqtypename)
01356 {
01357 Datum str = CStringGetDatum(fqtypename);
01358 Oid typid = DirectFunctionCall1(regtypein, str);
01359 Oid typoutput;
01360 Datum datum;
01361 bool typisvarlena,
01362 isnull;
01363
01364 if (!OidIsValid(typid))
01365 elog(ERROR, "lookup failed for type %s", fqtypename);
01366
01367 datum = plperl_sv_to_datum(sv,
01368 typid, -1,
01369 NULL, NULL, InvalidOid,
01370 &isnull);
01371
01372 if (isnull)
01373 return NULL;
01374
01375 getTypeOutputInfo(typid,
01376 &typoutput, &typisvarlena);
01377
01378 return OidOutputFunctionCall(typoutput, datum);
01379 }
01380
01381
01382
01383
01384
01385
01386 static SV *
01387 plperl_ref_from_pg_array(Datum arg, Oid typid)
01388 {
01389 ArrayType *ar = DatumGetArrayTypeP(arg);
01390 Oid elementtype = ARR_ELEMTYPE(ar);
01391 int16 typlen;
01392 bool typbyval;
01393 char typalign,
01394 typdelim;
01395 Oid typioparam;
01396 Oid typoutputfunc;
01397 int i,
01398 nitems,
01399 *dims;
01400 plperl_array_info *info;
01401 SV *av;
01402 HV *hv;
01403
01404 info = palloc(sizeof(plperl_array_info));
01405
01406
01407 get_type_io_data(elementtype, IOFunc_output,
01408 &typlen, &typbyval, &typalign,
01409 &typdelim, &typioparam, &typoutputfunc);
01410
01411 perm_fmgr_info(typoutputfunc, &info->proc);
01412
01413 info->elem_is_rowtype = type_is_rowtype(elementtype);
01414
01415
01416 info->ndims = ARR_NDIM(ar);
01417 dims = ARR_DIMS(ar);
01418
01419 deconstruct_array(ar, elementtype, typlen, typbyval,
01420 typalign, &info->elements, &info->nulls,
01421 &nitems);
01422
01423
01424 info->nelems = palloc(sizeof(int) * info->ndims);
01425 info->nelems[0] = nitems;
01426 for (i = 1; i < info->ndims; i++)
01427 info->nelems[i] = info->nelems[i - 1] / dims[i - 1];
01428
01429 av = split_array(info, 0, nitems, 0);
01430
01431 hv = newHV();
01432 (void) hv_store(hv, "array", 5, av, 0);
01433 (void) hv_store(hv, "typeoid", 7, newSViv(typid), 0);
01434
01435 return sv_bless(newRV_noinc((SV *) hv),
01436 gv_stashpv("PostgreSQL::InServer::ARRAY", 0));
01437 }
01438
01439
01440
01441
01442 static SV *
01443 split_array(plperl_array_info *info, int first, int last, int nest)
01444 {
01445 int i;
01446 AV *result;
01447
01448
01449 check_stack_depth();
01450
01451
01452
01453
01454 if (nest >= info->ndims - 1)
01455 return make_array_ref(info, first, last);
01456
01457 result = newAV();
01458 for (i = first; i < last; i += info->nelems[nest + 1])
01459 {
01460
01461 SV *ref = split_array(info, i, i + info->nelems[nest + 1], nest + 1);
01462
01463 av_push(result, ref);
01464 }
01465 return newRV_noinc((SV *) result);
01466 }
01467
01468
01469
01470
01471
01472 static SV *
01473 make_array_ref(plperl_array_info *info, int first, int last)
01474 {
01475 int i;
01476 AV *result = newAV();
01477
01478 for (i = first; i < last; i++)
01479 {
01480 if (info->nulls[i])
01481 {
01482
01483
01484
01485
01486 av_push(result, newSV(0));
01487 }
01488 else
01489 {
01490 Datum itemvalue = info->elements[i];
01491
01492
01493 if (info->elem_is_rowtype)
01494 av_push(result, plperl_hash_from_datum(itemvalue));
01495 else
01496 {
01497 char *val = OutputFunctionCall(&info->proc, itemvalue);
01498
01499 av_push(result, cstr2sv(val));
01500 }
01501 }
01502 }
01503 return newRV_noinc((SV *) result);
01504 }
01505
01506
01507 static SV *
01508 plperl_trigger_build_args(FunctionCallInfo fcinfo)
01509 {
01510 TriggerData *tdata;
01511 TupleDesc tupdesc;
01512 int i;
01513 char *level;
01514 char *event;
01515 char *relid;
01516 char *when;
01517 HV *hv;
01518
01519 hv = newHV();
01520 hv_ksplit(hv, 12);
01521
01522 tdata = (TriggerData *) fcinfo->context;
01523 tupdesc = tdata->tg_relation->rd_att;
01524
01525 relid = DatumGetCString(
01526 DirectFunctionCall1(oidout,
01527 ObjectIdGetDatum(tdata->tg_relation->rd_id)
01528 )
01529 );
01530
01531 hv_store_string(hv, "name", cstr2sv(tdata->tg_trigger->tgname));
01532 hv_store_string(hv, "relid", cstr2sv(relid));
01533
01534 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
01535 {
01536 event = "INSERT";
01537 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
01538 hv_store_string(hv, "new",
01539 plperl_hash_from_tuple(tdata->tg_trigtuple,
01540 tupdesc));
01541 }
01542 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
01543 {
01544 event = "DELETE";
01545 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
01546 hv_store_string(hv, "old",
01547 plperl_hash_from_tuple(tdata->tg_trigtuple,
01548 tupdesc));
01549 }
01550 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
01551 {
01552 event = "UPDATE";
01553 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
01554 {
01555 hv_store_string(hv, "old",
01556 plperl_hash_from_tuple(tdata->tg_trigtuple,
01557 tupdesc));
01558 hv_store_string(hv, "new",
01559 plperl_hash_from_tuple(tdata->tg_newtuple,
01560 tupdesc));
01561 }
01562 }
01563 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
01564 event = "TRUNCATE";
01565 else
01566 event = "UNKNOWN";
01567
01568 hv_store_string(hv, "event", cstr2sv(event));
01569 hv_store_string(hv, "argc", newSViv(tdata->tg_trigger->tgnargs));
01570
01571 if (tdata->tg_trigger->tgnargs > 0)
01572 {
01573 AV *av = newAV();
01574
01575 av_extend(av, tdata->tg_trigger->tgnargs);
01576 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
01577 av_push(av, cstr2sv(tdata->tg_trigger->tgargs[i]));
01578 hv_store_string(hv, "args", newRV_noinc((SV *) av));
01579 }
01580
01581 hv_store_string(hv, "relname",
01582 cstr2sv(SPI_getrelname(tdata->tg_relation)));
01583
01584 hv_store_string(hv, "table_name",
01585 cstr2sv(SPI_getrelname(tdata->tg_relation)));
01586
01587 hv_store_string(hv, "table_schema",
01588 cstr2sv(SPI_getnspname(tdata->tg_relation)));
01589
01590 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
01591 when = "BEFORE";
01592 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
01593 when = "AFTER";
01594 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
01595 when = "INSTEAD OF";
01596 else
01597 when = "UNKNOWN";
01598 hv_store_string(hv, "when", cstr2sv(when));
01599
01600 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
01601 level = "ROW";
01602 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
01603 level = "STATEMENT";
01604 else
01605 level = "UNKNOWN";
01606 hv_store_string(hv, "level", cstr2sv(level));
01607
01608 return newRV_noinc((SV *) hv);
01609 }
01610
01611
01612
01613
01614 static HeapTuple
01615 plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
01616 {
01617 SV **svp;
01618 HV *hvNew;
01619 HE *he;
01620 HeapTuple rtup;
01621 int slotsused;
01622 int *modattrs;
01623 Datum *modvalues;
01624 char *modnulls;
01625
01626 TupleDesc tupdesc;
01627
01628 tupdesc = tdata->tg_relation->rd_att;
01629
01630 svp = hv_fetch_string(hvTD, "new");
01631 if (!svp)
01632 ereport(ERROR,
01633 (errcode(ERRCODE_UNDEFINED_COLUMN),
01634 errmsg("$_TD->{new} does not exist")));
01635 if (!SvOK(*svp) || !SvROK(*svp) || SvTYPE(SvRV(*svp)) != SVt_PVHV)
01636 ereport(ERROR,
01637 (errcode(ERRCODE_DATATYPE_MISMATCH),
01638 errmsg("$_TD->{new} is not a hash reference")));
01639 hvNew = (HV *) SvRV(*svp);
01640
01641 modattrs = palloc(tupdesc->natts * sizeof(int));
01642 modvalues = palloc(tupdesc->natts * sizeof(Datum));
01643 modnulls = palloc(tupdesc->natts * sizeof(char));
01644 slotsused = 0;
01645
01646 hv_iterinit(hvNew);
01647 while ((he = hv_iternext(hvNew)))
01648 {
01649 bool isnull;
01650 char *key = hek2cstr(he);
01651 SV *val = HeVAL(he);
01652 int attn = SPI_fnumber(tupdesc, key);
01653
01654 if (attn <= 0 || tupdesc->attrs[attn - 1]->attisdropped)
01655 ereport(ERROR,
01656 (errcode(ERRCODE_UNDEFINED_COLUMN),
01657 errmsg("Perl hash contains nonexistent column \"%s\"",
01658 key)));
01659
01660 modvalues[slotsused] = plperl_sv_to_datum(val,
01661 tupdesc->attrs[attn - 1]->atttypid,
01662 tupdesc->attrs[attn - 1]->atttypmod,
01663 NULL,
01664 NULL,
01665 InvalidOid,
01666 &isnull);
01667
01668 modnulls[slotsused] = isnull ? 'n' : ' ';
01669 modattrs[slotsused] = attn;
01670 slotsused++;
01671
01672 pfree(key);
01673 }
01674 hv_iterinit(hvNew);
01675
01676 rtup = SPI_modifytuple(tdata->tg_relation, otup, slotsused,
01677 modattrs, modvalues, modnulls);
01678
01679 pfree(modattrs);
01680 pfree(modvalues);
01681 pfree(modnulls);
01682
01683 if (rtup == NULL)
01684 elog(ERROR, "SPI_modifytuple failed: %s",
01685 SPI_result_code_string(SPI_result));
01686
01687 return rtup;
01688 }
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 PG_FUNCTION_INFO_V1(plperl_call_handler);
01701
01702 Datum
01703 plperl_call_handler(PG_FUNCTION_ARGS)
01704 {
01705 Datum retval;
01706 plperl_call_data *save_call_data = current_call_data;
01707 plperl_interp_desc *oldinterp = plperl_active_interp;
01708 plperl_call_data this_call_data;
01709
01710
01711 MemSet(&this_call_data, 0, sizeof(this_call_data));
01712 this_call_data.fcinfo = fcinfo;
01713
01714 PG_TRY();
01715 {
01716 current_call_data = &this_call_data;
01717 if (CALLED_AS_TRIGGER(fcinfo))
01718 retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
01719 else
01720 retval = plperl_func_handler(fcinfo);
01721 }
01722 PG_CATCH();
01723 {
01724 if (this_call_data.prodesc)
01725 decrement_prodesc_refcount(this_call_data.prodesc);
01726 current_call_data = save_call_data;
01727 activate_interpreter(oldinterp);
01728 PG_RE_THROW();
01729 }
01730 PG_END_TRY();
01731
01732 if (this_call_data.prodesc)
01733 decrement_prodesc_refcount(this_call_data.prodesc);
01734 current_call_data = save_call_data;
01735 activate_interpreter(oldinterp);
01736 return retval;
01737 }
01738
01739
01740
01741
01742 PG_FUNCTION_INFO_V1(plperl_inline_handler);
01743
01744 Datum
01745 plperl_inline_handler(PG_FUNCTION_ARGS)
01746 {
01747 InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0);
01748 FunctionCallInfoData fake_fcinfo;
01749 FmgrInfo flinfo;
01750 plperl_proc_desc desc;
01751 plperl_call_data *save_call_data = current_call_data;
01752 plperl_interp_desc *oldinterp = plperl_active_interp;
01753 plperl_call_data this_call_data;
01754 ErrorContextCallback pl_error_context;
01755
01756
01757 MemSet(&this_call_data, 0, sizeof(this_call_data));
01758
01759
01760 pl_error_context.callback = plperl_inline_callback;
01761 pl_error_context.previous = error_context_stack;
01762 pl_error_context.arg = (Datum) 0;
01763 error_context_stack = &pl_error_context;
01764
01765
01766
01767
01768
01769
01770 MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
01771 MemSet(&flinfo, 0, sizeof(flinfo));
01772 MemSet(&desc, 0, sizeof(desc));
01773 fake_fcinfo.flinfo = &flinfo;
01774 flinfo.fn_oid = InvalidOid;
01775 flinfo.fn_mcxt = CurrentMemoryContext;
01776
01777 desc.proname = "inline_code_block";
01778 desc.fn_readonly = false;
01779
01780 desc.lanpltrusted = codeblock->langIsTrusted;
01781
01782 desc.fn_retistuple = false;
01783 desc.fn_retisset = false;
01784 desc.fn_retisarray = false;
01785 desc.result_oid = VOIDOID;
01786 desc.nargs = 0;
01787 desc.reference = NULL;
01788
01789 this_call_data.fcinfo = &fake_fcinfo;
01790 this_call_data.prodesc = &desc;
01791
01792
01793 PG_TRY();
01794 {
01795 SV *perlret;
01796
01797 current_call_data = &this_call_data;
01798
01799 if (SPI_connect() != SPI_OK_CONNECT)
01800 elog(ERROR, "could not connect to SPI manager");
01801
01802 select_perl_context(desc.lanpltrusted);
01803
01804 plperl_create_sub(&desc, codeblock->source_text, 0);
01805
01806 if (!desc.reference)
01807 elog(ERROR, "could not create internal procedure for anonymous code block");
01808
01809 perlret = plperl_call_perl_func(&desc, &fake_fcinfo);
01810
01811 SvREFCNT_dec(perlret);
01812
01813 if (SPI_finish() != SPI_OK_FINISH)
01814 elog(ERROR, "SPI_finish() failed");
01815 }
01816 PG_CATCH();
01817 {
01818 if (desc.reference)
01819 SvREFCNT_dec(desc.reference);
01820 current_call_data = save_call_data;
01821 activate_interpreter(oldinterp);
01822 PG_RE_THROW();
01823 }
01824 PG_END_TRY();
01825
01826 if (desc.reference)
01827 SvREFCNT_dec(desc.reference);
01828
01829 current_call_data = save_call_data;
01830 activate_interpreter(oldinterp);
01831
01832 error_context_stack = pl_error_context.previous;
01833
01834 PG_RETURN_VOID();
01835 }
01836
01837
01838
01839
01840
01841
01842 PG_FUNCTION_INFO_V1(plperl_validator);
01843
01844 Datum
01845 plperl_validator(PG_FUNCTION_ARGS)
01846 {
01847 Oid funcoid = PG_GETARG_OID(0);
01848 HeapTuple tuple;
01849 Form_pg_proc proc;
01850 char functyptype;
01851 int numargs;
01852 Oid *argtypes;
01853 char **argnames;
01854 char *argmodes;
01855 bool istrigger = false;
01856 int i;
01857
01858
01859 tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
01860 if (!HeapTupleIsValid(tuple))
01861 elog(ERROR, "cache lookup failed for function %u", funcoid);
01862 proc = (Form_pg_proc) GETSTRUCT(tuple);
01863
01864 functyptype = get_typtype(proc->prorettype);
01865
01866
01867
01868 if (functyptype == TYPTYPE_PSEUDO)
01869 {
01870
01871 if (proc->prorettype == TRIGGEROID ||
01872 (proc->prorettype == OPAQUEOID && proc->pronargs == 0))
01873 istrigger = true;
01874 else if (proc->prorettype != RECORDOID &&
01875 proc->prorettype != VOIDOID)
01876 ereport(ERROR,
01877 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01878 errmsg("PL/Perl functions cannot return type %s",
01879 format_type_be(proc->prorettype))));
01880 }
01881
01882
01883 numargs = get_func_arg_info(tuple,
01884 &argtypes, &argnames, &argmodes);
01885 for (i = 0; i < numargs; i++)
01886 {
01887 if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO &&
01888 argtypes[i] != RECORDOID)
01889 ereport(ERROR,
01890 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01891 errmsg("PL/Perl functions cannot accept type %s",
01892 format_type_be(argtypes[i]))));
01893 }
01894
01895 ReleaseSysCache(tuple);
01896
01897
01898 if (check_function_bodies)
01899 {
01900 (void) compile_plperl_function(funcoid, istrigger);
01901 }
01902
01903
01904 PG_RETURN_VOID();
01905 }
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916 PG_FUNCTION_INFO_V1(plperlu_call_handler);
01917
01918 Datum
01919 plperlu_call_handler(PG_FUNCTION_ARGS)
01920 {
01921 return plperl_call_handler(fcinfo);
01922 }
01923
01924 PG_FUNCTION_INFO_V1(plperlu_inline_handler);
01925
01926 Datum
01927 plperlu_inline_handler(PG_FUNCTION_ARGS)
01928 {
01929 return plperl_inline_handler(fcinfo);
01930 }
01931
01932 PG_FUNCTION_INFO_V1(plperlu_validator);
01933
01934 Datum
01935 plperlu_validator(PG_FUNCTION_ARGS)
01936 {
01937 return plperl_validator(fcinfo);
01938 }
01939
01940
01941
01942
01943
01944
01945 static void
01946 plperl_create_sub(plperl_proc_desc *prodesc, char *s, Oid fn_oid)
01947 {
01948 dSP;
01949 char subname[NAMEDATALEN + 40];
01950 HV *pragma_hv = newHV();
01951 SV *subref = NULL;
01952 int count;
01953
01954 sprintf(subname, "%s__%u", prodesc->proname, fn_oid);
01955
01956 if (plperl_use_strict)
01957 hv_store_string(pragma_hv, "strict", (SV *) newAV());
01958
01959 ENTER;
01960 SAVETMPS;
01961 PUSHMARK(SP);
01962 EXTEND(SP, 4);
01963 PUSHs(sv_2mortal(cstr2sv(subname)));
01964 PUSHs(sv_2mortal(newRV_noinc((SV *) pragma_hv)));
01965
01966
01967
01968
01969
01970
01971 PUSHs(&PL_sv_no);
01972 PUSHs(sv_2mortal(cstr2sv(s)));
01973 PUTBACK;
01974
01975
01976
01977
01978
01979
01980 count = perl_call_pv("PostgreSQL::InServer::mkfunc",
01981 G_SCALAR | G_EVAL | G_KEEPERR);
01982 SPAGAIN;
01983
01984 if (count == 1)
01985 {
01986 SV *sub_rv = (SV *) POPs;
01987
01988 if (sub_rv && SvROK(sub_rv) && SvTYPE(SvRV(sub_rv)) == SVt_PVCV)
01989 {
01990 subref = newRV_inc(SvRV(sub_rv));
01991 }
01992 }
01993
01994 PUTBACK;
01995 FREETMPS;
01996 LEAVE;
01997
01998 if (SvTRUE(ERRSV))
01999 ereport(ERROR,
02000 (errcode(ERRCODE_SYNTAX_ERROR),
02001 errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
02002
02003 if (!subref)
02004 ereport(ERROR,
02005 (errmsg("didn't get a CODE reference from compiling function \"%s\"",
02006 prodesc->proname)));
02007
02008 prodesc->reference = subref;
02009
02010 return;
02011 }
02012
02013
02014
02015
02016
02017
02018 static void
02019 plperl_init_shared_libs(pTHX)
02020 {
02021 char *file = __FILE__;
02022
02023 newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
02024 newXS("PostgreSQL::InServer::Util::bootstrap",
02025 boot_PostgreSQL__InServer__Util, file);
02026
02027 }
02028
02029
02030 static SV *
02031 plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
02032 {
02033 dSP;
02034 SV *retval;
02035 int i;
02036 int count;
02037
02038 ENTER;
02039 SAVETMPS;
02040
02041 PUSHMARK(SP);
02042 EXTEND(sp, desc->nargs);
02043
02044 for (i = 0; i < desc->nargs; i++)
02045 {
02046 if (fcinfo->argnull[i])
02047 PUSHs(&PL_sv_undef);
02048 else if (desc->arg_is_rowtype[i])
02049 {
02050 SV *sv = plperl_hash_from_datum(fcinfo->arg[i]);
02051
02052 PUSHs(sv_2mortal(sv));
02053 }
02054 else
02055 {
02056 SV *sv;
02057
02058 if (OidIsValid(desc->arg_arraytype[i]))
02059 sv = plperl_ref_from_pg_array(fcinfo->arg[i], desc->arg_arraytype[i]);
02060 else
02061 {
02062 char *tmp;
02063
02064 tmp = OutputFunctionCall(&(desc->arg_out_func[i]),
02065 fcinfo->arg[i]);
02066 sv = cstr2sv(tmp);
02067 pfree(tmp);
02068 }
02069
02070 PUSHs(sv_2mortal(sv));
02071 }
02072 }
02073 PUTBACK;
02074
02075
02076 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
02077
02078 SPAGAIN;
02079
02080 if (count != 1)
02081 {
02082 PUTBACK;
02083 FREETMPS;
02084 LEAVE;
02085 elog(ERROR, "didn't get a return item from function");
02086 }
02087
02088 if (SvTRUE(ERRSV))
02089 {
02090 (void) POPs;
02091 PUTBACK;
02092 FREETMPS;
02093 LEAVE;
02094
02095 ereport(ERROR,
02096 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
02097 }
02098
02099 retval = newSVsv(POPs);
02100
02101 PUTBACK;
02102 FREETMPS;
02103 LEAVE;
02104
02105 return retval;
02106 }
02107
02108
02109 static SV *
02110 plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
02111 SV *td)
02112 {
02113 dSP;
02114 SV *retval,
02115 *TDsv;
02116 int i,
02117 count;
02118 Trigger *tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
02119
02120 ENTER;
02121 SAVETMPS;
02122
02123 TDsv = get_sv("main::_TD", 0);
02124 if (!TDsv)
02125 elog(ERROR, "couldn't fetch $_TD");
02126
02127 save_item(TDsv);
02128 sv_setsv(TDsv, td);
02129
02130 PUSHMARK(sp);
02131 EXTEND(sp, tg_trigger->tgnargs);
02132
02133 for (i = 0; i < tg_trigger->tgnargs; i++)
02134 PUSHs(sv_2mortal(cstr2sv(tg_trigger->tgargs[i])));
02135 PUTBACK;
02136
02137
02138 count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
02139
02140 SPAGAIN;
02141
02142 if (count != 1)
02143 {
02144 PUTBACK;
02145 FREETMPS;
02146 LEAVE;
02147 elog(ERROR, "didn't get a return item from trigger function");
02148 }
02149
02150 if (SvTRUE(ERRSV))
02151 {
02152 (void) POPs;
02153 PUTBACK;
02154 FREETMPS;
02155 LEAVE;
02156
02157 ereport(ERROR,
02158 (errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
02159 }
02160
02161 retval = newSVsv(POPs);
02162
02163 PUTBACK;
02164 FREETMPS;
02165 LEAVE;
02166
02167 return retval;
02168 }
02169
02170
02171 static Datum
02172 plperl_func_handler(PG_FUNCTION_ARGS)
02173 {
02174 plperl_proc_desc *prodesc;
02175 SV *perlret;
02176 Datum retval = 0;
02177 ReturnSetInfo *rsi;
02178 ErrorContextCallback pl_error_context;
02179
02180 if (SPI_connect() != SPI_OK_CONNECT)
02181 elog(ERROR, "could not connect to SPI manager");
02182
02183 prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
02184 current_call_data->prodesc = prodesc;
02185 increment_prodesc_refcount(prodesc);
02186
02187
02188 pl_error_context.callback = plperl_exec_callback;
02189 pl_error_context.previous = error_context_stack;
02190 pl_error_context.arg = prodesc->proname;
02191 error_context_stack = &pl_error_context;
02192
02193 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
02194
02195 if (prodesc->fn_retisset)
02196 {
02197
02198 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
02199 (rsi->allowedModes & SFRM_Materialize) == 0 ||
02200 rsi->expectedDesc == NULL)
02201 ereport(ERROR,
02202 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02203 errmsg("set-valued function called in context that "
02204 "cannot accept a set")));
02205 }
02206
02207 activate_interpreter(prodesc->interp);
02208
02209 perlret = plperl_call_perl_func(prodesc, fcinfo);
02210
02211
02212
02213
02214
02215
02216
02217 if (SPI_finish() != SPI_OK_FINISH)
02218 elog(ERROR, "SPI_finish() failed");
02219
02220 if (prodesc->fn_retisset)
02221 {
02222 SV *sav;
02223
02224
02225
02226
02227
02228
02229
02230 sav = get_perl_array_ref(perlret);
02231 if (sav)
02232 {
02233 int i = 0;
02234 SV **svp = 0;
02235 AV *rav = (AV *) SvRV(sav);
02236
02237 while ((svp = av_fetch(rav, i, FALSE)) != NULL)
02238 {
02239 plperl_return_next(*svp);
02240 i++;
02241 }
02242 }
02243 else if (SvOK(perlret))
02244 {
02245 ereport(ERROR,
02246 (errcode(ERRCODE_DATATYPE_MISMATCH),
02247 errmsg("set-returning PL/Perl function must return "
02248 "reference to array or use return_next")));
02249 }
02250
02251 rsi->returnMode = SFRM_Materialize;
02252 if (current_call_data->tuple_store)
02253 {
02254 rsi->setResult = current_call_data->tuple_store;
02255 rsi->setDesc = current_call_data->ret_tdesc;
02256 }
02257 retval = (Datum) 0;
02258 }
02259 else
02260 {
02261 retval = plperl_sv_to_datum(perlret,
02262 prodesc->result_oid,
02263 -1,
02264 fcinfo,
02265 &prodesc->result_in_func,
02266 prodesc->result_typioparam,
02267 &fcinfo->isnull);
02268
02269 if (fcinfo->isnull && rsi && IsA(rsi, ReturnSetInfo))
02270 rsi->isDone = ExprEndResult;
02271 }
02272
02273
02274 error_context_stack = pl_error_context.previous;
02275
02276 SvREFCNT_dec(perlret);
02277
02278 return retval;
02279 }
02280
02281
02282 static Datum
02283 plperl_trigger_handler(PG_FUNCTION_ARGS)
02284 {
02285 plperl_proc_desc *prodesc;
02286 SV *perlret;
02287 Datum retval;
02288 SV *svTD;
02289 HV *hvTD;
02290 ErrorContextCallback pl_error_context;
02291
02292
02293 if (SPI_connect() != SPI_OK_CONNECT)
02294 elog(ERROR, "could not connect to SPI manager");
02295
02296
02297 prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true);
02298 current_call_data->prodesc = prodesc;
02299 increment_prodesc_refcount(prodesc);
02300
02301
02302 pl_error_context.callback = plperl_exec_callback;
02303 pl_error_context.previous = error_context_stack;
02304 pl_error_context.arg = prodesc->proname;
02305 error_context_stack = &pl_error_context;
02306
02307 activate_interpreter(prodesc->interp);
02308
02309 svTD = plperl_trigger_build_args(fcinfo);
02310 perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
02311 hvTD = (HV *) SvRV(svTD);
02312
02313
02314
02315
02316
02317
02318
02319 if (SPI_finish() != SPI_OK_FINISH)
02320 elog(ERROR, "SPI_finish() failed");
02321
02322 if (perlret == NULL || !SvOK(perlret))
02323 {
02324
02325 TriggerData *trigdata = ((TriggerData *) fcinfo->context);
02326
02327 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
02328 retval = (Datum) trigdata->tg_trigtuple;
02329 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
02330 retval = (Datum) trigdata->tg_newtuple;
02331 else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
02332 retval = (Datum) trigdata->tg_trigtuple;
02333 else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
02334 retval = (Datum) trigdata->tg_trigtuple;
02335 else
02336 retval = (Datum) 0;
02337 }
02338 else
02339 {
02340 HeapTuple trv;
02341 char *tmp;
02342
02343 tmp = sv2cstr(perlret);
02344
02345 if (pg_strcasecmp(tmp, "SKIP") == 0)
02346 trv = NULL;
02347 else if (pg_strcasecmp(tmp, "MODIFY") == 0)
02348 {
02349 TriggerData *trigdata = (TriggerData *) fcinfo->context;
02350
02351 if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
02352 trv = plperl_modify_tuple(hvTD, trigdata,
02353 trigdata->tg_trigtuple);
02354 else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
02355 trv = plperl_modify_tuple(hvTD, trigdata,
02356 trigdata->tg_newtuple);
02357 else
02358 {
02359 ereport(WARNING,
02360 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
02361 errmsg("ignoring modified row in DELETE trigger")));
02362 trv = NULL;
02363 }
02364 }
02365 else
02366 {
02367 ereport(ERROR,
02368 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
02369 errmsg("result of PL/Perl trigger function must be undef, "
02370 "\"SKIP\", or \"MODIFY\"")));
02371 trv = NULL;
02372 }
02373 retval = PointerGetDatum(trv);
02374 pfree(tmp);
02375 }
02376
02377
02378 error_context_stack = pl_error_context.previous;
02379
02380 SvREFCNT_dec(svTD);
02381 if (perlret)
02382 SvREFCNT_dec(perlret);
02383
02384 return retval;
02385 }
02386
02387
02388 static bool
02389 validate_plperl_function(plperl_proc_ptr *proc_ptr, HeapTuple procTup)
02390 {
02391 if (proc_ptr && proc_ptr->proc_ptr)
02392 {
02393 plperl_proc_desc *prodesc = proc_ptr->proc_ptr;
02394 bool uptodate;
02395
02396
02397
02398
02399
02400
02401 uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetXmin(procTup->t_data) &&
02402 ItemPointerEquals(&prodesc->fn_tid, &procTup->t_self));
02403
02404 if (uptodate)
02405 return true;
02406
02407
02408 proc_ptr->proc_ptr = NULL;
02409
02410 decrement_prodesc_refcount(prodesc);
02411 }
02412
02413 return false;
02414 }
02415
02416
02417 static void
02418 free_plperl_function(plperl_proc_desc *prodesc)
02419 {
02420 Assert(prodesc->refcount <= 0);
02421
02422 if (prodesc->reference)
02423 {
02424 plperl_interp_desc *oldinterp = plperl_active_interp;
02425
02426 activate_interpreter(prodesc->interp);
02427 SvREFCNT_dec(prodesc->reference);
02428 activate_interpreter(oldinterp);
02429 }
02430
02431
02432 if (prodesc->proname)
02433 free(prodesc->proname);
02434 free(prodesc);
02435 }
02436
02437
02438 static plperl_proc_desc *
02439 compile_plperl_function(Oid fn_oid, bool is_trigger)
02440 {
02441 HeapTuple procTup;
02442 Form_pg_proc procStruct;
02443 plperl_proc_key proc_key;
02444 plperl_proc_ptr *proc_ptr;
02445 plperl_proc_desc *prodesc = NULL;
02446 int i;
02447 plperl_interp_desc *oldinterp = plperl_active_interp;
02448 ErrorContextCallback plperl_error_context;
02449
02450
02451 procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
02452 if (!HeapTupleIsValid(procTup))
02453 elog(ERROR, "cache lookup failed for function %u", fn_oid);
02454 procStruct = (Form_pg_proc) GETSTRUCT(procTup);
02455
02456
02457 plperl_error_context.callback = plperl_compile_callback;
02458 plperl_error_context.previous = error_context_stack;
02459 plperl_error_context.arg = NameStr(procStruct->proname);
02460 error_context_stack = &plperl_error_context;
02461
02462
02463 proc_key.proc_id = fn_oid;
02464 proc_key.is_trigger = is_trigger;
02465 proc_key.user_id = GetUserId();
02466
02467 proc_ptr = hash_search(plperl_proc_hash, &proc_key,
02468 HASH_FIND, NULL);
02469
02470 if (validate_plperl_function(proc_ptr, procTup))
02471 prodesc = proc_ptr->proc_ptr;
02472 else
02473 {
02474
02475 proc_key.user_id = InvalidOid;
02476 proc_ptr = hash_search(plperl_proc_hash, &proc_key,
02477 HASH_FIND, NULL);
02478 if (validate_plperl_function(proc_ptr, procTup))
02479 prodesc = proc_ptr->proc_ptr;
02480 }
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490 if (prodesc == NULL)
02491 {
02492 HeapTuple langTup;
02493 HeapTuple typeTup;
02494 Form_pg_language langStruct;
02495 Form_pg_type typeStruct;
02496 Datum prosrcdatum;
02497 bool isnull;
02498 char *proc_source;
02499
02500
02501
02502
02503 prodesc = (plperl_proc_desc *) malloc(sizeof(plperl_proc_desc));
02504 if (prodesc == NULL)
02505 ereport(ERROR,
02506 (errcode(ERRCODE_OUT_OF_MEMORY),
02507 errmsg("out of memory")));
02508
02509 MemSet(prodesc, 0, sizeof(plperl_proc_desc));
02510
02511 prodesc->proname = strdup(NameStr(procStruct->proname));
02512 if (prodesc->proname == NULL)
02513 {
02514 free_plperl_function(prodesc);
02515 ereport(ERROR,
02516 (errcode(ERRCODE_OUT_OF_MEMORY),
02517 errmsg("out of memory")));
02518 }
02519 prodesc->fn_xmin = HeapTupleHeaderGetXmin(procTup->t_data);
02520 prodesc->fn_tid = procTup->t_self;
02521
02522
02523 prodesc->fn_readonly =
02524 (procStruct->provolatile != PROVOLATILE_VOLATILE);
02525
02526
02527
02528
02529 langTup = SearchSysCache1(LANGOID,
02530 ObjectIdGetDatum(procStruct->prolang));
02531 if (!HeapTupleIsValid(langTup))
02532 {
02533 free_plperl_function(prodesc);
02534 elog(ERROR, "cache lookup failed for language %u",
02535 procStruct->prolang);
02536 }
02537 langStruct = (Form_pg_language) GETSTRUCT(langTup);
02538 prodesc->lanpltrusted = langStruct->lanpltrusted;
02539 ReleaseSysCache(langTup);
02540
02541
02542
02543
02544
02545 if (!is_trigger)
02546 {
02547 typeTup =
02548 SearchSysCache1(TYPEOID,
02549 ObjectIdGetDatum(procStruct->prorettype));
02550 if (!HeapTupleIsValid(typeTup))
02551 {
02552 free_plperl_function(prodesc);
02553 elog(ERROR, "cache lookup failed for type %u",
02554 procStruct->prorettype);
02555 }
02556 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
02557
02558
02559 if (typeStruct->typtype == TYPTYPE_PSEUDO)
02560 {
02561 if (procStruct->prorettype == VOIDOID ||
02562 procStruct->prorettype == RECORDOID)
02563 ;
02564 else if (procStruct->prorettype == TRIGGEROID)
02565 {
02566 free_plperl_function(prodesc);
02567 ereport(ERROR,
02568 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02569 errmsg("trigger functions can only be called "
02570 "as triggers")));
02571 }
02572 else
02573 {
02574 free_plperl_function(prodesc);
02575 ereport(ERROR,
02576 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02577 errmsg("PL/Perl functions cannot return type %s",
02578 format_type_be(procStruct->prorettype))));
02579 }
02580 }
02581
02582 prodesc->result_oid = procStruct->prorettype;
02583 prodesc->fn_retisset = procStruct->proretset;
02584 prodesc->fn_retistuple = (procStruct->prorettype == RECORDOID ||
02585 typeStruct->typtype == TYPTYPE_COMPOSITE);
02586
02587 prodesc->fn_retisarray =
02588 (typeStruct->typlen == -1 && typeStruct->typelem);
02589
02590 perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func));
02591 prodesc->result_typioparam = getTypeIOParam(typeTup);
02592
02593 ReleaseSysCache(typeTup);
02594 }
02595
02596
02597
02598
02599
02600 if (!is_trigger)
02601 {
02602 prodesc->nargs = procStruct->pronargs;
02603 for (i = 0; i < prodesc->nargs; i++)
02604 {
02605 typeTup = SearchSysCache1(TYPEOID,
02606 ObjectIdGetDatum(procStruct->proargtypes.values[i]));
02607 if (!HeapTupleIsValid(typeTup))
02608 {
02609 free_plperl_function(prodesc);
02610 elog(ERROR, "cache lookup failed for type %u",
02611 procStruct->proargtypes.values[i]);
02612 }
02613 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
02614
02615
02616 if (typeStruct->typtype == TYPTYPE_PSEUDO &&
02617 procStruct->proargtypes.values[i] != RECORDOID)
02618 {
02619 free_plperl_function(prodesc);
02620 ereport(ERROR,
02621 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
02622 errmsg("PL/Perl functions cannot accept type %s",
02623 format_type_be(procStruct->proargtypes.values[i]))));
02624 }
02625
02626 if (typeStruct->typtype == TYPTYPE_COMPOSITE ||
02627 procStruct->proargtypes.values[i] == RECORDOID)
02628 prodesc->arg_is_rowtype[i] = true;
02629 else
02630 {
02631 prodesc->arg_is_rowtype[i] = false;
02632 perm_fmgr_info(typeStruct->typoutput,
02633 &(prodesc->arg_out_func[i]));
02634 }
02635
02636
02637 if (typeStruct->typelem != 0 && typeStruct->typlen == -1)
02638 prodesc->arg_arraytype[i] = procStruct->proargtypes.values[i];
02639 else
02640 prodesc->arg_arraytype[i] = InvalidOid;
02641
02642 ReleaseSysCache(typeTup);
02643 }
02644 }
02645
02646
02647
02648
02649
02650
02651 prosrcdatum = SysCacheGetAttr(PROCOID, procTup,
02652 Anum_pg_proc_prosrc, &isnull);
02653 if (isnull)
02654 elog(ERROR, "null prosrc");
02655 proc_source = TextDatumGetCString(prosrcdatum);
02656
02657
02658
02659
02660
02661 select_perl_context(prodesc->lanpltrusted);
02662
02663 prodesc->interp = plperl_active_interp;
02664
02665 plperl_create_sub(prodesc, proc_source, fn_oid);
02666
02667 activate_interpreter(oldinterp);
02668
02669 pfree(proc_source);
02670 if (!prodesc->reference)
02671 {
02672 free_plperl_function(prodesc);
02673 elog(ERROR, "could not create PL/Perl internal procedure");
02674 }
02675
02676
02677
02678
02679 proc_key.user_id = prodesc->lanpltrusted ? GetUserId() : InvalidOid;
02680
02681 proc_ptr = hash_search(plperl_proc_hash, &proc_key,
02682 HASH_ENTER, NULL);
02683 proc_ptr->proc_ptr = prodesc;
02684 increment_prodesc_refcount(prodesc);
02685 }
02686
02687
02688 error_context_stack = plperl_error_context.previous;
02689
02690 ReleaseSysCache(procTup);
02691
02692 return prodesc;
02693 }
02694
02695
02696 static SV *
02697 plperl_hash_from_datum(Datum attr)
02698 {
02699 HeapTupleHeader td;
02700 Oid tupType;
02701 int32 tupTypmod;
02702 TupleDesc tupdesc;
02703 HeapTupleData tmptup;
02704 SV *sv;
02705
02706 td = DatumGetHeapTupleHeader(attr);
02707
02708
02709 tupType = HeapTupleHeaderGetTypeId(td);
02710 tupTypmod = HeapTupleHeaderGetTypMod(td);
02711 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
02712
02713
02714 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
02715 tmptup.t_data = td;
02716
02717 sv = plperl_hash_from_tuple(&tmptup, tupdesc);
02718 ReleaseTupleDesc(tupdesc);
02719
02720 return sv;
02721 }
02722
02723
02724 static SV *
02725 plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
02726 {
02727 HV *hv;
02728 int i;
02729
02730
02731 check_stack_depth();
02732
02733 hv = newHV();
02734 hv_ksplit(hv, tupdesc->natts);
02735
02736 for (i = 0; i < tupdesc->natts; i++)
02737 {
02738 Datum attr;
02739 bool isnull,
02740 typisvarlena;
02741 char *attname;
02742 Oid typoutput;
02743
02744 if (tupdesc->attrs[i]->attisdropped)
02745 continue;
02746
02747 attname = NameStr(tupdesc->attrs[i]->attname);
02748 attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
02749
02750 if (isnull)
02751 {
02752
02753
02754
02755
02756
02757 hv_store_string(hv, attname, newSV(0));
02758 continue;
02759 }
02760
02761 if (type_is_rowtype(tupdesc->attrs[i]->atttypid))
02762 {
02763 SV *sv = plperl_hash_from_datum(attr);
02764
02765 hv_store_string(hv, attname, sv);
02766 }
02767 else
02768 {
02769 SV *sv;
02770
02771 if (OidIsValid(get_base_element_type(tupdesc->attrs[i]->atttypid)))
02772 sv = plperl_ref_from_pg_array(attr, tupdesc->attrs[i]->atttypid);
02773 else
02774 {
02775 char *outputstr;
02776
02777
02778 getTypeOutputInfo(tupdesc->attrs[i]->atttypid,
02779 &typoutput, &typisvarlena);
02780
02781 outputstr = OidOutputFunctionCall(typoutput, attr);
02782 sv = cstr2sv(outputstr);
02783 pfree(outputstr);
02784 }
02785
02786 hv_store_string(hv, attname, sv);
02787 }
02788 }
02789 return newRV_noinc((SV *) hv);
02790 }
02791
02792
02793 static void
02794 check_spi_usage_allowed()
02795 {
02796
02797 if (plperl_ending)
02798 {
02799
02800 croak("SPI functions can not be used in END blocks");
02801 }
02802 }
02803
02804
02805 HV *
02806 plperl_spi_exec(char *query, int limit)
02807 {
02808 HV *ret_hv;
02809
02810
02811
02812
02813
02814 MemoryContext oldcontext = CurrentMemoryContext;
02815 ResourceOwner oldowner = CurrentResourceOwner;
02816
02817 check_spi_usage_allowed();
02818
02819 BeginInternalSubTransaction(NULL);
02820
02821 MemoryContextSwitchTo(oldcontext);
02822
02823 PG_TRY();
02824 {
02825 int spi_rv;
02826
02827 pg_verifymbstr(query, strlen(query), false);
02828
02829 spi_rv = SPI_execute(query, current_call_data->prodesc->fn_readonly,
02830 limit);
02831 ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
02832 spi_rv);
02833
02834
02835 ReleaseCurrentSubTransaction();
02836 MemoryContextSwitchTo(oldcontext);
02837 CurrentResourceOwner = oldowner;
02838
02839
02840
02841
02842
02843 SPI_restore_connection();
02844 }
02845 PG_CATCH();
02846 {
02847 ErrorData *edata;
02848
02849
02850 MemoryContextSwitchTo(oldcontext);
02851 edata = CopyErrorData();
02852 FlushErrorState();
02853
02854
02855 RollbackAndReleaseCurrentSubTransaction();
02856 MemoryContextSwitchTo(oldcontext);
02857 CurrentResourceOwner = oldowner;
02858
02859
02860
02861
02862
02863
02864 SPI_restore_connection();
02865
02866
02867 croak("%s", edata->message);
02868
02869
02870 return NULL;
02871 }
02872 PG_END_TRY();
02873
02874 return ret_hv;
02875 }
02876
02877
02878 static HV *
02879 plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
02880 int status)
02881 {
02882 HV *result;
02883
02884 check_spi_usage_allowed();
02885
02886 result = newHV();
02887
02888 hv_store_string(result, "status",
02889 cstr2sv(SPI_result_code_string(status)));
02890 hv_store_string(result, "processed",
02891 newSViv(processed));
02892
02893 if (status > 0 && tuptable)
02894 {
02895 AV *rows;
02896 SV *row;
02897 int i;
02898
02899 rows = newAV();
02900 av_extend(rows, processed);
02901 for (i = 0; i < processed; i++)
02902 {
02903 row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc);
02904 av_push(rows, row);
02905 }
02906 hv_store_string(result, "rows",
02907 newRV_noinc((SV *) rows));
02908 }
02909
02910 SPI_freetuptable(tuptable);
02911
02912 return result;
02913 }
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924 void
02925 plperl_return_next(SV *sv)
02926 {
02927 plperl_proc_desc *prodesc;
02928 FunctionCallInfo fcinfo;
02929 ReturnSetInfo *rsi;
02930 MemoryContext old_cxt;
02931
02932 if (!sv)
02933 return;
02934
02935 prodesc = current_call_data->prodesc;
02936 fcinfo = current_call_data->fcinfo;
02937 rsi = (ReturnSetInfo *) fcinfo->resultinfo;
02938
02939 if (!prodesc->fn_retisset)
02940 ereport(ERROR,
02941 (errcode(ERRCODE_SYNTAX_ERROR),
02942 errmsg("cannot use return_next in a non-SETOF function")));
02943
02944 if (!current_call_data->ret_tdesc)
02945 {
02946 TupleDesc tupdesc;
02947
02948 Assert(!current_call_data->tuple_store);
02949
02950
02951
02952
02953
02954 if (prodesc->fn_retistuple)
02955 (void) get_call_result_type(fcinfo, NULL, &tupdesc);
02956 else
02957 tupdesc = rsi->expectedDesc;
02958
02959
02960
02961
02962
02963 old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
02964
02965 current_call_data->ret_tdesc = CreateTupleDescCopy(tupdesc);
02966 current_call_data->tuple_store =
02967 tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
02968 false, work_mem);
02969
02970 MemoryContextSwitchTo(old_cxt);
02971 }
02972
02973
02974
02975
02976
02977
02978
02979 if (!current_call_data->tmp_cxt)
02980 {
02981 current_call_data->tmp_cxt =
02982 AllocSetContextCreate(CurrentMemoryContext,
02983 "PL/Perl return_next temporary cxt",
02984 ALLOCSET_DEFAULT_MINSIZE,
02985 ALLOCSET_DEFAULT_INITSIZE,
02986 ALLOCSET_DEFAULT_MAXSIZE);
02987 }
02988
02989 old_cxt = MemoryContextSwitchTo(current_call_data->tmp_cxt);
02990
02991 if (prodesc->fn_retistuple)
02992 {
02993 HeapTuple tuple;
02994
02995 if (!(SvOK(sv) && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV))
02996 ereport(ERROR,
02997 (errcode(ERRCODE_DATATYPE_MISMATCH),
02998 errmsg("SETOF-composite-returning PL/Perl function "
02999 "must call return_next with reference to hash")));
03000
03001 tuple = plperl_build_tuple_result((HV *) SvRV(sv),
03002 current_call_data->ret_tdesc);
03003 tuplestore_puttuple(current_call_data->tuple_store, tuple);
03004 }
03005 else
03006 {
03007 Datum ret;
03008 bool isNull;
03009
03010 ret = plperl_sv_to_datum(sv,
03011 prodesc->result_oid,
03012 -1,
03013 fcinfo,
03014 &prodesc->result_in_func,
03015 prodesc->result_typioparam,
03016 &isNull);
03017
03018 tuplestore_putvalues(current_call_data->tuple_store,
03019 current_call_data->ret_tdesc,
03020 &ret, &isNull);
03021 }
03022
03023 MemoryContextSwitchTo(old_cxt);
03024 MemoryContextReset(current_call_data->tmp_cxt);
03025 }
03026
03027
03028 SV *
03029 plperl_spi_query(char *query)
03030 {
03031 SV *cursor;
03032
03033
03034
03035
03036
03037 MemoryContext oldcontext = CurrentMemoryContext;
03038 ResourceOwner oldowner = CurrentResourceOwner;
03039
03040 check_spi_usage_allowed();
03041
03042 BeginInternalSubTransaction(NULL);
03043
03044 MemoryContextSwitchTo(oldcontext);
03045
03046 PG_TRY();
03047 {
03048 SPIPlanPtr plan;
03049 Portal portal;
03050
03051
03052 pg_verifymbstr(query, strlen(query), false);
03053
03054
03055 plan = SPI_prepare(query, 0, NULL);
03056 if (plan == NULL)
03057 elog(ERROR, "SPI_prepare() failed:%s",
03058 SPI_result_code_string(SPI_result));
03059
03060 portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
03061 SPI_freeplan(plan);
03062 if (portal == NULL)
03063 elog(ERROR, "SPI_cursor_open() failed:%s",
03064 SPI_result_code_string(SPI_result));
03065 cursor = cstr2sv(portal->name);
03066
03067
03068 ReleaseCurrentSubTransaction();
03069 MemoryContextSwitchTo(oldcontext);
03070 CurrentResourceOwner = oldowner;
03071
03072
03073
03074
03075
03076 SPI_restore_connection();
03077 }
03078 PG_CATCH();
03079 {
03080 ErrorData *edata;
03081
03082
03083 MemoryContextSwitchTo(oldcontext);
03084 edata = CopyErrorData();
03085 FlushErrorState();
03086
03087
03088 RollbackAndReleaseCurrentSubTransaction();
03089 MemoryContextSwitchTo(oldcontext);
03090 CurrentResourceOwner = oldowner;
03091
03092
03093
03094
03095
03096
03097 SPI_restore_connection();
03098
03099
03100 croak("%s", edata->message);
03101
03102
03103 return NULL;
03104 }
03105 PG_END_TRY();
03106
03107 return cursor;
03108 }
03109
03110
03111 SV *
03112 plperl_spi_fetchrow(char *cursor)
03113 {
03114 SV *row;
03115
03116
03117
03118
03119
03120 MemoryContext oldcontext = CurrentMemoryContext;
03121 ResourceOwner oldowner = CurrentResourceOwner;
03122
03123 check_spi_usage_allowed();
03124
03125 BeginInternalSubTransaction(NULL);
03126
03127 MemoryContextSwitchTo(oldcontext);
03128
03129 PG_TRY();
03130 {
03131 Portal p = SPI_cursor_find(cursor);
03132
03133 if (!p)
03134 {
03135 row = &PL_sv_undef;
03136 }
03137 else
03138 {
03139 SPI_cursor_fetch(p, true, 1);
03140 if (SPI_processed == 0)
03141 {
03142 SPI_cursor_close(p);
03143 row = &PL_sv_undef;
03144 }
03145 else
03146 {
03147 row = plperl_hash_from_tuple(SPI_tuptable->vals[0],
03148 SPI_tuptable->tupdesc);
03149 }
03150 SPI_freetuptable(SPI_tuptable);
03151 }
03152
03153
03154 ReleaseCurrentSubTransaction();
03155 MemoryContextSwitchTo(oldcontext);
03156 CurrentResourceOwner = oldowner;
03157
03158
03159
03160
03161
03162 SPI_restore_connection();
03163 }
03164 PG_CATCH();
03165 {
03166 ErrorData *edata;
03167
03168
03169 MemoryContextSwitchTo(oldcontext);
03170 edata = CopyErrorData();
03171 FlushErrorState();
03172
03173
03174 RollbackAndReleaseCurrentSubTransaction();
03175 MemoryContextSwitchTo(oldcontext);
03176 CurrentResourceOwner = oldowner;
03177
03178
03179
03180
03181
03182
03183 SPI_restore_connection();
03184
03185
03186 croak("%s", edata->message);
03187
03188
03189 return NULL;
03190 }
03191 PG_END_TRY();
03192
03193 return row;
03194 }
03195
03196 void
03197 plperl_spi_cursor_close(char *cursor)
03198 {
03199 Portal p;
03200
03201 check_spi_usage_allowed();
03202
03203 p = SPI_cursor_find(cursor);
03204
03205 if (p)
03206 SPI_cursor_close(p);
03207 }
03208
03209 SV *
03210 plperl_spi_prepare(char *query, int argc, SV **argv)
03211 {
03212 volatile SPIPlanPtr plan = NULL;
03213 volatile MemoryContext plan_cxt = NULL;
03214 plperl_query_desc *volatile qdesc = NULL;
03215 plperl_query_entry *volatile hash_entry = NULL;
03216 MemoryContext oldcontext = CurrentMemoryContext;
03217 ResourceOwner oldowner = CurrentResourceOwner;
03218 MemoryContext work_cxt;
03219 bool found;
03220 int i;
03221
03222 check_spi_usage_allowed();
03223
03224 BeginInternalSubTransaction(NULL);
03225 MemoryContextSwitchTo(oldcontext);
03226
03227 PG_TRY();
03228 {
03229 CHECK_FOR_INTERRUPTS();
03230
03231
03232
03233
03234
03235
03236
03237 plan_cxt = AllocSetContextCreate(TopMemoryContext,
03238 "PL/Perl spi_prepare query",
03239 ALLOCSET_SMALL_MINSIZE,
03240 ALLOCSET_SMALL_INITSIZE,
03241 ALLOCSET_SMALL_MAXSIZE);
03242 MemoryContextSwitchTo(plan_cxt);
03243 qdesc = (plperl_query_desc *) palloc0(sizeof(plperl_query_desc));
03244 snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
03245 qdesc->plan_cxt = plan_cxt;
03246 qdesc->nargs = argc;
03247 qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
03248 qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
03249 qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
03250 MemoryContextSwitchTo(oldcontext);
03251
03252
03253
03254
03255
03256 work_cxt = AllocSetContextCreate(CurrentMemoryContext,
03257 "PL/Perl spi_prepare workspace",
03258 ALLOCSET_DEFAULT_MINSIZE,
03259 ALLOCSET_DEFAULT_INITSIZE,
03260 ALLOCSET_DEFAULT_MAXSIZE);
03261 MemoryContextSwitchTo(work_cxt);
03262
03263
03264
03265
03266
03267
03268 for (i = 0; i < argc; i++)
03269 {
03270 Oid typId,
03271 typInput,
03272 typIOParam;
03273 int32 typmod;
03274 char *typstr;
03275
03276 typstr = sv2cstr(argv[i]);
03277 parseTypeString(typstr, &typId, &typmod);
03278 pfree(typstr);
03279
03280 getTypeInputInfo(typId, &typInput, &typIOParam);
03281
03282 qdesc->argtypes[i] = typId;
03283 fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
03284 qdesc->argtypioparams[i] = typIOParam;
03285 }
03286
03287
03288 pg_verifymbstr(query, strlen(query), false);
03289
03290
03291
03292
03293 plan = SPI_prepare(query, argc, qdesc->argtypes);
03294
03295 if (plan == NULL)
03296 elog(ERROR, "SPI_prepare() failed:%s",
03297 SPI_result_code_string(SPI_result));
03298
03299
03300
03301
03302
03303 if (SPI_keepplan(plan))
03304 elog(ERROR, "SPI_keepplan() failed");
03305 qdesc->plan = plan;
03306
03307
03308
03309
03310 hash_entry = hash_search(plperl_active_interp->query_hash,
03311 qdesc->qname,
03312 HASH_ENTER, &found);
03313 hash_entry->query_data = qdesc;
03314
03315
03316 MemoryContextDelete(work_cxt);
03317
03318
03319 ReleaseCurrentSubTransaction();
03320 MemoryContextSwitchTo(oldcontext);
03321 CurrentResourceOwner = oldowner;
03322
03323
03324
03325
03326
03327 SPI_restore_connection();
03328 }
03329 PG_CATCH();
03330 {
03331 ErrorData *edata;
03332
03333
03334 MemoryContextSwitchTo(oldcontext);
03335 edata = CopyErrorData();
03336 FlushErrorState();
03337
03338
03339 if (hash_entry)
03340 hash_search(plperl_active_interp->query_hash,
03341 qdesc->qname,
03342 HASH_REMOVE, NULL);
03343 if (plan_cxt)
03344 MemoryContextDelete(plan_cxt);
03345 if (plan)
03346 SPI_freeplan(plan);
03347
03348
03349 RollbackAndReleaseCurrentSubTransaction();
03350 MemoryContextSwitchTo(oldcontext);
03351 CurrentResourceOwner = oldowner;
03352
03353
03354
03355
03356
03357
03358 SPI_restore_connection();
03359
03360
03361 croak("%s", edata->message);
03362
03363
03364 return NULL;
03365 }
03366 PG_END_TRY();
03367
03368
03369
03370
03371 return cstr2sv(qdesc->qname);
03372 }
03373
03374 HV *
03375 plperl_spi_exec_prepared(char *query, HV *attr, int argc, SV **argv)
03376 {
03377 HV *ret_hv;
03378 SV **sv;
03379 int i,
03380 limit,
03381 spi_rv;
03382 char *nulls;
03383 Datum *argvalues;
03384 plperl_query_desc *qdesc;
03385 plperl_query_entry *hash_entry;
03386
03387
03388
03389
03390
03391 MemoryContext oldcontext = CurrentMemoryContext;
03392 ResourceOwner oldowner = CurrentResourceOwner;
03393
03394 check_spi_usage_allowed();
03395
03396 BeginInternalSubTransaction(NULL);
03397
03398 MemoryContextSwitchTo(oldcontext);
03399
03400 PG_TRY();
03401 {
03402
03403
03404
03405 hash_entry = hash_search(plperl_active_interp->query_hash, query,
03406 HASH_FIND, NULL);
03407 if (hash_entry == NULL)
03408 elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
03409
03410 qdesc = hash_entry->query_data;
03411 if (qdesc == NULL)
03412 elog(ERROR, "spi_exec_prepared: plperl query_hash value vanished");
03413
03414 if (qdesc->nargs != argc)
03415 elog(ERROR, "spi_exec_prepared: expected %d argument(s), %d passed",
03416 qdesc->nargs, argc);
03417
03418
03419
03420
03421 limit = 0;
03422 if (attr != NULL)
03423 {
03424 sv = hv_fetch_string(attr, "limit");
03425 if (sv && *sv && SvIOK(*sv))
03426 limit = SvIV(*sv);
03427 }
03428
03429
03430
03431 if (argc > 0)
03432 {
03433 nulls = (char *) palloc(argc);
03434 argvalues = (Datum *) palloc(argc * sizeof(Datum));
03435 }
03436 else
03437 {
03438 nulls = NULL;
03439 argvalues = NULL;
03440 }
03441
03442 for (i = 0; i < argc; i++)
03443 {
03444 bool isnull;
03445
03446 argvalues[i] = plperl_sv_to_datum(argv[i],
03447 qdesc->argtypes[i],
03448 -1,
03449 NULL,
03450 &qdesc->arginfuncs[i],
03451 qdesc->argtypioparams[i],
03452 &isnull);
03453 nulls[i] = isnull ? 'n' : ' ';
03454 }
03455
03456
03457
03458
03459 spi_rv = SPI_execute_plan(qdesc->plan, argvalues, nulls,
03460 current_call_data->prodesc->fn_readonly, limit);
03461 ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
03462 spi_rv);
03463 if (argc > 0)
03464 {
03465 pfree(argvalues);
03466 pfree(nulls);
03467 }
03468
03469
03470 ReleaseCurrentSubTransaction();
03471 MemoryContextSwitchTo(oldcontext);
03472 CurrentResourceOwner = oldowner;
03473
03474
03475
03476
03477
03478 SPI_restore_connection();
03479 }
03480 PG_CATCH();
03481 {
03482 ErrorData *edata;
03483
03484
03485 MemoryContextSwitchTo(oldcontext);
03486 edata = CopyErrorData();
03487 FlushErrorState();
03488
03489
03490 RollbackAndReleaseCurrentSubTransaction();
03491 MemoryContextSwitchTo(oldcontext);
03492 CurrentResourceOwner = oldowner;
03493
03494
03495
03496
03497
03498
03499 SPI_restore_connection();
03500
03501
03502 croak("%s", edata->message);
03503
03504
03505 return NULL;
03506 }
03507 PG_END_TRY();
03508
03509 return ret_hv;
03510 }
03511
03512 SV *
03513 plperl_spi_query_prepared(char *query, int argc, SV **argv)
03514 {
03515 int i;
03516 char *nulls;
03517 Datum *argvalues;
03518 plperl_query_desc *qdesc;
03519 plperl_query_entry *hash_entry;
03520 SV *cursor;
03521 Portal portal = NULL;
03522
03523
03524
03525
03526
03527 MemoryContext oldcontext = CurrentMemoryContext;
03528 ResourceOwner oldowner = CurrentResourceOwner;
03529
03530 check_spi_usage_allowed();
03531
03532 BeginInternalSubTransaction(NULL);
03533
03534 MemoryContextSwitchTo(oldcontext);
03535
03536 PG_TRY();
03537 {
03538
03539
03540
03541 hash_entry = hash_search(plperl_active_interp->query_hash, query,
03542 HASH_FIND, NULL);
03543 if (hash_entry == NULL)
03544 elog(ERROR, "spi_query_prepared: Invalid prepared query passed");
03545
03546 qdesc = hash_entry->query_data;
03547 if (qdesc == NULL)
03548 elog(ERROR, "spi_query_prepared: plperl query_hash value vanished");
03549
03550 if (qdesc->nargs != argc)
03551 elog(ERROR, "spi_query_prepared: expected %d argument(s), %d passed",
03552 qdesc->nargs, argc);
03553
03554
03555
03556
03557 if (argc > 0)
03558 {
03559 nulls = (char *) palloc(argc);
03560 argvalues = (Datum *) palloc(argc * sizeof(Datum));
03561 }
03562 else
03563 {
03564 nulls = NULL;
03565 argvalues = NULL;
03566 }
03567
03568 for (i = 0; i < argc; i++)
03569 {
03570 bool isnull;
03571
03572 argvalues[i] = plperl_sv_to_datum(argv[i],
03573 qdesc->argtypes[i],
03574 -1,
03575 NULL,
03576 &qdesc->arginfuncs[i],
03577 qdesc->argtypioparams[i],
03578 &isnull);
03579 nulls[i] = isnull ? 'n' : ' ';
03580 }
03581
03582
03583
03584
03585 portal = SPI_cursor_open(NULL, qdesc->plan, argvalues, nulls,
03586 current_call_data->prodesc->fn_readonly);
03587 if (argc > 0)
03588 {
03589 pfree(argvalues);
03590 pfree(nulls);
03591 }
03592 if (portal == NULL)
03593 elog(ERROR, "SPI_cursor_open() failed:%s",
03594 SPI_result_code_string(SPI_result));
03595
03596 cursor = cstr2sv(portal->name);
03597
03598
03599 ReleaseCurrentSubTransaction();
03600 MemoryContextSwitchTo(oldcontext);
03601 CurrentResourceOwner = oldowner;
03602
03603
03604
03605
03606
03607 SPI_restore_connection();
03608 }
03609 PG_CATCH();
03610 {
03611 ErrorData *edata;
03612
03613
03614 MemoryContextSwitchTo(oldcontext);
03615 edata = CopyErrorData();
03616 FlushErrorState();
03617
03618
03619 RollbackAndReleaseCurrentSubTransaction();
03620 MemoryContextSwitchTo(oldcontext);
03621 CurrentResourceOwner = oldowner;
03622
03623
03624
03625
03626
03627
03628 SPI_restore_connection();
03629
03630
03631 croak("%s", edata->message);
03632
03633
03634 return NULL;
03635 }
03636 PG_END_TRY();
03637
03638 return cursor;
03639 }
03640
03641 void
03642 plperl_spi_freeplan(char *query)
03643 {
03644 SPIPlanPtr plan;
03645 plperl_query_desc *qdesc;
03646 plperl_query_entry *hash_entry;
03647
03648 check_spi_usage_allowed();
03649
03650 hash_entry = hash_search(plperl_active_interp->query_hash, query,
03651 HASH_FIND, NULL);
03652 if (hash_entry == NULL)
03653 elog(ERROR, "spi_freeplan: Invalid prepared query passed");
03654
03655 qdesc = hash_entry->query_data;
03656 if (qdesc == NULL)
03657 elog(ERROR, "spi_freeplan: plperl query_hash value vanished");
03658 plan = qdesc->plan;
03659
03660
03661
03662
03663
03664 hash_search(plperl_active_interp->query_hash, query,
03665 HASH_REMOVE, NULL);
03666
03667 MemoryContextDelete(qdesc->plan_cxt);
03668
03669 SPI_freeplan(plan);
03670 }
03671
03672
03673
03674
03675
03676 static SV **
03677 hv_store_string(HV *hv, const char *key, SV *val)
03678 {
03679 int32 hlen;
03680 char *hkey;
03681 SV **ret;
03682
03683 hkey = (char *)
03684 pg_do_encoding_conversion((unsigned char *) key, strlen(key),
03685 GetDatabaseEncoding(), PG_UTF8);
03686
03687
03688
03689
03690
03691
03692
03693 hlen = -(int) strlen(hkey);
03694 ret = hv_store(hv, hkey, hlen, val, 0);
03695
03696 if (hkey != key)
03697 pfree(hkey);
03698
03699 return ret;
03700 }
03701
03702
03703
03704
03705
03706 static SV **
03707 hv_fetch_string(HV *hv, const char *key)
03708 {
03709 int32 hlen;
03710 char *hkey;
03711 SV **ret;
03712
03713 hkey = (char *)
03714 pg_do_encoding_conversion((unsigned char *) key, strlen(key),
03715 GetDatabaseEncoding(), PG_UTF8);
03716
03717
03718 hlen = -(int) strlen(hkey);
03719 ret = hv_fetch(hv, hkey, hlen, 0);
03720
03721 if (hkey != key)
03722 pfree(hkey);
03723
03724 return ret;
03725 }
03726
03727
03728
03729
03730 static void
03731 plperl_exec_callback(void *arg)
03732 {
03733 char *procname = (char *) arg;
03734
03735 if (procname)
03736 errcontext("PL/Perl function \"%s\"", procname);
03737 }
03738
03739
03740
03741
03742 static void
03743 plperl_compile_callback(void *arg)
03744 {
03745 char *procname = (char *) arg;
03746
03747 if (procname)
03748 errcontext("compilation of PL/Perl function \"%s\"", procname);
03749 }
03750
03751
03752
03753
03754 static void
03755 plperl_inline_callback(void *arg)
03756 {
03757 errcontext("PL/Perl anonymous code block");
03758 }
03759
03760
03761
03762
03763
03764
03765 #ifdef WIN32
03766 static char *
03767 setlocale_perl(int category, char *locale)
03768 {
03769 char *RETVAL = setlocale(category, locale);
03770
03771 if (RETVAL)
03772 {
03773 #ifdef USE_LOCALE_CTYPE
03774 if (category == LC_CTYPE
03775 #ifdef LC_ALL
03776 || category == LC_ALL
03777 #endif
03778 )
03779 {
03780 char *newctype;
03781
03782 #ifdef LC_ALL
03783 if (category == LC_ALL)
03784 newctype = setlocale(LC_CTYPE, NULL);
03785 else
03786 #endif
03787 newctype = RETVAL;
03788 new_ctype(newctype);
03789 }
03790 #endif
03791 #ifdef USE_LOCALE_COLLATE
03792 if (category == LC_COLLATE
03793 #ifdef LC_ALL
03794 || category == LC_ALL
03795 #endif
03796 )
03797 {
03798 char *newcoll;
03799
03800 #ifdef LC_ALL
03801 if (category == LC_ALL)
03802 newcoll = setlocale(LC_COLLATE, NULL);
03803 else
03804 #endif
03805 newcoll = RETVAL;
03806 new_collate(newcoll);
03807 }
03808 #endif
03809
03810 #ifdef USE_LOCALE_NUMERIC
03811 if (category == LC_NUMERIC
03812 #ifdef LC_ALL
03813 || category == LC_ALL
03814 #endif
03815 )
03816 {
03817 char *newnum;
03818
03819 #ifdef LC_ALL
03820 if (category == LC_ALL)
03821 newnum = setlocale(LC_NUMERIC, NULL);
03822 else
03823 #endif
03824 newnum = RETVAL;
03825 new_numeric(newnum);
03826 }
03827 #endif
03828 }
03829
03830 return RETVAL;
03831 }
03832
03833 #endif