>From 30dc7544919c97610e1c22ef711ccbfd1873b921 Mon Sep 17 00:00:00 2001
From: Petr Jelinek <pjmodos@pjmodos.net>
Date: Wed, 3 May 2017 11:39:22 +0200
Subject: [PATCH] Rework the options for logical replication

Use similar option style as other statements which use WITH clause for
options.
---
 doc/src/sgml/ref/alter_publication.sgml            |  25 +--
 doc/src/sgml/ref/alter_subscription.sgml           |  72 +++++--
 doc/src/sgml/ref/create_publication.sgml           |  57 ++---
 doc/src/sgml/ref/create_subscription.sgml          | 229 +++++++++++----------
 src/backend/commands/publicationcmds.c             | 133 +++++-------
 src/backend/commands/subscriptioncmds.c            |  42 +---
 src/backend/parser/gram.y                          |   8 +-
 src/bin/pg_dump/pg_dump.c                          |  36 ++--
 src/bin/pg_dump/t/002_pg_dump.pl                   |  12 +-
 src/bin/psql/tab-complete.c                        |  16 +-
 src/include/parser/kwlist.h                        |   1 -
 .../dummy_seclabel/expected/dummy_seclabel.out     |   2 +-
 .../modules/dummy_seclabel/sql/dummy_seclabel.sql  |   2 +-
 src/test/regress/expected/object_address.out       |   2 +-
 src/test/regress/expected/publication.out          |  10 +-
 src/test/regress/expected/subscription.out         |  22 +-
 src/test/regress/sql/object_address.sql            |   2 +-
 src/test/regress/sql/publication.sql               |  10 +-
 src/test/regress/sql/subscription.sql              |  20 +-
 src/test/subscription/t/001_rep_changes.pl         |   8 +-
 src/test/subscription/t/002_types.pl               |   2 +-
 src/test/subscription/t/003_constraints.pl         |   2 +-
 src/test/subscription/t/004_sync.pl                |   2 +-
 23 files changed, 328 insertions(+), 387 deletions(-)

diff --git a/doc/src/sgml/ref/alter_publication.sgml b/doc/src/sgml/ref/alter_publication.sgml
index 05bd57d..00e5cfe 100644
--- a/doc/src/sgml/ref/alter_publication.sgml
+++ b/doc/src/sgml/ref/alter_publication.sgml
@@ -21,14 +21,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="PARAMETER">option</replaceable> [, ... ] )
-
-<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
-
-      PUBLISH INSERT | NOPUBLISH INSERT
-    | PUBLISH UPDATE | NOPUBLISH UPDATE
-    | PUBLISH DELETE | NOPUBLISH DELETE
-
+ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="parameter">publication_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )
 ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> ADD TABLE [ ONLY ] <replaceable class="PARAMETER">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> SET TABLE [ ONLY ] <replaceable class="PARAMETER">table_name</replaceable> [ * ] [, ...]
 ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> DROP TABLE [ ONLY ] <replaceable class="PARAMETER">table_name</replaceable> [ * ] [, ...]
@@ -44,8 +37,7 @@ ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> RENAME TO <r
    The first variant of this command listed in the synopsis can change
    all of the publication properties specified in
    <xref linkend="sql-createpublication">.  Properties not mentioned in the
-   command retain their previous settings.  Database superusers can change any
-   of these settings for any role.
+   command retain their previous settings.
   </para>
 
   <para>
@@ -80,15 +72,10 @@ ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> RENAME TO <r
    </varlistentry>
 
    <varlistentry>
-    <term><literal>PUBLISH INSERT</literal></term>
-    <term><literal>NOPUBLISH INSERT</literal></term>
-    <term><literal>PUBLISH UPDATE</literal></term>
-    <term><literal>NOPUBLISH UPDATE</literal></term>
-    <term><literal>PUBLISH DELETE</literal></term>
-    <term><literal>NOPUBLISH DELETE</literal></term>
+    <term><literal>publish</literal></term>
     <listitem>
      <para>
-      These clauses alter properties originally set by
+      This clause alters property originally set by
       <xref linkend="SQL-CREATEPUBLICATION">.  See there for more information.
      </para>
     </listitem>
@@ -131,9 +118,9 @@ ALTER PUBLICATION <replaceable class="PARAMETER">name</replaceable> RENAME TO <r
   <title>Examples</title>
 
   <para>
-   Change the publication to not publish inserts:
+   Change the publication to publish only deletes and updates:
 <programlisting>
-ALTER PUBLICATION noinsert WITH (NOPUBLISH INSERT);
+ALTER PUBLICATION noinsert OPTIONS (publish 'update, delete');
 </programlisting>
   </para>
 
