From 76f94148107e4dc42843001aab20dfa0d775735c Mon Sep 17 00:00:00 2001 From: "houzj.fnst" Date: Wed, 8 Sep 2021 09:20:27 +0800 Subject: [PATCH] Invalidate relcache for publications defined for all tables. Updates/Deletes on a relation were allowed even without replica identity after we define the publication for all tables. This would later lead to conflicts on subscriber. The reason was that for such publications we were not invalidating the relcache and the publication information for relations was not getting rebuilt. Author: Vignesh C Reviewed-by: Hou Zhijie, Kyotaro Horiguchi, Amit Kapila Discussion: https://postgr.es/m/CALDaNm0pF6zeWqCA8TCe2sDuwFAy8fCqba=nHampCKag-qLixg@mail.gmail.com --- src/backend/commands/publicationcmds.c | 15 +++++++++++++-- src/test/regress/expected/publication.out | 15 +++++++++++++++ src/test/regress/sql/publication.sql | 14 ++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index a5e29b5a82..0b08cbddd0 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -236,6 +236,11 @@ CreatePublication(CreatePublicationStmt *stmt) PublicationAddTables(puboid, rels, true, NULL); CloseTableList(rels); } + else if (stmt->for_all_tables) + { + /* Invalidate relcache so that publication info is rebuilt. */ + CacheInvalidateRelcacheAll(); + } table_close(rel, RowExclusiveLock); @@ -469,21 +474,27 @@ AlterPublication(AlterPublicationStmt *stmt) } /* - * Drop publication by OID + * Remove the publication by mapping OID. */ void RemovePublicationById(Oid pubid) { Relation rel; HeapTuple tup; + Form_pg_publication pubform; rel = table_open(PublicationRelationId, RowExclusiveLock); tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid)); - if (!HeapTupleIsValid(tup)) elog(ERROR, "cache lookup failed for publication %u", pubid); + pubform = (Form_pg_publication) GETSTRUCT(tup); + + /* Invalidate relcache so that publication info is rebuilt. */ + if (pubform->puballtables) + CacheInvalidateRelcacheAll(); + CatalogTupleDelete(rel, &tup->t_self); ReleaseSysCache(tup); diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 63d6ab7a4e..c299702480 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -156,6 +156,21 @@ Tables: DROP TABLE testpub_parted1; DROP PUBLICATION testpub_forparted, testpub_forparted1; +-- Test cache invalidation FOR ALL TABLES publication +SET client_min_messages = 'ERROR'; +CREATE TABLE testpub_tbl4(a int); +INSERT INTO testpub_tbl4 values(1); +UPDATE testpub_tbl4 set a = 2; +CREATE PUBLICATION testpub_foralltables FOR ALL TABLES; +RESET client_min_messages; +-- fail missing REPLICA IDENTITY +UPDATE testpub_tbl4 set a = 3; +ERROR: cannot update table "testpub_tbl4" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE. +DROP PUBLICATION testpub_foralltables; +-- should pass after dropping the publication +UPDATE testpub_tbl4 set a = 3; +DROP TABLE testpub_tbl4; -- fail - view CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_view; ERROR: "testpub_view" is not a table diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql index d844075368..04b34ee299 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -93,6 +93,20 @@ ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true); DROP TABLE testpub_parted1; DROP PUBLICATION testpub_forparted, testpub_forparted1; +-- Test cache invalidation FOR ALL TABLES publication +SET client_min_messages = 'ERROR'; +CREATE TABLE testpub_tbl4(a int); +INSERT INTO testpub_tbl4 values(1); +UPDATE testpub_tbl4 set a = 2; +CREATE PUBLICATION testpub_foralltables FOR ALL TABLES; +RESET client_min_messages; +-- fail missing REPLICA IDENTITY +UPDATE testpub_tbl4 set a = 3; +DROP PUBLICATION testpub_foralltables; +-- should pass after dropping the publication +UPDATE testpub_tbl4 set a = 3; +DROP TABLE testpub_tbl4; + -- fail - view CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_view; SET client_min_messages = 'ERROR'; -- 2.18.4