PostgreSQL Source Code  git master
plperl.h File Reference
#include "EXTERN.h"
#include "perl.h"
#include "ppport.h"
Include dependency graph for plperl.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define PERL_UNUSED_DECL   pg_attribute_unused()
 
#define PERL_NO_GET_CONTEXT
 
#define vsnprintf   pg_vsnprintf
 
#define snprintf   pg_snprintf
 
#define vsprintf   pg_vsprintf
 
#define sprintf   pg_sprintf
 
#define vfprintf   pg_vfprintf
 
#define fprintf   pg_fprintf
 
#define vprintf   pg_vprintf
 
#define printf(...)   pg_printf(__VA_ARGS__)
 
#define _(x)   dgettext(TEXTDOMAIN, x)
 
#define HeUTF8(he)
 
#define GvCV_set(gv, cv)   (GvCV(gv) = cv)
 
#define AV_SIZE_MAX   I32_MAX
 

Functions

HV * plperl_spi_exec (char *, int)
 
void plperl_return_next (SV *)
 
SV * plperl_spi_query (char *)
 
SV * plperl_spi_fetchrow (char *)
 
SV * plperl_spi_prepare (char *, int, SV **)
 
HV * plperl_spi_exec_prepared (char *, HV *, int, SV **)
 
SV * plperl_spi_query_prepared (char *, int, SV **)
 
void plperl_spi_freeplan (char *)
 
void plperl_spi_cursor_close (char *)
 
void plperl_spi_commit (void)
 
void plperl_spi_rollback (void)
 
char * plperl_sv_to_literal (SV *, char *)
 
void plperl_util_elog (int level, SV *msg)
 

Macro Definition Documentation

◆ _

#define _ (   x)    dgettext(TEXTDOMAIN, x)

Definition at line 157 of file plperl.h.

◆ AV_SIZE_MAX

#define AV_SIZE_MAX   I32_MAX

Definition at line 198 of file plperl.h.

◆ fprintf

#define fprintf   pg_fprintf

Definition at line 145 of file plperl.h.

◆ GvCV_set

#define GvCV_set (   gv,
  cv 
)    (GvCV(gv) = cv)

Definition at line 191 of file plperl.h.

◆ HeUTF8

#define HeUTF8 (   he)
Value:
((HeKLEN(he) == HEf_SVKEY) ? \
SvUTF8(HeKEY_sv(he)) : \
(U32)HeKUTF8(he))
#define HEf_SVKEY
Definition: ppport.h:12118
#define SvUTF8(sv)
Definition: ppport.h:17000

Definition at line 184 of file plperl.h.

◆ PERL_NO_GET_CONTEXT

#define PERL_NO_GET_CONTEXT

Definition at line 76 of file plperl.h.

◆ PERL_UNUSED_DECL

#define PERL_UNUSED_DECL   pg_attribute_unused()

Definition at line 26 of file plperl.h.

◆ printf

#define printf (   ...)    pg_printf(__VA_ARGS__)

Definition at line 147 of file plperl.h.

◆ snprintf

#define snprintf   pg_snprintf

Definition at line 141 of file plperl.h.

◆ sprintf

#define sprintf   pg_sprintf

Definition at line 143 of file plperl.h.

◆ vfprintf

#define vfprintf   pg_vfprintf

Definition at line 144 of file plperl.h.

◆ vprintf

#define vprintf   pg_vprintf

Definition at line 146 of file plperl.h.

◆ vsnprintf

#define vsnprintf   pg_vsnprintf

Definition at line 140 of file plperl.h.

◆ vsprintf

#define vsprintf   pg_vsprintf

Definition at line 142 of file plperl.h.

Function Documentation

◆ plperl_return_next()

void plperl_return_next ( SV *  sv)

Definition at line 3234 of file plperl.c.

3235 {
3236  MemoryContext oldcontext = CurrentMemoryContext;
3237 
3239 
3240  PG_TRY();
3241  {
3243  }
3244  PG_CATCH();
3245  {
3246  ErrorData *edata;
3247 
3248  /* Must reset elog.c's state */
3249  MemoryContextSwitchTo(oldcontext);
3250  edata = CopyErrorData();
3251  FlushErrorState();
3252 
3253  /* Punt the error to Perl */
3254  croak_cstr(edata->message);
3255  }
3256  PG_END_TRY();
3257 }
void FlushErrorState(void)
Definition: elog.c:1649
ErrorData * CopyErrorData(void)
Definition: elog.c:1555
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define PG_CATCH()
Definition: elog.h:309
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void check_spi_usage_allowed(void)
Definition: plperl.c:3095
static void plperl_return_next_internal(SV *sv)
Definition: plperl.c:3264
static void croak_cstr(const char *str)
char * message
Definition: elog.h:368

