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

3253{
3255
3257
3258 PG_TRY();
3259 {
3261 }
3262 PG_CATCH();
3263 {
3265
3266 /* Must reset elog.c's state */
3267 MemoryContextSwitchTo(oldcontext);
3268 edata = CopyErrorData();
3270
3271 /* Punt the error to Perl */
3272 croak_cstr(edata->message);
3273 }
3274 PG_END_TRY();
3275}
ErrorData * CopyErrorData(void)
Definition elog.c:1942
void FlushErrorState(void)
Definition elog.c:2063
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define PG_CATCH(...)
Definition elog.h:384
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:3113
static void plperl_return_next_internal(SV *sv)
Definition plperl.c:3282
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 3998 of file plperl.c.

3999{
4001
4003
4004 PG_TRY();
4005 {
4006 SPI_commit();
4007 }
4008 PG_CATCH();
4009 {
4011
4012 /* Save error info */
4013 MemoryContextSwitchTo(oldcontext);
4014 edata = CopyErrorData();
4016
4017 /* Punt the error to Perl */
4018 croak_cstr(edata->message);
4019 }
4020 PG_END_TRY();
4021}
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 3558 of file plperl.c.

3559{
3560 Portal p;
3561
3563
3565
3566 if (p)
3567 {
3568 UnpinPortal(p);
3570 }
3571}
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 3140 of file plperl.c.

3141{
3142 HV *ret_hv;
3143
3144 /*
3145 * Execute the query inside a sub-transaction, so we can cope with errors
3146 * sanely
3147 */
3150
3152
3154 /* Want to run inside function's memory context */
3155 MemoryContextSwitchTo(oldcontext);
3156
3157 PG_TRY();
3158 {
3159 int spi_rv;
3160
3161 pg_verifymbstr(query, strlen(query), false);
3162
3164 limit);
3166 spi_rv);
3167
3168 /* Commit the inner transaction, return to outer xact context */
3170 MemoryContextSwitchTo(oldcontext);
3171 CurrentResourceOwner = oldowner;
3172 }
3173 PG_CATCH();
3174 {
3176
3177 /* Save error info */
3178 MemoryContextSwitchTo(oldcontext);
3179 edata = CopyErrorData();
3181
3182 /* Abort the inner transaction */
3184 MemoryContextSwitchTo(oldcontext);
3185 CurrentResourceOwner = oldowner;
3186
3187 /* Punt the error to Perl */
3188 croak_cstr(edata->message);
3189
3190 /* Can't get here, but keep compiler quiet */
3191 return NULL;
3192 }
3193 PG_END_TRY();
3194
3195 return ret_hv;
3196}
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition mbutils.c:1682
static HV * plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed, int status)
Definition plperl.c:3200
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:4745
void RollbackAndReleaseCurrentSubTransaction(void)
Definition xact.c:4847
void ReleaseCurrentSubTransaction(void)
Definition xact.c:4819

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

3723{
3724 HV *ret_hv;
3725 SV **sv;
3726 int i,
3727 limit,
3728 spi_rv;
3729 char *nulls;
3733
3734 /*
3735 * Execute the query inside a sub-transaction, so we can cope with errors
3736 * sanely
3737 */
3740
3742
3744 /* Want to run inside function's memory context */
3745 MemoryContextSwitchTo(oldcontext);
3746
3747 PG_TRY();
3748 {
3749 dTHX;
3750
3751 /************************************************************
3752 * Fetch the saved plan descriptor, see if it's o.k.
3753 ************************************************************/
3755 HASH_FIND, NULL);
3756 if (hash_entry == NULL)
3757 elog(ERROR, "spi_exec_prepared: Invalid prepared query passed");
3758
3759 qdesc = hash_entry->query_data;
3760 if (qdesc == NULL)
3761 elog(ERROR, "spi_exec_prepared: plperl query_hash value vanished");
3762
3763 if (qdesc->nargs != argc)
3764 elog(ERROR, "spi_exec_prepared: expected %d argument(s), %d passed",
3765 qdesc->nargs, argc);
3766
3767 /************************************************************
3768 * Parse eventual attributes
3769 ************************************************************/
3770 limit = 0;
3771 if (attr != NULL)
3772 {
3773 sv = hv_fetch_string(attr, "limit");
3774 if (sv && *sv && SvIOK(*sv))
3775 limit = SvIV(*sv);
3776 }
3777 /************************************************************
3778 * Set up arguments
3779 ************************************************************/
3780 if (argc > 0)
3781 {
3782 nulls = (char *) palloc(argc);
3783 argvalues = (Datum *) palloc(argc * sizeof(Datum));
3784 }
3785 else
3786 {
3787 nulls = NULL;
3788 argvalues = NULL;
3789 }
3790
3791 for (i = 0; i < argc; i++)
3792 {
3793 bool isnull;
3794
3796 qdesc->argtypes[i],
3797 -1,
3798 NULL,
3799 &qdesc->arginfuncs[i],
3800 qdesc->argtypioparams[i],
3801 &isnull);
3802 nulls[i] = isnull ? 'n' : ' ';
3803 }
3804
3805 /************************************************************
3806 * go
3807 ************************************************************/
3808 spi_rv = SPI_execute_plan(qdesc->plan, argvalues, nulls,
3811 spi_rv);
3812 if (argc > 0)
3813 {
3815 pfree(nulls);
3816 }
3817
3818 /* Commit the inner transaction, return to outer xact context */
3820 MemoryContextSwitchTo(oldcontext);
3821 CurrentResourceOwner = oldowner;
3822 }
3823 PG_CATCH();
3824 {
3826
3827 /* Save error info */
3828 MemoryContextSwitchTo(oldcontext);
3829 edata = CopyErrorData();
3831
3832 /* Abort the inner transaction */
3834 MemoryContextSwitchTo(oldcontext);
3835 CurrentResourceOwner = oldowner;
3836
3837 /* Punt the error to Perl */
3838 croak_cstr(edata->message);
3839
3840 /* Can't get here, but keep compiler quiet */
3841 return NULL;
3842 }
3843 PG_END_TRY();
3844
3845 return ret_hv;
3846}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:889
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
@ HASH_FIND
Definition hsearch.h:108
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:1329
static SV ** hv_fetch_string(HV *hv, const char *key)
Definition plperl.c:4127
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 3483 of file plperl.c.

3484{
3485 SV *row;
3486
3487 /*
3488 * Execute the FETCH inside a sub-transaction, so we can cope with errors
3489 * sanely
3490 */
3493
3495
3497 /* Want to run inside function's memory context */
3498 MemoryContextSwitchTo(oldcontext);
3499
3500 PG_TRY();
3501 {
3502 dTHX;
3504
3505 if (!p)
3506 {
3507 row = &PL_sv_undef;
3508 }
3509 else
3510 {
3511 SPI_cursor_fetch(p, true, 1);
3512 if (SPI_processed == 0)
3513 {
3514 UnpinPortal(p);
3516 row = &PL_sv_undef;
3517 }
3518 else
3519 {
3522 true);
3523 }
3525 }
3526
3527 /* Commit the inner transaction, return to outer xact context */
3529 MemoryContextSwitchTo(oldcontext);
3530 CurrentResourceOwner = oldowner;
3531 }
3532 PG_CATCH();
3533 {
3535
3536 /* Save error info */
3537 MemoryContextSwitchTo(oldcontext);
3538 edata = CopyErrorData();
3540
3541 /* Abort the inner transaction */
3543 MemoryContextSwitchTo(oldcontext);
3544 CurrentResourceOwner = oldowner;
3545
3546 /* Punt the error to Perl */
3547 croak_cstr(edata->message);
3548
3549 /* Can't get here, but keep compiler quiet */
3550 return NULL;
3551 }
3552 PG_END_TRY();
3553
3554 return row;
3555}
static SV * plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated)
Definition plperl.c:3030
#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 3967 of file plperl.c.

