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])

Reply via email to