Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 40ab64c

Browse files
author
Amit Kapila
committed
Fix ALTER PUBLICATION...DROP TABLE behavior.
Commit 69bd606 fixed the initialization of streamed transactions for RelationSyncEntry. It forgot to initialize the publication actions while invalidating the RelationSyncEntry due to which even though the relation is dropped from a particular publication we still publish its changes. Fix it by initializing pubactions when entry got invalidated. Author: Japin Li and Bharath Rupireddy Reviewed-by: Amit Kapila Discussion: https://postgr.es/m/CALj2ACV+0UFpcZs5czYgBpujM9p0Hg1qdOZai_43OU7bqHU_xw@mail.gmail.com
1 parent a4b03de commit 40ab64c

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

src/backend/replication/pgoutput/pgoutput.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,5 +1179,16 @@ rel_sync_cache_publication_cb(Datum arg, int cacheid, uint32 hashvalue)
11791179
*/
11801180
hash_seq_init(&status, RelationSyncCache);
11811181
while ((entry = (RelationSyncEntry *) hash_seq_search(&status)) != NULL)
1182+
{
11821183
entry->replicate_valid = false;
1184+
1185+
/*
1186+
* There might be some relations dropped from the publication so we
1187+
* don't need to publish the changes for them.
1188+
*/
1189+
entry->pubactions.pubinsert = false;
1190+
entry->pubactions.pubupdate = false;
1191+
entry->pubactions.pubdelete = false;
1192+
entry->pubactions.pubtruncate = false;
1193+
}
11831194
}

src/test/subscription/t/001_rep_changes.pl

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use warnings;
44
use PostgresNode;
55
use TestLib;
6-
use Test::More tests => 23;
6+
use Test::More tests => 27;
77

88
# Initialize publisher node
99
my $node_publisher = get_new_node('publisher');
@@ -153,6 +153,99 @@
153153
$node_publisher->safe_psql('postgres',
154154
"INSERT INTO tab_full SELECT generate_series(1,10)");
155155

156+
# Test behaviour of ALTER PUBLICATION ... DROP TABLE
157+
#
158+
# When a publisher drops a table from publication, it should also stop sending
159+
# its changes to subscribers. We look at the subscriber whether it receives
160+
# the row that is inserted to the table in the publisher after it is dropped
161+
# from the publication.
162+
$result = $node_subscriber->safe_psql('postgres',
163+
"SELECT count(*), min(a), max(a) FROM tab_ins");
164+
is($result, qq(1052|1|1002), 'check rows on subscriber before table drop from publication');
165+
166+
# Drop the table from publication
167+
$node_publisher->safe_psql('postgres',
168+
"ALTER PUBLICATION tap_pub_ins_only DROP TABLE tab_ins");
169+
170+
# Insert a row in publisher, but publisher will not send this row to subscriber
171+
$node_publisher->safe_psql('postgres', "INSERT INTO tab_ins VALUES(8888)");
172+
173+
$node_publisher->wait_for_catchup('tap_sub');
174+
175+
# Subscriber will not receive the inserted row, after table is dropped from
176+
# publication, so row count should remain the same.
177+
$result = $node_subscriber->safe_psql('postgres',
178+
"SELECT count(*), min(a), max(a) FROM tab_ins");
179+
is($result, qq(1052|1|1002), 'check rows on subscriber after table drop from publication');
180+
181+
# Delete the inserted row in publisher
182+
$node_publisher->safe_psql('postgres', "DELETE FROM tab_ins WHERE a = 8888");
183+
184+
# Add the table to publication again
185+
$node_publisher->safe_psql('postgres',
186+
"ALTER PUBLICATION tap_pub_ins_only ADD TABLE tab_ins");
187+
188+
# Refresh publication after table is added to publication
189+
$node_subscriber->safe_psql('postgres',
190+
"ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION");
191+
192+
# Test replication with multiple publications for a subscription such that the
193+
# operations are performed on the table from the first publication in the list.
194+
195+
# Create tables on publisher
196+
$node_publisher->safe_psql('postgres', "CREATE TABLE temp1 (a int)");
197+
$node_publisher->safe_psql('postgres', "CREATE TABLE temp2 (a int)");
198+
199+
# Create tables on subscriber
200+
$node_subscriber->safe_psql('postgres', "CREATE TABLE temp1 (a int)");
201+
$node_subscriber->safe_psql('postgres', "CREATE TABLE temp2 (a int)");
202+
203+
# Setup logical replication that will only be used for this test
204+
$node_publisher->safe_psql('postgres',
205+
"CREATE PUBLICATION tap_pub_temp1 FOR TABLE temp1 WITH (publish = insert)");
206+
$node_publisher->safe_psql('postgres',
207+
"CREATE PUBLICATION tap_pub_temp2 FOR TABLE temp2");
208+
$node_subscriber->safe_psql('postgres',
209+
"CREATE SUBSCRIPTION tap_sub_temp1 CONNECTION '$publisher_connstr' PUBLICATION tap_pub_temp1, tap_pub_temp2"
210+
);
211+
212+
$node_publisher->wait_for_catchup('tap_sub_temp1');
213+
214+
# Also wait for initial table sync to finish
215+
$synced_query =
216+
"SELECT count(1) = 0 FROM pg_subscription_rel WHERE srsubstate NOT IN ('r', 's');";
217+
$node_subscriber->poll_query_until('postgres', $synced_query)
218+
or die "Timed out while waiting for subscriber to synchronize data";
219+
220+
# Subscriber table will have no rows initially
221+
$result = $node_subscriber->safe_psql('postgres',
222+
"SELECT count(*) FROM temp1");
223+
is($result, qq(0), 'check initial rows on subscriber with multiple publications');
224+
225+
# Insert a row into the table that's part of first publication in subscriber
226+
# list of publications.
227+
$node_publisher->safe_psql('postgres', "INSERT INTO temp1 VALUES (1)");
228+
229+
$node_publisher->wait_for_catchup('tap_sub_temp1');
230+
231+
# Subscriber should receive the inserted row
232+
$result = $node_subscriber->safe_psql('postgres',
233+
"SELECT count(*) FROM temp1");
234+
is($result, qq(1), 'check rows on subscriber with multiple publications');
235+
236+
# Drop subscription as we don't need it anymore
237+
$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_temp1");
238+
239+
# Drop publications as we don't need them anymore
240+
$node_publisher->safe_psql('postgres', "DROP PUBLICATION tap_pub_temp1");
241+
$node_publisher->safe_psql('postgres', "DROP PUBLICATION tap_pub_temp2");
242+
243+
# Clean up the tables on both publisher and subscriber as we don't need them
244+
$node_publisher->safe_psql('postgres', "DROP TABLE temp1");
245+
$node_publisher->safe_psql('postgres', "DROP TABLE temp2");
246+
$node_subscriber->safe_psql('postgres', "DROP TABLE temp1");
247+
$node_subscriber->safe_psql('postgres', "DROP TABLE temp2");
248+
156249
# add REPLICA IDENTITY FULL so we can update
157250
$node_publisher->safe_psql('postgres',
158251
"ALTER TABLE tab_full REPLICA IDENTITY FULL");

0 commit comments

Comments
 (0)