27
27
#include "access/xact.h"
28
28
#include "catalog/pg_proc.h"
29
29
#include "catalog/pg_type.h"
30
+ #include "commands/event_trigger.h"
30
31
#include "commands/trigger.h"
31
32
#include "executor/spi.h"
32
33
#include "fmgr.h"
@@ -200,11 +201,13 @@ static Datum pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted);
200
201
static Datum pltcl_func_handler (PG_FUNCTION_ARGS , bool pltrusted );
201
202
202
203
static HeapTuple pltcl_trigger_handler (PG_FUNCTION_ARGS , bool pltrusted );
204
+ static void pltcl_event_trigger_handler (PG_FUNCTION_ARGS , bool pltrusted );
203
205
204
206
static void throw_tcl_error (Tcl_Interp * interp , const char * proname );
205
207
206
208
static pltcl_proc_desc * compile_pltcl_function (Oid fn_oid , Oid tgreloid ,
207
- bool pltrusted );
209
+ bool is_event_trigger ,
210
+ bool pltrusted );
208
211
209
212
static int pltcl_elog (ClientData cdata , Tcl_Interp * interp ,
210
213
int argc , CONST84 char * argv []);
@@ -644,6 +647,12 @@ pltcl_handler(PG_FUNCTION_ARGS, bool pltrusted)
644
647
pltcl_current_fcinfo = NULL ;
645
648
retval = PointerGetDatum (pltcl_trigger_handler (fcinfo , pltrusted ));
646
649
}
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
+ }
647
656
else
648
657
{
649
658
pltcl_current_fcinfo = fcinfo ;
@@ -685,7 +694,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, bool pltrusted)
685
694
686
695
/* Find or compile the function */
687
696
prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid , InvalidOid ,
688
- pltrusted );
697
+ false, pltrusted );
689
698
690
699
pltcl_current_prodesc = prodesc ;
691
700
@@ -844,6 +853,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
844
853
/* Find or compile the function */
845
854
prodesc = compile_pltcl_function (fcinfo -> flinfo -> fn_oid ,
846
855
RelationGetRelid (trigdata -> tg_relation ),
856
+ false, /* not an event trigger */
847
857
pltrusted );
848
858
849
859
pltcl_current_prodesc = prodesc ;
@@ -1130,6 +1140,47 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
1130
1140
return rettup ;
1131
1141
}
1132
1142
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
+
1133
1184
1134
1185
/**********************************************************************
1135
1186
* throw_tcl_error - ereport an error returned from the Tcl interpreter
@@ -1168,7 +1219,8 @@ throw_tcl_error(Tcl_Interp *interp, const char *proname)
1168
1219
* (InvalidOid) when compiling a plain function.
1169
1220
**********************************************************************/
1170
1221
static 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 )
1172
1224
{
1173
1225
HeapTuple procTup ;
1174
1226
Form_pg_proc procStruct ;
@@ -1245,10 +1297,13 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1245
1297
* "_trigger" when appropriate to ensure the normal and trigger
1246
1298
* cases are kept separate.
1247
1299
************************************************************/
1248
- if (!is_trigger )
1300
+ if (!is_trigger && ! is_event_trigger )
1249
1301
snprintf (internal_proname , sizeof (internal_proname ),
1250
1302
"__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 )
1252
1307
snprintf (internal_proname , sizeof (internal_proname ),
1253
1308
"__PLTcl_proc_%u_trigger" , fn_oid );
1254
1309
@@ -1286,7 +1341,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1286
1341
* Get the required information for input conversion of the
1287
1342
* return value.
1288
1343
************************************************************/
1289
- if (!is_trigger )
1344
+ if (!is_trigger && ! is_event_trigger )
1290
1345
{
1291
1346
typeTup =
1292
1347
SearchSysCache1 (TYPEOID ,
@@ -1306,7 +1361,8 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1306
1361
{
1307
1362
if (procStruct -> prorettype == VOIDOID )
1308
1363
/* okay */ ;
1309
- else if (procStruct -> prorettype == TRIGGEROID )
1364
+ else if (procStruct -> prorettype == TRIGGEROID ||
1365
+ procStruct -> prorettype == EVTTRIGGEROID )
1310
1366
{
1311
1367
free (prodesc -> user_proname );
1312
1368
free (prodesc -> internal_proname );
@@ -1347,7 +1403,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1347
1403
* Get the required information for output conversion
1348
1404
* of all procedure arguments
1349
1405
************************************************************/
1350
- if (!is_trigger )
1406
+ if (!is_trigger && ! is_event_trigger )
1351
1407
{
1352
1408
prodesc -> nargs = procStruct -> pronargs ;
1353
1409
proc_internal_args [0 ] = '\0' ;
@@ -1397,12 +1453,17 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1397
1453
ReleaseSysCache (typeTup );
1398
1454
}
1399
1455
}
1400
- else
1456
+ else if ( is_trigger )
1401
1457
{
1402
1458
/* trigger procedure has fixed args */
1403
1459
strcpy (proc_internal_args ,
1404
1460
"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" );
1405
1461
}
1462
+ else if (is_event_trigger )
1463
+ {
1464
+ /* event trigger procedure has fixed args */
1465
+ strcpy (proc_internal_args , "TG_event TG_tag" );
1466
+ }
1406
1467
1407
1468
/************************************************************
1408
1469
* Create the tcl command to define the internal
@@ -1422,20 +1483,7 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1422
1483
Tcl_DStringAppend (& proc_internal_body , "upvar #0 " , -1 );
1423
1484
Tcl_DStringAppend (& proc_internal_body , internal_proname , -1 );
1424
1485
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 )
1439
1487
{
1440
1488
Tcl_DStringAppend (& proc_internal_body ,
1441
1489
"array set NEW $__PLTcl_Tup_NEW\n" , -1 );
@@ -1451,6 +1499,23 @@ compile_pltcl_function(Oid fn_oid, Oid tgreloid, bool pltrusted)
1451
1499
"}\n"
1452
1500
"unset i v\n\n" , -1 );
1453
1501
}
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
+ }
1454
1519
1455
1520
/************************************************************
1456
1521
* Add user's function definition to proc body
0 commit comments