* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.19 2001/03/22 04:01:40 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.20 2001/06/01 18:17:44 tgl Exp $
*
**********************************************************************/
#endif
+/*
+ * This routine is a crock, and so is everyplace that calls it. The problem
+ * is that the cached form of plperl 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);
+}
+
/**********************************************************************
* plperl_init_all() - Initialize all
**********************************************************************/
elog(ERROR, "plperl: 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 = (Oid) (typeStruct->typelem);
prodesc->result_in_len = typeStruct->typlen;
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;
ReleaseSysCache(typeTup);
if (!HeapTupleIsValid(typeTup))
elog(ERROR, "plperl: 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);
-/* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.3 2001/05/25 15:48:33 momjian Exp $ */
-
-/*
+/**********************************************************************
* plpython.c - python as a procedural language for PostgreSQL
*
- * IDENTIFICATION
- *
* This software is copyright by Andrew Bosma
* but is really shameless cribbed from pltcl.c by Jan Weick, and
* plperl.c by Mark Hollomon.
* AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- **********************************************************************/
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.4 2001/06/01 18:17:44 tgl Exp $
+ *
+ *********************************************************************
+ */
#include "postgres.h"
volatile int func_leave_calls = 0;
#endif
-/* the function definitions
+/*
+ * the function definitions
*/
+
+/*
+ * This routine is a crock, and so is everyplace that calls it. The problem
+ * is that the cached form of plpython 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);
+}
+
+
Datum
plpython_call_handler(PG_FUNCTION_ARGS)
{
{
enter();
- fmgr_info(typeStruct->typinput, &arg->typfunc);
+ perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
arg->typelem = (Oid) typeStruct->typelem;
arg->typlen = typeStruct->typlen;
}
char *type;
arg->typoutput = typeStruct->typoutput;
- fmgr_info(typeStruct->typoutput, &arg->typfunc);
+ perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
arg->typlen = typeStruct->typlen;
arg->typelem = typeStruct->typelem;
* 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 $
*
**********************************************************************/
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
**********************************************************************/
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);
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;
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);