@ -31,7 +31,7 @@
* ENHANCEMENTS , OR MODIFICATIONS .
*
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / pl / tcl / pltcl . c , v 1.35 2001 / 05 / 11 23 : 38 : 06 petere Exp $
* $ Header : / cvsroot / pgsql / src / pl / tcl / pltcl . c , v 1.36 2001 / 06 / 01 18 : 17 : 44 tgl Exp $
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -145,6 +145,27 @@ static void pltcl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
static void pltcl_build_tuple_argument ( HeapTuple tuple , TupleDesc tupdesc ,
Tcl_DString * retval ) ;
/*
* This routine is a crock , and so is everyplace that calls it . The problem
* is that the cached form of pltcl functions / queries is allocated permanently
* ( mostly via malloc ( ) ) and never released until backend exit . Subsidiary
* data structures such as fmgr info records therefore must live forever
* as well . A better implementation would store all this stuff in a per -
* function memory context that could be reclaimed at need . In the meantime ,
* fmgr_info must be called in TopMemoryContext so that whatever it might
* allocate , and whatever the eventual function might allocate using fn_mcxt ,
* will live forever too .
*/
static void
perm_fmgr_info ( Oid functionId , FmgrInfo * finfo )
{
MemoryContext oldcontext ;
oldcontext = MemoryContextSwitchTo ( TopMemoryContext ) ;
fmgr_info ( functionId , finfo ) ;
MemoryContextSwitchTo ( oldcontext ) ;
}
/**********************************************************************
* pltcl_init_all ( ) - Initialize all
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -508,7 +529,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
elog ( ERROR , " pltcl: return types of tuples not supported yet " ) ;
}
fmgr_info ( typeStruct - > typinput , & ( prodesc - > result_in_func ) ) ;
perm_ fmgr_info( typeStruct - > typinput , & ( prodesc - > result_in_func ) ) ;
prodesc - > result_in_elem = typeStruct - > typelem ;
ReleaseSysCache ( typeTup ) ;
@ -549,7 +570,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
else
prodesc - > arg_is_rel [ i ] = 0 ;
fmgr_info ( typeStruct - > typoutput , & ( prodesc - > arg_out_func [ i ] ) ) ;
perm_ fmgr_info( typeStruct - > typoutput , & ( prodesc - > arg_out_func [ i ] ) ) ;
prodesc - > arg_out_elem [ i ] = ( Oid ) ( typeStruct - > typelem ) ;
prodesc - > arg_out_len [ i ] = typeStruct - > typlen ;
@ -1760,8 +1781,8 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
if ( ! HeapTupleIsValid ( typeTup ) )
elog ( ERROR , " pltcl: Cache lookup of type %s failed " , args [ i ] ) ;
qdesc - > argtypes [ i ] = typeTup - > t_data - > t_oid ;
fmgr_info ( ( ( Form_pg_type ) GETSTRUCT ( typeTup ) ) - > typinput ,
& ( qdesc - > arginfuncs [ i ] ) ) ;
perm_ fmgr_info( ( ( Form_pg_type ) GETSTRUCT ( typeTup ) ) - > typinput ,
& ( qdesc - > arginfuncs [ i ] ) ) ;
qdesc - > argtypelems [ i ] = ( ( Form_pg_type ) GETSTRUCT ( typeTup ) ) - > typelem ;
qdesc - > argvalues [ i ] = ( Datum ) NULL ;
qdesc - > arglen [ i ] = ( int ) ( ( ( Form_pg_type ) GETSTRUCT ( typeTup ) ) - > typlen ) ;