Fix assertion with relation using REPLICA IDENTITY FULL in subscriber
authorMichael Paquier <[email protected]>
Sat, 16 May 2020 09:16:41 +0000 (18:16 +0900)
committerMichael Paquier <[email protected]>
Sat, 16 May 2020 09:16:41 +0000 (18:16 +0900)
In a logical replication subscriber, a table using REPLICA IDENTITY FULL
which has a primary key would try to use the primary key's index
available to scan for a tuple, but an assertion only assumed as correct
the case of an index associated to REPLICA IDENTITY USING INDEX.  This
commit corrects the assertion so as the use of a primary key index is a
valid case.

Reported-by: Dilip Kumar
Analyzed-by: Dilip Kumar
Author: Euler Taveira
Reviewed-by: Michael Paquier, Masahiko Sawada
Discussion: https://postgr.es/m/CAFiTN-u64S5bUiPL1q5kwpHNd0hRnf1OE-bzxNiOs5zo84i51w@mail.gmail.com
Backpatch-through: 10

src/backend/executor/execReplication.c
src/test/subscription/t/001_rep_changes.pl

index 60dca6e1f33862e6df57ed9225bb605fef01f95c..c499042bf84a69303899caf05f609fdba5890816 100644 (file)
@@ -55,7 +55,8 @@ build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel,
    int2vector *indkey = &idxrel->rd_index->indkey;
    bool        hasnulls = false;
 
-   Assert(RelationGetReplicaIndex(rel) == RelationGetRelid(idxrel));
+   Assert(RelationGetReplicaIndex(rel) == RelationGetRelid(idxrel) ||
+          RelationGetPrimaryKeyIndex(rel) == RelationGetRelid(idxrel));
 
    indclassDatum = SysCacheGetAttr(INDEXRELID, idxrel->rd_indextuple,
                                    Anum_pg_index_indclass, &isnull);
index b7c503f7795e06ca73a15e3c88bed23676c4a841..bd670c0f8225f2812db7ecd36bed8648ab5e9071 100644 (file)
@@ -31,6 +31,10 @@ $node_publisher->safe_psql('postgres',
    "CREATE TABLE tab_mixed (a int primary key, b text, c numeric)");
 $node_publisher->safe_psql('postgres',
    "INSERT INTO tab_mixed (a, b, c) VALUES (1, 'foo', 1.1)");
+$node_publisher->safe_psql('postgres',
+   "CREATE TABLE tab_full_pk (a int primary key, b text)");
+$node_publisher->safe_psql('postgres',
+   "ALTER TABLE tab_full_pk REPLICA IDENTITY FULL");
 # Let this table with REPLICA IDENTITY NOTHING, allowing only INSERT changes.
 $node_publisher->safe_psql('postgres', "CREATE TABLE tab_nothing (a int)");
 $node_publisher->safe_psql('postgres',
@@ -43,6 +47,10 @@ $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_full (a int)");
 $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_full2 (x text)");
 $node_subscriber->safe_psql('postgres',
    "CREATE TABLE tab_rep (a int primary key)");
+$node_subscriber->safe_psql('postgres',
+   "CREATE TABLE tab_full_pk (a int primary key, b text)");
+$node_subscriber->safe_psql('postgres',
+   "ALTER TABLE tab_full_pk REPLICA IDENTITY FULL");
 $node_subscriber->safe_psql('postgres', "CREATE TABLE tab_nothing (a int)");
 
 # different column count and order than on publisher
@@ -56,7 +64,7 @@ $node_publisher->safe_psql('postgres', "CREATE PUBLICATION tap_pub");
 $node_publisher->safe_psql('postgres',
    "CREATE PUBLICATION tap_pub_ins_only WITH (publish = insert)");
 $node_publisher->safe_psql('postgres',
-"ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed, tab_nothing"
+"ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full, tab_full2, tab_mixed, tab_nothing, tab_full_pk"
 );
 $node_publisher->safe_psql('postgres',
    "ALTER PUBLICATION tap_pub_ins_only ADD TABLE tab_ins");
@@ -99,6 +107,9 @@ $node_publisher->safe_psql('postgres', "UPDATE tab_rep SET a = -a");
 $node_publisher->safe_psql('postgres',
    "INSERT INTO tab_mixed VALUES (2, 'bar', 2.2)");
 
+$node_publisher->safe_psql('postgres',
+   "INSERT INTO tab_full_pk VALUES (1, 'foo')");
+
 $node_publisher->safe_psql('postgres',
    "INSERT INTO tab_nothing VALUES (generate_series(1,20))");
 
@@ -146,6 +157,8 @@ $node_publisher->safe_psql('postgres',
    "UPDATE tab_full2 SET x = 'bb' WHERE x = 'b'");
 $node_publisher->safe_psql('postgres',
    "UPDATE tab_mixed SET b = 'baz' WHERE a = 1");
+$node_publisher->safe_psql('postgres',
+   "UPDATE tab_full_pk SET b = 'bar' WHERE a = 1");
 
 # Wait for subscription to catch up
 $node_publisher->poll_query_until('postgres', $caughtup_query)