@ -43,6 +43,7 @@
/* perl stuff */
/* perl stuff */
# include "plperl.h"
# include "plperl.h"
# include "plperl_helpers.h"
/* string literal macros defining chunks of perl code */
/* string literal macros defining chunks of perl code */
# include "perlchunks.h"
# include "perlchunks.h"
@ -222,7 +223,7 @@ static void plperl_init_shared_libs(pTHX);
static void plperl_trusted_init ( void ) ;
static void plperl_trusted_init ( void ) ;
static void plperl_untrusted_init ( void ) ;
static void plperl_untrusted_init ( void ) ;
static HV * plperl_spi_execute_fetch_result ( SPITupleTable * , int , int ) ;
static HV * plperl_spi_execute_fetch_result ( SPITupleTable * , int , int ) ;
static SV * newSVstring ( const char * str ) ;
static char * hek2cstr ( HE * he ) ;
static SV * * hv_store_string ( HV * hv , const char * key , SV * val ) ;
static SV * * hv_store_string ( HV * hv , const char * key , SV * val ) ;
static SV * * hv_fetch_string ( HV * hv , const char * key ) ;
static SV * * hv_fetch_string ( HV * hv , const char * key ) ;
static void plperl_create_sub ( plperl_proc_desc * desc , char * s , Oid fn_oid ) ;
static void plperl_create_sub ( plperl_proc_desc * desc , char * s , Oid fn_oid ) ;
@ -239,24 +240,39 @@ static char *setlocale_perl(int category, char *locale);
# endif
# endif
/*
/*
* Convert an SV to char * and verify the encoding via pg_verifymbstr ( )
* convert a HE ( hash entry ) key to a cstr in the current database encoding
*/
*/
static inline char *
static char *
sv2text_mbverified ( SV * sv )
hek2cstr ( HE * he )
{
{
char * val ;
STRLEN len ;
/*
/*
* The value returned here might include an embedded nul byte , because
* Unfortunately , while HeUTF8 is true for most things > 256 , for
* perl allows such things . That ' s OK , because pg_verifymbstr will choke
* values 128. .255 it ' s not , but perl will treat them as
* on it , If we just used strlen ( ) instead of getting perl ' s idea of the
* unicode code points if the utf8 flag is not set ( see
* length , whatever uses the " verified " value might get something quite
* The " Unicode Bug " in perldoc perlunicode for more )
* weird .
*
* So if we did the expected :
* if ( HeUTF8 ( he ) )
* utf_u2e ( key . . . ) ;
* else // must be ascii
* return HePV ( he ) ;
* we won ' t match columns with codepoints from 128. .255
*
* For a more concrete example given a column with the
* name of the unicode codepoint U + 00 ae ( registered sign )
* and a UTF8 database and the perl return_next {
* " \ N{U+00ae}=>'text } would always fail as heUTF8
* returns 0 and HePV ( ) would give us a char * with 1 byte
* contains the decimal value 174
*
* Perl has the brains to know when it should utf8 encode
* 174 properly , so here we force it into an SV so that
* perl will figure it out and do the right thing
*/
*/
val = SvPV ( sv , len ) ;
SV * sv = HeSVKEY_force ( he ) ;
pg_verifymbstr ( val , len , false ) ;
if ( HeUTF8 ( he ) )
return val ;
SvUTF8_on ( sv ) ;
return sv2cstr ( sv ) ;
}
}
/*
/*
@ -568,7 +584,7 @@ select_perl_context(bool trusted)
eval_pv ( " PostgreSQL::InServer::SPI::bootstrap() " , FALSE ) ;
eval_pv ( " PostgreSQL::InServer::SPI::bootstrap() " , FALSE ) ;
if ( SvTRUE ( ERRSV ) )
if ( SvTRUE ( ERRSV ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while executing PostgreSQL::InServer::SPI::bootstrap " ) ) ) ;
errcontext ( " while executing PostgreSQL::InServer::SPI::bootstrap " ) ) ) ;
/* Fully initialized, so mark the hashtable entry valid */
/* Fully initialized, so mark the hashtable entry valid */
@ -609,7 +625,6 @@ static PerlInterpreter *
plperl_init_interp ( void )
plperl_init_interp ( void )
{
{
PerlInterpreter * plperl ;
PerlInterpreter * plperl ;
static int perl_sys_init_done ;
static char * embedding [ 3 + 2 ] = {
static char * embedding [ 3 + 2 ] = {
" " , " -e " , PLC_PERLBOOT
" " , " -e " , PLC_PERLBOOT
@ -678,15 +693,19 @@ plperl_init_interp(void)
* true when MYMALLOC is set .
* true when MYMALLOC is set .
*/
*/
# if defined(PERL_SYS_INIT3) && !defined(MYMALLOC)
# if defined(PERL_SYS_INIT3) && !defined(MYMALLOC)
/* only call this the first time through, as per perlembed man page */
if ( ! perl_sys_init_done )
{
{
char * dummy_env [ 1 ] = { NULL } ;
static int perl_sys_init_done ;
PERL_SYS_INIT3 ( & nargs , ( char * * * ) & embedding , ( char * * * ) & dummy_env ) ;
/* only call this the first time through, as per perlembed man page */
perl_sys_init_done = 1 ;
if ( ! perl_sys_init_done )
/* quiet warning if PERL_SYS_INIT3 doesn't use the third argument */
{
dummy_env [ 0 ] = NULL ;
char * dummy_env [ 1 ] = { NULL } ;
PERL_SYS_INIT3 ( & nargs , ( char * * * ) & embedding , ( char * * * ) & dummy_env ) ;
perl_sys_init_done = 1 ;
/* quiet warning if PERL_SYS_INIT3 doesn't use the third argument */
dummy_env [ 0 ] = NULL ;
}
}
}
# endif
# endif
@ -727,12 +746,12 @@ plperl_init_interp(void)
if ( perl_parse ( plperl , plperl_init_shared_libs ,
if ( perl_parse ( plperl , plperl_init_shared_libs ,
nargs , embedding , NULL ) ! = 0 )
nargs , embedding , NULL ) ! = 0 )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while parsing Perl initialization " ) ) ) ;
errcontext ( " while parsing Perl initialization " ) ) ) ;
if ( perl_run ( plperl ) ! = 0 )
if ( perl_run ( plperl ) ! = 0 )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while running Perl initialization " ) ) ) ;
errcontext ( " while running Perl initialization " ) ) ) ;
# ifdef PLPERL_RESTORE_LOCALE
# ifdef PLPERL_RESTORE_LOCALE
@ -836,22 +855,19 @@ plperl_trusted_init(void)
eval_pv ( PLC_TRUSTED , FALSE ) ;
eval_pv ( PLC_TRUSTED , FALSE ) ;
if ( SvTRUE ( ERRSV ) )
if ( SvTRUE ( ERRSV ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while executing PLC_TRUSTED " ) ) ) ;
errcontext ( " while executing PLC_TRUSTED " ) ) ) ;
if ( GetDatabaseEncoding ( ) = = PG_UTF8 )
/*
{
* Force loading of utf8 module now to prevent errors that can arise
/*
* from the regex code later trying to load utf8 modules . See
* Force loading of utf8 module now to prevent errors that can arise
* http : //rt.perl.org/rt3/Ticket/Display.html?id=47576
* from the regex code later trying to load utf8 modules . See
*/
* http : //rt.perl.org/rt3/Ticket/Display.html?id=47576
eval_pv ( " my $a=chr(0x100); return $a =~ / \\ xa9/i " , FALSE ) ;
*/
if ( SvTRUE ( ERRSV ) )
eval_pv ( " my $a=chr(0x100); return $a =~ / \\ xa9/i " , FALSE ) ;
ereport ( ERROR ,
if ( SvTRUE ( ERRSV ) )
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
ereport ( ERROR ,
errcontext ( " while executing utf8fix " ) ) ) ;
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
errcontext ( " while executing utf8fix " ) ) ) ;
}
/*
/*
* Lock down the interpreter
* Lock down the interpreter
@ -891,7 +907,7 @@ plperl_trusted_init(void)
eval_pv ( plperl_on_plperl_init , FALSE ) ;
eval_pv ( plperl_on_plperl_init , FALSE ) ;
if ( SvTRUE ( ERRSV ) )
if ( SvTRUE ( ERRSV ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while executing plperl.on_plperl_init " ) ) ) ;
errcontext ( " while executing plperl.on_plperl_init " ) ) ) ;
}
}
@ -912,7 +928,7 @@ plperl_untrusted_init(void)
eval_pv ( plperl_on_plperlu_init , FALSE ) ;
eval_pv ( plperl_on_plperlu_init , FALSE ) ;
if ( SvTRUE ( ERRSV ) )
if ( SvTRUE ( ERRSV ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ,
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ,
errcontext ( " while executing plperl.on_plperlu_init " ) ) ) ;
errcontext ( " while executing plperl.on_plperlu_init " ) ) ) ;
}
}
}
}
@ -940,17 +956,18 @@ plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
{
{
TupleDesc td = attinmeta - > tupdesc ;
TupleDesc td = attinmeta - > tupdesc ;
char * * values ;
char * * values ;
SV * val ;
HE * he ;
char * key ;
I32 klen ;
HeapTuple tup ;
HeapTuple tup ;
int i ;
values = ( char * * ) palloc0 ( td - > natts * sizeof ( char * ) ) ;
values = ( char * * ) palloc0 ( td - > natts * sizeof ( char * ) ) ;
hv_iterinit ( perlhash ) ;
hv_iterinit ( perlhash ) ;
while ( ( val = hv_iternextsv ( perlhash , & key , & klen ) ) )
while ( ( he = hv_iternext ( perlhash ) ) )
{
{
int attn = SPI_fnumber ( td , key ) ;
SV * val = HeVAL ( he ) ;
char * key = hek2cstr ( he ) ;
int attn = SPI_fnumber ( td , key ) ;
if ( attn < = 0 | | td - > attrs [ attn - 1 ] - > attisdropped )
if ( attn < = 0 | | td - > attrs [ attn - 1 ] - > attisdropped )
ereport ( ERROR ,
ereport ( ERROR ,
@ -959,13 +976,22 @@ plperl_build_tuple_result(HV *perlhash, AttInMetadata *attinmeta)
key ) ) ) ;
key ) ) ) ;
if ( SvOK ( val ) )
if ( SvOK ( val ) )
{
{
values [ attn - 1 ] = sv2text_mbverified ( val ) ;
values [ attn - 1 ] = sv2cstr ( val ) ;
}
}
pfree ( key ) ;
}
}
hv_iterinit ( perlhash ) ;
hv_iterinit ( perlhash ) ;
tup = BuildTupleFromCStrings ( attinmeta , values ) ;
tup = BuildTupleFromCStrings ( attinmeta , values ) ;
for ( i = 0 ; i < td - > natts ; i + + )
{
if ( values [ i ] )
pfree ( values [ i ] ) ;
}
pfree ( values ) ;
pfree ( values ) ;
return tup ;
return tup ;
}
}
@ -1025,8 +1051,8 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
)
)
) ;
) ;
hv_store_string ( hv , " name " , newSVstring ( tdata - > tg_trigger - > tgname ) ) ;
hv_store_string ( hv , " name " , cstr2sv ( tdata - > tg_trigger - > tgname ) ) ;
hv_store_string ( hv , " relid " , newSVstring ( relid ) ) ;
hv_store_string ( hv , " relid " , cstr2sv ( relid ) ) ;
if ( TRIGGER_FIRED_BY_INSERT ( tdata - > tg_event ) )
if ( TRIGGER_FIRED_BY_INSERT ( tdata - > tg_event ) )
{
{
@ -1062,7 +1088,7 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
else
else
event = " UNKNOWN " ;
event = " UNKNOWN " ;
hv_store_string ( hv , " event " , newSVstring ( event ) ) ;
hv_store_string ( hv , " event " , cstr2sv ( event ) ) ;
hv_store_string ( hv , " argc " , newSViv ( tdata - > tg_trigger - > tgnargs ) ) ;
hv_store_string ( hv , " argc " , newSViv ( tdata - > tg_trigger - > tgnargs ) ) ;
if ( tdata - > tg_trigger - > tgnargs > 0 )
if ( tdata - > tg_trigger - > tgnargs > 0 )
@ -1071,18 +1097,18 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
av_extend ( av , tdata - > tg_trigger - > tgnargs ) ;
av_extend ( av , tdata - > tg_trigger - > tgnargs ) ;
for ( i = 0 ; i < tdata - > tg_trigger - > tgnargs ; i + + )
for ( i = 0 ; i < tdata - > tg_trigger - > tgnargs ; i + + )
av_push ( av , newSVstring ( tdata - > tg_trigger - > tgargs [ i ] ) ) ;
av_push ( av , cstr2sv ( tdata - > tg_trigger - > tgargs [ i ] ) ) ;
hv_store_string ( hv , " args " , newRV_noinc ( ( SV * ) av ) ) ;
hv_store_string ( hv , " args " , newRV_noinc ( ( SV * ) av ) ) ;
}
}
hv_store_string ( hv , " relname " ,
hv_store_string ( hv , " relname " ,
newSVstring ( SPI_getrelname ( tdata - > tg_relation ) ) ) ;
cstr2sv ( SPI_getrelname ( tdata - > tg_relation ) ) ) ;
hv_store_string ( hv , " table_name " ,
hv_store_string ( hv , " table_name " ,
newSVstring ( SPI_getrelname ( tdata - > tg_relation ) ) ) ;
cstr2sv ( SPI_getrelname ( tdata - > tg_relation ) ) ) ;
hv_store_string ( hv , " table_schema " ,
hv_store_string ( hv , " table_schema " ,
newSVstring ( SPI_getnspname ( tdata - > tg_relation ) ) ) ;
cstr2sv ( SPI_getnspname ( tdata - > tg_relation ) ) ) ;
if ( TRIGGER_FIRED_BEFORE ( tdata - > tg_event ) )
if ( TRIGGER_FIRED_BEFORE ( tdata - > tg_event ) )
when = " BEFORE " ;
when = " BEFORE " ;
@ -1092,7 +1118,7 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
when = " INSTEAD OF " ;
when = " INSTEAD OF " ;
else
else
when = " UNKNOWN " ;
when = " UNKNOWN " ;
hv_store_string ( hv , " when " , newSVstring ( when ) ) ;
hv_store_string ( hv , " when " , cstr2sv ( when ) ) ;
if ( TRIGGER_FIRED_FOR_ROW ( tdata - > tg_event ) )
if ( TRIGGER_FIRED_FOR_ROW ( tdata - > tg_event ) )
level = " ROW " ;
level = " ROW " ;
@ -1100,7 +1126,7 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
level = " STATEMENT " ;
level = " STATEMENT " ;
else
else
level = " UNKNOWN " ;
level = " UNKNOWN " ;
hv_store_string ( hv , " level " , newSVstring ( level ) ) ;
hv_store_string ( hv , " level " , cstr2sv ( level ) ) ;
return newRV_noinc ( ( SV * ) hv ) ;
return newRV_noinc ( ( SV * ) hv ) ;
}
}
@ -1113,10 +1139,8 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
{
{
SV * * svp ;
SV * * svp ;
HV * hvNew ;
HV * hvNew ;
HE * he ;
HeapTuple rtup ;
HeapTuple rtup ;
SV * val ;
char * key ;
I32 klen ;
int slotsused ;
int slotsused ;
int * modattrs ;
int * modattrs ;
Datum * modvalues ;
Datum * modvalues ;
@ -1143,13 +1167,15 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
slotsused = 0 ;
slotsused = 0 ;
hv_iterinit ( hvNew ) ;
hv_iterinit ( hvNew ) ;
while ( ( val = hv_iternextsv ( hvNew , & key , & klen ) ) )
while ( ( he = hv_iternext ( hvNew ) ) )
{
{
int attn = SPI_fnumber ( tupdesc , key ) ;
Oid typinput ;
Oid typinput ;
Oid typioparam ;
Oid typioparam ;
int32 atttypmod ;
int32 atttypmod ;
FmgrInfo finfo ;
FmgrInfo finfo ;
SV * val = HeVAL ( he ) ;
char * key = hek2cstr ( he ) ;
int attn = SPI_fnumber ( tupdesc , key ) ;
if ( attn < = 0 | | tupdesc - > attrs [ attn - 1 ] - > attisdropped )
if ( attn < = 0 | | tupdesc - > attrs [ attn - 1 ] - > attisdropped )
ereport ( ERROR ,
ereport ( ERROR ,
@ -1163,11 +1189,13 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
atttypmod = tupdesc - > attrs [ attn - 1 ] - > atttypmod ;
atttypmod = tupdesc - > attrs [ attn - 1 ] - > atttypmod ;
if ( SvOK ( val ) )
if ( SvOK ( val ) )
{
{
char * str = sv2cstr ( val ) ;
modvalues [ slotsused ] = InputFunctionCall ( & finfo ,
modvalues [ slotsused ] = InputFunctionCall ( & finfo ,
sv2 text_mbve rified ( val ) ,
str ,
typioparam ,
typioparam ,
atttypmod ) ;
atttypmod ) ;
modnulls [ slotsused ] = ' ' ;
modnulls [ slotsused ] = ' ' ;
pfree ( str ) ;
}
}
else
else
{
{
@ -1179,6 +1207,8 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup)
}
}
modattrs [ slotsused ] = attn ;
modattrs [ slotsused ] = attn ;
slotsused + + ;
slotsused + + ;
pfree ( key ) ;
}
}
hv_iterinit ( hvNew ) ;
hv_iterinit ( hvNew ) ;
@ -1420,7 +1450,7 @@ plperl_create_sub(plperl_proc_desc *prodesc, char *s, Oid fn_oid)
SAVETMPS ;
SAVETMPS ;
PUSHMARK ( SP ) ;
PUSHMARK ( SP ) ;
EXTEND ( SP , 4 ) ;
EXTEND ( SP , 4 ) ;
PUSHs ( sv_2mortal ( newSVstring ( subname ) ) ) ;
PUSHs ( sv_2mortal ( cstr2sv ( subname ) ) ) ;
PUSHs ( sv_2mortal ( newRV_noinc ( ( SV * ) pragma_hv ) ) ) ;
PUSHs ( sv_2mortal ( newRV_noinc ( ( SV * ) pragma_hv ) ) ) ;
/*
/*
* Use ' false ' for $ prolog in mkfunc , which is kept for compatibility
* Use ' false ' for $ prolog in mkfunc , which is kept for compatibility
@ -1428,7 +1458,7 @@ plperl_create_sub(plperl_proc_desc *prodesc, char *s, Oid fn_oid)
* the function compiler .
* the function compiler .
*/
*/
PUSHs ( & PL_sv_no ) ;
PUSHs ( & PL_sv_no ) ;
PUSHs ( sv_2mortal ( newSVstring ( s ) ) ) ;
PUSHs ( sv_2mortal ( cstr2sv ( s ) ) ) ;
PUTBACK ;
PUTBACK ;
/*
/*
@ -1457,7 +1487,7 @@ plperl_create_sub(plperl_proc_desc *prodesc, char *s, Oid fn_oid)
if ( SvTRUE ( ERRSV ) )
if ( SvTRUE ( ERRSV ) )
ereport ( ERROR ,
ereport ( ERROR ,
( errcode ( ERRCODE_SYNTAX_ERROR ) ,
( errcode ( ERRCODE_SYNTAX_ERROR ) ,
errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ) ) ;
errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ) ) ;
if ( ! subref )
if ( ! subref )
ereport ( ERROR ,
ereport ( ERROR ,
@ -1533,7 +1563,7 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
tmp = OutputFunctionCall ( & ( desc - > arg_out_func [ i ] ) ,
tmp = OutputFunctionCall ( & ( desc - > arg_out_func [ i ] ) ,
fcinfo - > arg [ i ] ) ;
fcinfo - > arg [ i ] ) ;
sv = newSVstring ( tmp ) ;
sv = cstr2sv ( tmp ) ;
PUSHs ( sv_2mortal ( sv ) ) ;
PUSHs ( sv_2mortal ( sv ) ) ;
pfree ( tmp ) ;
pfree ( tmp ) ;
}
}
@ -1561,7 +1591,7 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
LEAVE ;
LEAVE ;
/* XXX need to find a way to assign an errcode here */
/* XXX need to find a way to assign an errcode here */
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ) ) ;
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ) ) ;
}
}
retval = newSVsv ( POPs ) ;
retval = newSVsv ( POPs ) ;
@ -1594,7 +1624,7 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
EXTEND ( sp , tg_trigger - > tgnargs ) ;
EXTEND ( sp , tg_trigger - > tgnargs ) ;
for ( i = 0 ; i < tg_trigger - > tgnargs ; i + + )
for ( i = 0 ; i < tg_trigger - > tgnargs ; i + + )
PUSHs ( sv_2mortal ( newSVstring ( tg_trigger - > tgargs [ i ] ) ) ) ;
PUSHs ( sv_2mortal ( cstr2sv ( tg_trigger - > tgargs [ i ] ) ) ) ;
PUTBACK ;
PUTBACK ;
/* Do NOT use G_KEEPERR here */
/* Do NOT use G_KEEPERR here */
@ -1618,7 +1648,7 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
LEAVE ;
LEAVE ;
/* XXX need to find a way to assign an errcode here */
/* XXX need to find a way to assign an errcode here */
ereport ( ERROR ,
ereport ( ERROR ,
( errmsg ( " %s " , strip_trailing_ws ( SvPV_nolen ( ERRSV ) ) ) ) ) ;
( errmsg ( " %s " , strip_trailing_ws ( sv2cstr ( ERRSV ) ) ) ) ) ;
}
}
retval = newSVsv ( POPs ) ;
retval = newSVsv ( POPs ) ;
@ -1766,6 +1796,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
else
else
{
{
/* Return a perl string converted to a Datum */
/* Return a perl string converted to a Datum */
char * str ;
if ( prodesc - > fn_retisarray & & SvROK ( perlret ) & &
if ( prodesc - > fn_retisarray & & SvROK ( perlret ) & &
SvTYPE ( SvRV ( perlret ) ) = = SVt_PVAV )
SvTYPE ( SvRV ( perlret ) ) = = SVt_PVAV )
@ -1775,9 +1806,11 @@ plperl_func_handler(PG_FUNCTION_ARGS)
perlret = array_ret ;
perlret = array_ret ;
}
}
str = sv2cstr ( perlret ) ;
retval = InputFunctionCall ( & prodesc - > result_in_func ,
retval = InputFunctionCall ( & prodesc - > result_in_func ,
sv2 text_mbve rified ( perlret ) ,
str ,
prodesc - > result_typioparam , - 1 ) ;
prodesc - > result_typioparam , - 1 ) ;
pfree ( str ) ;
}
}
/* Restore the previous error callback */
/* Restore the previous error callback */
@ -1857,7 +1890,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
HeapTuple trv ;
HeapTuple trv ;
char * tmp ;
char * tmp ;
tmp = SvPV_nolen ( perlret ) ;
tmp = sv2cstr ( perlret ) ;
if ( pg_strcasecmp ( tmp , " SKIP " ) = = 0 )
if ( pg_strcasecmp ( tmp , " SKIP " ) = = 0 )
trv = NULL ;
trv = NULL ;
@ -1888,6 +1921,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
trv = NULL ;
trv = NULL ;
}
}
retval = PointerGetDatum ( trv ) ;
retval = PointerGetDatum ( trv ) ;
pfree ( tmp ) ;
}
}
/* Restore the previous error callback */
/* Restore the previous error callback */
@ -2231,7 +2265,7 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
outputstr = OidOutputFunctionCall ( typoutput , attr ) ;
outputstr = OidOutputFunctionCall ( typoutput , attr ) ;
hv_store_string ( hv , attname , newSVstring ( outputstr ) ) ;
hv_store_string ( hv , attname , cstr2sv ( outputstr ) ) ;
pfree ( outputstr ) ;
pfree ( outputstr ) ;
}
}
@ -2336,7 +2370,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, int processed,
result = newHV ( ) ;
result = newHV ( ) ;
hv_store_string ( result , " status " ,
hv_store_string ( result , " status " ,
newSVstring ( SPI_result_code_string ( status ) ) ) ;
cstr2sv ( SPI_result_code_string ( status ) ) ) ;
hv_store_string ( result , " processed " ,
hv_store_string ( result , " processed " ,
newSViv ( processed ) ) ;
newSViv ( processed ) ) ;
@ -2466,16 +2500,20 @@ plperl_return_next(SV *sv)
if ( SvOK ( sv ) )
if ( SvOK ( sv ) )
{
{
char * str ;
if ( prodesc - > fn_retisarray & & SvROK ( sv ) & &
if ( prodesc - > fn_retisarray & & SvROK ( sv ) & &
SvTYPE ( SvRV ( sv ) ) = = SVt_PVAV )
SvTYPE ( SvRV ( sv ) ) = = SVt_PVAV )
{
{
sv = plperl_convert_to_pg_array ( sv ) ;
sv = plperl_convert_to_pg_array ( sv ) ;
}
}
str = sv2cstr ( sv ) ;
ret = InputFunctionCall ( & prodesc - > result_in_func ,
ret = InputFunctionCall ( & prodesc - > result_in_func ,
sv2 text_mbve rified ( sv ) ,
str ,
prodesc - > result_typioparam , - 1 ) ;
prodesc - > result_typioparam , - 1 ) ;
isNull = false ;
isNull = false ;
pfree ( str ) ;
}
}
else
else
{
{
@ -2531,7 +2569,7 @@ plperl_spi_query(char *query)
if ( portal = = NULL )
if ( portal = = NULL )
elog ( ERROR , " SPI_cursor_open() failed:%s " ,
elog ( ERROR , " SPI_cursor_open() failed:%s " ,
SPI_result_code_string ( SPI_result ) ) ;
SPI_result_code_string ( SPI_result ) ) ;
cursor = newSVstring ( portal - > name ) ;
cursor = cstr2sv ( portal - > name ) ;
/* Commit the inner transaction, return to outer xact context */
/* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction ( ) ;
ReleaseCurrentSubTransaction ( ) ;
@ -2716,8 +2754,11 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
typInput ,
typInput ,
typIOParam ;
typIOParam ;
int32 typmod ;
int32 typmod ;
char * typstr ;
parseTypeString ( SvPV_nolen ( argv [ i ] ) , & typId , & typmod ) ;
typstr = sv2cstr ( argv [ i ] ) ;
parseTypeString ( typstr , & typId , & typmod ) ;
pfree ( typstr ) ;
getTypeInputInfo ( typId , & typInput , & typIOParam ) ;
getTypeInputInfo ( typId , & typInput , & typIOParam ) ;
@ -2804,7 +2845,7 @@ plperl_spi_prepare(char *query, int argc, SV **argv)
HASH_ENTER , & found ) ;
HASH_ENTER , & found ) ;
hash_entry - > query_data = qdesc ;
hash_entry - > query_data = qdesc ;
return newSVstring ( qdesc - > qname ) ;
return cstr2sv ( qdesc - > qname ) ;
}
}
HV *
HV *
@ -2881,11 +2922,13 @@ plperl_spi_exec_prepared(char *query, HV *attr, int argc, SV **argv)
{
{
if ( SvOK ( argv [ i ] ) )
if ( SvOK ( argv [ i ] ) )
{
{
char * str = sv2cstr ( argv [ i ] ) ;
argvalues [ i ] = InputFunctionCall ( & qdesc - > arginfuncs [ i ] ,
argvalues [ i ] = InputFunctionCall ( & qdesc - > arginfuncs [ i ] ,
sv2 text_mbve rified ( argv [ i ] ) ,
str ,
qdesc - > argtypioparams [ i ] ,
qdesc - > argtypioparams [ i ] ,
- 1 ) ;
- 1 ) ;
nulls [ i ] = ' ' ;
nulls [ i ] = ' ' ;
pfree ( str ) ;
}
}
else
else
{
{
@ -3014,11 +3057,13 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
{
{
if ( SvOK ( argv [ i ] ) )
if ( SvOK ( argv [ i ] ) )
{
{
char * str = sv2cstr ( argv [ i ] ) ;
argvalues [ i ] = InputFunctionCall ( & qdesc - > arginfuncs [ i ] ,
argvalues [ i ] = InputFunctionCall ( & qdesc - > arginfuncs [ i ] ,
sv2 text_mbve rified ( argv [ i ] ) ,
str ,
qdesc - > argtypioparams [ i ] ,
qdesc - > argtypioparams [ i ] ,
- 1 ) ;
- 1 ) ;
nulls [ i ] = ' ' ;
nulls [ i ] = ' ' ;
pfree ( str ) ;
}
}
else
else
{
{
@ -3044,7 +3089,7 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
elog ( ERROR , " SPI_cursor_open() failed:%s " ,
elog ( ERROR , " SPI_cursor_open() failed:%s " ,
SPI_result_code_string ( SPI_result ) ) ;
SPI_result_code_string ( SPI_result ) ) ;
cursor = newSVstring ( portal - > name ) ;
cursor = cstr2sv ( portal - > name ) ;
/* Commit the inner transaction, return to outer xact context */
/* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction ( ) ;
ReleaseCurrentSubTransaction ( ) ;
@ -3124,23 +3169,6 @@ plperl_spi_freeplan(char *query)
SPI_freeplan ( plan ) ;
SPI_freeplan ( plan ) ;
}
}
/*
* Create a new SV from a string assumed to be in the current database ' s
* encoding .
*/
static SV *
newSVstring ( const char * str )
{
SV * sv ;
sv = newSVpv ( str , 0 ) ;
# if PERL_BCDVERSION >= 0x5006000L
if ( GetDatabaseEncoding ( ) = = PG_UTF8 )
SvUTF8_on ( sv ) ;
# endif
return sv ;
}
/*
/*
* Store an SV into a hash table under a key that is a string assumed to be
* Store an SV into a hash table under a key that is a string assumed to be
* in the current database ' s encoding .
* in the current database ' s encoding .
@ -3148,7 +3176,11 @@ newSVstring(const char *str)
static SV * *
static SV * *
hv_store_string ( HV * hv , const char * key , SV * val )
hv_store_string ( HV * hv , const char * key , SV * val )
{
{
int32 klen = strlen ( key ) ;
int32 hlen ;
char * hkey ;
SV * * ret ;
hkey = ( char * ) pg_do_encoding_conversion ( ( unsigned char * ) key , strlen ( key ) , GetDatabaseEncoding ( ) , PG_UTF8 ) ;
/*
/*
* This seems nowhere documented , but under Perl 5.8 .0 and up , hv_store ( )
* This seems nowhere documented , but under Perl 5.8 .0 and up , hv_store ( )
@ -3156,11 +3188,13 @@ hv_store_string(HV *hv, const char *key, SV *val)
* does not appear that hashes track UTF - 8 - ness of keys at all in Perl
* does not appear that hashes track UTF - 8 - ness of keys at all in Perl
* 5.6 .
* 5.6 .
*/
*/
# if PERL_BCDVERSION >= 0x5008000L
hlen = - strlen ( hkey ) ;
if ( GetDatabaseEncoding ( ) = = PG_UTF8 )
ret = hv_store ( hv , hkey , hlen , val , 0 ) ;
klen = - klen ;
# endif
if ( hkey ! = key )
return hv_store ( hv , key , klen , val , 0 ) ;
pfree ( hkey ) ;
return ret ;
}
}
/*
/*
@ -3170,14 +3204,20 @@ hv_store_string(HV *hv, const char *key, SV *val)
static SV * *
static SV * *
hv_fetch_string ( HV * hv , const char * key )
hv_fetch_string ( HV * hv , const char * key )
{
{
int32 klen = strlen ( key ) ;
int32 hlen ;
char * hkey ;
SV * * ret ;
hkey = ( char * ) pg_do_encoding_conversion ( ( unsigned char * ) key , strlen ( key ) , GetDatabaseEncoding ( ) , PG_UTF8 ) ;
/* See notes in hv_store_string */
/* See notes in hv_store_string */
# if PERL_BCDVERSION >= 0x5008000L
hlen = - strlen ( hkey ) ;
if ( GetDatabaseEncoding ( ) = = PG_UTF8 )
ret = hv_fetch ( hv , hkey , hlen , 0 ) ;
klen = - klen ;
# endif
if ( hkey ! = key )
return hv_fetch ( hv , key , klen , 0 ) ;
pfree ( hkey ) ;
return ret ;
}
}
/*
/*