Add RENAME support for PUBLICATIONs and SUBSCRIPTIONs
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 3 Mar 2017 15:47:04 +0000 (10:47 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 3 Mar 2017 15:47:04 +0000 (10:47 -0500)
From: Petr Jelinek <petr.jelinek@2ndquadrant.com>

src/backend/commands/alter.c
src/backend/parser/gram.y
src/backend/replication/logical/worker.c
src/bin/psql/tab-complete.c
src/test/regress/expected/publication.out
src/test/regress/expected/subscription.out
src/test/regress/sql/publication.sql
src/test/regress/sql/subscription.sql
src/test/subscription/t/001_rep_changes.pl

index d6195e49f5e8762cd7b96bd7ff7b1acc9c94e047..8ff5dd5aaf2d4f8f8c6cadd1a5217fcf53b02740 100644 (file)
@@ -32,6 +32,7 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_subscription.h"
 #include "catalog/pg_ts_config.h"
 #include "catalog/pg_ts_dict.h"
 #include "catalog/pg_ts_parser.h"
@@ -90,6 +91,12 @@ report_name_conflict(Oid classId, const char *name)
        case LanguageRelationId:
            msgfmt = gettext_noop("language \"%s\" already exists");
            break;
+       case PublicationRelationId:
+           msgfmt = gettext_noop("publication \"%s\" already exists");
+           break;
+       case SubscriptionRelationId:
+           msgfmt = gettext_noop("subscription \"%s\" already exists");
+           break;
        default:
            elog(ERROR, "unsupported object class %u", classId);
            break;
@@ -256,6 +263,12 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
        IsThereOpFamilyInNamespace(new_name, opf->opfmethod,
                                   opf->opfnamespace);
    }
