pltcl, plperl, and plpython all suffer the same bug previously fixed
in plpgsql: they fail for datatypes that have old-style I/O functions due to caching FmgrInfo structs with wrong fn_mcxt lifetime. Although the plpython fix seems straightforward, I can't check it here since I don't have Python installed --- would someone check it?
This commit is contained in:
parent
7c0c9b3cce
commit
7748e9e7e5
|
@ -33,7 +33,7 @@
|
||||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
@ -163,6 +163,27 @@ static void plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
|
||||||
#endif
|
#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
|
* plperl_init_all() - Initialize all
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
@ -562,7 +583,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
|
||||||
elog(ERROR, "plperl: return types of tuples not supported yet");
|
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_elem = (Oid) (typeStruct->typelem);
|
||||||
prodesc->result_in_len = typeStruct->typlen;
|
prodesc->result_in_len = typeStruct->typlen;
|
||||||
|
|
||||||
|
@ -595,7 +616,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
|
||||||
else
|
else
|
||||||
prodesc->arg_is_rel[i] = 0;
|
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_elem[i] = (Oid) (typeStruct->typelem);
|
||||||
prodesc->arg_out_len[i] = typeStruct->typlen;
|
prodesc->arg_out_len[i] = typeStruct->typlen;
|
||||||
ReleaseSysCache(typeTup);
|
ReleaseSysCache(typeTup);
|
||||||
|
@ -1560,7 +1581,7 @@ plperl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
||||||
if (!HeapTupleIsValid(typeTup))
|
if (!HeapTupleIsValid(typeTup))
|
||||||
elog(ERROR, "plperl: Cache lookup of type %s failed", args[i]);
|
elog(ERROR, "plperl: Cache lookup of type %s failed", args[i]);
|
||||||
qdesc->argtypes[i] = typeTup->t_data->t_oid;
|
qdesc->argtypes[i] = typeTup->t_data->t_oid;
|
||||||
fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
|
perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
|
||||||
&(qdesc->arginfuncs[i]));
|
&(qdesc->arginfuncs[i]));
|
||||||
qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
|
qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
|
||||||
qdesc->argvalues[i] = (Datum) NULL;
|
qdesc->argvalues[i] = (Datum) NULL;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
/* $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
|
* plpython.c - python as a procedural language for PostgreSQL
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
|
||||||
*
|
|
||||||
* This software is copyright by Andrew Bosma
|
* This software is copyright by Andrew Bosma
|
||||||
* but is really shameless cribbed from pltcl.c by Jan Weick, and
|
* but is really shameless cribbed from pltcl.c by Jan Weick, and
|
||||||
* plperl.c by Mark Hollomon.
|
* plperl.c by Mark Hollomon.
|
||||||
|
@ -32,7 +28,11 @@
|
||||||
* AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
* AND THE AUTHOR AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
|
||||||
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
* 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"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
@ -296,8 +296,32 @@ volatile int func_enter_calls = 0;
|
||||||
volatile int func_leave_calls = 0;
|
volatile int func_leave_calls = 0;
|
||||||
#endif
|
#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
|
Datum
|
||||||
plpython_call_handler(PG_FUNCTION_ARGS)
|
plpython_call_handler(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
|
@ -1282,7 +1306,7 @@ PLy_output_datum_func2(PLyObToDatum *arg, Form_pg_type typeStruct)
|
||||||
{
|
{
|
||||||
enter();
|
enter();
|
||||||
|
|
||||||
fmgr_info(typeStruct->typinput, &arg->typfunc);
|
perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
|
||||||
arg->typelem = (Oid) typeStruct->typelem;
|
arg->typelem = (Oid) typeStruct->typelem;
|
||||||
arg->typlen = typeStruct->typlen;
|
arg->typlen = typeStruct->typlen;
|
||||||
}
|
}
|
||||||
|
@ -1304,7 +1328,7 @@ PLy_input_datum_func2(PLyDatumToOb *arg, Form_pg_type typeStruct)
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
arg->typoutput = typeStruct->typoutput;
|
arg->typoutput = typeStruct->typoutput;
|
||||||
fmgr_info(typeStruct->typoutput, &arg->typfunc);
|
perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
|
||||||
arg->typlen = typeStruct->typlen;
|
arg->typlen = typeStruct->typlen;
|
||||||
arg->typelem = typeStruct->typelem;
|
arg->typelem = typeStruct->typelem;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
* ENHANCEMENTS, OR MODIFICATIONS.
|
* ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,
|
static void pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc,
|
||||||
Tcl_DString *retval);
|
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
|
* 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");
|
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;
|
prodesc->result_in_elem = typeStruct->typelem;
|
||||||
|
|
||||||
ReleaseSysCache(typeTup);
|
ReleaseSysCache(typeTup);
|
||||||
|
@ -549,7 +570,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
|
||||||
else
|
else
|
||||||
prodesc->arg_is_rel[i] = 0;
|
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_elem[i] = (Oid) (typeStruct->typelem);
|
||||||
prodesc->arg_out_len[i] = typeStruct->typlen;
|
prodesc->arg_out_len[i] = typeStruct->typlen;
|
||||||
|
|
||||||
|
@ -1760,7 +1781,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
|
||||||
if (!HeapTupleIsValid(typeTup))
|
if (!HeapTupleIsValid(typeTup))
|
||||||
elog(ERROR, "pltcl: Cache lookup of type %s failed", args[i]);
|
elog(ERROR, "pltcl: Cache lookup of type %s failed", args[i]);
|
||||||
qdesc->argtypes[i] = typeTup->t_data->t_oid;
|
qdesc->argtypes[i] = typeTup->t_data->t_oid;
|
||||||
fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
|
perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput,
|
||||||
&(qdesc->arginfuncs[i]));
|
&(qdesc->arginfuncs[i]));
|
||||||
qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
|
qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
|
||||||
qdesc->argvalues[i] = (Datum) NULL;
|
qdesc->argvalues[i] = (Datum) NULL;
|
||||||
|
|
Loading…
Reference in New Issue