From 9668f9e4f0882abe343c8cb4df944ff3da3a1031 Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Mon, 14 Mar 2022 14:24:09 +0100 Subject: [PATCH v27 1/2] Provide a GUC for temporarily ignoring event triggers In order to allow troubleshooting and repair without the need for restarting in single-user mode, allow to ignore event triggers per session. --- doc/src/sgml/config.sgml | 15 ++++++++ doc/src/sgml/ref/create_event_trigger.sgml | 4 ++- src/backend/commands/event_trigger.c | 40 ++++++++++++++++++---- src/backend/utils/misc/guc.c | 17 +++++++++ src/include/commands/event_trigger.h | 8 +++++ 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 7a48973b3c..54e86ba3de 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -9195,6 +9195,21 @@ SET XML OPTION { DOCUMENT | CONTENT }; + + ignore_event_trigger (enum) + + ignore_event_trigger + configuration parameter + + + + + Allows to temporarily disable event triggers from executing in order + to troubleshoot and repair faulty event triggers. + + + + diff --git a/doc/src/sgml/ref/create_event_trigger.sgml b/doc/src/sgml/ref/create_event_trigger.sgml index 22c8119198..1a78555c64 100644 --- a/doc/src/sgml/ref/create_event_trigger.sgml +++ b/doc/src/sgml/ref/create_event_trigger.sgml @@ -123,7 +123,9 @@ CREATE EVENT TRIGGER name Event triggers are disabled in single-user mode (see ). If an erroneous event trigger disables the database so much that you can't even drop the trigger, restart in - single-user mode and you'll be able to do that. + single-user mode and you'll be able to do that. Even triggers can also be + temporarily disabled for such troubleshooting, see + . diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 3c3fc2515b..70995cfc49 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -72,6 +72,9 @@ typedef struct EventTriggerQueryState static EventTriggerQueryState *currentEventTriggerState = NULL; +/* GUC parameter */ +int ignore_event_trigger = IGNORE_EVENT_TRIGGER_NONE; + /* Support for dropped objects */ typedef struct SQLDropObject { @@ -100,6 +103,7 @@ static void validate_table_rewrite_tags(const char *filtervar, List *taglist); static void EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata); static const char *stringify_grant_objtype(ObjectType objtype); static const char *stringify_adefprivs_objtype(ObjectType objtype); +static bool ignore_event_trigger_check(EventTriggerEvent event); /* * Create an event trigger. @@ -658,8 +662,11 @@ EventTriggerDDLCommandStart(Node *parsetree) * wherein event triggers are disabled. (Or we could implement * heapscan-and-sort logic for that case, but having disaster recovery * scenarios depend on code that's otherwise untested isn't appetizing.) + * + * Additionally, event triggers can be disabled with a superuser only GUC + * to make fixing database easier as per 1 above. */ - if (!IsUnderPostmaster) + if (!IsUnderPostmaster || ignore_event_trigger_check(EVT_DDLCommandStart)) return; runlist = EventTriggerCommonSetup(parsetree, @@ -693,9 +700,9 @@ EventTriggerDDLCommandEnd(Node *parsetree) /* * See EventTriggerDDLCommandStart for a discussion about why event - * triggers are disabled in single user mode. + * triggers are disabled in single user mode or via GUC. */ - if (!IsUnderPostmaster) + if (!IsUnderPostmaster || ignore_event_trigger_check(EVT_DDLCommandEnd)) return; /* @@ -741,9 +748,9 @@ EventTriggerSQLDrop(Node *parsetree) /* * See EventTriggerDDLCommandStart for a discussion about why event - * triggers are disabled in single user mode. + * triggers are disabled in single user mode or via a GUC. */ - if (!IsUnderPostmaster) + if (!IsUnderPostmaster || ignore_event_trigger_check(EVT_SQLDrop)) return; /* @@ -812,9 +819,9 @@ EventTriggerTableRewrite(Node *parsetree, Oid tableOid, int reason) /* * See EventTriggerDDLCommandStart for a discussion about why event - * triggers are disabled in single user mode. + * triggers are disabled in single user mode or via a GUC. */ - if (!IsUnderPostmaster) + if (!IsUnderPostmaster || ignore_event_trigger_check(EVT_TableRewrite)) return; /* @@ -2175,3 +2182,22 @@ stringify_adefprivs_objtype(ObjectType objtype) return "???"; /* keep compiler quiet */ } + + +/* + * Checks whether the specified event is ignored by the ignore_event_trigger + * GUC or not. Currently, the GUC only supports ignoreing all or nothing but + * that will most likely change so the function takes an event to aid that. + */ +static bool +ignore_event_trigger_check(EventTriggerEvent event) +{ + (void) event; /* unused parameter */ + + if (ignore_event_trigger == IGNORE_EVENT_TRIGGER_ALL) + return true; + + /* IGNORE_EVENT_TRIGGER_NONE */ + return false; + +} diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index e7f0a380e6..088c4690d9 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -46,6 +46,7 @@ #include "catalog/pg_authid.h" #include "catalog/storage.h" #include "commands/async.h" +#include "commands/event_trigger.h" #include "commands/prepare.h" #include "commands/tablespace.h" #include "commands/trigger.h" @@ -565,6 +566,12 @@ static const struct config_enum_entry wal_compression_options[] = { {NULL, 0, false} }; +static const struct config_enum_entry ignore_event_trigger_options[] = { + {"none", IGNORE_EVENT_TRIGGER_NONE, false}, + {"all", IGNORE_EVENT_TRIGGER_ALL, false}, + {NULL, 0, false} +}; + /* * Options for enum values stored in other modules */ @@ -4904,6 +4911,16 @@ static struct config_enum ConfigureNamesEnum[] = NULL, NULL, NULL }, + { + {"ignore_event_trigger", PGC_SUSET, CLIENT_CONN_STATEMENT, + gettext_noop("Disable event triggers during the session."), + NULL + }, + &ignore_event_trigger, + IGNORE_EVENT_TRIGGER_NONE, ignore_event_trigger_options, + NULL, NULL, NULL + }, + { {"wal_level", PGC_POSTMASTER, WAL_SETTINGS, gettext_noop("Sets the level of information written to the WAL."), diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index 10091c3aaf..9e7671e63f 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -29,6 +29,14 @@ typedef struct EventTriggerData CommandTag tag; } EventTriggerData; +typedef enum ignore_event_trigger_events +{ + IGNORE_EVENT_TRIGGER_NONE, + IGNORE_EVENT_TRIGGER_ALL +} IgnoreEventTriggersEvents; + +extern int ignore_event_trigger; + #define AT_REWRITE_ALTER_PERSISTENCE 0x01 #define AT_REWRITE_DEFAULT_VAL 0x02 #define AT_REWRITE_COLUMN_REWRITE 0x04 -- 2.24.3 (Apple Git-128)