+   else if (classId == SubscriptionRelationId)
+   {
+       if (SearchSysCacheExists2(SUBSCRIPTIONNAME, MyDatabaseId,
+                                 CStringGetDatum(new_name)))
+           report_name_conflict(classId, new_name);
+   }
    else if (nameCacheId >= 0)
    {
        if (OidIsValid(namespaceId))
@@ -364,6 +377,8 @@ ExecRenameStmt(RenameStmt *stmt)
        case OBJECT_TSDICTIONARY:
        case OBJECT_TSPARSER:
        case OBJECT_TSTEMPLATE:
+       case OBJECT_PUBLICATION:
+       case OBJECT_SUBSCRIPTION:
            {
                ObjectAddress address;
                Relation    catalog;
index e833b2eba5a0b4dcb5d994c845e7c61700030b51..9713b4422324f01b12dd1ab0cfac531d1d12a2ab 100644 (file)
@@ -8151,6 +8151,15 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
                    n->missing_ok = true;
                    $$ = (Node *)n;
                }
+           | ALTER PUBLICATION name RENAME TO name
+               {
+                   RenameStmt *n = makeNode(RenameStmt);
+                   n->renameType = OBJECT_PUBLICATION;
+                   n->object = list_make1(makeString($3));
+                   n->newname = $6;
+                   n->missing_ok = false;
+                   $$ = (Node *)n;
+               }
            | ALTER SCHEMA name RENAME TO name
                {
                    RenameStmt *n = makeNode(RenameStmt);
@@ -8169,6 +8178,15 @@ RenameStmt: ALTER AGGREGATE aggregate_with_argtypes RENAME TO name
                    n->missing_ok = false;
                    $$ = (Node *)n;
                }
+           | ALTER SUBSCRIPTION name RENAME TO name
+               {
+                   RenameStmt *n = makeNode(RenameStmt);
+                   n->renameType = OBJECT_SUBSCRIPTION;
+                   n->object = list_make1(makeString($3));
+                   n->newname = $6;
+                   n->missing_ok = false;
+                   $$ = (Node *)n;
+               }
            | ALTER TABLE relation_expr RENAME TO name
                {
                    RenameStmt *n = makeNode(RenameStmt);
index 718aafb78a7550cc0de93a664e24f02ebd4d87a7..535aa2df1ba42ac031581cb6d51449309fa98689 100644 (file)
@@ -1259,6 +1259,21 @@ reread_subscription(void)
        proc_exit(0);
    }
 
+   /*
+    * Exit if subscription name was changed (it's used for
+    * fallback_application_name). The launcher will start new worker.
+    */
+   if (strcmp(newsub->name, MySubscription->name) != 0)
+   {
+       ereport(LOG,
+               (errmsg("logical replication worker for subscription \"%s\" will "
+                       "restart because subscription was renamed",
+                       MySubscription->name)));
+
+       walrcv_disconnect(wrconn);
+       proc_exit(0);
+   }
+
    /*
     * Exit if publication list was changed. The launcher will start
     * new worker.
@@ -1292,7 +1307,6 @@ reread_subscription(void)
 
    /* Check for other changes that should never happen too. */
    if (newsub->dbid != MySubscription->dbid ||
-       strcmp(newsub->name, MySubscription->name) != 0 ||
        strcmp(newsub->slotname, MySubscription->slotname) != 0)
    {
        elog(ERROR, "subscription %u changed unexpectedly",
index 38a3fd27c46f0c9c2697cce58ce2eb30acd5afe2..115cb5ce716cef6c44714651b5ae5488ed8c4385 100644 (file)
@@ -1463,7 +1463,8 @@ psql_completion(const char *text, int start, int end)
    /* ALTER PUBLICATION <name> ...*/
    else if (Matches3("ALTER","PUBLICATION",MatchAny))
    {
-       COMPLETE_WITH_LIST5("WITH", "ADD TABLE", "SET TABLE", "DROP TABLE", "OWNER TO");
+       COMPLETE_WITH_LIST6("WITH", "ADD TABLE", "SET TABLE", "DROP TABLE",
+                           "OWNER TO", "RENAME TO");
    }
    /* ALTER PUBLICATION <name> .. WITH ( ... */
    else if (HeadMatches3("ALTER", "PUBLICATION",MatchAny) && TailMatches2("WITH", "("))
@@ -1474,7 +1475,8 @@ psql_completion(const char *text, int start, int end)
    /* ALTER SUBSCRIPTION <name> ... */
    else if (Matches3("ALTER","SUBSCRIPTION",MatchAny))
    {
-       COMPLETE_WITH_LIST6("WITH", "CONNECTION", "SET PUBLICATION", "ENABLE", "DISABLE", "OWNER TO");
+       COMPLETE_WITH_LIST7("WITH", "CONNECTION", "SET PUBLICATION", "ENABLE",
+                           "DISABLE", "OWNER TO", "RENAME TO");
    }
    else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("WITH", "("))
    {
index 5784b0fded47baa8d0cde9a825a9e362e9baf668..6416fbb9142eb311ccd5d68c7da5b8ce165f53cc 100644 (file)
@@ -148,7 +148,15 @@ DROP TABLE testpub_tbl1;
  t       | t       | t
 (1 row)
 
-DROP PUBLICATION testpub_default;
+ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
+\dRp testpub_foo
+                         List of publications
+    Name     |          Owner           | Inserts | Updates | Deletes 
+-------------+--------------------------+---------+---------+---------
+ testpub_foo | regress_publication_user | t       | t       | t
+(1 row)
+
+DROP PUBLICATION testpub_foo;
 DROP PUBLICATION testpib_ins_trunct;
 DROP PUBLICATION testpub_fortbl;
 DROP SCHEMA pub_test CASCADE;
index 2ccec98b15806958c6425855f082780188f94d6c..cb1ab4e7914a4143a3be5ce82017cc45f205e5de 100644 (file)
@@ -61,6 +61,14 @@ ALTER SUBSCRIPTION testsub DISABLE;
 (1 row)
 
 COMMIT;
-DROP SUBSCRIPTION testsub NODROP SLOT;
+ALTER SUBSCRIPTION testsub RENAME TO testsub_foo;
+\dRs
+                         List of subscriptions
+    Name     |           Owner           | Enabled |    Publication     
+-------------+---------------------------+---------+--------------------
+ testsub_foo | regress_subscription_user | f       | {testpub,testpub1}
+(1 row)
+
+DROP SUBSCRIPTION testsub_foo NODROP SLOT;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_subscription_user;
index 87797884d25367f2772fff0e3c814542dbc030c3..9563ea1857294f182b0c1acf36696245ece94723 100644 (file)
@@ -73,7 +73,11 @@ DROP TABLE testpub_tbl1;
 
 \dRp+ testpub_default
 
-DROP PUBLICATION testpub_default;
+ALTER PUBLICATION testpub_default RENAME TO testpub_foo;
+
+\dRp testpub_foo
+
+DROP PUBLICATION testpub_foo;
 DROP PUBLICATION testpib_ins_trunct;
 DROP PUBLICATION testpub_fortbl;
 
index 68c17d5cfdacc72d233c1aeb31529f7b1951b340..fce6069a9cd71f9a281ba0862b3d147adae2a826 100644 (file)
@@ -38,7 +38,11 @@ ALTER SUBSCRIPTION testsub DISABLE;
 
 COMMIT;
 
-DROP SUBSCRIPTION testsub NODROP SLOT;
+ALTER SUBSCRIPTION testsub RENAME TO testsub_foo;
+
+\dRs
+
+DROP SUBSCRIPTION testsub_foo NODROP SLOT;
 
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_subscription_user;
index fa50e495a5515ed44478f3b036a9525ea0a6a0c7..fffb3c51bef969336ef5203416bcdcd051258c1c 100644 (file)
@@ -169,8 +169,17 @@ $result =
   $node_subscriber->safe_psql('postgres', "SELECT count(*), min(a), max(a) FROM tab_full");
 is($result, qq(11|0|100), 'check replicated insert after alter publication');
 
+# check restart on rename
+$oldpid = $node_publisher->safe_psql('postgres',
+   "SELECT pid FROM pg_stat_replication WHERE application_name = '$appname';");
+$node_subscriber->safe_psql('postgres',
+   "ALTER SUBSCRIPTION tap_sub RENAME TO tap_sub_renamed");
+$node_publisher->poll_query_until('postgres',
+   "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname';")
+  or die "Timed out while waiting for apply to restart";
+
 # check all the cleanup
-$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub");
+$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION tap_sub_renamed");
 
 $result =
   $node_subscriber->safe_psql('postgres', "SELECT count(*) FROM pg_subscription");