From: Petr Jelinek <petr.jelinek@2ndquadrant.com>
To: Peter Eisentraut <peter.eisentraut@2ndquadrant.com>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Robert Haas <robertmhaas@gmail.com>
Cc: Michael Paquier <michael.paquier@gmail.com>
Cc: PostgreSQL mailing lists <pgsql-hackers@postgresql.org>
Subject: Re: logical replication syntax (was DROP SUBSCRIPTION, query cancellations and slot handling)
Date: Tue, 9 May 2017 17:43:21 +0200
Message-ID: <20856826-de0f-f630-4c67-36dca21037ad@2ndquadrant.com> (raw)
In-Reply-To: <b54076fd-67d4-cc80-d5a6-ee8db2528e17@2ndquadrant.com>
References: <CA+TgmoZmkbpAWRzVKDVcHnTBkYjJEFS8=09RL-G3zgdozCLFHQ@mail.gmail.com>
<27478.1493727233@sss.pgh.pa.us>
<29431.1493730652@sss.pgh.pa.us>
<360a1932-7af4-609b-94f1-2ad419430869@2ndquadrant.com>
<9174dc31-787a-a2f6-818f-cb4a5c1dfddb@2ndquadrant.com>
<30166.1493731904@sss.pgh.pa.us>
<daf9909a-7033-9cfe-a8cc-a606025820fc@2ndquadrant.com>
<2b931e0e-d9f2-c79e-b74b-91df2f915e66@2ndquadrant.com>
<96e95255-94d9-0881-16ba-bdb6d05bb307@2ndquadrant.com>
<52a1f160-db1f-49c6-9832-498dbea58ae8@2ndquadrant.com>
<35f3592b-8582-e348-1823-f8edfcf03ba3@2ndquadrant.com>
<5f6ad263-af87-2aee-b86b-8bf7e3260b73@2ndquadrant.com>
<b54076fd-67d4-cc80-d5a6-ee8db2528e17@2ndquadrant.com>
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
On 09/05/17 16:28, Peter Eisentraut wrote:
> On 5/9/17 04:39, Petr Jelinek wrote:
>>>> What we want to simulate instead is an "auto" dependency of the slot on
>>>> the subscription. So you can drop the slot separately (subject to other
>>>> restrictions), and it is dropped automatically when the subscription is
>>>> dropped. To avoid that, you can disassociate the slot from the
>>>> subscription, which you have implemented.
>>>>
>>>> I think we can therefore do without RESTRICT/CASCADE here. If a slot is
>>>> associated with the subscription, it should be there when we drop the
>>>> subscription. Otherwise, the user has to disassociate the slot and take
>>>> care of it manually. So just keep the "cascade" behavior.
>>>>
>>>> Similarly, I wouldn't check first whether the slot exists. If the
>>>> subscription is associated with the slot, it should be there.
>>>
>>> Here is your patch amended for that.
>>
>> I am fine with this mechanism as well.
>
> Committed.
>
> I also wrote a bit of documentation about slot handling for
> subscriptions, covering some of what was discussed in this thread.
>
Great, thanks.
Here is rebased version of the other patch (the interface rework). I
also fixed the tab completion there.
--
Petr Jelinek http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackersAttachments:Rework-the-options-for-logical-replication-v2.patch (binary/octet-stream, 60.3K) download
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.sgmlindex 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.sgmlindex 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.sgmlindex 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.sgmlindex 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.cindex 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.cindex 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.yindex 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.cindex 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.plindex 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.cindex 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.hindex 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.outindex 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.sqlindex 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.outindex 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.outindex 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.outindex 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.sqlindex 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.sqlindex 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.sqlindex 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.plindex 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.plindex 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.plindex 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.plindex 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: petr.jelinek@2ndquadrant.com, peter.eisentraut@2ndquadrant.com, tgl@sss.pgh.pa.us, robertmhaas@gmail.com, michael.paquier@gmail.com
Subject: Re: logical replication syntax (was DROP SUBSCRIPTION, query cancellations and slot handling)
In-Reply-To: <20856826-de0f-f630-4c67-36dca21037ad@2ndquadrant.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox