PostgreSQL Source Code git master
Loading...
Searching...
No Matches
plperl.h File Reference
#include "mb/pg_wchar.h"
#include "plperl_system.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.

Functions

HVplperl_spi_exec (char *, int)
 
void plperl_return_next (SV *)
 
SVplperl_spi_query (char *)
 
SVplperl_spi_fetchrow (char *)
 
SVplperl_spi_prepare (char *, int, SV **)
 
HVplperl_spi_exec_prepared (char *, HV *, int, SV **)
 
SVplperl_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)
 
charplperl_sv_to_literal (SV *, char *)
 
void plperl_util_elog (int level, SV *msg)
 
static charutf_u2e (char *utf8_str, size_t len)
 
static charutf_e2u (const char *str)
 
static charsv2cstr (SV *sv)
 
static SVcstr2sv (const char *str)
 
static void croak_cstr (const char *str)
 

Function Documentation

◆ croak_cstr()

static void croak_cstr ( const char str)
inlinestatic

Definition at line 175 of file plperl.h.

176{
177 dTHX;
178
179#ifdef croak_sv
180 /* Use sv_2mortal() to be sure the transient SV gets freed */
182#else
183
184 /*
185 * The older way to do this is to assign a UTF8-marked value to ERRSV and
186 * then call croak(NULL). But if we leave it to croak() to append the
187 * error location, it does so too late (only after popping the stack) in
188 * some Perl versions. Hence, use mess() to create an SV with the error
189 * location info already appended.
190 */
191 SV *errsv = get_sv("@", GV_ADD);
192 char *utf8_str = utf_e2u(str);
193 SV *ssv;
194
195 ssv = mess("%s", utf8_str);
196 SvUTF8_on(ssv);
197
199
201
202 croak(NULL);
203#endif /* croak_sv */
204}
const char * str
void pfree(void *pointer)
Definition mcxt.c:1616
static char * utf_e2u(const char *str)
Definition plperl.h:70
static SV * cstr2sv(const char *str)
Definition plperl.h:147
#define get_sv
Definition ppport.h:12463
#define dTHX
Definition ppport.h:11306
#define croak_sv(sv)
Definition ppport.h:14714
static int fb(int x)

References croak_sv, cstr2sv(), dTHX, fb(), get_sv, pfree(), str, and utf_e2u().

Referenced by plperl_return_next(), plperl_spi_commit(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), plperl_spi_rollback(), and plperl_util_elog().

◆ cstr2sv()

static SV * cstr2sv ( const char str)
inlinestatic

◆ plperl_return_next()

void plperl_return_next ( SV sv)

Definition at line 3247 of file plperl.c.

3248{
3250
3252
3253 PG_TRY();
3254 {
3256 }
3257 PG_CATCH();
3258 {
3260
3261 /* Must reset elog.c's state */
3262 MemoryContextSwitchTo(oldcontext);
3263 edata = CopyErrorData();
3265
3266 /* Punt the error to Perl */
3267 croak_cstr(edata->message);
3268 }
3269 PG_END_TRY();
3270}
ErrorData * CopyErrorData(void)
Definition elog.c:1941
void FlushErrorState(void)
Definition elog.c:2062
#define PG_TRY(...)
Definition elog.h:372
#define PG_END_TRY(...)
Definition elog.h:397
#define PG_CATCH(...)
Definition elog.h:382
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static void check_spi_usage_allowed(void)
Definition plperl.c:3108
static void plperl_return_next_internal(SV *sv)
Definition plperl.c:3277
static void croak_cstr(const char *str)
Definition plperl.h:175

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

◆ plperl_spi_commit()

void plperl_spi_commit ( void  )

Definition at line 3993 of file plperl.c.

