1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Disallow SET UNLOGGED for tables in a publication's EXCEPT clause.

Unlogged tables cannot be replicated, so they can neither be published nor
be named in a publication's EXCEPT clause.  ALTER TABLE ... SET UNLOGGED
checked only whether the table was published, so a table in an EXCEPT
clause could still be made unlogged, leaving a state that CREATE
PUBLICATION would reject and that pg_dump could not restore.

Author: Vignesh C <vignesh21@gmail.com>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: shveta malik <shveta.malik@gmail.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Peter Smith <smithpb2250@gmail.com>
Reviewed-by: Zhijie Hou <houzj.fnst@fujitsu.com>
Discussion: https://postgr.es/m/CALDaNm1r2MkGu6h8zgU1Kj1sX-FcMQ7wGTeLSnhx-5joiyXEvg@mail.gmail.com
Backpatch-through: 19, where it was introduced
This commit is contained in:
Amit Kapila
2026-09-14 09:35:02 +05:30
parent 2d48d0f153
commit 17d84c2b67
5 changed files with 45 additions and 6 deletions

View File

@@ -927,6 +927,25 @@ GetRelationExcludedPublications(Oid relid)
return get_relation_publications(relid, true);
}
/*
* Check whether the relation is referenced by any publication, either as a
* published relation or in a publication's EXCEPT clause.
*/
bool
RelationHasPublication(Oid relid)
{
CatCList *pubrellist;
bool found;
pubrellist = SearchSysCacheList1(PUBLICATIONRELMAP,
ObjectIdGetDatum(relid));
found = (pubrellist->n_members > 0);
ReleaseSysCacheList(pubrellist);
return found;
}
/*
* Internal function to get the list of relation oids for a publication.
*

View File

@@ -19481,16 +19481,17 @@ 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.
* UNLOGGED tables can neither be published nor be named in a
* publication's EXCEPT clause, so reject the change if the table is
* referenced by any publication.
*/
if (!toLogged &&
GetRelationIncludedPublications(RelationGetRelid(rel)) != NIL)
if (!toLogged && RelationHasPublication(RelationGetRelid(rel)))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot change table \"%s\" to unlogged because it is part of a publication",
errmsg("cannot change table \"%s\" to unlogged because it is referenced by a publication",
RelationGetRelationName(rel)),
errdetail("Unlogged relations cannot be replicated.")));
errdetail("Unlogged relations cannot be published or excluded via an EXCEPT clause."),
errhint("Drop the table from the publication, or remove it from the publication's EXCEPT clause, first.")));
/*
* Check existing foreign key constraints to preserve the invariant that

View File

@@ -157,6 +157,7 @@ extern Publication *GetPublication(Oid pubid);
extern Publication *GetPublicationByName(const char *pubname, bool missing_ok);
extern List *GetRelationIncludedPublications(Oid relid);
extern List *GetRelationExcludedPublications(Oid relid);
extern bool RelationHasPublication(Oid relid);
/*---------
* Expected values for pub_partopt parameter of

View File

@@ -270,6 +270,16 @@ 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 by a publication
DETAIL: Unlogged relations cannot be published or excluded via an EXCEPT clause.
HINT: Drop the table from the publication, or remove it from the publication's EXCEPT clause, first.
DROP PUBLICATION testpub_exc_unlogged;
DROP TABLE testpub_exc_unlogged_tbl;
---------------------------------------------
-- SET ALL TABLES/SEQUENCES
---------------------------------------------

View File

@@ -124,6 +124,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
---------------------------------------------