From 1e3e01f0e10cb88041b5e94351ddee122321195b Mon Sep 17 00:00:00 2001 From: Greg Nancarrow Date: Wed, 9 Dec 2020 20:57:45 +1100 Subject: [PATCH v1 1/2] Add new configuration parameter "disable_event_triggers". If an erroneous event trigger disables the database, this new GUC may be used as an alternative to using single-user mode, to disable all event triggers for those with superuser privileges or for those who own the database to which an event trigger belongs. Discussion: https://www.postgresql.org/message-id/flat/0d46d29f-4558-3af9-9c85-7774e14a7709%40postgrespro.ru --- doc/src/sgml/ref/create_event_trigger.sgml | 9 ++++++++- src/backend/commands/event_trigger.c | 19 +++++++++++++++++++ src/backend/utils/misc/guc.c | 11 +++++++++++ src/include/commands/event_trigger.h | 2 ++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/ref/create_event_trigger.sgml b/doc/src/sgml/ref/create_event_trigger.sgml index becd31b..09ed331 100644 --- a/doc/src/sgml/ref/create_event_trigger.sgml +++ b/doc/src/sgml/ref/create_event_trigger.sgml @@ -123,7 +123,14 @@ 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. As an alternative to + single-user mode, the configuration parameter + disable_event_triggers may be set to + true, to disable all event triggers for those with + superuser privileges or for those who own the database to which an + event trigger belongs. This global event trigger disabling mechanism is + completely separate to the individual enable/disable event trigger + mechanism provided by the ALTER EVENT TRIGGER command. diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 3ffba4e..d0dd4aa 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -48,6 +48,8 @@ #include "utils/rel.h" #include "utils/syscache.h" +bool disable_event_triggers; + typedef struct EventTriggerQueryState { /* memory context for this state's objects */ @@ -100,6 +102,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 inline bool EventTriggersDisabled(void); /* * Create an event trigger. @@ -596,6 +599,9 @@ EventTriggerCommonSetup(Node *parsetree, } #endif + if (EventTriggersDisabled()) + return NIL; + /* Use cache to find triggers for this event; fast exit if none. */ cachelist = EventCacheLookup(event); if (cachelist == NIL) @@ -635,6 +641,19 @@ EventTriggerCommonSetup(Node *parsetree, } /* + * Indicates whether all event triggers are currently disabled + * for the current user. + * Event triggers are disabled when configuration parameter + * "disable_event_triggers" is true, and the current user + * is the database owner or has superuser privileges. + */ +static inline bool +EventTriggersDisabled(void) +{ + return (disable_event_triggers && pg_database_ownercheck(MyDatabaseId, GetUserId())); +} + +/* * Fire ddl_command_start triggers. */ void diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index dabcbb0..ac247be 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -43,6 +43,7 @@ #include "commands/async.h" #include "commands/prepare.h" #include "commands/trigger.h" +#include "commands/event_trigger.h" #include "commands/user.h" #include "commands/vacuum.h" #include "commands/variable.h" @@ -928,6 +929,16 @@ static const unit_conversion time_unit_conversion_table[] = static struct config_bool ConfigureNamesBool[] = { { + {"disable_event_triggers", PGC_SU_BACKEND, DEVELOPER_OPTIONS, + gettext_noop("Disables all event triggers."), + gettext_noop("In case of errors in an EVENT TRIGGER procedure, this parameter can be used to disable trigger activation and provide access to the database."), + GUC_EXPLAIN + }, + &disable_event_triggers, + false, + NULL, NULL, NULL + }, + { {"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD, gettext_noop("Enables the planner's use of sequential-scan plans."), NULL, diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h index 407fd6a..c4940b8 100644 --- a/src/include/commands/event_trigger.h +++ b/src/include/commands/event_trigger.h @@ -21,6 +21,8 @@ #include "tcop/deparse_utility.h" #include "utils/aclchk_internal.h" +extern bool disable_event_triggers; /* GUC */ + typedef struct EventTriggerData { NodeTag type; -- 1.8.3.1