3030#include "utils/lsyscache.h"
3131#include "utils/syscache.h"
3232
33+ /*
34+ * Hooks for function calls
35+ */
36+ PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL ;
37+ PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL ;
3338
3439/*
3540 * Declaration for old-style function pointer type. This is now used only
@@ -216,9 +221,9 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
216221 finfo -> fn_retset = procedureStruct -> proretset ;
217222
218223 /*
219- * If it has prosecdef set, or non-null proconfig, use
220- * fmgr_security_definer call handler --- unless we are being called again
221- * by fmgr_security_definer.
224+ * If it has prosecdef set, non-null proconfig, or if a plugin wants to
225+ * hook function entry/exit, use fmgr_security_definer call handler ---
226+ * unless we are being called again by fmgr_security_definer.
222227 *
223228 * When using fmgr_security_definer, function stats tracking is always
224229 * disabled at the outer level, and instead we set the flag properly in
@@ -230,7 +235,8 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt,
230235 */
231236 if (!ignore_security &&
232237 (procedureStruct -> prosecdef ||
233- !heap_attisnull (procedureTuple , Anum_pg_proc_proconfig )))
238+ !heap_attisnull (procedureTuple , Anum_pg_proc_proconfig ) ||
239+ FmgrHookIsNeeded (functionId )))
234240 {
235241 finfo -> fn_addr = fmgr_security_definer ;
236242 finfo -> fn_stats = TRACK_FUNC_ALL ; /* ie, never track */
@@ -857,17 +863,18 @@ struct fmgr_security_definer_cache
857863 FmgrInfo flinfo ; /* lookup info for target function */
858864 Oid userid ; /* userid to set, or InvalidOid */
859865 ArrayType * proconfig ; /* GUC values to set, or NULL */
866+ Datum private ; /* private usage for plugin modules */
860867};
861868
862869/*
863- * Function handler for security-definer/proconfig functions. We extract the
864- * OID of the actual function and do a fmgr lookup again. Then we fetch the
865- * pg_proc row and copy the owner ID and proconfig fields. (All this info
866- * is cached for the duration of the current query.) To execute a call,
867- * we temporarily replace the flinfo with the cached/looked-up one, while
868- * keeping the outer fcinfo (which contains all the actual arguments, etc.)
869- * intact. This is not re-entrant, but then the fcinfo itself can't be used
870- * re-entrantly anyway.
870+ * Function handler for security-definer/proconfig/plugin-hooked functions.
871+ * We extract the OID of the actual function and do a fmgr lookup again.
872+ * Then we fetch the pg_proc row and copy the owner ID and proconfig fields.
873+ * (All this info is cached for the duration of the current query.)
874+ * To execute a call, we temporarily replace the flinfo with the cached
875+ * and looked-up one, while keeping the outer fcinfo (which contains all
876+ * the actual arguments, etc.) intact. This is not re-entrant, but then
877+ * the fcinfo itself can't be used re-entrantly anyway.
871878 */
872879static Datum
873880fmgr_security_definer (PG_FUNCTION_ARGS )
@@ -940,6 +947,10 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
940947 GUC_ACTION_SAVE );
941948 }
942949
950+ /* function manager hook */
951+ if (fmgr_hook )
952+ (* fmgr_hook )(FHET_START , & fcache -> flinfo , & fcache -> private );
953+
943954 /*
944955 * We don't need to restore GUC or userid settings on error, because the
945956 * ensuing xact or subxact abort will do that. The PG_TRY block is only
@@ -968,6 +979,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
968979 PG_CATCH ();
969980 {
970981 fcinfo -> flinfo = save_flinfo ;
982+ if (fmgr_hook )
983+ (* fmgr_hook )(FHET_ABORT , & fcache -> flinfo , & fcache -> private );
971984 PG_RE_THROW ();
972985 }
973986 PG_END_TRY ();
@@ -978,6 +991,8 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
978991 AtEOXact_GUC (true, save_nestlevel );
979992 if (OidIsValid (fcache -> userid ))
980993 SetUserIdAndSecContext (save_userid , save_sec_context );
994+ if (fmgr_hook )
995+ (* fmgr_hook )(FHET_END , & fcache -> flinfo , & fcache -> private );
981996
982997 return result ;
983998}
0 commit comments