References check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, PG_CATCH, PG_END_TRY, PG_TRY, and plperl_return_next_internal().

◆ plperl_spi_commit()

void plperl_spi_commit ( void  )

Definition at line 3980 of file plperl.c.

3981 {
3982  MemoryContext oldcontext = CurrentMemoryContext;
3983 
3985 
3986  PG_TRY();
3987  {
3988  SPI_commit();
3989  }
3990  PG_CATCH();
3991  {
3992  ErrorData *edata;
3993 
3994  /* Save error info */
3995  MemoryContextSwitchTo(oldcontext);
3996  edata = CopyErrorData();
3997  FlushErrorState();
3998 
3999  /* Punt the error to Perl */
4000  croak_cstr(edata->message);
4001  }
4002  PG_END_TRY();
4003 }
void SPI_commit(void)
Definition: spi.c:321

References check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, PG_CATCH, PG_END_TRY, PG_TRY, and SPI_commit().

◆ plperl_spi_cursor_close()

void plperl_spi_cursor_close ( char *  cursor)

Definition at line 3540 of file plperl.c.

3541 {
3542  Portal p;
3543 
3545 
3546  p = SPI_cursor_find(cursor);
3547 
3548  if (p)
3549  {
3550  UnpinPortal(p);
3551  SPI_cursor_close(p);
3552  }
3553 }
void UnpinPortal(Portal portal)
Definition: portalmem.c:381
Portal SPI_cursor_find(const char *name)
Definition: spi.c:1792
void SPI_cursor_close(Portal portal)
Definition: spi.c:1860
Definition: type.h:131

References check_spi_usage_allowed(), SPI_cursor_close(), SPI_cursor_find(), and UnpinPortal().

◆ plperl_spi_exec()

HV* plperl_spi_exec ( char *  query,
int  limit 
)

Definition at line 3122 of file plperl.c.

3123 {
3124  HV *ret_hv;
3125 
3126  /*
3127  * Execute the query inside a sub-transaction, so we can cope with errors
3128  * sanely
3129  */
3130  MemoryContext oldcontext = CurrentMemoryContext;
3132 
3134 
3136  /* Want to run inside function's memory context */
3137  MemoryContextSwitchTo(oldcontext);
3138 
3139  PG_TRY();
3140  {
3141  int spi_rv;
3142 
3143  pg_verifymbstr(query, strlen(query), false);
3144 
3146  limit);
3148  spi_rv);
3149 
3150  /* Commit the inner transaction, return to outer xact context */
3152  MemoryContextSwitchTo(oldcontext);
3153  CurrentResourceOwner = oldowner;
3154  }
3155  PG_CATCH();
3156  {
3157  ErrorData *edata;
3158 
3159  /* Save error info */
3160  MemoryContextSwitchTo(oldcontext);
3161  edata = CopyErrorData();
3162  FlushErrorState();
3163 
3164  /* Abort the inner transaction */
3166  MemoryContextSwitchTo(oldcontext);
3167  CurrentResourceOwner = oldowner;
3168 
3169  /* Punt the error to Perl */
3170  croak_cstr(edata->message);
3171 
3172  /* Can't get here, but keep compiler quiet */
3173  return NULL;
3174  }
3175  PG_END_TRY();
3176 
3177  return ret_hv;
3178 }
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: mbutils.c:1505
static HV * plperl_spi_execute_fetch_result(SPITupleTable *, uint64, int)
Definition: plperl.c:3182
static plperl_call_data * current_call_data
Definition: plperl.c:243
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
uint64 SPI_processed
Definition: spi.c:45
SPITupleTable * SPI_tuptable
Definition: spi.c:46
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:594
plperl_proc_desc * prodesc
Definition: plperl.c:175
bool fn_readonly
Definition: plperl.c:111
void BeginInternalSubTransaction(const char *name)
Definition: xact.c:4490
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4595
void ReleaseCurrentSubTransaction(void)
Definition: xact.c:4561

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, FlushErrorState(), plperl_proc_desc::fn_readonly, MemoryContextSwitchTo(), ErrorData::message, PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), plperl_spi_execute_fetch_result(), plperl_call_data::prodesc, ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), SPI_execute(), SPI_processed, and SPI_tuptable.

