From 9b799635db437aafd56a73220c6d56e86e31d10e Mon Sep 17 00:00:00 2001 From: "houzj.fnst" Date: Tue, 14 Dec 2021 14:52:22 +0800 Subject: [PATCH] fix replication after ATTACH or DETACH partition --- src/backend/replication/pgoutput/pgoutput.c | 11 ++++ src/test/subscription/t/013_partition.pl | 71 ++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index 6f6a203dea..81376e2be7 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -1337,6 +1337,11 @@ rel_sync_cache_relation_cb(Datum arg, Oid relid) /* * Reset schema sent status as the relation definition may have changed. * Also free any objects that depended on the earlier definition. + * + * Besides, it's possible that the relation was ATTACHed to or DETACHed + * from a published partitioned table, in which case the publication + * actions of this relation would become invalid. So, we also need to + * invalidate the publication actions here. */ if (entry != NULL) { @@ -1354,6 +1359,12 @@ rel_sync_cache_relation_cb(Datum arg, Oid relid) free_conversion_map(entry->map); } entry->map = NULL; + + entry->replicate_valid = false; + entry->pubactions.pubinsert = false; + entry->pubactions.pubupdate = false; + entry->pubactions.pubdelete = false; + entry->pubactions.pubtruncate = false; } } diff --git a/src/test/subscription/t/013_partition.pl b/src/test/subscription/t/013_partition.pl index 6005178a32..2403bbfe4e 100644 --- a/src/test/subscription/t/013_partition.pl +++ b/src/test/subscription/t/013_partition.pl @@ -6,7 +6,7 @@ use strict; use warnings; use PostgreSQL::Test::Cluster; use PostgreSQL::Test::Utils; -use Test::More tests => 63; +use Test::More tests => 66; # setup @@ -347,6 +347,33 @@ $result = $node_subscriber2->safe_psql('postgres', "SELECT a FROM tab1 ORDER BY 1"); is($result, qq(), 'truncate of tab1 replicated'); +# check the replication after attaching to or detaching from a published +# partitioned table +$node_publisher->safe_psql('postgres', + "ALTER TABLE tab1 DETACH PARTITION tab1_2"); + +# the change on tab1_2 won't be replicated after detaching tab1_2 +# from the partitioned table. +$node_publisher->safe_psql('postgres', + "INSERT INTO tab1_2 (a) VALUES (4)"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE tab1 ATTACH PARTITION tab1_2 FOR VALUES IN (4, 5, 6)"); + +# the change on tab1_2 will be replicated after attaching tab1_2 to +# the partitioned table +$node_publisher->safe_psql('postgres', + "INSERT INTO tab1_2 (a) VALUES (5)"); + +$node_publisher->wait_for_catchup('sub1'); + +$result = + $node_subscriber1->safe_psql('postgres', "SELECT a FROM tab1_2 ORDER BY 1"); +is($result, qq(5), 'insert into tab1_2 replicated'); + +# clean the data +$node_publisher->safe_psql('postgres', "TRUNCATE tab1_2"); + # Check that subscriber handles cases where update/delete target tuple # is missing. We have to look for the DEBUG1 log messages about that, # so temporarily bump up the log verbosity. @@ -456,6 +483,9 @@ $node_subscriber2->safe_psql('postgres', $node_subscriber2->safe_psql('postgres', "CREATE TABLE tab2 (a int PRIMARY KEY, c text DEFAULT 'sub2_tab2', b text)" ); +$node_subscriber2->safe_psql('postgres', + "CREATE TABLE tab2_2 (a int PRIMARY KEY, c text DEFAULT 'sub2_tab2_2', b text)" +); $node_subscriber2->safe_psql('postgres', "CREATE TABLE tab3 (a int PRIMARY KEY, c text DEFAULT 'sub2_tab3', b text)" ); @@ -707,6 +737,45 @@ pub_tab2|3|yyy pub_tab2|5|zzz xxx_c|6|aaa), 'inserts into tab2 replicated'); +# check the replication after attaching to or detaching from a published +# partitioned table +$node_publisher->safe_psql('postgres', + "ALTER TABLE tab2 DETACH PARTITION tab2_2" +); + +# the change on tab2_2 won't be replicated to sub_viaroot after detaching tab2_2 +# from the partitioned table +$node_publisher->safe_psql('postgres', + "INSERT INTO tab2_2 VALUES (7, 'bbb')"); + +$node_publisher->safe_psql('postgres', + "ALTER TABLE tab2 ATTACH PARTITION tab2_2 FOR VALUES IN (5, 6, 7, 8)" +); + +# the change on tab2_2 will be replicated to sub_viaroot again after +# attaching tab2_2 to the partitioned table +$node_publisher->safe_psql('postgres', + "INSERT INTO tab2_2 (a, b) VALUES (8, 'aaa')"); + +$node_publisher->wait_for_catchup('sub_viaroot'); +$node_publisher->wait_for_catchup('sub2'); + +$result = $node_subscriber1->safe_psql('postgres', + "SELECT c, a, b FROM tab2 ORDER BY 1, 2"); +is( $result, qq(pub_tab2|1|xxx +pub_tab2|3|yyy +pub_tab2|5|zzz +pub_tab2|8|aaa +xxx_c|6|aaa), 'insert values (8, aaa) replicated'); + +$result = $node_subscriber2->safe_psql('postgres', + "SELECT c, a, b FROM tab2 ORDER BY 1, 2"); +is( $result, qq(pub_tab2|1|xxx +pub_tab2|3|yyy +pub_tab2|5|zzz +pub_tab2|8|aaa +xxx_c|6|aaa), 'insert values (8, aaa) replicated'); + # Check that subscriber handles cases where update/delete target tuple # is missing. We have to look for the DEBUG1 log messages about that, # so temporarily bump up the log verbosity. -- 2.18.4