diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index d232a213088..0ee09987812 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -2050,6 +2050,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); @@ -2063,6 +2064,7 @@ index_constraint_create(Relation heapRelation, { indexForm->indisprimary = true; dirty = true; + marked_as_primary = true; } if (deferrable && indexForm->indimmediate) @@ -2075,6 +2077,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 a2aca234ef8..7c7e0226658 100644 --- a/src/test/regress/expected/publication.out +++ b/src/test/regress/expected/publication.out @@ -268,6 +268,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 4f2445ad117..4b7738395ec 100644 --- a/src/test/regress/sql/publication.sql +++ b/src/test/regress/sql/publication.sql @@ -149,6 +149,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