LCOV - code coverage report
Current view: top level - src/pl/plperl - plperl.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 89.0 % 1433 1276
Test Date: 2026-05-04 16:16:34 Functions: 100.0 % 73 73
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /**********************************************************************
       2              :  * plperl.c - perl as a procedural language for PostgreSQL
       3              :  *
       4              :  *    src/pl/plperl/plperl.c
       5              :  *
       6              :  **********************************************************************/
       7              : 
       8              : #include "postgres.h"
       9              : 
      10              : /* system stuff */
      11              : #include <ctype.h>
      12              : #include <fcntl.h>
      13              : #include <limits.h>
      14              : #include <unistd.h>
      15              : 
      16              : /* postgreSQL stuff */
      17              : #include "access/htup_details.h"
      18              : #include "access/xact.h"
      19              : #include "catalog/pg_language.h"
      20              : #include "catalog/pg_proc.h"
      21              : #include "catalog/pg_type.h"
      22              : #include "commands/event_trigger.h"
      23              : #include "commands/trigger.h"
      24              : #include "executor/spi.h"
      25              : #include "funcapi.h"
      26              : #include "miscadmin.h"
      27              : #include "parser/parse_type.h"
      28              : #include "storage/ipc.h"
      29              : #include "tcop/tcopprot.h"
      30              : #include "utils/builtins.h"
      31              : #include "utils/fmgroids.h"
      32              : #include "utils/guc.h"
      33              : #include "utils/hsearch.h"
      34              : #include "utils/lsyscache.h"
      35              : #include "utils/memutils.h"
      36              : #include "utils/rel.h"
      37              : #include "utils/syscache.h"
      38              : #include "utils/tuplestore.h"
      39              : #include "utils/typcache.h"
      40              : 
      41              : /* define our text domain for translations */
      42              : #undef TEXTDOMAIN
      43              : #define TEXTDOMAIN PG_TEXTDOMAIN("plperl")
      44              : 
      45              : /* perl stuff */
      46              : /* string literal macros defining chunks of perl code */
      47              : #include "perlchunks.h"
      48              : #include "plperl.h"
      49              : /* defines PLPERL_SET_OPMASK */
      50              : #include "plperl_opmask.h"
      51              : 
      52              : EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
      53              : EXTERN_C void boot_PostgreSQL__InServer__Util(pTHX_ CV *cv);
      54              : EXTERN_C void boot_PostgreSQL__InServer__SPI(pTHX_ CV *cv);
      55              : 
      56           24 : PG_MODULE_MAGIC_EXT(
      57              :                     .name = "plperl",
      58              :                     .version = PG_VERSION
      59              : );
      60              : 
      61              : /**********************************************************************
      62              :  * Information associated with a Perl interpreter.  We have one interpreter
      63              :  * that is used for all plperlu (untrusted) functions.  For plperl (trusted)
      64              :  * functions, there is a separate interpreter for each effective SQL userid.
      65              :  * (This is needed to ensure that an unprivileged user can't inject Perl code
      66              :  * that'll be executed with the privileges of some other SQL user.)
      67              :  *
      68              :  * The plperl_interp_desc structs are kept in a Postgres hash table indexed
      69              :  * by userid OID, with OID 0 used for the single untrusted interpreter.
      70              :  * Once created, an interpreter is kept for the life of the process.
      71              :  *
      72              :  * We start out by creating a "held" interpreter, which we initialize
      73              :  * only as far as we can do without deciding if it will be trusted or
      74              :  * untrusted.  Later, when we first need to run a plperl or plperlu
      75              :  * function, we complete the initialization appropriately and move the
      76              :  * PerlInterpreter pointer into the plperl_interp_hash hashtable.  If after
      77              :  * that we need more interpreters, we create them as needed if we can, or
      78              :  * fail if the Perl build doesn't support multiple interpreters.
      79              :  *
      80              :  * The reason for all the dancing about with a held interpreter is to make
      81              :  * it possible for people to preload a lot of Perl code at postmaster startup
      82              :  * (using plperl.on_init) and then use that code in backends.  Of course this
      83              :  * will only work for the first interpreter created in any backend, but it's
      84              :  * still useful with that restriction.
      85              :  **********************************************************************/
      86              : typedef struct plperl_interp_desc
      87              : {
      88              :     Oid         user_id;        /* Hash key (must be first!) */
      89              :     PerlInterpreter *interp;    /* The interpreter */
      90              :     HTAB       *query_hash;     /* plperl_query_entry structs */
      91              : } plperl_interp_desc;
      92              : 
      93              : 
      94              : /**********************************************************************
      95              :  * The information we cache about loaded procedures
      96              :  *
      97              :  * The fn_refcount field counts the struct's reference from the hash table
      98              :  * shown below, plus one reference for each function call level that is using
      99              :  * the struct.  We can release the struct, and the associated Perl sub, when
     100              :  * the fn_refcount goes to zero.  Releasing the struct itself is done by
     101              :  * deleting the fn_cxt, which also gets rid of all subsidiary data.
     102              :  **********************************************************************/
     103              : typedef struct plperl_proc_desc
     104              : {
     105              :     char       *proname;        /* user name of procedure */
     106              :     MemoryContext fn_cxt;       /* memory context for this procedure */
     107              :     unsigned long fn_refcount;  /* number of active references */
     108              :     TransactionId fn_xmin;      /* xmin/TID of procedure's pg_proc tuple */
     109              :     ItemPointerData fn_tid;
     110              :     SV         *reference;      /* CODE reference for Perl sub */
     111              :     plperl_interp_desc *interp; /* interpreter it's created in */
     112              :     bool        fn_readonly;    /* is function readonly (not volatile)? */
     113              :     Oid         lang_oid;
     114              :     List       *trftypes;
     115              :     bool        lanpltrusted;   /* is it plperl, rather than plperlu? */
     116              :     bool        fn_retistuple;  /* true, if function returns tuple */
     117              :     bool        fn_retisset;    /* true, if function returns set */
     118              :     bool        fn_retisarray;  /* true if function returns array */
     119              :     /* Conversion info for function's result type: */
     120              :     Oid         result_oid;     /* Oid of result type */
     121              :     FmgrInfo    result_in_func; /* I/O function and arg for result type */
     122              :     Oid         result_typioparam;
     123              :     /* Per-argument info for function's argument types: */
     124              :     int         nargs;
     125              :     FmgrInfo   *arg_out_func;   /* output fns for arg types */
     126              :     bool       *arg_is_rowtype; /* is each arg composite? */
     127              :     Oid        *arg_arraytype;  /* InvalidOid if not an array */
     128              : } plperl_proc_desc;
     129              : 
     130              : #define increment_prodesc_refcount(prodesc)  \
     131              :     ((prodesc)->fn_refcount++)
     132              : #define decrement_prodesc_refcount(prodesc)  \
     133              :     do { \
     134              :         Assert((prodesc)->fn_refcount > 0); \
     135              :         if (--((prodesc)->fn_refcount) == 0) \
     136              :             free_plperl_function(prodesc); \
     137              :     } while(0)
     138              : 
     139              : /**********************************************************************
     140              :  * For speedy lookup, we maintain a hash table mapping from
     141              :  * function OID + trigger flag + user OID to plperl_proc_desc pointers.
     142              :  * The reason the plperl_proc_desc struct isn't directly part of the hash
     143              :  * entry is to simplify recovery from errors during compile_plperl_function.
     144              :  *
     145              :  * Note: if the same function is called by multiple userIDs within a session,
     146              :  * there will be a separate plperl_proc_desc entry for each userID in the case
     147              :  * of plperl functions, but only one entry for plperlu functions, because we
     148              :  * set user_id = 0 for that case.  If the user redeclares the same function
     149              :  * from plperl to plperlu or vice versa, there might be multiple
     150              :  * plperl_proc_ptr entries in the hashtable, but only one is valid.
     151              :  **********************************************************************/
     152              : typedef struct plperl_proc_key
     153              : {
     154              :     Oid         proc_id;        /* Function OID */
     155              : 
     156              :     /*
     157              :      * is_trigger is really a bool, but declare as Oid to ensure this struct
     158              :      * contains no padding
     159              :      */
     160              :     Oid         is_trigger;     /* is it a trigger function? */
     161              :     Oid         user_id;        /* User calling the function, or 0 */
     162              : } plperl_proc_key;
     163              : 
     164              : typedef struct plperl_proc_ptr
     165              : {
     166              :     plperl_proc_key proc_key;   /* Hash key (must be first!) */
     167              :     plperl_proc_desc *proc_ptr;
     168              : } plperl_proc_ptr;
     169              : 
     170              : /*
     171              :  * The information we cache for the duration of a single call to a
     172              :  * function.
     173              :  */
     174              : typedef struct plperl_call_data
     175              : {
     176              :     plperl_proc_desc *prodesc;
     177              :     FunctionCallInfo fcinfo;
     178              :     /* remaining fields are used only in a function returning set: */
     179              :     Tuplestorestate *tuple_store;
     180              :     TupleDesc   ret_tdesc;
     181              :     Oid         cdomain_oid;    /* 0 unless returning domain-over-composite */
     182              :     void       *cdomain_info;
     183              :     MemoryContext tmp_cxt;
     184              : } plperl_call_data;
     185              : 
     186              : /**********************************************************************
     187              :  * The information we cache about prepared and saved plans
     188              :  **********************************************************************/
     189              : typedef struct plperl_query_desc
     190              : {
     191              :     char        qname[24];
     192              :     MemoryContext plan_cxt;     /* context holding this struct */
     193              :     SPIPlanPtr  plan;
     194              :     int         nargs;
     195              :     Oid        *argtypes;
     196              :     FmgrInfo   *arginfuncs;
     197              :     Oid        *argtypioparams;
     198              : } plperl_query_desc;
     199              : 
     200              : /* hash table entry for query desc  */
     201              : 
     202              : typedef struct plperl_query_entry
     203              : {
     204              :     char        query_name[NAMEDATALEN];
     205              :     plperl_query_desc *query_data;
     206              : } plperl_query_entry;
     207              : 
     208              : /**********************************************************************
     209              :  * Information for PostgreSQL - Perl array conversion.
     210              :  **********************************************************************/
     211              : typedef struct plperl_array_info
     212              : {
     213              :     int         ndims;
     214              :     bool        elem_is_rowtype;    /* 't' if element type is a rowtype */
     215              :     Datum      *elements;
     216              :     bool       *nulls;
     217              :     int        *nelems;
     218              :     FmgrInfo    proc;
     219              :     FmgrInfo    transform_proc;
     220              : } plperl_array_info;
     221              : 
     222              : /**********************************************************************
     223              :  * Global data
     224              :  **********************************************************************/
     225              : 
     226              : static HTAB *plperl_interp_hash = NULL;
     227              : static HTAB *plperl_proc_hash = NULL;
     228              : static plperl_interp_desc *plperl_active_interp = NULL;
     229              : 
     230              : /* If we have an unassigned "held" interpreter, it's stored here */
     231              : static PerlInterpreter *plperl_held_interp = NULL;
     232              : 
     233              : /* GUC variables */
     234              : static bool plperl_use_strict = false;
     235              : static char *plperl_on_init = NULL;
     236              : static char *plperl_on_plperl_init = NULL;
     237              : static char *plperl_on_plperlu_init = NULL;
     238              : 
     239              : static bool plperl_ending = false;
     240              : static OP  *(*pp_require_orig) (pTHX) = NULL;
     241              : static char plperl_opmask[MAXO];
     242              : 
     243              : /* this is saved and restored by plperl_call_handler */
     244              : static plperl_call_data *current_call_data = NULL;
     245              : 
     246              : /**********************************************************************
     247              :  * Forward declarations
     248              :  **********************************************************************/
     249              : 
     250              : static PerlInterpreter *plperl_init_interp(void);
     251              : static void plperl_destroy_interp(PerlInterpreter **interp);
     252              : static void plperl_fini(int code, Datum arg);
     253              : static void set_interp_require(bool trusted);
     254              : 
     255              : static Datum plperl_func_handler(PG_FUNCTION_ARGS);
     256              : static Datum plperl_trigger_handler(PG_FUNCTION_ARGS);
     257              : static void plperl_event_trigger_handler(PG_FUNCTION_ARGS);
     258              : 
     259              : static void free_plperl_function(plperl_proc_desc *prodesc);
     260              : 
     261              : static plperl_proc_desc *compile_plperl_function(Oid fn_oid,
     262              :                                                  bool is_trigger,
     263              :                                                  bool is_event_trigger);
     264              : 
     265              : static SV  *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated);
     266              : static SV  *plperl_hash_from_datum(Datum attr);
     267              : static void check_spi_usage_allowed(void);
     268              : static SV  *plperl_ref_from_pg_array(Datum arg, Oid typid);
     269              : static SV  *split_array(plperl_array_info *info, int first, int last, int nest);
     270              : static SV  *make_array_ref(plperl_array_info *info, int first, int last);
     271              : static SV  *get_perl_array_ref(SV *sv);
     272              : static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
     273              :                                 FunctionCallInfo fcinfo,
     274              :                                 FmgrInfo *finfo, Oid typioparam,
     275              :                                 bool *isnull);
     276              : static void _sv_to_datum_finfo(Oid typid, FmgrInfo *finfo, Oid *typioparam);
     277              : static Datum plperl_array_to_datum(SV *src, Oid typid, int32 typmod);
     278              : static void array_to_datum_internal(AV *av, ArrayBuildState **astatep,
     279              :                                     int *ndims, int *dims, int cur_depth,
     280              :                                     Oid elemtypid, int32 typmod,
     281              :                                     FmgrInfo *finfo, Oid typioparam);
     282              : static Datum plperl_hash_to_datum(SV *src, TupleDesc td);
     283              : 
     284              : static void plperl_init_shared_libs(pTHX);
     285              : static void plperl_trusted_init(void);
     286              : static void plperl_untrusted_init(void);
     287              : static HV  *plperl_spi_execute_fetch_result(SPITupleTable *tuptable,
     288              :                                             uint64 processed, int status);
     289              : static void plperl_return_next_internal(SV *sv);
     290              : static char *hek2cstr(HE *he);
     291              : static SV **hv_store_string(HV *hv, const char *key, SV *val);
     292              : static SV **hv_fetch_string(HV *hv, const char *key);
     293              : static void plperl_create_sub(plperl_proc_desc *prodesc, const char *s,
     294              :                               Oid fn_oid);
     295              : static SV  *plperl_call_perl_func(plperl_proc_desc *desc,
     296              :                                   FunctionCallInfo fcinfo);
     297              : static void plperl_compile_callback(void *arg);
     298              : static void plperl_exec_callback(void *arg);
     299              : static void plperl_inline_callback(void *arg);
     300              : static char *strip_trailing_ws(const char *msg);
     301              : static OP  *pp_require_safe(pTHX);
     302              : static void activate_interpreter(plperl_interp_desc *interp_desc);
     303              : 
     304              : #if defined(WIN32) && PERL_VERSION_LT(5, 28, 0)
     305              : static char *setlocale_perl(int category, char *locale);
     306              : #else
     307              : #define setlocale_perl(a,b)  Perl_setlocale(a,b)
     308              : #endif                          /* defined(WIN32) && PERL_VERSION_LT(5, 28, 0) */
     309              : 
     310              : /*
     311              :  * Decrement the refcount of the given SV within the active Perl interpreter
     312              :  *
     313              :  * This is handy because it reloads the active-interpreter pointer, saving
     314              :  * some notation in callers that switch the active interpreter.
     315              :  */
     316              : static inline void
     317          316 : SvREFCNT_dec_current(SV *sv)
     318              : {
     319          316 :     dTHX;
     320              : 
     321          316 :     SvREFCNT_dec(sv);
     322          316 : }
     323              : 
     324              : /*
     325              :  * convert a HE (hash entry) key to a cstr in the current database encoding
     326              :  */
     327              : static char *
     328          202 : hek2cstr(HE *he)
     329              : {
     330          202 :     dTHX;
     331              :     char       *ret;
     332              :     SV         *sv;
     333              : 
     334              :     /*
     335              :      * HeSVKEY_force will return a temporary mortal SV*, so we need to make
     336              :      * sure to free it with ENTER/SAVE/FREE/LEAVE
     337              :      */
     338          202 :     ENTER;
     339          202 :     SAVETMPS;
     340              : 
     341              :     /*-------------------------
     342              :      * Unfortunately, while HeUTF8 is true for most things > 256, for values
     343              :      * 128..255 it's not, but perl will treat them as unicode code points if
     344              :      * the utf8 flag is not set ( see The "Unicode Bug" in perldoc perlunicode
     345              :      * for more)
     346              :      *
     347              :      * So if we did the expected:
     348              :      *    if (HeUTF8(he))
     349              :      *        utf_u2e(key...);
     350              :      *    else // must be ascii
     351              :      *        return HePV(he);
     352              :      * we won't match columns with codepoints from 128..255
     353              :      *
     354              :      * For a more concrete example given a column with the name of the unicode
     355              :      * codepoint U+00ae (registered sign) and a UTF8 database and the perl
     356              :      * return_next { "\N{U+00ae}=>'text } would always fail as heUTF8 returns
     357              :      * 0 and HePV() would give us a char * with 1 byte contains the decimal
     358              :      * value 174
     359              :      *
     360              :      * Perl has the brains to know when it should utf8 encode 174 properly, so
     361              :      * here we force it into an SV so that perl will figure it out and do the
     362              :      * right thing
     363              :      *-------------------------
     364              :      */
     365              : 
     366          202 :     sv = HeSVKEY_force(he);
     367          202 :     if (HeUTF8(he))
     368            0 :         SvUTF8_on(sv);
     369          202 :     ret = sv2cstr(sv);
     370              : 
     371              :     /* free sv */
     372          202 :     FREETMPS;
     373          202 :     LEAVE;
     374              : 
     375          202 :     return ret;
     376              : }
     377              : 
     378              : 
     379              : /*
     380              :  * _PG_init()           - library load-time initialization
     381              :  *
     382              :  * DO NOT make this static nor change its name!
     383              :  */
     384              : void
     385           24 : _PG_init(void)
     386              : {
     387              :     /*
     388              :      * Be sure we do initialization only once.
     389              :      *
     390              :      * If initialization fails due to, e.g., plperl_init_interp() throwing an
     391              :      * exception, then we'll return here on the next usage and the user will
     392              :      * get a rather cryptic: ERROR:  attempt to redefine parameter
     393              :      * "plperl.use_strict"
     394              :      */
     395              :     static bool inited = false;
     396              :     HASHCTL     hash_ctl;
     397              : 
     398           24 :     if (inited)
     399            0 :         return;
     400              : 
     401              :     /*
     402              :      * Support localized messages.
     403              :      */
     404           24 :     pg_bindtextdomain(TEXTDOMAIN);
     405              : 
     406              :     /*
     407              :      * Initialize plperl's GUCs.
     408              :      */
     409           24 :     DefineCustomBoolVariable("plperl.use_strict",
     410              :                              gettext_noop("If true, trusted and untrusted Perl code will be compiled in strict mode."),
     411              :                              NULL,
     412              :                              &plperl_use_strict,
     413              :                              false,
     414              :                              PGC_USERSET, 0,
     415              :                              NULL, NULL, NULL);
     416              : 
     417              :     /*
     418              :      * plperl.on_init is marked PGC_SIGHUP to support the idea that it might
     419              :      * be executed in the postmaster (if plperl is loaded into the postmaster
     420              :      * via shared_preload_libraries).  This isn't really right either way,
     421              :      * though.
     422              :      */
     423           24 :     DefineCustomStringVariable("plperl.on_init",
     424              :                                gettext_noop("Perl initialization code to execute when a Perl interpreter is initialized."),
     425              :                                NULL,
     426              :                                &plperl_on_init,
     427              :                                NULL,
     428              :                                PGC_SIGHUP, 0,
     429              :                                NULL, NULL, NULL);
     430              : 
     431              :     /*
     432              :      * plperl.on_plperl_init is marked PGC_SUSET to avoid issues whereby a
     433              :      * user who might not even have USAGE privilege on the plperl language
     434              :      * could nonetheless use SET plperl.on_plperl_init='...' to influence the
     435              :      * behaviour of any existing plperl function that they can execute (which
     436              :      * might be SECURITY DEFINER, leading to a privilege escalation).  See
     437              :      * http://archives.postgresql.org/pgsql-hackers/2010-02/msg00281.php and
     438              :      * the overall thread.
     439              :      *
     440              :      * Note that because plperl.use_strict is USERSET, a nefarious user could
     441              :      * set it to be applied against other people's functions.  This is judged
     442              :      * OK since the worst result would be an error.  Your code oughta pass
     443              :      * use_strict anyway ;-)
     444              :      */
     445           24 :     DefineCustomStringVariable("plperl.on_plperl_init",
     446              :                                gettext_noop("Perl initialization code to execute once when plperl is first used."),
     447              :                                NULL,
     448              :                                &plperl_on_plperl_init,
     449              :                                NULL,
     450              :                                PGC_SUSET, 0,
     451              :                                NULL, NULL, NULL);
     452              : 
     453           24 :     DefineCustomStringVariable("plperl.on_plperlu_init",
     454              :                                gettext_noop("Perl initialization code to execute once when plperlu is first used."),
     455              :                                NULL,
     456              :                                &plperl_on_plperlu_init,
     457              :                                NULL,
     458              :                                PGC_SUSET, 0,
     459              :                                NULL, NULL, NULL);
     460              : 
     461           24 :     MarkGUCPrefixReserved("plperl");
     462              : 
     463              :     /*
     464              :      * Create hash tables.
     465              :      */
     466           24 :     hash_ctl.keysize = sizeof(Oid);
     467           24 :     hash_ctl.entrysize = sizeof(plperl_interp_desc);
     468           24 :     plperl_interp_hash = hash_create("PL/Perl interpreters",
     469              :                                      8,
     470              :                                      &hash_ctl,
     471              :                                      HASH_ELEM | HASH_BLOBS);
     472              : 
     473           24 :     hash_ctl.keysize = sizeof(plperl_proc_key);
     474           24 :     hash_ctl.entrysize = sizeof(plperl_proc_ptr);
     475           24 :     plperl_proc_hash = hash_create("PL/Perl procedures",
     476              :                                    32,
     477              :                                    &hash_ctl,
     478              :                                    HASH_ELEM | HASH_BLOBS);
     479              : 
     480              :     /*
     481              :      * Save the default opmask.
     482              :      */
     483           24 :     PLPERL_SET_OPMASK(plperl_opmask);
     484              : 
     485              :     /*
     486              :      * Create the first Perl interpreter, but only partially initialize it.
     487              :      */
     488           24 :     plperl_held_interp = plperl_init_interp();
     489              : 
     490           24 :     inited = true;
     491              : }
     492              : 
     493              : 
     494              : static void
     495           49 : set_interp_require(bool trusted)
     496              : {
     497           49 :     if (trusted)
     498              :     {
     499           31 :         PL_ppaddr[OP_REQUIRE] = pp_require_safe;
     500           31 :         PL_ppaddr[OP_DOFILE] = pp_require_safe;
     501              :     }
     502              :     else
     503              :     {
     504           18 :         PL_ppaddr[OP_REQUIRE] = pp_require_orig;
     505           18 :         PL_ppaddr[OP_DOFILE] = pp_require_orig;
     506              :     }
     507           49 : }
     508              : 
     509              : /*
     510              :  * Cleanup perl interpreters, including running END blocks.
     511              :  * Does not fully undo the actions of _PG_init() nor make it callable again.
     512              :  */
     513              : static void
     514           22 : plperl_fini(int code, Datum arg)
     515              : {
     516              :     HASH_SEQ_STATUS hash_seq;
     517              :     plperl_interp_desc *interp_desc;
     518              : 
     519           22 :     elog(DEBUG3, "plperl_fini");
     520              : 
     521              :     /*
     522              :      * Indicate that perl is terminating. Disables use of spi_* functions when
     523              :      * running END/DESTROY code. See check_spi_usage_allowed(). Could be
     524              :      * enabled in future, with care, using a transaction
     525              :      * http://archives.postgresql.org/pgsql-hackers/2010-01/msg02743.php
     526              :      */
     527           22 :     plperl_ending = true;
     528              : 
     529              :     /* Only perform perl cleanup if we're exiting cleanly */
     530           22 :     if (code)
     531              :     {
     532            0 :         elog(DEBUG3, "plperl_fini: skipped");
     533            0 :         return;
     534              :     }
     535              : 
     536              :     /* Zap the "held" interpreter, if we still have it */
     537           22 :     plperl_destroy_interp(&plperl_held_interp);
     538              : 
     539              :     /* Zap any fully-initialized interpreters */
     540           22 :     hash_seq_init(&hash_seq, plperl_interp_hash);
     541           67 :     while ((interp_desc = hash_seq_search(&hash_seq)) != NULL)
     542              :     {
     543           23 :         if (interp_desc->interp)
     544              :         {
     545           23 :             activate_interpreter(interp_desc);
     546           23 :             plperl_destroy_interp(&interp_desc->interp);
     547              :         }
     548              :     }
     549              : 
     550           22 :     elog(DEBUG3, "plperl_fini: done");
     551              : }
     552              : 
     553              : 
     554              : /*
     555              :  * Select and activate an appropriate Perl interpreter.
     556              :  */
     557              : static void
     558          174 : select_perl_context(bool trusted)
     559              : {
     560              :     Oid         user_id;
     561              :     plperl_interp_desc *interp_desc;
     562              :     bool        found;
     563          174 :     PerlInterpreter *interp = NULL;
     564              : 
     565              :     /* Find or create the interpreter hashtable entry for this userid */
     566          174 :     if (trusted)
     567          149 :         user_id = GetUserId();
     568              :     else
     569           25 :         user_id = InvalidOid;
     570              : 
     571          174 :     interp_desc = hash_search(plperl_interp_hash, &user_id,
     572              :                               HASH_ENTER,
     573              :                               &found);
     574          174 :     if (!found)
     575              :     {
     576              :         /* Initialize newly-created hashtable entry */
     577           24 :         interp_desc->interp = NULL;
     578           24 :         interp_desc->query_hash = NULL;
     579              :     }
     580              : 
     581              :     /* Make sure we have a query_hash for this interpreter */
     582          174 :     if (interp_desc->query_hash == NULL)
     583              :     {
     584              :         HASHCTL     hash_ctl;
     585              : 
     586           24 :         hash_ctl.keysize = NAMEDATALEN;
     587           24 :         hash_ctl.entrysize = sizeof(plperl_query_entry);
     588           24 :         interp_desc->query_hash = hash_create("PL/Perl queries",
     589              :                                               32,
     590              :                                               &hash_ctl,
     591              :                                               HASH_ELEM | HASH_STRINGS);
     592              :     }
     593              : 
     594              :     /*
     595              :      * Quick exit if already have an interpreter
     596              :      */
     597          174 :     if (interp_desc->interp)
     598              :     {
     599          150 :         activate_interpreter(interp_desc);
     600          150 :         return;
     601              :     }
     602              : 
     603              :     /*
     604              :      * adopt held interp if free, else create new one if possible
     605              :      */
     606           24 :     if (plperl_held_interp != NULL)
     607              :     {
     608              :         /* first actual use of a perl interpreter */
     609           23 :         interp = plperl_held_interp;
     610              : 
     611              :         /*
     612              :          * Reset the plperl_held_interp pointer first; if we fail during init
     613              :          * we don't want to try again with the partially-initialized interp.
     614              :          */
     615           23 :         plperl_held_interp = NULL;
     616              : 
     617           23 :         if (trusted)
     618           19 :             plperl_trusted_init();
     619              :         else
     620            4 :             plperl_untrusted_init();
     621              : 
     622              :         /* successfully initialized, so arrange for cleanup */
     623           22 :         on_proc_exit(plperl_fini, 0);
     624              :     }
     625              :     else
     626              :     {
     627              : #ifdef MULTIPLICITY
     628              : 
     629              :         /*
     630              :          * plperl_init_interp will change Perl's idea of the active
     631              :          * interpreter.  Reset plperl_active_interp temporarily, so that if we
     632              :          * hit an error partway through here, we'll make sure to switch back
     633              :          * to a non-broken interpreter before running any other Perl
     634              :          * functions.
     635              :          */
     636            1 :         plperl_active_interp = NULL;
     637              : 
     638              :         /* Now build the new interpreter */
     639            1 :         interp = plperl_init_interp();
     640              : 
     641            1 :         if (trusted)
     642            0 :             plperl_trusted_init();
     643              :         else
     644            1 :             plperl_untrusted_init();
     645              : #else
     646              :         ereport(ERROR,
     647              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     648              :                  errmsg("cannot allocate multiple Perl interpreters on this platform")));
     649              : #endif
     650              :     }
     651              : 
     652           23 :     set_interp_require(trusted);
     653              : 
     654              :     /*
     655              :      * Since the timing of first use of PL/Perl can't be predicted, any
     656              :      * database interaction during initialization is problematic. Including,
     657              :      * but not limited to, security definer issues. So we only enable access
     658              :      * to the database AFTER on_*_init code has run. See
     659              :      * http://archives.postgresql.org/pgsql-hackers/2010-01/msg02669.php
     660              :      */
     661              :     {
     662           23 :         dTHX;
     663              : 
     664           23 :         newXS("PostgreSQL::InServer::SPI::bootstrap",
     665              :               boot_PostgreSQL__InServer__SPI, __FILE__);
     666              : 
     667           23 :         eval_pv("PostgreSQL::InServer::SPI::bootstrap()", FALSE);
     668           23 :         if (SvTRUE(ERRSV))
     669            0 :             ereport(ERROR,
     670              :                     (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
     671              :                      errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
     672              :                      errcontext("while executing PostgreSQL::InServer::SPI::bootstrap")));
     673              :     }
     674              : 
     675              :     /* Fully initialized, so mark the hashtable entry valid */
     676           23 :     interp_desc->interp = interp;
     677              : 
     678              :     /* And mark this as the active interpreter */
     679           23 :     plperl_active_interp = interp_desc;
     680              : }
     681              : 
     682              : /*
     683              :  * Make the specified interpreter the active one
     684              :  *
     685              :  * A call with NULL does nothing.  This is so that "restoring" to a previously
     686              :  * null state of plperl_active_interp doesn't result in useless thrashing.
     687              :  */
     688              : static void
     689          951 : activate_interpreter(plperl_interp_desc *interp_desc)
     690              : {
     691          951 :     if (interp_desc && plperl_active_interp != interp_desc)
     692              :     {
     693              :         Assert(interp_desc->interp);
     694           26 :         PERL_SET_CONTEXT(interp_desc->interp);
     695              :         /* trusted iff user_id isn't InvalidOid */
     696           26 :         set_interp_require(OidIsValid(interp_desc->user_id));
     697           26 :         plperl_active_interp = interp_desc;
     698              :     }
     699          951 : }
     700              : 
     701              : /*
     702              :  * Create a new Perl interpreter.
     703              :  *
     704              :  * We initialize the interpreter as far as we can without knowing whether
     705              :  * it will become a trusted or untrusted interpreter; in particular, the
     706              :  * plperl.on_init code will get executed.  Later, either plperl_trusted_init
     707              :  * or plperl_untrusted_init must be called to complete the initialization.
     708              :  */
     709              : static PerlInterpreter *
     710           25 : plperl_init_interp(void)
     711              : {
     712              :     PerlInterpreter *plperl;
     713              : 
     714              :     static char *embedding[3 + 2] = {
     715              :         "", "-e", PLC_PERLBOOT
     716              :     };
     717           25 :     int         nargs = 3;
     718              : 
     719              : #ifdef WIN32
     720              : 
     721              :     /*
     722              :      * The perl library on startup does horrible things like call
     723              :      * setlocale(LC_ALL,""). We have protected against that on most platforms
     724              :      * by setting the environment appropriately. However, on Windows,
     725              :      * setlocale() does not consult the environment, so we need to save the
     726              :      * existing locale settings before perl has a chance to mangle them and
     727              :      * restore them after its dirty deeds are done.
     728              :      *
     729              :      * MSDN ref:
     730              :      * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_locale.asp
     731              :      *
     732              :      * It appears that we only need to do this on interpreter startup, and
     733              :      * subsequent calls to the interpreter don't mess with the locale
     734              :      * settings.
     735              :      *
     736              :      * We restore them using setlocale_perl(), defined below, so that Perl
     737              :      * doesn't have a different idea of the locale from Postgres.
     738              :      *
     739              :      */
     740              : 
     741              :     char       *loc;
     742              :     char       *save_collate,
     743              :                *save_ctype,
     744              :                *save_monetary,
     745              :                *save_numeric,
     746              :                *save_time;
     747              : 
     748              :     loc = setlocale(LC_COLLATE, NULL);
     749              :     save_collate = loc ? pstrdup(loc) : NULL;
     750              :     loc = setlocale(LC_CTYPE, NULL);
     751              :     save_ctype = loc ? pstrdup(loc) : NULL;
     752              :     loc = setlocale(LC_MONETARY, NULL);
     753              :     save_monetary = loc ? pstrdup(loc) : NULL;
     754              :     loc = setlocale(LC_NUMERIC, NULL);
     755              :     save_numeric = loc ? pstrdup(loc) : NULL;
     756              :     loc = setlocale(LC_TIME, NULL);
     757              :     save_time = loc ? pstrdup(loc) : NULL;
     758              : 
     759              : #define PLPERL_RESTORE_LOCALE(name, saved) \
     760              :     STMT_START { \
     761              :         if (saved != NULL) { setlocale_perl(name, saved); pfree(saved); } \
     762              :     } STMT_END
     763              : #endif                          /* WIN32 */
     764              : 
     765           25 :     if (plperl_on_init && *plperl_on_init)
     766              :     {
     767            0 :         embedding[nargs++] = "-e";
     768            0 :         embedding[nargs++] = plperl_on_init;
     769              :     }
     770              : 
     771              :     /*
     772              :      * The perl API docs state that PERL_SYS_INIT3 should be called before
     773              :      * allocating interpreters. Unfortunately, on some platforms this fails in
     774              :      * the Perl_do_taint() routine, which is called when the platform is using
     775              :      * the system's malloc() instead of perl's own. Other platforms, notably
     776              :      * Windows, fail if PERL_SYS_INIT3 is not called. So we call it if it's
     777              :      * available, unless perl is using the system malloc(), which is true when
     778              :      * MYMALLOC is set.
     779              :      */
     780              : #if defined(PERL_SYS_INIT3) && !defined(MYMALLOC)
     781              :     {
     782              :         static int  perl_sys_init_done;
     783              : 
     784              :         /* only call this the first time through, as per perlembed man page */
     785           25 :         if (!perl_sys_init_done)
     786              :         {
     787           24 :             char       *dummy_env[1] = {NULL};
     788              : 
     789           24 :             PERL_SYS_INIT3(&nargs, (char ***) &embedding, (char ***) &dummy_env);
     790              : 
     791              :             /*
     792              :              * For unclear reasons, PERL_SYS_INIT3 sets the SIGFPE handler to
     793              :              * SIG_IGN.  Aside from being extremely unfriendly behavior for a
     794              :              * library, this is dumb on the grounds that the results of a
     795              :              * SIGFPE in this state are undefined according to POSIX, and in
     796              :              * fact you get a forced process kill at least on Linux.  Hence,
     797              :              * restore the SIGFPE handler to the backend's standard setting.
     798              :              * (See Perl bug 114574 for more information.)
     799              :              */
     800           24 :             pqsignal(SIGFPE, FloatExceptionHandler);
     801              : 
     802           24 :             perl_sys_init_done = 1;
     803              :             /* quiet warning if PERL_SYS_INIT3 doesn't use the third argument */
     804           24 :             dummy_env[0] = NULL;
     805              :         }
     806              :     }
     807              : #endif
     808              : 
     809           25 :     plperl = perl_alloc();
     810           25 :     if (!plperl)
     811            0 :         elog(ERROR, "could not allocate Perl interpreter");
     812              : 
     813           25 :     PERL_SET_CONTEXT(plperl);
     814           25 :     perl_construct(plperl);
     815              : 
     816              :     /*
     817              :      * Run END blocks in perl_destruct instead of perl_run.  Note that dTHX
     818              :      * loads up a pointer to the current interpreter, so we have to postpone
     819              :      * it to here rather than put it at the function head.
     820              :      */
     821              :     {
     822           25 :         dTHX;
     823              : 
     824           25 :         PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
     825              : 
     826              :         /*
     827              :          * Record the original function for the 'require' and 'dofile'
     828              :          * opcodes.  (They share the same implementation.)  Ensure it's used
     829              :          * for new interpreters.
     830              :          */
     831           25 :         if (!pp_require_orig)
     832           24 :             pp_require_orig = PL_ppaddr[OP_REQUIRE];
     833              :         else
     834              :         {
     835            1 :             PL_ppaddr[OP_REQUIRE] = pp_require_orig;
     836            1 :             PL_ppaddr[OP_DOFILE] = pp_require_orig;
     837              :         }
     838              : 
     839              : #ifdef PLPERL_ENABLE_OPMASK_EARLY
     840              : 
     841              :         /*
     842              :          * For regression testing to prove that the PLC_PERLBOOT and
     843              :          * PLC_TRUSTED code doesn't even compile any unsafe ops.  In future
     844              :          * there may be a valid need for them to do so, in which case this
     845              :          * could be softened (perhaps moved to plperl_trusted_init()) or
     846              :          * removed.
     847              :          */
     848              :         PL_op_mask = plperl_opmask;
     849              : #endif
     850              : 
     851           25 :         if (perl_parse(plperl, plperl_init_shared_libs,
     852              :                        nargs, embedding, NULL) != 0)
     853            0 :             ereport(ERROR,
     854              :                     (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
     855              :                      errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
     856              :                      errcontext("while parsing Perl initialization")));
     857              : 
     858           25 :         if (perl_run(plperl) != 0)
     859            0 :             ereport(ERROR,
     860              :                     (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
     861              :                      errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
     862              :                      errcontext("while running Perl initialization")));
     863              : 
     864              : #ifdef PLPERL_RESTORE_LOCALE
     865              :         PLPERL_RESTORE_LOCALE(LC_COLLATE, save_collate);
     866              :         PLPERL_RESTORE_LOCALE(LC_CTYPE, save_ctype);
     867              :         PLPERL_RESTORE_LOCALE(LC_MONETARY, save_monetary);
     868              :         PLPERL_RESTORE_LOCALE(LC_NUMERIC, save_numeric);
     869              :         PLPERL_RESTORE_LOCALE(LC_TIME, save_time);
     870              : #endif
     871              :     }
     872              : 
     873           25 :     return plperl;
     874              : }
     875              : 
     876              : 
     877              : /*
     878              :  * Our safe implementation of the require opcode.
     879              :  * This is safe because it's completely unable to load any code.
     880              :  * If the requested file/module has already been loaded it'll return true.
     881              :  * If not, it'll die.
     882              :  * So now "use Foo;" will work iff Foo has already been loaded.
     883              :  */
     884              : static OP  *
     885            8 : pp_require_safe(pTHX)
     886              : {
     887              :     dVAR;
     888            8 :     dSP;
     889              :     SV         *sv,
     890              :               **svp;
     891              :     char       *name;
     892              :     STRLEN      len;
     893              : 
     894            8 :     sv = POPs;
     895            8 :     name = SvPV(sv, len);
     896            8 :     if (!(name && len > 0 && *name))
     897            0 :         RETPUSHNO;
     898              : 
     899            8 :     svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
     900            8 :     if (svp && *svp != &PL_sv_undef)
     901            4 :         RETPUSHYES;
     902              : 
     903            4 :     DIE(aTHX_ "Unable to load %s into plperl", name);
     904              : 
     905              :     /*
     906              :      * In most Perl versions, DIE() expands to a return statement, so the next
     907              :      * line is not necessary.  But in versions between but not including
     908              :      * 5.11.1 and 5.13.3 it does not, so the next line is necessary to avoid a
     909              :      * "control reaches end of non-void function" warning from gcc.  Other
     910              :      * compilers such as Solaris Studio will, however, issue a "statement not
     911              :      * reached" warning instead.
     912              :      */
     913              :     return NULL;
     914              : }
     915              : 
     916              : 
     917              : /*
     918              :  * Destroy one Perl interpreter ... actually we just run END blocks.
     919              :  *
     920              :  * Caller must have ensured this interpreter is the active one.
     921              :  */
     922              : static void
     923           45 : plperl_destroy_interp(PerlInterpreter **interp)
     924              : {
     925           45 :     if (interp && *interp)
     926              :     {
     927              :         /*
     928              :          * Only a very minimal destruction is performed: - just call END
     929              :          * blocks.
     930              :          *
     931              :          * We could call perl_destruct() but we'd need to audit its actions
     932              :          * very carefully and work-around any that impact us. (Calling
     933              :          * sv_clean_objs() isn't an option because it's not part of perl's
     934              :          * public API so isn't portably available.) Meanwhile END blocks can
     935              :          * be used to perform manual cleanup.
     936              :          */
     937           23 :         dTHX;
     938              : 
     939              :         /* Run END blocks - based on perl's perl_destruct() */
     940           23 :         if (PL_exit_flags & PERL_EXIT_DESTRUCT_END)
     941              :         {
     942              :             dJMPENV;
     943           23 :             int         x = 0;
     944              : 
     945           23 :             JMPENV_PUSH(x);
     946              :             PERL_UNUSED_VAR(x);
     947           23 :             if (PL_endav && !PL_minus_c)
     948            0 :                 call_list(PL_scopestack_ix, PL_endav);
     949           23 :             JMPENV_POP;
     950              :         }
     951           23 :         LEAVE;
     952           23 :         FREETMPS;
     953              : 
     954           23 :         *interp = NULL;
     955              :     }
     956           45 : }
     957              : 
     958              : /*
     959              :  * Initialize the current Perl interpreter as a trusted interp
     960              :  */
     961              : static void
     962           19 : plperl_trusted_init(void)
     963              : {
     964           19 :     dTHX;
     965              :     HV         *stash;
     966              :     SV         *sv;
     967              :     char       *key;
     968              :     I32         klen;
     969              : 
     970              :     /* use original require while we set up */
     971           19 :     PL_ppaddr[OP_REQUIRE] = pp_require_orig;
     972           19 :     PL_ppaddr[OP_DOFILE] = pp_require_orig;
     973              : 
     974           19 :     eval_pv(PLC_TRUSTED, FALSE);
     975           19 :     if (SvTRUE(ERRSV))
     976            0 :         ereport(ERROR,
     977              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
     978              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
     979              :                  errcontext("while executing PLC_TRUSTED")));
     980              : 
     981              :     /*
     982              :      * Force loading of utf8 module now to prevent errors that can arise from
     983              :      * the regex code later trying to load utf8 modules. See
     984              :      * http://rt.perl.org/rt3/Ticket/Display.html?id=47576
     985              :      */
     986           19 :     eval_pv("my $a=chr(0x100); return $a =~ /\\xa9/i", FALSE);
     987           19 :     if (SvTRUE(ERRSV))
     988            0 :         ereport(ERROR,
     989              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
     990              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
     991              :                  errcontext("while executing utf8fix")));
     992              : 
     993              :     /*
     994              :      * Lock down the interpreter
     995              :      */
     996              : 
     997              :     /* switch to the safe require/dofile opcode for future code */
     998           19 :     PL_ppaddr[OP_REQUIRE] = pp_require_safe;
     999           19 :     PL_ppaddr[OP_DOFILE] = pp_require_safe;
    1000              : 
    1001              :     /*
    1002              :      * prevent (any more) unsafe opcodes being compiled PL_op_mask is per
    1003              :      * interpreter, so this only needs to be set once
    1004              :      */
    1005           19 :     PL_op_mask = plperl_opmask;
    1006              : 
    1007              :     /* delete the DynaLoader:: namespace so extensions can't be loaded */
    1008           19 :     stash = gv_stashpv("DynaLoader", GV_ADDWARN);
    1009           19 :     hv_iterinit(stash);
    1010           38 :     while ((sv = hv_iternextsv(stash, &key, &klen)))
    1011              :     {
    1012           19 :         if (!isGV_with_GP(sv) || !GvCV(sv))
    1013            0 :             continue;
    1014           19 :         SvREFCNT_dec(GvCV(sv)); /* free the CV */
    1015           19 :         GvCV_set(sv, NULL);     /* prevent call via GV */
    1016              :     }
    1017           19 :     hv_clear(stash);
    1018              : 
    1019              :     /* invalidate assorted caches */
    1020           19 :     ++PL_sub_generation;
    1021           19 :     hv_clear(PL_stashcache);
    1022              : 
    1023              :     /*
    1024              :      * Execute plperl.on_plperl_init in the locked-down interpreter
    1025              :      */
    1026           19 :     if (plperl_on_plperl_init && *plperl_on_plperl_init)
    1027              :     {
    1028            2 :         eval_pv(plperl_on_plperl_init, FALSE);
    1029              :         /* XXX need to find a way to determine a better errcode here */
    1030            2 :         if (SvTRUE(ERRSV))
    1031            1 :             ereport(ERROR,
    1032              :                     (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    1033              :                      errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
    1034              :                      errcontext("while executing plperl.on_plperl_init")));
    1035              :     }
    1036           18 : }
    1037              : 
    1038              : 
    1039              : /*
    1040              :  * Initialize the current Perl interpreter as an untrusted interp
    1041              :  */
    1042              : static void
    1043            5 : plperl_untrusted_init(void)
    1044              : {
    1045            5 :     dTHX;
    1046              : 
    1047              :     /*
    1048              :      * Nothing to do except execute plperl.on_plperlu_init
    1049              :      */
    1050            5 :     if (plperl_on_plperlu_init && *plperl_on_plperlu_init)
    1051              :     {
    1052            1 :         eval_pv(plperl_on_plperlu_init, FALSE);
    1053            1 :         if (SvTRUE(ERRSV))
    1054            0 :             ereport(ERROR,
    1055              :                     (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    1056              :                      errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV))),
    1057              :                      errcontext("while executing plperl.on_plperlu_init")));
    1058              :     }
    1059            5 : }
    1060              : 
    1061              : 
    1062              : /*
    1063              :  * Perl likes to put a newline after its error messages; clean up such
    1064              :  */
    1065              : static char *
    1066           27 : strip_trailing_ws(const char *msg)
    1067              : {
    1068           27 :     char       *res = pstrdup(msg);
    1069           27 :     int         len = strlen(res);
    1070              : 
    1071           54 :     while (len > 0 && isspace((unsigned char) res[len - 1]))
    1072           27 :         res[--len] = '\0';
    1073           27 :     return res;
    1074              : }
    1075              : 
    1076              : 
    1077              : /* Build a tuple from a hash. */
    1078              : 
    1079              : static HeapTuple
    1080           80 : plperl_build_tuple_result(HV *perlhash, TupleDesc td)
    1081              : {
    1082           80 :     dTHX;
    1083              :     Datum      *values;
    1084              :     bool       *nulls;
    1085              :     HE         *he;
    1086              :     HeapTuple   tup;
    1087              : 
    1088           80 :     values = palloc0_array(Datum, td->natts);
    1089           80 :     nulls = palloc_array(bool, td->natts);
    1090           80 :     memset(nulls, true, sizeof(bool) * td->natts);
    1091              : 
    1092           80 :     hv_iterinit(perlhash);
    1093          265 :     while ((he = hv_iternext(perlhash)))
    1094              :     {
    1095          187 :         SV         *val = HeVAL(he);
    1096          187 :         char       *key = hek2cstr(he);
    1097          187 :         int         attn = SPI_fnumber(td, key);
    1098              :         Form_pg_attribute attr;
    1099              : 
    1100          187 :         if (attn == SPI_ERROR_NOATTRIBUTE)
    1101            2 :             ereport(ERROR,
    1102              :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1103              :                      errmsg("Perl hash contains nonexistent column \"%s\"",
    1104              :                             key)));
    1105          185 :         if (attn <= 0)
    1106            0 :             ereport(ERROR,
    1107              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1108              :                      errmsg("cannot set system attribute \"%s\"",
    1109              :                             key)));
    1110              : 
    1111          185 :         attr = TupleDescAttr(td, attn - 1);
    1112          370 :         values[attn - 1] = plperl_sv_to_datum(val,
    1113              :                                               attr->atttypid,
    1114              :                                               attr->atttypmod,
    1115              :                                               NULL,
    1116              :                                               NULL,
    1117              :                                               InvalidOid,
    1118          185 :                                               &nulls[attn - 1]);
    1119              : 
    1120          185 :         pfree(key);
    1121              :     }
    1122           78 :     hv_iterinit(perlhash);
    1123              : 
    1124           78 :     tup = heap_form_tuple(td, values, nulls);
    1125           78 :     pfree(values);
    1126           78 :     pfree(nulls);
    1127           78 :     return tup;
    1128              : }
    1129              : 
    1130              : /* convert a hash reference to a datum */
    1131              : static Datum
    1132           41 : plperl_hash_to_datum(SV *src, TupleDesc td)
    1133              : {
    1134           41 :     HeapTuple   tup = plperl_build_tuple_result((HV *) SvRV(src), td);
    1135              : 
    1136           40 :     return HeapTupleGetDatum(tup);
    1137              : }
    1138              : 
    1139              : /*
    1140              :  * if we are an array ref return the reference. this is special in that if we
    1141              :  * are a PostgreSQL::InServer::ARRAY object we will return the 'magic' array.
    1142              :  */
    1143              : static SV  *
    1144          374 : get_perl_array_ref(SV *sv)
    1145              : {
    1146          374 :     dTHX;
    1147              : 
    1148          374 :     if (SvOK(sv) && SvROK(sv))
    1149              :     {
    1150          205 :         if (SvTYPE(SvRV(sv)) == SVt_PVAV)
    1151          152 :             return sv;
    1152           53 :         else if (sv_isa(sv, "PostgreSQL::InServer::ARRAY"))
    1153              :         {
    1154            1 :             HV         *hv = (HV *) SvRV(sv);
    1155            1 :             SV        **sav = hv_fetch_string(hv, "array");
    1156              : 
    1157            1 :             if (*sav && SvOK(*sav) && SvROK(*sav) &&
    1158            1 :                 SvTYPE(SvRV(*sav)) == SVt_PVAV)
    1159            1 :                 return *sav;
    1160              : 
    1161            0 :             elog(ERROR, "could not get array reference from PostgreSQL::InServer::ARRAY object");
    1162              :         }
    1163              :     }
    1164          221 :     return NULL;
    1165              : }
    1166              : 
    1167              : /*
    1168              :  * helper function for plperl_array_to_datum, recurses for multi-D arrays
    1169              :  *
    1170              :  * The ArrayBuildState is created only when we first find a scalar element;
    1171              :  * if we didn't do it like that, we'd need some other convention for knowing
    1172              :  * whether we'd already found any scalars (and thus the number of dimensions
    1173              :  * is frozen).
    1174              :  */
    1175              : static void
    1176          130 : array_to_datum_internal(AV *av, ArrayBuildState **astatep,
    1177              :                         int *ndims, int *dims, int cur_depth,
    1178              :                         Oid elemtypid, int32 typmod,
    1179              :                         FmgrInfo *finfo, Oid typioparam)
    1180              : {
    1181          130 :     dTHX;
    1182              :     int         i;
    1183          130 :     int         len = av_len(av) + 1;
    1184              : 
    1185          375 :     for (i = 0; i < len; i++)
    1186              :     {
    1187              :         /* fetch the array element */
    1188          250 :         SV        **svp = av_fetch(av, i, FALSE);
    1189              : 
    1190              :         /* see if this element is an array, if so get that */
    1191          250 :         SV         *sav = svp ? get_perl_array_ref(*svp) : NULL;
    1192              : 
    1193              :         /* multi-dimensional array? */
    1194          250 :         if (sav)
    1195              :         {
    1196           98 :             AV         *nav = (AV *) SvRV(sav);
    1197              : 
    1198              :             /* set size when at first element in this level, else compare */
    1199           98 :             if (i == 0 && *ndims == cur_depth)
    1200              :             {
    1201              :                 /* array after some scalars at same level? */
    1202           22 :                 if (*astatep != NULL)
    1203            1 :                     ereport(ERROR,
    1204              :                             (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    1205              :                              errmsg("multidimensional arrays must have array expressions with matching dimensions")));
    1206              :                 /* too many dimensions? */
    1207           21 :                 if (cur_depth + 1 > MAXDIM)
    1208            0 :                     ereport(ERROR,
    1209              :                             (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1210              :                              errmsg("number of array dimensions exceeds the maximum allowed (%d)",
    1211              :                                     MAXDIM)));
    1212              :                 /* OK, add a dimension */
    1213           21 :                 dims[*ndims] = av_len(nav) + 1;
    1214           21 :                 (*ndims)++;
    1215              :             }
    1216           76 :             else if (cur_depth >= *ndims ||
    1217           75 :                      av_len(nav) + 1 != dims[cur_depth])
    1218            2 :                 ereport(ERROR,
    1219              :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    1220              :                          errmsg("multidimensional arrays must have array expressions with matching dimensions")));
    1221              : 
    1222              :             /* recurse to fetch elements of this sub-array */
    1223           95 :             array_to_datum_internal(nav, astatep,
    1224              :                                     ndims, dims, cur_depth + 1,
    1225              :                                     elemtypid, typmod,
    1226              :                                     finfo, typioparam);
    1227              :         }
    1228              :         else
    1229              :         {
    1230              :             Datum       dat;
    1231              :             bool        isnull;
    1232              : 
    1233              :             /* scalar after some sub-arrays at same level? */
    1234          152 :             if (*ndims != cur_depth)
    1235            1 :                 ereport(ERROR,
    1236              :                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
    1237              :                          errmsg("multidimensional arrays must have array expressions with matching dimensions")));
    1238              : 
    1239          151 :             dat = plperl_sv_to_datum(svp ? *svp : NULL,
    1240              :                                      elemtypid,
    1241              :                                      typmod,
    1242              :                                      NULL,
    1243              :                                      finfo,
    1244              :                                      typioparam,
    1245              :                                      &isnull);
    1246              : 
    1247              :             /* Create ArrayBuildState if we didn't already */
    1248          151 :             if (*astatep == NULL)
    1249           31 :                 *astatep = initArrayResult(elemtypid,
    1250              :                                            CurrentMemoryContext, true);
    1251              : 
    1252              :             /* ... and save the element value in it */
    1253          151 :             (void) accumArrayResult(*astatep, dat, isnull,
    1254              :                                     elemtypid, CurrentMemoryContext);
    1255              :         }
    1256              :     }
    1257          125 : }
    1258              : 
    1259              : /*
    1260              :  * convert perl array ref to a datum
    1261              :  */
    1262              : static Datum
    1263           37 : plperl_array_to_datum(SV *src, Oid typid, int32 typmod)
    1264              : {
    1265           37 :     dTHX;
    1266           37 :     AV         *nav = (AV *) SvRV(src);
    1267           37 :     ArrayBuildState *astate = NULL;
    1268              :     Oid         elemtypid;
    1269              :     FmgrInfo    finfo;
    1270              :     Oid         typioparam;
    1271              :     int         dims[MAXDIM];
    1272              :     int         lbs[MAXDIM];
    1273           37 :     int         ndims = 1;
    1274              :     int         i;
    1275              : 
    1276           37 :     elemtypid = get_element_type(typid);
    1277           37 :     if (!elemtypid)
    1278            2 :         ereport(ERROR,
    1279              :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    1280              :                  errmsg("cannot convert Perl array to non-array type %s",
    1281              :                         format_type_be(typid))));
    1282              : 
    1283           35 :     _sv_to_datum_finfo(elemtypid, &finfo, &typioparam);
    1284              : 
    1285           35 :     memset(dims, 0, sizeof(dims));
    1286           35 :     dims[0] = av_len(nav) + 1;
    1287              : 
    1288           35 :     array_to_datum_internal(nav, &astate,
    1289              :                             &ndims, dims, 1,
    1290              :                             elemtypid, typmod,
    1291              :                             &finfo, typioparam);
    1292              : 
    1293              :     /* ensure we get zero-D array for no inputs, as per PG convention */
    1294           31 :     if (astate == NULL)
    1295            2 :         return PointerGetDatum(construct_empty_array(elemtypid));
    1296              : 
    1297           75 :     for (i = 0; i < ndims; i++)
    1298           46 :         lbs[i] = 1;
    1299              : 
    1300           29 :     return makeMdArrayResult(astate, ndims, dims, lbs,
    1301              :                              CurrentMemoryContext, true);
    1302              : }
    1303              : 
    1304              : /* Get the information needed to convert data to the specified PG type */
    1305              : static void
    1306          204 : _sv_to_datum_finfo(Oid typid, FmgrInfo *finfo, Oid *typioparam)
    1307              : {
    1308              :     Oid         typinput;
    1309              : 
    1310              :     /* XXX would be better to cache these lookups */
    1311          204 :     getTypeInputInfo(typid,
    1312              :                      &typinput, typioparam);
    1313          204 :     fmgr_info(typinput, finfo);
    1314          204 : }
    1315              : 
    1316              : /*
    1317              :  * convert Perl SV to PG datum of type typid, typmod typmod
    1318              :  *
    1319              :  * Pass the PL/Perl function's fcinfo when attempting to convert to the
    1320              :  * function's result type; otherwise pass NULL.  This is used when we need to
    1321              :  * resolve the actual result type of a function returning RECORD.
    1322              :  *
    1323              :  * finfo and typioparam should be the results of _sv_to_datum_finfo for the
    1324              :  * given typid, or NULL/InvalidOid to let this function do the lookups.
    1325              :  *
    1326              :  * *isnull is an output parameter.
    1327              :  */
    1328              : static Datum
    1329          647 : plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
    1330              :                    FunctionCallInfo fcinfo,
    1331              :                    FmgrInfo *finfo, Oid typioparam,
    1332              :                    bool *isnull)
    1333              : {
    1334              :     FmgrInfo    tmp;
    1335              :     Oid         funcid;
    1336              : 
    1337              :     /* we might recurse */
    1338          647 :     check_stack_depth();
    1339              : 
    1340          647 :     *isnull = false;
    1341              : 
    1342              :     /*
    1343              :      * Return NULL if result is undef, or if we're in a function returning
    1344              :      * VOID.  In the latter case, we should pay no attention to the last Perl
    1345              :      * statement's result, and this is a convenient means to ensure that.
    1346              :      */
    1347          647 :     if (!sv || !SvOK(sv) || typid == VOIDOID)
    1348              :     {
    1349              :         /* look up type info if they did not pass it */
    1350           39 :         if (!finfo)
    1351              :         {
    1352            5 :             _sv_to_datum_finfo(typid, &tmp, &typioparam);
    1353            5 :             finfo = &tmp;
    1354              :         }
    1355           39 :         *isnull = true;
    1356              :         /* must call typinput in case it wants to reject NULL */
    1357           39 :         return InputFunctionCall(finfo, NULL, typioparam, typmod);
    1358              :     }
    1359          608 :     else if ((funcid = get_transform_tosql(typid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
    1360           78 :         return OidFunctionCall1(funcid, PointerGetDatum(sv));
    1361          530 :     else if (SvROK(sv))
    1362              :     {
    1363              :         /* handle references */
    1364           82 :         SV         *sav = get_perl_array_ref(sv);
    1365              : 
    1366           82 :         if (sav)
    1367              :         {
    1368              :             /* handle an arrayref */
    1369           37 :             return plperl_array_to_datum(sav, typid, typmod);
    1370              :         }
    1371           45 :         else if (SvTYPE(SvRV(sv)) == SVt_PVHV)
    1372              :         {
    1373              :             /* handle a hashref */
    1374              :             Datum       ret;
    1375              :             TupleDesc   td;
    1376              :             bool        isdomain;
    1377              : 
    1378           44 :             if (!type_is_rowtype(typid))
    1379            2 :                 ereport(ERROR,
    1380              :                         (errcode(ERRCODE_DATATYPE_MISMATCH),
    1381              :                          errmsg("cannot convert Perl hash to non-composite type %s",
    1382              :                                 format_type_be(typid))));
    1383              : 
    1384           42 :             td = lookup_rowtype_tupdesc_domain(typid, typmod, true);
    1385           42 :             if (td != NULL)
    1386              :             {
    1387              :                 /* Did we look through a domain? */
    1388           34 :                 isdomain = (typid != td->tdtypeid);
    1389              :             }
    1390              :             else
    1391              :             {
    1392              :                 /* Must be RECORD, try to resolve based on call info */
    1393              :                 TypeFuncClass funcclass;
    1394              : 
    1395            8 :                 if (fcinfo)
    1396            8 :                     funcclass = get_call_result_type(fcinfo, &typid, &td);
    1397              :                 else
    1398            0 :                     funcclass = TYPEFUNC_OTHER;
    1399            8 :                 if (funcclass != TYPEFUNC_COMPOSITE &&
    1400              :                     funcclass != TYPEFUNC_COMPOSITE_DOMAIN)
    1401            1 :                     ereport(ERROR,
    1402              :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1403              :                              errmsg("function returning record called in context "
    1404              :                                     "that cannot accept type record")));
    1405              :                 Assert(td);
    1406            7 :                 isdomain = (funcclass == TYPEFUNC_COMPOSITE_DOMAIN);
    1407              :             }
    1408              : 
    1409           41 :             ret = plperl_hash_to_datum(sv, td);
    1410              : 
    1411           40 :             if (isdomain)
    1412            4 :                 domain_check(ret, false, typid, NULL, NULL);
    1413              : 
    1414              :             /* Release on the result of get_call_result_type is harmless */
    1415           38 :             ReleaseTupleDesc(td);
    1416              : 
    1417           38 :             return ret;
    1418              :         }
    1419              : 
    1420              :         /*
    1421              :          * If it's a reference to something else, such as a scalar, just
    1422              :          * recursively look through the reference.
    1423              :          */
    1424            1 :         return plperl_sv_to_datum(SvRV(sv), typid, typmod,
    1425              :                                   fcinfo, finfo, typioparam,
    1426              :                                   isnull);
    1427              :     }
    1428              :     else
    1429              :     {
    1430              :         /* handle a string/number */
    1431              :         Datum       ret;
    1432          448 :         char       *str = sv2cstr(sv);
    1433              : 
    1434              :         /* did not pass in any typeinfo? look it up */
    1435          447 :         if (!finfo)
    1436              :         {
    1437          164 :             _sv_to_datum_finfo(typid, &tmp, &typioparam);
    1438          164 :             finfo = &tmp;
    1439              :         }
    1440              : 
    1441          447 :         ret = InputFunctionCall(finfo, str, typioparam, typmod);
    1442          446 :         pfree(str);
    1443              : 
    1444          446 :         return ret;
    1445              :     }
    1446              : }
    1447              : 
    1448              : /* Convert the perl SV to a string returned by the type output function */
    1449              : char *
    1450           16 : plperl_sv_to_literal(SV *sv, char *fqtypename)
    1451              : {
    1452              :     Oid         typid;
    1453              :     Oid         typoutput;
    1454              :     Datum       datum;
    1455              :     bool        typisvarlena,
    1456              :                 isnull;
    1457              : 
    1458           16 :     check_spi_usage_allowed();
    1459              : 
    1460           16 :     typid = DatumGetObjectId(DirectFunctionCall1(regtypein, CStringGetDatum(fqtypename)));
    1461           16 :     if (!OidIsValid(typid))
    1462            0 :         ereport(ERROR,
    1463              :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
    1464              :                  errmsg("lookup failed for type %s", fqtypename)));
    1465              : 
    1466           16 :     datum = plperl_sv_to_datum(sv,
    1467              :                                typid, -1,
    1468              :                                NULL, NULL, InvalidOid,
    1469              :                                &isnull);
    1470              : 
    1471           15 :     if (isnull)
    1472            1 :         return NULL;
    1473              : 
    1474           14 :     getTypeOutputInfo(typid,
    1475              :                       &typoutput, &typisvarlena);
    1476              : 
    1477           14 :     return OidOutputFunctionCall(typoutput, datum);
    1478              : }
    1479              : 
    1480              : /*
    1481              :  * Convert PostgreSQL array datum to a perl array reference.
    1482              :  *
    1483              :  * typid is arg's OID, which must be an array type.
    1484              :  */
    1485              : static SV  *
    1486           17 : plperl_ref_from_pg_array(Datum arg, Oid typid)
    1487              : {
    1488           17 :     dTHX;
    1489           17 :     ArrayType  *ar = DatumGetArrayTypeP(arg);
    1490           17 :     Oid         elementtype = ARR_ELEMTYPE(ar);
    1491              :     int16       typlen;
    1492              :     bool        typbyval;
    1493              :     char        typalign,
    1494              :                 typdelim;
    1495              :     Oid         typioparam;
    1496              :     Oid         typoutputfunc;
    1497              :     Oid         transform_funcid;
    1498              :     int         i,
    1499              :                 nitems,
    1500              :                *dims;
    1501              :     plperl_array_info *info;
    1502              :     SV         *av;
    1503              :     HV         *hv;
    1504              : 
    1505              :     /*
    1506              :      * Currently we make no effort to cache any of the stuff we look up here,
    1507              :      * which is bad.
    1508              :      */
    1509           17 :     info = palloc0_object(plperl_array_info);
    1510              : 
    1511              :     /* get element type information, including output conversion function */
    1512           17 :     get_type_io_data(elementtype, IOFunc_output,
    1513              :                      &typlen, &typbyval, &typalign,
    1514              :                      &typdelim, &typioparam, &typoutputfunc);
    1515              : 
    1516              :     /* Check for a transform function */
    1517           17 :     transform_funcid = get_transform_fromsql(elementtype,
    1518           17 :                                              current_call_data->prodesc->lang_oid,
    1519           17 :                                              current_call_data->prodesc->trftypes);
    1520              : 
    1521              :     /* Look up transform or output function as appropriate */
    1522           17 :     if (OidIsValid(transform_funcid))
    1523            1 :         fmgr_info(transform_funcid, &info->transform_proc);
    1524              :     else
    1525           16 :         fmgr_info(typoutputfunc, &info->proc);
    1526              : 
    1527           17 :     info->elem_is_rowtype = type_is_rowtype(elementtype);
    1528              : 
    1529              :     /* Get the number and bounds of array dimensions */
    1530           17 :     info->ndims = ARR_NDIM(ar);
    1531           17 :     dims = ARR_DIMS(ar);
    1532              : 
    1533              :     /* No dimensions? Return an empty array */
    1534           17 :     if (info->ndims == 0)
    1535              :     {
    1536            1 :         av = newRV_noinc((SV *) newAV());
    1537              :     }
    1538              :     else
    1539              :     {
    1540           16 :         deconstruct_array(ar, elementtype, typlen, typbyval,
    1541              :                           typalign, &info->elements, &info->nulls,
    1542              :                           &nitems);
    1543              : 
    1544              :         /* Get total number of elements in each dimension */
    1545           16 :         info->nelems = palloc_array(int, info->ndims);
    1546           16 :         info->nelems[0] = nitems;
    1547           28 :         for (i = 1; i < info->ndims; i++)
    1548           12 :             info->nelems[i] = info->nelems[i - 1] / dims[i - 1];
    1549              : 
    1550           16 :         av = split_array(info, 0, nitems, 0);
    1551              :     }
    1552              : 
    1553           17 :     hv = newHV();
    1554           17 :     (void) hv_store(hv, "array", 5, av, 0);
    1555           17 :     (void) hv_store(hv, "typeoid", 7, newSVuv(typid), 0);
    1556              : 
    1557           17 :     return sv_bless(newRV_noinc((SV *) hv),
    1558              :                     gv_stashpv("PostgreSQL::InServer::ARRAY", 0));
    1559              : }
    1560              : 
    1561              : /*
    1562              :  * Recursively form array references from splices of the initial array
    1563              :  */
    1564              : static SV  *
    1565           96 : split_array(plperl_array_info *info, int first, int last, int nest)
    1566              : {
    1567           96 :     dTHX;
    1568              :     int         i;
    1569              :     AV         *result;
    1570              : 
    1571              :     /* we should only be called when we have something to split */
    1572              :     Assert(info->ndims > 0);
    1573              : 
    1574              :     /* since this function recurses, it could be driven to stack overflow */
    1575           96 :     check_stack_depth();
    1576              : 
    1577              :     /*
    1578              :      * Base case, return a reference to a single-dimensional array
    1579              :      */
    1580           96 :     if (nest >= info->ndims - 1)
    1581           57 :         return make_array_ref(info, first, last);
    1582              : 
    1583           39 :     result = newAV();
    1584          119 :     for (i = first; i < last; i += info->nelems[nest + 1])
    1585              :     {
    1586              :         /* Recursively form references to arrays of lower dimensions */
    1587           80 :         SV         *ref = split_array(info, i, i + info->nelems[nest + 1], nest + 1);
    1588              : 
    1589           80 :         av_push(result, ref);
    1590              :     }
    1591           39 :     return newRV_noinc((SV *) result);
    1592              : }
    1593              : 
    1594              : /*
    1595              :  * Create a Perl reference from a one-dimensional C array, converting
    1596              :  * composite type elements to hash references.
    1597              :  */
    1598              : static SV  *
    1599           57 : make_array_ref(plperl_array_info *info, int first, int last)
    1600              : {
    1601           57 :     dTHX;
    1602              :     int         i;
    1603           57 :     AV         *result = newAV();
    1604              : 
    1605          193 :     for (i = first; i < last; i++)
    1606              :     {
    1607          136 :         if (info->nulls[i])
    1608              :         {
    1609              :             /*
    1610              :              * We can't use &PL_sv_undef here.  See "AVs, HVs and undefined
    1611              :              * values" in perlguts.
    1612              :              */
    1613            4 :             av_push(result, newSV(0));
    1614              :         }
    1615              :         else
    1616              :         {
    1617          132 :             Datum       itemvalue = info->elements[i];
    1618              : 
    1619          132 :             if (info->transform_proc.fn_oid)
    1620            2 :                 av_push(result, (SV *) DatumGetPointer(FunctionCall1(&info->transform_proc, itemvalue)));
    1621          130 :             else if (info->elem_is_rowtype)
    1622              :                 /* Handle composite type elements */
    1623            4 :                 av_push(result, plperl_hash_from_datum(itemvalue));
    1624              :             else
    1625              :             {
    1626          126 :                 char       *val = OutputFunctionCall(&info->proc, itemvalue);
    1627              : 
    1628          126 :                 av_push(result, cstr2sv(val));
    1629              :             }
    1630              :         }
    1631              :     }
    1632           57 :     return newRV_noinc((SV *) result);
    1633              : }
    1634              : 
    1635              : /* Set up the arguments for a trigger call. */
    1636              : static SV  *
    1637           30 : plperl_trigger_build_args(FunctionCallInfo fcinfo)
    1638              : {
    1639           30 :     dTHX;
    1640              :     TriggerData *tdata;
    1641              :     TupleDesc   tupdesc;
    1642              :     int         i;
    1643              :     char       *level;
    1644              :     char       *event;
    1645              :     char       *relid;
    1646              :     char       *when;
    1647              :     HV         *hv;
    1648              : 
    1649           30 :     hv = newHV();
    1650           30 :     hv_ksplit(hv, 12);          /* pre-grow the hash */
    1651              : 
    1652           30 :     tdata = (TriggerData *) fcinfo->context;
    1653           30 :     tupdesc = tdata->tg_relation->rd_att;
    1654              : 
    1655           30 :     relid = DatumGetCString(DirectFunctionCall1(oidout,
    1656              :                                                 ObjectIdGetDatum(tdata->tg_relation->rd_id)));
    1657              : 
    1658           30 :     hv_store_string(hv, "name", cstr2sv(tdata->tg_trigger->tgname));
    1659           30 :     hv_store_string(hv, "relid", cstr2sv(relid));
    1660              : 
    1661              :     /*
    1662              :      * Note: In BEFORE trigger, stored generated columns are not computed yet,
    1663              :      * so don't make them accessible in NEW row.
    1664              :      */
    1665              : 
    1666           30 :     if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
    1667              :     {
    1668           12 :         event = "INSERT";
    1669           12 :         if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
    1670           12 :             hv_store_string(hv, "new",
    1671              :                             plperl_hash_from_tuple(tdata->tg_trigtuple,
    1672              :                                                    tupdesc,
    1673           12 :                                                    !TRIGGER_FIRED_BEFORE(tdata->tg_event)));
    1674              :     }
    1675           18 :     else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
    1676              :     {
    1677           10 :         event = "DELETE";
    1678           10 :         if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
    1679           10 :             hv_store_string(hv, "old",
    1680              :                             plperl_hash_from_tuple(tdata->tg_trigtuple,
    1681              :                                                    tupdesc,
    1682              :                                                    true));
    1683              :     }
    1684            8 :     else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
    1685              :     {
    1686            8 :         event = "UPDATE";
    1687            8 :         if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
    1688              :         {
    1689            7 :             hv_store_string(hv, "old",
    1690              :                             plperl_hash_from_tuple(tdata->tg_trigtuple,
    1691              :                                                    tupdesc,
    1692              :                                                    true));
    1693            7 :             hv_store_string(hv, "new",
    1694              :                             plperl_hash_from_tuple(tdata->tg_newtuple,
    1695              :                                                    tupdesc,
    1696            7 :                                                    !TRIGGER_FIRED_BEFORE(tdata->tg_event)));
    1697              :         }
    1698              :     }
    1699            0 :     else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
    1700            0 :         event = "TRUNCATE";
    1701              :     else
    1702            0 :         event = "UNKNOWN";
    1703              : 
    1704           30 :     hv_store_string(hv, "event", cstr2sv(event));
    1705           30 :     hv_store_string(hv, "argc", newSViv(tdata->tg_trigger->tgnargs));
    1706              : 
    1707           30 :     if (tdata->tg_trigger->tgnargs > 0)
    1708              :     {
    1709           12 :         AV         *av = newAV();
    1710              : 
    1711           12 :         av_extend(av, tdata->tg_trigger->tgnargs);
    1712           30 :         for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
    1713           18 :             av_push(av, cstr2sv(tdata->tg_trigger->tgargs[i]));
    1714           12 :         hv_store_string(hv, "args", newRV_noinc((SV *) av));
    1715              :     }
    1716              : 
    1717           30 :     hv_store_string(hv, "relname",
    1718           30 :                     cstr2sv(SPI_getrelname(tdata->tg_relation)));
    1719              : 
    1720           30 :     hv_store_string(hv, "table_name",
    1721           30 :                     cstr2sv(SPI_getrelname(tdata->tg_relation)));
    1722              : 
    1723           30 :     hv_store_string(hv, "table_schema",
    1724           30 :                     cstr2sv(SPI_getnspname(tdata->tg_relation)));
    1725              : 
    1726           30 :     if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
    1727           23 :         when = "BEFORE";
    1728            7 :     else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
    1729            4 :         when = "AFTER";
    1730            3 :     else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
    1731            3 :         when = "INSTEAD OF";
    1732              :     else
    1733            0 :         when = "UNKNOWN";
    1734           30 :     hv_store_string(hv, "when", cstr2sv(when));
    1735              : 
    1736           30 :     if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
    1737           29 :         level = "ROW";
    1738            1 :     else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
    1739            1 :         level = "STATEMENT";
    1740              :     else
    1741            0 :         level = "UNKNOWN";
    1742           30 :     hv_store_string(hv, "level", cstr2sv(level));
    1743              : 
    1744           30 :     return newRV_noinc((SV *) hv);
    1745              : }
    1746              : 
    1747              : 
    1748              : /* Set up the arguments for an event trigger call. */
    1749              : static SV  *
    1750           10 : plperl_event_trigger_build_args(FunctionCallInfo fcinfo)
    1751              : {
    1752           10 :     dTHX;
    1753              :     EventTriggerData *tdata;
    1754              :     HV         *hv;
    1755              : 
    1756           10 :     hv = newHV();
    1757              : 
    1758           10 :     tdata = (EventTriggerData *) fcinfo->context;
    1759              : 
    1760           10 :     hv_store_string(hv, "event", cstr2sv(tdata->event));
    1761           10 :     hv_store_string(hv, "tag", cstr2sv(GetCommandTagName(tdata->tag)));
    1762              : 
    1763           10 :     return newRV_noinc((SV *) hv);
    1764              : }
    1765              : 
    1766              : /* Construct the modified new tuple to be returned from a trigger. */
    1767              : static HeapTuple
    1768            6 : plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
    1769              : {
    1770            6 :     dTHX;
    1771              :     SV        **svp;
    1772              :     HV         *hvNew;
    1773              :     HE         *he;
    1774              :     HeapTuple   rtup;
    1775              :     TupleDesc   tupdesc;
    1776              :     int         natts;
    1777              :     Datum      *modvalues;
    1778              :     bool       *modnulls;
    1779              :     bool       *modrepls;
    1780              : 
    1781            6 :     svp = hv_fetch_string(hvTD, "new");
    1782            6 :     if (!svp)
    1783            0 :         ereport(ERROR,
    1784              :                 (errcode(ERRCODE_UNDEFINED_COLUMN),
    1785              :                  errmsg("$_TD->{new} does not exist")));
    1786            6 :     if (!SvOK(*svp) || !SvROK(*svp) || SvTYPE(SvRV(*svp)) != SVt_PVHV)
    1787            0 :         ereport(ERROR,
    1788              :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
    1789              :                  errmsg("$_TD->{new} is not a hash reference")));
    1790            6 :     hvNew = (HV *) SvRV(*svp);
    1791              : 
    1792            6 :     tupdesc = tdata->tg_relation->rd_att;
    1793            6 :     natts = tupdesc->natts;
    1794              : 
    1795            6 :     modvalues = (Datum *) palloc0(natts * sizeof(Datum));
    1796            6 :     modnulls = (bool *) palloc0(natts * sizeof(bool));
    1797            6 :     modrepls = (bool *) palloc0(natts * sizeof(bool));
    1798              : 
    1799            6 :     hv_iterinit(hvNew);
    1800           20 :     while ((he = hv_iternext(hvNew)))
    1801              :     {
    1802           15 :         char       *key = hek2cstr(he);
    1803           15 :         SV         *val = HeVAL(he);
    1804           15 :         int         attn = SPI_fnumber(tupdesc, key);
    1805              :         Form_pg_attribute attr;
    1806              : 
    1807           15 :         if (attn == SPI_ERROR_NOATTRIBUTE)
    1808            0 :             ereport(ERROR,
    1809              :                     (errcode(ERRCODE_UNDEFINED_COLUMN),
    1810              :                      errmsg("Perl hash contains nonexistent column \"%s\"",
    1811              :                             key)));
    1812           15 :         if (attn <= 0)
    1813            0 :             ereport(ERROR,
    1814              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1815              :                      errmsg("cannot set system attribute \"%s\"",
    1816              :                             key)));
    1817              : 
    1818           15 :         attr = TupleDescAttr(tupdesc, attn - 1);
    1819           15 :         if (attr->attgenerated)
    1820            1 :             ereport(ERROR,
    1821              :                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
    1822              :                      errmsg("cannot set generated column \"%s\"",
    1823              :                             key)));
    1824              : 
    1825           28 :         modvalues[attn - 1] = plperl_sv_to_datum(val,
    1826              :                                                  attr->atttypid,
    1827              :                                                  attr->atttypmod,
    1828              :                                                  NULL,
    1829              :                                                  NULL,
    1830              :                                                  InvalidOid,
    1831           14 :                                                  &modnulls[attn - 1]);
    1832           14 :         modrepls[attn - 1] = true;
    1833              : 
    1834           14 :         pfree(key);
    1835              :     }
    1836            5 :     hv_iterinit(hvNew);
    1837              : 
    1838            5 :     rtup = heap_modify_tuple(otup, tupdesc, modvalues, modnulls, modrepls);
    1839              : 
    1840            5 :     pfree(modvalues);
    1841            5 :     pfree(modnulls);
    1842            5 :     pfree(modrepls);
    1843              : 
    1844            5 :     return rtup;
    1845              : }
    1846              : 
    1847              : 
    1848              : /*
    1849              :  * There are three externally visible pieces to plperl: plperl_call_handler,
    1850              :  * plperl_inline_handler, and plperl_validator.
    1851              :  */
    1852              : 
    1853              : /*
    1854              :  * The call handler is called to run normal functions (including trigger
    1855              :  * functions) that are defined in pg_proc.
    1856              :  */
    1857           22 : PG_FUNCTION_INFO_V1(plperl_call_handler);
    1858              : 
    1859              : Datum
    1860          274 : plperl_call_handler(PG_FUNCTION_ARGS)
    1861              : {
    1862          274 :     Datum       retval = (Datum) 0;
    1863          274 :     plperl_call_data *volatile save_call_data = current_call_data;
    1864          274 :     plperl_interp_desc *volatile oldinterp = plperl_active_interp;
    1865              :     plperl_call_data this_call_data;
    1866              : 
    1867              :     /* Initialize current-call status record */
    1868         2192 :     MemSet(&this_call_data, 0, sizeof(this_call_data));
    1869          274 :     this_call_data.fcinfo = fcinfo;
    1870              : 
    1871          274 :     PG_TRY();
    1872              :     {
    1873          274 :         current_call_data = &this_call_data;
    1874          274 :         if (CALLED_AS_TRIGGER(fcinfo))
    1875           30 :             retval = plperl_trigger_handler(fcinfo);
    1876          244 :         else if (CALLED_AS_EVENT_TRIGGER(fcinfo))
    1877              :         {
    1878           10 :             plperl_event_trigger_handler(fcinfo);
    1879           10 :             retval = (Datum) 0;
    1880              :         }
    1881              :         else
    1882          234 :             retval = plperl_func_handler(fcinfo);
    1883              :     }
    1884           42 :     PG_FINALLY();
    1885              :     {
    1886          274 :         current_call_data = save_call_data;
    1887          274 :         activate_interpreter(oldinterp);
    1888          274 :         if (this_call_data.prodesc)
    1889          273 :             decrement_prodesc_refcount(this_call_data.prodesc);
    1890              :     }
    1891          274 :     PG_END_TRY();
    1892              : 
    1893          232 :     return retval;
    1894              : }
    1895              : 
    1896              : /*
    1897              :  * The inline handler runs anonymous code blocks (DO blocks).
    1898              :  */
    1899           12 : PG_FUNCTION_INFO_V1(plperl_inline_handler);
    1900              : 
    1901              : Datum
    1902           22 : plperl_inline_handler(PG_FUNCTION_ARGS)
    1903              : {
    1904           22 :     LOCAL_FCINFO(fake_fcinfo, 0);
    1905           22 :     InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0);
    1906              :     FmgrInfo    flinfo;
    1907              :     plperl_proc_desc desc;
    1908           22 :     plperl_call_data *volatile save_call_data = current_call_data;
    1909           22 :     plperl_interp_desc *volatile oldinterp = plperl_active_interp;
    1910              :     plperl_call_data this_call_data;
    1911              :     ErrorContextCallback pl_error_context;
    1912              : 
    1913              :     /* Initialize current-call status record */
    1914          176 :     MemSet(&this_call_data, 0, sizeof(this_call_data));
    1915              : 
    1916              :     /* Set up a callback for error reporting */
    1917           22 :     pl_error_context.callback = plperl_inline_callback;
    1918           22 :     pl_error_context.previous = error_context_stack;
    1919           22 :     pl_error_context.arg = NULL;
    1920           22 :     error_context_stack = &pl_error_context;
    1921              : 
    1922              :     /*
    1923              :      * Set up a fake fcinfo and descriptor with just enough info to satisfy
    1924              :      * plperl_call_perl_func().  In particular note that this sets things up
    1925              :      * with no arguments passed, and a result type of VOID.
    1926              :      */
    1927          110 :     MemSet(fake_fcinfo, 0, SizeForFunctionCallInfo(0));
    1928          154 :     MemSet(&flinfo, 0, sizeof(flinfo));
    1929          462 :     MemSet(&desc, 0, sizeof(desc));
    1930           22 :     fake_fcinfo->flinfo = &flinfo;
    1931           22 :     flinfo.fn_oid = InvalidOid;
    1932           22 :     flinfo.fn_mcxt = CurrentMemoryContext;
    1933              : 
    1934           22 :     desc.proname = "inline_code_block";
    1935           22 :     desc.fn_readonly = false;
    1936              : 
    1937           22 :     desc.lang_oid = codeblock->langOid;
    1938           22 :     desc.trftypes = NIL;
    1939           22 :     desc.lanpltrusted = codeblock->langIsTrusted;
    1940              : 
    1941           22 :     desc.fn_retistuple = false;
    1942           22 :     desc.fn_retisset = false;
    1943           22 :     desc.fn_retisarray = false;
    1944           22 :     desc.result_oid = InvalidOid;
    1945           22 :     desc.nargs = 0;
    1946           22 :     desc.reference = NULL;
    1947              : 
    1948           22 :     this_call_data.fcinfo = fake_fcinfo;
    1949           22 :     this_call_data.prodesc = &desc;
    1950              :     /* we do not bother with refcounting the fake prodesc */
    1951              : 
    1952           22 :     PG_TRY();
    1953              :     {
    1954              :         SV         *perlret;
    1955              : 
    1956           22 :         current_call_data = &this_call_data;
    1957              : 
    1958           22 :         SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC);
    1959              : 
    1960           22 :         select_perl_context(desc.lanpltrusted);
    1961              : 
    1962           21 :         plperl_create_sub(&desc, codeblock->source_text, 0);
    1963              : 
    1964           16 :         if (!desc.reference)    /* can this happen? */
    1965            0 :             elog(ERROR, "could not create internal procedure for anonymous code block");
    1966              : 
    1967           16 :         perlret = plperl_call_perl_func(&desc, fake_fcinfo);
    1968              : 
    1969           11 :         SvREFCNT_dec_current(perlret);
    1970              : 
    1971           11 :         if (SPI_finish() != SPI_OK_FINISH)
    1972            0 :             elog(ERROR, "SPI_finish() failed");
    1973              :     }
    1974           11 :     PG_FINALLY();
    1975              :     {
    1976           22 :         if (desc.reference)
    1977           16 :             SvREFCNT_dec_current(desc.reference);
    1978           22 :         current_call_data = save_call_data;
    1979           22 :         activate_interpreter(oldinterp);
    1980              :     }
    1981           22 :     PG_END_TRY();
    1982              : 
    1983           11 :     error_context_stack = pl_error_context.previous;
    1984              : 
    1985           11 :     PG_RETURN_VOID();
    1986              : }
    1987              : 
    1988              : /*
    1989              :  * The validator is called during CREATE FUNCTION to validate the function
    1990              :  * being created/replaced. The precise behavior of the validator may be
    1991              :  * modified by the check_function_bodies GUC.
    1992              :  */
    1993           22 : PG_FUNCTION_INFO_V1(plperl_validator);
    1994              : 
    1995              : Datum
    1996          152 : plperl_validator(PG_FUNCTION_ARGS)
    1997              : {
    1998          152 :     Oid         funcoid = PG_GETARG_OID(0);
    1999              :     HeapTuple   tuple;
    2000              :     Form_pg_proc proc;
    2001              :     char        functyptype;
    2002              :     int         numargs;
    2003              :     Oid        *argtypes;
    2004              :     char      **argnames;
    2005              :     char       *argmodes;
    2006          152 :     bool        is_trigger = false;
    2007          152 :     bool        is_event_trigger = false;
    2008              :     int         i;
    2009              : 
    2010          152 :     if (!CheckFunctionValidatorAccess(fcinfo->flinfo->fn_oid, funcoid))
    2011            0 :         PG_RETURN_VOID();
    2012              : 
    2013              :     /* Get the new function's pg_proc entry */
    2014          152 :     tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcoid));
    2015          152 :     if (!HeapTupleIsValid(tuple))
    2016            0 :         elog(ERROR, "cache lookup failed for function %u", funcoid);
    2017          152 :     proc = (Form_pg_proc) GETSTRUCT(tuple);
    2018              : 
    2019          152 :     functyptype = get_typtype(proc->prorettype);
    2020              : 
    2021              :     /* Disallow pseudotype result */
    2022              :     /* except for TRIGGER, EVTTRIGGER, RECORD, or VOID */
    2023          152 :     if (functyptype == TYPTYPE_PSEUDO)
    2024              :     {
    2025           38 :         if (proc->prorettype == TRIGGEROID)
    2026            8 :             is_trigger = true;
    2027           30 :         else if (proc->prorettype == EVENT_TRIGGEROID)
    2028            1 :             is_event_trigger = true;
    2029           29 :         else if (proc->prorettype != RECORDOID &&
    2030           18 :                  proc->prorettype != VOIDOID)
    2031            0 :             ereport(ERROR,
    2032              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2033              :                      errmsg("PL/Perl functions cannot return type %s",
    2034              :                             format_type_be(proc->prorettype))));
    2035              :     }
    2036              : 
    2037              :     /* Disallow pseudotypes in arguments (either IN or OUT) */
    2038          152 :     numargs = get_func_arg_info(tuple,
    2039              :                                 &argtypes, &argnames, &argmodes);
    2040          225 :     for (i = 0; i < numargs; i++)
    2041              :     {
    2042           73 :         if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO &&
    2043            1 :             argtypes[i] != RECORDOID)
    2044            0 :             ereport(ERROR,
    2045              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2046              :                      errmsg("PL/Perl functions cannot accept type %s",
    2047              :                             format_type_be(argtypes[i]))));
    2048              :     }
    2049              : 
    2050          152 :     ReleaseSysCache(tuple);
    2051              : 
    2052              :     /* Postpone body checks if !check_function_bodies */
    2053          152 :     if (check_function_bodies)
    2054              :     {
    2055          152 :         (void) compile_plperl_function(funcoid, is_trigger, is_event_trigger);
    2056              :     }
    2057              : 
    2058              :     /* the result of a validator is ignored */
    2059          149 :     PG_RETURN_VOID();
    2060              : }
    2061              : 
    2062              : 
    2063              : /*
    2064              :  * plperlu likewise requires three externally visible functions:
    2065              :  * plperlu_call_handler, plperlu_inline_handler, and plperlu_validator.
    2066              :  * These are currently just aliases that send control to the plperl
    2067              :  * handler functions, and we decide whether a particular function is
    2068              :  * trusted or not by inspecting the actual pg_language tuple.
    2069              :  */
    2070              : 
    2071            8 : PG_FUNCTION_INFO_V1(plperlu_call_handler);
    2072              : 
    2073              : Datum
    2074           50 : plperlu_call_handler(PG_FUNCTION_ARGS)
    2075              : {
    2076           50 :     return plperl_call_handler(fcinfo);
    2077              : }
    2078              : 
    2079            5 : PG_FUNCTION_INFO_V1(plperlu_inline_handler);
    2080              : 
    2081              : Datum
    2082            1 : plperlu_inline_handler(PG_FUNCTION_ARGS)
    2083              : {
    2084            1 :     return plperl_inline_handler(fcinfo);
    2085              : }
    2086              : 
    2087            9 : PG_FUNCTION_INFO_V1(plperlu_validator);
    2088              : 
    2089              : Datum
    2090           24 : plperlu_validator(PG_FUNCTION_ARGS)
    2091              : {
    2092              :     /* call plperl validator with our fcinfo so it gets our oid */
    2093           24 :     return plperl_validator(fcinfo);
    2094              : }
    2095              : 
    2096              : 
    2097              : /*
    2098              :  * Uses mkfunc to create a subroutine whose text is
    2099              :  * supplied in s, and returns a reference to it
    2100              :  */
    2101              : static void
    2102          173 : plperl_create_sub(plperl_proc_desc *prodesc, const char *s, Oid fn_oid)
    2103              : {
    2104          173 :     dTHX;
    2105          173 :     dSP;
    2106              :     char        subname[NAMEDATALEN + 40];
    2107          173 :     HV         *pragma_hv = newHV();
    2108          173 :     SV         *subref = NULL;
    2109              :     int         count;
    2110              : 
    2111          173 :     sprintf(subname, "%s__%u", prodesc->proname, fn_oid);
    2112              : 
    2113          173 :     if (plperl_use_strict)
    2114            1 :         hv_store_string(pragma_hv, "strict", (SV *) newAV());
    2115              : 
    2116          173 :     ENTER;
    2117          173 :     SAVETMPS;
    2118          173 :     PUSHMARK(SP);
    2119          173 :     EXTEND(SP, 4);
    2120          173 :     PUSHs(sv_2mortal(cstr2sv(subname)));
    2121          173 :     PUSHs(sv_2mortal(newRV_noinc((SV *) pragma_hv)));
    2122              : 
    2123              :     /*
    2124              :      * Use 'false' for $prolog in mkfunc, which is kept for compatibility in
    2125              :      * case a module such as PostgreSQL::PLPerl::NYTprof replaces the function
    2126              :      * compiler.
    2127              :      */
    2128          173 :     PUSHs(&PL_sv_no);
    2129          173 :     PUSHs(sv_2mortal(cstr2sv(s)));
    2130          173 :     PUTBACK;
    2131              : 
    2132              :     /*
    2133              :      * G_KEEPERR seems to be needed here, else we don't recognize compile
    2134              :      * errors properly.  Perhaps it's because there's another level of eval
    2135              :      * inside mkfunc?
    2136              :      */
    2137          173 :     count = call_pv("PostgreSQL::InServer::mkfunc",
    2138              :                     G_SCALAR | G_EVAL | G_KEEPERR);
    2139          173 :     SPAGAIN;
    2140              : 
    2141          173 :     if (count == 1)
    2142              :     {
    2143          173 :         SV         *sub_rv = (SV *) POPs;
    2144              : 
    2145          173 :         if (sub_rv && SvROK(sub_rv) && SvTYPE(SvRV(sub_rv)) == SVt_PVCV)
    2146              :         {
    2147          165 :             subref = newRV_inc(SvRV(sub_rv));
    2148              :         }
    2149              :     }
    2150              : 
    2151          173 :     PUTBACK;
    2152          173 :     FREETMPS;
    2153          173 :     LEAVE;
    2154              : 
    2155          173 :     if (SvTRUE(ERRSV))
    2156            8 :         ereport(ERROR,
    2157              :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2158              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
    2159              : 
    2160          165 :     if (!subref)
    2161            0 :         ereport(ERROR,
    2162              :                 (errcode(ERRCODE_SYNTAX_ERROR),
    2163              :                  errmsg("didn't get a CODE reference from compiling function \"%s\"",
    2164              :                         prodesc->proname)));
    2165              : 
    2166          165 :     prodesc->reference = subref;
    2167          165 : }
    2168              : 
    2169              : 
    2170              : /**********************************************************************
    2171              :  * plperl_init_shared_libs()        -
    2172              :  **********************************************************************/
    2173              : 
    2174              : static void
    2175           25 : plperl_init_shared_libs(pTHX)
    2176              : {
    2177           25 :     char       *file = __FILE__;
    2178              : 
    2179           25 :     newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
    2180           25 :     newXS("PostgreSQL::InServer::Util::bootstrap",
    2181              :           boot_PostgreSQL__InServer__Util, file);
    2182              :     /* newXS for...::SPI::bootstrap is in select_perl_context() */
    2183           25 : }
    2184              : 
    2185              : 
    2186              : static SV  *
    2187          249 : plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
    2188              : {
    2189          249 :     dTHX;
    2190          249 :     dSP;
    2191              :     SV         *retval;
    2192              :     int         i;
    2193              :     int         count;
    2194          249 :     Oid        *argtypes = NULL;
    2195          249 :     int         nargs = 0;
    2196              : 
    2197          249 :     ENTER;
    2198          249 :     SAVETMPS;
    2199              : 
    2200          249 :     PUSHMARK(SP);
    2201          249 :     EXTEND(sp, desc->nargs);
    2202              : 
    2203              :     /* Get signature for true functions; inline blocks have no args. */
    2204          249 :     if (fcinfo->flinfo->fn_oid)
    2205          233 :         get_func_signature(fcinfo->flinfo->fn_oid, &argtypes, &nargs);
    2206              :     Assert(nargs == desc->nargs);
    2207              : 
    2208          441 :     for (i = 0; i < desc->nargs; i++)
    2209              :     {
    2210          192 :         if (fcinfo->args[i].isnull)
    2211            4 :             PUSHs(&PL_sv_undef);
    2212          188 :         else if (desc->arg_is_rowtype[i])
    2213              :         {
    2214           11 :             SV         *sv = plperl_hash_from_datum(fcinfo->args[i].value);
    2215              : 
    2216           11 :             PUSHs(sv_2mortal(sv));
    2217              :         }
    2218              :         else
    2219              :         {
    2220              :             SV         *sv;
    2221              :             Oid         funcid;
    2222              : 
    2223          177 :             if (OidIsValid(desc->arg_arraytype[i]))
    2224           13 :                 sv = plperl_ref_from_pg_array(fcinfo->args[i].value, desc->arg_arraytype[i]);
    2225          164 :             else if ((funcid = get_transform_fromsql(argtypes[i], current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
    2226           57 :                 sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->args[i].value));
    2227              :             else
    2228              :             {
    2229              :                 char       *tmp;
    2230              : 
    2231          107 :                 tmp = OutputFunctionCall(&(desc->arg_out_func[i]),
    2232              :                                          fcinfo->args[i].value);
    2233          107 :                 sv = cstr2sv(tmp);
    2234          107 :                 pfree(tmp);
    2235              :             }
    2236              : 
    2237          177 :             PUSHs(sv_2mortal(sv));
    2238              :         }
    2239              :     }
    2240          249 :     PUTBACK;
    2241              : 
    2242              :     /* Do NOT use G_KEEPERR here */
    2243          249 :     count = call_sv(desc->reference, G_SCALAR | G_EVAL);
    2244              : 
    2245          248 :     SPAGAIN;
    2246              : 
    2247          248 :     if (count != 1)
    2248              :     {
    2249            0 :         PUTBACK;
    2250            0 :         FREETMPS;
    2251            0 :         LEAVE;
    2252            0 :         ereport(ERROR,
    2253              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2254              :                  errmsg("didn't get a return item from function")));
    2255              :     }
    2256              : 
    2257          248 :     if (SvTRUE(ERRSV))
    2258              :     {
    2259           18 :         (void) POPs;
    2260           18 :         PUTBACK;
    2261           18 :         FREETMPS;
    2262           18 :         LEAVE;
    2263              :         /* XXX need to find a way to determine a better errcode here */
    2264           18 :         ereport(ERROR,
    2265              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2266              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
    2267              :     }
    2268              : 
    2269          230 :     retval = newSVsv(POPs);
    2270              : 
    2271          230 :     PUTBACK;
    2272          230 :     FREETMPS;
    2273          230 :     LEAVE;
    2274              : 
    2275          230 :     return retval;
    2276              : }
    2277              : 
    2278              : 
    2279              : static SV  *
    2280           30 : plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
    2281              :                               SV *td)
    2282              : {
    2283           30 :     dTHX;
    2284           30 :     dSP;
    2285              :     SV         *retval,
    2286              :                *TDsv;
    2287              :     int         i,
    2288              :                 count;
    2289           30 :     Trigger    *tg_trigger = ((TriggerData *) fcinfo->context)->tg_trigger;
    2290              : 
    2291           30 :     ENTER;
    2292           30 :     SAVETMPS;
    2293              : 
    2294           30 :     TDsv = get_sv("main::_TD", 0);
    2295           30 :     if (!TDsv)
    2296            0 :         ereport(ERROR,
    2297              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2298              :                  errmsg("couldn't fetch $_TD")));
    2299              : 
    2300           30 :     save_item(TDsv);            /* local $_TD */
    2301           30 :     sv_setsv(TDsv, td);
    2302              : 
    2303           30 :     PUSHMARK(sp);
    2304           30 :     EXTEND(sp, tg_trigger->tgnargs);
    2305              : 
    2306           48 :     for (i = 0; i < tg_trigger->tgnargs; i++)
    2307           18 :         PUSHs(sv_2mortal(cstr2sv(tg_trigger->tgargs[i])));
    2308           30 :     PUTBACK;
    2309              : 
    2310              :     /* Do NOT use G_KEEPERR here */
    2311           30 :     count = call_sv(desc->reference, G_SCALAR | G_EVAL);
    2312              : 
    2313           30 :     SPAGAIN;
    2314              : 
    2315           30 :     if (count != 1)
    2316              :     {
    2317            0 :         PUTBACK;
    2318            0 :         FREETMPS;
    2319            0 :         LEAVE;
    2320            0 :         ereport(ERROR,
    2321              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2322              :                  errmsg("didn't get a return item from trigger function")));
    2323              :     }
    2324              : 
    2325           30 :     if (SvTRUE(ERRSV))
    2326              :     {
    2327            0 :         (void) POPs;
    2328            0 :         PUTBACK;
    2329            0 :         FREETMPS;
    2330            0 :         LEAVE;
    2331              :         /* XXX need to find a way to determine a better errcode here */
    2332            0 :         ereport(ERROR,
    2333              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2334              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
    2335              :     }
    2336              : 
    2337           30 :     retval = newSVsv(POPs);
    2338              : 
    2339           30 :     PUTBACK;
    2340           30 :     FREETMPS;
    2341           30 :     LEAVE;
    2342              : 
    2343           30 :     return retval;
    2344              : }
    2345              : 
    2346              : 
    2347              : static void
    2348           10 : plperl_call_perl_event_trigger_func(plperl_proc_desc *desc,
    2349              :                                     FunctionCallInfo fcinfo,
    2350              :                                     SV *td)
    2351              : {
    2352           10 :     dTHX;
    2353           10 :     dSP;
    2354              :     SV         *retval,
    2355              :                *TDsv;
    2356              :     int         count;
    2357              : 
    2358           10 :     ENTER;
    2359           10 :     SAVETMPS;
    2360              : 
    2361           10 :     TDsv = get_sv("main::_TD", 0);
    2362           10 :     if (!TDsv)
    2363            0 :         ereport(ERROR,
    2364              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2365              :                  errmsg("couldn't fetch $_TD")));
    2366              : 
    2367           10 :     save_item(TDsv);            /* local $_TD */
    2368           10 :     sv_setsv(TDsv, td);
    2369              : 
    2370           10 :     PUSHMARK(sp);
    2371           10 :     PUTBACK;
    2372              : 
    2373              :     /* Do NOT use G_KEEPERR here */
    2374           10 :     count = call_sv(desc->reference, G_SCALAR | G_EVAL);
    2375              : 
    2376           10 :     SPAGAIN;
    2377              : 
    2378           10 :     if (count != 1)
    2379              :     {
    2380            0 :         PUTBACK;
    2381            0 :         FREETMPS;
    2382            0 :         LEAVE;
    2383            0 :         ereport(ERROR,
    2384              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2385              :                  errmsg("didn't get a return item from trigger function")));
    2386              :     }
    2387              : 
    2388           10 :     if (SvTRUE(ERRSV))
    2389              :     {
    2390            0 :         (void) POPs;
    2391            0 :         PUTBACK;
    2392            0 :         FREETMPS;
    2393            0 :         LEAVE;
    2394              :         /* XXX need to find a way to determine a better errcode here */
    2395            0 :         ereport(ERROR,
    2396              :                 (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
    2397              :                  errmsg("%s", strip_trailing_ws(sv2cstr(ERRSV)))));
    2398              :     }
    2399              : 
    2400           10 :     retval = newSVsv(POPs);
    2401              :     (void) retval;              /* silence compiler warning */
    2402              : 
    2403           10 :     PUTBACK;
    2404           10 :     FREETMPS;
    2405           10 :     LEAVE;
    2406           10 : }
    2407              : 
    2408              : static Datum
    2409          234 : plperl_func_handler(PG_FUNCTION_ARGS)
    2410              : {
    2411              :     bool        nonatomic;
    2412              :     plperl_proc_desc *prodesc;
    2413              :     SV         *perlret;
    2414          234 :     Datum       retval = 0;
    2415              :     ReturnSetInfo *rsi;
    2416              :     ErrorContextCallback pl_error_context;
    2417              : 
    2418          476 :     nonatomic = fcinfo->context &&
    2419          242 :         IsA(fcinfo->context, CallContext) &&
    2420            8 :         !castNode(CallContext, fcinfo->context)->atomic;
    2421              : 
    2422          234 :     SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0);
    2423              : 
    2424          234 :     prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false, false);
    2425          233 :     current_call_data->prodesc = prodesc;
    2426          233 :     increment_prodesc_refcount(prodesc);
    2427              : 
    2428              :     /* Set a callback for error reporting */
    2429          233 :     pl_error_context.callback = plperl_exec_callback;
    2430          233 :     pl_error_context.previous = error_context_stack;
    2431          233 :     pl_error_context.arg = prodesc->proname;
    2432          233 :     error_context_stack = &pl_error_context;
    2433              : 
    2434          233 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    2435              : 
    2436          233 :     if (prodesc->fn_retisset)
    2437              :     {
    2438              :         /* Check context before allowing the call to go through */
    2439           43 :         if (!rsi || !IsA(rsi, ReturnSetInfo))
    2440            0 :             ereport(ERROR,
    2441              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2442              :                      errmsg("set-valued function called in context that cannot accept a set")));
    2443              : 
    2444           43 :         if (!(rsi->allowedModes & SFRM_Materialize))
    2445            0 :             ereport(ERROR,
    2446              :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2447              :                      errmsg("materialize mode required, but it is not allowed in this context")));
    2448              :     }
    2449              : 
    2450          233 :     activate_interpreter(prodesc->interp);
    2451              : 
    2452          233 :     perlret = plperl_call_perl_func(prodesc, fcinfo);
    2453              : 
    2454              :     /************************************************************
    2455              :      * Disconnect from SPI manager and then create the return
    2456              :      * values datum (if the input function does a palloc for it
    2457              :      * this must not be allocated in the SPI memory context
    2458              :      * because SPI_finish would free it).
    2459              :      ************************************************************/
    2460          219 :     if (SPI_finish() != SPI_OK_FINISH)
    2461            0 :         elog(ERROR, "SPI_finish() failed");
    2462              : 
    2463          219 :     if (prodesc->fn_retisset)
    2464              :     {
    2465              :         SV         *sav;
    2466              : 
    2467              :         /*
    2468              :          * If the Perl function returned an arrayref, we pretend that it
    2469              :          * called return_next() for each element of the array, to handle old
    2470              :          * SRFs that didn't know about return_next(). Any other sort of return
    2471              :          * value is an error, except undef which means return an empty set.
    2472              :          */
    2473           42 :         sav = get_perl_array_ref(perlret);
    2474           42 :         if (sav)
    2475              :         {
    2476           18 :             dTHX;
    2477           18 :             int         i = 0;
    2478           18 :             SV        **svp = 0;
    2479           18 :             AV         *rav = (AV *) SvRV(sav);
    2480              : 
    2481           64 :             while ((svp = av_fetch(rav, i, FALSE)) != NULL)
    2482              :             {
    2483           54 :                 plperl_return_next_internal(*svp);
    2484           46 :                 i++;
    2485              :             }
    2486              :         }
    2487           24 :         else if (SvOK(perlret))
    2488              :         {
    2489            2 :             ereport(ERROR,
    2490              :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    2491              :                      errmsg("set-returning PL/Perl function must return "
    2492              :                             "reference to array or use return_next")));
    2493              :         }
    2494              : 
    2495           32 :         rsi->returnMode = SFRM_Materialize;
    2496           32 :         if (current_call_data->tuple_store)
    2497              :         {
    2498           26 :             rsi->setResult = current_call_data->tuple_store;
    2499           26 :             rsi->setDesc = current_call_data->ret_tdesc;
    2500              :         }
    2501           32 :         retval = (Datum) 0;
    2502              :     }
    2503          177 :     else if (prodesc->result_oid)
    2504              :     {
    2505          177 :         retval = plperl_sv_to_datum(perlret,
    2506              :                                     prodesc->result_oid,
    2507              :                                     -1,
    2508              :                                     fcinfo,
    2509              :                                     &prodesc->result_in_func,
    2510              :                                     prodesc->result_typioparam,
    2511              :                                     &fcinfo->isnull);
    2512              : 
    2513          161 :         if (fcinfo->isnull && rsi && IsA(rsi, ReturnSetInfo))
    2514            3 :             rsi->isDone = ExprEndResult;
    2515              :     }
    2516              : 
    2517              :     /* Restore the previous error callback */
    2518          193 :     error_context_stack = pl_error_context.previous;
    2519              : 
    2520          193 :     SvREFCNT_dec_current(perlret);
    2521              : 
    2522          193 :     return retval;
    2523              : }
    2524              : 
    2525              : 
    2526              : static Datum
    2527           30 : plperl_trigger_handler(PG_FUNCTION_ARGS)
    2528              : {
    2529              :     plperl_proc_desc *prodesc;
    2530              :     SV         *perlret;
    2531              :     Datum       retval;
    2532              :     SV         *svTD;
    2533              :     HV         *hvTD;
    2534              :     ErrorContextCallback pl_error_context;
    2535              :     TriggerData *tdata;
    2536              :     int         rc PG_USED_FOR_ASSERTS_ONLY;
    2537              : 
    2538              :     /* Connect to SPI manager */
    2539           30 :     SPI_connect();
    2540              : 
    2541              :     /* Make transition tables visible to this SPI connection */
    2542           30 :     tdata = (TriggerData *) fcinfo->context;
    2543           30 :     rc = SPI_register_trigger_data(tdata);
    2544              :     Assert(rc >= 0);
    2545              : 
    2546              :     /* Find or compile the function */
    2547           30 :     prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, true, false);
    2548           30 :     current_call_data->prodesc = prodesc;
    2549           30 :     increment_prodesc_refcount(prodesc);
    2550              : 
    2551              :     /* Set a callback for error reporting */
    2552           30 :     pl_error_context.callback = plperl_exec_callback;
    2553           30 :     pl_error_context.previous = error_context_stack;
    2554           30 :     pl_error_context.arg = prodesc->proname;
    2555           30 :     error_context_stack = &pl_error_context;
    2556              : 
    2557           30 :     activate_interpreter(prodesc->interp);
    2558              : 
    2559           30 :     svTD = plperl_trigger_build_args(fcinfo);
    2560           30 :     perlret = plperl_call_perl_trigger_func(prodesc, fcinfo, svTD);
    2561           30 :     hvTD = (HV *) SvRV(svTD);
    2562              : 
    2563              :     /************************************************************
    2564              :     * Disconnect from SPI manager and then create the return
    2565              :     * values datum (if the input function does a palloc for it
    2566              :     * this must not be allocated in the SPI memory context
    2567              :     * because SPI_finish would free it).
    2568              :     ************************************************************/
    2569           30 :     if (SPI_finish() != SPI_OK_FINISH)
    2570            0 :         elog(ERROR, "SPI_finish() failed");
    2571              : 
    2572           30 :     if (perlret == NULL || !SvOK(perlret))
    2573           21 :     {
    2574              :         /* undef result means go ahead with original tuple */
    2575           21 :         TriggerData *trigdata = ((TriggerData *) fcinfo->context);
    2576              : 
    2577           21 :         if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
    2578            7 :             retval = PointerGetDatum(trigdata->tg_trigtuple);
    2579           14 :         else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
    2580            5 :             retval = PointerGetDatum(trigdata->tg_newtuple);
    2581            9 :         else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
    2582            9 :             retval = PointerGetDatum(trigdata->tg_trigtuple);
    2583            0 :         else if (TRIGGER_FIRED_BY_TRUNCATE(trigdata->tg_event))
    2584            0 :             retval = PointerGetDatum(trigdata->tg_trigtuple);
    2585              :         else
    2586            0 :             retval = (Datum) 0; /* can this happen? */
    2587              :     }
    2588              :     else
    2589              :     {
    2590              :         HeapTuple   trv;
    2591              :         char       *tmp;
    2592              : 
    2593            9 :         tmp = sv2cstr(perlret);
    2594              : 
    2595            9 :         if (pg_strcasecmp(tmp, "SKIP") == 0)
    2596            3 :             trv = NULL;
    2597            6 :         else if (pg_strcasecmp(tmp, "MODIFY") == 0)
    2598              :         {
    2599            6 :             TriggerData *trigdata = (TriggerData *) fcinfo->context;
    2600              : 
    2601            6 :             if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
    2602            4 :                 trv = plperl_modify_tuple(hvTD, trigdata,
    2603              :                                           trigdata->tg_trigtuple);
    2604            2 :             else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
    2605            2 :                 trv = plperl_modify_tuple(hvTD, trigdata,
    2606              :                                           trigdata->tg_newtuple);
    2607              :             else
    2608              :             {
    2609            0 :                 ereport(WARNING,
    2610              :                         (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
    2611              :                          errmsg("ignoring modified row in DELETE trigger")));
    2612            0 :                 trv = NULL;
    2613              :             }
    2614              :         }
    2615              :         else
    2616              :         {
    2617            0 :             ereport(ERROR,
    2618              :                     (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
    2619              :                      errmsg("result of PL/Perl trigger function must be undef, "
    2620              :                             "\"SKIP\", or \"MODIFY\"")));
    2621              :             trv = NULL;
    2622              :         }
    2623            8 :         retval = PointerGetDatum(trv);
    2624            8 :         pfree(tmp);
    2625              :     }
    2626              : 
    2627              :     /* Restore the previous error callback */
    2628           29 :     error_context_stack = pl_error_context.previous;
    2629              : 
    2630           29 :     SvREFCNT_dec_current(svTD);
    2631           29 :     if (perlret)
    2632           29 :         SvREFCNT_dec_current(perlret);
    2633              : 
    2634           29 :     return retval;
    2635              : }
    2636              : 
    2637              : 
    2638              : static void
    2639           10 : plperl_event_trigger_handler(PG_FUNCTION_ARGS)
    2640              : {
    2641              :     plperl_proc_desc *prodesc;
    2642              :     SV         *svTD;
    2643              :     ErrorContextCallback pl_error_context;
    2644              : 
    2645              :     /* Connect to SPI manager */
    2646           10 :     SPI_connect();
    2647              : 
    2648              :     /* Find or compile the function */
    2649           10 :     prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false, true);
    2650           10 :     current_call_data->prodesc = prodesc;
    2651           10 :     increment_prodesc_refcount(prodesc);
    2652              : 
    2653              :     /* Set a callback for error reporting */
    2654           10 :     pl_error_context.callback = plperl_exec_callback;
    2655           10 :     pl_error_context.previous = error_context_stack;
    2656           10 :     pl_error_context.arg = prodesc->proname;
    2657           10 :     error_context_stack = &pl_error_context;
    2658              : 
    2659           10 :     activate_interpreter(prodesc->interp);
    2660              : 
    2661           10 :     svTD = plperl_event_trigger_build_args(fcinfo);
    2662           10 :     plperl_call_perl_event_trigger_func(prodesc, fcinfo, svTD);
    2663              : 
    2664           10 :     if (SPI_finish() != SPI_OK_FINISH)
    2665            0 :         elog(ERROR, "SPI_finish() failed");
    2666              : 
    2667              :     /* Restore the previous error callback */
    2668           10 :     error_context_stack = pl_error_context.previous;
    2669              : 
    2670           10 :     SvREFCNT_dec_current(svTD);
    2671           10 : }
    2672              : 
    2673              : 
    2674              : static bool
    2675          629 : validate_plperl_function(plperl_proc_ptr *proc_ptr, HeapTuple procTup)
    2676              : {
    2677          629 :     if (proc_ptr && proc_ptr->proc_ptr)
    2678              :     {
    2679          301 :         plperl_proc_desc *prodesc = proc_ptr->proc_ptr;
    2680              :         bool        uptodate;
    2681              : 
    2682              :         /************************************************************
    2683              :          * If it's present, must check whether it's still up to date.
    2684              :          * This is needed because CREATE OR REPLACE FUNCTION can modify the
    2685              :          * function's pg_proc entry without changing its OID.
    2686              :          ************************************************************/
    2687          574 :         uptodate = (prodesc->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) &&
    2688          273 :                     ItemPointerEquals(&prodesc->fn_tid, &procTup->t_self));
    2689              : 
    2690          301 :         if (uptodate)
    2691          273 :             return true;
    2692              : 
    2693              :         /* Otherwise, unlink the obsoleted entry from the hashtable ... */
    2694           28 :         proc_ptr->proc_ptr = NULL;
    2695              :         /* ... and release the corresponding refcount, probably deleting it */
    2696           28 :         decrement_prodesc_refcount(prodesc);
    2697              :     }
    2698              : 
    2699          356 :     return false;
    2700              : }
    2701              : 
    2702              : 
    2703              : static void
    2704           28 : free_plperl_function(plperl_proc_desc *prodesc)
    2705              : {
    2706              :     Assert(prodesc->fn_refcount == 0);
    2707              :     /* Release CODE reference, if we have one, from the appropriate interp */
    2708           28 :     if (prodesc->reference)
    2709              :     {
    2710           28 :         plperl_interp_desc *oldinterp = plperl_active_interp;
    2711              : 
    2712           28 :         activate_interpreter(prodesc->interp);
    2713           28 :         SvREFCNT_dec_current(prodesc->reference);
    2714           28 :         activate_interpreter(oldinterp);
    2715              :     }
    2716              :     /* Release all PG-owned data for this proc */
    2717           28 :     MemoryContextDelete(prodesc->fn_cxt);
    2718           28 : }
    2719              : 
    2720              : 
    2721              : static plperl_proc_desc *
    2722          426 : compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
    2723              : {
    2724              :     HeapTuple   procTup;
    2725              :     Form_pg_proc procStruct;
    2726              :     plperl_proc_key proc_key;
    2727              :     plperl_proc_ptr *proc_ptr;
    2728          426 :     plperl_proc_desc *volatile prodesc = NULL;
    2729          426 :     volatile MemoryContext proc_cxt = NULL;
    2730          426 :     plperl_interp_desc *oldinterp = plperl_active_interp;
    2731              :     ErrorContextCallback plperl_error_context;
    2732              : 
    2733              :     /* We'll need the pg_proc tuple in any case... */
    2734          426 :     procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid));
    2735          426 :     if (!HeapTupleIsValid(procTup))
    2736            0 :         elog(ERROR, "cache lookup failed for function %u", fn_oid);
    2737          426 :     procStruct = (Form_pg_proc) GETSTRUCT(procTup);
    2738              : 
    2739              :     /*
    2740              :      * Try to find function in plperl_proc_hash.  The reason for this
    2741              :      * overcomplicated-seeming lookup procedure is that we don't know whether
    2742              :      * it's plperl or plperlu, and don't want to spend a lookup in pg_language
    2743              :      * to find out.
    2744              :      */
    2745          426 :     proc_key.proc_id = fn_oid;
    2746          426 :     proc_key.is_trigger = is_trigger;
    2747          426 :     proc_key.user_id = GetUserId();
    2748          426 :     proc_ptr = hash_search(plperl_proc_hash, &proc_key,
    2749              :                            HASH_FIND, NULL);
    2750          426 :     if (validate_plperl_function(proc_ptr, procTup))
    2751              :     {
    2752              :         /* Found valid plperl entry */
    2753          223 :         ReleaseSysCache(procTup);
    2754          223 :         return proc_ptr->proc_ptr;
    2755              :     }
    2756              : 
    2757              :     /* If not found or obsolete, maybe it's plperlu */
    2758          203 :     proc_key.user_id = InvalidOid;
    2759          203 :     proc_ptr = hash_search(plperl_proc_hash, &proc_key,
    2760              :                            HASH_FIND, NULL);
    2761          203 :     if (validate_plperl_function(proc_ptr, procTup))
    2762              :     {
    2763              :         /* Found valid plperlu entry */
    2764           50 :         ReleaseSysCache(procTup);
    2765           50 :         return proc_ptr->proc_ptr;
    2766              :     }
    2767              : 
    2768              :     /************************************************************
    2769              :      * If we haven't found it in the hashtable, we analyze
    2770              :      * the function's arguments and return type and store
    2771              :      * the in-/out-functions in the prodesc block,
    2772              :      * then we load the procedure into the Perl interpreter,
    2773              :      * and last we create a new hashtable entry for it.
    2774              :      ************************************************************/
    2775              : 
    2776              :     /* Set a callback for reporting compilation errors */
    2777          153 :     plperl_error_context.callback = plperl_compile_callback;
    2778          153 :     plperl_error_context.previous = error_context_stack;
    2779          153 :     plperl_error_context.arg = NameStr(procStruct->proname);
    2780          153 :     error_context_stack = &plperl_error_context;
    2781              : 
    2782          153 :     PG_TRY();
    2783              :     {
    2784              :         HeapTuple   langTup;
    2785              :         HeapTuple   typeTup;
    2786              :         Form_pg_language langStruct;
    2787              :         Form_pg_type typeStruct;
    2788              :         Datum       protrftypes_datum;
    2789              :         Datum       prosrcdatum;
    2790              :         bool        isnull;
    2791              :         char       *proc_source;
    2792              :         MemoryContext oldcontext;
    2793              : 
    2794              :         /************************************************************
    2795              :          * Allocate a context that will hold all PG data for the procedure.
    2796              :          ************************************************************/
    2797          153 :         proc_cxt = AllocSetContextCreate(TopMemoryContext,
    2798              :                                          "PL/Perl function",
    2799              :                                          ALLOCSET_SMALL_SIZES);
    2800              : 
    2801              :         /************************************************************
    2802              :          * Allocate and fill a new procedure description block.
    2803              :          * struct prodesc and subsidiary data must all live in proc_cxt.
    2804              :          ************************************************************/
    2805          153 :         oldcontext = MemoryContextSwitchTo(proc_cxt);
    2806          153 :         prodesc = palloc0_object(plperl_proc_desc);
    2807          153 :         prodesc->proname = pstrdup(NameStr(procStruct->proname));
    2808          153 :         MemoryContextSetIdentifier(proc_cxt, prodesc->proname);
    2809          153 :         prodesc->fn_cxt = proc_cxt;
    2810          153 :         prodesc->fn_refcount = 0;
    2811          153 :         prodesc->fn_xmin = HeapTupleHeaderGetRawXmin(procTup->t_data);
    2812          153 :         prodesc->fn_tid = procTup->t_self;
    2813          153 :         prodesc->nargs = procStruct->pronargs;
    2814          153 :         prodesc->arg_out_func = (FmgrInfo *) palloc0(prodesc->nargs * sizeof(FmgrInfo));
    2815          153 :         prodesc->arg_is_rowtype = (bool *) palloc0(prodesc->nargs * sizeof(bool));
    2816          153 :         prodesc->arg_arraytype = (Oid *) palloc0(prodesc->nargs * sizeof(Oid));
    2817          153 :         MemoryContextSwitchTo(oldcontext);
    2818              : 
    2819              :         /* Remember if function is STABLE/IMMUTABLE */
    2820          153 :         prodesc->fn_readonly =
    2821          153 :             (procStruct->provolatile != PROVOLATILE_VOLATILE);
    2822              : 
    2823              :         /* Fetch protrftypes */
    2824          153 :         protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
    2825              :                                             Anum_pg_proc_protrftypes, &isnull);
    2826          153 :         MemoryContextSwitchTo(proc_cxt);
    2827          153 :         prodesc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
    2828          153 :         MemoryContextSwitchTo(oldcontext);
    2829              : 
    2830              :         /************************************************************
    2831              :          * Lookup the pg_language tuple by Oid
    2832              :          ************************************************************/
    2833          153 :         langTup = SearchSysCache1(LANGOID,
    2834              :                                   ObjectIdGetDatum(procStruct->prolang));
    2835          153 :         if (!HeapTupleIsValid(langTup))
    2836            0 :             elog(ERROR, "cache lookup failed for language %u",
    2837              :                  procStruct->prolang);
    2838          153 :         langStruct = (Form_pg_language) GETSTRUCT(langTup);
    2839          153 :         prodesc->lang_oid = langStruct->oid;
    2840          153 :         prodesc->lanpltrusted = langStruct->lanpltrusted;
    2841          153 :         ReleaseSysCache(langTup);
    2842              : 
    2843              :         /************************************************************
    2844              :          * Get the required information for input conversion of the
    2845              :          * return value.
    2846              :          ************************************************************/
    2847          153 :         if (!is_trigger && !is_event_trigger)
    2848              :         {
    2849          144 :             Oid         rettype = procStruct->prorettype;
    2850              : 
    2851          144 :             typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rettype));
    2852          144 :             if (!HeapTupleIsValid(typeTup))
    2853            0 :                 elog(ERROR, "cache lookup failed for type %u", rettype);
    2854          144 :             typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
    2855              : 
    2856              :             /* Disallow pseudotype result, except VOID or RECORD */
    2857          144 :             if (typeStruct->typtype == TYPTYPE_PSEUDO)
    2858              :             {
    2859           30 :                 if (rettype == VOIDOID ||
    2860              :                     rettype == RECORDOID)
    2861              :                      /* okay */ ;
    2862            1 :                 else if (rettype == TRIGGEROID ||
    2863              :                          rettype == EVENT_TRIGGEROID)
    2864            1 :                     ereport(ERROR,
    2865              :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2866              :                              errmsg("trigger functions can only be called "
    2867              :                                     "as triggers")));
    2868              :                 else
    2869            0 :                     ereport(ERROR,
    2870              :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2871              :                              errmsg("PL/Perl functions cannot return type %s",
    2872              :                                     format_type_be(rettype))));
    2873              :             }
    2874              : 
    2875          143 :             prodesc->result_oid = rettype;
    2876          143 :             prodesc->fn_retisset = procStruct->proretset;
    2877          143 :             prodesc->fn_retistuple = type_is_rowtype(rettype);
    2878          143 :             prodesc->fn_retisarray = IsTrueArrayType(typeStruct);
    2879              : 
    2880          143 :             fmgr_info_cxt(typeStruct->typinput,
    2881          143 :                           &(prodesc->result_in_func),
    2882              :                           proc_cxt);
    2883          143 :             prodesc->result_typioparam = getTypeIOParam(typeTup);
    2884              : 
    2885          143 :             ReleaseSysCache(typeTup);
    2886              :         }
    2887              : 
    2888              :         /************************************************************
    2889              :          * Get the required information for output conversion
    2890              :          * of all procedure arguments
    2891              :          ************************************************************/
    2892          152 :         if (!is_trigger && !is_event_trigger)
    2893              :         {
    2894              :             int         i;
    2895              : 
    2896          208 :             for (i = 0; i < prodesc->nargs; i++)
    2897              :             {
    2898           65 :                 Oid         argtype = procStruct->proargtypes.values[i];
    2899              : 
    2900           65 :                 typeTup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(argtype));
    2901           65 :                 if (!HeapTupleIsValid(typeTup))
    2902            0 :                     elog(ERROR, "cache lookup failed for type %u", argtype);
    2903           65 :                 typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
    2904              : 
    2905              :                 /* Disallow pseudotype argument, except RECORD */
    2906           65 :                 if (typeStruct->typtype == TYPTYPE_PSEUDO &&
    2907              :                     argtype != RECORDOID)
    2908            0 :                     ereport(ERROR,
    2909              :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2910              :                              errmsg("PL/Perl functions cannot accept type %s",
    2911              :                                     format_type_be(argtype))));
    2912              : 
    2913           65 :                 if (type_is_rowtype(argtype))
    2914            6 :                     prodesc->arg_is_rowtype[i] = true;
    2915              :                 else
    2916              :                 {
    2917           59 :                     prodesc->arg_is_rowtype[i] = false;
    2918           59 :                     fmgr_info_cxt(typeStruct->typoutput,
    2919           59 :                                   &(prodesc->arg_out_func[i]),
    2920              :                                   proc_cxt);
    2921              :                 }
    2922              : 
    2923              :                 /* Identify array-type arguments */
    2924           65 :                 if (IsTrueArrayType(typeStruct))
    2925            7 :                     prodesc->arg_arraytype[i] = argtype;
    2926              :                 else
    2927           58 :                     prodesc->arg_arraytype[i] = InvalidOid;
    2928              : 
    2929           65 :                 ReleaseSysCache(typeTup);
    2930              :             }
    2931              :         }
    2932              : 
    2933              :         /************************************************************
    2934              :          * create the text of the anonymous subroutine.
    2935              :          * we do not use a named subroutine so that we can call directly
    2936              :          * through the reference.
    2937              :          ************************************************************/
    2938          152 :         prosrcdatum = SysCacheGetAttrNotNull(PROCOID, procTup,
    2939              :                                              Anum_pg_proc_prosrc);
    2940          152 :         proc_source = TextDatumGetCString(prosrcdatum);
    2941              : 
    2942              :         /************************************************************
    2943              :          * Create the procedure in the appropriate interpreter
    2944              :          ************************************************************/
    2945              : 
    2946          152 :         select_perl_context(prodesc->lanpltrusted);
    2947              : 
    2948          152 :         prodesc->interp = plperl_active_interp;
    2949              : 
    2950          152 :         plperl_create_sub(prodesc, proc_source, fn_oid);
    2951              : 
    2952          149 :         activate_interpreter(oldinterp);
    2953              : 
    2954          149 :         pfree(proc_source);
    2955              : 
    2956          149 :         if (!prodesc->reference) /* can this happen? */
    2957            0 :             elog(ERROR, "could not create PL/Perl internal procedure");
    2958              : 
    2959              :         /************************************************************
    2960              :          * OK, link the procedure into the correct hashtable entry.
    2961              :          * Note we assume that the hashtable entry either doesn't exist yet,
    2962              :          * or we already cleared its proc_ptr during the validation attempts
    2963              :          * above.  So no need to decrement an old refcount here.
    2964              :          ************************************************************/
    2965          149 :         proc_key.user_id = prodesc->lanpltrusted ? GetUserId() : InvalidOid;
    2966              : 
    2967          149 :         proc_ptr = hash_search(plperl_proc_hash, &proc_key,
    2968              :                                HASH_ENTER, NULL);
    2969              :         /* We assume these two steps can't throw an error: */
    2970          149 :         proc_ptr->proc_ptr = prodesc;
    2971          149 :         increment_prodesc_refcount(prodesc);
    2972              :     }
    2973            4 :     PG_CATCH();
    2974              :     {
    2975              :         /*
    2976              :          * If we got as far as creating a reference, we should be able to use
    2977              :          * free_plperl_function() to clean up.  If not, then at most we have
    2978              :          * some PG memory resources in proc_cxt, which we can just delete.
    2979              :          */
    2980            4 :         if (prodesc && prodesc->reference)
    2981            0 :             free_plperl_function(prodesc);
    2982            4 :         else if (proc_cxt)
    2983            4 :             MemoryContextDelete(proc_cxt);
    2984              : 
    2985              :         /* Be sure to restore the previous interpreter, too, for luck */
    2986            4 :         activate_interpreter(oldinterp);
    2987              : 
    2988            4 :         PG_RE_THROW();
    2989              :     }
    2990          149 :     PG_END_TRY();
    2991              : 
    2992              :     /* restore previous error callback */
    2993          149 :     error_context_stack = plperl_error_context.previous;
    2994              : 
    2995          149 :     ReleaseSysCache(procTup);
    2996              : 
    2997          149 :     return prodesc;
    2998              : }
    2999              : 
    3000              : /* Build a hash from a given composite/row datum */
    3001              : static SV  *
    3002           57 : plperl_hash_from_datum(Datum attr)
    3003              : {
    3004              :     HeapTupleHeader td;
    3005              :     Oid         tupType;
    3006              :     int32       tupTypmod;
    3007              :     TupleDesc   tupdesc;
    3008              :     HeapTupleData tmptup;
    3009              :     SV         *sv;
    3010              : 
    3011           57 :     td = DatumGetHeapTupleHeader(attr);
    3012              : 
    3013              :     /* Extract rowtype info and find a tupdesc */
    3014           57 :     tupType = HeapTupleHeaderGetTypeId(td);
    3015           57 :     tupTypmod = HeapTupleHeaderGetTypMod(td);
    3016           57 :     tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
    3017              : 
    3018              :     /* Build a temporary HeapTuple control structure */
    3019           57 :     tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
    3020           57 :     tmptup.t_data = td;
    3021              : 
    3022           57 :     sv = plperl_hash_from_tuple(&tmptup, tupdesc, true);
    3023           57 :     ReleaseTupleDesc(tupdesc);
    3024              : 
    3025           57 :     return sv;
    3026              : }
    3027              : 
    3028              : /* Build a hash from all attributes of a given tuple. */
    3029              : static SV  *
    3030          192 : plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated)
    3031              : {
    3032          192 :     dTHX;
    3033              :     HV         *hv;
    3034              :     int         i;
    3035              : 
    3036              :     /* since this function recurses, it could be driven to stack overflow */
    3037          192 :     check_stack_depth();
    3038              : 
    3039          192 :     hv = newHV();
    3040          192 :     hv_ksplit(hv, tupdesc->natts);   /* pre-grow the hash */
    3041              : 
    3042          476 :     for (i = 0; i < tupdesc->natts; i++)
    3043              :     {
    3044              :         Datum       attr;
    3045              :         bool        isnull,
    3046              :                     typisvarlena;
    3047              :         char       *attname;
    3048              :         Oid         typoutput;
    3049          284 :         Form_pg_attribute att = TupleDescAttr(tupdesc, i);
    3050              : 
    3051          284 :         if (att->attisdropped)
    3052           19 :             continue;
    3053              : 
    3054          284 :         if (att->attgenerated)
    3055              :         {
    3056              :             /* don't include unless requested */
    3057           18 :             if (!include_generated)
    3058            6 :                 continue;
    3059              :             /* never include virtual columns */
    3060           12 :             if (att->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
    3061            6 :                 continue;
    3062              :         }
    3063              : 
    3064          272 :         attname = NameStr(att->attname);
    3065          272 :         attr = heap_getattr(tuple, i + 1, tupdesc, &isnull);
    3066              : 
    3067          272 :         if (isnull)
    3068              :         {
    3069              :             /*
    3070              :              * Store (attname => undef) and move on.  Note we can't use
    3071              :              * &PL_sv_undef here; see "AVs, HVs and undefined values" in
    3072              :              * perlguts for an explanation.
    3073              :              */
    3074            7 :             hv_store_string(hv, attname, newSV(0));
    3075            7 :             continue;
    3076              :         }
    3077              : 
    3078          265 :         if (type_is_rowtype(att->atttypid))
    3079              :         {
    3080           42 :             SV         *sv = plperl_hash_from_datum(attr);
    3081              : 
    3082           42 :             hv_store_string(hv, attname, sv);
    3083              :         }
    3084              :         else
    3085              :         {
    3086              :             SV         *sv;
    3087              :             Oid         funcid;
    3088              : 
    3089          223 :             if (OidIsValid(get_base_element_type(att->atttypid)))
    3090            4 :                 sv = plperl_ref_from_pg_array(attr, att->atttypid);
    3091          219 :             else if ((funcid = get_transform_fromsql(att->atttypid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
    3092            7 :                 sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, attr));
    3093              :             else
    3094              :             {
    3095              :                 char       *outputstr;
    3096              : 
    3097              :                 /* XXX should have a way to cache these lookups */
    3098          212 :                 getTypeOutputInfo(att->atttypid, &typoutput, &typisvarlena);
    3099              : 
    3100          212 :                 outputstr = OidOutputFunctionCall(typoutput, attr);
    3101          212 :                 sv = cstr2sv(outputstr);
    3102          212 :                 pfree(outputstr);
    3103              :             }
    3104              : 
    3105          223 :             hv_store_string(hv, attname, sv);
    3106              :         }
    3107              :     }
    3108          192 :     return newRV_noinc((SV *) hv);
    3109              : }
    3110              : 
    3111              : 
    3112              : static void
    3113          326 : check_spi_usage_allowed(void)
    3114              : {
    3115              :     /* see comment in plperl_fini() */
    3116          326 :     if (plperl_ending)
    3117              :     {
    3118              :         /* simple croak as we don't want to involve PostgreSQL code */
    3119            0 :         croak("SPI functions can not be used in END blocks");
    3120              :     }
    3121              : 
    3122              :     /*
    3123              :      * Disallow SPI usage if we're not executing a fully-compiled plperl
    3124              :      * function.  It might seem impossible to get here in that case, but there
    3125              :      * are cases where Perl will try to execute code during compilation.  If
    3126              :      * we proceed we are likely to crash trying to dereference the prodesc
    3127              :      * pointer.  Working around that might be possible, but it seems unwise
    3128              :      * because it'd allow code execution to happen while validating a
    3129              :      * function, which is undesirable.
    3130              :      */
    3131          326 :     if (current_call_data == NULL || current_call_data->prodesc == NULL)
    3132              :     {
    3133              :         /* simple croak as we don't want to involve PostgreSQL code */
    3134            0 :         croak("SPI functions can not be used during function compilation");
    3135              :     }
    3136          326 : }
    3137              : 
    3138              : 
    3139              : HV *
    3140           57 : plperl_spi_exec(char *query, int limit)
    3141              : {
    3142              :     HV         *ret_hv;
    3143              : 
    3144              :     /*
    3145              :      * Execute the query inside a sub-transaction, so we can cope with errors
    3146              :      * sanely
    3147              :      */
    3148           57 :     MemoryContext oldcontext = CurrentMemoryContext;
    3149           57 :     ResourceOwner oldowner = CurrentResourceOwner;
    3150              : 
    3151           57 :     check_spi_usage_allowed();
    3152              : 
    3153           57 :     BeginInternalSubTransaction(NULL);
    3154              :     /* Want to run inside function's memory context */
    3155           57 :     MemoryContextSwitchTo(oldcontext);
    3156              : 
    3157           57 :     PG_TRY();
    3158              :     {
    3159              :         int         spi_rv;
    3160              : 
    3161           57 :         pg_verifymbstr(query, strlen(query), false);
    3162              : 
    3163           57 :         spi_rv = SPI_execute(query, current_call_data->prodesc->fn_readonly,
    3164              :                              limit);
    3165           51 :         ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
    3166              :                                                  spi_rv);
    3167              : 
    3168              :         /* Commit the inner transaction, return to outer xact context */
    3169           51 :         ReleaseCurrentSubTransaction();
    3170           51 :         MemoryContextSwitchTo(oldcontext);
    3171           51 :         CurrentResourceOwner = oldowner;
    3172              :     }
    3173            6 :     PG_CATCH();
    3174              :     {
    3175              :         ErrorData  *edata;
    3176              : 
    3177              :         /* Save error info */
    3178            6 :         MemoryContextSwitchTo(oldcontext);
    3179            6 :         edata = CopyErrorData();
    3180            6 :         FlushErrorState();
    3181              : 
    3182              :         /* Abort the inner transaction */
    3183            6 :         RollbackAndReleaseCurrentSubTransaction();
    3184            6 :         MemoryContextSwitchTo(oldcontext);
    3185            6 :         CurrentResourceOwner = oldowner;
    3186              : 
    3187              :         /* Punt the error to Perl */
    3188            6 :         croak_cstr(edata->message);
    3189              : 
    3190              :         /* Can't get here, but keep compiler quiet */
    3191            0 :         return NULL;
    3192              :     }
    3193           51 :     PG_END_TRY();
    3194              : 
    3195           51 :     return ret_hv;
    3196              : }
    3197              : 
    3198              : 
    3199              : static HV  *
    3200           57 : plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed,
    3201              :                                 int status)
    3202              : {
    3203           57 :     dTHX;
    3204              :     HV         *result;
    3205              : 
    3206           57 :     check_spi_usage_allowed();
    3207              : 
    3208           57 :     result = newHV();
    3209              : 
    3210           57 :     hv_store_string(result, "status",
    3211              :                     cstr2sv(SPI_result_code_string(status)));
    3212           57 :     hv_store_string(result, "processed",
    3213              :                     (processed > (uint64) UV_MAX) ?
    3214              :                     newSVnv((NV) processed) :
    3215              :                     newSVuv((UV) processed));
    3216              : 
    3217           57 :     if (status > 0 && tuptable)
    3218              :     {
    3219              :         AV         *rows;
    3220              :         SV         *row;
    3221              :         uint64      i;
    3222              : 
    3223              :         /* Prevent overflow in call to av_extend() */
    3224           11 :         if (processed > (uint64) AV_SIZE_MAX)
    3225            0 :             ereport(ERROR,
    3226              :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    3227              :                      errmsg("query result has too many rows to fit in a Perl array")));
    3228              : 
    3229           11 :         rows = newAV();
    3230           11 :         av_extend(rows, processed);
    3231           83 :         for (i = 0; i < processed; i++)
    3232              :         {
    3233           72 :             row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc, true);
    3234           72 :             av_push(rows, row);
    3235              :         }
    3236           11 :         hv_store_string(result, "rows",
    3237              :                         newRV_noinc((SV *) rows));
    3238              :     }
    3239              : 
    3240           57 :     SPI_freetuptable(tuptable);
    3241              : 
    3242           57 :     return result;
    3243              : }
    3244              : 
    3245              : 
    3246              : /*
    3247              :  * plperl_return_next catches any error and converts it to a Perl error.
    3248              :  * We assume (perhaps without adequate justification) that we need not abort
    3249              :  * the current transaction if the Perl code traps the error.
    3250              :  */
    3251              : void
    3252           87 : plperl_return_next(SV *sv)
    3253              : {
    3254           87 :     MemoryContext oldcontext = CurrentMemoryContext;
    3255              : 
    3256           87 :     check_spi_usage_allowed();
    3257              : 
    3258           87 :     PG_TRY();
    3259              :     {
    3260           87 :         plperl_return_next_internal(sv);
    3261              :     }
    3262            0 :     PG_CATCH();
    3263              :     {
    3264              :         ErrorData  *edata;
    3265              : 
    3266              :         /* Must reset elog.c's state */
    3267            0 :         MemoryContextSwitchTo(oldcontext);
    3268            0 :         edata = CopyErrorData();
    3269            0 :         FlushErrorState();
    3270              : 
    3271              :         /* Punt the error to Perl */
    3272            0 :         croak_cstr(edata->message);
    3273              :     }
    3274           87 :     PG_END_TRY();
    3275           87 : }
    3276              : 
    3277              : /*
    3278              :  * plperl_return_next_internal reports any errors in Postgres fashion
    3279              :  * (via ereport).
    3280              :  */
    3281              : static void
    3282          141 : plperl_return_next_internal(SV *sv)
    3283              : {
    3284              :     plperl_proc_desc *prodesc;
    3285              :     FunctionCallInfo fcinfo;
    3286              :     ReturnSetInfo *rsi;
    3287              :     MemoryContext old_cxt;
    3288              : 
    3289          141 :     if (!sv)
    3290            0 :         return;
    3291              : 
    3292          141 :     prodesc = current_call_data->prodesc;
    3293          141 :     fcinfo = current_call_data->fcinfo;
    3294          141 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
    3295              : 
    3296          141 :     if (!prodesc->fn_retisset)
    3297            0 :         ereport(ERROR,
    3298              :                 (errcode(ERRCODE_SYNTAX_ERROR),
    3299              :                  errmsg("cannot use return_next in a non-SETOF function")));
    3300              : 
    3301          141 :     if (!current_call_data->ret_tdesc)
    3302              :     {
    3303              :         TupleDesc   tupdesc;
    3304              : 
    3305              :         Assert(!current_call_data->tuple_store);
    3306              : 
    3307              :         /*
    3308              :          * This is the first call to return_next in the current PL/Perl
    3309              :          * function call, so identify the output tuple type and create a
    3310              :          * tuplestore to hold the result rows.
    3311              :          */
    3312           34 :         if (prodesc->fn_retistuple)
    3313              :         {
    3314              :             TypeFuncClass funcclass;
    3315              :             Oid         typid;
    3316              : 
    3317           17 :             funcclass = get_call_result_type(fcinfo, &typid, &tupdesc);
    3318           17 :             if (funcclass != TYPEFUNC_COMPOSITE &&
    3319              :                 funcclass != TYPEFUNC_COMPOSITE_DOMAIN)
    3320            2 :                 ereport(ERROR,
    3321              :                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    3322              :                          errmsg("function returning record called in context "
    3323              :                                 "that cannot accept type record")));
    3324              :             /* if domain-over-composite, remember the domain's type OID */
    3325           15 :             if (funcclass == TYPEFUNC_COMPOSITE_DOMAIN)
    3326            2 :                 current_call_data->cdomain_oid = typid;
    3327              :         }
    3328              :         else
    3329              :         {
    3330           17 :             tupdesc = rsi->expectedDesc;
    3331              :             /* Protect assumption below that we return exactly one column */
    3332           17 :             if (tupdesc == NULL || tupdesc->natts != 1)
    3333            0 :                 elog(ERROR, "expected single-column result descriptor for non-composite SETOF result");
    3334              :         }
    3335              : 
    3336              :         /*
    3337              :          * Make sure the tuple_store and ret_tdesc are sufficiently
    3338              :          * long-lived.
    3339              :          */
    3340           32 :         old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
    3341              : 
    3342           32 :         current_call_data->ret_tdesc = CreateTupleDescCopy(tupdesc);
    3343           64 :         current_call_data->tuple_store =
    3344           32 :             tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
    3345              :                                   false, work_mem);
    3346              : 
    3347           32 :         MemoryContextSwitchTo(old_cxt);
    3348              :     }
    3349              : 
    3350              :     /*
    3351              :      * Producing the tuple we want to return requires making plenty of
    3352              :      * palloc() allocations that are not cleaned up. Since this function can
    3353              :      * be called many times before the current memory context is reset, we
    3354              :      * need to do those allocations in a temporary context.
    3355              :      */
    3356          139 :     if (!current_call_data->tmp_cxt)
    3357              :     {
    3358           32 :         current_call_data->tmp_cxt =
    3359           32 :             AllocSetContextCreate(CurrentMemoryContext,
    3360              :                                   "PL/Perl return_next temporary cxt",
    3361              :                                   ALLOCSET_DEFAULT_SIZES);
    3362              :     }
    3363              : 
    3364          139 :     old_cxt = MemoryContextSwitchTo(current_call_data->tmp_cxt);
    3365              : 
    3366          139 :     if (prodesc->fn_retistuple)
    3367              :     {
    3368              :         HeapTuple   tuple;
    3369              : 
    3370           43 :         if (!(SvOK(sv) && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV))
    3371            4 :             ereport(ERROR,
    3372              :                     (errcode(ERRCODE_DATATYPE_MISMATCH),
    3373              :                      errmsg("SETOF-composite-returning PL/Perl function "
    3374              :                             "must call return_next with reference to hash")));
    3375              : 
    3376           39 :         tuple = plperl_build_tuple_result((HV *) SvRV(sv),
    3377           39 :                                           current_call_data->ret_tdesc);
    3378              : 
    3379           38 :         if (OidIsValid(current_call_data->cdomain_oid))
    3380            4 :             domain_check(HeapTupleGetDatum(tuple), false,
    3381            4 :                          current_call_data->cdomain_oid,
    3382            4 :                          &current_call_data->cdomain_info,
    3383            4 :                          rsi->econtext->ecxt_per_query_memory);
    3384              : 
    3385           37 :         tuplestore_puttuple(current_call_data->tuple_store, tuple);
    3386              :     }
    3387           96 :     else if (prodesc->result_oid)
    3388              :     {
    3389              :         Datum       ret[1];
    3390              :         bool        isNull[1];
    3391              : 
    3392           96 :         ret[0] = plperl_sv_to_datum(sv,
    3393              :                                     prodesc->result_oid,
    3394              :                                     -1,
    3395              :                                     fcinfo,
    3396              :                                     &prodesc->result_in_func,
    3397              :                                     prodesc->result_typioparam,
    3398              :                                     &isNull[0]);
    3399              : 
    3400           96 :         tuplestore_putvalues(current_call_data->tuple_store,
    3401           96 :                              current_call_data->ret_tdesc,
    3402              :                              ret, isNull);
    3403              :     }
    3404              : 
    3405          133 :     MemoryContextSwitchTo(old_cxt);
    3406          133 :     MemoryContextReset(current_call_data->tmp_cxt);
    3407              : }
    3408              : 
    3409              : 
    3410              : SV *
    3411            9 : plperl_spi_query(char *query)
    3412              : {
    3413              :     SV         *cursor;
    3414              : 
    3415              :     /*
    3416              :      * Execute the query inside a sub-transaction, so we can cope with errors
    3417              :      * sanely
    3418              :      */
    3419            9 :     MemoryContext oldcontext = CurrentMemoryContext;
    3420            9 :     ResourceOwner oldowner = CurrentResourceOwner;
    3421              : 
    3422            9 :     check_spi_usage_allowed();
    3423              : 
    3424            9 :     BeginInternalSubTransaction(NULL);
    3425              :     /* Want to run inside function's memory context */
    3426            9 :     MemoryContextSwitchTo(oldcontext);
    3427              : 
    3428            9 :     PG_TRY();
    3429              :     {
    3430              :         SPIPlanPtr  plan;
    3431              :         Portal      portal;
    3432              : 
    3433              :         /* Make sure the query is validly encoded */
    3434            9 :         pg_verifymbstr(query, strlen(query), false);
    3435              : 
    3436              :         /* Create a cursor for the query */
    3437            9 :         plan = SPI_prepare(query, 0, NULL);
    3438            9 :         if (plan == NULL)
    3439            0 :             elog(ERROR, "SPI_prepare() failed:%s",
    3440              :                  SPI_result_code_string(SPI_result));
    3441              : 
    3442            9 :         portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
    3443            9 :         SPI_freeplan(plan);
    3444            9 :         if (portal == NULL)
    3445            0 :             elog(ERROR, "SPI_cursor_open() failed:%s",
    3446              :                  SPI_result_code_string(SPI_result));
    3447            9 :         cursor = cstr2sv(portal->name);
    3448              : 
    3449            9 :         PinPortal(portal);
    3450              : 
    3451              :         /* Commit the inner transaction, return to outer xact context */
    3452            9 :         ReleaseCurrentSubTransaction();
    3453            9 :         MemoryContextSwitchTo(oldcontext);
    3454            9 :         CurrentResourceOwner = oldowner;
    3455              :     }
    3456            0 :     PG_CATCH();
    3457              :     {
    3458              :         ErrorData  *edata;
    3459              : 
    3460              :         /* Save error info */
    3461            0 :         MemoryContextSwitchTo(oldcontext);
    3462            0 :         edata = CopyErrorData();
    3463            0 :         FlushErrorState();
    3464              : 
    3465              :         /* Abort the inner transaction */
    3466            0 :         RollbackAndReleaseCurrentSubTransaction();
    3467            0 :         MemoryContextSwitchTo(oldcontext);
    3468            0 :         CurrentResourceOwner = oldowner;
    3469              : 
    3470              :         /* Punt the error to Perl */
    3471            0 :         croak_cstr(edata->message);
    3472              : 
    3473              :         /* Can't get here, but keep compiler quiet */
    3474            0 :         return NULL;
    3475              :     }
    3476            9 :     PG_END_TRY();
    3477              : 
    3478            9 :     return cursor;
    3479              : }
    3480              : 
    3481              : 
    3482              : SV *
    3483           36 : plperl_spi_fetchrow(char *cursor)
    3484              : {
    3485              :     SV         *row;
    3486              : 
    3487              :     /*
    3488              :      * Execute the FETCH inside a sub-transaction, so we can cope with errors
    3489              :      * sanely
    3490              :      */
    3491           36 :     MemoryContext oldcontext = CurrentMemoryContext;
    3492           36 :     ResourceOwner oldowner = CurrentResourceOwner;
    3493              : 
    3494           36 :     check_spi_usage_allowed();
    3495              : 
    3496           36 :     BeginInternalSubTransaction(NULL);
    3497              :     /* Want to run inside function's memory context */
    3498           36 :     MemoryContextSwitchTo(oldcontext);
    3499              : 
    3500           36 :     PG_TRY();
    3501              :     {
    3502           36 :         dTHX;
    3503           36 :         Portal      p = SPI_cursor_find(cursor);
    3504              : 
    3505           36 :         if (!p)
    3506              :         {
    3507            0 :             row = &PL_sv_undef;
    3508              :         }
    3509              :         else
    3510              :         {
    3511           36 :             SPI_cursor_fetch(p, true, 1);
    3512           36 :             if (SPI_processed == 0)
    3513              :             {
    3514            9 :                 UnpinPortal(p);
    3515            9 :                 SPI_cursor_close(p);
    3516            9 :                 row = &PL_sv_undef;
    3517              :             }
    3518              :             else
    3519              :             {
    3520           27 :                 row = plperl_hash_from_tuple(SPI_tuptable->vals[0],
    3521           27 :                                              SPI_tuptable->tupdesc,
    3522              :                                              true);
    3523              :             }
    3524           36 :             SPI_freetuptable(SPI_tuptable);
    3525              :         }
    3526              : 
    3527              :         /* Commit the inner transaction, return to outer xact context */
    3528           36 :         ReleaseCurrentSubTransaction();
    3529           36 :         MemoryContextSwitchTo(oldcontext);
    3530           36 :         CurrentResourceOwner = oldowner;
    3531              :     }
    3532            0 :     PG_CATCH();
    3533              :     {
    3534              :         ErrorData  *edata;
    3535              : 
    3536              :         /* Save error info */
    3537            0 :         MemoryContextSwitchTo(oldcontext);
    3538            0 :         edata = CopyErrorData();
    3539            0 :         FlushErrorState();
    3540              : 
    3541              :         /* Abort the inner transaction */
    3542            0 :         RollbackAndReleaseCurrentSubTransaction();
    3543            0 :         MemoryContextSwitchTo(oldcontext);
    3544            0 :         CurrentResourceOwner = oldowner;
    3545              : 
    3546              :         /* Punt the error to Perl */
    3547            0 :         croak_cstr(edata->message);
    3548              : 
    3549              :         /* Can't get here, but keep compiler quiet */
    3550            0 :         return NULL;
    3551              :     }
    3552           36 :     PG_END_TRY();
    3553              : 
    3554           36 :     return row;
    3555              : }
    3556              : 
    3557              : void
    3558            1 : plperl_spi_cursor_close(char *cursor)
    3559              : {
    3560              :     Portal      p;
    3561              : 
    3562            1 :     check_spi_usage_allowed();
    3563              : 
    3564            1 :     p = SPI_cursor_find(cursor);
    3565              : 
    3566            1 :     if (p)
    3567              :     {
    3568            1 :         UnpinPortal(p);
    3569            1 :         SPI_cursor_close(p);
    3570              :     }
    3571            1 : }
    3572              : 
    3573              : SV *
    3574            8 : plperl_spi_prepare(char *query, int argc, SV **argv)
    3575              : {
    3576            8 :     volatile SPIPlanPtr plan = NULL;
    3577            8 :     volatile MemoryContext plan_cxt = NULL;
    3578            8 :     plperl_query_desc *volatile qdesc = NULL;
    3579            8 :     plperl_query_entry *volatile hash_entry = NULL;
    3580            8 :     MemoryContext oldcontext = CurrentMemoryContext;
    3581            8 :     ResourceOwner oldowner = CurrentResourceOwner;
    3582              :     MemoryContext work_cxt;
    3583              :     bool        found;
    3584              :     int         i;
    3585              : 
    3586            8 :     check_spi_usage_allowed();
    3587              : 
    3588            8 :     BeginInternalSubTransaction(NULL);
    3589            8 :     MemoryContextSwitchTo(oldcontext);
    3590              : 
    3591            8 :     PG_TRY();
    3592              :     {
    3593            8 :         CHECK_FOR_INTERRUPTS();
    3594              : 
    3595              :         /************************************************************
    3596              :          * Allocate the new querydesc structure
    3597              :          *
    3598              :          * The qdesc struct, as well as all its subsidiary data, lives in its
    3599              :          * plan_cxt.  But note that the SPIPlan does not.
    3600              :          ************************************************************/
    3601            8 :         plan_cxt = AllocSetContextCreate(TopMemoryContext,
    3602              :                                          "PL/Perl spi_prepare query",
    3603              :                                          ALLOCSET_SMALL_SIZES);
    3604            8 :         MemoryContextSwitchTo(plan_cxt);
    3605            8 :         qdesc = palloc0_object(plperl_query_desc);
    3606            8 :         snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
    3607            8 :         qdesc->plan_cxt = plan_cxt;
    3608            8 :         qdesc->nargs = argc;
    3609            8 :         qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
    3610            8 :         qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
    3611            8 :         qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
    3612            8 :         MemoryContextSwitchTo(oldcontext);
    3613              : 
    3614              :         /************************************************************
    3615              :          * Do the following work in a short-lived context so that we don't
    3616              :          * leak a lot of memory in the PL/Perl function's SPI Proc context.
    3617              :          ************************************************************/
    3618            8 :         work_cxt = AllocSetContextCreate(CurrentMemoryContext,
    3619              :                                          "PL/Perl spi_prepare workspace",
    3620              :                                          ALLOCSET_DEFAULT_SIZES);
    3621            8 :         MemoryContextSwitchTo(work_cxt);
    3622              : 
    3623              :         /************************************************************
    3624              :          * Resolve argument type names and then look them up by oid
    3625              :          * in the system cache, and remember the required information
    3626              :          * for input conversion.
    3627              :          ************************************************************/
    3628           15 :         for (i = 0; i < argc; i++)
    3629              :         {
    3630              :             Oid         typId,
    3631              :                         typInput,
    3632              :                         typIOParam;
    3633              :             int32       typmod;
    3634              :             char       *typstr;
    3635              : 
    3636            8 :             typstr = sv2cstr(argv[i]);
    3637            8 :             (void) parseTypeString(typstr, &typId, &typmod, NULL);
    3638            7 :             pfree(typstr);
    3639              : 
    3640            7 :             getTypeInputInfo(typId, &typInput, &typIOParam);
    3641              : 
    3642            7 :             qdesc->argtypes[i] = typId;
    3643            7 :             fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
    3644            7 :             qdesc->argtypioparams[i] = typIOParam;
    3645              :         }
    3646              : 
    3647              :         /* Make sure the query is validly encoded */
    3648            7 :         pg_verifymbstr(query, strlen(query), false);
    3649              : 
    3650              :         /************************************************************
    3651              :          * Prepare the plan and check for errors
    3652              :          ************************************************************/
    3653            7 :         plan = SPI_prepare(query, argc, qdesc->argtypes);
    3654              : 
    3655            7 :         if (plan == NULL)
    3656            0 :             elog(ERROR, "SPI_prepare() failed:%s",
    3657              :                  SPI_result_code_string(SPI_result));
    3658              : 
    3659              :         /************************************************************
    3660              :          * Save the plan into permanent memory (right now it's in the
    3661              :          * SPI procCxt, which will go away at function end).
    3662              :          ************************************************************/
    3663            7 :         if (SPI_keepplan(plan))
    3664            0 :             elog(ERROR, "SPI_keepplan() failed");
    3665            7 :         qdesc->plan = plan;
    3666              : 
    3667              :         /************************************************************
    3668              :          * Insert a hashtable entry for the plan.
    3669              :          ************************************************************/
    3670           14 :         hash_entry = hash_search(plperl_active_interp->query_hash,
    3671            7 :                                  qdesc->qname,
    3672              :                                  HASH_ENTER, &found);
    3673            7 :         hash_entry->query_data = qdesc;
    3674              : 
    3675              :         /* Get rid of workspace */
    3676            7 :         MemoryContextDelete(work_cxt);
    3677              : 
    3678              :         /* Commit the inner transaction, return to outer xact context */
    3679            7 :         ReleaseCurrentSubTransaction();
    3680            7 :         MemoryContextSwitchTo(oldcontext);
    3681            7 :         CurrentResourceOwner = oldowner;
    3682              :     }
    3683            1 :     PG_CATCH();
    3684              :     {
    3685              :         ErrorData  *edata;
    3686              : 
    3687              :         /* Save error info */
    3688            1 :         MemoryContextSwitchTo(oldcontext);
    3689            1 :         edata = CopyErrorData();
    3690            1 :         FlushErrorState();
    3691              : 
    3692              :         /* Drop anything we managed to allocate */
    3693            1 :         if (hash_entry)
    3694            0 :             hash_search(plperl_active_interp->query_hash,
    3695            0 :                         qdesc->qname,
    3696              :                         HASH_REMOVE, NULL);
    3697            1 :         if (plan_cxt)
    3698            1 :             MemoryContextDelete(plan_cxt);
    3699            1 :         if (plan)
    3700            0 :             SPI_freeplan(plan);
    3701              : 
    3702              :         /* Abort the inner transaction */
    3703            1 :         RollbackAndReleaseCurrentSubTransaction();
    3704            1 :         MemoryContextSwitchTo(oldcontext);
    3705            1 :         CurrentResourceOwner = oldowner;
    3706              : 
    3707              :         /* Punt the error to Perl */
    3708            1 :         croak_cstr(edata->message);
    3709              : 
    3710              :         /* Can't get here, but keep compiler quiet */
    3711            0 :         return NULL;
    3712              :     }
    3713            7 :     PG_END_TRY();
    3714              : 
    3715              :     /************************************************************
    3716              :      * Return the query's hash key to the caller.
    3717              :      ************************************************************/
    3718            7 :     return cstr2sv(qdesc->qname);
    3719              : }
    3720              : 
    3721              : HV *
    3722            6 : plperl_spi_exec_prepared(char *query, HV *attr, int argc, SV **argv)
    3723              : {
    3724              :     HV         *ret_hv;
    3725              :     SV        **sv;
    3726              :     int         i,
    3727              :                 limit,
    3728              :                 spi_rv;
    3729              :     char       *nulls;
    3730              :     Datum      *argvalues;
    3731              :     plperl_query_desc *qdesc;
    3732              :     plperl_query_entry *hash_entry;
    3733              : 
    3734              :     /*
    3735              :      * Execute the query inside a sub-transaction, so we can cope with errors
    3736              :      * sanely
    3737              :      */
    3738            6 :     MemoryContext oldcontext = CurrentMemoryContext;
    3739            6 :     ResourceOwner oldowner = CurrentResourceOwner;
    3740              : 
    3741            6 :     check_spi_usage_allowed();
    3742              : 
    3743            6 :     BeginInternalSubTransaction(NULL);
    3744              :     /* Want to run inside function's memory context */
    3745            6 :     MemoryContextSwitchTo(oldcontext);
    3746              : 
    3747            6 :     PG_TRY();
    3748              :     {
    3749            6 :         dTHX;
    3750              : 
    3751              :         /************************************************************
    3752              :          * Fetch the saved plan descriptor, see if it's o.k.
    3753              :          ************************************************************/
    3754            6 :         hash_entry = hash_search(plperl_active_interp->query_hash, query,
    3755              :                                  HASH_FIND, NULL);
    3756            6 :         if (hash_entry == NULL)
    3757            0 :             elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
    3758              : 
    3759            6 :         qdesc = hash_entry->query_data;
    3760            6 :         if (qdesc == NULL)
    3761            0 :             elog(ERROR, "spi_exec_prepared: plperl query_hash value vanished");
    3762              : 
    3763            6 :         if (qdesc->nargs != argc)
    3764            0 :             elog(ERROR, "spi_exec_prepared: expected %d argument(s), %d passed",
    3765              :                  qdesc->nargs, argc);
    3766              : 
    3767              :         /************************************************************
    3768              :          * Parse eventual attributes
    3769              :          ************************************************************/
    3770            6 :         limit = 0;
    3771            6 :         if (attr != NULL)
    3772              :         {
    3773            2 :             sv = hv_fetch_string(attr, "limit");
    3774            2 :             if (sv && *sv && SvIOK(*sv))
    3775            0 :                 limit = SvIV(*sv);
    3776              :         }
    3777              :         /************************************************************
    3778              :          * Set up arguments
    3779              :          ************************************************************/
    3780            6 :         if (argc > 0)
    3781              :         {
    3782            4 :             nulls = (char *) palloc(argc);
    3783            4 :             argvalues = (Datum *) palloc(argc * sizeof(Datum));
    3784              :         }
    3785              :         else
    3786              :         {
    3787            2 :             nulls = NULL;
    3788            2 :             argvalues = NULL;
    3789              :         }
    3790              : 
    3791           10 :         for (i = 0; i < argc; i++)
    3792              :         {
    3793              :             bool        isnull;
    3794              : 
    3795            8 :             argvalues[i] = plperl_sv_to_datum(argv[i],
    3796            4 :                                               qdesc->argtypes[i],
    3797              :                                               -1,
    3798              :                                               NULL,
    3799            4 :                                               &qdesc->arginfuncs[i],
    3800            4 :                                               qdesc->argtypioparams[i],
    3801              :                                               &isnull);
    3802            4 :             nulls[i] = isnull ? 'n' : ' ';
    3803              :         }
    3804              : 
    3805              :         /************************************************************
    3806              :          * go
    3807              :          ************************************************************/
    3808           12 :         spi_rv = SPI_execute_plan(qdesc->plan, argvalues, nulls,
    3809            6 :                                   current_call_data->prodesc->fn_readonly, limit);
    3810            6 :         ret_hv = plperl_spi_execute_fetch_result(SPI_tuptable, SPI_processed,
    3811              :                                                  spi_rv);
    3812            6 :         if (argc > 0)
    3813              :         {
    3814            4 :             pfree(argvalues);
    3815            4 :             pfree(nulls);
    3816              :         }
    3817              : 
    3818              :         /* Commit the inner transaction, return to outer xact context */
    3819            6 :         ReleaseCurrentSubTransaction();
    3820            6 :         MemoryContextSwitchTo(oldcontext);
    3821            6 :         CurrentResourceOwner = oldowner;
    3822              :     }
    3823            0 :     PG_CATCH();
    3824              :     {
    3825              :         ErrorData  *edata;
    3826              : 
    3827              :         /* Save error info */
    3828            0 :         MemoryContextSwitchTo(oldcontext);
    3829            0 :         edata = CopyErrorData();
    3830            0 :         FlushErrorState();
    3831              : 
    3832              :         /* Abort the inner transaction */
    3833            0 :         RollbackAndReleaseCurrentSubTransaction();
    3834            0 :         MemoryContextSwitchTo(oldcontext);
    3835            0 :         CurrentResourceOwner = oldowner;
    3836              : 
    3837              :         /* Punt the error to Perl */
    3838            0 :         croak_cstr(edata->message);
    3839              : 
    3840              :         /* Can't get here, but keep compiler quiet */
    3841            0 :         return NULL;
    3842              :     }
    3843            6 :     PG_END_TRY();
    3844              : 
    3845            6 :     return ret_hv;
    3846              : }
    3847              : 
    3848              : SV *
    3849            2 : plperl_spi_query_prepared(char *query, int argc, SV **argv)
    3850              : {
    3851              :     int         i;
    3852              :     char       *nulls;
    3853              :     Datum      *argvalues;
    3854              :     plperl_query_desc *qdesc;
    3855              :     plperl_query_entry *hash_entry;
    3856              :     SV         *cursor;
    3857            2 :     Portal      portal = NULL;
    3858              : 
    3859              :     /*
    3860              :      * Execute the query inside a sub-transaction, so we can cope with errors
    3861              :      * sanely
    3862              :      */
    3863            2 :     MemoryContext oldcontext = CurrentMemoryContext;
    3864            2 :     ResourceOwner oldowner = CurrentResourceOwner;
    3865              : 
    3866            2 :     check_spi_usage_allowed();
    3867              : 
    3868            2 :     BeginInternalSubTransaction(NULL);
    3869              :     /* Want to run inside function's memory context */
    3870            2 :     MemoryContextSwitchTo(oldcontext);
    3871              : 
    3872            2 :     PG_TRY();
    3873              :     {
    3874              :         /************************************************************
    3875              :          * Fetch the saved plan descriptor, see if it's o.k.
    3876              :          ************************************************************/
    3877            2 :         hash_entry = hash_search(plperl_active_interp->query_hash, query,
    3878              :                                  HASH_FIND, NULL);
    3879            2 :         if (hash_entry == NULL)
    3880            0 :             elog(ERROR, "spi_query_prepared: Invalid prepared query passed");
    3881              : 
    3882            2 :         qdesc = hash_entry->query_data;
    3883            2 :         if (qdesc == NULL)
    3884            0 :             elog(ERROR, "spi_query_prepared: plperl query_hash value vanished");
    3885              : 
    3886            2 :         if (qdesc->nargs != argc)
    3887            0 :             elog(ERROR, "spi_query_prepared: expected %d argument(s), %d passed",
    3888              :                  qdesc->nargs, argc);
    3889              : 
    3890              :         /************************************************************
    3891              :          * Set up arguments
    3892              :          ************************************************************/
    3893            2 :         if (argc > 0)
    3894              :         {
    3895            2 :             nulls = (char *) palloc(argc);
    3896            2 :             argvalues = (Datum *) palloc(argc * sizeof(Datum));
    3897              :         }
    3898              :         else
    3899              :         {
    3900            0 :             nulls = NULL;
    3901            0 :             argvalues = NULL;
    3902              :         }
    3903              : 
    3904            5 :         for (i = 0; i < argc; i++)
    3905              :         {
    3906              :             bool        isnull;
    3907              : 
    3908            6 :             argvalues[i] = plperl_sv_to_datum(argv[i],
    3909            3 :                                               qdesc->argtypes[i],
    3910              :                                               -1,
    3911              :                                               NULL,
    3912            3 :                                               &qdesc->arginfuncs[i],
    3913            3 :                                               qdesc->argtypioparams[i],
    3914              :                                               &isnull);
    3915            3 :             nulls[i] = isnull ? 'n' : ' ';
    3916              :         }
    3917              : 
    3918              :         /************************************************************
    3919              :          * go
    3920              :          ************************************************************/
    3921            4 :         portal = SPI_cursor_open(NULL, qdesc->plan, argvalues, nulls,
    3922            2 :                                  current_call_data->prodesc->fn_readonly);
    3923            2 :         if (argc > 0)
    3924              :         {
    3925            2 :             pfree(argvalues);
    3926            2 :             pfree(nulls);
    3927              :         }
    3928            2 :         if (portal == NULL)
    3929            0 :             elog(ERROR, "SPI_cursor_open() failed:%s",
    3930              :                  SPI_result_code_string(SPI_result));
    3931              : 
    3932            2 :         cursor = cstr2sv(portal->name);
    3933              : 
    3934            2 :         PinPortal(portal);
    3935              : 
    3936              :         /* Commit the inner transaction, return to outer xact context */
    3937            2 :         ReleaseCurrentSubTransaction();
    3938            2 :         MemoryContextSwitchTo(oldcontext);
    3939            2 :         CurrentResourceOwner = oldowner;
    3940              :     }
    3941            0 :     PG_CATCH();
    3942              :     {
    3943              :         ErrorData  *edata;
    3944              : 
    3945              :         /* Save error info */
    3946            0 :         MemoryContextSwitchTo(oldcontext);
    3947            0 :         edata = CopyErrorData();
    3948            0 :         FlushErrorState();
    3949              : 
    3950              :         /* Abort the inner transaction */
    3951            0 :         RollbackAndReleaseCurrentSubTransaction();
    3952            0 :         MemoryContextSwitchTo(oldcontext);
    3953            0 :         CurrentResourceOwner = oldowner;
    3954              : 
    3955              :         /* Punt the error to Perl */
    3956            0 :         croak_cstr(edata->message);
    3957              : 
    3958              :         /* Can't get here, but keep compiler quiet */
    3959            0 :         return NULL;
    3960              :     }
    3961            2 :     PG_END_TRY();
    3962              : 
    3963            2 :     return cursor;
    3964              : }
    3965              : 
    3966              : void
    3967            5 : plperl_spi_freeplan(char *query)
    3968              : {
    3969              :     SPIPlanPtr  plan;
    3970              :     plperl_query_desc *qdesc;
    3971              :     plperl_query_entry *hash_entry;
    3972              : 
    3973            5 :     check_spi_usage_allowed();
    3974              : 
    3975            5 :     hash_entry = hash_search(plperl_active_interp->query_hash, query,
    3976              :                              HASH_FIND, NULL);
    3977            5 :     if (hash_entry == NULL)
    3978            0 :         elog(ERROR, "spi_freeplan: Invalid prepared query passed");
    3979              : 
    3980            5 :     qdesc = hash_entry->query_data;
    3981            5 :     if (qdesc == NULL)
    3982            0 :         elog(ERROR, "spi_freeplan: plperl query_hash value vanished");
    3983            5 :     plan = qdesc->plan;
    3984              : 
    3985              :     /*
    3986              :      * free all memory before SPI_freeplan, so if it dies, nothing will be
    3987              :      * left over
    3988              :      */
    3989            5 :     hash_search(plperl_active_interp->query_hash, query,
    3990              :                 HASH_REMOVE, NULL);
    3991              : 
    3992            5 :     MemoryContextDelete(qdesc->plan_cxt);
    3993              : 
    3994            5 :     SPI_freeplan(plan);
    3995            5 : }
    3996              : 
    3997              : void
    3998           25 : plperl_spi_commit(void)
    3999              : {
    4000           25 :     MemoryContext oldcontext = CurrentMemoryContext;
    4001              : 
    4002           25 :     check_spi_usage_allowed();
    4003              : 
    4004           25 :     PG_TRY();
    4005              :     {
    4006           25 :         SPI_commit();
    4007              :     }
    4008            5 :     PG_CATCH();
    4009              :     {
    4010              :         ErrorData  *edata;
    4011              : 
    4012              :         /* Save error info */
    4013            5 :         MemoryContextSwitchTo(oldcontext);
    4014            5 :         edata = CopyErrorData();
    4015            5 :         FlushErrorState();
    4016              : 
    4017              :         /* Punt the error to Perl */
    4018            5 :         croak_cstr(edata->message);
    4019              :     }
    4020           20 :     PG_END_TRY();
    4021           20 : }
    4022              : 
    4023              : void
    4024           17 : plperl_spi_rollback(void)
    4025              : {
    4026           17 :     MemoryContext oldcontext = CurrentMemoryContext;
    4027              : 
    4028           17 :     check_spi_usage_allowed();
    4029              : 
    4030           17 :     PG_TRY();
    4031              :     {
    4032           17 :         SPI_rollback();
    4033              :     }
    4034            0 :     PG_CATCH();
    4035              :     {
    4036              :         ErrorData  *edata;
    4037              : 
    4038              :         /* Save error info */
    4039            0 :         MemoryContextSwitchTo(oldcontext);
    4040            0 :         edata = CopyErrorData();
    4041            0 :         FlushErrorState();
    4042              : 
    4043              :         /* Punt the error to Perl */
    4044            0 :         croak_cstr(edata->message);
    4045              :     }
    4046           17 :     PG_END_TRY();
    4047           17 : }
    4048              : 
    4049              : /*
    4050              :  * Implementation of plperl's elog() function
    4051              :  *
    4052              :  * If the error level is less than ERROR, we'll just emit the message and
    4053              :  * return.  When it is ERROR, elog() will longjmp, which we catch and
    4054              :  * turn into a Perl croak().  Note we are assuming that elog() can't have
    4055              :  * any internal failures that are so bad as to require a transaction abort.
    4056              :  *
    4057              :  * The main reason this is out-of-line is to avoid conflicts between XSUB.h
    4058              :  * and the PG_TRY macros.
    4059              :  */
    4060              : void
    4061          186 : plperl_util_elog(int level, SV *msg)
    4062              : {
    4063          186 :     MemoryContext oldcontext = CurrentMemoryContext;
    4064          186 :     char       *volatile cmsg = NULL;
    4065              : 
    4066              :     /*
    4067              :      * We intentionally omit check_spi_usage_allowed() here, as this seems
    4068              :      * safe to allow even in the contexts that that function rejects.
    4069              :      */
    4070              : 
    4071          186 :     PG_TRY();
    4072              :     {
    4073          186 :         cmsg = sv2cstr(msg);
    4074          186 :         elog(level, "%s", cmsg);
    4075          185 :         pfree(cmsg);
    4076              :     }
    4077            1 :     PG_CATCH();
    4078              :     {
    4079              :         ErrorData  *edata;
    4080              : 
    4081              :         /* Must reset elog.c's state */
    4082            1 :         MemoryContextSwitchTo(oldcontext);
    4083            1 :         edata = CopyErrorData();
    4084            1 :         FlushErrorState();
    4085              : 
    4086            1 :         if (cmsg)
    4087            1 :             pfree(cmsg);
    4088              : 
    4089              :         /* Punt the error to Perl */
    4090            1 :         croak_cstr(edata->message);
    4091              :     }
    4092          185 :     PG_END_TRY();
    4093          185 : }
    4094              : 
    4095              : /*
    4096              :  * Store an SV into a hash table under a key that is a string assumed to be
    4097              :  * in the current database's encoding.
    4098              :  */
    4099              : static SV **
    4100          736 : hv_store_string(HV *hv, const char *key, SV *val)
    4101              : {
    4102          736 :     dTHX;
    4103              :     int32       hlen;
    4104              :     char       *hkey;
    4105              :     SV        **ret;
    4106              : 
    4107          736 :     hkey = pg_server_to_any(key, strlen(key), PG_UTF8);
    4108              : 
    4109              :     /*
    4110              :      * hv_store() recognizes a negative klen parameter as meaning a UTF-8
    4111              :      * encoded key.
    4112              :      */
    4113          736 :     hlen = -(int) strlen(hkey);
    4114          736 :     ret = hv_store(hv, hkey, hlen, val, 0);
    4115              : 
    4116          736 :     if (hkey != key)
    4117            0 :         pfree(hkey);
    4118              : 
    4119          736 :     return ret;
    4120              : }
    4121              : 
    4122              : /*
    4123              :  * Fetch an SV from a hash table under a key that is a string assumed to be
    4124              :  * in the current database's encoding.
    4125              :  */
    4126              : static SV **
    4127            9 : hv_fetch_string(HV *hv, const char *key)
    4128              : {
    4129            9 :     dTHX;
    4130              :     int32       hlen;
    4131              :     char       *hkey;
    4132              :     SV        **ret;
    4133              : 
    4134            9 :     hkey = pg_server_to_any(key, strlen(key), PG_UTF8);
    4135              : 
    4136              :     /* See notes in hv_store_string */
    4137            9 :     hlen = -(int) strlen(hkey);
    4138            9 :     ret = hv_fetch(hv, hkey, hlen, 0);
    4139              : 
    4140            9 :     if (hkey != key)
    4141            0 :         pfree(hkey);
    4142              : 
    4143            9 :     return ret;
    4144              : }
    4145              : 
    4146              : /*
    4147              :  * Provide function name for PL/Perl execution errors
    4148              :  */
    4149              : static void
    4150          234 : plperl_exec_callback(void *arg)
    4151              : {
    4152          234 :     char       *procname = (char *) arg;
    4153              : 
    4154          234 :     if (procname)
    4155          234 :         errcontext("PL/Perl function \"%s\"", procname);
    4156          234 : }
    4157              : 
    4158              : /*
    4159              :  * Provide function name for PL/Perl compilation errors
    4160              :  */
    4161              : static void
    4162            4 : plperl_compile_callback(void *arg)
    4163              : {
    4164            4 :     char       *procname = (char *) arg;
    4165              : 
    4166            4 :     if (procname)
    4167            4 :         errcontext("compilation of PL/Perl function \"%s\"", procname);
    4168            4 : }
    4169              : 
    4170              : /*
    4171              :  * Provide error context for the inline handler
    4172              :  */
    4173              : static void
    4174           23 : plperl_inline_callback(void *arg)
    4175              : {
    4176           23 :     errcontext("PL/Perl anonymous code block");
    4177           23 : }
    4178              : 
    4179              : 
    4180              : /*
    4181              :  * Perl's own setlocale(), copied from POSIX.xs
    4182              :  * (needed because of the calls to new_*())
    4183              :  *
    4184              :  * Starting in 5.28, perl exposes Perl_setlocale to do so.
    4185              :  */
    4186              : #if defined(WIN32) && PERL_VERSION_LT(5, 28, 0)
    4187              : static char *
    4188              : setlocale_perl(int category, char *locale)
    4189              : {
    4190              :     dTHX;
    4191              :     char       *RETVAL = setlocale(category, locale);
    4192              : 
    4193              :     if (RETVAL)
    4194              :     {
    4195              : #ifdef USE_LOCALE_CTYPE
    4196              :         if (category == LC_CTYPE
    4197              : #ifdef LC_ALL
    4198              :             || category == LC_ALL
    4199              : #endif
    4200              :             )
    4201              :         {
    4202              :             char       *newctype;
    4203              : 
    4204              : #ifdef LC_ALL
    4205              :             if (category == LC_ALL)
    4206              :                 newctype = setlocale(LC_CTYPE, NULL);
    4207              :             else
    4208              : #endif
    4209              :                 newctype = RETVAL;
    4210              :             new_ctype(newctype);
    4211              :         }
    4212              : #endif                          /* USE_LOCALE_CTYPE */
    4213              : #ifdef USE_LOCALE_COLLATE
    4214              :         if (category == LC_COLLATE
    4215              : #ifdef LC_ALL
    4216              :             || category == LC_ALL
    4217              : #endif
    4218              :             )
    4219              :         {
    4220              :             char       *newcoll;
    4221              : 
    4222              : #ifdef LC_ALL
    4223              :             if (category == LC_ALL)
    4224              :                 newcoll = setlocale(LC_COLLATE, NULL);
    4225              :             else
    4226              : #endif
    4227              :                 newcoll = RETVAL;
    4228              :             new_collate(newcoll);
    4229              :         }
    4230              : #endif                          /* USE_LOCALE_COLLATE */
    4231              : 
    4232              : #ifdef USE_LOCALE_NUMERIC
    4233              :         if (category == LC_NUMERIC
    4234              : #ifdef LC_ALL
    4235              :             || category == LC_ALL
    4236              : #endif
    4237              :             )
    4238              :         {
    4239              :             char       *newnum;
    4240              : 
    4241              : #ifdef LC_ALL
    4242              :             if (category == LC_ALL)
    4243              :                 newnum = setlocale(LC_NUMERIC, NULL);
    4244              :             else
    4245              : #endif
    4246              :                 newnum = RETVAL;
    4247              :             new_numeric(newnum);
    4248              :         }
    4249              : #endif                          /* USE_LOCALE_NUMERIC */
    4250              :     }
    4251              : 
    4252              :     return RETVAL;
    4253              : }
    4254              : #endif                          /* defined(WIN32) && PERL_VERSION_LT(5, 28, 0) */
        

Generated by: LCOV version 2.0-1