Re: A generic trigger? - Mailing list pgsql-sql

From Tom Lane
Subject Re: A generic trigger?
Date
Msg-id 18569.1063560659@sss.pgh.pa.us
Whole thread Raw
In response to Re: A generic trigger?  (Peter Childs <Blue.Dragon@blueyonder.co.uk>)
List pgsql-sql
Peter Childs <Blue.Dragon@blueyonder.co.uk> writes:
> Yes it is possible and I've done it. The reason I'm not using it is because I
> wrote it in Pl/Python and if you attach the same trigger to more than one 
> table in the same transaction pg/python (actually the entire server crashes 
> but thats not the point) crashes. Well it did when I last tested it in early 
> versions.

I've been expecting someone to submit a fix for this, but nobody did
:-(.  So I went ahead and repaired it in CVS tip.  The patch is attached
if you want to try patching your local copy (it looks like it will apply
to 7.3 branch with some fuzz, but I have not actually tested it there).
        regards, tom lane

*** src/pl/plpython/plpython.c.orig    Mon Aug  4 14:40:50 2003
--- src/pl/plpython/plpython.c    Sun Sep 14 13:07:02 2003
***************
*** 224,236 ****  static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *); 
! /* returns a cached PLyProcedure, or creates, stores and returns
!  * a new PLyProcedure.
!  */
! static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo, bool);  static PLyProcedure
*PLy_procedure_create(FunctionCallInfofcinfo,
 
!                      bool is_trigger,                      HeapTuple procTup, char *key);  static void
PLy_procedure_compile(PLyProcedure*, const char *);
 
--- 224,234 ----  static PyObject *PLy_procedure_call(PLyProcedure *, char *, PyObject *); 
! static PLyProcedure *PLy_procedure_get(FunctionCallInfo fcinfo,
!                                        Oid tgreloid);  static PLyProcedure *PLy_procedure_create(FunctionCallInfo
fcinfo,
!                      Oid tgreloid,                      HeapTuple procTup, char *key);  static void
PLy_procedure_compile(PLyProcedure*, const char *);
 
***************
*** 326,332 **** {     DECLARE_EXC();     Datum        retval;
-     volatile bool is_trigger;     PLyProcedure *volatile proc = NULL;      enter();
--- 324,329 ----
***************
*** 337,343 ****         elog(ERROR, "could not connect to SPI manager");      CALL_LEVEL_INC();
-     is_trigger = CALLED_AS_TRIGGER(fcinfo);      SAVE_EXC();     if (TRAP_EXC())
--- 334,339 ----
***************
*** 364,379 ****      * PLy_restart_in_progress);      */ 
!     proc = PLy_procedure_get(fcinfo, is_trigger);
! 
!     if (is_trigger)     {
!         HeapTuple    trv = PLy_trigger_handler(fcinfo, proc);          retval = PointerGetDatum(trv);     }     else
      retval = PLy_function_handler(fcinfo, proc);      CALL_LEVEL_DEC();     RESTORE_EXC();
 
