aboutsummaryrefslogtreecommitdiff
path: root/src/pl/plperl/plperl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl/plperl/plperl.c')
-rw-r--r--src/pl/plperl/plperl.c47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index e3dda5d63bc..840df2ee0b8 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -20,6 +20,7 @@
#include "access/xact.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
+#include "catalog/pg_proc_fn.h"
#include "catalog/pg_type.h"
#include "commands/event_trigger.h"
#include "commands/trigger.h"
@@ -110,6 +111,8 @@ typedef struct plperl_proc_desc
SV *reference; /* CODE reference for Perl sub */
plperl_interp_desc *interp; /* interpreter it's created in */
bool fn_readonly; /* is function readonly (not volatile)? */
+ Oid lang_oid;
+ List *trftypes;
bool lanpltrusted; /* is it plperl, rather than plperlu? */
bool fn_retistuple; /* true, if function returns tuple */
bool fn_retisset; /* true, if function returns set */
@@ -210,6 +213,7 @@ typedef struct plperl_array_info
bool *nulls;
int *nelems;
FmgrInfo proc;
+ FmgrInfo transform_proc;
} plperl_array_info;
/**********************************************************************
@@ -1272,6 +1276,7 @@ plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
bool *isnull)
{
FmgrInfo tmp;
+ Oid funcid;
/* we might recurse */
check_stack_depth();
@@ -1295,6 +1300,8 @@ plperl_sv_to_datum(SV *sv, Oid typid, int32 typmod,
/* must call typinput in case it wants to reject NULL */
return InputFunctionCall(finfo, NULL, typioparam, typmod);
}
+ else if ((funcid = get_transform_tosql(typid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
+ return OidFunctionCall1(funcid, PointerGetDatum(sv));
else if (SvROK(sv))
{
/* handle references */
@@ -1407,6 +1414,7 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
typdelim;
Oid typioparam;
Oid typoutputfunc;
+ Oid transform_funcid;
int i,
nitems,
*dims;
@@ -1414,14 +1422,17 @@ plperl_ref_from_pg_array(Datum arg, Oid typid)
SV *av;
HV *hv;
- info = palloc(sizeof(plperl_array_info));
+ info = palloc0(sizeof(plperl_array_info));
/* get element type information, including output conversion function */
get_type_io_data(elementtype, IOFunc_output,
&typlen, &typbyval, &typalign,
&typdelim, &typioparam, &typoutputfunc);
- perm_fmgr_info(typoutputfunc, &info->proc);
+ if ((transform_funcid = get_transform_fromsql(elementtype, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
+ perm_fmgr_info(transform_funcid, &info->transform_proc);
+ else
+ perm_fmgr_info(typoutputfunc, &info->proc);
info->elem_is_rowtype = type_is_rowtype(elementtype);
@@ -1502,8 +1513,10 @@ make_array_ref(plperl_array_info *info, int first, int last)
{
Datum itemvalue = info->elements[i];
- /* Handle composite type elements */
- if (info->elem_is_rowtype)
+ if (info->transform_proc.fn_oid)
+ av_push(result, (SV *) DatumGetPointer(FunctionCall1(&info->transform_proc, itemvalue)));
+ else if (info->elem_is_rowtype)
+ /* Handle composite type elements */
av_push(result, plperl_hash_from_datum(itemvalue));
else
{
@@ -1812,6 +1825,8 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
desc.proname = "inline_code_block";
desc.fn_readonly = false;
+ desc.lang_oid = codeblock->langOid;
+ desc.trftypes = NIL;
desc.lanpltrusted = codeblock->langIsTrusted;
desc.fn_retistuple = false;
@@ -2076,6 +2091,8 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
SV *retval;
int i;
int count;
+ Oid *argtypes = NULL;
+ int nargs = 0;
ENTER;
SAVETMPS;
@@ -2083,6 +2100,9 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
PUSHMARK(SP);
EXTEND(sp, desc->nargs);
+ if (fcinfo->flinfo->fn_oid)
+ get_func_signature(fcinfo->flinfo->fn_oid, &argtypes, &nargs);
+
for (i = 0; i < desc->nargs; i++)
{
if (fcinfo->argnull[i])
@@ -2096,9 +2116,12 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
else
{
SV *sv;
+ Oid funcid;
if (OidIsValid(desc->arg_arraytype[i]))
sv = plperl_ref_from_pg_array(fcinfo->arg[i], desc->arg_arraytype[i]);
+ else if ((funcid = get_transform_fromsql(argtypes[i], current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
+ sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->arg[i]));
else
{
char *tmp;
@@ -2569,6 +2592,7 @@ free_plperl_function(plperl_proc_desc *prodesc)
/* (FmgrInfo subsidiary info will get leaked ...) */
if (prodesc->proname)
free(prodesc->proname);
+ list_free(prodesc->trftypes);
free(prodesc);
}
@@ -2631,6 +2655,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
HeapTuple typeTup;
Form_pg_language langStruct;
Form_pg_type typeStruct;
+ Datum protrftypes_datum;
Datum prosrcdatum;
bool isnull;
char *proc_source;
@@ -2661,6 +2686,16 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
prodesc->fn_readonly =
(procStruct->provolatile != PROVOLATILE_VOLATILE);
+ {
+ MemoryContext oldcxt;
+
+ protrftypes_datum = SysCacheGetAttr(PROCOID, procTup,
+ Anum_pg_proc_protrftypes, &isnull);
+ oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+ prodesc->trftypes = isnull ? NIL : oid_array_to_list(protrftypes_datum);
+ MemoryContextSwitchTo(oldcxt);
+ }
+
/************************************************************
* Lookup the pg_language tuple by Oid
************************************************************/
@@ -2673,6 +2708,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
procStruct->prolang);
}
langStruct = (Form_pg_language) GETSTRUCT(langTup);
+ prodesc->lang_oid = HeapTupleGetOid(langTup);
prodesc->lanpltrusted = langStruct->lanpltrusted;
ReleaseSysCache(langTup);
@@ -2906,9 +2942,12 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc)
else
{
SV *sv;
+ Oid funcid;
if (OidIsValid(get_base_element_type(tupdesc->attrs[i]->atttypid)))
sv = plperl_ref_from_pg_array(attr, tupdesc->attrs[i]->atttypid);
+ else if ((funcid = get_transform_fromsql(tupdesc->attrs[i]->atttypid, current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
+ sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, attr));
else
{
char *outputstr;