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 ,
210213 int argc , CONST84 char * argv []);
@@ -644,6 +647,12 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
644647 pltcl_current_fcinfo = NULL ;
645648 retval = 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+ }
647656 else
648657 {
649658 pltcl_current_fcinfo = fcinfo ;
@@ -685,7 +694,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, bool pltrusted)
685694
686695 /* Find or compile the function */
687696 prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid , InvalidOid ,
688- pltrusted );
697+ false, pltrusted );
689698
690699 pltcl_current_prodesc = prodesc ;
691700
@@ -844,6 +853,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
844853 /* Find or compile the function */
845854 prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid ,
846855 RelationGetRelid (trigdata -> tg_relation ),
856+ false, /* not an event trigger */
847857 pltrusted );
848858
849859 pltcl_current_prodesc = prodesc ;
@@ -1130,6 +1140,47 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
11301140 return 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{
11731225 HeapTuple procTup ;
11741226 Form_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 )
12491301 snprintf (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 )
12521307 snprintf (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 {
12911346 typeTup =
12921347 SearchSysCache1 (TYPEOID ,
@@ -1306,7 +1361,8 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
13061361 {
13071362 if (procStruct -> prorettype == VOIDOID )
13081363 /* okay */ ;
1309- else if (procStruct -> prorettype == TRIGGEROID )
1364+ else if (procStruct -> prorettype == TRIGGEROID ||
1365+ procStruct -> prorettype == EVTTRIGGEROID )
13101366 {
13111367 free (prodesc -> user_proname );
13121368 free (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 {
13521408 prodesc -> nargs = procStruct -> pronargs ;
13531409 proc_internal_args [0 ] = '\0' ;
@@ -1397,12 +1453,17 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
13971453 ReleaseSysCache (typeTup );
13981454 }
13991455 }
1400- else
1456+ else if ( is_trigger )
14011457 {
14021458 /* trigger procedure has fixed args */
14031459 strcpy (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)
14221483 Tcl_DStringAppend (& proc_internal_body , "upvar #0 " , -1 );
14231484 Tcl_DStringAppend (& proc_internal_body , internal_proname , -1 );
14241485 Tcl_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 {
14401488 Tcl_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
0 commit comments