From 5ad17c4ed06179889cc156d747624b060a54dc47 Mon Sep 17 00:00:00 2001
From: Osumi Takamichi <osumi.takamichi@fujitsu.com>
Date: Sat, 6 Feb 2021 07:01:46 +0000
Subject: [PATCH] tests for AlterSubscription and DROP SUBSCRIPTION

Check that to execute ALTER SUBSCRIPTION
with refresh in a transaction or in a function is not allowed.
Also, confirm that DROP SUBSCRIPTION during error
(like PK violation) of the subscriber can
clean up the publisher's slots correctly.

Author : Takamichi Osumi <osumi.takamichi@fujitsu.com>

---
 src/test/regress/expected/subscription.out | 20 ++++++++++++++++++++
 src/test/regress/sql/subscription.sql      | 21 +++++++++++++++++++++
 src/test/subscription/t/004_sync.pl        | 20 +++++++++++++++++++-
 3 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 2fa9bce..9dde54b 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -201,6 +201,26 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub;
+-- Executing ALTER SUBSCRIPTION with refresh in a transaction or function is not allowed
+CREATE SUBSCRIPTION mytest CONNECTION 'dbname=postgres' PUBLICATION mypub
+       WITH (enabled = true, create_slot = false, copy_data = false);
+BEGIN;
+ALTER SUBSCRIPTION mytest SET PUBLICATION foo WITH (refresh = true);
+ERROR:  ALTER SUBSCRIPTION with refresh cannot run inside a transaction block
+END;
+BEGIN;
+ALTER SUBSCRIPTION mytest REFRESH PUBLICATION;
+ERROR:  ALTER SUBSCRIPTION ... REFRESH cannot run inside a transaction block
+END;
+CREATE FUNCTION func() RETURNS VOID AS
+$$ ALTER SUBSCRIPTION mytest SET PUBLICATION mypub WITH (refresh = true) $$ LANGUAGE SQL;
+SELECT func();
+ERROR:  ALTER SUBSCRIPTION with refresh cannot be executed from a function
+CONTEXT:  SQL function "func" statement 1
+ALTER SUBSCRIPTION mytest DISABLE;
+ALTER SUBSCRIPTION mytest SET (slot_name = NONE);
+DROP SUBSCRIPTION mytest;
+DROP FUNCTION func;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_subscription_user;
 DROP ROLE regress_subscription_user2;
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 14fa0b2..567c451 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -147,6 +147,27 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 
 DROP SUBSCRIPTION regress_testsub;
 
+-- Executing ALTER SUBSCRIPTION with refresh in a transaction or function is not allowed
+CREATE SUBSCRIPTION mytest CONNECTION 'dbname=postgres' PUBLICATION mypub
+       WITH (enabled = true, create_slot = false, copy_data = false);
+
+BEGIN;
+ALTER SUBSCRIPTION mytest SET PUBLICATION foo WITH (refresh = true);
+END;
+
+BEGIN;
+ALTER SUBSCRIPTION mytest REFRESH PUBLICATION;
+END;
+
+CREATE FUNCTION func() RETURNS VOID AS
+$$ ALTER SUBSCRIPTION mytest SET PUBLICATION mypub WITH (refresh = true) $$ LANGUAGE SQL;
+SELECT func();
+
+ALTER SUBSCRIPTION mytest DISABLE;
+ALTER SUBSCRIPTION mytest SET (slot_name = NONE);
+DROP SUBSCRIPTION mytest;
+DROP FUNCTION func;
+
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_subscription_user;
 DROP ROLE regress_subscription_user2;
diff --git a/src/test/subscription/t/004_sync.pl b/src/test/subscription/t/004_sync.pl
index e111ab9..b5e5748 100644
--- a/src/test/subscription/t/004_sync.pl
+++ b/src/test/subscription/t/004_sync.pl
@@ -3,7 +3,7 @@ use strict;
 use warnings;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 7;
+use Test::More tests => 9;
 
 # Initialize publisher node
 my $node_publisher = get_new_node('publisher');
@@ -149,7 +149,25 @@ $result = $node_subscriber->safe_psql('postgres',
 is($result, qq(20),
 	'changes for table added after subscription initialized replicated');
 
+$node_publisher->safe_psql('postgres', "DROP TABLE tab_rep_next");
+$node_subscriber->safe_psql('postgres', "DROP TABLE tab_rep_next");
+
+# Check if DROP SUBSCRIPTION cleans up slots on the publisher side
+# when the subscriber is stuck on data copy for constraint
 $node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub");
+$node_subscriber->safe_psql('postgres',
+	 "CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr' PUBLICATION tap_pub");
+
+$result = $node_subscriber->poll_query_until('postgres', $started_query)
+    or die "Timed out while waiting for subscriber to start sync";
+
+$result = $node_publisher->safe_psql('postgres', "SELECT count(*) FROM pg_replication_slots");
+is($result, qq(2), 'There should be 2 slots on the publisher before dropping the slots');
+
+$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub");
+
+$result = $node_publisher->safe_psql('postgres', "SELECT count(*) FROM pg_replication_slots");
+is($result, qq(0), 'DROP SUBSCRIPTION during error can clean up the slots on the publisher');
 
 $node_subscriber->stop('fast');
 $node_publisher->stop('fast');
-- 
2.2.0