3994{
3996
3998
3999 PG_TRY();
4000 {
4001 SPI_commit();
4002 }
4003 PG_CATCH();
4004 {
4006
4007 /* Save error info */
4008 MemoryContextSwitchTo(oldcontext);
4009 edata = CopyErrorData();
4011
4012 /* Punt the error to Perl */
4013 croak_cstr(edata->message);
4014 }
4015 PG_END_TRY();
4016}
void SPI_commit(void)
Definition spi.c:321

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

◆ plperl_spi_cursor_close()

void plperl_spi_cursor_close ( char cursor)

Definition at line 3553 of file plperl.c.

3554{
3555 Portal p;
3556
3558
3560
3561 if (p)
3562 {
3563 UnpinPortal(p);
3565 }
3566}
void UnpinPortal(Portal portal)
Definition portalmem.c:381
Portal SPI_cursor_find(const char *name)
Definition spi.c:1795
void SPI_cursor_close(Portal portal)
Definition spi.c:1863
Definition type.h:138

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 3135 of file plperl.c.

3136{
3137 HV *ret_hv;
3138
3139 /*
3140 * Execute the query inside a sub-transaction, so we can cope with errors
3141 * sanely
3142 */
3145
3147
3149 /* Want to run inside function's memory context */
3150 MemoryContextSwitchTo(oldcontext);
3151
3152 PG_TRY();
3153 {
3154 int spi_rv;
3155
3156 pg_verifymbstr(query, strlen(query), false);
3157
3159 limit);
3161 spi_rv);
3162
3163 /* Commit the inner transaction, return to outer xact context */
3165 MemoryContextSwitchTo(oldcontext);
3166 CurrentResourceOwner = oldowner;
3167 }
3168 PG_CATCH();
3169 {
3171
3172 /* Save error info */
3173 MemoryContextSwitchTo(oldcontext);
3174 edata = CopyErrorData();
3176
3177 /* Abort the inner transaction */
3179 MemoryContextSwitchTo(oldcontext);
3180 CurrentResourceOwner = oldowner;
3181
3182 /* Punt the error to Perl */
3183 croak_cstr(edata->message);
3184
3185 /* Can't get here, but keep compiler quiet */
3186 return NULL;
3187 }
3188 PG_END_TRY();
3189
3190 return ret_hv;
3191}
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition mbutils.c:1684
static HV * plperl_spi_execute_fetch_result(SPITupleTable *, uint64, int)
Definition plperl.c:3195
static plperl_call_data * current_call_data
Definition plperl.c:244
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
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:597
plperl_proc_desc * prodesc
Definition plperl.c:176
void BeginInternalSubTransaction(const char *name)
Definition xact.c:4717
void RollbackAndReleaseCurrentSubTransaction(void)
Definition xact.c:4819
void ReleaseCurrentSubTransaction(void)
Definition xact.c:4791

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, fb(), FlushErrorState(), plperl_proc_desc::fn_readonly, MemoryContextSwitchTo(), 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 3717 of file plperl.c.

