2727#include "access/xact.h"
2828#include "catalog/pg_proc.h"
2929#include "catalog/pg_type.h"
30+ #include "commands/event_trigger.h"
3031#include "commands/trigger.h"
3132#include "executor/spi.h"
3233#include "fmgr.h"
@@ -200,11 +201,13 @@ static Datum pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted);
200201static Datum pltcl_func_handler (PG_FUNCTION_ARGS ,bool pltrusted );
201202
202203static HeapTuple pltcl_trigger_handler (PG_FUNCTION_ARGS ,bool pltrusted );
204+ static void pltcl_event_trigger_handler (PG_FUNCTION_ARGS ,bool pltrusted );
203205
204206static void throw_tcl_error (Tcl_Interp * interp ,const char * proname );
205207
206208static pltcl_proc_desc * compile_pltcl_function (Oid fn_oid ,Oid tgreloid ,
207- bool pltrusted );
209+ bool is_event_trigger ,
210+ bool pltrusted );
208211
209212static int pltcl_elog (ClientData cdata ,Tcl_Interp * interp ,
210213int argc ,CONST84 char * argv []);
@@ -644,6 +647,12 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
644647pltcl_current_fcinfo = NULL ;
645648retval = PointerGetDatum (pltcl_trigger_handler (fcinfo ,pltrusted ));
646649}
650+ else if (CALLED_AS_EVENT_TRIGGER (fcinfo ))
651+ {
652+ pltcl_current_fcinfo = NULL ;
653+ pltcl_event_trigger_handler (fcinfo ,pltrusted );
654+ retval = (Datum )0 ;
655+ }
647656else
648657{
649658pltcl_current_fcinfo = fcinfo ;
@@ -685,7 +694,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, bool pltrusted)
685694
686695/* Find or compile the function */
687696prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid ,InvalidOid ,
688- pltrusted );
697+ false, pltrusted );
689698
690699pltcl_current_prodesc = prodesc ;
691700
@@ -844,6 +853,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
844853/* Find or compile the function */
845854prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid ,
846855RelationGetRelid (trigdata -> tg_relation ),
856+ false,/* not an event trigger */
847857pltrusted );
848858
849859pltcl_current_prodesc = prodesc ;
@@ -1130,6 +1140,47 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
11301140return rettup ;
11311141}
11321142
1143+ /**********************************************************************
1144+ * pltcl_event_trigger_handler()- Handler for event trigger calls
1145+ **********************************************************************/
1146+ static void
1147+ pltcl_event_trigger_handler (PG_FUNCTION_ARGS ,bool pltrusted )
1148+ {
1149+ pltcl_proc_desc * prodesc ;
1150+ Tcl_Interp * volatile interp ;
1151+ EventTriggerData * tdata = (EventTriggerData * )fcinfo -> context ;
1152+ Tcl_DString tcl_cmd ;
1153+ int tcl_rc ;
1154+
1155+ /* Connect to SPI manager */
1156+ if (SPI_connect ()!= SPI_OK_CONNECT )
1157+ elog (ERROR ,"could not connect to SPI manager" );
1158+
1159+ /* Find or compile the function */
1160+ prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid ,
1161+ InvalidOid , true,pltrusted );
1162+
1163+ pltcl_current_prodesc = prodesc ;
1164+
1165+ interp = prodesc -> interp_desc -> interp ;
1166+
1167+ /* Create the tcl command and call the internal proc */
1168+ Tcl_DStringInit (& tcl_cmd );
1169+ Tcl_DStringAppendElement (& tcl_cmd ,prodesc -> internal_proname );
1170+ Tcl_DStringAppendElement (& tcl_cmd ,tdata -> event );
1171+ Tcl_DStringAppendElement (& tcl_cmd ,tdata -> tag );
1172+
1173+ tcl_rc = Tcl_GlobalEval (interp ,Tcl_DStringValue (& tcl_cmd ));
1174+ Tcl_DStringFree (& tcl_cmd );
1175+
1176+ /* Check for errors reported by Tcl. */
1177+ if (tcl_rc != TCL_OK )
1178+ throw_tcl_error (interp ,prodesc -> user_proname );
1179+
1180+ if (SPI_finish ()!= SPI_OK_FINISH )
1181+ elog (ERROR ,"SPI_finish() failed" );
1182+ }
1183+
11331184
11341185/**********************************************************************
11351186 * throw_tcl_error- ereport an error returned from the Tcl interpreter
@@ -1168,7 +1219,8 @@ throw_tcl_error(Tcl_Interp *interp, const char *proname)
11681219 * (InvalidOid) when compiling a plain function.
11691220 **********************************************************************/
11701221static pltcl_proc_desc *
1171- compile_pltcl_function (Oid fn_oid ,Oid tgreloid ,bool pltrusted )
1222+ compile_pltcl_function (Oid fn_oid ,Oid tgreloid ,
1223+ bool is_event_trigger ,bool pltrusted )
11721224{
11731225HeapTuple procTup ;
11741226Form_pg_proc procStruct ;
@@ -1245,10 +1297,13 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
12451297 * "_trigger" when appropriate to ensure the normal and trigger
12461298 * cases are kept separate.
12471299 ************************************************************/
1248- if (!is_trigger )
1300+ if (!is_trigger && ! is_event_trigger )
12491301snprintf (internal_proname ,sizeof (internal_proname ),
12501302"__PLTcl_proc_%u" ,fn_oid );
1251- else
1303+ else if (is_event_trigger )
1304+ snprintf (internal_proname ,sizeof (internal_proname ),
1305+ "__PLTcl_proc_%u_evttrigger" ,fn_oid );
1306+ else if (is_trigger )
12521307snprintf (internal_proname ,sizeof (internal_proname ),
12531308"__PLTcl_proc_%u_trigger" ,fn_oid );
12541309
@@ -1286,7 +1341,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
12861341 * Get the required information for input conversion of the
12871342 * return value.
12881343 ************************************************************/
1289- if (!is_trigger )
1344+ if (!is_trigger && ! is_event_trigger )
12901345{
12911346typeTup =
12921347SearchSysCache1 (TYPEOID ,
@@ -1306,7 +1361,8 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
13061361{
13071362if (procStruct -> prorettype == VOIDOID )
13081363/* okay */ ;
1309- else if (procStruct -> prorettype == TRIGGEROID )
1364+ else if (procStruct -> prorettype == TRIGGEROID ||
1365+ procStruct -> prorettype == EVTTRIGGEROID )
13101366{
13111367free (prodesc -> user_proname );
13121368free (prodesc -> internal_proname );
@@ -1347,7 +1403,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
13471403 * Get the required information for output conversion
13481404 * of all procedure arguments
13491405 ************************************************************/
1350- if (!is_trigger )
1406+ if (!is_trigger && ! is_event_trigger )
13511407{
13521408prodesc -> nargs = procStruct -> pronargs ;
13531409proc_internal_args [0 ]= '\0' ;
@@ -1397,12 +1453,17 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
13971453ReleaseSysCache (typeTup );
13981454}
13991455}
1400- else
1456+ else if ( is_trigger )
14011457{
14021458/* trigger procedure has fixed args */
14031459strcpy (proc_internal_args ,
14041460"TG_name TG_relid TG_table_name TG_table_schema TG_relatts TG_when TG_level TG_op __PLTcl_Tup_NEW __PLTcl_Tup_OLD args" );
14051461}
1462+ else if (is_event_trigger )
1463+ {
1464+ /* event trigger procedure has fixed args */
1465+ strcpy (proc_internal_args ,"TG_event TG_tag" );
1466+ }
14061467
14071468/************************************************************
14081469 * Create the tcl command to define the internal
@@ -1422,20 +1483,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
14221483Tcl_DStringAppend (& proc_internal_body ,"upvar #0 " ,-1 );
14231484Tcl_DStringAppend (& proc_internal_body ,internal_proname ,-1 );
14241485Tcl_DStringAppend (& proc_internal_body ," GD\n" ,-1 );
1425- if (!is_trigger )
1426- {
1427- for (i = 0 ;i < prodesc -> nargs ;i ++ )
1428- {
1429- if (prodesc -> arg_is_rowtype [i ])
1430- {
1431- snprintf (buf ,sizeof (buf ),
1432- "array set %d $__PLTcl_Tup_%d\n" ,
1433- i + 1 ,i + 1 );
1434- Tcl_DStringAppend (& proc_internal_body ,buf ,-1 );
1435- }
1436- }
1437- }
1438- else
1486+ if (is_trigger )
14391487{
14401488Tcl_DStringAppend (& proc_internal_body ,
14411489"array set NEW $__PLTcl_Tup_NEW\n" ,-1 );
@@ -1451,6 +1499,23 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
14511499"}\n"
14521500"unset i v\n\n" ,-1 );
14531501}
1502+ else if (is_event_trigger )
1503+ {
1504+ /* no argument support for event triggers */
1505+ }
1506+ else
1507+ {
1508+ for (i = 0 ;i < prodesc -> nargs ;i ++ )
1509+ {
1510+ if (prodesc -> arg_is_rowtype [i ])
1511+ {
1512+ snprintf (buf ,sizeof (buf ),
1513+ "array set %d $__PLTcl_Tup_%d\n" ,
1514+ i + 1 ,i + 1 );
1515+ Tcl_DStringAppend (& proc_internal_body ,buf ,-1 );
1516+ }
1517+ }
1518+ }
14541519
14551520/************************************************************
14561521 * Add user's function definition to proc body