mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-28 01:21:49 +02:00
Rebuild cached function definition after CREATE OR REPLACE FUNCTION.
Fix typlen-vs-typmod errors inherited from pltcl.
This commit is contained in:
parent
b2e859a4fe
commit
970a2d1c91
@ -29,7 +29,7 @@
|
|||||||
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.8 2001/10/06 23:21:45 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.9 2001/10/22 19:32:27 tgl Exp $
|
||||||
*
|
*
|
||||||
*********************************************************************
|
*********************************************************************
|
||||||
*/
|
*/
|
||||||
@ -73,9 +73,8 @@ typedef PyObject *(*PLyDatumToObFunc) (const char *);
|
|||||||
typedef struct PLyDatumToOb {
|
typedef struct PLyDatumToOb {
|
||||||
PLyDatumToObFunc func;
|
PLyDatumToObFunc func;
|
||||||
FmgrInfo typfunc;
|
FmgrInfo typfunc;
|
||||||
Oid typoutput;
|
|
||||||
Oid typelem;
|
Oid typelem;
|
||||||
int2 typlen;
|
bool typbyval;
|
||||||
} PLyDatumToOb;
|
} PLyDatumToOb;
|
||||||
|
|
||||||
typedef struct PLyTupleToOb {
|
typedef struct PLyTupleToOb {
|
||||||
@ -94,7 +93,7 @@ typedef union PLyTypeInput {
|
|||||||
typedef struct PLyObToDatum {
|
typedef struct PLyObToDatum {
|
||||||
FmgrInfo typfunc;
|
FmgrInfo typfunc;
|
||||||
Oid typelem;
|
Oid typelem;
|
||||||
int2 typlen;
|
bool typbyval;
|
||||||
} PLyObToDatum;
|
} PLyObToDatum;
|
||||||
|
|
||||||
typedef struct PLyObToTuple {
|
typedef struct PLyObToTuple {
|
||||||
@ -121,6 +120,8 @@ typedef struct PLyTypeInfo {
|
|||||||
*/
|
*/
|
||||||
typedef struct PLyProcedure {
|
typedef struct PLyProcedure {
|
||||||
char *proname;
|
char *proname;
|
||||||
|
TransactionId fn_xmin;
|
||||||
|
CommandId fn_cmin;
|
||||||
PLyTypeInfo result; /* also used to store info for trigger tuple type */
|
PLyTypeInfo result; /* also used to store info for trigger tuple type */
|
||||||
PLyTypeInfo args[FUNC_MAX_ARGS];
|
PLyTypeInfo args[FUNC_MAX_ARGS];
|
||||||
int nargs;
|
int nargs;
|
||||||
@ -192,11 +193,11 @@ static void PLy_free(void *);
|
|||||||
|
|
||||||
/* sub handlers for functions and triggers
|
/* sub handlers for functions and triggers
|
||||||
*/
|
*/
|
||||||
static Datum PLy_function_handler(PG_FUNCTION_ARGS, PLyProcedure *);
|
static Datum PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *);
|
||||||
static HeapTuple PLy_trigger_handler(PG_FUNCTION_ARGS, PLyProcedure *);
|
static HeapTuple PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *);
|
||||||
|
|
||||||
static PyObject *PLy_function_build_args(PG_FUNCTION_ARGS, PLyProcedure *);
|
static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *);
|
||||||
static PyObject *PLy_trigger_build_args(PG_FUNCTION_ARGS, PLyProcedure *,
|
static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *,
|
||||||
HeapTuple *);
|
HeapTuple *);
|
||||||
static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *,
|
static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *,
|
||||||
TriggerData *, HeapTuple);
|
TriggerData *, HeapTuple);
|
||||||
@ -206,12 +207,14 @@ static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *);
|
|||||||
/* returns a cached PLyProcedure, or creates, stores and returns
|
/* returns a cached PLyProcedure, or creates, stores and returns
|
||||||
* a new PLyProcedure.
|
* a new PLyProcedure.
|
||||||
*/
|
*/
|
||||||
static PLyProcedure *PLy_procedure_get(PG_FUNCTION_ARGS, bool);
|
static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, bool);
|
||||||
|
|
||||||
|
static PLyProcedure *PLy_procedure_create(FunctionCallInfo fcinfo,
|
||||||
|
bool is_trigger,
|
||||||
|
HeapTuple procTup, char *key);
|
||||||
|
|
||||||
static PLyProcedure *PLy_procedure_create(PG_FUNCTION_ARGS, bool, char *);
|
|
||||||
static void PLy_procedure_compile(PLyProcedure *, const char *);
|
static void PLy_procedure_compile(PLyProcedure *, const char *);
|
||||||
static char *PLy_procedure_munge_source(const char *, const char *);
|
static char *PLy_procedure_munge_source(const char *, const char *);
|
||||||
static PLyProcedure *PLy_procedure_new(const char *name);
|
|
||||||
static void PLy_procedure_delete(PLyProcedure *);
|
static void PLy_procedure_delete(PLyProcedure *);
|
||||||
|
|
||||||
static void PLy_typeinfo_init(PLyTypeInfo *);
|
static void PLy_typeinfo_init(PLyTypeInfo *);
|
||||||
@ -249,7 +252,6 @@ static PyObject *PLy_interp_safe = NULL;
|
|||||||
static PyObject *PLy_interp_safe_globals = NULL;
|
static PyObject *PLy_interp_safe_globals = NULL;
|
||||||
static PyObject *PLy_importable_modules = NULL;
|
static PyObject *PLy_importable_modules = NULL;
|
||||||
static PyObject *PLy_procedure_cache = NULL;
|
static PyObject *PLy_procedure_cache = NULL;
|
||||||
static char *PLy_procedure_fmt = "__plpython_procedure_%s_%u";
|
|
||||||
|
|
||||||
char *PLy_importable_modules_list[] = {
|
char *PLy_importable_modules_list[] = {
|
||||||
"array",
|
"array",
|
||||||
@ -387,12 +389,12 @@ plpython_call_handler(PG_FUNCTION_ARGS)
|
|||||||
* to take no arguments and return an argument of type opaque.
|
* to take no arguments and return an argument of type opaque.
|
||||||
*/
|
*/
|
||||||
HeapTuple
|
HeapTuple
|
||||||
PLy_trigger_handler(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
PLy_trigger_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
HeapTuple rv = NULL;
|
HeapTuple rv = NULL;
|
||||||
PyObject *plargs = NULL;
|
PyObject * volatile plargs = NULL;
|
||||||
PyObject *plrv = NULL;
|
PyObject * volatile plrv = NULL;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
|
|
||||||
@ -468,12 +470,16 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
|
|||||||
HeapTuple otup)
|
HeapTuple otup)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
PyObject *plntup, *plkeys, *platt, *plval, *plstr;
|
PyObject * volatile plntup;
|
||||||
|
PyObject * volatile plkeys;
|
||||||
|
PyObject * volatile platt;
|
||||||
|
PyObject * volatile plval;
|
||||||
|
PyObject * volatile plstr;
|
||||||
HeapTuple rtup;
|
HeapTuple rtup;
|
||||||
int natts, i, j, attn, atti;
|
int natts, i, j, attn, atti;
|
||||||
int *modattrs;
|
int * volatile modattrs;
|
||||||
Datum *modvalues;
|
Datum * volatile modvalues;
|
||||||
char *modnulls;
|
char *volatile modnulls;
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
|
|
||||||
plntup = plkeys = platt = plval = plstr = NULL;
|
plntup = plkeys = platt = plval = plstr = NULL;
|
||||||
@ -556,8 +562,8 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
|
|||||||
|
|
||||||
modvalues[j] = FunctionCall3(&proc->result.out.r.atts[atti].typfunc,
|
modvalues[j] = FunctionCall3(&proc->result.out.r.atts[atti].typfunc,
|
||||||
CStringGetDatum(src),
|
CStringGetDatum(src),
|
||||||
proc->result.out.r.atts[atti].typelem,
|
ObjectIdGetDatum(proc->result.out.r.atts[atti].typelem),
|
||||||
proc->result.out.r.atts[atti].typlen);
|
Int32GetDatum(tupdesc->attrs[j]->atttypmod));
|
||||||
modnulls[j] = ' ';
|
modnulls[j] = ' ';
|
||||||
|
|
||||||
Py_DECREF(plstr);
|
Py_DECREF(plstr);
|
||||||
@ -588,13 +594,13 @@ PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PLy_trigger_build_args(PG_FUNCTION_ARGS, PLyProcedure *proc, HeapTuple *rv)
|
PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
TriggerData *tdata;
|
TriggerData *tdata;
|
||||||
PyObject *pltname, *pltevent, *pltwhen, *pltlevel, *pltrelid;
|
PyObject *pltname, *pltevent, *pltwhen, *pltlevel, *pltrelid;
|
||||||
PyObject *pltargs, *pytnew, *pytold;
|
PyObject *pltargs, *pytnew, *pytold;
|
||||||
PyObject *pltdata = NULL;
|
PyObject * volatile pltdata = NULL;
|
||||||
char *stroid;
|
char *stroid;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
@ -723,13 +729,13 @@ PLy_trigger_build_args(PG_FUNCTION_ARGS, PLyProcedure *proc, HeapTuple *rv)
|
|||||||
/* function handler and friends
|
/* function handler and friends
|
||||||
*/
|
*/
|
||||||
Datum
|
Datum
|
||||||
PLy_function_handler(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
PLy_function_handler(FunctionCallInfo fcinfo, PLyProcedure *proc)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
Datum rv;
|
Datum rv;
|
||||||
PyObject *plargs = NULL;
|
PyObject * volatile plargs = NULL;
|
||||||
PyObject *plrv = NULL;
|
PyObject * volatile plrv = NULL;
|
||||||
PyObject *plrv_so = NULL;
|
PyObject * volatile plrv_so = NULL;
|
||||||
char *plrv_sc;
|
char *plrv_sc;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
@ -792,9 +798,9 @@ PLy_function_handler(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
|||||||
plrv_so = PyObject_Str(plrv);
|
plrv_so = PyObject_Str(plrv);
|
||||||
plrv_sc = PyString_AsString(plrv_so);
|
plrv_sc = PyString_AsString(plrv_so);
|
||||||
rv = FunctionCall3(&proc->result.out.d.typfunc,
|
rv = FunctionCall3(&proc->result.out.d.typfunc,
|
||||||
PointerGetDatum(plrv_sc),
|
PointerGetDatum(plrv_sc),
|
||||||
proc->result.out.d.typelem,
|
ObjectIdGetDatum(proc->result.out.d.typelem),
|
||||||
proc->result.out.d.typlen);
|
Int32GetDatum(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
RESTORE_EXC();
|
RESTORE_EXC();
|
||||||
@ -828,11 +834,11 @@ PLy_procedure_call(PLyProcedure *proc, char *kargs, PyObject *vargs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PLy_function_build_args(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
PyObject *arg = NULL;
|
PyObject * volatile arg = NULL;
|
||||||
PyObject *args = NULL;
|
PyObject * volatile args = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
@ -868,9 +874,9 @@ PLy_function_build_args(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
|||||||
Datum dt;
|
Datum dt;
|
||||||
|
|
||||||
dt = FunctionCall3(&(proc->args[i].in.d.typfunc),
|
dt = FunctionCall3(&(proc->args[i].in.d.typfunc),
|
||||||
fcinfo->arg[i],
|
fcinfo->arg[i],
|
||||||
proc->args[i].in.d.typelem,
|
ObjectIdGetDatum(proc->args[i].in.d.typelem),
|
||||||
proc->args[i].in.d.typlen);
|
Int32GetDatum(-1));
|
||||||
ct = DatumGetCString(dt);
|
ct = DatumGetCString(dt);
|
||||||
arg = (proc->args[i].in.d.func)(ct);
|
arg = (proc->args[i].in.d.func)(ct);
|
||||||
pfree(ct);
|
pfree(ct);
|
||||||
@ -898,45 +904,68 @@ PLy_function_build_args(PG_FUNCTION_ARGS, PLyProcedure *proc)
|
|||||||
|
|
||||||
/* PLyProcedure functions
|
/* PLyProcedure functions
|
||||||
*/
|
*/
|
||||||
PLyProcedure *
|
static PLyProcedure *
|
||||||
PLy_procedure_get(PG_FUNCTION_ARGS, bool is_trigger)
|
PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger)
|
||||||
{
|
{
|
||||||
|
Oid fn_oid;
|
||||||
|
HeapTuple procTup;
|
||||||
char key[128];
|
char key[128];
|
||||||
PyObject *plproc;
|
PyObject *plproc;
|
||||||
PLyProcedure *proc;
|
PLyProcedure *proc = NULL;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
|
|
||||||
rv = snprintf(key, sizeof(key), "%u", fcinfo->flinfo->fn_oid);
|
fn_oid = fcinfo->flinfo->fn_oid;
|
||||||
|
procTup = SearchSysCache(PROCOID,
|
||||||
|
ObjectIdGetDatum(fn_oid),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(procTup))
|
||||||
|
elog(ERROR, "plpython: cache lookup for procedure %u failed", fn_oid);
|
||||||
|
|
||||||
|
rv = snprintf(key, sizeof(key), "%u%s",
|
||||||
|
fn_oid,
|
||||||
|
is_trigger ? "_trigger" : "");
|
||||||
if ((rv >= sizeof(key)) || (rv < 0))
|
if ((rv >= sizeof(key)) || (rv < 0))
|
||||||
elog(FATAL, "plpython: Buffer overrun in %s:%d", __FILE__, __LINE__);
|
elog(FATAL, "plpython: Buffer overrun in %s:%d", __FILE__, __LINE__);
|
||||||
|
|
||||||
plproc = PyDict_GetItemString(PLy_procedure_cache, key);
|
plproc = PyDict_GetItemString(PLy_procedure_cache, key);
|
||||||
if (plproc == NULL)
|
|
||||||
return PLy_procedure_create(fcinfo, is_trigger, key);
|
|
||||||
|
|
||||||
Py_INCREF(plproc);
|
if (plproc != NULL)
|
||||||
if (!PyCObject_Check(plproc))
|
{
|
||||||
elog(FATAL, "plpython: Expected a PyCObject, didn't get one");
|
Py_INCREF(plproc);
|
||||||
|
if (!PyCObject_Check(plproc))
|
||||||
|
elog(FATAL, "plpython: Expected a PyCObject, didn't get one");
|
||||||
|
|
||||||
mark();
|
mark();
|
||||||
|
|
||||||
proc = PyCObject_AsVoidPtr(plproc);
|
proc = PyCObject_AsVoidPtr(plproc);
|
||||||
if (proc->me != plproc)
|
if (proc->me != plproc)
|
||||||
elog(FATAL, "plpython: Aiieee, proc->me != plproc");
|
elog(FATAL, "plpython: Aiieee, proc->me != plproc");
|
||||||
|
/* did we find an up-to-date cache entry? */
|
||||||
|
if (proc->fn_xmin != procTup->t_data->t_xmin ||
|
||||||
|
proc->fn_cmin != procTup->t_data->t_cmin)
|
||||||
|
{
|
||||||
|
Py_DECREF(plproc);
|
||||||
|
proc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc == NULL)
|
||||||
|
proc = PLy_procedure_create(fcinfo, is_trigger, procTup, key);
|
||||||
|
|
||||||
|
ReleaseSysCache(procTup);
|
||||||
|
|
||||||
return proc;
|
return proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
PLyProcedure *
|
static PLyProcedure *
|
||||||
PLy_procedure_create(PG_FUNCTION_ARGS, bool is_trigger, char *key)
|
PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
|
||||||
|
HeapTuple procTup, char *key)
|
||||||
{
|
{
|
||||||
char procName[256];
|
char procName[256];
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
HeapTuple procTup;
|
|
||||||
Form_pg_proc procStruct;
|
Form_pg_proc procStruct;
|
||||||
Oid fn_oid;
|
|
||||||
PLyProcedure *volatile proc;
|
PLyProcedure *volatile proc;
|
||||||
char *volatile procSource = NULL;
|
char *volatile procSource = NULL;
|
||||||
Datum procDatum;
|
Datum procDatum;
|
||||||
@ -944,19 +973,28 @@ PLy_procedure_create(PG_FUNCTION_ARGS, bool is_trigger, char *key)
|
|||||||
|
|
||||||
enter();
|
enter();
|
||||||
|
|
||||||
fn_oid = fcinfo->flinfo->fn_oid;
|
|
||||||
procTup = SearchSysCache(PROCOID, ObjectIdGetDatum(fn_oid), 0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(procTup))
|
|
||||||
elog(ERROR, "plpython: cache lookup for procedure \"%u\" failed", fn_oid);
|
|
||||||
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
|
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
|
||||||
|
|
||||||
rv = snprintf(procName, sizeof(procName), PLy_procedure_fmt,
|
rv = snprintf(procName, sizeof(procName),
|
||||||
NameStr(procStruct->proname), fn_oid);
|
"__plpython_procedure_%s_%u%s",
|
||||||
|
NameStr(procStruct->proname),
|
||||||
|
fcinfo->flinfo->fn_oid,
|
||||||
|
is_trigger ? "_trigger" : "");
|
||||||
if ((rv >= sizeof(procName)) || (rv < 0))
|
if ((rv >= sizeof(procName)) || (rv < 0))
|
||||||
elog(FATAL, "plpython: Procedure name would overrun buffer");
|
elog(FATAL, "plpython: Procedure name would overrun buffer");
|
||||||
|
|
||||||
proc = PLy_procedure_new(procName);
|
proc = PLy_malloc(sizeof(PLyProcedure));
|
||||||
|
proc->proname = PLy_malloc(strlen(procName) + 1);
|
||||||
|
strcpy(proc->proname, procName);
|
||||||
|
proc->fn_xmin = procTup->t_data->t_xmin;
|
||||||
|
proc->fn_cmin = procTup->t_data->t_cmin;
|
||||||
|
PLy_typeinfo_init(&proc->result);
|
||||||
|
for (i = 0; i < FUNC_MAX_ARGS; i++)
|
||||||
|
PLy_typeinfo_init(&proc->args[i]);
|
||||||
|
proc->nargs = 0;
|
||||||
|
proc->code = proc->interp = proc->reval = proc->statics = NULL;
|
||||||
|
proc->globals = proc->me = NULL;
|
||||||
|
|
||||||
SAVE_EXC();
|
SAVE_EXC();
|
||||||
if (TRAP_EXC())
|
if (TRAP_EXC())
|
||||||
{
|
{
|
||||||
@ -1037,8 +1075,6 @@ PLy_procedure_create(PG_FUNCTION_ARGS, bool is_trigger, char *key)
|
|||||||
PointerGetDatum(&procStruct->prosrc));
|
PointerGetDatum(&procStruct->prosrc));
|
||||||
procSource = DatumGetCString(procDatum);
|
procSource = DatumGetCString(procDatum);
|
||||||
|
|
||||||
ReleaseSysCache(procTup);
|
|
||||||
|
|
||||||
PLy_procedure_compile(proc, procSource);
|
PLy_procedure_compile(proc, procSource);
|
||||||
|
|
||||||
pfree(procSource);
|
pfree(procSource);
|
||||||
@ -1170,29 +1206,6 @@ PLy_procedure_munge_source(const char *name, const char *src)
|
|||||||
return mrc;
|
return mrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
PLyProcedure *
|
|
||||||
PLy_procedure_new(const char *name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
PLyProcedure *proc;
|
|
||||||
|
|
||||||
enter();
|
|
||||||
|
|
||||||
proc = PLy_malloc(sizeof(PLyProcedure));
|
|
||||||
proc->proname = PLy_malloc(strlen(name) + 1);
|
|
||||||
strcpy(proc->proname, name);
|
|
||||||
PLy_typeinfo_init(&proc->result);
|
|
||||||
for (i = 0; i < FUNC_MAX_ARGS; i++)
|
|
||||||
PLy_typeinfo_init(&proc->args[i]);
|
|
||||||
proc->nargs = 0;
|
|
||||||
proc->code = proc->interp = proc->reval = proc->statics = NULL;
|
|
||||||
proc->globals = proc->me = NULL;
|
|
||||||
|
|
||||||
leave();
|
|
||||||
|
|
||||||
return proc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PLy_procedure_delete(PLyProcedure *proc)
|
PLy_procedure_delete(PLyProcedure *proc)
|
||||||
{
|
{
|
||||||
@ -1314,8 +1327,8 @@ PLy_output_datum_func2(PLyObToDatum *arg, Form_pg_type typeStruct)
|
|||||||
enter();
|
enter();
|
||||||
|
|
||||||
perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
|
perm_fmgr_info(typeStruct->typinput, &arg->typfunc);
|
||||||
arg->typelem = (Oid) typeStruct->typelem;
|
arg->typelem = typeStruct->typelem;
|
||||||
arg->typlen = typeStruct->typlen;
|
arg->typbyval = typeStruct->typbyval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1334,10 +1347,9 @@ PLy_input_datum_func2(PLyDatumToOb *arg, Form_pg_type typeStruct)
|
|||||||
{
|
{
|
||||||
char *type;
|
char *type;
|
||||||
|
|
||||||
arg->typoutput = typeStruct->typoutput;
|
|
||||||
perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
|
perm_fmgr_info(typeStruct->typoutput, &arg->typfunc);
|
||||||
arg->typlen = typeStruct->typlen;
|
|
||||||
arg->typelem = typeStruct->typelem;
|
arg->typelem = typeStruct->typelem;
|
||||||
|
arg->typbyval = typeStruct->typbyval;
|
||||||
|
|
||||||
/* hmmm, wierd. means this arg will always be converted
|
/* hmmm, wierd. means this arg will always be converted
|
||||||
* to a python None
|
* to a python None
|
||||||
@ -1516,9 +1528,10 @@ PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
|
|||||||
PyDict_SetItemString(dict, key, Py_None);
|
PyDict_SetItemString(dict, key, Py_None);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vdat = OidFunctionCall3(info->in.r.atts[i].typoutput, vattr,
|
vdat = FunctionCall3(&info->in.r.atts[i].typfunc,
|
||||||
ObjectIdGetDatum(info->in.r.atts[i].typelem),
|
vattr,
|
||||||
Int32GetDatum(info->in.r.atts[i].typlen));
|
ObjectIdGetDatum(info->in.r.atts[i].typelem),
|
||||||
|
Int32GetDatum(desc->attrs[i]->atttypmod));
|
||||||
vsrc = DatumGetCString(vdat);
|
vsrc = DatumGetCString(vdat);
|
||||||
|
|
||||||
/* no exceptions allowed
|
/* no exceptions allowed
|
||||||
@ -1873,7 +1886,7 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
|
|||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
PLyPlanObject *plan;
|
PLyPlanObject *plan;
|
||||||
PyObject *list = NULL;
|
PyObject *list = NULL;
|
||||||
PyObject *optr = NULL;
|
PyObject * volatile optr = NULL;
|
||||||
char *query;
|
char *query;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
@ -2037,7 +2050,8 @@ PyObject *
|
|||||||
PLy_spi_execute_plan(PyObject *ob, PyObject *list, int limit)
|
PLy_spi_execute_plan(PyObject *ob, PyObject *list, int limit)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
int nargs, i, rv;
|
volatile int nargs;
|
||||||
|
int i, rv;
|
||||||
PLyPlanObject *plan;
|
PLyPlanObject *plan;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
@ -2080,12 +2094,10 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, int limit)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
{
|
{
|
||||||
/* FIXME -- typbyval the proper check?
|
if (!plan->args[i].out.d.typbyval &&
|
||||||
*/
|
(plan->values[i] != (Datum) NULL))
|
||||||
if ((plan->values[i] != (Datum) NULL) &&
|
{
|
||||||
(plan->args[i].out.d.typlen < 0))
|
pfree(DatumGetPointer(plan->values[i]));
|
||||||
{
|
|
||||||
pfree((void *) plan->values[i]);
|
|
||||||
plan->values[i] = (Datum) NULL;
|
plan->values[i] = (Datum) NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2100,21 +2112,19 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, int limit)
|
|||||||
{
|
{
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
{
|
{
|
||||||
Datum typelem, typlen, dv;
|
|
||||||
PyObject *elem, *so;
|
PyObject *elem, *so;
|
||||||
char *sv;
|
char *sv;
|
||||||
|
|
||||||
typelem = ObjectIdGetDatum(plan->args[i].out.d.typelem);
|
|
||||||
typlen = Int32GetDatum(plan->args[i].out.d.typlen);
|
|
||||||
elem = PySequence_GetItem(list, i);
|
elem = PySequence_GetItem(list, i);
|
||||||
so = PyObject_Str(elem);
|
so = PyObject_Str(elem);
|
||||||
sv = PyString_AsString(so);
|
sv = PyString_AsString(so);
|
||||||
dv = CStringGetDatum(sv);
|
|
||||||
|
|
||||||
/* FIXME -- if this can elog, we have leak
|
/* FIXME -- if this can elog, we have leak
|
||||||
*/
|
*/
|
||||||
plan->values[i] = FunctionCall3(&(plan->args[i].out.d.typfunc),
|
plan->values[i] = FunctionCall3(&(plan->args[i].out.d.typfunc),
|
||||||
dv, typelem, typlen);
|
CStringGetDatum(sv),
|
||||||
|
ObjectIdGetDatum(plan->args[i].out.d.typelem),
|
||||||
|
Int32GetDatum(-1));
|
||||||
|
|
||||||
Py_DECREF(so);
|
Py_DECREF(so);
|
||||||
Py_DECREF(elem);
|
Py_DECREF(elem);
|
||||||
@ -2126,12 +2136,10 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, int limit)
|
|||||||
|
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
{
|
{
|
||||||
/* FIXME -- typbyval the proper check?
|
if (!plan->args[i].out.d.typbyval &&
|
||||||
*/
|
(plan->values[i] != (Datum) NULL))
|
||||||
if ((plan->values[i] != (Datum) NULL) &&
|
|
||||||
(plan->args[i].out.d.typlen < 0))
|
|
||||||
{
|
{
|
||||||
pfree((void *) plan->values[i]);
|
pfree(DatumGetPointer(plan->values[i]));
|
||||||
plan->values[i] = (Datum) NULL;
|
plan->values[i] = (Datum) NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2413,11 +2421,11 @@ PLy_notice(PyObject *self, PyObject *args)
|
|||||||
|
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PLy_log(int level, PyObject *self, PyObject *args)
|
PLy_log(volatile int level, PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
DECLARE_EXC();
|
DECLARE_EXC();
|
||||||
PyObject *so;
|
PyObject *so;
|
||||||
char *sv;
|
char * volatile sv;
|
||||||
|
|
||||||
enter();
|
enter();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user