3718{
3719 HV *ret_hv;
3720 SV **sv;
3721 int i,
3722 limit,
3723 spi_rv;
3724 char *nulls;
3728
3729 /*
3730 * Execute the query inside a sub-transaction, so we can cope with errors
3731 * sanely
3732 */
3735
3737
3739 /* Want to run inside function's memory context */
3740 MemoryContextSwitchTo(oldcontext);
3741
3742 PG_TRY();
3743 {
3744 dTHX;
3745
3746 /************************************************************
3747 * Fetch the saved plan descriptor, see if it's o.k.
3748 ************************************************************/
3750 HASH_FIND, NULL);
3751 if (hash_entry == NULL)
3752 elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
3753
3754 qdesc = hash_entry->query_data;
3755 if (qdesc == NULL)
3756 elog(ERROR, "spi_exec_prepared: plperl query_hash value vanished");
3757
3758 if (qdesc->nargs != argc)
3759 elog(ERROR, "spi_exec_prepared: expected %d argument(s), %d passed",
3760 qdesc->nargs, argc);
3761
3762 /************************************************************
3763 * Parse eventual attributes
3764 ************************************************************/
3765 limit = 0;
3766 if (attr != NULL)
3767 {
3768 sv = hv_fetch_string(attr, "limit");
3769 if (sv && *sv && SvIOK(*sv))
3770 limit = SvIV(*sv);
3771 }
3772 /************************************************************
3773 * Set up arguments
3774 ************************************************************/
3775 if (argc > 0)
3776 {
3777 nulls = (char *) palloc(argc);
3778 argvalues = (Datum *) palloc(argc * sizeof(Datum));
3779 }
3780 else
3781 {
3782 nulls = NULL;
3783 argvalues = NULL;
3784 }
3785
3786 for (i = 0; i < argc; i++)
3787 {
3788 bool isnull;
3789
3791 qdesc->argtypes[i],
3792 -1,
3793 NULL,
3794 &qdesc->arginfuncs[i],
3795 qdesc->argtypioparams[i],
3796 &isnull);
3797 nulls[i] = isnull ? 'n' : ' ';
3798 }
3799
3800 /************************************************************
3801 * go
3802 ************************************************************/
3803 spi_rv = SPI_execute_plan(qdesc->plan, argvalues, nulls,
3806 spi_rv);
3807 if (argc > 0)
3808 {
3810 pfree(nulls);
3811 }
3812
3813 /* Commit the inner transaction, return to outer xact context */
3815 MemoryContextSwitchTo(oldcontext);
3816 CurrentResourceOwner = oldowner;
3817 }
3818 PG_CATCH();
3819 {
3821
3822 /* Save error info */
3823 MemoryContextSwitchTo(oldcontext);
3824 edata = CopyErrorData();
3826
3827 /* Abort the inner transaction */
3829 MemoryContextSwitchTo(oldcontext);
3830 CurrentResourceOwner = oldowner;
3831
3832 /* Punt the error to Perl */
3833 croak_cstr(edata->message);
3834
3835 /* Can't get here, but keep compiler quiet */
3836 return NULL;
3837 }
3838 PG_END_TRY();
3839
3840 return ret_hv;
3841}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:952
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
@ HASH_FIND
Definition hsearch.h:113
int i
Definition isn.c:77
void * palloc(Size size)
Definition mcxt.c:1387
static plperl_interp_desc * plperl_active_interp
Definition plperl.c:228
static Datum plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod, FunctionCallInfo fcinfo, FmgrInfo *finfo, Oid typioparam, bool *isnull)
Definition plperl.c:1326
static SV ** hv_fetch_string(HV *hv, const char *key)
Definition plperl.c:4122
uint64_t Datum
Definition postgres.h:70
int SPI_execute_plan(SPIPlanPtr plan, const Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition spi.c:673
HTAB * query_hash
Definition plperl.c:90
Definition plperl.c:203

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, dTHX, elog, ERROR, fb(), FlushErrorState(), plperl_proc_desc::fn_readonly, HASH_FIND, hash_search(), hv_fetch_string(), i, MemoryContextSwitchTo(), palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, plperl_active_interp, plperl_spi_execute_fetch_result(), plperl_sv_to_datum(), plperl_call_data::prodesc, 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 3478 of file plperl.c.

3479{
3480 SV *row;
3481
3482 /*
3483 * Execute the FETCH inside a sub-transaction, so we can cope with errors
3484 * sanely
3485 */
3488
3490
3492 /* Want to run inside function's memory context */
3493 MemoryContextSwitchTo(oldcontext);
3494
3495 PG_TRY();
3496 {
3497 dTHX;
3499
3500 if (!p)
3501 {
3502 row = &PL_sv_undef;
3503 }
3504 else
3505 {
3506 SPI_cursor_fetch(p, true, 1);
3507 if (SPI_processed == 0)
3508 {
3509 UnpinPortal(p);
3511 row = &PL_sv_undef;
3512 }
3513 else
3514 {
3517 true);
3518 }
3520 }
3521
3522 /* Commit the inner transaction, return to outer xact context */
3524 MemoryContextSwitchTo(oldcontext);
3525 CurrentResourceOwner = oldowner;
3526 }
3527 PG_CATCH();
3528 {
3530
3531 /* Save error info */
3532 MemoryContextSwitchTo(oldcontext);
3533 edata = CopyErrorData();
3535
3536 /* Abort the inner transaction */
3538 MemoryContextSwitchTo(oldcontext);
3539 CurrentResourceOwner = oldowner;
3540
3541 /* Punt the error to Perl */
3542 croak_cstr(edata->message);
3543
3544 /* Can't get here, but keep compiler quiet */
3545 return NULL;
3546 }
3547 PG_END_TRY();
3548
3549 return row;
3550}
static SV * plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated)
Definition plperl.c:3025
#define PL_sv_undef
Definition ppport.h:11780
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition spi.c:1807
void SPI_freetuptable(SPITupleTable *tuptable)
Definition spi.c:1387
TupleDesc tupdesc
Definition spi.h:25
HeapTuple * vals
Definition spi.h:26

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, CurrentResourceOwner, dTHX, fb(), FlushErrorState(), MemoryContextSwitchTo(), 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 3962 of file plperl.c.

3963{
3967
3969
3971 HASH_FIND, NULL);
3972 if (hash_entry == NULL)
3973 elog(ERROR, "spi_freeplan: Invalid prepared query passed");
3974
3975 qdesc = hash_entry->query_data;
3976 if (qdesc == NULL)
3977 elog(ERROR, "spi_freeplan: plperl query_hash value vanished");
3978 plan = qdesc->plan;
3979
3980 /*
3981 * free all memory before SPI_freeplan, so if it dies, nothing will be
3982 * left over
3983 */
3985 HASH_REMOVE, NULL);
3986
3987 MemoryContextDelete(qdesc->plan_cxt);
3988
3990}
@ HASH_REMOVE
Definition hsearch.h:115
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define plan(x)
Definition pg_regress.c:161
int SPI_freeplan(SPIPlanPtr plan)
Definition spi.c:1026

References check_spi_usage_allowed(), elog, ERROR, fb(), HASH_FIND, HASH_REMOVE, hash_search(), MemoryContextDelete(), plan, plperl_active_interp, plperl_interp_desc::query_hash, and SPI_freeplan().

◆ plperl_spi_prepare()

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

Definition at line 3569 of file plperl.c.

3570{
3571 volatile SPIPlanPtr plan = NULL;
3572 volatile MemoryContext plan_cxt = NULL;
3573 plperl_query_desc *volatile qdesc = NULL;
3578 bool found;
3579 int i;
3580
3582
3584 MemoryContextSwitchTo(oldcontext);
3585
3586 PG_TRY();
3587 {
3589
3590 /************************************************************
3591 * Allocate the new querydesc structure
3592 *
3593 * The qdesc struct, as well as all its subsidiary data, lives in its
3594 * plan_cxt. But note that the SPIPlan does not.
3595 ************************************************************/
3597 "PL/Perl spi_prepare query",
3599 MemoryContextSwitchTo(plan_cxt);
3601 snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
3602 qdesc->plan_cxt = plan_cxt;
3603 qdesc->nargs = argc;
3604 qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
3605 qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
3606 qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
3607 MemoryContextSwitchTo(oldcontext);
3608
3609 /************************************************************
3610 * Do the following work in a short-lived context so that we don't
3611 * leak a lot of memory in the PL/Perl function's SPI Proc context.
3612 ************************************************************/
3614 "PL/Perl spi_prepare workspace",
3617
3618 /************************************************************
3619 * Resolve argument type names and then look them up by oid
3620 * in the system cache, and remember the required information
3621 * for input conversion.
3622 ************************************************************/
3623 for (i = 0; i < argc; i++)
3624 {
3625 Oid typId,
3626 typInput,
3627 typIOParam;
3628 int32 typmod;
3629 char *typstr;
3630
3631 typstr = sv2cstr(argv[i]);
3632 (void) parseTypeString(typstr, &typId, &typmod, NULL);
3633 pfree(typstr);
3634
3636
3637 qdesc->argtypes[i] = typId;
3638 fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
3639 qdesc->argtypioparams[i] = typIOParam;
3640 }
3641
3642 /* Make sure the query is validly encoded */
3643 pg_verifymbstr(query, strlen(query), false);
3644
3645 /************************************************************
3646 * Prepare the plan and check for errors
3647 ************************************************************/
3648 plan = SPI_prepare(query, argc, qdesc->argtypes);
3649
3650 if (plan == NULL)
3651 elog(ERROR, "SPI_prepare() failed:%s",
3653
3654 /************************************************************
3655 * Save the plan into permanent memory (right now it's in the
3656 * SPI procCxt, which will go away at function end).
3657 ************************************************************/
3658 if (SPI_keepplan(plan))
3659 elog(ERROR, "SPI_keepplan() failed");
3660 qdesc->plan = plan;
3661
3662 /************************************************************
3663 * Insert a hashtable entry for the plan.
3664 ************************************************************/
3666 qdesc->qname,
3667 HASH_ENTER, &found);
3668 hash_entry->query_data = qdesc;
3669
3670 /* Get rid of workspace */
3672
3673 /* Commit the inner transaction, return to outer xact context */
3675 MemoryContextSwitchTo(oldcontext);
3676 CurrentResourceOwner = oldowner;
3677 }
3678 PG_CATCH();
3679 {
3681
3682 /* Save error info */
3683 MemoryContextSwitchTo(oldcontext);
3684 edata = CopyErrorData();
3686
3687 /* Drop anything we managed to allocate */
3688 if (hash_entry)
3690 qdesc->qname,
3691 HASH_REMOVE, NULL);
3692 if (plan_cxt)
3693 MemoryContextDelete(plan_cxt);
3694 if (plan)
3696
3697 /* Abort the inner transaction */
3699 MemoryContextSwitchTo(oldcontext);
3700 CurrentResourceOwner = oldowner;
3701
3702 /* Punt the error to Perl */
3703 croak_cstr(edata->message);
3704
3705 /* Can't get here, but keep compiler quiet */
3706 return NULL;
3707 }
3708 PG_END_TRY();
3709
3710 /************************************************************
3711 * Return the query's hash key to the caller.
3712 ************************************************************/
3713 return cstr2sv(qdesc->qname);
3714}
int32_t int32
Definition c.h:614
#define palloc0_object(type)
Definition fe_memutils.h:75
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition fmgr.c:139
@ HASH_ENTER
Definition hsearch.h:114
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3096
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
bool parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, Node *escontext)
Definition parse_type.c:785
static char * sv2cstr(SV *sv)
Definition plperl.h:89
#define snprintf
Definition port.h:260
unsigned int Oid
const char * SPI_result_code_string(int code)
Definition spi.c:1973
int SPI_result
Definition spi.c:47
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition spi.c:861
int SPI_keepplan(SPIPlanPtr plan)
Definition spi.c:977

References ALLOCSET_DEFAULT_SIZES, ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BeginInternalSubTransaction(), CHECK_FOR_INTERRUPTS, check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, fb(), FlushErrorState(), fmgr_info_cxt(), getTypeInputInfo(), HASH_ENTER, HASH_REMOVE, hash_search(), i, MemoryContextDelete(), MemoryContextSwitchTo(), palloc(), palloc0_object, parseTypeString(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), plan, plperl_active_interp, 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 3406 of file plperl.c.

3407{
3408 SV *cursor;
3409
3410 /*
3411 * Execute the query inside a sub-transaction, so we can cope with errors
3412 * sanely
3413 */
3416
3418
3420 /* Want to run inside function's memory context */
3421 MemoryContextSwitchTo(oldcontext);
3422
3423 PG_TRY();
3424 {
3426 Portal portal;
3427
3428 /* Make sure the query is validly encoded */
3429 pg_verifymbstr(query, strlen(query), false);
3430
3431 /* Create a cursor for the query */
3432 plan = SPI_prepare(query, 0, NULL);
3433 if (plan == NULL)
3434 elog(ERROR, "SPI_prepare() failed:%s",
3436
3437 portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
3439 if (portal == NULL)
3440 elog(ERROR, "SPI_cursor_open() failed:%s",
3442 cursor = cstr2sv(portal->name);
3443
3444 PinPortal(portal);
3445
3446 /* Commit the inner transaction, return to outer xact context */
3448 MemoryContextSwitchTo(oldcontext);
3449 CurrentResourceOwner = oldowner;
3450 }
3451 PG_CATCH();
3452 {
3454
3455 /* Save error info */
3456 MemoryContextSwitchTo(oldcontext);
3457 edata = CopyErrorData();
3459
3460 /* Abort the inner transaction */
3462 MemoryContextSwitchTo(oldcontext);
3463 CurrentResourceOwner = oldowner;
3464
3465 /* Punt the error to Perl */
3466 croak_cstr(edata->message);
3467
3468 /* Can't get here, but keep compiler quiet */
3469 return NULL;
3470 }
3471 PG_END_TRY();
3472
3473 return cursor;
3474}
void PinPortal(Portal portal)
Definition portalmem.c:372
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, const Datum *Values, const char *Nulls, bool read_only)
Definition spi.c:1446
const char * name
Definition portal.h:118

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, fb(), FlushErrorState(), MemoryContextSwitchTo(), PortalData::name, PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), PinPortal(), plan, 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 3844 of file plperl.c.

3845{
3846 int i;
3847 char *nulls;
3851 SV *cursor;
3852 Portal portal = NULL;
3853
3854 /*
3855 * Execute the query inside a sub-transaction, so we can cope with errors
3856 * sanely
3857 */
3860
3862
3864 /* Want to run inside function's memory context */
3865 MemoryContextSwitchTo(oldcontext);
3866
3867 PG_TRY();
3868 {
3869 /************************************************************
3870 * Fetch the saved plan descriptor, see if it's o.k.
3871 ************************************************************/
3873 HASH_FIND, NULL);
3874 if (hash_entry == NULL)
3875 elog(ERROR, "spi_query_prepared: Invalid prepared query passed");
3876
3877 qdesc = hash_entry->query_data;
3878 if (qdesc == NULL)
3879 elog(ERROR, "spi_query_prepared: plperl query_hash value vanished");
3880
3881 if (qdesc->nargs != argc)
3882 elog(ERROR, "spi_query_prepared: expected %d argument(s), %d passed",
3883 qdesc->nargs, argc);
3884
3885 /************************************************************
3886 * Set up arguments
3887 ************************************************************/
3888 if (argc > 0)
3889 {
3890 nulls = (char *) palloc(argc);
3891 argvalues = (Datum *) palloc(argc * sizeof(Datum));
3892 }
3893 else
3894 {
3895 nulls = NULL;
3896 argvalues = NULL;
3897 }
3898
3899 for (i = 0; i < argc; i++)
3900 {
3901 bool isnull;
3902
3904 qdesc->argtypes[i],
3905 -1,
3906 NULL,
3907 &qdesc->arginfuncs[i],
3908 qdesc->argtypioparams[i],
3909 &isnull);
3910 nulls[i] = isnull ? 'n' : ' ';
3911 }
3912
3913 /************************************************************
3914 * go
3915 ************************************************************/
3916 portal = SPI_cursor_open(NULL, qdesc->plan, argvalues, nulls,
3918 if (argc > 0)
3919 {
3921 pfree(nulls);
3922 }
3923 if (portal == NULL)
3924 elog(ERROR, "SPI_cursor_open() failed:%s",
3926
3927 cursor = cstr2sv(portal->name);
3928
3929 PinPortal(portal);
3930
3931 /* Commit the inner transaction, return to outer xact context */
3933 MemoryContextSwitchTo(oldcontext);
3934 CurrentResourceOwner = oldowner;
3935 }
3936 PG_CATCH();
3937 {
3939
3940 /* Save error info */
3941 MemoryContextSwitchTo(oldcontext);
3942 edata = CopyErrorData();
3944
3945 /* Abort the inner transaction */
3947 MemoryContextSwitchTo(oldcontext);
3948 CurrentResourceOwner = oldowner;
3949
3950 /* Punt the error to Perl */
3951 croak_cstr(edata->message);
3952
3953 /* Can't get here, but keep compiler quiet */
3954 return NULL;
3955 }
3956 PG_END_TRY();
3957
3958 return cursor;
3959}

