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

Generated by: LCOV version 1.14