mirror of
https://github.com/postgres/postgres.git
synced 2025-05-15 19:15:29 +03:00
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
This commit is contained in:
parent
f4ebf0dbea
commit
3839e29c58
@ -2050,6 +2050,7 @@ index_constraint_create(Relation heapRelation,
|
|||||||
HeapTuple indexTuple;
|
HeapTuple indexTuple;
|
||||||
Form_pg_index indexForm;
|
Form_pg_index indexForm;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
bool marked_as_primary = false;
|
||||||
|
|
||||||
pg_index = table_open(IndexRelationId, RowExclusiveLock);
|
pg_index = table_open(IndexRelationId, RowExclusiveLock);
|
||||||
|
|
||||||
@ -2063,6 +2064,7 @@ index_constraint_create(Relation heapRelation,
|
|||||||
{
|
{
|
||||||
indexForm->indisprimary = true;
|
indexForm->indisprimary = true;
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
marked_as_primary = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deferrable && indexForm->indimmediate)
|
if (deferrable && indexForm->indimmediate)
|
||||||
@ -2075,6 +2077,15 @@ index_constraint_create(Relation heapRelation,
|
|||||||
{
|
{
|
||||||
CatalogTupleUpdate(pg_index, &indexTuple->t_self, indexTuple);
|
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,
|
InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
|
||||||
InvalidOid, is_internal);
|
InvalidOid, is_internal);
|
||||||
}
|
}
|
||||||
|
@ -268,6 +268,20 @@ Publications:
|
|||||||
"testpib_ins_trunct"
|
"testpib_ins_trunct"
|
||||||
"testpub_fortbl"
|
"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
|
-- permissions
|
||||||
SET ROLE regress_publication_user2;
|
SET ROLE regress_publication_user2;
|
||||||
CREATE PUBLICATION testpub2; -- fail
|
CREATE PUBLICATION testpub2; -- fail
|
||||||
|
@ -149,6 +149,19 @@ ALTER PUBLICATION testpub_default DROP TABLE pub_test.testpub_nopk;
|
|||||||
|
|
||||||
\d+ testpub_tbl1
|
\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
|
-- permissions
|
||||||
SET ROLE regress_publication_user2;
|
SET ROLE regress_publication_user2;
|
||||||
CREATE PUBLICATION testpub2; -- fail
|
CREATE PUBLICATION testpub2; -- fail
|
||||||
|
Loading…
x
Reference in New Issue
Block a user