Skip to content

Commit 8db27fb

Browse files
author
Amit Kapila
committed
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
1 parent b7fd291 commit 8db27fb

File tree

5 files changed

+68
-1
lines changed

5 files changed

+68
-1
lines changed

src/backend/catalog/dependency.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,10 @@ doDeletion(const ObjectAddress *object, int flags)
14701470
RemovePublicationRelById(object->objectId);
14711471
break;
14721472

1473+
case OCLASS_PUBLICATION:
1474+
RemovePublicationById(object->objectId);
1475+
break;
1476+
14731477
case OCLASS_CAST:
14741478
case OCLASS_COLLATION:
14751479
case OCLASS_CONVERSION:
@@ -1488,7 +1492,6 @@ doDeletion(const ObjectAddress *object, int flags)
14881492
case OCLASS_USER_MAPPING:
14891493
case OCLASS_DEFACL:
14901494
case OCLASS_EVENT_TRIGGER:
1491-
case OCLASS_PUBLICATION:
14921495
case OCLASS_TRANSFORM:
14931496
DropObjectById(object);
14941497
break;

src/backend/commands/publicationcmds.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ CreatePublication(CreatePublicationStmt *stmt)
236236
PublicationAddTables(puboid, rels, true, NULL);
237237
CloseTableList(rels);
238238
}
239+
else if (stmt->for_all_tables)
240+
{
241+
/* Invalidate relcache so that publication info is rebuilt. */
242+
CacheInvalidateRelcacheAll();
243+
}
239244

240245
table_close(rel, RowExclusiveLock);
241246

@@ -498,6 +503,35 @@ RemovePublicationRelById(Oid proid)
498503
table_close(rel, RowExclusiveLock);
499504
}
500505

506+
/*
507+
* Remove the publication by mapping OID.
508+
*/
509+
void
510+
RemovePublicationById(Oid pubid)
511+
{
512+
Relation rel;
513+
HeapTuple tup;
514+
Form_pg_publication pubform;
515+
516+
rel = table_open(PublicationRelationId, RowExclusiveLock);
517+
518+
tup = SearchSysCache1(PUBLICATIONOID, ObjectIdGetDatum(pubid));
519+
if (!HeapTupleIsValid(tup))
520+
elog(ERROR, "cache lookup failed for publication %u", pubid);
521+
522+
pubform = (Form_pg_publication) GETSTRUCT(tup);
523+
524+
/* Invalidate relcache so that publication info is rebuilt. */
525+
if (pubform->puballtables)
526+
CacheInvalidateRelcacheAll();
527+
528+
CatalogTupleDelete(rel, &tup->t_self);
529+
530+
ReleaseSysCache(tup);
531+
532+
table_close(rel, RowExclusiveLock);
533+
}
534+
501535
/*
502536
* Open relations specified by a RangeVar list.
503537
* The returned tables are locked in ShareUpdateExclusiveLock mode in order to

src/include/commands/publicationcmds.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
extern ObjectAddress CreatePublication(CreatePublicationStmt *stmt);
2222
extern void AlterPublication(AlterPublicationStmt *stmt);
23+
extern void RemovePublicationById(Oid pubid);
2324
extern void RemovePublicationRelById(Oid proid);
2425

2526
extern ObjectAddress AlterPublicationOwner(const char *name, Oid newOwnerId);

src/test/regress/expected/publication.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ Tables:
156156

157157
DROP TABLE testpub_parted1;
158158
DROP PUBLICATION testpub_forparted, testpub_forparted1;
159+
-- Test cache invalidation FOR ALL TABLES publication
160+
SET client_min_messages = 'ERROR';
161+
CREATE TABLE testpub_tbl4(a int);
162+
INSERT INTO testpub_tbl4 values(1);
163+
UPDATE testpub_tbl4 set a = 2;
164+
CREATE PUBLICATION testpub_foralltables FOR ALL TABLES;
165+
RESET client_min_messages;
166+
-- fail missing REPLICA IDENTITY
167+
UPDATE testpub_tbl4 set a = 3;
168+
ERROR: cannot update table "testpub_tbl4" because it does not have a replica identity and publishes updates
169+
HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
170+
DROP PUBLICATION testpub_foralltables;
171+
-- should pass after dropping the publication
172+
UPDATE testpub_tbl4 set a = 3;
173+
DROP TABLE testpub_tbl4;
159174
-- fail - view
160175
CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_view;
161176
ERROR: "testpub_view" is not a table

src/test/regress/sql/publication.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,20 @@ ALTER PUBLICATION testpub_forparted SET (publish_via_partition_root = true);
9393
DROP TABLE testpub_parted1;
9494
DROP PUBLICATION testpub_forparted, testpub_forparted1;
9595

96+
-- Test cache invalidation FOR ALL TABLES publication
97+
SET client_min_messages = 'ERROR';
98+
CREATE TABLE testpub_tbl4(a int);
99+
INSERT INTO testpub_tbl4 values(1);
100+
UPDATE testpub_tbl4 set a = 2;
101+
CREATE PUBLICATION testpub_foralltables FOR ALL TABLES;
102+
RESET client_min_messages;
103+
-- fail missing REPLICA IDENTITY
104+
UPDATE testpub_tbl4 set a = 3;
105+
DROP PUBLICATION testpub_foralltables;
106+
-- should pass after dropping the publication
107+
UPDATE testpub_tbl4 set a = 3;
108+
DROP TABLE testpub_tbl4;
109+
96110
-- fail - view
97111
CREATE PUBLICATION testpub_fortbl FOR TABLE testpub_view;
98112
SET client_min_messages = 'ERROR';

0 commit comments

Comments
 (0)