[PATCH] Add pg_get_event_trigger_ddl() function

Started by Ian Lawrence Barwick8 days ago12 messageshackers
Jump to latest
#1Ian Lawrence Barwick
barwick@gmail.com

Hi

Attached is a patch implementing a function to generate the DDL for a CREATE
EVENT TRIGGER statement. This complements existing similar functions
(pg_get_database_ddl(), pg_get_role_ddl() etc.).

Patch includes regression test and documentation.

Example:

CREATE OR REPLACE FUNCTION forbid_table_rewrites()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION 'command % prohibited', tg_tag;
END;
$$;

CREATE EVENT TRIGGER forbid_rewrites
ON table_rewrite
WHEN tag IN ('ALTER TABLE', 'ALTER MATERIALIZED VIEW')
EXECUTE FUNCTION forbid_table_rewrites();

SELECT pg_get_event_trigger_ddl('forbid_rewrites');

postgres=# SELECT pg_get_event_trigger_ddl('forbid_rewrites',true);
pg_get_event_trigger_ddl
------------------------------------------------------------
CREATE EVENT TRIGGER forbid_rewrites +
ON table_rewrite +
WHEN TAG IN ('ALTER TABLE', 'ALTER MATERIALIZED VIEW')+
EXECUTE FUNCTION public.forbid_table_rewrites();
(1 row)

Regards

Ian Barwick

Attachments:

v1-0001-Add-pg_get_event_trigger_ddl-function.patchapplication/octet-stream; name=v1-0001-Add-pg_get_event_trigger_ddl-function.patchDownload+176-1
#2Zsolt Parragi
zsolt.parragi@percona.com
In reply to: Ian Lawrence Barwick (#1)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

Hello!

Should the function preserve the disabled state of an event trigger?

CREATE FUNCTION noop_evt() RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
END;
$$;
CREATE EVENT TRIGGER my_evt ON ddl_command_start EXECUTE FUNCTION noop_evt();
ALTER EVENT TRIGGER my_evt DISABLE;
SELECT pg_get_event_trigger_ddl('my_evt', false);

also REPLICA:

ALTER EVENT TRIGGER my_evt ENABLE REPLICA;
SELECT pg_get_event_trigger_ddl('my_evt', false);

and OWNER:

CREATE ROLE evt_owner_role SUPERUSER;
ALTER EVENT TRIGGER my_evt OWNER TO evt_owner_role;
SELECT pg_get_event_trigger_ddl('my_evt');

+				appendStringInfoString(&filters, ", ");
+
+			appendStringInfo(&filters, "'%s'", str);

Shouldn't this use quote_literal_cstr?

#3Ian Lawrence Barwick
barwick@gmail.com
In reply to: Zsolt Parragi (#2)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

2026年7月18日(土) 6:26 Zsolt Parragi <zsolt.parragi@percona.com>:

Hello!

Thanks for the review!

Should the function preserve the disabled state of an event trigger?

CREATE FUNCTION noop_evt() RETURNS event_trigger LANGUAGE plpgsql AS $$
BEGIN
END;
$$;
CREATE EVENT TRIGGER my_evt ON ddl_command_start EXECUTE FUNCTION

noop_evt();

ALTER EVENT TRIGGER my_evt DISABLE;
SELECT pg_get_event_trigger_ddl('my_evt', false);

also REPLICA:

ALTER EVENT TRIGGER my_evt ENABLE REPLICA;
SELECT pg_get_event_trigger_ddl('my_evt', false);

and OWNER:

CREATE ROLE evt_owner_role SUPERUSER;
ALTER EVENT TRIGGER my_evt OWNER TO evt_owner_role;
SELECT pg_get_event_trigger_ddl('my_evt');

Correct.

+                               appendStringInfoString(&filters, ", ");
+
+                       appendStringInfo(&filters, "'%s'", str);

Shouldn't this use quote_literal_cstr?

Arguably it wouldn't strictly need to, as we'd only ever get plain ASCII
command tags here,
but it's not a critical performance choke point or anything, so might as
well use it to be
on the safe side.

Updated patch version attached.

Regards

Ian Barwick

Attachments:

v2-0001-Add-pg_get_event_trigger_ddl-function.patchtext/x-patch; charset=US-ASCII; name=v2-0001-Add-pg_get_event_trigger_ddl-function.patchDownload+332-2
#4Jim Jones
jim.jones@uni-muenster.de
In reply to: Zsolt Parragi (#2)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

Hi Ian

Thanks for the patch! Here a few comments on v2:

== shadow variable ==

The function pg_get_event_trigger_ddl_internal has a bool parameter
named owner, and its body has a char* with the same name.

== trailing XXX (placeholder?) ==

+ * CREATE EVENT TRIGGER statement; XXX

== typo (2x the) ==

+ is false, the the corresponding <literal>ENABLE</literal> clause is

=== switch without default ==

I realise that "switch (evtForm->evtenabled)" already tests all possible
values of evtenable, but I'm wondering if we really should let it
silently finish the buffer like "ALTER EVENT TRIGGER foo ;" if evtenable
ever gets a different value. I'd argue that an error message would be
better than a malformed DDL. What do you think?

Best, Jim

#5Ian Lawrence Barwick
barwick@gmail.com
In reply to: Jim Jones (#4)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

Hi Jim

2026年7月21日(火) 0:13 Jim Jones <jim.jones@uni-muenster.de>:

Hi Ian

Thanks for the patch! Here a few comments on v2:

== shadow variable ==

The function pg_get_event_trigger_ddl_internal has a bool parameter
named owner, and its body has a char* with the same name.

Good catch - I note the compiler-level shadow check is only effective
for variables of the same type, which hadn't occurred to me before.

== trailing XXX (placeholder?) ==

+ * CREATE EVENT TRIGGER statement; XXX

Whoops, fixed.

== typo (2x the) ==

+ is false, the the corresponding <literal>ENABLE</literal> clause is

Classic typo invisible to the author, fixed.

=== switch without default ==

I realise that "switch (evtForm->evtenabled)" already tests all possible
values of evtenable, but I'm wondering if we really should let it
silently finish the buffer like "ALTER EVENT TRIGGER foo ;" if evtenable
ever gets a different value. I'd argue that an error message would be
better than a malformed DDL. What do you think?

I did wonder - the corresponding switch statement in pg_dump falls through to
"ENABLE" as the default value, but only calls that if "evtenabled" is
not 'O' (the
default), so the addition of some new trigger firing state would result
in "ALTER EVENT TRIGGER foo ENABLE;" if the code was not updated,
which is easy to overlook with this kind of setup. On the other hand, I can't
imagine what kind of new trigger firing state might be added, so maybe
it's more of a theoretical risk. In any case I added an error message, and
also updated the tests to check each existing firing state is
correctly rendered.

While looking at that, I did update the comment in
"src/include/commands/trigger.h"
to note that the "TRIGGER_*" definitions also apply to pg_event_trigger.

Regards

Ian Barwick

Attachments:

v3-0001-Add-pg_get_event_trigger_ddl-function.patchtext/x-patch; charset=US-ASCII; name=v3-0001-Add-pg_get_event_trigger_ddl-function.patchDownload+377-3
#6Rithvika Devisetti
devisettirithvika@gmail.com
In reply to: Ian Lawrence Barwick (#5)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

Hi,

On Mon, Jul 20, 2026 at 6:49 PM Ian Lawrence Barwick <barwick@gmail.com>
wrote:

Hi Jim

2026年7月21日(火) 0:13 Jim Jones <jim.jones@uni-muenster.de>:

Hi Ian

Thanks for the patch! Here a few comments on v2:

== shadow variable ==

The function pg_get_event_trigger_ddl_internal has a bool parameter
named owner, and its body has a char* with the same name.

Good catch - I note the compiler-level shadow check is only effective
for variables of the same type, which hadn't occurred to me before.

== trailing XXX (placeholder?) ==

+ * CREATE EVENT TRIGGER statement; XXX

Whoops, fixed.

== typo (2x the) ==

+ is false, the the corresponding <literal>ENABLE</literal> clause is

Classic typo invisible to the author, fixed.

=== switch without default ==

I realise that "switch (evtForm->evtenabled)" already tests all possible
values of evtenable, but I'm wondering if we really should let it
silently finish the buffer like "ALTER EVENT TRIGGER foo ;" if evtenable
ever gets a different value. I'd argue that an error message would be
better than a malformed DDL. What do you think?

I did wonder - the corresponding switch statement in pg_dump falls through
to
"ENABLE" as the default value, but only calls that if "evtenabled" is
not 'O' (the
default), so the addition of some new trigger firing state would result
in "ALTER EVENT TRIGGER foo ENABLE;" if the code was not updated,
which is easy to overlook with this kind of setup. On the other hand, I
can't
imagine what kind of new trigger firing state might be added, so maybe
it's more of a theoretical risk. In any case I added an error message, and
also updated the tests to check each existing firing state is
correctly rendered.

While looking at that, I did update the comment in

"src/include/commands/trigger.h"
to note that the "TRIGGER_*" definitions also apply to pg_event_trigger.

Patch applies clean to me, and tests passed. I see a grammatical typo below,
there is an additional "be".

cannot be actually be used in a valid statement

Thanks,

Rithvika

#7Ian Lawrence Barwick
barwick@gmail.com
In reply to: Rithvika Devisetti (#6)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

2026年7月21日(火) 12:38 Rithvika Devisetti <devisettirithvika@gmail.com>:

Hi,

On Mon, Jul 20, 2026 at 6:49 PM Ian Lawrence Barwick <barwick@gmail.com> wrote:

Hi Jim

2026年7月21日(火) 0:13 Jim Jones <jim.jones@uni-muenster.de>:

Hi Ian

Thanks for the patch! Here a few comments on v2:

== shadow variable ==

The function pg_get_event_trigger_ddl_internal has a bool parameter
named owner, and its body has a char* with the same name.

Good catch - I note the compiler-level shadow check is only effective
for variables of the same type, which hadn't occurred to me before.

== trailing XXX (placeholder?) ==

+ * CREATE EVENT TRIGGER statement; XXX

Whoops, fixed.

== typo (2x the) ==

+ is false, the the corresponding <literal>ENABLE</literal> clause is

Classic typo invisible to the author, fixed.

=== switch without default ==

I realise that "switch (evtForm->evtenabled)" already tests all possible
values of evtenable, but I'm wondering if we really should let it
silently finish the buffer like "ALTER EVENT TRIGGER foo ;" if evtenable
ever gets a different value. I'd argue that an error message would be
better than a malformed DDL. What do you think?

I did wonder - the corresponding switch statement in pg_dump falls through to
"ENABLE" as the default value, but only calls that if "evtenabled" is
not 'O' (the
default), so the addition of some new trigger firing state would result
in "ALTER EVENT TRIGGER foo ENABLE;" if the code was not updated,
which is easy to overlook with this kind of setup. On the other hand, I can't
imagine what kind of new trigger firing state might be added, so maybe
it's more of a theoretical risk. In any case I added an error message, and
also updated the tests to check each existing firing state is
correctly rendered.

While looking at that, I did update the comment in
"src/include/commands/trigger.h"
to note that the "TRIGGER_*" definitions also apply to pg_event_trigger.

Patch applies clean to me, and tests passed. I see a grammatical typo below,
there is an additional "be".

cannot be actually be used in a valid statement

Thanks for checking! Revised version attached, with that and a couple of
minor text tweaks.

Regards

Ian Barwick

Attachments:

v4-0001-Add-pg_get_event_trigger_ddl-function.patchtext/x-patch; charset=US-ASCII; name=v4-0001-Add-pg_get_event_trigger_ddl-function.patchDownload+376-3
#8Zsolt Parragi
zsolt.parragi@percona.com
In reply to: Ian Lawrence Barwick (#7)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

v4 looks good to me, I only have one nitpick question:

+        <optional>, <parameter>enable</parameter> <type>boolean</type>
+        <literal>DEFAULT</literal> true</optional> )

Shouldn't we call this something different, for example enabled?

#9Ian Lawrence Barwick
barwick@gmail.com
In reply to: Zsolt Parragi (#8)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

2026年7月22日(水) 4:53 Zsolt Parragi <zsolt.parragi@percona.com>:

v4 looks good to me, I only have one nitpick question:

+        <optional>, <parameter>enable</parameter> <type>boolean</type>
+        <literal>DEFAULT</literal> true</optional> )

Shouldn't we call this something different, for example enabled?

That did cross my mind, but while "enabled" feels more natural grammatically,
"enable" corresponds to the "ENABLE" clause which is to be emitted (or omitted).
Except when it's "DISABLE"... I can't think of any better phrasing
which is reasonably
short and conveys the meaning "emit the clause which indicates the trigger is to
be disabled or enabled, and if the latter in what context".

Regards

Ian Barwick

#10solai v
solai.cdac@gmail.com
In reply to: Ian Lawrence Barwick (#7)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

Hi all,

On Tue, Jul 21, 2026 at 4:46 PM Ian Lawrence Barwick <barwick@gmail.com> wrote:

2026年7月21日(火) 12:38 Rithvika Devisetti <devisettirithvika@gmail.com>:

Hi,

On Mon, Jul 20, 2026 at 6:49 PM Ian Lawrence Barwick <barwick@gmail.com> wrote:

Hi Jim

2026年7月21日(火) 0:13 Jim Jones <jim.jones@uni-muenster.de>:

Hi Ian

Thanks for the patch! Here a few comments on v2:

== shadow variable ==

The function pg_get_event_trigger_ddl_internal has a bool parameter
named owner, and its body has a char* with the same name.

Good catch - I note the compiler-level shadow check is only effective
for variables of the same type, which hadn't occurred to me before.

== trailing XXX (placeholder?) ==

+ * CREATE EVENT TRIGGER statement; XXX

Whoops, fixed.

== typo (2x the) ==

+ is false, the the corresponding <literal>ENABLE</literal> clause is

Classic typo invisible to the author, fixed.

=== switch without default ==

I realise that "switch (evtForm->evtenabled)" already tests all possible
values of evtenable, but I'm wondering if we really should let it
silently finish the buffer like "ALTER EVENT TRIGGER foo ;" if evtenable
ever gets a different value. I'd argue that an error message would be
better than a malformed DDL. What do you think?

I did wonder - the corresponding switch statement in pg_dump falls through to
"ENABLE" as the default value, but only calls that if "evtenabled" is
not 'O' (the
default), so the addition of some new trigger firing state would result
in "ALTER EVENT TRIGGER foo ENABLE;" if the code was not updated,
which is easy to overlook with this kind of setup. On the other hand, I can't
imagine what kind of new trigger firing state might be added, so maybe
it's more of a theoretical risk. In any case I added an error message, and
also updated the tests to check each existing firing state is
correctly rendered.

While looking at that, I did update the comment in
"src/include/commands/trigger.h"
to note that the "TRIGGER_*" definitions also apply to pg_event_trigger.

Patch applies clean to me, and tests passed. I see a grammatical typo below,
there is an additional "be".

cannot be actually be used in a valid statement

Thanks for checking! Revised version attached, with that and a couple of
minor text tweaks.

Thank you for the updated patch. I reviewed and tested this patch on
my tree. The patch applied cleanly and the regression test completed
successfully without any failures. I performed functional testing of
the new pg_get_event_trigger_ddl() function and verified: the function
is installed and registered correctly, the reconstruction of CREATE
EVENT TRIGGER statements, output formats, reconstruction of single and
multiple WHEN TAG clauses, preservation of event trigger enable
states, optional owner and enable parameters, schema-qualified
function names in the generated DDL, handling of quoted event trigger
names, expected error reporting for non-existent event triggers and
also confirmed that the generated DDL is consistent with the metadata
stored in pg_event_trigger. However I did not observe any functional
issues during testing and behaved as intended. The patch looks good to
me.

Regards,
Solai

#11Zsolt Parragi
zsolt.parragi@percona.com
In reply to: Ian Lawrence Barwick (#9)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

That did cross my mind, but while "enabled" feels more natural grammatically,
"enable" corresponds to the "ENABLE" clause which is to be emitted (or omitted).
Except when it's "DISABLE"... I can't think of any better phrasing
which is reasonably
short and conveys the meaning "emit the clause which indicates the trigger is to
be disabled or enabled, and if the latter in what context".

Yeah, I agree with this reasoning, I wasn't even sure to mention this or not. I only did because the ALTER EVENT TRIGGER documentation also mentions "disabled", so there's some precedent of using that form.

Keeping it "enable" is fine with me.

#12Jim Jones
jim.jones@uni-muenster.de
In reply to: Zsolt Parragi (#11)
Re: [PATCH] Add pg_get_event_trigger_ddl() function

On 22/07/2026 08:14, Zsolt Parragi wrote:

That did cross my mind, but while "enabled" feels more natural grammatically,
"enable" corresponds to the "ENABLE" clause which is to be emitted (or omitted).
Except when it's "DISABLE"... I can't think of any better phrasing
which is reasonably
short and conveys the meaning "emit the clause which indicates the trigger is to
be disabled or enabled, and if the latter in what context".

Yeah, I agree with this reasoning, I wasn't even sure to mention this
or not. I only did because the ALTER EVENT TRIGGER documentation also
mentions "disabled", so there's some precedent of using that form.

Keeping it "enable" is fine with me.

Since there seems to be a consensus among all reviewers I'll mark the CF
entry as ready for committer.

Thanks!

Best, Jim