2121#include "catalog/pg_language.h"
2222#include "catalog/pg_proc.h"
2323#include "catalog/pg_type.h"
24+ #include "commands/event_trigger.h"
2425#include "commands/trigger.h"
2526#include "executor/spi.h"
2627#include "funcapi.h"
@@ -254,10 +255,13 @@ static void set_interp_require(bool trusted);
254255
255256static Datum plperl_func_handler (PG_FUNCTION_ARGS );
256257static Datum plperl_trigger_handler (PG_FUNCTION_ARGS );
258+ static void plperl_event_trigger_handler (PG_FUNCTION_ARGS );
257259
258260static void free_plperl_function (plperl_proc_desc * prodesc );
259261
260- static plperl_proc_desc * compile_plperl_function (Oid fn_oid ,bool is_trigger );
262+ static plperl_proc_desc * compile_plperl_function (Oid fn_oid ,
263+ bool is_trigger ,
264+ bool is_event_trigger );
261265
262266static SV * plperl_hash_from_tuple (HeapTuple tuple ,TupleDesc tupdesc );
263267static SV * plperl_hash_from_datum (Datum attr );
@@ -1610,6 +1614,23 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo)
16101614}
16111615
16121616
1617+ /* Set up the arguments for an event trigger call. */
1618+ static SV *
1619+ plperl_event_trigger_build_args (FunctionCallInfo fcinfo )
1620+ {
1621+ EventTriggerData * tdata ;
1622+ HV * hv ;
1623+
1624+ hv = newHV ();
1625+
1626+ tdata = (EventTriggerData * )fcinfo -> context ;
1627+
1628+ hv_store_string (hv ,"event" ,cstr2sv (tdata -> event ));
1629+ hv_store_string (hv ,"tag" ,cstr2sv (tdata -> tag ));
1630+
1631+ return newRV_noinc ((SV * )hv );
1632+ }
1633+
16131634/* Set up the new tuple returned from a trigger. */
16141635
16151636static HeapTuple
@@ -1717,6 +1738,11 @@ plperl_call_handler(PG_FUNCTION_ARGS)
17171738current_call_data = & this_call_data ;
17181739if (CALLED_AS_TRIGGER (fcinfo ))
17191740retval = PointerGetDatum (plperl_trigger_handler (fcinfo ));
1741+ else if (CALLED_AS_EVENT_TRIGGER (fcinfo ))
1742+ {
1743+ plperl_event_trigger_handler (fcinfo );
1744+ retval = (Datum )0 ;
1745+ }
17201746else
17211747retval = plperl_func_handler (fcinfo );
17221748}
@@ -1853,7 +1879,8 @@ plperl_validator(PG_FUNCTION_ARGS)
18531879Oid * argtypes ;
18541880char * * argnames ;
18551881char * argmodes ;
1856- bool istrigger = false;
1882+ bool is_trigger = false;
1883+ bool is_event_trigger = false;
18571884int i ;
18581885
18591886/* Get the new function's pg_proc entry */
@@ -1865,13 +1892,15 @@ plperl_validator(PG_FUNCTION_ARGS)
18651892functyptype = get_typtype (proc -> prorettype );
18661893
18671894/* Disallow pseudotype result */
1868- /* except for TRIGGER, RECORD, or VOID */
1895+ /* except for TRIGGER,EVTTRIGGER, RECORD, or VOID */
18691896if (functyptype == TYPTYPE_PSEUDO )
18701897{
18711898/* we assume OPAQUE with no arguments means a trigger */
18721899if (proc -> prorettype == TRIGGEROID ||
18731900(proc -> prorettype == OPAQUEOID && proc -> pronargs == 0 ))
1874- istrigger = true;
1901+ is_trigger = true;
1902+ else if (proc -> prorettype == EVTTRIGGEROID )
1903+ is_event_trigger = true;
18751904else if (proc -> prorettype != RECORDOID &&
18761905proc -> prorettype != VOIDOID )
18771906ereport (ERROR ,
@@ -1898,7 +1927,7 @@ plperl_validator(PG_FUNCTION_ARGS)
18981927/* Postpone body checks if !check_function_bodies */
18991928if (check_function_bodies )
19001929{
1901- (void )compile_plperl_function (funcoid ,istrigger );
1930+ (void )compile_plperl_function (funcoid ,is_trigger , is_event_trigger );
19021931}
19031932
19041933/* the result of a validator is ignored */
@@ -2169,6 +2198,63 @@ plperl_call_perl_trigger_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo,
21692198}
21702199
21712200
2201+ static void
2202+ plperl_call_perl_event_trigger_func (plperl_proc_desc * desc ,
2203+ FunctionCallInfo fcinfo ,
2204+ SV * td )
2205+ {
2206+ dSP ;
2207+ SV * retval ,
2208+ * TDsv ;
2209+ int count ;
2210+
2211+ ENTER ;
2212+ SAVETMPS ;
2213+
2214+ TDsv = get_sv ("main::_TD" ,0 );
2215+ if (!TDsv )
2216+ elog (ERROR ,"couldn't fetch $_TD" );
2217+
2218+ save_item (TDsv );/* local $_TD */
2219+ sv_setsv (TDsv ,td );
2220+
2221+ PUSHMARK (sp );
2222+ PUTBACK ;
2223+
2224+ /* Do NOT use G_KEEPERR here */
2225+ count = perl_call_sv (desc -> reference ,G_SCALAR |G_EVAL );
2226+
2227+ SPAGAIN ;
2228+
2229+ if (count != 1 )
2230+ {
2231+ PUTBACK ;
2232+ FREETMPS ;
2233+ LEAVE ;
2234+ elog (ERROR ,"didn't get a return item from trigger function" );
2235+ }
2236+
2237+ if (SvTRUE (ERRSV ))
2238+ {
2239+ (void )POPs ;
2240+ PUTBACK ;
2241+ FREETMPS ;
2242+ LEAVE ;
2243+ /* XXX need to find a way to assign an errcode here */
2244+ ereport (ERROR ,
2245+ (errmsg ("%s" ,strip_trailing_ws (sv2cstr (ERRSV )))));
2246+ }
2247+
2248+ retval = newSVsv (POPs );
2249+ (void )retval ;/* silence compiler warning */
2250+
2251+ PUTBACK ;
2252+ FREETMPS ;
2253+ LEAVE ;
2254+
2255+ return ;
2256+ }
2257+
21722258static Datum
21732259plperl_func_handler (PG_FUNCTION_ARGS )
21742260{
@@ -2181,7 +2267,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
21812267if (SPI_connect ()!= SPI_OK_CONNECT )
21822268elog (ERROR ,"could not connect to SPI manager" );
21832269
2184- prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
2270+ prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false, false );
21852271current_call_data -> prodesc = prodesc ;
21862272increment_prodesc_refcount (prodesc );
21872273
@@ -2295,7 +2381,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22952381elog (ERROR ,"could not connect to SPI manager" );
22962382
22972383/* Find or compile the function */
2298- prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true);
2384+ prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true, false );
22992385current_call_data -> prodesc = prodesc ;
23002386increment_prodesc_refcount (prodesc );
23012387
@@ -2386,6 +2472,45 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
23862472}
23872473
23882474
2475+ static void
2476+ plperl_event_trigger_handler (PG_FUNCTION_ARGS )
2477+ {
2478+ plperl_proc_desc * prodesc ;
2479+ SV * svTD ;
2480+ ErrorContextCallback pl_error_context ;
2481+
2482+ /* Connect to SPI manager */
2483+ if (SPI_connect ()!= SPI_OK_CONNECT )
2484+ elog (ERROR ,"could not connect to SPI manager" );
2485+
2486+ /* Find or compile the function */
2487+ prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false, true);
2488+ current_call_data -> prodesc = prodesc ;
2489+ increment_prodesc_refcount (prodesc );
2490+
2491+ /* Set a callback for error reporting */
2492+ pl_error_context .callback = plperl_exec_callback ;
2493+ pl_error_context .previous = error_context_stack ;
2494+ pl_error_context .arg = prodesc -> proname ;
2495+ error_context_stack = & pl_error_context ;
2496+
2497+ activate_interpreter (prodesc -> interp );
2498+
2499+ svTD = plperl_event_trigger_build_args (fcinfo );
2500+ plperl_call_perl_event_trigger_func (prodesc ,fcinfo ,svTD );
2501+
2502+ if (SPI_finish ()!= SPI_OK_FINISH )
2503+ elog (ERROR ,"SPI_finish() failed" );
2504+
2505+ /* Restore the previous error callback */
2506+ error_context_stack = pl_error_context .previous ;
2507+
2508+ SvREFCNT_dec (svTD );
2509+
2510+ return ;
2511+ }
2512+
2513+
23892514static bool
23902515validate_plperl_function (plperl_proc_ptr * proc_ptr ,HeapTuple procTup )
23912516{
@@ -2437,7 +2562,7 @@ free_plperl_function(plperl_proc_desc *prodesc)
24372562
24382563
24392564static plperl_proc_desc *
2440- compile_plperl_function (Oid fn_oid ,bool is_trigger )
2565+ compile_plperl_function (Oid fn_oid ,bool is_trigger , bool is_event_trigger )
24412566{
24422567HeapTuple procTup ;
24432568Form_pg_proc procStruct ;
@@ -2543,7 +2668,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25432668 * Get the required information for input conversion of the
25442669 * return value.
25452670 ************************************************************/
2546- if (!is_trigger )
2671+ if (!is_trigger && ! is_event_trigger )
25472672{
25482673typeTup =
25492674SearchSysCache1 (TYPEOID ,
@@ -2562,7 +2687,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25622687if (procStruct -> prorettype == VOIDOID ||
25632688procStruct -> prorettype == RECORDOID )
25642689/* okay */ ;
2565- else if (procStruct -> prorettype == TRIGGEROID )
2690+ else if (procStruct -> prorettype == TRIGGEROID ||
2691+ procStruct -> prorettype == EVTTRIGGEROID )
25662692{
25672693free_plperl_function (prodesc );
25682694ereport (ERROR ,
@@ -2598,7 +2724,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25982724 * Get the required information for output conversion
25992725 * of all procedure arguments
26002726 ************************************************************/
2601- if (!is_trigger )
2727+ if (!is_trigger && ! is_event_trigger )
26022728{
26032729prodesc -> nargs = procStruct -> pronargs ;
26042730for (i = 0 ;i < prodesc -> nargs ;i ++ )