On 5/27/17 06:54, Petr Jelinek wrote:
> On 27/05/17 04:00, Euler Taveira wrote:
>> 2017-05-26 21:29 GMT-03:00 Petr Jelinek <petr.jeli...@2ndquadrant.com
>> <mailto:petr.jeli...@2ndquadrant.com>>:
>>
>>
>>     Actually another possibility would be to remove the REFRESH keyword
>>     completely and just have [ WITH (...) ] and have the refresh option
>>     there, ie simplified version of what you have suggested (without the
>>     ugliness of specifying refresh twice to disable).
>>
>>
>> It will cause confusion. It seems that WITH sets ALTER SUBSCRIPTION
>> properties. Indeed, they are REFRESH properties. I think we shouldn't
>> exclude REFRESH keyword. Syntax leaves no doubt that WITH are REFRESH
>> properties.
>>
> 
> Maybe, I don't know, it might not be that confusing when SET PUBLICATION
> and REFRESH PUBLICATION have same set of WITH options.

I'm not sure what the conclusion from the above discussion was supposed
to be, but here is a patch.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 697c4cbdd386a4bd856614de6cedf5af8d1b63be Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Fri, 2 Jun 2017 21:59:07 -0400
Subject: [PATCH] Fix ALTER SUBSCRIPTION grammar ambiguity

There was a grammar ambiguity between SET PUBLICATION name REFRESH and
SET PUBLICATION SKIP REFRESH, because SKIP is not a reserved word.  To
resolve that, fold the refresh choice into the WITH options.  Refreshing
is the default now.

Author: tushar <tushar.ah...@enterprisedb.com>
---
 doc/src/sgml/catalogs.sgml                 |  2 +-
 doc/src/sgml/ref/alter_subscription.sgml   | 35 ++++++++++++++++++++----------
 src/backend/commands/subscriptioncmds.c    | 34 +++++++++++++++++++++--------
 src/backend/parser/gram.y                  | 14 ++----------
 src/include/nodes/parsenodes.h             |  1 -
 src/test/regress/expected/subscription.out |  2 +-
 src/test/regress/sql/subscription.sql      |  2 +-
 src/test/subscription/t/001_rep_changes.pl |  2 +-
 8 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index b2fae027f5..5723be744d 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -6609,7 +6609,7 @@ 
<title><structname>pg_subscription_rel</structname></title>
   <para>
    This catalog only contains tables known to the subscription after running
    either <command>CREATE SUBSCRIPTION</command> or
-   <command>ALTER SUBSCRIPTION ... REFRESH</command>.
+   <command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command>.
   </para>
 
   <table>
diff --git a/doc/src/sgml/ref/alter_subscription.sgml 
b/doc/src/sgml/ref/alter_subscription.sgml
index a3471a0442..bead99622e 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -22,7 +22,7 @@
  <refsynopsisdiv>
 <synopsis>
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> 
CONNECTION '<replaceable>conninfo</replaceable>'
-ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET 
PUBLICATION <replaceable class="PARAMETER">publication_name</replaceable> [, 
...] { REFRESH [ WITH ( <replaceable 
class="PARAMETER">refresh_option</replaceable> [= <replaceable 
class="PARAMETER">value</replaceable>] [, ... ] ) ] | SKIP REFRESH }
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET 
PUBLICATION <replaceable class="PARAMETER">publication_name</replaceable> [, 
...] [ WITH ( <replaceable 
class="PARAMETER">set_publication_option</replaceable> [= <replaceable 
class="PARAMETER">value</replaceable>] [, ... ] ) ]
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> REFRESH 
PUBLICATION [ WITH ( <replaceable 
class="PARAMETER">refresh_option</replaceable> [= <replaceable 
class="PARAMETER">value</replaceable>] [, ... ] ) ]
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> ENABLE
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> DISABLE
@@ -80,18 +80,29 @@ <title>Parameters</title>
      <para>
       Changes list of subscribed publications. See
       <xref linkend="SQL-CREATESUBSCRIPTION"> for more information.
+      By default this command will also act like <literal>REFRESH
+      PUBLICATION</literal>.
      </para>
 
      <para>
-      When <literal>REFRESH</literal> is specified, this command will also act
-      like <literal>REFRESH
-      PUBLICATION</literal>.  <literal>refresh_option</literal> specifies
-      additional options for the refresh operation, as described
-      under <literal>REFRESH PUBLICATION</literal>.  When
-      <literal>SKIP REFRESH</literal> is specified, the command will not try
-      to refresh table information.  Note that
-      either <literal>REFRESH</literal> or <literal>SKIP REFRESH</literal>
-      must be specified.
+      <replaceable>set_publication_option</replaceable> specifies additional
+      options for this operation.  The supported options are:
+
+      <variablelist>
+       <varlistentry>
+        <term><literal>refresh</literal> (<type>boolean</type>)</term>
+        <listitem>
+         <para>
+          When false, the command will not try to refresh table information.
+          <literal>REFRESH PUBLICATION</literal> should then be executed 
separately.
+          The default is <literal>true</literal>.
+         </para>
+        </listitem>
+       </varlistentry>
+      </variablelist>
+
+      Additionally, refresh options as described
+      under <literal>REFRESH PUBLICATION</literal> may be specified.
      </para>
     </listitem>
    </varlistentry>
@@ -107,7 +118,7 @@ <title>Parameters</title>
      </para>
 
      <para>
-      <literal>refresh_option</literal> specifies additional options for the
+      <replaceable>refresh_option</replaceable> specifies additional options 
for the
       refresh operation.  The supported options are:
 
       <variablelist>
@@ -185,7 +196,7 @@ <title>Examples</title>
    Change the publication subscribed by a subscription to
    <literal>insert_only</literal>:
 <programlisting>
-ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only REFRESH;
+ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only;
 </programlisting>
   </para>
 
diff --git a/src/backend/commands/subscriptioncmds.c 
b/src/backend/commands/subscriptioncmds.c
index 86eb31df93..ad98b38efe 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -64,12 +64,14 @@ static void
 parse_subscription_options(List *options, bool *connect, bool *enabled_given,
                                                   bool *enabled, bool 
*create_slot,
                                                   bool *slot_name_given, char 
**slot_name,
-                                                  bool *copy_data, char 
**synchronous_commit)
+                                                  bool *copy_data, char 
**synchronous_commit,
+                                                  bool *refresh)
 {
        ListCell   *lc;
        bool            connect_given = false;
        bool            create_slot_given = false;
        bool            copy_data_given = false;
+       bool            refresh_given = false;
 
        /* If connect is specified, the others also need to be. */
        Assert(!connect || (enabled && create_slot && copy_data));
@@ -92,6 +94,8 @@ parse_subscription_options(List *options, bool *connect, bool 
*enabled_given,
                *copy_data = true;
        if (synchronous_commit)
                *synchronous_commit = NULL;
+       if (refresh)
+               *refresh = true;
 
        /* Parse options */
        foreach(lc, options)
@@ -167,6 +171,16 @@ parse_subscription_options(List *options, bool *connect, 
bool *enabled_given,
                                                                         
PGC_BACKEND, PGC_S_TEST, GUC_ACTION_SET,
                                                                         false, 
0, false);
                }
+               else if (strcmp(defel->defname, "refresh") == 0 && refresh)
+               {
+                       if (refresh_given)
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                                errmsg("conflicting or 
redundant options")));
+
+                       refresh_given = true;
+                       *refresh = defGetBoolean(defel);
+               }
                else
                        ereport(ERROR,
                                        (errcode(ERRCODE_SYNTAX_ERROR),
@@ -315,7 +329,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool 
isTopLevel)
         */
        parse_subscription_options(stmt->options, &connect, &enabled_given,
                                                           &enabled, 
&create_slot, &slotname_given,
-                                                          &slotname, 
&copy_data, &synchronous_commit);
+                                                          &slotname, 
&copy_data, &synchronous_commit,
+                                                          NULL);
 
        /*
         * Since creating a replication slot is not transactional, rolling back
@@ -645,7 +660,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 
                                parse_subscription_options(stmt->options, NULL, 
NULL, NULL,
                                                                                
   NULL, &slotname_given, &slotname,
-                                                                               
   NULL, &synchronous_commit);
+                                                                               
   NULL, &synchronous_commit, NULL);
 
                                if (slotname_given)
                                {
@@ -680,7 +695,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 
                                parse_subscription_options(stmt->options, NULL,
                                                                                
   &enabled_given, &enabled, NULL,
-                                                                               
   NULL, NULL, NULL, NULL);
+                                                                               
   NULL, NULL, NULL, NULL, NULL);
                                Assert(enabled_given);
 
                                if (!sub->slotname && enabled)
@@ -712,13 +727,13 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
                        break;
 
                case ALTER_SUBSCRIPTION_PUBLICATION:
-               case ALTER_SUBSCRIPTION_PUBLICATION_REFRESH:
                        {
                                bool            copy_data;
+                               bool            refresh;
 
                                parse_subscription_options(stmt->options, NULL, 
NULL, NULL,
                                                                                
   NULL, NULL, NULL, &copy_data,
-                                                                               
   NULL);
+                                                                               
   NULL, &refresh);
 
                                values[Anum_pg_subscription_subpublications - 
1] =
                                        
publicationListToArray(stmt->publication);
@@ -727,12 +742,13 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
                                update_tuple = true;
 
                                /* Refresh if user asked us to. */
-                               if (stmt->kind == 
ALTER_SUBSCRIPTION_PUBLICATION_REFRESH)
+                               if (refresh)
                                {
                                        if (!sub->enabled)
                                                ereport(ERROR,
                                                                
(errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("ALTER 
SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
+                                                                errmsg("ALTER 
SUBSCRIPTION with refresh is not allowed for disabled subscriptions"),
+                                                                errhint("Use 
ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false).")));
 
                                        /* Make sure refresh sees the new list 
of publications. */
                                        sub->publications = stmt->publication;
@@ -754,7 +770,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 
                                parse_subscription_options(stmt->options, NULL, 
NULL, NULL,
                                                                                
   NULL, NULL, NULL, &copy_data,
-                                                                               
   NULL);
+                                                                               
   NULL, NULL);
 
                                AlterSubscription_refresh(sub, copy_data);
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7e03624eb4..ada95e5bc3 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -9279,24 +9279,14 @@ AlterSubscriptionStmt:
                                        n->options = $6;
                                        $$ = (Node *)n;
                                }
-                       | ALTER SUBSCRIPTION name SET PUBLICATION 
publication_name_list REFRESH opt_definition
-                               {
-                                       AlterSubscriptionStmt *n =
-                                               makeNode(AlterSubscriptionStmt);
-                                       n->kind = 
ALTER_SUBSCRIPTION_PUBLICATION_REFRESH;
-                                       n->subname = $3;
-                                       n->publication = $6;
-                                       n->options = $8;
-                                       $$ = (Node *)n;
-                               }
-                       | ALTER SUBSCRIPTION name SET PUBLICATION 
publication_name_list SKIP REFRESH
+                       | ALTER SUBSCRIPTION name SET PUBLICATION 
publication_name_list opt_definition
                                {
                                        AlterSubscriptionStmt *n =
                                                makeNode(AlterSubscriptionStmt);
                                        n->kind = 
ALTER_SUBSCRIPTION_PUBLICATION;
                                        n->subname = $3;
                                        n->publication = $6;
-                                       n->options = NIL;
+                                       n->options = $7;
                                        $$ = (Node *)n;
                                }
                        | ALTER SUBSCRIPTION name ENABLE_P
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 8720e713c4..2d2e2c0fbc 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -3382,7 +3382,6 @@ typedef enum AlterSubscriptionType
        ALTER_SUBSCRIPTION_OPTIONS,
        ALTER_SUBSCRIPTION_CONNECTION,
        ALTER_SUBSCRIPTION_PUBLICATION,
-       ALTER_SUBSCRIPTION_PUBLICATION_REFRESH,
        ALTER_SUBSCRIPTION_REFRESH,
        ALTER_SUBSCRIPTION_ENABLED
 } AlterSubscriptionType;
diff --git a/src/test/regress/expected/subscription.out 
b/src/test/regress/expected/subscription.out
index 91ba8ab95a..4fcbf7efe9 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -82,7 +82,7 @@ ERROR:  invalid connection string syntax: missing "=" after 
"foobar" in connecti
  testsub | regress_subscription_user | f       | {testpub}   | off             
   | dbname=doesnotexist
 (1 row)
 
-ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
+ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = 
false);
 ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
 ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
 -- fail
diff --git a/src/test/regress/sql/subscription.sql 
b/src/test/regress/sql/subscription.sql
index 4b694a357e..36fa1bbac8 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -61,7 +61,7 @@ CREATE SUBSCRIPTION testsub3 CONNECTION 'dbname=doesnotexist' 
PUBLICATION testpu
 
 \dRs+
 
-ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
+ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = 
false);
 ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
 ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
 
diff --git a/src/test/subscription/t/001_rep_changes.pl 
b/src/test/subscription/t/001_rep_changes.pl
index e5638d3322..f9cf5e4392 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -143,7 +143,7 @@
        "SELECT pid FROM pg_stat_replication WHERE application_name = 
'$appname';"
 );
 $node_subscriber->safe_psql('postgres',
-"ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_ins_only REFRESH WITH 
(copy_data = false)"
+"ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_ins_only WITH (copy_data = 
false)"
 );
 $node_publisher->poll_query_until('postgres',
 "SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = 
'$appname';"
-- 
2.13.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to