--- 360,380 ----      * PLy_restart_in_progress);      */ 
!     if (CALLED_AS_TRIGGER(fcinfo))     {
!         TriggerData *tdata = (TriggerData *) fcinfo->context;
!         HeapTuple    trv; 
+         proc = PLy_procedure_get(fcinfo,
+                                  RelationGetRelid(tdata->tg_relation));
+         trv = PLy_trigger_handler(fcinfo, proc);         retval = PointerGetDatum(trv);     }     else
+     {
+         proc = PLy_procedure_get(fcinfo, InvalidOid);         retval = PLy_function_handler(fcinfo, proc);
+     }      CALL_LEVEL_DEC();     RESTORE_EXC();
***************
*** 962,971 **** }  
! /* PLyProcedure functions  */ static PLyProcedure *
! PLy_procedure_get(FunctionCallInfo fcinfo, bool is_trigger) {     Oid            fn_oid;     HeapTuple    procTup;
--- 963,979 ---- }  
! /*
!  * PLyProcedure functions
!  */
! 
! /* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
!  * returns a new PLyProcedure.  fcinfo is the call info, tgreloid is the
!  * relation OID when calling a trigger, or InvalidOid (zero) for ordinary
!  * function calls.  */ static PLyProcedure *
! PLy_procedure_get(FunctionCallInfo fcinfo, Oid tgreloid) {     Oid            fn_oid;     HeapTuple    procTup;
***************
*** 983,991 ****     if (!HeapTupleIsValid(procTup))         elog(ERROR, "cache lookup failed for function %u",
fn_oid);
 
!     rv = snprintf(key, sizeof(key), "%u%s",
!                   fn_oid,
!                   is_trigger ? "_trigger" : "");     if ((rv >= sizeof(key)) || (rv < 0))         elog(ERROR, "key
toolong"); 
 
--- 991,997 ----     if (!HeapTupleIsValid(procTup))         elog(ERROR, "cache lookup failed for function %u",
fn_oid);
 
!     rv = snprintf(key, sizeof(key), "%u_%u", fn_oid, tgreloid);     if ((rv >= sizeof(key)) || (rv < 0))
elog(ERROR,"key too long"); 
 
***************
*** 1012,1018 ****     }      if (proc == NULL)
!         proc = PLy_procedure_create(fcinfo, is_trigger, procTup, key);      ReleaseSysCache(procTup); 
--- 1018,1024 ----     }      if (proc == NULL)
!         proc = PLy_procedure_create(fcinfo, tgreloid, procTup, key);      ReleaseSysCache(procTup); 
***************
*** 1020,1026 **** }  static PLyProcedure *
! PLy_procedure_create(FunctionCallInfo fcinfo, bool is_trigger,                      HeapTuple procTup, char *key) {
 char        procName[NAMEDATALEN + 256];
 
--- 1026,1032 ---- }  static PLyProcedure *
! PLy_procedure_create(FunctionCallInfo fcinfo, Oid tgreloid,                      HeapTuple procTup, char *key) {
char       procName[NAMEDATALEN + 256];
 
***************
*** 1037,1047 ****      procStruct = (Form_pg_proc) GETSTRUCT(procTup); 
!     rv = snprintf(procName, sizeof(procName),
!                   "__plpython_procedure_%s_%u%s",
!                   NameStr(procStruct->proname),
!                   fcinfo->flinfo->fn_oid,
!                   is_trigger ? "_trigger" : "");     if ((rv >= sizeof(procName)) || (rv < 0))         elog(ERROR,
"procedurename would overrun buffer"); 
 
--- 1043,1059 ----      procStruct = (Form_pg_proc) GETSTRUCT(procTup); 
!     if (OidIsValid(tgreloid))
!         rv = snprintf(procName, sizeof(procName),
!                       "__plpython_procedure_%s_%u_trigger_%u",
!                       NameStr(procStruct->proname),
!                       fcinfo->flinfo->fn_oid,
!                       tgreloid);
!     else
!         rv = snprintf(procName, sizeof(procName),
!                       "__plpython_procedure_%s_%u",
!                       NameStr(procStruct->proname),
!                       fcinfo->flinfo->fn_oid);     if ((rv >= sizeof(procName)) || (rv < 0))         elog(ERROR,
"procedurename would overrun buffer"); 
 
***************
*** 1073,1079 ****      * get information required for output conversion of the return value,      * but only if this
isn'ta trigger.      */
 
!     if (!is_trigger)     {         HeapTuple    rvTypeTup;         Form_pg_type rvTypeStruct;
--- 1085,1091 ----      * get information required for output conversion of the return value,      * but only if this
isn'ta trigger.      */
 
!     if (!CALLED_AS_TRIGGER(fcinfo))     {         HeapTuple    rvTypeTup;         Form_pg_type rvTypeStruct;


pgsql-sql by date:

Previous
From: "Muhyiddin A.M Hayat"
Date:
Subject:
Next
From: "Marek Lewczuk"
Date:
Subject: MD5() function not available ??