#include #include #include #include #include #include #include #include #include #include "postgres.h" #include "plpgsql.h" #include "miscadmin.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/explain.h" #include "executor/executor.h" #include "executor/instrument.h" #include "executor/spi.h" #include "nodes/params.h" #include "parser/parser.h" #include "parser/parse_target.h" #include "parser/parse_node.h" #include "utils/builtins.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/syscache.h" #include "utils/lsyscache.h" PG_MODULE_MAGIC; static MemoryContext MyMemoryContext = NULL; static needs_fmgr_hook_type prev_needs_fmgr_hook = NULL; static fmgr_hook_type prev_fmgr_hook = NULL; void _PG_fini(void); void _PG_init(void); static void do_stuff() { MemoryContext oldcxt; ResourceOwner oldowner = CurrentResourceOwner; oldcxt = MemoryContextSwitchTo(MyMemoryContext); BeginInternalSubTransaction(NULL); PG_TRY(); { elog(ERROR, "BIG LETTERS"); } PG_CATCH(); { ErrorData *edata; MemoryContextSwitchTo(MyMemoryContext); edata = CopyErrorData(); FlushErrorState(); RollbackAndReleaseCurrentSubTransaction(); MemoryContextSwitchTo(oldcxt); CurrentResourceOwner = oldowner; //SPI_restore_connection(); FreeErrorData(edata); } PG_END_TRY(); } static bool cleanup_test_needs_fmgr_hook(Oid functionId) { return true; } static void cleanup_test_fmgr_hook(FmgrHookEventType event, FmgrInfo *flinfo, Datum *args) { if (prev_fmgr_hook) (*prev_fmgr_hook) (event, flinfo, args); switch (event) { case FHET_START: do_stuff(); break; case FHET_ABORT: case FHET_END: break; default: elog(ERROR, "unknown FmgtHookEventType %d", event); } } void _PG_init(void) { MyMemoryContext = AllocSetContextCreate(TopTransactionContext, "mymemcxt", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); prev_needs_fmgr_hook = needs_fmgr_hook; needs_fmgr_hook = cleanup_test_needs_fmgr_hook; prev_fmgr_hook = fmgr_hook; fmgr_hook = cleanup_test_fmgr_hook; } void _PG_fini(void) { needs_fmgr_hook = prev_needs_fmgr_hook; prev_needs_fmgr_hook = NULL; fmgr_hook = prev_fmgr_hook; prev_fmgr_hook = NULL; MemoryContextDelete(MyMemoryContext); MyMemoryContext = NULL; }