From 56058316df0cc241d5298003773f36268cf6f056 Mon Sep 17 00:00:00 2001 From: Vignesh C Date: Thu, 10 Sep 2026 09:54:03 +0530 Subject: [PATCH v1 5/5] Prevent unlogged tables in publication EXCEPT clauses Reject changing a table to UNLOGGED when it is referenced by a publication's EXCEPT clause. This keeps the catalog state consistent with the restriction that unlogged tables cannot be specified in publication EXCEPT clauses and ensures that pg_dump can recreate the publication. --- src/backend/commands/tablecmds.c | 12 ++++++++++++ src/test/regress/expected/publication.out | 9 +++++++++ src/test/regress/sql/publication.sql | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 8dc70bfa0f1..1d7c659d367 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -19552,6 +19552,18 @@ ATPrepChangePersistence(AlteredTableInfo *tab, Relation rel, bool toLogged) RelationGetRelationName(rel)), errdetail("Unlogged relations cannot be replicated."))); + /* + * Likewise, reject the change if the table is named in a publication's + * EXCEPT clause, since unlogged tables are not allowed there. + */ + if (!toLogged && + GetRelationExcludedPublications(RelationGetRelid(rel)) != NIL) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot change table \"%s\" to unlogged because it is referenced in a publication EXCEPT clause", + RelationGetRelationName(rel)), + errhint("Remove the table from the EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES first."))); + /* * Check existing foreign key constraints to preserve the invariant that * permanent tables cannot reference unlogged ones. Self-referencing diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 4f21462cc17..1fdea6ee088 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -279,6 +279,15 @@ CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (test ERROR: syntax error at or near "testpub_tbl1" LINE 1: ..._foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tb... ^ +-- A table in an EXCEPT clause cannot be changed to UNLOGGED. +CREATE TABLE testpub_exc_unlogged_tbl (a int); +CREATE PUBLICATION testpub_exc_unlogged FOR ALL TABLES EXCEPT (TABLE testpub_exc_unlogged_tbl); +-- fail - the table is referenced in a publication EXCEPT clause +ALTER TABLE testpub_exc_unlogged_tbl SET UNLOGGED; +ERROR: cannot change table "testpub_exc_unlogged_tbl" to unlogged because it is referenced in a publication EXCEPT clause +HINT: Remove the table from the EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES first. +DROP PUBLICATION testpub_exc_unlogged; +DROP TABLE testpub_exc_unlogged_tbl; --------------------------------------------- -- SET ALL TABLES/SEQUENCES --------------------------------------------- diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql index fac54b02e27..80c244c9138 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -126,6 +126,14 @@ CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT (TABL -- fail - first table in the EXCEPT list should use TABLE keyword CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tbl1, testpub_tbl2); +-- A table in an EXCEPT clause cannot be changed to UNLOGGED. +CREATE TABLE testpub_exc_unlogged_tbl (a int); +CREATE PUBLICATION testpub_exc_unlogged FOR ALL TABLES EXCEPT (TABLE testpub_exc_unlogged_tbl); +-- fail - the table is referenced in a publication EXCEPT clause +ALTER TABLE testpub_exc_unlogged_tbl SET UNLOGGED; +DROP PUBLICATION testpub_exc_unlogged; +DROP TABLE testpub_exc_unlogged_tbl; + --------------------------------------------- -- SET ALL TABLES/SEQUENCES --------------------------------------------- -- 2.55.0