From 74211d016528699205163dab8ecc7fe04aec09b2 Mon Sep 17 00:00:00 2001 From: Vigneshwaran C Date: Sat, 12 Mar 2022 13:04:55 +0530 Subject: [PATCH v4] Fix for invalidating logical replication relations when there is a change in schema. When the schema gets changed, the rel sync cache invalidation was not happening, fixed it by adding a callback for schema change. --- src/backend/replication/pgoutput/pgoutput.c | 3 + src/test/subscription/t/001_rep_changes.pl | 67 +++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c index 7737242516..f68c271cf2 100644 --- a/src/backend/replication/pgoutput/pgoutput.c +++ b/src/backend/replication/pgoutput/pgoutput.c @@ -1936,6 +1936,9 @@ init_rel_sync_cache(MemoryContext cachectx) CacheRegisterSyscacheCallback(PUBLICATIONNAMESPACEMAP, rel_sync_cache_publication_cb, (Datum) 0); + CacheRegisterSyscacheCallback(NAMESPACEOID, + rel_sync_cache_publication_cb, + (Datum) 0); } /* diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl index 91aa068c95..3e91640c03 100644 --- a/src/test/subscription/t/001_rep_changes.pl +++ b/src/test/subscription/t/001_rep_changes.pl @@ -542,6 +542,73 @@ is($result, qq(0), 'check replication origin was dropped on subscriber'); $node_subscriber->stop('fast'); $node_publisher->stop('fast'); +# Test schema invalidation by renaming the schema +# Create tables on publisher +# Initialize publisher node +my $node_publisher1 = PostgreSQL::Test::Cluster->new('publisher1'); +$node_publisher1->init(allows_streaming => 'logical'); +$node_publisher1->start; + +# Create subscriber node +my $node_subscriber1 = PostgreSQL::Test::Cluster->new('subscriber1'); +$node_subscriber1->init(allows_streaming => 'logical'); +$node_subscriber1->start; + +my $publisher1_connstr = $node_publisher1->connstr . ' dbname=postgres'; + +$node_publisher1->safe_psql('postgres', "CREATE SCHEMA sch1"); +$node_publisher1->safe_psql('postgres', "CREATE TABLE sch1.t1 (c1 int)"); + +# Create tables on subscriber +$node_subscriber1->safe_psql('postgres', "CREATE SCHEMA sch1"); +$node_subscriber1->safe_psql('postgres', "CREATE TABLE sch1.t1 (c1 int)"); +$node_subscriber1->safe_psql('postgres', "CREATE SCHEMA sch2"); +$node_subscriber1->safe_psql('postgres', "CREATE TABLE sch2.t1 (c1 int)"); + +# Setup logical replication that will only be used for this test +$node_publisher1->safe_psql('postgres', + "CREATE PUBLICATION tap_pub_sch FOR ALL TABLES" +); +$node_subscriber1->safe_psql('postgres', + "CREATE SUBSCRIPTION tap_sub_sch CONNECTION '$publisher1_connstr' PUBLICATION tap_pub_sch" +); + +# Wait for initial table sync to finish +$node_subscriber1->wait_for_subscription_sync($node_publisher1, 'tap_sub_sch'); + +$node_publisher1->safe_psql('postgres', + "begin; +insert into sch1.t1 values(1); +alter schema sch1 rename to sch2; +create schema sch1; +create table sch1.t1(c1 int); +insert into sch1.t1 values(2); +insert into sch2.t1 values(3); +commit;"); + +$node_subscriber1->wait_for_subscription_sync($node_publisher1, 'tap_sub_sch'); + +# Subscriber should not receive the inserted row for renamed schema +$result = + $node_subscriber1->safe_psql('postgres', "SELECT * FROM sch1.t1"); +is($result, qq(1 +2), 'check rows on subscriber after schema invalidation'); + +# Drop subscription as we don't need it anymore +$node_subscriber1->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_sch"); + +# Drop publications as we don't need them anymore +$node_publisher1->safe_psql('postgres', "DROP PUBLICATION tap_pub_sch"); + +# Clean up the tables on both publisher and subscriber as we don't need them +$node_publisher1->safe_psql('postgres', "DROP SCHEMA sch1 cascade"); +$node_publisher1->safe_psql('postgres', "DROP SCHEMA sch2 cascade"); +$node_subscriber1->safe_psql('postgres', "DROP SCHEMA sch1 cascade"); +$node_subscriber1->safe_psql('postgres', "DROP SCHEMA sch2 cascade"); + +$node_subscriber1->stop('fast'); +$node_publisher1->stop('fast'); + # CREATE PUBLICATION while wal_level=minimal should succeed, with a WARNING $node_publisher->append_conf( 'postgresql.conf', qq( -- 2.34.1