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)
17171738 current_call_data = & this_call_data ;
17181739 if (CALLED_AS_TRIGGER (fcinfo ))
17191740 retval = 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+ }
17201746 else
17211747 retval = plperl_func_handler (fcinfo );
17221748 }
@@ -1853,7 +1879,8 @@ plperl_validator(PG_FUNCTION_ARGS)
18531879 Oid * argtypes ;
18541880 char * * argnames ;
18551881 char * argmodes ;
1856- bool istrigger = false;
1882+ bool is_trigger = false;
1883+ bool is_event_trigger = false;
18571884 int i ;
18581885
18591886 /* Get the new function's pg_proc entry */
@@ -1865,13 +1892,15 @@ plperl_validator(PG_FUNCTION_ARGS)
18651892 functyptype = get_typtype (proc -> prorettype );
18661893
18671894 /* Disallow pseudotype result */
1868- /* except for TRIGGER, RECORD, or VOID */
1895+ /* except for TRIGGER, EVTTRIGGER, RECORD, or VOID */
18691896 if (functyptype == TYPTYPE_PSEUDO )
18701897 {
18711898 /* we assume OPAQUE with no arguments means a trigger */
18721899 if (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;
18751904 else if (proc -> prorettype != RECORDOID &&
18761905 proc -> prorettype != VOIDOID )
18771906 ereport (ERROR ,
@@ -1898,7 +1927,7 @@ plperl_validator(PG_FUNCTION_ARGS)
18981927 /* Postpone body checks if !check_function_bodies */
18991928 if (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)
21812267 if (SPI_connect () != SPI_OK_CONNECT )
21822268 elog (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 );
21852271 current_call_data -> prodesc = prodesc ;
21862272 increment_prodesc_refcount (prodesc );
21872273
@@ -2295,7 +2381,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22952381 elog (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 );
22992385 current_call_data -> prodesc = prodesc ;
23002386 increment_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{
24422567 HeapTuple procTup ;
24432568 Form_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 {
25482673 typeTup =
25492674 SearchSysCache1 (TYPEOID ,
@@ -2562,7 +2687,8 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25622687 if (procStruct -> prorettype == VOIDOID ||
25632688 procStruct -> prorettype == RECORDOID )
25642689 /* okay */ ;
2565- else if (procStruct -> prorettype == TRIGGEROID )
2690+ else if (procStruct -> prorettype == TRIGGEROID ||
2691+ procStruct -> prorettype == EVTTRIGGEROID )
25662692 {
25672693 free_plperl_function (prodesc );
25682694 ereport (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 {
26032729 prodesc -> nargs = procStruct -> pronargs ;
26042730 for (i = 0 ; i < prodesc -> nargs ; i ++ )
0 commit comments