Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)