From b3d488c99eaec0558104992033e815fd20a6e925 Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
Date: Fri, 24 Jul 2026 10:41:40 +0900
Subject: [PATCH v2 2/3] Collect ALTER PUBLICATION SET ALL commands for event
 triggers

Previously, ALTER PUBLICATION ... SET ALL TABLES and
SET ALL SEQUENCES fired ddl_command_end, but
pg_event_trigger_ddl_commands() could return no entry for the altered
publication because none was collected.

Fix this by collecting the publication itself as the
ALTER PUBLICATION command whenever a SET ALL command changes the
publication state.

As a side-effect of this fix, SET ALL TABLES with EXCEPT entries may now
produce both a publication-level ALTER PUBLICATION entry and the existing
per-membership entries for added exclusions. This is intentional, since
they represent different parts of the command.

Backpatch to v19, where ALTER PUBLICATION SET ALL TABLES and
SET ALL SEQUENCES were introduced.
---
 src/backend/commands/publicationcmds.c      | 11 +++++++----
 src/test/regress/expected/event_trigger.out |  9 +++++++++
 src/test/regress/sql/event_trigger.sql      |  5 +++++
 3 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 6fa354b170c..5edbf1c7920 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -1607,7 +1607,7 @@ CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
 /*
  * Update FOR ALL TABLES / FOR ALL SEQUENCES flags of a publication.
  */
-static void
+static bool
 AlterPublicationAllFlags(AlterPublicationStmt *stmt, Relation rel,
 						 HeapTuple tup)
 {
@@ -1618,7 +1618,7 @@ AlterPublicationAllFlags(AlterPublicationStmt *stmt, Relation rel,
 	bool		dirty = false;
 
 	if (!stmt->for_all_tables && !stmt->for_all_sequences)
-		return;
+		return false;
 
 	pubform = (Form_pg_publication) GETSTRUCT(tup);
 
@@ -1651,6 +1651,8 @@ AlterPublicationAllFlags(AlterPublicationStmt *stmt, Relation rel,
 		if (replaces[Anum_pg_publication_puballtables - 1])
 			CacheInvalidateRelcacheAll();
 	}
+
+	return dirty;
 }
 
 /*
@@ -1694,6 +1696,7 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
 		Oid			pubid = pubform->oid;
 		bool		tables_dropped;
 		bool		schemas_dropped;
+		bool		all_flags_changed;
 
 		ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
 								   &exceptrelations, &schemaidlist);
@@ -1724,9 +1727,9 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
 			AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext,
 								   schemaidlist != NIL);
 		schemas_dropped = AlterPublicationSchemas(stmt, tup, schemaidlist);
-		AlterPublicationAllFlags(stmt, rel, tup);
+		all_flags_changed = AlterPublicationAllFlags(stmt, rel, tup);
 
-		if (tables_dropped || schemas_dropped)
+		if (tables_dropped || schemas_dropped || all_flags_changed)
 		{
 			ObjectAddress obj;
 
diff --git a/src/test/regress/expected/event_trigger.out b/src/test/regress/expected/event_trigger.out
index 960f6d002e3..438b486aacf 100644
--- a/src/test/regress/expected/event_trigger.out
+++ b/src/test/regress/expected/event_trigger.out
@@ -452,6 +452,14 @@ ALTER PUBLICATION evttrig_pub SET TABLE evttrig_pub_tbl2;
 NOTICE:  NORMAL: orig=t normal=f istemp=f type=publication namespace identity=evttrig_pub_schema2 in publication evttrig_pub schema=<NULL> name=<NULL> addr={evttrig_pub_schema2} args={evttrig_pub}
 NOTICE:  NORMAL: orig=t normal=f istemp=f type=publication relation identity=public.evttrig_pub_tbl3 in publication evttrig_pub schema=<NULL> name=<NULL> addr={public,evttrig_pub_tbl3} args={evttrig_pub}
 NOTICE:  END: command_tag=ALTER PUBLICATION type=publication identity=evttrig_pub
+CREATE PUBLICATION evttrig_all_pub;
+NOTICE:  END: command_tag=CREATE PUBLICATION type=publication identity=evttrig_all_pub
+ALTER PUBLICATION evttrig_all_pub SET ALL TABLES EXCEPT (TABLE evttrig_pub_tbl);
+NOTICE:  END: command_tag=ALTER PUBLICATION type=publication relation identity=public.evttrig_pub_tbl in publication evttrig_all_pub
+NOTICE:  END: command_tag=ALTER PUBLICATION type=publication identity=evttrig_all_pub
+ALTER PUBLICATION evttrig_all_pub SET ALL SEQUENCES;
+NOTICE:  NORMAL: orig=t normal=f istemp=f type=publication relation identity=public.evttrig_pub_tbl in publication evttrig_all_pub schema=<NULL> name=<NULL> addr={public,evttrig_pub_tbl} args={evttrig_all_pub}
+NOTICE:  END: command_tag=ALTER PUBLICATION type=publication identity=evttrig_all_pub
 CREATE SCHEMA evttrig
 	CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two', col_c SERIAL)
 	CREATE INDEX one_idx ON one (col_b)
@@ -609,6 +617,7 @@ NOTICE:  END: command_tag=CREATE OPERATOR CLASS type=operator class identity=pub
 DROP EVENT TRIGGER regress_event_trigger_report_dropped;
 DROP EVENT TRIGGER regress_event_trigger_report_end;
 DROP PUBLICATION evttrig_pub;
+DROP PUBLICATION evttrig_all_pub;
 DROP TABLE evttrig_pub_tbl;
 DROP TABLE evttrig_pub_tbl2;
 DROP TABLE evttrig_pub_tbl3;
diff --git a/src/test/regress/sql/event_trigger.sql b/src/test/regress/sql/event_trigger.sql
index 028ab53e408..49291fe82d3 100644
--- a/src/test/regress/sql/event_trigger.sql
+++ b/src/test/regress/sql/event_trigger.sql
@@ -348,6 +348,10 @@ ALTER PUBLICATION evttrig_pub DROP TABLE evttrig_pub_tbl;
 ALTER PUBLICATION evttrig_pub DROP TABLES IN SCHEMA evttrig_pub_schema;
 ALTER PUBLICATION evttrig_pub SET TABLE evttrig_pub_tbl2;
 
+CREATE PUBLICATION evttrig_all_pub;
+ALTER PUBLICATION evttrig_all_pub SET ALL TABLES EXCEPT (TABLE evttrig_pub_tbl);
+ALTER PUBLICATION evttrig_all_pub SET ALL SEQUENCES;
+
 CREATE SCHEMA evttrig
 	CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two', col_c SERIAL)
 	CREATE INDEX one_idx ON one (col_b)
@@ -431,6 +435,7 @@ DROP EVENT TRIGGER regress_event_trigger_report_dropped;
 DROP EVENT TRIGGER regress_event_trigger_report_end;
 
 DROP PUBLICATION evttrig_pub;
+DROP PUBLICATION evttrig_all_pub;
 DROP TABLE evttrig_pub_tbl;
 DROP TABLE evttrig_pub_tbl2;
 DROP TABLE evttrig_pub_tbl3;
-- 
2.55.0

