Skip to content

Commit d8fbbb9

Browse files
committed
Flush table's relcache during ALTER TABLE ADD PRIMARY KEY USING INDEX.
Previously, unless we had to add a NOT NULL constraint to the column, this command resulted in updating only the index's relcache entry. That's problematic when replication behavior is being driven off the existence of a primary key: other sessions (and ours too for that matter) failed to recalculate their opinion of whether the table can be replicated. Add a relcache invalidation to fix it. This has been broken since pg_class.relhaspkey was removed in v11. Before that, updating the table's relhaspkey value sufficed to cause a cache flush. Hence, backpatch to v11. Report and patch by Hou Zhijie Discussion: https://postgr.es/m/OS0PR01MB5716EBE01F112C62F8F9B786947B9@OS0PR01MB5716.jpnprd01.prod.outlook.com
1 parent 1f655fd commit d8fbbb9

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

src/backend/catalog/index.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,7 @@ index_constraint_create(Relation heapRelation,
20712071
HeapTuple indexTuple;
20722072
Form_pg_index indexForm;
20732073
bool dirty = false;
2074+
bool marked_as_primary = false;
20742075

20752076
pg_index = table_open(IndexRelationId, RowExclusiveLock);
20762077

@@ -2084,6 +2085,7 @@ index_constraint_create(Relation heapRelation,
20842085
{
20852086
indexForm->indisprimary = true;
20862087
dirty = true;
2088+
marked_as_primary = true;
20872089
}
20882090

20892091
if (deferrable && indexForm->indimmediate)
@@ -2096,6 +2098,15 @@ index_constraint_create(Relation heapRelation,
20962098
{
20972099
CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
20982100

2101+
/*
2102+
* When we mark an existing index as primary, force a relcache
2103+
* flush on its parent table, so that all sessions will become
2104+
* aware that the table now has a primary key. This is important
2105+
* because it affects some replication behaviors.
2106+
*/
2107+
if (marked_as_primary)
2108+
CacheInvalidateRelcache(heapRelation);
2109+
20992110
InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
21002111
InvalidOid, is_internal);
21012112
}

src/test/regress/expected/publication.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,20 @@ Publications:
349349
"testpib_ins_trunct"
350350
"testpub_fortbl"
351351

352+
-- verify relation cache invalidation when a primary key is added using
353+
-- an existing index
354+
CREATE TABLE pub_test.testpub_addpk (id int not null, data int);
355+
ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_addpk;
356+
INSERT INTO pub_test.testpub_addpk VALUES(1, 11);
357+
CREATE UNIQUE INDEX testpub_addpk_id_idx ON pub_test.testpub_addpk(id);
358+
-- fail:
359+
UPDATE pub_test.testpub_addpk SET id = 2;
360+
ERROR: cannot update table "testpub_addpk" because it does not have a replica identity and publishes updates
361+
HINT: To enable updating the table, set REPLICA IDENTITY using ALTER TABLE.
362+
ALTER TABLE pub_test.testpub_addpk ADD PRIMARY KEY USING INDEX testpub_addpk_id_idx;
363+
-- now it should work:
364+
UPDATE pub_test.testpub_addpk SET id = 2;
365+
DROP TABLE pub_test.testpub_addpk;
352366
-- permissions
353367
SET ROLE regress_publication_user2;
354368
CREATE PUBLICATION testpub2; -- fail

src/test/regress/sql/publication.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,19 @@ ALTER PUBLICATION testpub_default DROP TABLE pub_test.testpub_nopk;
193193

194194
\d+ testpub_tbl1
195195

196+
-- verify relation cache invalidation when a primary key is added using
197+
-- an existing index
198+
CREATE TABLE pub_test.testpub_addpk (id int not null, data int);
199+
ALTER PUBLICATION testpub_default ADD TABLE pub_test.testpub_addpk;
200+
INSERT INTO pub_test.testpub_addpk VALUES(1, 11);
201+
CREATE UNIQUE INDEX testpub_addpk_id_idx ON pub_test.testpub_addpk(id);
202+
-- fail:
203+
UPDATE pub_test.testpub_addpk SET id = 2;
204+
ALTER TABLE pub_test.testpub_addpk ADD PRIMARY KEY USING INDEX testpub_addpk_id_idx;
205+
-- now it should work:
206+
UPDATE pub_test.testpub_addpk SET id = 2;
207+
DROP TABLE pub_test.testpub_addpk;
208+
196209
-- permissions
197210
SET ROLE regress_publication_user2;
198211
CREATE PUBLICATION testpub2; -- fail

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy