summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Kapila2021-09-08 06:20:37 +0000
committerAmit Kapila2021-09-08 06:20:37 +0000
commit8bd534274099aabf721ca4baef2e8a3a379d7b02 (patch)
treedfe72874407cf58efa38daa47488131cb455da19
parentaa37a439db6bd328d68ce815ab9e12467f42493b (diff)
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 an error on subscribers. The reason was that for such publications we were not invalidating the relcache and the publication information for relations was not getting rebuilt. Similarly, we were not invalidating the relcache after dropping of such publications which will prohibit Updates/Deletes without replica identity even without any publication. Author: Vignesh C and Hou Zhijie Reviewed-by: Hou Zhijie, Kyotaro Horiguchi, Amit Kapila Backpatch-through: 10, where it was introduced Discussion: https://postgr.es/m/CALDaNm0pF6zeWqCA8TCe2sDuwFAy8fCqba=nHampCKag-qLixg@mail.gmail.com
-rw-r--r--src/backend/catalog/dependency.c5
-rw-r--r--src/backend/commands/publicationcmds.c34
-rw-r--r--src/include/commands/publicationcmds.h1
-rw-r--r--src/test/regress/expected/publication.out15
-rw-r--r--src/test/regress/sql/publication.sql14
5 files changed, 68 insertions, 1 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index 76b65e39c4..91c3e976e0 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -1460,6 +1460,10 @@ doDeletion(const ObjectAddress *object, int flags)
RemovePublicationRelById(object->objectId);
break;
+ case OCLASS_PUBLICATION:
+ RemovePublicationById(object->objectId);
+ break;
+
case OCLASS_CAST:
case OCLASS_COLLATION:
case OCLASS_CONVERSION:
@@ -1478,7 +1482,6 @@ doDeletion(const ObjectAddress *object, int flags)
case OCLASS_USER_MAPPING:
case OCLASS_DEFACL:
case OCLASS_EVENT_TRIGGER:
- case OCLASS_PUBLICATION:
case OCLASS_TRANSFORM:
DropObjectById(object);
break;
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 179a0ef982..30929da1f5 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -234,6 +234,11 @@ CreatePublication(ParseState *pstate, 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);
@@ -505,6 +510,35 @@ RemovePublicationRelById(Oid proid)
}
/*
+ * 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);
+
+ table_close(rel, RowExclusiveLock);
+}
+
+/*
* Open relations specified by a PublicationTable list.
* In the returned list of PublicationRelInfo, tables are locked
* in ShareUpdateExclusiveLock mode in order to add them to a publication.
diff --git a/src/include/commands/publicationcmds.h b/src/include/commands/publicationcmds.h
index a3fa2ac6cd..c98d519b29 100644
--- a/src/include/commands/publicationcmds.h
+++ b/src/include/commands/publicationcmds.h
@@ -20,6 +20,7 @@
extern ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt);
extern void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt);
+extern void RemovePublicationById(Oid pubid);
extern void RemovePublicationRelById(Oid proid);
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 4a5ef0bc24..cad1b374be 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -158,6 +158,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: cannot add relation "testpub_view" to publication
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';