References BeginInternalSubTransaction(), check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), cstr2sv(), current_call_data, CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, fb(), FlushErrorState(), plperl_proc_desc::fn_readonly, HASH_FIND, hash_search(), i, MemoryContextSwitchTo(), PortalData::name, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_TRY, PinPortal(), plperl_active_interp, plperl_sv_to_datum(), plperl_call_data::prodesc, 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 4019 of file plperl.c.

4020{
4022
4024
4025 PG_TRY();
4026 {
4027 SPI_rollback();
4028 }
4029 PG_CATCH();
4030 {
4032
4033 /* Save error info */
4034 MemoryContextSwitchTo(oldcontext);
4035 edata = CopyErrorData();
4037
4038 /* Punt the error to Perl */
4039 croak_cstr(edata->message);
4040 }
4041 PG_END_TRY();
4042}
void SPI_rollback(void)
Definition spi.c:414

References check_spi_usage_allowed(), CopyErrorData(), croak_cstr(), CurrentMemoryContext, fb(), FlushErrorState(), MemoryContextSwitchTo(), 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 1447 of file plperl.c.

1448{
1449 Oid typid;
1450 Oid typoutput;
1451 Datum datum;
1452 bool typisvarlena,
1453 isnull;
1454
1456
1458 if (!OidIsValid(typid))
1459 ereport(ERROR,
1461 errmsg("lookup failed for type %s", fqtypename)));
1462
1463 datum = plperl_sv_to_datum(sv,
1464 typid, -1,
1466 &isnull);
1467
1468 if (isnull)
1469 return NULL;
1470
1471 getTypeOutputInfo(typid,
1472 &typoutput, &typisvarlena);
1473
1474 return OidOutputFunctionCall(typoutput, datum);
1475}
#define OidIsValid(objectId)
Definition c.h:860
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:150
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1764
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3129
static char * errmsg
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static Datum CStringGetDatum(const char *X)
Definition postgres.h:370
#define InvalidOid
Datum regtypein(PG_FUNCTION_ARGS)
Definition regproc.c:1184

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

◆ plperl_util_elog()

void plperl_util_elog ( int  level,
SV msg 
)

Definition at line 4056 of file plperl.c.

4057{
4059 char *volatile cmsg = NULL;
4060
4061 /*
4062 * We intentionally omit check_spi_usage_allowed() here, as this seems
4063 * safe to allow even in the contexts that that function rejects.
4064 */
4065
4066 PG_TRY();
4067 {
4068 cmsg = sv2cstr(msg);
4069 elog(level, "%s", cmsg);
4070 pfree(cmsg);
4071 }
4072 PG_CATCH();
4073 {
4075
4076 /* Must reset elog.c's state */
4077 MemoryContextSwitchTo(oldcontext);
4078 edata = CopyErrorData();
4080
4081 if (cmsg)
4082 pfree(cmsg);
4083
4084 /* Punt the error to Perl */
4085 croak_cstr(edata->message);
4086 }
4087 PG_END_TRY();
4088}

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