3968{
3972
3974
3976 HASH_FIND, NULL);
3977 if (hash_entry == NULL)
3978 elog(ERROR, "spi_freeplan: Invalid prepared query passed");
3979
3980 qdesc = hash_entry->query_data;
3981 if (qdesc == NULL)
3982 elog(ERROR, "spi_freeplan: plperl query_hash value vanished");
3983 plan = qdesc->plan;
3984
3985 /*
3986 * free all memory before SPI_freeplan, so if it dies, nothing will be
3987 * left over
3988 */
3990 HASH_REMOVE, NULL);
3991
3992 MemoryContextDelete(qdesc->plan_cxt);
3993
3995}
@ HASH_REMOVE
Definition hsearch.h:110
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define plan(x)
Definition pg_regress.c:164
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 3574 of file plperl.c.

3575{
3576 volatile SPIPlanPtr plan = NULL;
3577 volatile MemoryContext plan_cxt = NULL;
3578 plperl_query_desc *volatile qdesc = NULL;
3583 bool found;
3584 int i;
3585
3587
3589 MemoryContextSwitchTo(oldcontext);
3590
3591 PG_TRY();
3592 {
3594
3595 /************************************************************
3596 * Allocate the new querydesc structure
3597 *
3598 * The qdesc struct, as well as all its subsidiary data, lives in its
3599 * plan_cxt. But note that the SPIPlan does not.
3600 ************************************************************/
3602 "PL/Perl spi_prepare query",
3604 MemoryContextSwitchTo(plan_cxt);
3606 snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
3607 qdesc->plan_cxt = plan_cxt;
3608 qdesc->nargs = argc;
3609 qdesc->argtypes = (Oid *) palloc(argc * sizeof(Oid));
3610 qdesc->arginfuncs = (FmgrInfo *) palloc(argc * sizeof(FmgrInfo));
3611 qdesc->argtypioparams = (Oid *) palloc(argc * sizeof(Oid));
3612 MemoryContextSwitchTo(oldcontext);
3613
3614 /************************************************************
3615 * Do the following work in a short-lived context so that we don't
3616 * leak a lot of memory in the PL/Perl function's SPI Proc context.
3617 ************************************************************/
3619 "PL/Perl spi_prepare workspace",
3622
3623 /************************************************************
3624 * Resolve argument type names and then look them up by oid
3625 * in the system cache, and remember the required information
3626 * for input conversion.
3627 ************************************************************/
3628 for (i = 0; i < argc; i++)
3629 {
3630 Oid typId,
3631 typInput,
3632 typIOParam;
3633 int32 typmod;
3634 char *typstr;
3635
3636 typstr = sv2cstr(argv[i]);
3637 (void) parseTypeString(typstr, &typId, &typmod, NULL);
3638 pfree(typstr);
3639
3641
3642 qdesc->argtypes[i] = typId;
3643 fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
3644 qdesc->argtypioparams[i] = typIOParam;
3645 }
3646
3647 /* Make sure the query is validly encoded */
3648 pg_verifymbstr(query, strlen(query), false);
3649
3650 /************************************************************
3651 * Prepare the plan and check for errors
3652 ************************************************************/
3653 plan = SPI_prepare(query, argc, qdesc->argtypes);
3654
3655 if (plan == NULL)
3656 elog(ERROR, "SPI_prepare() failed:%s",
3658
3659 /************************************************************
3660 * Save the plan into permanent memory (right now it's in the
3661 * SPI procCxt, which will go away at function end).
3662 ************************************************************/
3663 if (SPI_keepplan(plan))
3664 elog(ERROR, "SPI_keepplan() failed");
3665 qdesc->plan = plan;
3666
3667 /************************************************************
3668 * Insert a hashtable entry for the plan.
3669 ************************************************************/
3671 qdesc->qname,
3672 HASH_ENTER, &found);
3673 hash_entry->query_data = qdesc;
3674
3675 /* Get rid of workspace */
3677
3678 /* Commit the inner transaction, return to outer xact context */
3680 MemoryContextSwitchTo(oldcontext);
3681 CurrentResourceOwner = oldowner;
3682 }
3683 PG_CATCH();
3684 {
3686
3687 /* Save error info */
3688 MemoryContextSwitchTo(oldcontext);
3689 edata = CopyErrorData();
3691
3692 /* Drop anything we managed to allocate */
3693 if (hash_entry)
3695 qdesc->qname,
3696 HASH_REMOVE, NULL);
3697 if (plan_cxt)
3698 MemoryContextDelete(plan_cxt);
3699 if (plan)
3701
3702 /* Abort the inner transaction */
3704 MemoryContextSwitchTo(oldcontext);
3705 CurrentResourceOwner = oldowner;
3706
3707 /* Punt the error to Perl */
3708 croak_cstr(edata->message);
3709
3710 /* Can't get here, but keep compiler quiet */
3711 return NULL;
3712 }
3713 PG_END_TRY();
3714
3715 /************************************************************
3716 * Return the query's hash key to the caller.
3717 ************************************************************/
3718 return cstr2sv(qdesc->qname);
3719}
int32_t int32
Definition c.h:620
#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:109
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition lsyscache.c:3069
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:125
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 3411 of file plperl.c.

3412{
3413 SV *cursor;
3414
3415 /*
3416 * Execute the query inside a sub-transaction, so we can cope with errors
3417 * sanely
3418 */
3421
3423
3425 /* Want to run inside function's memory context */
3426 MemoryContextSwitchTo(oldcontext);
3427
3428 PG_TRY();
3429 {
3431 Portal portal;
3432
3433 /* Make sure the query is validly encoded */
3434 pg_verifymbstr(query, strlen(query), false);
3435
3436 /* Create a cursor for the query */
3437 plan = SPI_prepare(query, 0, NULL);
3438 if (plan == NULL)
3439 elog(ERROR, "SPI_prepare() failed:%s",
3441
3442 portal = SPI_cursor_open(NULL, plan, NULL, NULL, false);
3444 if (portal == NULL)
3445 elog(ERROR, "SPI_cursor_open() failed:%s",
3447 cursor = cstr2sv(portal->name);
3448
3449 PinPortal(portal);
3450
3451 /* Commit the inner transaction, return to outer xact context */
3453 MemoryContextSwitchTo(oldcontext);
3454 CurrentResourceOwner = oldowner;
3455 }
3456 PG_CATCH();
3457 {
3459
3460 /* Save error info */
3461 MemoryContextSwitchTo(oldcontext);
3462 edata = CopyErrorData();
3464
3465 /* Abort the inner transaction */
3467 MemoryContextSwitchTo(oldcontext);
3468 CurrentResourceOwner = oldowner;
3469
3470 /* Punt the error to Perl */
3471 croak_cstr(edata->message);
3472
3473 /* Can't get here, but keep compiler quiet */
3474 return NULL;
3475 }
3476 PG_END_TRY();
3477
3478 return cursor;
3479}
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 3849 of file plperl.c.

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

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

4025{
4027
4029
4030 PG_TRY();
4031 {
4032 SPI_rollback();
4033 }
4034 PG_CATCH();
4035 {
4037
4038 /* Save error info */
4039 MemoryContextSwitchTo(oldcontext);
4040 edata = CopyErrorData();
4042
4043 /* Punt the error to Perl */
4044 croak_cstr(edata->message);
4045 }
4046 PG_END_TRY();
4047}
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 1450 of file plperl.c.

1451{
1452 Oid typid;
1453 Oid typoutput;
1454 Datum datum;
1455 bool typisvarlena,
1456 isnull;
1457
1459
1461 if (!OidIsValid(typid))
1462 ereport(ERROR,
1464 errmsg("lookup failed for type %s", fqtypename)));
1465
1466 datum = plperl_sv_to_datum(sv,
1467 typid, -1,
1469 &isnull);
1470
1471 if (isnull)
1472 return NULL;
1473
1474 getTypeOutputInfo(typid,
1475 &typoutput, &typisvarlena);
1476
1477 return OidOutputFunctionCall(typoutput, datum);
1478}
#define OidIsValid(objectId)
Definition c.h:858
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereport(elevel,...)
Definition elog.h:152
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:3102
static char * errmsg
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#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 4061 of file plperl.c.

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

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().