Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 96e6319

Browse files
committed
Fix plpython to generate separate cached procedure data for each
relation, when the same function is used as a trigger on more than one relation. This avoids crashes due to differing rowtypes for different relations. Per bug report from Lance Thomas, 7-Feb-03.
1 parent efebe26 commit 96e6319

File tree

1 file changed

+37
-25
lines changed

1 file changed

+37
-25
lines changed

src/pl/plpython/plpython.c

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
3030
*
3131
* IDENTIFICATION
32-
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.39 2003/08/04 18:40:50 tgl Exp $
32+
* $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.40 2003/09/14 17:13:06 tgl Exp $
3333
*
3434
*********************************************************************
3535
*/
@@ -224,13 +224,11 @@ static HeapTuple PLy_modify_tuple(PLyProcedure *, PyObject *,
224224

225225
static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *);
226226

227-
/* returns a cached PLyProcedure, or creates, stores and returns
228-
* a new PLyProcedure.
229-
*/
230-
static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, bool);
227+
static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo,
228+
Oid tgreloid);
231229

232230
static PLyProcedure *PLy_procedure_create(FunctionCallInfo fcinfo,
233-
bool is_trigger,
231+
Oid tgreloid,
234232
HeapTuple procTup, char *key);
235233

236234
static void PLy_procedure_compile(PLyProcedure *, const char *);
@@ -326,7 +324,6 @@ plpython_call_handler(PG_FUNCTION_ARGS)
326324
{
327325
DECLARE_EXC();
328326
Datum retval;
329-
volatile bool is_trigger;
330327
PLyProcedure *volatile proc = NULL;
331328

332329
enter();
@@ -337,7 +334,6 @@ plpython_call_handler(PG_FUNCTION_ARGS)
337334
elog(ERROR, "could not connect to SPI manager");
338335

339336
CALL_LEVEL_INC();
340-
is_trigger = CALLED_AS_TRIGGER(fcinfo);
341337

342338
SAVE_EXC();
343339
if (TRAP_EXC())
@@ -364,16 +360,21 @@ plpython_call_handler(PG_FUNCTION_ARGS)
364360
* PLy_restart_in_progress);
365361
*/
366362

367-
proc = PLy_procedure_get(fcinfo, is_trigger);
368-
369-
if (is_trigger)
363+
if (CALLED_AS_TRIGGER(fcinfo))
370364
{
371-
HeapTuple trv = PLy_trigger_handler(fcinfo, proc);
365+
TriggerData *tdata = (TriggerData *) fcinfo->context;
366+
HeapTuple trv;
372367

368+
proc = PLy_procedure_get(fcinfo,
369+
RelationGetRelid(tdata->tg_relation));
370+
trv = PLy_trigger_handler(fcinfo, proc);
373371
retval = PointerGetDatum(trv);
374372
}
375373
else
374+
{
375+
proc = PLy_procedure_get(fcinfo, InvalidOid);
376376
retval = PLy_function_handler(fcinfo, proc);
377+
}
377378

378379
CALL_LEVEL_DEC();
379380
RESTORE_EXC();
@@ -962,10 +963,17 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure * proc)
962963
}
963964

964965

965-
/* PLyProcedure functions
966+
/*
967+
* PLyProcedure functions
968+
*/
969+
970+
/* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
971+
* returns a new PLyProcedure. fcinfo is the call info, tgreloid is the
972+
* relation OID when calling a trigger, or InvalidOid (zero) for ordinary
973+
* function calls.
966974
*/
967975
static PLyProcedure *
968-
PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger)
976+
PLy_procedure_get(FunctionCallInfo fcinfo, Oid tgreloid)
969977
{
970978
Oid fn_oid;
971979
HeapTuple procTup;
@@ -983,9 +991,7 @@ PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger)
983991
if (!HeapTupleIsValid(procTup))
984992
elog(ERROR, "cache lookup failed for function %u", fn_oid);
985993

986-
rv = snprintf(key, sizeof(key), "%u%s",
987-
fn_oid,
988-
is_trigger ? "_trigger" : "");
994+
rv = snprintf(key, sizeof(key), "%u_%u", fn_oid, tgreloid);
989995
if ((rv >= sizeof(key)) || (rv < 0))
990996
elog(ERROR, "key too long");
991997

@@ -1012,15 +1018,15 @@ PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger)
10121018
}
10131019

10141020
if (proc == NULL)
1015-
proc = PLy_procedure_create(fcinfo, is_trigger, procTup, key);
1021+
proc = PLy_procedure_create(fcinfo, tgreloid, procTup, key);
10161022

10171023
ReleaseSysCache(procTup);
10181024

10191025
return proc;
10201026
}
10211027

10221028
static PLyProcedure *
1023-
PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
1029+
PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,
10241030
HeapTuple procTup, char *key)
10251031
{
10261032
char procName[NAMEDATALEN + 256];
@@ -1037,11 +1043,17 @@ PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
10371043

10381044
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
10391045

1040-
rv = snprintf(procName, sizeof(procName),
1041-
"__plpython_procedure_%s_%u%s",
1042-
NameStr(procStruct->proname),
1043-
fcinfo->flinfo->fn_oid,
1044-
is_trigger ? "_trigger" : "");
1046+
if (OidIsValid(tgreloid))
1047+
rv = snprintf(procName, sizeof(procName),
1048+
"__plpython_procedure_%s_%u_trigger_%u",
1049+
NameStr(procStruct->proname),
1050+
fcinfo->flinfo->fn_oid,
1051+
tgreloid);
1052+
else
1053+
rv = snprintf(procName, sizeof(procName),
1054+
"__plpython_procedure_%s_%u",
1055+
NameStr(procStruct->proname),
1056+
fcinfo->flinfo->fn_oid);
10451057
if ((rv >= sizeof(procName)) || (rv < 0))
10461058
elog(ERROR, "procedure name would overrun buffer");
10471059

@@ -1073,7 +1085,7 @@ PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,
10731085
* get information required for output conversion of the return value,
10741086
* but only if this isn't a trigger.
10751087
*/
1076-
if (!is_trigger)
1088+
if (!CALLED_AS_TRIGGER(fcinfo))
10771089
{
10781090
HeapTuple rvTypeTup;
10791091
Form_pg_type rvTypeStruct;

0 commit comments

Comments
 (0)