diff --git a/doc/src/sgml/ref/alter_subscription.sgml b/doc/src/sgml/ref/alter_subscription.sgml
index 5dae4ae..57652d1 100644
--- a/doc/src/sgml/ref/alter_subscription.sgml
+++ b/doc/src/sgml/ref/alter_subscription.sgml
@@ -21,20 +21,9 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="PARAMETER">suboption</replaceable> [, ... ] )
-
-<phrase>where <replaceable class="PARAMETER">suboption</replaceable> can be:</phrase>
-
-    SLOT NAME = <replaceable class="PARAMETER">slot_name</replaceable>
-    | SYNCHRONOUS_COMMIT = <replaceable class="PARAMETER">synchronous_commit</replaceable>
-
-ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET PUBLICATION <replaceable class="PARAMETER">publication_name</replaceable> [, ...] { REFRESH WITH ( <replaceable class="PARAMETER">puboption</replaceable> [, ... ] ) | NOREFRESH }
-ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> REFRESH PUBLICATION [ WITH ( <replaceable class="PARAMETER">puboption</replaceable> [, ... ] ) ]
-
-<phrase>where <replaceable class="PARAMETER">puboption</replaceable> can be:</phrase>
-
-    COPY DATA | NOCOPY DATA
-
+ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> WITH ( <replaceable class="parameter">subscription_option</replaceable> [= <replaceable class="parameter">value</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> REFRESH PUBLICATION [ WITH ( <replaceable class="PARAMETER">refresh_option</replaceable> <replaceable class="PARAMETER">value</replaceable> [, ... ] ) ]
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> CONNECTION '<replaceable>conninfo</replaceable>'
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> ENABLE
 ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> DISABLE
@@ -73,11 +62,9 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
 
    <varlistentry>
     <term><literal>CONNECTION '<replaceable class="parameter">conninfo</replaceable>'</literal></term>
-    <term><literal>SLOT NAME = <replaceable class="parameter">slot_name</replaceable></literal></term>
-    <term><literal>SYNCHRONOUS_COMMIT = <replaceable class="PARAMETER">synchronous_commit</replaceable></literal></term>
     <listitem>
      <para>
-      These clauses alter properties originally set by
+      This clause alter property originally set by
       <xref linkend="SQL-CREATESUBSCRIPTION">.  See there for more
       information.
      </para>
@@ -85,6 +72,18 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
    </varlistentry>
 
    <varlistentry>
+    <term><literal>WITH ( <replaceable class="parameter">subscription_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
+    <listitem>
+     <para>
+      This clause alter property originally set by
+      <xref linkend="SQL-CREATESUBSCRIPTION">.  See there for more
+      information.  The allowed options are <literal>slot_name</literal> and
+      <literal>synchronous_commit</literal>
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
     <term><literal>SET PUBLICATION <replaceable class="parameter">publication_name</replaceable></literal></term>
     <listitem>
      <para>
@@ -97,7 +96,12 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
       <literal>NOREFRESH</literal> is specified, the comamnd will not try to
       refresh table information.
      </para>
-    </listitem>
+      <para>
+      The <literal>refresh_option</literal> is an additional option for the
+      refresh operation.  See
+      <xref linkend="sql-altersubscription-refresh-options"> for details.
+     </para>
+   </listitem>
    </varlistentry>
 
    <varlistentry>
@@ -110,10 +114,9 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
       since <command>CREATE SUBSCRIPTION</command>.
      </para>
      <para>
-      The <literal>COPY DATA</literal> and <literal>NOCOPY DATA</literal>
-      options specify if the existing data in the publications that are being
-      subscribed to should be copied. <literal>COPY DATA</literal> is the
-      default.
+      The <literal>refresh_option</literal> is an additional option for the
+      refresh operation.  See
+      <xref linkend="sql-altersubscription-refresh-options"> for details.
      </para>
     </listitem>
    </varlistentry>
@@ -156,6 +159,31 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
     </listitem>
    </varlistentry>
   </variablelist>
+
+  <refsect2 id="sql-altersubscription-refresh-options">
+   <title id="sql-altersubscription-refresh-options-title">Refresh options</title>
+
+   <para>
+    The optional <literal>WITH</> clause for
+    <literal>SET PUBLICATION</literal> and
+    <literal>REFRESH PUBLICATION</literal> clauses specifies behavior of the
+    refresh operation. The supported options are:
+   </para>
+
+   <variablelist>
+    <varlistentry>
+     <term><literal>copy_data</literal> (<type>boolean</type>)</term>
+     <listitem>
+      <para>
+       Specifies if the existing data in the publications that are being
+       subscribed to should be copied once the replication starts.
+       The default is <literal>true</literal>.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+  </refsect2>
+
  </refsect1>
 
  <refsect1>
diff --git a/doc/src/sgml/ref/create_publication.sgml b/doc/src/sgml/ref/create_publication.sgml
index 521376e..76f4250 100644
--- a/doc/src/sgml/ref/create_publication.sgml
+++ b/doc/src/sgml/ref/create_publication.sgml
@@ -24,13 +24,8 @@ PostgreSQL documentation
 CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
     [ FOR TABLE [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [, ...]
       | FOR ALL TABLES ]
-    [ WITH ( <replaceable class="parameter">option</replaceable> [, ... ] ) ]
+    [ WITH ( <replaceable class="parameter">publication_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) ]
 
-<phrase>where <replaceable class="parameter">option</replaceable> can be:</phrase>
-
-      PUBLISH INSERT | NOPUBLISH INSERT
-    | PUBLISH UPDATE | NOPUBLISH UPDATE
-    | PUBLISH DELETE | NOPUBLISH DELETE
 </synopsis>
  </refsynopsisdiv>
 
@@ -97,37 +92,29 @@ CREATE PUBLICATION <replaceable class="parameter">name</replaceable>
    </varlistentry>
 
    <varlistentry>
-    <term><literal>PUBLISH INSERT</literal></term>
-    <term><literal>NOPUBLISH INSERT</literal></term>
-    <listitem>
-     <para>
-      These clauses determine whether the new publication will send
-      the <command>INSERT</command> operations to the subscribers.
-      <literal>PUBLISH INSERT</literal> is the default.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>PUBLISH UPDATE</literal></term>
-    <term><literal>NOPUBLISH UPDATE</literal></term>
+    <term><literal>WITH ( <replaceable class="parameter">publication_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
-      These clauses determine whether the new publication will send
-      the <command>UPDATE</command> operations to the subscribers.
-      <literal>PUBLISH UPDATE</literal> is the default.
-     </para>
-    </listitem>
-   </varlistentry>
+      This clause specifies optional parameters for a pubication; the
+      following parameters are supported:
+
+      <variablelist>
+       <varlistentry>
+        <term><literal>publish</literal> (<type>string</type>)</term>
+        <listitem>
+         <para>
+          This clause determine which DML operations will be published by
+          the new publication to the subscribers. The value is comma
+          separated list of actions.  The allowed operations are
+          <literal>insert</literal>, <literal>update</literal>, and
+          <literal>delete</literal>. The default is to publish all actions so
+          the default value for this option is
+          <literal>'insert,update,delete'</literal>.
+         </para>
+        </listitem>
+       </varlistentry>
+      </variablelist>
 
-   <varlistentry>
-    <term><literal>PUBLISH DELETE</literal></term>
-    <term><literal>NOPUBLISH DELETE</literal></term>
-    <listitem>
-     <para>
-      These clauses determine whether the new publication will send
-      the <command>DELETE</command> operations to the subscribers.
-      <literal>PUBLISH DELETE</literal> is the default.
      </para>
     </listitem>
    </varlistentry>
@@ -203,7 +190,7 @@ CREATE PUBLICATION alltables FOR ALL TABLES;
    operations in one table:
 <programlisting>
 CREATE PUBLICATION insert_only FOR TABLE mydata
-    WITH (NOPUBLISH UPDATE, NOPUBLISH DELETE);
+    WITH (publish = 'insert');
 </programlisting>
   </para>
  </refsect1>
diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml
index 6382468..9fbc804 100644
--- a/doc/src/sgml/ref/create_subscription.sgml
+++ b/doc/src/sgml/ref/create_subscription.sgml
@@ -24,16 +24,7 @@ PostgreSQL documentation
 CREATE SUBSCRIPTION <replaceable class="PARAMETER">subscription_name</replaceable>
     CONNECTION '<replaceable class="PARAMETER">conninfo</replaceable>'
     PUBLICATION { <replaceable class="PARAMETER">publication_name</replaceable> [, ...] }
-    [ WITH ( <replaceable class="PARAMETER">option</replaceable> [, ... ] ) ]
-
-<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
-
-    | ENABLED | DISABLED
-    | CREATE SLOT | NOCREATE SLOT
-    | SLOT NAME = <replaceable class="PARAMETER">slot_name</replaceable>
-    | COPY DATA | NOCOPY DATA
-    | SYNCHRONOUS_COMMIT = <replaceable class="PARAMETER">synchronous_commit</replaceable>
-    | NOCONNECT
+    [ WITH ( <replaceable class="parameter">subscription_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -103,110 +94,122 @@ CREATE SUBSCRIPTION <replaceable class="PARAMETER">subscription_name</replaceabl
    </varlistentry>
 
    <varlistentry>
-    <term><literal>ENABLED</literal></term>
-    <term><literal>DISABLED</literal></term>
-    <listitem>
-     <para>
-      Specifies whether the subscription should be actively replicating or
-      if it should be just setup but not started yet.  Note that the
-      replication slot as described above is created in either case.
-      <literal>ENABLED</literal> is the default.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>CREATE SLOT</literal></term>
-    <term><literal>NOCREATE SLOT</literal></term>
-    <listitem>
-     <para>
-      Specifies whether the command should create the replication slot on the
-      publisher. <literal>CREATE SLOT</literal> is the default.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>SLOT NAME = <replaceable class="parameter">slot_name</replaceable></literal></term>
-    <listitem>
-     <para>
-      Name of the replication slot to use. The default behavior is to use
-      <literal>subscription_name</> for slot name.
-     </para>
-
-     <para>
-      When <literal>SLOT NAME</literal> is set to
-      <literal>NONE</literal>, there will be no replication slot associated
-      with the subscription.  This can be used if the replication slot will be
-      created later manually.  Such subscriptions must also have both
-      <literal>ENABLED</literal> and <literal>CREATE SLOT</literal> set
-      to <literal>false</literal>.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>COPY DATA</literal></term>
-    <term><literal>NOCOPY DATA</literal></term>
+    <term><literal>WITH ( <replaceable class="parameter">subscription_option</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
      <para>
-      Specifies if the existing data in the publications that are being
-      subscribed to should be copied once the replication starts.
-      <literal>COPY DATA</literal> is the default.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>SYNCHRONOUS_COMMIT = <replaceable class="PARAMETER">synchronous_commit</replaceable></literal></term>
-    <listitem>
-     <para>
-      The value of this parameter overrides the
-      <xref linkend="guc-synchronous-commit"> setting.  The default value is
-      <literal>off</literal>.
-     </para>
-
-     <para>
-      It is safe to use <literal>off</literal> for logical replication: If the
-      subscriber loses transactions because of missing synchronization, the
-      data will be resent from the publisher.
-     </para>
-
-     <para>
-      A different setting might be appropriate when doing synchronous logical
-      replication.  The logical replication workers report the positions of
-      writes and flushes to the publisher, and when using synchronous
-      replication, the publisher will wait for the actual flush.  This means
-      that setting <literal>SYNCHRONOUS_COMMIT</literal> for the subscriber
-      to <literal>off</literal> when the subscription is used for synchronous
-      replication might increase the latency for <command>COMMIT</command> on
-      the publisher.  In this scenario, it can be advantageous to set
-      <literal>SYNCHRONOUS_COMMIT</literal> to <literal>local</literal> or
-      higher.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>NOCONNECT</literal></term>
-    <listitem>
-     <para>
-      Instructs <command>CREATE SUBSCRIPTION</command> to skip the initial
-      connection to the provider. This will change default values of other
-      options to <literal>DISABLED</literal>,
-      <literal>NOCREATE SLOT</literal>, and <literal>NOCOPY DATA</literal>.
-     </para>
-     <para>
-      It's not allowed to combine <literal>NOCONNECT</literal> and
-      <literal>ENABLED</literal>, <literal>CREATE SLOT</literal>, or
-      <literal>COPY DATA</literal>.
-     </para>
-     <para>
-      Since no connection is made when this option is specified, the tables
-      are not subscribed, so after you enable the subscription nothing will
-      be replicated. It is required to run
-      <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</> in order for
-      tables to be subscribed.
+      This clause specifies optional parameters for a subscription; the
+      following parameters are supported:
+
+      <variablelist>
+       <varlistentry>
+        <term><literal>enabled</literal> (<type>boolean</type>)</term>
+        <listitem>
+         <para>
+          Specifies whether the subscription should be actively replicating
+          or if it should be just setup but not started yet. The default is
+          <literal>true</literal>.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>create_slot</literal> (<type>boolean</type>)</term>
+        <listitem>
+         <para>
+          Specifies whether the command should create the replication slot
+          on the publisher. The default is <literal>true</literal>.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>slot_name</literal> (<type>string</type>)</term>
+        <listitem>
+         <para>
+          Name of the replication slot to use. The default behavior is to
+          use <literal>subscription_name</> for slot name.
+         </para>
+
+         <para>
+          When <literal>slot_name</literal> is set to
+          <literal>NONE</literal>, there will be no replication slot
+          associated with the subscription.  This can be used if the
+          replication slot will be created later manually.  Such
+          subscriptions must also have both <literal>enabled</literal> and
+         <literal>create_slot</literal> set to <literal>false</literal>.
+         </para>
+       </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>copy_data</literal> (<type>boolean</type>)</term>
+        <listitem>
+         <para>
+          Specifies if the existing data in the publications that are being
+          subscribed to should be copied once the replication starts.
+          The default is <literal>true</literal>.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>synchronous_commit</literal> (<type>enum</type>)</term>
+        <listitem>
+         <para>
+          The value of this parameter overrides the
+          <xref linkend="guc-synchronous-commit"> setting.  The default
+          value is <literal>off</literal>.
+         </para>
+
+         <para>
+          It is safe to use <literal>off</literal> for logical replication:
+          If the subscriber loses transactions because of missing
+          synchronization, the data will be resent from the publisher.
+         </para>
+
+         <para>
+          A different setting might be appropriate when doing synchronous
+          logical replication.  The logical replication workers report the
+          positions of writes and flushes to the publisher, and when using
+          synchronous replication, the publisher will wait for the actual
+          flush.  This means that setting
+          <literal>synchronous_commit</literal> for the subscriber to
+          <literal>off</literal> when the subscription is used for
+          synchronous replication might increase the latency for
+          <command>COMMIT</command> on the publisher.  In this scenario, it
+          can be advantageous to set <literal>synchronous_commit</literal>
+          to <literal>local</literal> or higher.
+         </para>
+        </listitem>
+       </varlistentry>
+
+       <varlistentry>
+        <term><literal>connect</literal> (<type>boolean</type>)</term>
+        <listitem>
+         <para>
+          Boolean specifying if the <command>CREATE SUBSCRIPTION</command>
+          should connect to the provider. Setting this to
+          <literal>false</literal> will change default values of
+          <literal>enabled</literal>, <literal>create_slot</literal> and
+          <literal>copy_data</literal> to <literal>false</literal>.
+         </para>
+         <para>
+          It's not allowed to combine <literal>connect</literal> set to
+          <literal>false</literal> and <literal>enabled</literal>,
+          <literal>create_slot</literal>, or <literal>copy_data</literal>
+          to <literal>true</literal>.
+         </para>
+         <para>
+          Since no connection is made when this option is specified, the
+          tables are not subscribed, so after you enable the subscription
+          nothing will be replicated. It is required to run
+          <literal>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</> in order
+          for tables to be subscribed.
+         </para>
+        </listitem>
+       </varlistentry>
+
+      </variablelist>
      </para>
     </listitem>
    </varlistentry>
@@ -246,7 +249,7 @@ CREATE SUBSCRIPTION mysub
 CREATE SUBSCRIPTION mysub
          CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
         PUBLICATION insert_only
-               WITH (DISABLED);
+               WITH (enabled = false);
 </programlisting>
   </para>
  </refsect1>
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 541da7e..0ead996 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -46,6 +46,7 @@
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
 #include "utils/syscache.h"
+#include "utils/varlena.h"
 
 /* Same as MAXNUMMESSAGES in sinvaladt.c */
 #define MAX_RELCACHE_INVAL_MSGS 4096
@@ -58,18 +59,14 @@ static void PublicationDropTables(Oid pubid, List *rels, bool missing_ok);
 
 static void
 parse_publication_options(List *options,
-						  bool *publish_insert_given,
+						  bool *publish_given,
 						  bool *publish_insert,
-						  bool *publish_update_given,
 						  bool *publish_update,
-						  bool *publish_delete_given,
 						  bool *publish_delete)
 {
 	ListCell   *lc;
 
-	*publish_insert_given = false;
-	*publish_update_given = false;
-	*publish_delete_given = false;
+	*publish_given = false;
 
 	/* Defaults are true */
 	*publish_insert = true;
@@ -81,65 +78,47 @@ parse_publication_options(List *options,
 	{
 		DefElem    *defel = (DefElem *) lfirst(lc);
 
-		if (strcmp(defel->defname, "publish insert") == 0)
+		if (strcmp(defel->defname, "publish") == 0)
 		{
-			if (*publish_insert_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
+			char	   *publish;
+			List	   *publish_list;
+			ListCell   *lc;
 
-			*publish_insert_given = true;
-			*publish_insert = defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "nopublish insert") == 0)
-		{
-			if (*publish_insert_given)
+			if (*publish_given)
 				ereport(ERROR,
 						(errcode(ERRCODE_SYNTAX_ERROR),
 						 errmsg("conflicting or redundant options")));
 
-			*publish_insert_given = true;
-			*publish_insert = !defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "publish update") == 0)
-		{
-			if (*publish_update_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
+			/*
+			 * If publish option was given only the explicitly listed actions
+			 * should be published.
+			 */
+			*publish_insert = false;
+			*publish_update = false;
+			*publish_delete = false;
 
-			*publish_update_given = true;
-			*publish_update = defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "nopublish update") == 0)
-		{
-			if (*publish_update_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
+			*publish_given = true;
+			publish = defGetString(defel);
 
-			*publish_update_given = true;
-			*publish_update = !defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "publish delete") == 0)
-		{
-			if (*publish_delete_given)
+			if (!SplitIdentifierString(publish, ',', &publish_list))
 				ereport(ERROR,
 						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
+						 errmsg("invalid publish list")));
 
-			*publish_delete_given = true;
-			*publish_delete = defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "nopublish delete") == 0)
-		{
-			if (*publish_delete_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
-
-			*publish_delete_given = true;
-			*publish_delete = !defGetBoolean(defel);
+			/* Process the option list. */
+			foreach (lc, publish_list)
+			{
+				char *publish_opt = (char *)lfirst(lc);
+
+				if (strcmp(publish_opt, "insert") == 0)
+					*publish_insert = true;
+				else if (strcmp(publish_opt, "update") == 0)
+					*publish_update = true;
+				else if (strcmp(publish_opt, "delete") == 0)
+					*publish_delete = true;
+				else
+					elog(ERROR, "unrecognized publish option: %s", publish_opt);
+			}
 		}
 		else
 			elog(ERROR, "unrecognized option: %s", defel->defname);
@@ -158,9 +137,7 @@ CreatePublication(CreatePublicationStmt *stmt)
 	bool		nulls[Natts_pg_publication];
 	Datum		values[Natts_pg_publication];
 	HeapTuple	tup;
-	bool		publish_insert_given;
-	bool		publish_update_given;
-	bool		publish_delete_given;
+	bool		publish_given;
 	bool		publish_insert;
 	bool		publish_update;
 	bool		publish_delete;
@@ -199,9 +176,8 @@ CreatePublication(CreatePublicationStmt *stmt)
 	values[Anum_pg_publication_pubowner - 1] = ObjectIdGetDatum(GetUserId());
 
 	parse_publication_options(stmt->options,
-							  &publish_insert_given, &publish_insert,
-							  &publish_update_given, &publish_update,
-							  &publish_delete_given, &publish_delete);
+							  &publish_given, &publish_insert,
+							  &publish_update, &publish_delete);
 
 	values[Anum_pg_publication_puballtables - 1] =
 		BoolGetDatum(stmt->for_all_tables);
@@ -253,42 +229,31 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
 	bool		nulls[Natts_pg_publication];
 	bool		replaces[Natts_pg_publication];
 	Datum		values[Natts_pg_publication];
-	bool		publish_insert_given;
-	bool		publish_update_given;
-	bool		publish_delete_given;
+	bool		publish_given;
 	bool		publish_insert;
 	bool		publish_update;
 	bool		publish_delete;
 	ObjectAddress		obj;
 
 	parse_publication_options(stmt->options,
-							  &publish_insert_given, &publish_insert,
-							  &publish_update_given, &publish_update,
-							  &publish_delete_given, &publish_delete);
+							  &publish_given, &publish_insert,
+							  &publish_update, &publish_delete);
+
+	Assert(publish_given);
 
 	/* Everything ok, form a new tuple. */
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 	memset(replaces, false, sizeof(replaces));
 
-	if (publish_insert_given)
-	{
-		values[Anum_pg_publication_pubinsert - 1] =
-			BoolGetDatum(publish_insert);
-		replaces[Anum_pg_publication_pubinsert - 1] = true;
-	}
-	if (publish_update_given)
-	{
-		values[Anum_pg_publication_pubupdate - 1] =
-			BoolGetDatum(publish_update);
-		replaces[Anum_pg_publication_pubupdate - 1] = true;
-	}
-	if (publish_delete_given)
-	{
-		values[Anum_pg_publication_pubdelete - 1] =
-			BoolGetDatum(publish_delete);
-		replaces[Anum_pg_publication_pubdelete - 1] = true;
-	}
+	values[Anum_pg_publication_pubinsert - 1] = BoolGetDatum(publish_insert);
+	replaces[Anum_pg_publication_pubinsert - 1] = true;
+
+	values[Anum_pg_publication_pubupdate - 1] = BoolGetDatum(publish_update);
+	replaces[Anum_pg_publication_pubupdate - 1] = true;
+
+	values[Anum_pg_publication_pubdelete - 1] = BoolGetDatum(publish_delete);
+	replaces[Anum_pg_publication_pubdelete - 1] = true;
 
 	tup = heap_modify_tuple(tup, RelationGetDescr(rel), values, nulls,
 							replaces);
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index b76cdc5..b3a41a2 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -93,7 +93,7 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 	{
 		DefElem    *defel = (DefElem *) lfirst(lc);
 
-		if (strcmp(defel->defname, "noconnect") == 0 && connect)
+		if (strcmp(defel->defname, "connect") == 0 && connect)
 		{
 			if (connect_given)
 				ereport(ERROR,
@@ -101,7 +101,7 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 						 errmsg("conflicting or redundant options")));
 
 			connect_given = true;
-			*connect = !defGetBoolean(defel);
+			*connect = defGetBoolean(defel);
 		}
 		else if (strcmp(defel->defname, "enabled") == 0 && enabled)
 		{
@@ -113,17 +113,7 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 			*enabled_given = true;
 			*enabled = defGetBoolean(defel);
 		}
-		else if (strcmp(defel->defname, "disabled") == 0 && enabled)
-		{
-			if (*enabled_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
-
-			*enabled_given = true;
-			*enabled = !defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "create slot") == 0 && create_slot)
+		else if (strcmp(defel->defname, "create_slot") == 0 && create_slot)
 		{
 			if (create_slot_given)
 				ereport(ERROR,
@@ -133,17 +123,7 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 			create_slot_given = true;
 			*create_slot = defGetBoolean(defel);
 		}
-		else if (strcmp(defel->defname, "nocreate slot") == 0 && create_slot)
-		{
-			if (create_slot_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
-
-			create_slot_given = true;
-			*create_slot = !defGetBoolean(defel);
-		}
-		else if (strcmp(defel->defname, "slot name") == 0 && slot_name)
+		else if (strcmp(defel->defname, "slot_name") == 0 && slot_name)
 		{
 			if (*slot_name_given)
 				ereport(ERROR,
@@ -157,7 +137,7 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 			if (strcmp(*slot_name, "none") == 0)
 				*slot_name = NULL;
 		}
-		else if (strcmp(defel->defname, "copy data") == 0 && copy_data)
+		else if (strcmp(defel->defname, "copy_data") == 0 && copy_data)
 		{
 			if (copy_data_given)
 				ereport(ERROR,
@@ -167,16 +147,6 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
 			copy_data_given = true;
 			*copy_data = defGetBoolean(defel);
 		}
-		else if (strcmp(defel->defname, "nocopy data") == 0 && copy_data)
-		{
-			if (copy_data_given)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
-
-			copy_data_given = true;
-			*copy_data = !defGetBoolean(defel);
-		}
 		else if (strcmp(defel->defname, "synchronous_commit") == 0 &&
 				 synchronous_commit)
 		{
@@ -336,7 +306,7 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
 	 * replication slot.
 	 */
 	if (create_slot)
-		PreventTransactionChain(isTopLevel, "CREATE SUBSCRIPTION ... CREATE SLOT");
+		PreventTransactionChain(isTopLevel, "CREATE SUBSCRIPTION ... (create_slot true)");
 
 	if (!superuser())
 		ereport(ERROR,
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 65c004c..68f5efd 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -652,8 +652,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 	MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
 
 	NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NONE
-	NOREFRESH NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
-	NULLS_P NUMERIC
+	NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
 
 	OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
 	ORDER ORDINALITY OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER
@@ -5685,7 +5684,6 @@ def_elem:	def_key '=' def_arg
 
 def_key:
 			ColLabel						{ $$ = $1; }
-			| ColLabel ColLabel				{ $$ = psprintf("%s %s", $1, $2); }
 		;
 
 /* Note: any simple identifier will be returned as a type name! */
@@ -9173,6 +9171,7 @@ publication_for_tables:
 				}
 		;
 
+
 /*****************************************************************************
  *
  * ALTER PUBLICATION name [ WITH ] options
@@ -9296,7 +9295,7 @@ AlterSubscriptionStmt:
 					n->options = $8;
 					$$ = (Node *)n;
 				}
-			| ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list NOREFRESH
+			| ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list SKIP REFRESH
 				{
 					AlterSubscriptionStmt *n =
 						makeNode(AlterSubscriptionStmt);
@@ -14758,7 +14757,6 @@ unreserved_keyword:
 			| NEW
 			| NEXT
 			| NO
-			| NOREFRESH
 			| NOTHING
 			| NOTIFY
 			| NOWAIT
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index d724b11..8aa420f 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -3460,6 +3460,7 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 	PQExpBuffer delq;
 	PQExpBuffer query;
 	PQExpBuffer labelq;
+	bool		first = true;
 
 	if (!(pubinfo->dobj.dump & DUMP_COMPONENT_DEFINITION))
 		return;
@@ -3479,23 +3480,32 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 	if (pubinfo->puballtables)
 		appendPQExpBufferStr(query, " FOR ALL TABLES");
 
-	appendPQExpBufferStr(query, " WITH (");
+	appendPQExpBufferStr(query, " WITH (publish = '");
 	if (pubinfo->pubinsert)
-		appendPQExpBufferStr(query, "PUBLISH INSERT");
-	else
-		appendPQExpBufferStr(query, "NOPUBLISH INSERT");
+	{
+		appendPQExpBufferStr(query, "insert");
+		first = false;
+	}
+
+	if (!first)
+		appendPQExpBufferChar(query, ',');
 
 	if (pubinfo->pubupdate)
-		appendPQExpBufferStr(query, ", PUBLISH UPDATE");
-	else
-		appendPQExpBufferStr(query, ", NOPUBLISH UPDATE");
+	{
+		appendPQExpBufferStr(query, "update");
+		first = false;
+	}
+
+	if (!first)
+		appendPQExpBufferChar(query, ',');
 
 	if (pubinfo->pubdelete)
-		appendPQExpBufferStr(query, ", PUBLISH DELETE");
-	else
-		appendPQExpBufferStr(query, ", NOPUBLISH DELETE");
+	{
+		appendPQExpBufferStr(query, "delete");
+		first = false;
+	}
 
-	appendPQExpBufferStr(query, ");\n");
+	appendPQExpBufferStr(query, "');\n");
 
 	ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
 				 pubinfo->dobj.name,
@@ -3817,11 +3827,11 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 		appendPQExpBufferStr(publications, fmtId(pubnames[i]));
 	}
 
-	appendPQExpBuffer(query, " PUBLICATION %s WITH (NOCONNECT, SLOT NAME = ", publications->data);
+	appendPQExpBuffer(query, " PUBLICATION %s WITH (connect = false, slot_name = ", publications->data);
 	appendStringLiteralAH(query, subinfo->subslotname, fout);
 
 	if (strcmp(subinfo->subsynccommit, "off") != 0)
-		appendPQExpBuffer(query, ", SYNCHRONOUS_COMMIT = %s", fmtId(subinfo->subsynccommit));
+		appendPQExpBuffer(query, ", synchronous_commit = %s", fmtId(subinfo->subsynccommit));
 
 	appendPQExpBufferStr(query, ");\n");
 
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index ce0c9ef..938c332 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -4351,7 +4351,7 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
 		create_order => 50,
 		create_sql   => 'CREATE PUBLICATION pub1;',
 		regexp       => qr/^
-			\QCREATE PUBLICATION pub1 WITH (PUBLISH INSERT, PUBLISH UPDATE, PUBLISH DELETE);\E
+			\QCREATE PUBLICATION pub1 WITH (publish = 'insert,update,delete');\E
 			/xm,
 		like => {
 			binary_upgrade           => 1,
@@ -4384,11 +4384,9 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
 		create_order => 50,
 		create_sql   => 'CREATE PUBLICATION pub2
 						 FOR ALL TABLES
-						 WITH (NOPUBLISH INSERT,
-							   NOPUBLISH UPDATE,
-							   NOPUBLISH DELETE);',
+						 WITH (publish = \'\');',
 		regexp       => qr/^
-			\QCREATE PUBLICATION pub2 FOR ALL TABLES WITH (NOPUBLISH INSERT, NOPUBLISH UPDATE, NOPUBLISH DELETE);\E
+			\QCREATE PUBLICATION pub2 FOR ALL TABLES WITH (publish = '');\E
 			/xm,
 		like => {
 			binary_upgrade           => 1,
@@ -4421,9 +4419,9 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
 		create_order => 50,
 		create_sql   => 'CREATE SUBSCRIPTION sub1
 						 CONNECTION \'dbname=doesnotexist\' PUBLICATION pub1
-						 WITH (NOCONNECT);',
+						 WITH (connect = false);',
 		regexp       => qr/^
-			\QCREATE SUBSCRIPTION sub1 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (NOCONNECT, SLOT NAME = 'sub1');\E
+			\QCREATE SUBSCRIPTION sub1 CONNECTION 'dbname=doesnotexist' PUBLICATION pub1 WITH (connect = false, slot_name = 'sub1');\E
 			/xm,
 		like => {
 			binary_upgrade           => 1,
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 3bd5277..16c93fa 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -1507,8 +1507,7 @@ psql_completion(const char *text, int start, int end)
 	/* ALTER PUBLICATION <name> .. WITH ( ... */
 	else if (HeadMatches3("ALTER", "PUBLICATION",MatchAny) && TailMatches2("WITH", "("))
 	{
-		COMPLETE_WITH_LIST6("PUBLISH INSERT", "NOPUBLISH INSERT", "PUBLISH UPDATE",
-							"NOPUBLISH UPDATE", "PUBLISH DELETE", "NOPUBLISH DELETE");
+		COMPLETE_WITH_CONST("publish");
 	}
 	/* ALTER SUBSCRIPTION <name> ... */
 	else if (Matches3("ALTER","SUBSCRIPTION",MatchAny))
@@ -1520,12 +1519,12 @@ psql_completion(const char *text, int start, int end)
 	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) &&
 			 TailMatches4("REFRESH", "PUBLICATION", "WITH", "("))
 	{
-		COMPLETE_WITH_LIST2("COPY DATA", "NOCOPY DATA");
+		COMPLETE_WITH_CONST("copy_data");
 	}
 	/* ALTER SUBSCRIPTION <name> .. WITH ( ... */
 	else if (HeadMatches3("ALTER", "SUBSCRIPTION", MatchAny) && TailMatches2("WITH", "("))
 	{
-		COMPLETE_WITH_CONST("SLOT NAME");
+		COMPLETE_WITH_CONST("slot_name");
 	}
 	/* ALTER SCHEMA <name> */
 	else if (Matches3("ALTER", "SCHEMA", MatchAny))
@@ -2349,9 +2348,7 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
 	/* Complete "CREATE PUBLICATION <name> [...] WITH" */
 	else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches2("WITH", "("))
-		COMPLETE_WITH_LIST2("PUBLISH", "NOPUBLISH");
-	else if (HeadMatches2("CREATE", "PUBLICATION") && TailMatches3("WITH", "(", MatchAny))
-		COMPLETE_WITH_LIST3("INSERT", "UPDATE", "DELETE");
+		COMPLETE_WITH_CONST("publish");
 
 /* CREATE RULE */
 	/* Complete "CREATE RULE <sth>" with "AS ON" */
@@ -2427,9 +2424,8 @@ psql_completion(const char *text, int start, int end)
 		COMPLETE_WITH_CONST("WITH (");
 	/* Complete "CREATE SUBSCRIPTION <name> ...  WITH ( <opt>" */
 	else if (HeadMatches2("CREATE", "SUBSCRIPTION") && TailMatches2("WITH", "("))
-		COMPLETE_WITH_LIST8("ENABLED", "DISABLED", "CREATE SLOT",
-							"NOCREATE SLOT", "SLOT NAME", "COPY DATA", "NOCOPY DATA",
-							"NOCONNECT");
+		COMPLETE_WITH_LIST5("enabled", "create_slot", "slot_name",
+							"copy_data", "connect");
 
 /* CREATE TRIGGER --- is allowed inside CREATE SCHEMA, so use TailMatches */
 	/* complete CREATE TRIGGER <name> with BEFORE,AFTER,INSTEAD OF */
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 1ef03cf..f50e45e 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -259,7 +259,6 @@ PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD)
 PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD)
 PG_KEYWORD("no", NO, UNRESERVED_KEYWORD)
 PG_KEYWORD("none", NONE, COL_NAME_KEYWORD)
-PG_KEYWORD("norefresh", NOREFRESH, UNRESERVED_KEYWORD)
 PG_KEYWORD("not", NOT, RESERVED_KEYWORD)
 PG_KEYWORD("nothing", NOTHING, UNRESERVED_KEYWORD)
 PG_KEYWORD("notify", NOTIFY, UNRESERVED_KEYWORD)
diff --git a/src/test/modules/dummy_seclabel/expected/dummy_seclabel.out b/src/test/modules/dummy_seclabel/expected/dummy_seclabel.out
index 5f37681..77bdc93 100644
--- a/src/test/modules/dummy_seclabel/expected/dummy_seclabel.out
+++ b/src/test/modules/dummy_seclabel/expected/dummy_seclabel.out
@@ -69,7 +69,7 @@ CREATE SCHEMA dummy_seclabel_test;
 SECURITY LABEL ON SCHEMA dummy_seclabel_test IS 'unclassified';		-- OK
 SET client_min_messages = error;
 CREATE PUBLICATION dummy_pub;
-CREATE SUBSCRIPTION dummy_sub CONNECTION '' PUBLICATION foo WITH (NOCONNECT, SLOT NAME = NONE);
+CREATE SUBSCRIPTION dummy_sub CONNECTION '' PUBLICATION foo WITH (connect = false, slot_name = NONE);
 RESET client_min_messages;
 SECURITY LABEL ON PUBLICATION dummy_pub IS 'classified';
 SECURITY LABEL ON SUBSCRIPTION dummy_sub IS 'classified';
diff --git a/src/test/modules/dummy_seclabel/sql/dummy_seclabel.sql b/src/test/modules/dummy_seclabel/sql/dummy_seclabel.sql
index 97311c7..8c347b6 100644
--- a/src/test/modules/dummy_seclabel/sql/dummy_seclabel.sql
+++ b/src/test/modules/dummy_seclabel/sql/dummy_seclabel.sql
@@ -73,7 +73,7 @@ SECURITY LABEL ON SCHEMA dummy_seclabel_test IS 'unclassified';		-- OK
 
 SET client_min_messages = error;
 CREATE PUBLICATION dummy_pub;
-CREATE SUBSCRIPTION dummy_sub CONNECTION '' PUBLICATION foo WITH (NOCONNECT, SLOT NAME = NONE);
+CREATE SUBSCRIPTION dummy_sub CONNECTION '' PUBLICATION foo WITH (connect = false, slot_name = NONE);
 RESET client_min_messages;
 SECURITY LABEL ON PUBLICATION dummy_pub IS 'classified';
 SECURITY LABEL ON SUBSCRIPTION dummy_sub IS 'classified';
diff --git a/src/test/regress/expected/object_address.out b/src/test/regress/expected/object_address.out
index 40eeeed..700f261 100644
--- a/src/test/regress/expected/object_address.out
+++ b/src/test/regress/expected/object_address.out
@@ -37,7 +37,7 @@ CREATE TRANSFORM FOR int LANGUAGE SQL (
 	FROM SQL WITH FUNCTION varchar_transform(internal),
 	TO SQL WITH FUNCTION int4recv(internal));
 CREATE PUBLICATION addr_pub FOR TABLE addr_nsp.gentable;
-CREATE SUBSCRIPTION addr_sub CONNECTION '' PUBLICATION bar WITH (NOCONNECT, SLOT NAME = NONE);
+CREATE SUBSCRIPTION addr_sub CONNECTION '' PUBLICATION bar WITH (connect = false, slot_name = NONE);
 WARNING:  tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables
 CREATE STATISTICS addr_nsp.gentable_stat ON (a,b) FROM addr_nsp.gentable;
 -- test some error cases
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index f3a348d..d9089af 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -13,8 +13,8 @@ SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
  test publication
 (1 row)
 
-CREATE PUBLICATION testpib_ins_trunct WITH (nopublish delete, nopublish update);
-ALTER PUBLICATION testpub_default WITH (nopublish insert, nopublish delete);
+CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert);
+ALTER PUBLICATION testpub_default WITH (publish = update);
 \dRp
                             List of publications
         Name        |          Owner           | Inserts | Updates | Deletes 
@@ -23,7 +23,7 @@ ALTER PUBLICATION testpub_default WITH (nopublish insert, nopublish delete);
  testpub_default    | regress_publication_user | f       | t       | f
 (2 rows)
 
-ALTER PUBLICATION testpub_default WITH (publish insert, publish delete);
+ALTER PUBLICATION testpub_default WITH (publish = 'insert, update, delete');
 \dRp
                             List of publications
         Name        |          Owner           | Inserts | Updates | Deletes 
@@ -38,8 +38,8 @@ CREATE TABLE testpub_tbl1 (id serial primary key, data text);
 CREATE TABLE pub_test.testpub_nopk (foo int, bar int);
 CREATE VIEW testpub_view AS SELECT 1;
 CREATE TABLE testpub_parted (a int) PARTITION BY LIST (a);
-CREATE PUBLICATION testpub_foralltables FOR ALL TABLES WITH (nopublish delete, nopublish update);
-ALTER PUBLICATION testpub_foralltables WITH (publish update);
+CREATE PUBLICATION testpub_foralltables FOR ALL TABLES WITH (publish = 'insert');
+ALTER PUBLICATION testpub_foralltables WITH (publish = 'insert,update');
 CREATE TABLE testpub_tbl2 (id serial primary key, data text);
 -- fail - can't add to for all tables publication
 ALTER PUBLICATION testpub_foralltables ADD TABLE testpub_tbl2;
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 56f826b..2caff71 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -17,18 +17,18 @@ LINE 1: CREATE SUBSCRIPTION testsub PUBLICATION foo;
                                     ^
 -- fail - cannot do CREATE SUBSCRIPTION CREATE SLOT inside transaction block
 BEGIN;
-CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub WITH (CREATE SLOT);
-ERROR:  CREATE SUBSCRIPTION ... CREATE SLOT cannot run inside a transaction block
+CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub WITH (create_slot);
+ERROR:  CREATE SUBSCRIPTION ... (create_slot true) cannot run inside a transaction block
 COMMIT;
 -- fail - invalid connection string
 CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub;
 ERROR:  invalid connection string syntax: missing "=" after "testconn" in connection info string
 
 -- fail - duplicate publications
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION foo, testpub, foo WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION foo, testpub, foo WITH (connect = false);
 ERROR:  publication name "foo" used more than once
 -- ok
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (connect = false);
 WARNING:  tables were not subscribed, you will have to run ALTER SUBSCRIPTION ... REFRESH PUBLICATION to subscribe the tables
 COMMENT ON SUBSCRIPTION testsub IS 'test subscription';
 SELECT obj_description(s.oid, 'pg_subscription') FROM pg_subscription s;
@@ -38,11 +38,11 @@ SELECT obj_description(s.oid, 'pg_subscription') FROM pg_subscription s;
 (1 row)
 
 -- fail - name already exists
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (connect = false);
 ERROR:  subscription "testsub" already exists
 -- fail - must be superuser
 SET SESSION AUTHORIZATION 'regress_subscription_user2';
-CREATE SUBSCRIPTION testsub2 CONNECTION 'dbname=doesnotexist' PUBLICATION foo WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub2 CONNECTION 'dbname=doesnotexist' PUBLICATION foo WITH (connect = false);
 ERROR:  must be superuser to create subscriptions
 SET SESSION AUTHORIZATION 'regress_subscription_user';
 -- fail - invalid connection string
@@ -56,9 +56,9 @@ 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 NOREFRESH;
+ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
 ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
-ALTER SUBSCRIPTION testsub WITH (SLOT NAME = 'newname');
+ALTER SUBSCRIPTION testsub WITH (slot_name = 'newname');
 -- fail
 ALTER SUBSCRIPTION doesnotexist CONNECTION 'dbname=doesnotexist2';
 ERROR:  subscription "doesnotexist" does not exist
@@ -93,8 +93,8 @@ ALTER SUBSCRIPTION testsub RENAME TO testsub_dummy;
 ERROR:  must be owner of subscription testsub
 RESET ROLE;
 ALTER SUBSCRIPTION testsub RENAME TO testsub_foo;
-ALTER SUBSCRIPTION testsub_foo WITH (SYNCHRONOUS_COMMIT = local);
-ALTER SUBSCRIPTION testsub_foo WITH (SYNCHRONOUS_COMMIT = foobar);
+ALTER SUBSCRIPTION testsub_foo WITH (synchronous_commit = local);
+ALTER SUBSCRIPTION testsub_foo WITH (synchronous_commit = foobar);
 ERROR:  invalid value for parameter "synchronous_commit": "foobar"
 HINT:  Available values: local, remote_write, remote_apply, on, off.
 \dRs+
@@ -118,7 +118,7 @@ BEGIN;
 DROP SUBSCRIPTION testsub;
 ERROR:  DROP SUBSCRIPTION cannot run inside a transaction block
 COMMIT;
-ALTER SUBSCRIPTION testsub WITH (SLOT NAME = NONE);
+ALTER SUBSCRIPTION testsub WITH (slot_name = NONE);
 -- now it works
 BEGIN;
 DROP SUBSCRIPTION testsub;
diff --git a/src/test/regress/sql/object_address.sql b/src/test/regress/sql/object_address.sql
index 6940392..8a738e2 100644
--- a/src/test/regress/sql/object_address.sql
+++ b/src/test/regress/sql/object_address.sql
@@ -40,7 +40,7 @@ CREATE TRANSFORM FOR int LANGUAGE SQL (
 	FROM SQL WITH FUNCTION varchar_transform(internal),
 	TO SQL WITH FUNCTION int4recv(internal));
 CREATE PUBLICATION addr_pub FOR TABLE addr_nsp.gentable;
-CREATE SUBSCRIPTION addr_sub CONNECTION '' PUBLICATION bar WITH (NOCONNECT, SLOT NAME = NONE);
+CREATE SUBSCRIPTION addr_sub CONNECTION '' PUBLICATION bar WITH (connect = false, slot_name = NONE);
 CREATE STATISTICS addr_nsp.gentable_stat ON (a,b) FROM addr_nsp.gentable;
 
 -- test some error cases
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 7d1cba5..ed6bd57 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -11,13 +11,13 @@ CREATE PUBLICATION testpub_default;
 COMMENT ON PUBLICATION testpub_default IS 'test publication';
 SELECT obj_description(p.oid, 'pg_publication') FROM pg_publication p;
 
-CREATE PUBLICATION testpib_ins_trunct WITH (nopublish delete, nopublish update);
+CREATE PUBLICATION testpib_ins_trunct WITH (publish = insert);
 
-ALTER PUBLICATION testpub_default WITH (nopublish insert, nopublish delete);
+ALTER PUBLICATION testpub_default WITH (publish = update);
 
 \dRp
 
-ALTER PUBLICATION testpub_default WITH (publish insert, publish delete);
+ALTER PUBLICATION testpub_default WITH (publish = 'insert, update, delete');
 
 \dRp
 
@@ -28,8 +28,8 @@ CREATE TABLE pub_test.testpub_nopk (foo int, bar int);
 CREATE VIEW testpub_view AS SELECT 1;
 CREATE TABLE testpub_parted (a int) PARTITION BY LIST (a);
 
-CREATE PUBLICATION testpub_foralltables FOR ALL TABLES WITH (nopublish delete, nopublish update);
-ALTER PUBLICATION testpub_foralltables WITH (publish update);
+CREATE PUBLICATION testpub_foralltables FOR ALL TABLES WITH (publish = 'insert');
+ALTER PUBLICATION testpub_foralltables WITH (publish = 'insert,update');
 
 CREATE TABLE testpub_tbl2 (id serial primary key, data text);
 -- fail - can't add to for all tables publication
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index b920446..0e0f042 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -15,27 +15,27 @@ CREATE SUBSCRIPTION testsub PUBLICATION foo;
 
 -- fail - cannot do CREATE SUBSCRIPTION CREATE SLOT inside transaction block
 BEGIN;
-CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub WITH (CREATE SLOT);
+CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub WITH (create_slot);
 COMMIT;
 
 -- fail - invalid connection string
 CREATE SUBSCRIPTION testsub CONNECTION 'testconn' PUBLICATION testpub;
 
 -- fail - duplicate publications
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION foo, testpub, foo WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION foo, testpub, foo WITH (connect = false);
 
 -- ok
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (connect = false);
 
 COMMENT ON SUBSCRIPTION testsub IS 'test subscription';
 SELECT obj_description(s.oid, 'pg_subscription') FROM pg_subscription s;
 
 -- fail - name already exists
-CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist' PUBLICATION testpub WITH (connect = false);
 
 -- fail - must be superuser
 SET SESSION AUTHORIZATION 'regress_subscription_user2';
-CREATE SUBSCRIPTION testsub2 CONNECTION 'dbname=doesnotexist' PUBLICATION foo WITH (NOCONNECT);
+CREATE SUBSCRIPTION testsub2 CONNECTION 'dbname=doesnotexist' PUBLICATION foo WITH (connect = false);
 SET SESSION AUTHORIZATION 'regress_subscription_user';
 
 -- fail - invalid connection string
@@ -43,9 +43,9 @@ ALTER SUBSCRIPTION testsub CONNECTION 'foobar';
 
 \dRs+
 
-ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 NOREFRESH;
+ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
 ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
-ALTER SUBSCRIPTION testsub WITH (SLOT NAME = 'newname');
+ALTER SUBSCRIPTION testsub WITH (slot_name = 'newname');
 
 -- fail
 ALTER SUBSCRIPTION doesnotexist CONNECTION 'dbname=doesnotexist2';
@@ -69,8 +69,8 @@ ALTER SUBSCRIPTION testsub RENAME TO testsub_dummy;
 RESET ROLE;
 
 ALTER SUBSCRIPTION testsub RENAME TO testsub_foo;
-ALTER SUBSCRIPTION testsub_foo WITH (SYNCHRONOUS_COMMIT = local);
-ALTER SUBSCRIPTION testsub_foo WITH (SYNCHRONOUS_COMMIT = foobar);
+ALTER SUBSCRIPTION testsub_foo WITH (synchronous_commit = local);
+ALTER SUBSCRIPTION testsub_foo WITH (synchronous_commit = foobar);
 
 \dRs+
 
@@ -88,7 +88,7 @@ BEGIN;
 DROP SUBSCRIPTION testsub;
 COMMIT;
 
-ALTER SUBSCRIPTION testsub WITH (SLOT NAME = NONE);
+ALTER SUBSCRIPTION testsub WITH (slot_name = NONE);
 
 -- now it works
 BEGIN;
diff --git a/src/test/subscription/t/001_rep_changes.pl b/src/test/subscription/t/001_rep_changes.pl
index 8e79fa3..50c4f4d 100644
--- a/src/test/subscription/t/001_rep_changes.pl
+++ b/src/test/subscription/t/001_rep_changes.pl
@@ -40,7 +40,7 @@ my $publisher_connstr = $node_publisher->connstr . ' dbname=postgres';
 $node_publisher->safe_psql('postgres',
 	"CREATE PUBLICATION tap_pub");
 $node_publisher->safe_psql('postgres',
-	"CREATE PUBLICATION tap_pub_ins_only WITH (nopublish delete, nopublish update)");
+	"CREATE PUBLICATION tap_pub_ins_only WITH (publish = insert)");
 $node_publisher->safe_psql('postgres',
 	"ALTER PUBLICATION tap_pub ADD TABLE tab_rep, tab_full");
 $node_publisher->safe_psql('postgres',
@@ -136,7 +136,7 @@ $node_publisher->poll_query_until('postgres',
 $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 SET PUBLICATION tap_pub_ins_only REFRESH WITH (NOCOPY DATA)");
+	"ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_ins_only REFRESH WITH (copy_data = false)");
 $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";
@@ -159,13 +159,13 @@ is($result, qq(20|-20|-1), 'check changes skipped after subscription publication
 
 # check alter publication (relcache invalidation etc)
 $node_publisher->safe_psql('postgres',
-	"ALTER PUBLICATION tap_pub_ins_only WITH (publish delete)");
+	"ALTER PUBLICATION tap_pub_ins_only WITH (publish = 'insert,delete')");
 $node_publisher->safe_psql('postgres',
 	"ALTER PUBLICATION tap_pub_ins_only ADD TABLE tab_full");
 $node_publisher->safe_psql('postgres',
 	"DELETE FROM tab_ins WHERE a > 0");
 $node_subscriber->safe_psql('postgres',
-	"ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION WITH (NOCOPY DATA)");
+	"ALTER SUBSCRIPTION tap_sub REFRESH PUBLICATION WITH (copy_data = false)");
 $node_publisher->safe_psql('postgres',
 	"INSERT INTO tab_full VALUES(0)");
 
diff --git a/src/test/subscription/t/002_types.pl b/src/test/subscription/t/002_types.pl
index ad15e85..e9368ab 100644
--- a/src/test/subscription/t/002_types.pl
+++ b/src/test/subscription/t/002_types.pl
@@ -103,7 +103,7 @@ $node_publisher->safe_psql('postgres',
 
 my $appname = 'tap_sub';
 $node_subscriber->safe_psql('postgres',
-	"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (SLOT NAME = tap_sub_slot)");
+	"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (slot_name = tap_sub_slot)");
 
 # Wait for subscriber to finish initialization
 my $caughtup_query =
diff --git a/src/test/subscription/t/003_constraints.pl b/src/test/subscription/t/003_constraints.pl
index 11b8254..e906ea1 100644
--- a/src/test/subscription/t/003_constraints.pl
+++ b/src/test/subscription/t/003_constraints.pl
@@ -34,7 +34,7 @@ $node_publisher->safe_psql('postgres',
 
 my $appname = 'tap_sub';
 $node_subscriber->safe_psql('postgres',
-	"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (NOCOPY DATA)");
+	"CREATE SUBSCRIPTION tap_sub CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (copy_data = false)");
 
 # Wait for subscriber to finish initialization
 my $caughtup_query =
diff --git a/src/test/subscription/t/004_sync.pl b/src/test/subscription/t/004_sync.pl
index fa0bf7f..8ece7dd 100644
--- a/src/test/subscription/t/004_sync.pl
+++ b/src/test/subscription/t/004_sync.pl
@@ -82,7 +82,7 @@ is($result, qq(20), 'initial data synced for second sub');
 
 # now check another subscription for the same node pair
 $node_subscriber->safe_psql('postgres',
-	"CREATE SUBSCRIPTION tap_sub2 CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (NOCOPY DATA)");
+	"CREATE SUBSCRIPTION tap_sub2 CONNECTION '$publisher_connstr application_name=$appname' PUBLICATION tap_pub WITH (copy_data = false)");
 
 # wait for it to start
 $node_subscriber->poll_query_until('postgres', "SELECT pid IS NOT NULL FROM pg_stat_subscription WHERE subname = 'tap_sub2' AND relid IS NULL")
-- 
2.7.4