◆ sv2cstr()

static char * sv2cstr ( SV sv)
inlinestatic

Definition at line 89 of file plperl.h.

90{
91 dTHX;
92 char *val,
93 *res;
94 STRLEN len;
95
96 /*
97 * get a utf8 encoded char * out of perl. *note* it may not be valid utf8!
98 */
99
100 /*
101 * SvPVutf8() croaks nastily on certain things, like typeglobs and
102 * readonly objects such as $^V. That's a perl bug - it's not supposed to
103 * happen. To avoid crashing the backend, we make a copy of the sv before
104 * passing it to SvPVutf8(). The copy is garbage collected when we're done
105 * with it.
106 */
107 if (SvREADONLY(sv) ||
108 isGV_with_GP(sv) ||
109 (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM))
110 sv = newSVsv(sv);
111 else
112 {
113 /*
114 * increase the reference count so we can just SvREFCNT_dec() it when
115 * we are done
116 */
118 }
119
120 /*
121 * Request the string from Perl, in UTF-8 encoding; but if we're in a
122 * SQL_ASCII database, just request the byte soup without trying to make
123 * it UTF8, because that might fail.
124 */
126 val = SvPV(sv, len);
127 else
128 val = SvPVutf8(sv, len);
129
130 /*
131 * Now convert to database encoding. We use perl's length in the event we
132 * had an embedded null byte to ensure we error out properly.
133 */
134 res = utf_u2e(val, len);
135
136 /* safe now to garbage collect the new SV */
138
139 return res;
140}
long val
Definition informix.c:689
const void size_t len
static char * utf_u2e(char *utf8_str, size_t len)
Definition plperl.h:51
#define SvREFCNT_inc_simple_void(sv)
Definition ppport.h:15412
#define isGV_with_GP(gv)
Definition ppport.h:15703

References dTHX, fb(), GetDatabaseEncoding(), isGV_with_GP, len, PG_SQL_ASCII, SvREFCNT_inc_simple_void, utf_u2e(), and val.

Referenced by hek2cstr(), plperl_call_perl_event_trigger_func(), plperl_call_perl_func(), plperl_call_perl_trigger_func(), plperl_create_sub(), plperl_init_interp(), plperl_spi_prepare(), plperl_sv_to_datum(), plperl_to_hstore(), plperl_trigger_handler(), plperl_trusted_init(), plperl_untrusted_init(), plperl_util_elog(), select_perl_context(), and SV_to_JsonbValue().

◆ utf_e2u()

static char * utf_e2u ( const char str)
inlinestatic

Definition at line 70 of file plperl.h.

71{
72 char *ret;
73
75
76 /* ensure we have a copy even if no conversion happened */
77 if (ret == str)
78 ret = pstrdup(ret);
79
80 return ret;
81}
#define PG_UTF8
Definition mbprint.c:43
char * pg_server_to_any(const char *s, int len, int encoding)
Definition mbutils.c:760
char * pstrdup(const char *in)
Definition mcxt.c:1781

References fb(), pg_server_to_any(), PG_UTF8, pstrdup(), and str.

Referenced by croak_cstr(), and cstr2sv().

◆ utf_u2e()

static char * utf_u2e ( char utf8_str,
size_t  len 
)
inlinestatic

Definition at line 51 of file plperl.h.

52{
53 char *ret;
54
56
57 /* ensure we have a copy even if no conversion happened */
58 if (ret == utf8_str)
59 ret = pstrdup(ret);
60
61 return ret;
62}
char * pg_any_to_server(const char *s, int len, int encoding)
Definition mbutils.c:687

References fb(), len, pg_any_to_server(), PG_UTF8, and pstrdup().

Referenced by sv2cstr().