I assume this is an 8.0 fix.

Your patch has been added to the PostgreSQL unapplied patches list at:

        http://momjian.postgresql.org/cgi-bin/pgpatches

It will be applied as soon as one of the PostgreSQL committers reviews
and approves it.

---------------------------------------------------------------------------


Sergej Sergeev wrote:
> 
> >Sergej Sergeev <[EMAIL PROTECTED]> 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;

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  [EMAIL PROTECTED]               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])

Reply via email to