diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 3ece136b3d..5368023de3 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2025,6 +2025,7 @@ index_constraint_create(Relation heapRelation, HeapTuple indexTuple; Form_pg_index indexForm; bool dirty = false; + bool marked_as_primary = false; pg_index = table_open(IndexRelationId, RowExclusiveLock); @@ -2038,6 +2039,7 @@ index_constraint_create(Relation heapRelation, { indexForm->indisprimary = true; dirty = true; + marked_as_primary = true; } if (deferrable && indexForm->indimmediate) @@ -2050,6 +2052,15 @@ index_constraint_create(Relation heapRelation, { CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple); + /* + * When we mark an existing index as primary, force a relcache + * flush on its parent table, so that all sessions will become + * aware that the table now has a primary key. This is important + * because it affects some replication behaviors. + */ + if (marked_as_primary) + CacheInvalidateRelcache(heapRelation); + InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0, InvalidOid, is_internal); } diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out index 06c7b157d6..856ea29e37 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -204,6 +204,20 @@ Publications: "testpib_ins_trunct" "testpub_fortbl" +-- verify relation cache invalidation when a primary key is added using +-- an existing index +CREATE TABLE pub_test.testpub_addpk (id int not null, data int); +ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_addpk; +INSERT INTO pub_test.testpub_addpk VALUES(1, 11); +CREATE UNIQUE INDEX testpub_addpk_id_idx ON pub_test.testpub_addpk(id); +-- fail: +UPDATE pub_test.testpub_addpk SET id = 2; +ERROR: cannot update table "testpub_addpk" because it does not have a replica identity and publishes updates +HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE. +ALTER TABLE pub_test.testpub_addpk ADD PRIMARY KEY USING INDEX testpub_addpk_id_idx; +-- now it should work: +UPDATE pub_test.testpub_addpk SET id = 2; +DROP TABLE pub_test.testpub_addpk; -- permissions SET ROLE regress_publication_user2; CREATE PUBLICATION testpub2; -- fail diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql index 1071334825..6d3f471dd2 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -105,6 +105,19 @@ ALTER PUBLICATION testpub_default DROP TABLE pub_test.testpub_nopk; \d+ testpub_tbl1 +-- verify relation cache invalidation when a primary key is added using +-- an existing index +CREATE TABLE pub_test.testpub_addpk (id int not null, data int); +ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_addpk; +INSERT INTO pub_test.testpub_addpk VALUES(1, 11); +CREATE UNIQUE INDEX testpub_addpk_id_idx ON pub_test.testpub_addpk(id); +-- fail: +UPDATE pub_test.testpub_addpk SET id = 2; +ALTER TABLE pub_test.testpub_addpk ADD PRIMARY KEY USING INDEX testpub_addpk_id_idx; +-- now it should work: +UPDATE pub_test.testpub_addpk SET id = 2; +DROP TABLE pub_test.testpub_addpk; + -- permissions SET ROLE regress_publication_user2; CREATE PUBLICATION testpub2; -- fail