Re: plperl features - Mailing list pgsql-patches
From | Sergej Sergeev |
---|---|
Subject | Re: plperl features |
Date | |
Msg-id | 415C3429.7040904@commandprompt.com Whole thread Raw |
In response to | Re: plperl features (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: plperl features
Re: plperl features Re: plperl features |
List | pgsql-patches |
>Sergej Sergeev <sergej@commandprompt.com> writes: > > >>>What happens if you feed other pseudotypes, like cstring or >>>language_handler? Shouldn't that be disallowed or something? >>> >>> > > > >>Other pseudo-types are disallowed (no-change) >> >> > >No, because you diked out the check at lines 1452ff, rather than >upgrading it to something correct. > >I find the "fn_retispseudo" and "arg_is_p" flags pretty bogus anyway >since they fail to indicate *which* pseudotype it is. You might as >well just test for the specific type OID. > > regards, tom lane > > New patch. I have added the check pseudo-type argumetns. Specific type is substituted in runtime, during function call. -- g.gRay: PL/perl, PL/PHP ;) Index: plperl.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/pl/plperl/plperl.c,v retrieving revision 1.51 diff -c -w -r1.51 plperl.c *** plperl.c 13 Sep 2004 20:08:59 -0000 1.51 --- plperl.c 30 Sep 2004 16:07:25 -0000 *************** *** 82,87 **** --- 82,89 ---- bool lanpltrusted; bool fn_retistuple; /* true, if function returns tuple */ bool fn_retisset; /* true, if function returns set */ + bool fn_retisarray; /* true, if function returns "true" array*/ + bool fn_retispseudo; /* true, if function returns pseudo type*/ Oid ret_oid; /* Oid of returning type */ FmgrInfo result_in_func; Oid result_typioparam; *************** *** 89,94 **** --- 91,97 ---- FmgrInfo arg_out_func[FUNC_MAX_ARGS]; Oid arg_typioparam[FUNC_MAX_ARGS]; bool arg_is_rowtype[FUNC_MAX_ARGS]; + bool arg_is_p[FUNC_MAX_ARGS]; SV *reference; } plperl_proc_desc; *************** *** 277,282 **** --- 280,319 ---- } /********************************************************************** + * convert perl array to the string representation + **********************************************************************/ + static SV* + plperl_convert_to_pg_array(SV *src) + { + SV* rv; + SV** val;; + AV* internal; + int len, + i; + + internal=(AV*)SvRV(src); + len = av_len(internal)+1; + + rv = newSVpv("{ ",0); + for(i=0; i<len; i++) + { + val = av_fetch(internal, i, FALSE); + if (SvTYPE(*val)==SVt_RV) + if (SvTYPE(SvRV(*val))==SVt_PVAV) + sv_catpvf(rv, "%s", SvPV(plperl_convert_to_pg_array(*val),PL_na)); + else + elog(ERROR, "plperl: check array structure"); + else + sv_catpvf(rv, "%s", SvPV(*val,PL_na)); + if (i != len-1) sv_catpvf(rv, ","); + } + + sv_catpvf(rv, "}"); + + return rv; + } + + /********************************************************************** * turn a tuple into a hash expression and add it to a list **********************************************************************/ static void *************** *** 752,757 **** --- 789,807 ---- XPUSHs(sv_2mortal(newSVpv("undef", 0))); for (i = 0; i < desc->nargs; i++) { + if (desc->arg_is_p[i]){ + HeapTuple typeTup; + Form_pg_type typeStruct; + + typeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(get_fn_expr_argtype(fcinfo->flinfo, i)), + 0, 0, 0); + typeStruct = (Form_pg_type) GETSTRUCT(typeTup); + perm_fmgr_info(typeStruct->typoutput, &(desc->arg_out_func[i])); + desc->arg_typioparam[i] = getTypeIOParam(typeTup); + ReleaseSysCache(typeTup); + } + if (desc->arg_is_rowtype[i]) { if (fcinfo->argnull[i]) *************** *** 909,914 **** --- 959,977 ---- perlret = srf_perlret; } + if (prodesc->fn_retispseudo){ + HeapTuple retTypeTup; + Form_pg_type retTypeStruct; + + retTypeTup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(get_fn_expr_rettype(fcinfo->flinfo)), + 0, 0, 0); + retTypeStruct = (Form_pg_type) GETSTRUCT(retTypeTup); + perm_fmgr_info(retTypeStruct->typinput, &(prodesc->result_in_func)); + prodesc->result_typioparam = getTypeIOParam(retTypeTup); + ReleaseSysCache(retTypeTup); + } + if (prodesc->fn_retisset && SRF_IS_FIRSTCALL()) { if (prodesc->fn_retistuple) *************** *** 1149,1161 **** } else /* perl string to Datum */ retval = FunctionCall3(&prodesc->result_in_func, PointerGetDatum(SvPV(perlret, PL_na)), ObjectIdGetDatum(prodesc->result_typioparam), Int32GetDatum(-1)); ! } SvREFCNT_dec(perlret); --- 1212,1234 ---- } else + { + SV* ret; + + if (prodesc->fn_retisarray) + { + if(SvTYPE(SvRV(perlret))!=SVt_PVAV) elog(ERROR, "plperl: this function must return reference to array"); + ret = plperl_convert_to_pg_array(perlret); + SvREFCNT_dec(perlret); + perlret = ret; + } /* perl string to Datum */ retval = FunctionCall3(&prodesc->result_in_func, PointerGetDatum(SvPV(perlret, PL_na)), ObjectIdGetDatum(prodesc->result_typioparam), Int32GetDatum(-1)); ! } } SvREFCNT_dec(perlret); *************** *** 1384,1395 **** } typeStruct = (Form_pg_type) GETSTRUCT(typeTup); ! /* Disallow pseudotype result, except VOID or RECORD */ if (typeStruct->typtype == 'p') { if (procStruct->prorettype == VOIDOID || ! procStruct->prorettype == RECORDOID) ! /* okay */ ; else if (procStruct->prorettype == TRIGGEROID) { free(prodesc->proname); --- 1457,1471 ---- } typeStruct = (Form_pg_type) GETSTRUCT(typeTup); ! /* Disallow pseudotype result, except VOID, RECORD, ANYELEMENT or ANYARRAY */ if (typeStruct->typtype == 'p') { if (procStruct->prorettype == VOIDOID || ! procStruct->prorettype == RECORDOID || ! procStruct->prorettype == ANYARRAYOID || ! procStruct->prorettype == ANYELEMENTOID) ! /* okay */ ! prodesc->fn_retispseudo=true; else if (procStruct->prorettype == TRIGGEROID) { free(prodesc->proname); *************** *** 1421,1426 **** --- 1497,1509 ---- procStruct->prorettype; } + if (procStruct->prorettype != ANYARRAYOID) + if (typeStruct->typlen == -1 && typeStruct->typelem) /*true, if function returns "true" array*/ + prodesc->fn_retisarray = true; + else + prodesc->fn_retisarray = false; + else prodesc->fn_retisarray = true; + perm_fmgr_info(typeStruct->typinput, &(prodesc->result_in_func)); prodesc->result_typioparam = getTypeIOParam(typeTup); *************** *** 1448,1455 **** } typeStruct = (Form_pg_type) GETSTRUCT(typeTup); ! /* Disallow pseudotype argument */ if (typeStruct->typtype == 'p') { free(prodesc->proname); free(prodesc); --- 1531,1543 ---- } typeStruct = (Form_pg_type) GETSTRUCT(typeTup); ! /* Disallow pseudotype argument, except ANYELEMENT or ANYARRAY */ if (typeStruct->typtype == 'p') + if (procStruct->proargtypes[i] == ANYARRAYOID || + procStruct->proargtypes[i] == ANYELEMENTOID) + /* okay */ + prodesc->arg_is_p[i] = true; + else { free(prodesc->proname); free(prodesc); *************** *** 1458,1463 **** --- 1546,1553 ---- errmsg("plperl functions cannot take type %s", format_type_be(procStruct->proargtypes[i])))); } + else + prodesc->arg_is_p[i] = false; if (typeStruct->typtype == 'c') prodesc->arg_is_rowtype[i] = true;
pgsql-patches by date: