v1-0001-Handle-EXCEPT-publications-when-changing-table-to.patch
application/octet-stream
Filename: v1-0001-Handle-EXCEPT-publications-when-changing-table-to.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v1-0001
Subject: Handle EXCEPT publications when changing table to UNLOGGED
| File | + | − |
|---|---|---|
| src/backend/commands/tablecmds.c | 39 | 7 |
| src/test/regress/expected/publication.out | 26 | 0 |
| src/test/regress/sql/publication.sql | 16 | 0 |
From 8c9b04f003d4989e09149efd3c875edc31a3a5bd Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Mon, 20 Apr 2026 15:02:31 +0530
Subject: [PATCH v1] Handle EXCEPT publications when changing table to UNLOGGED
When changing a table to UNLOGGED, tables that appear in publications
only via EXCEPT clauses (prexcept = true) were allowed, but left stale
entries in pg_publication_rel.
Since UNLOGGED tables are not supported in publications, remove such
entries when the table is changed to UNLOGGED, and emit a NOTICE to
inform the user.
---
src/backend/commands/tablecmds.c | 46 +++++++++++++++++++----
src/test/regress/expected/publication.out | 26 +++++++++++++
src/test/regress/sql/publication.sql | 16 ++++++++
3 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index eec09ba1ded..3cb4b51489a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -98,6 +98,7 @@
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/builtins.h"
+#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/inval.h"
#include "utils/lsyscache.h"
@@ -19093,13 +19094,44 @@ ATPrepChangePersistence(AlteredTableInfo *tab, Relation rel, bool toLogged)
* Check that the table is not part of any publication when changing to
* UNLOGGED, as UNLOGGED tables can't be published.
*/
- if (!toLogged &&
- GetRelationIncludedPublications(RelationGetRelid(rel)) != NIL)
- ereport(ERROR,
- (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
- errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
- RelationGetRelationName(rel)),
- errdetail("Unlogged relations cannot be replicated.")));
+ if (!toLogged)
+ {
+ CatCList *pubrellist;
+
+ /* Find all publications associated with the relation. */
+ pubrellist = SearchSysCacheList1(PUBLICATIONRELMAP,
+ ObjectIdGetDatum(RelationGetRelid(rel)));
+ for (int i = 0; i < pubrellist->n_members; i++)
+ {
+ HeapTuple tup = &pubrellist->members[i]->tuple;
+ Form_pg_publication_rel pubrel = (Form_pg_publication_rel) GETSTRUCT(tup);
+
+ if (!pubrel->prexcept)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
+ RelationGetRelationName(rel)),
+ errdetail("Unlogged relations cannot be replicated.")));
+ }
+ else
+ {
+ ObjectAddress obj;
+ char *pubname;
+
+ pubname = get_publication_name(pubrel->prpubid, false);
+
+ ObjectAddressSet(obj, PublicationRelRelationId, pubrel->oid);
+ performDeletion(&obj, DROP_CASCADE, 0);
+
+ ereport(NOTICE,
+ errmsg("relation \"%s\" removed from publication \"%s\" due to being changed to UNLOGGED",
+ RelationGetRelationName(rel), pubname));
+ }
+ }
+
+ ReleaseSysCacheList(pubrellist);
+ }
/*
* Check existing foreign key constraints to preserve the invariant that
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index d028e9be866..dec7f5b24fb 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -256,6 +256,32 @@ Except publications:
"testpub_foralltables_excepttable"
"testpub_foralltables_excepttable1"
+SET client_min_messages = 'NOTICE';
+-- Change testpub_tbl1 to UNLOGGED. This should remove the relation from the
+-- publication (and effectively from the EXCEPT clause), since UNLOGGED tables
+-- are not supported in publications.
+ALTER TABLE testpub_tbl1 SET UNLOGGED;
+NOTICE: relation "testpub_tbl1" removed from publication "testpub_foralltables_excepttable" due to being changed to UNLOGGED
+NOTICE: relation "testpub_tbl1" removed from publication "testpub_foralltables_excepttable1" due to being changed to UNLOGGED
+\dRp+ testpub_foralltables_excepttable1
+ Publication testpub_foralltables_excepttable1
+ Owner | All tables | All sequences | Inserts | Updates | Deletes | Truncates | Generated columns | Via root | Description
+--------------------------+------------+---------------+---------+---------+---------+-----------+-------------------+----------+-------------
+ regress_publication_user | t | f | t | t | t | t | none | f |
+(1 row)
+
+\d testpub_tbl1
+ Unlogged table "public.testpub_tbl1"
+ Column | Type | Collation | Nullable | Default
+--------+---------+-----------+----------+------------------------------------------
+ id | integer | | not null | nextval('testpub_tbl1_id_seq'::regclass)
+ data | text | | |
+Indexes:
+ "testpub_tbl1_pkey" PRIMARY KEY, btree (id)
+
+-- Restore the table to LOGGED.
+ALTER TABLE testpub_tbl1 SET LOGGED;
+SET client_min_messages = 'ERROR';
-- fail - first table in the EXCEPT list should use TABLE keyword
CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tbl1, testpub_tbl2);
ERROR: syntax error at or near "testpub_tbl1"
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 642e32fa098..3c8b5a3a980 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -119,6 +119,22 @@ CREATE PUBLICATION testpub_foralltables_excepttable1 FOR ALL TABLES EXCEPT (TABL
-- Check that the table description shows the publications where it is listed
-- in the EXCEPT clause
\d testpub_tbl1
+
+SET client_min_messages = 'NOTICE';
+
+-- Change testpub_tbl1 to UNLOGGED. This should remove the relation from the
+-- publication (and effectively from the EXCEPT clause), since UNLOGGED tables
+-- are not supported in publications.
+ALTER TABLE testpub_tbl1 SET UNLOGGED;
+\dRp+ testpub_foralltables_excepttable1
+\d testpub_tbl1
+
+-- Restore the table to LOGGED.
+ALTER TABLE testpub_tbl1 SET LOGGED;
+
+SET client_min_messages = 'ERROR';
+
+
-- fail - first table in the EXCEPT list should use TABLE keyword
CREATE PUBLICATION testpub_foralltables_excepttable2 FOR ALL TABLES EXCEPT (testpub_tbl1, testpub_tbl2);
--
2.43.0