◆ plperl_spi_exec_prepared()

HV* plperl_spi_exec_prepared ( char *  query,
HV *  attr,
int  argc,
SV **  argv 
)

Definition at line 3704 of file plperl.c.

3705 {
3706  HV *ret_hv;
3707  SV **sv;
3708  int i,
3709  limit,
3710  spi_rv;
3711  char *nulls;
3712  Datum *argvalues;
3713  plperl_query_desc *qdesc;
3714  plperl_query_entry *hash_entry;
3715 
3716  /*
3717  * Execute the query inside a sub-transaction, so we can cope with errors
3718  * sanely
3719  */
3720  MemoryContext oldcontext = CurrentMemoryContext;
3722 
3724 
3726  /* Want to run inside function's memory context */
3727  MemoryContextSwitchTo(oldcontext);
3728 
3729  PG_TRY();
3730  {
3731  dTHX;
3732 
3733  /************************************************************
3734  * Fetch the saved plan descriptor, see if it's o.k.
3735  ************************************************************/
3736  hash_entry = hash_search(plperl_active_interp->query_hash, query,
3737  HASH_FIND, NULL);
3738  if (hash_entry == NULL)
3739  elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
3740 
3741  qdesc = hash_entry->query_data;
3742  if (qdesc == NULL)
3743  elog(ERROR, "spi_exec_prepared: plperl query_hash value vanished");
3744 
3745  if (qdesc->nargs != argc)
3746  elog(ERROR, "spi_exec_prepared: expected %d argument(s), %d passed",
3747  qdesc->nargs, argc);
3748 
3749  /************************************************************
3750  * Parse eventual attributes
3751  ************************************************************/
3752  limit = 0;
3753  if (attr != NULL)
3754  {
3755  sv = hv_fetch_string(attr, "limit");
3756  if (sv && *sv && SvIOK(*sv))
3757  limit = SvIV(*sv);
3758  }
3759  /************************************************************
3760  * Set up arguments
3761  ************************************************************/
3762  if (argc > 0)
3763  {
3764  nulls = (char *) palloc(argc);
3765  argvalues = (Datum *) palloc(argc * sizeof(Datum));
3766  }
3767  else
3768  {
3769  nulls = NULL;
3770  argvalues = NULL;
3771  }
3772 
3773  for (i = 0; i < argc; i++)
3774  {
3775  bool isnull;
3776 
3777  argvalues[i] = plperl_sv_to_datum(argv[i],
3778  qdesc->argtypes[i],
3779  -1,
3780  NULL,
3781  &qdesc->arginfuncs[i],
3782  qdesc->argtypioparams[i],
3783  &isnull);
3784  nulls[i] = isnull ? 'n' : ' ';
3785  }
3786 
3787  /************************************************************
3788  * go
3789  ************************************************************/
3790  spi_rv = SPI_execute_plan(qdesc->plan, argvalues, nulls,
3793  spi_rv);
3794  if (argc > 0)
3795  {
3796  pfree(argvalues);
3797  pfree(nulls);
3798  }
3799 
3800  /* Commit the inner transaction, return to outer xact context */
3802  MemoryContextSwitchTo(oldcontext);
3803  CurrentResourceOwner = oldowner;
3804  }
3805  PG_CATCH();
3806  {
3807  ErrorData *edata;
3808 
3809  /* Save error info */
3810  MemoryContextSwitchTo(oldcontext);
3811  edata = CopyErrorData();
3812  FlushErrorState();
3813 
3814  /* Abort the inner transaction */
3816  MemoryContextSwitchTo(oldcontext);
3817  CurrentResourceOwner = oldowner;
3818 
3819  /* Punt the error to Perl */
3820  croak_cstr(edata->message);
3821 
3822  /* Can't get here, but keep compiler quiet */
3823  return NULL;
3824  }
3825  PG_END_TRY();
3826 
3827  return ret_hv;
3828 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:954
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
@ HASH_FIND
Definition: hsearch.h:113
int i
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
static plperl_interp_desc * plperl_active_interp
Definition: plperl.c:227
static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod, FunctionCallInfo fcinfo, FmgrInfo *finfo, Oid typioparam, bool *isnull)
Definition: plperl.c:1310
static SV ** hv_fetch_string(HV *hv, const char *key)
Definition: plperl.c:4109
uintptr_t Datum
Definition: postgres.h:411
#define dTHX
Definition: ppport.h:11306
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:670
HTAB * query_hash
Definition: plperl.c:89
FmgrInfo * arginfuncs
Definition: plperl.c:195
Oid * argtypes
Definition: plperl.c:194
SPIPlanPtr plan
Definition: plperl.c:192
Oid * argtypioparams
Definition: plperl.c:196
Definition: plperl.c:202
plperl_query_desc * query_data
Definition: plperl.c:204

References plperl_query_desc::arginfuncs, plperl_query_desc::argtypes, plperl_query_desc::argtypioparams, BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, dTHX, elog, ERROR, FlushErrorState(), plperl_proc_desc::fn_readonly, HASH_FIND, hash_search(), hv_fetch_string(), i, MemoryContextSwitchTo(), ErrorData::message, plperl_query_desc::nargs, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, plperl_query_desc::plan, plperl_active_interp, plperl_spi_execute_fetch_result(), plperl_sv_to_datum(), plperl_call_data::prodesc, plperl_query_entry::query_data, plperl_interp_desc::query_hash, ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), SPI_execute_plan(), SPI_processed, and SPI_tuptable.

◆ plperl_spi_fetchrow()

SV* plperl_spi_fetchrow ( char *  cursor)

Definition at line 3465 of file plperl.c.

3466 {
3467  SV *row;
3468 
3469  /*
3470  * Execute the FETCH inside a sub-transaction, so we can cope with errors
3471  * sanely
3472  */
3473  MemoryContext oldcontext = CurrentMemoryContext;
3475 
3477 
3479  /* Want to run inside function's memory context */
3480  MemoryContextSwitchTo(oldcontext);
3481 
3482  PG_TRY();
3483  {
3484  dTHX;
3486 
3487  if (!p)
3488  {
3489  row = &PL_sv_undef;
3490  }
3491  else
3492  {
3493  SPI_cursor_fetch(p, true, 1);
3494  if (SPI_processed == 0)
3495  {
3496  UnpinPortal(p);
3497  SPI_cursor_close(p);
3498  row = &PL_sv_undef;
3499  }
3500  else
3501  {
3504  true);
3505  }
3507  }
3508 
3509  /* Commit the inner transaction, return to outer xact context */
3511  MemoryContextSwitchTo(oldcontext);
3512  CurrentResourceOwner = oldowner;
3513  }
3514  PG_CATCH();
3515  {
3516  ErrorData *edata;
3517 
3518  /* Save error info */
3519  MemoryContextSwitchTo(oldcontext);
3520  edata = CopyErrorData();
3521  FlushErrorState();
3522 
3523  /* Abort the inner transaction */
3525  MemoryContextSwitchTo(oldcontext);
3526  CurrentResourceOwner = oldowner;
3527 
3528  /* Punt the error to Perl */
3529  croak_cstr(edata->message);
3530 
3531  /* Can't get here, but keep compiler quiet */
3532  return NULL;
3533  }
3534  PG_END_TRY();
3535 
3536  return row;
3537 }
static SV * plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated)
Definition: plperl.c:3015
#define PL_sv_undef
Definition: ppport.h:11780
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition: spi.c:1804
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:1384
TupleDesc tupdesc
Definition: spi.h:25
HeapTuple * vals
Definition: spi.h:26

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, CurrentResourceOwner, dTHX, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, PG_CATCH, PG_END_TRY, PG_TRY, PL_sv_undef, plperl_hash_from_tuple(), ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), SPI_cursor_close(), SPI_cursor_fetch(), SPI_cursor_find(), SPI_freetuptable(), SPI_processed, SPI_tuptable, SPITupleTable::tupdesc, UnpinPortal(), and SPITupleTable::vals.

◆ plperl_spi_freeplan()

void plperl_spi_freeplan ( char *  query)

Definition at line 3949 of file plperl.c.

3950 {
3951  SPIPlanPtr plan;
3952  plperl_query_desc *qdesc;
3953  plperl_query_entry *hash_entry;
3954 
3956 
3957  hash_entry = hash_search(plperl_active_interp->query_hash, query,
3958  HASH_FIND, NULL);
3959  if (hash_entry == NULL)
3960  elog(ERROR, "spi_freeplan: Invalid prepared query passed");
3961 
3962  qdesc = hash_entry->query_data;
3963  if (qdesc == NULL)
3964  elog(ERROR, "spi_freeplan: plperl query_hash value vanished");
3965  plan = qdesc->plan;
3966 
3967  /*
3968  * free all memory before SPI_freeplan, so if it dies, nothing will be
3969  * left over
3970  */
3972  HASH_REMOVE, NULL);
3973 
3974  MemoryContextDelete(qdesc->plan_cxt);
3975 
3976  SPI_freeplan(plan);
3977 }
@ HASH_REMOVE
Definition: hsearch.h:115
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
int SPI_freeplan(SPIPlanPtr plan)
Definition: spi.c:1023
MemoryContext plan_cxt
Definition: plperl.c:191

References check_spi_usage_allowed(), elog, ERROR, HASH_FIND, HASH_REMOVE, hash_search(), MemoryContextDelete(), plperl_query_desc::plan, plperl_query_desc::plan_cxt, plperl_active_interp, plperl_query_entry::query_data, plperl_interp_desc::query_hash, and SPI_freeplan().

◆ plperl_spi_prepare()

SV* plperl_spi_prepare ( char *  query,
int  argc,
SV **  argv 
)

Definition at line 3556 of file plperl.c.

3557 {
3558  volatile SPIPlanPtr plan = NULL;
3559  volatile MemoryContext plan_cxt = NULL;
3560  plperl_query_desc *volatile qdesc = NULL;
3561  plperl_query_entry *volatile hash_entry = NULL;
3562  MemoryContext oldcontext = CurrentMemoryContext;
3564  MemoryContext work_cxt;
3565  bool found;
3566  int i;
3567 
3569 
3571  MemoryContextSwitchTo(oldcontext);
3572 
3573  PG_TRY();
3574  {
3576 
3577  /************************************************************
3578  * Allocate the new querydesc structure
3579  *
3580  * The qdesc struct, as well as all its subsidiary data, lives in its
3581  * plan_cxt. But note that the SPIPlan does not.
3582  ************************************************************/
3584  "PL/Perl spi_prepare query",
3586  MemoryContextSwitchTo(plan_cxt);
3587  qdesc = (plperl_query_desc *) palloc0(sizeof(plperl_query_desc));
3588  snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
3589  qdesc->plan_cxt = plan_cxt;
3590  qdesc->nargs = argc;
3591  qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
3592  qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
3593  qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
3594  MemoryContextSwitchTo(oldcontext);
3595 
3596  /************************************************************
3597  * Do the following work in a short-lived context so that we don't
3598  * leak a lot of memory in the PL/Perl function's SPI Proc context.
3599  ************************************************************/
3601  "PL/Perl spi_prepare workspace",
3603  MemoryContextSwitchTo(work_cxt);
3604 
3605  /************************************************************
3606  * Resolve argument type names and then look them up by oid
3607  * in the system cache, and remember the required information
3608  * for input conversion.
3609  ************************************************************/
3610  for (i = 0; i < argc; i++)
3611  {
3612  Oid typId,
3613  typInput,
3614  typIOParam;
3615  int32 typmod;
3616  char *typstr;
3617 
3618  typstr = sv2cstr(argv[i]);
3619  parseTypeString(typstr, &typId, &typmod, false);
3620  pfree(typstr);
3621 
3622  getTypeInputInfo(typId, &typInput, &typIOParam);
3623 
3624  qdesc->argtypes[i] = typId;
3625  fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
3626  qdesc->argtypioparams[i] = typIOParam;
3627  }
3628 
3629  /* Make sure the query is validly encoded */
3630  pg_verifymbstr(query, strlen(query), false);
3631 
3632  /************************************************************
3633  * Prepare the plan and check for errors
3634  ************************************************************/
3635  plan = SPI_prepare(query, argc, qdesc->argtypes);
3636 
3637  if (plan == NULL)
3638  elog(ERROR, "SPI_prepare() failed:%s",
3640 
3641  /************************************************************
3642  * Save the plan into permanent memory (right now it's in the
3643  * SPI procCxt, which will go away at function end).
3644  ************************************************************/
3645  if (SPI_keepplan(plan))
3646  elog(ERROR, "SPI_keepplan() failed");
3647  qdesc->plan = plan;
3648 
3649  /************************************************************
3650  * Insert a hashtable entry for the plan.
3651  ************************************************************/
3653  qdesc->qname,
3654  HASH_ENTER, &found);
3655  hash_entry->query_data = qdesc;
3656 
3657  /* Get rid of workspace */
3658  MemoryContextDelete(work_cxt);
3659 
3660  /* Commit the inner transaction, return to outer xact context */
3662  MemoryContextSwitchTo(oldcontext);
3663  CurrentResourceOwner = oldowner;
3664  }
3665  PG_CATCH();
3666  {
3667  ErrorData *edata;
3668 
3669  /* Save error info */
3670  MemoryContextSwitchTo(oldcontext);
3671  edata = CopyErrorData();
3672  FlushErrorState();
3673 
3674  /* Drop anything we managed to allocate */
3675  if (hash_entry)
3677  qdesc->qname,
3678  HASH_REMOVE, NULL);
3679  if (plan_cxt)
3680  MemoryContextDelete(plan_cxt);
3681  if (plan)
3682  SPI_freeplan(plan);
3683 
3684  /* Abort the inner transaction */
3686  MemoryContextSwitchTo(oldcontext);
3687  CurrentResourceOwner = oldowner;
3688 
3689  /* Punt the error to Perl */
3690  croak_cstr(edata->message);
3691 
3692  /* Can't get here, but keep compiler quiet */
3693  return NULL;
3694  }
3695  PG_END_TRY();
3696 
3697  /************************************************************
3698  * Return the query's hash key to the caller.
3699  ************************************************************/
3700  return cstr2sv(qdesc->qname);
3701 }
signed int int32
Definition: c.h:429
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
@ HASH_ENTER
Definition: hsearch.h:114
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2831
MemoryContext TopMemoryContext
Definition: mcxt.c:48
void * palloc0(Size size)
Definition: mcxt.c:1099
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:782
static SV * cstr2sv(const char *str)
static char * sv2cstr(SV *sv)
#define snprintf
Definition: port.h:225
unsigned int Oid
Definition: postgres_ext.h:31
int SPI_result
Definition: spi.c:47
const char * SPI_result_code_string(int code)
Definition: spi.c:1970
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:858
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:974
Definition: fmgr.h:57
char qname[24]
Definition: plperl.c:190

References ALLOCSET_DEFAULT_SIZES, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, plperl_query_desc::arginfuncs, plperl_query_desc::argtypes, plperl_query_desc::argtypioparams, BeginInternalSubTransaction(), CHECK_FOR_INTERRUPTS, check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, FlushErrorState(), fmgr_info_cxt(), getTypeInputInfo(), HASH_ENTER, HASH_REMOVE, hash_search(), i, MemoryContextDelete(), MemoryContextSwitchTo(), ErrorData::message, plperl_query_desc::nargs, palloc(), palloc0(), parseTypeString(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), plperl_query_desc::plan, plperl_query_desc::plan_cxt, plperl_active_interp, plperl_query_desc::qname, plperl_query_entry::query_data, plperl_interp_desc::query_hash, ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), snprintf, SPI_freeplan(), SPI_keepplan(), SPI_prepare(), SPI_result, SPI_result_code_string(), sv2cstr(), and TopMemoryContext.

◆ plperl_spi_query()

SV* plperl_spi_query ( char *  query)

Definition at line 3393 of file plperl.c.

3394 {
3395  SV *cursor;
3396 
3397  /*
3398  * Execute the query inside a sub-transaction, so we can cope with errors
3399  * sanely
3400  */
3401  MemoryContext oldcontext = CurrentMemoryContext;
3403 
3405 
3407  /* Want to run inside function's memory context */
3408  MemoryContextSwitchTo(oldcontext);
3409 
3410  PG_TRY();
3411  {
3412  SPIPlanPtr plan;
3413  Portal portal;
3414 
3415  /* Make sure the query is validly encoded */
3416  pg_verifymbstr(query, strlen(query), false);
3417 
3418  /* Create a cursor for the query */
3419  plan = SPI_prepare(query, 0, NULL);
3420  if (plan == NULL)
3421  elog(ERROR, "SPI_prepare() failed:%s",
3423 
3424  portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
3425  SPI_freeplan(plan);
3426  if (portal == NULL)
3427  elog(ERROR, "SPI_cursor_open() failed:%s",
3429  cursor = cstr2sv(portal->name);
3430 
3431  PinPortal(portal);
3432 
3433  /* Commit the inner transaction, return to outer xact context */
3435  MemoryContextSwitchTo(oldcontext);
3436  CurrentResourceOwner = oldowner;
3437  }
3438  PG_CATCH();
3439  {
3440  ErrorData *edata;
3441 
3442  /* Save error info */
3443  MemoryContextSwitchTo(oldcontext);
3444  edata = CopyErrorData();
3445  FlushErrorState();
3446 
3447  /* Abort the inner transaction */
3449  MemoryContextSwitchTo(oldcontext);
3450  CurrentResourceOwner = oldowner;
3451 
3452  /* Punt the error to Perl */
3453  croak_cstr(edata->message);
3454 
3455  /* Can't get here, but keep compiler quiet */
3456  return NULL;
3457  }
3458  PG_END_TRY();
3459 
3460  return cursor;
3461 }
void PinPortal(Portal portal)
Definition: portalmem.c:372
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1443
const char * name
Definition: portal.h:118

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, PortalData::name, PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), PinPortal(), ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), SPI_cursor_open(), SPI_freeplan(), SPI_prepare(), SPI_result, and SPI_result_code_string().

◆ plperl_spi_query_prepared()

SV* plperl_spi_query_prepared ( char *  query,
int  argc,
SV **  argv 
)

Definition at line 3831 of file plperl.c.

3832 {
3833  int i;
3834  char *nulls;
3835  Datum *argvalues;
3836  plperl_query_desc *qdesc;
3837  plperl_query_entry *hash_entry;
3838  SV *cursor;
3839  Portal portal = NULL;
3840 
3841  /*
3842  * Execute the query inside a sub-transaction, so we can cope with errors
3843  * sanely
3844  */
3845  MemoryContext oldcontext = CurrentMemoryContext;
3847 
3849 
3851  /* Want to run inside function's memory context */
3852  MemoryContextSwitchTo(oldcontext);
3853 
3854  PG_TRY();
3855  {
3856  /************************************************************
3857  * Fetch the saved plan descriptor, see if it's o.k.
3858  ************************************************************/
3859  hash_entry = hash_search(plperl_active_interp->query_hash, query,
3860  HASH_FIND, NULL);
3861  if (hash_entry == NULL)
3862  elog(ERROR, "spi_query_prepared: Invalid prepared query passed");
3863 
3864  qdesc = hash_entry->query_data;
3865  if (qdesc == NULL)
3866  elog(ERROR, "spi_query_prepared: plperl query_hash value vanished");
3867 
3868  if (qdesc->nargs != argc)
3869  elog(ERROR, "spi_query_prepared: expected %d argument(s), %d passed",
3870  qdesc->nargs, argc);
3871 
3872  /************************************************************
3873  * Set up arguments
3874  ************************************************************/
3875  if (argc > 0)
3876  {
3877  nulls = (char *) palloc(argc);
3878  argvalues = (Datum *) palloc(argc * sizeof(Datum));
3879  }
3880  else
3881  {
3882  nulls = NULL;
3883  argvalues = NULL;
3884  }
3885 
3886  for (i = 0; i < argc; i++)
3887  {
3888  bool isnull;
3889 
3890  argvalues[i] = plperl_sv_to_datum(argv[i],
3891  qdesc->argtypes[i],
3892  -1,
3893  NULL,
3894  &qdesc->arginfuncs[i],
3895  qdesc->argtypioparams[i],
3896  &isnull);
3897  nulls[i] = isnull ? 'n' : ' ';
3898  }
3899 
3900  /************************************************************
3901  * go
3902  ************************************************************/
3903  portal = SPI_cursor_open(NULL, qdesc->plan, argvalues, nulls,
3905  if (argc > 0)
3906  {
3907  pfree(argvalues);
3908  pfree(nulls);
3909  }
3910  if (portal == NULL)
3911  elog(ERROR, "SPI_cursor_open() failed:%s",
3913 
3914  cursor = cstr2sv(portal->name);
3915 
3916  PinPortal(portal);
3917 
3918  /* Commit the inner transaction, return to outer xact context */
3920  MemoryContextSwitchTo(oldcontext);
3921  CurrentResourceOwner = oldowner;
3922  }
3923  PG_CATCH();
3924  {
3925  ErrorData *edata;
3926 
3927  /* Save error info */
3928  MemoryContextSwitchTo(oldcontext);
3929  edata = CopyErrorData();
3930  FlushErrorState();
3931 
3932  /* Abort the inner transaction */
3934  MemoryContextSwitchTo(oldcontext);
3935  CurrentResourceOwner = oldowner;
3936 
3937  /* Punt the error to Perl */
3938  croak_cstr(edata->message);
3939 
3940  /* Can't get here, but keep compiler quiet */
3941  return NULL;
3942  }
3943  PG_END_TRY();
3944 
3945  return cursor;
3946 }

References plperl_query_desc::arginfuncs, plperl_query_desc::argtypes, plperl_query_desc::argtypioparams, BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, FlushErrorState(), plperl_proc_desc::fn_readonly, HASH_FIND, hash_search(), i, MemoryContextSwitchTo(), ErrorData::message, PortalData::name, plperl_query_desc::nargs, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, PinPortal(), plperl_query_desc::plan, plperl_active_interp, plperl_sv_to_datum(), plperl_call_data::prodesc, plperl_query_entry::query_data, plperl_interp_desc::query_hash, ReleaseCurrentSubTransaction(), RollbackAndReleaseCurrentSubTransaction(), SPI_cursor_open(), SPI_result, and SPI_result_code_string().

◆ plperl_spi_rollback()

void plperl_spi_rollback ( void  )

Definition at line 4006 of file plperl.c.

4007 {
4008  MemoryContext oldcontext = CurrentMemoryContext;
4009 
4011 
4012  PG_TRY();
4013  {
4014  SPI_rollback();
4015  }
4016  PG_CATCH();
4017  {
4018  ErrorData *edata;
4019 
4020  /* Save error info */
4021  MemoryContextSwitchTo(oldcontext);
4022  edata = CopyErrorData();
4023  FlushErrorState();
4024 
4025  /* Punt the error to Perl */
4026  croak_cstr(edata->message);
4027  }
4028  PG_END_TRY();
4029 }
void SPI_rollback(void)
Definition: spi.c:414

References check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, PG_CATCH, PG_END_TRY, PG_TRY, and SPI_rollback().

◆ plperl_sv_to_literal()

char* plperl_sv_to_literal ( SV *  sv,
char *  fqtypename 
)

Definition at line 1431 of file plperl.c.

1432 {
1433  Oid typid;
1434  Oid typoutput;
1435  Datum datum;
1436  bool typisvarlena,
1437  isnull;
1438 
1440 
1441  typid = DirectFunctionCall1(regtypein, CStringGetDatum(fqtypename));
1442  if (!OidIsValid(typid))
1443  ereport(ERROR,
1444  (errcode(ERRCODE_UNDEFINED_OBJECT),
1445  errmsg("lookup failed for type %s", fqtypename)));
1446 
1447  datum = plperl_sv_to_datum(sv,
1448  typid, -1,
1449  NULL, NULL, InvalidOid,
1450  &isnull);
1451 
1452  if (isnull)
1453  return NULL;
1454 
1455  getTypeOutputInfo(typid,
1456  &typoutput, &typisvarlena);
1457 
1458  return OidOutputFunctionCall(typoutput, datum);
1459 }
#define OidIsValid(objectId)
Definition: c.h:710
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ereport(elevel,...)
Definition: elog.h:143
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1639
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
#define CStringGetDatum(X)
Definition: postgres.h:622
#define InvalidOid
Definition: postgres_ext.h:36
Datum regtypein(PG_FUNCTION_ARGS)
Definition: regproc.c:1251

References check_spi_usage_allowed(), CStringGetDatum, DirectFunctionCall1, ereport, errcode(), errmsg(), ERROR, getTypeOutputInfo(), InvalidOid, OidIsValid, OidOutputFunctionCall(), plperl_sv_to_datum(), and regtypein().

◆ plperl_util_elog()

void plperl_util_elog ( int  level,
SV *  msg 
)

Definition at line 4043 of file plperl.c.

4044 {
4045  MemoryContext oldcontext = CurrentMemoryContext;
4046  char *volatile cmsg = NULL;
4047 
4048  /*
4049  * We intentionally omit check_spi_usage_allowed() here, as this seems
4050  * safe to allow even in the contexts that that function rejects.
4051  */
4052 
4053  PG_TRY();
4054  {
4055  cmsg = sv2cstr(msg);
4056  elog(level, "%s", cmsg);
4057  pfree(cmsg);
4058  }
4059  PG_CATCH();
4060  {
4061  ErrorData *edata;
4062 
4063  /* Must reset elog.c's state */
4064  MemoryContextSwitchTo(oldcontext);
4065  edata = CopyErrorData();
4066  FlushErrorState();
4067 
4068  if (cmsg)
4069  pfree(cmsg);
4070 
4071  /* Punt the error to Perl */
4072  croak_cstr(edata->message);
4073  }
4074  PG_END_TRY();
4075 }

References CopyErrorData(), croak_cstr(), CurrentMemoryContext, elog, FlushErrorState(), MemoryContextSwitchTo(), ErrorData::message, pfree(), PG_CATCH, PG_END_TRY, PG_TRY, and sv2cstr().