v6-0001-Add-GUC-for-temporarily-disabling-event-triggers.patch
application/octet-stream
Filename: v6-0001-Add-GUC-for-temporarily-disabling-event-triggers.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v6-0001
Subject: Add GUC for temporarily disabling event triggers
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 19 | 0 |
| doc/src/sgml/ref/create_event_trigger.sgml | 3 | 1 |
| src/backend/commands/event_trigger.c | 13 | 7 |
| src/backend/utils/misc/guc_tables.c | 12 | 0 |
| src/include/commands/event_trigger.h | 2 | 0 |
| src/test/regress/expected/event_trigger.out | 22 | 0 |
| src/test/regress/sql/event_trigger.sql | 24 | 0 |
From 004a2f0753877ab93b149ea38c1c0ed0661b1f2e Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <dgustafsson@postgresql.org>
Date: Tue, 5 Sep 2023 13:39:42 +0200
Subject: [PATCH v6] Add GUC for temporarily disabling event triggers
In order to troubleshoot misbehaving or buggy event triggers, the
documented advice is to enter single-user mode. In an attempt to
reduce the number of situations where single-user mode is required
for non-extraordinary maintenance, this GUC allows to temporarily
suspend event triggers.
This was originally extracted from a larger patchset which aimed
at supporting event triggers on login events.
Reviewed-by: Ted Yu <yuzhihong@gmail.com>
Reviewed-by: Mikhail Gribkov <youzhick@gmail.com>
Reviewed-by: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz
Discussion: https://postgr.es/m/9140106E-F9BF-4D85-8FC8-F2D3C094A6D9@yesql.se
---
doc/src/sgml/config.sgml | 19 ++++++++++++++++
doc/src/sgml/ref/create_event_trigger.sgml | 4 +++-
src/backend/commands/event_trigger.c | 20 +++++++++++------
src/backend/utils/misc/guc_tables.c | 12 +++++++++++
src/include/commands/event_trigger.h | 2 ++
src/test/regress/expected/event_trigger.out | 22 +++++++++++++++++++
src/test/regress/sql/event_trigger.sql | 24 +++++++++++++++++++++
7 files changed, 95 insertions(+), 8 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 694d667bf9..988494fafa 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -9494,6 +9494,25 @@ SET XML OPTION { DOCUMENT | CONTENT };
</listitem>
</varlistentry>
+ <varlistentry id="guc-ignore-event-trigger" xreflabel="debug_event_trigger">
+ <term><varname>debug_event_trigger</varname> (<type>boolean</type>)
+ <indexterm>
+ <primary><varname>debug_event_trigger</varname></primary>
+ <secondary>configuration parameter</secondary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Allow temporarily disabling execution of event triggers in order to
+ troubleshoot and repair faulty event triggers. All event triggers will
+ be disabled by setting it to <literal>true</literal>. Setting the value
+ to <literal>false</literal> will not disable any event triggers, this
+ is the default value. Only superusers and users with the appropriate
+ <literal>SET</literal> privilege can change this setting.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect2>
<sect2 id="runtime-config-client-format">
diff --git a/doc/src/sgml/ref/create_event_trigger.sgml b/doc/src/sgml/ref/create_event_trigger.sgml
index 22c8119198..40ca5fe6fd 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 <replaceable class="parameter">name</replaceable>
Event triggers are disabled in single-user mode (see <xref
linkend="app-postgres"/>). 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. Event triggers can also be
+ temporarily disabled for such troubleshooting, see
+ <xref linkend="guc-debug-event-trigger"/>.
</para>
</refsect1>
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index d4b00d1a82..bb1375c3f7 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 */
+bool debug_event_trigger = false;
+
/* Support for dropped objects */
typedef struct SQLDropObject
{
@@ -657,8 +660,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 || debug_event_trigger)
return;
runlist = EventTriggerCommonSetup(parsetree,
@@ -692,9 +698,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 || debug_event_trigger)
return;
/*
@@ -740,9 +746,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 || debug_event_trigger)
return;
/*
@@ -811,9 +817,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 || debug_event_trigger)
return;
/*
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index e565a3092f..bafb1aef88 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -37,6 +37,7 @@
#include "catalog/namespace.h"
#include "catalog/storage.h"
#include "commands/async.h"
+#include "commands/event_trigger.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/user.h"
@@ -1999,6 +2000,17 @@ struct config_bool ConfigureNamesBool[] =
NULL, NULL, NULL
},
+ {
+ {"debug_event_trigger", PGC_SUSET, CLIENT_CONN_STATEMENT,
+ gettext_noop("Enables event triggers."),
+ NULL,
+ GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
+ },
+ &debug_event_trigger,
+ false,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 5ed6ece555..3fd27489aa 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -29,6 +29,8 @@ typedef struct EventTriggerData
CommandTag tag;
} EventTriggerData;
+extern PGDLLIMPORT bool debug_event_trigger;
+
#define AT_REWRITE_ALTER_PERSISTENCE 0x01
#define AT_REWRITE_DEFAULT_VAL 0x02
#define AT_REWRITE_COLUMN_REWRITE 0x04
diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out
index 2c8a6b2212..81b000f5d4 100644
--- a/src/test/regress/expected/event_trigger.out
+++ b/src/test/regress/expected/event_trigger.out
@@ -616,3 +616,25 @@ SELECT
DROP EVENT TRIGGER start_rls_command;
DROP EVENT TRIGGER end_rls_command;
DROP EVENT TRIGGER sql_drop_command;
+-- Check the GUC for disabling event triggers
+CREATE FUNCTION test_event_trigger_guc() RETURNS event_trigger
+LANGUAGE plpgsql AS $$
+DECLARE
+ obj record;
+BEGIN
+ FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
+ LOOP
+ RAISE NOTICE '% dropped %', tg_tag, obj.object_type;
+ END LOOP;
+END;
+$$;
+CREATE EVENT TRIGGER test_event_trigger_guc
+ ON sql_drop
+ WHEN TAG IN ('DROP POLICY') EXECUTE FUNCTION test_event_trigger_guc();
+SET debug_event_trigger = 'false';
+CREATE POLICY pguc ON event_trigger_test USING (FALSE);
+DROP POLICY pguc ON event_trigger_test;
+NOTICE: DROP POLICY dropped policy
+CREATE POLICY pguc ON event_trigger_test USING (FALSE);
+SET debug_event_trigger = 'true';
+DROP POLICY pguc ON event_trigger_test;
diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql
index 1aeaddbe71..abfce0c7b4 100644
--- a/src/test/regress/sql/event_trigger.sql
+++ b/src/test/regress/sql/event_trigger.sql
@@ -471,3 +471,27 @@ SELECT
DROP EVENT TRIGGER start_rls_command;
DROP EVENT TRIGGER end_rls_command;
DROP EVENT TRIGGER sql_drop_command;
+
+-- Check the GUC for disabling event triggers
+CREATE FUNCTION test_event_trigger_guc() RETURNS event_trigger
+LANGUAGE plpgsql AS $$
+DECLARE
+ obj record;
+BEGIN
+ FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
+ LOOP
+ RAISE NOTICE '% dropped %', tg_tag, obj.object_type;
+ END LOOP;
+END;
+$$;
+CREATE EVENT TRIGGER test_event_trigger_guc
+ ON sql_drop
+ WHEN TAG IN ('DROP POLICY') EXECUTE FUNCTION test_event_trigger_guc();
+
+SET debug_event_trigger = 'false';
+CREATE POLICY pguc ON event_trigger_test USING (FALSE);
+DROP POLICY pguc ON event_trigger_test;
+
+CREATE POLICY pguc ON event_trigger_test USING (FALSE);
+SET debug_event_trigger = 'true';
+DROP POLICY pguc ON event_trigger_test;
--
2.32.1 (Apple Git-133)