mirror of
https://github.com/postgres/postgres.git
synced 2025-06-06 00:02:36 -04:00
Fix ALTER SUBSCRIPTION grammar ambiguity
There was a grammar ambiguity between SET PUBLICATION name REFRESH and SET PUBLICATION SKIP REFRESH, because SKIP is not a reserved word. To resolve that, fold the refresh choice into the WITH options. Refreshing is the default now. Reported-by: tushar <tushar.ahuja@enterprisedb.com>
This commit is contained in:
parent
06bfb801c7
commit
9907b55ceb
@ -6609,7 +6609,7 @@ SCRAM-SHA-256$<replaceable><iteration count></>:<replaceable><salt><
|
|||||||
<para>
|
<para>
|
||||||
This catalog only contains tables known to the subscription after running
|
This catalog only contains tables known to the subscription after running
|
||||||
either <command>CREATE SUBSCRIPTION</command> or
|
either <command>CREATE SUBSCRIPTION</command> or
|
||||||
<command>ALTER SUBSCRIPTION ... REFRESH</command>.
|
<command>ALTER SUBSCRIPTION ... REFRESH PUBLICATION</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
@ -22,7 +22,7 @@ PostgreSQL documentation
|
|||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> CONNECTION '<replaceable>conninfo</replaceable>'
|
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> CONNECTION '<replaceable>conninfo</replaceable>'
|
||||||
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET PUBLICATION <replaceable class="PARAMETER">publication_name</replaceable> [, ...] { REFRESH [ WITH ( <replaceable class="PARAMETER">refresh_option</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ] | SKIP REFRESH }
|
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> SET PUBLICATION <replaceable class="PARAMETER">publication_name</replaceable> [, ...] [ WITH ( <replaceable class="PARAMETER">set_publication_option</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
|
||||||
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> REFRESH PUBLICATION [ WITH ( <replaceable class="PARAMETER">refresh_option</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
|
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> REFRESH PUBLICATION [ WITH ( <replaceable class="PARAMETER">refresh_option</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
|
||||||
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> ENABLE
|
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> ENABLE
|
||||||
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> DISABLE
|
ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> DISABLE
|
||||||
@ -80,18 +80,29 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
|
|||||||
<para>
|
<para>
|
||||||
Changes list of subscribed publications. See
|
Changes list of subscribed publications. See
|
||||||
<xref linkend="SQL-CREATESUBSCRIPTION"> for more information.
|
<xref linkend="SQL-CREATESUBSCRIPTION"> for more information.
|
||||||
|
By default this command will also act like <literal>REFRESH
|
||||||
|
PUBLICATION</literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When <literal>REFRESH</literal> is specified, this command will also act
|
<replaceable>set_publication_option</replaceable> specifies additional
|
||||||
like <literal>REFRESH
|
options for this operation. The supported options are:
|
||||||
PUBLICATION</literal>. <literal>refresh_option</literal> specifies
|
|
||||||
additional options for the refresh operation, as described
|
<variablelist>
|
||||||
under <literal>REFRESH PUBLICATION</literal>. When
|
<varlistentry>
|
||||||
<literal>SKIP REFRESH</literal> is specified, the command will not try
|
<term><literal>refresh</literal> (<type>boolean</type>)</term>
|
||||||
to refresh table information. Note that
|
<listitem>
|
||||||
either <literal>REFRESH</literal> or <literal>SKIP REFRESH</literal>
|
<para>
|
||||||
must be specified.
|
When false, the command will not try to refresh table information.
|
||||||
|
<literal>REFRESH PUBLICATION</literal> should then be executed separately.
|
||||||
|
The default is <literal>true</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
Additionally, refresh options as described
|
||||||
|
under <literal>REFRESH PUBLICATION</literal> may be specified.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -107,7 +118,7 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<literal>refresh_option</literal> specifies additional options for the
|
<replaceable>refresh_option</replaceable> specifies additional options for the
|
||||||
refresh operation. The supported options are:
|
refresh operation. The supported options are:
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@ -185,7 +196,7 @@ ALTER SUBSCRIPTION <replaceable class="PARAMETER">name</replaceable> RENAME TO <
|
|||||||
Change the publication subscribed by a subscription to
|
Change the publication subscribed by a subscription to
|
||||||
<literal>insert_only</literal>:
|
<literal>insert_only</literal>:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only REFRESH;
|
ALTER SUBSCRIPTION mysub SET PUBLICATION insert_only;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -64,12 +64,14 @@ static void
|
|||||||
parse_subscription_options(List *options, bool *connect, bool *enabled_given,
|
parse_subscription_options(List *options, bool *connect, bool *enabled_given,
|
||||||
bool *enabled, bool *create_slot,
|
bool *enabled, bool *create_slot,
|
||||||
bool *slot_name_given, char **slot_name,
|
bool *slot_name_given, char **slot_name,
|
||||||
bool *copy_data, char **synchronous_commit)
|
bool *copy_data, char **synchronous_commit,
|
||||||
|
bool *refresh)
|
||||||
{
|
{
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
bool connect_given = false;
|
bool connect_given = false;
|
||||||
bool create_slot_given = false;
|
bool create_slot_given = false;
|
||||||
bool copy_data_given = false;
|
bool copy_data_given = false;
|
||||||
|
bool refresh_given = false;
|
||||||
|
|
||||||
/* If connect is specified, the others also need to be. */
|
/* If connect is specified, the others also need to be. */
|
||||||
Assert(!connect || (enabled && create_slot && copy_data));
|
Assert(!connect || (enabled && create_slot && copy_data));
|
||||||
@ -92,6 +94,8 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
|
|||||||
*copy_data = true;
|
*copy_data = true;
|
||||||
if (synchronous_commit)
|
if (synchronous_commit)
|
||||||
*synchronous_commit = NULL;
|
*synchronous_commit = NULL;
|
||||||
|
if (refresh)
|
||||||
|
*refresh = true;
|
||||||
|
|
||||||
/* Parse options */
|
/* Parse options */
|
||||||
foreach(lc, options)
|
foreach(lc, options)
|
||||||
@ -167,6 +171,16 @@ parse_subscription_options(List *options, bool *connect, bool *enabled_given,
|
|||||||
PGC_BACKEND, PGC_S_TEST, GUC_ACTION_SET,
|
PGC_BACKEND, PGC_S_TEST, GUC_ACTION_SET,
|
||||||
false, 0, false);
|
false, 0, false);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(defel->defname, "refresh") == 0 && refresh)
|
||||||
|
{
|
||||||
|
if (refresh_given)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
|
errmsg("conflicting or redundant options")));
|
||||||
|
|
||||||
|
refresh_given = true;
|
||||||
|
*refresh = defGetBoolean(defel);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
@ -315,7 +329,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
|
|||||||
*/
|
*/
|
||||||
parse_subscription_options(stmt->options, &connect, &enabled_given,
|
parse_subscription_options(stmt->options, &connect, &enabled_given,
|
||||||
&enabled, &create_slot, &slotname_given,
|
&enabled, &create_slot, &slotname_given,
|
||||||
&slotname, ©_data, &synchronous_commit);
|
&slotname, ©_data, &synchronous_commit,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since creating a replication slot is not transactional, rolling back
|
* Since creating a replication slot is not transactional, rolling back
|
||||||
@ -645,7 +660,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
|
|||||||
|
|
||||||
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
||||||
NULL, &slotname_given, &slotname,
|
NULL, &slotname_given, &slotname,
|
||||||
NULL, &synchronous_commit);
|
NULL, &synchronous_commit, NULL);
|
||||||
|
|
||||||
if (slotname_given)
|
if (slotname_given)
|
||||||
{
|
{
|
||||||
@ -680,7 +695,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
|
|||||||
|
|
||||||
parse_subscription_options(stmt->options, NULL,
|
parse_subscription_options(stmt->options, NULL,
|
||||||
&enabled_given, &enabled, NULL,
|
&enabled_given, &enabled, NULL,
|
||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL, NULL);
|
||||||
Assert(enabled_given);
|
Assert(enabled_given);
|
||||||
|
|
||||||
if (!sub->slotname && enabled)
|
if (!sub->slotname && enabled)
|
||||||
@ -712,13 +727,13 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ALTER_SUBSCRIPTION_PUBLICATION:
|
case ALTER_SUBSCRIPTION_PUBLICATION:
|
||||||
case ALTER_SUBSCRIPTION_PUBLICATION_REFRESH:
|
|
||||||
{
|
{
|
||||||
bool copy_data;
|
bool copy_data;
|
||||||
|
bool refresh;
|
||||||
|
|
||||||
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, ©_data,
|
NULL, NULL, NULL, ©_data,
|
||||||
NULL);
|
NULL, &refresh);
|
||||||
|
|
||||||
values[Anum_pg_subscription_subpublications - 1] =
|
values[Anum_pg_subscription_subpublications - 1] =
|
||||||
publicationListToArray(stmt->publication);
|
publicationListToArray(stmt->publication);
|
||||||
@ -727,12 +742,13 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
|
|||||||
update_tuple = true;
|
update_tuple = true;
|
||||||
|
|
||||||
/* Refresh if user asked us to. */
|
/* Refresh if user asked us to. */
|
||||||
if (stmt->kind == ALTER_SUBSCRIPTION_PUBLICATION_REFRESH)
|
if (refresh)
|
||||||
{
|
{
|
||||||
if (!sub->enabled)
|
if (!sub->enabled)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||||
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
|
errmsg("ALTER SUBSCRIPTION with refresh is not allowed for disabled subscriptions"),
|
||||||
|
errhint("Use ALTER SUBSCRIPTION ... SET PUBLICATION ... WITH (refresh = false).")));
|
||||||
|
|
||||||
/* Make sure refresh sees the new list of publications. */
|
/* Make sure refresh sees the new list of publications. */
|
||||||
sub->publications = stmt->publication;
|
sub->publications = stmt->publication;
|
||||||
@ -754,7 +770,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
|
|||||||
|
|
||||||
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
parse_subscription_options(stmt->options, NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL, ©_data,
|
NULL, NULL, NULL, ©_data,
|
||||||
NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
AlterSubscription_refresh(sub, copy_data);
|
AlterSubscription_refresh(sub, copy_data);
|
||||||
|
|
||||||
|
@ -9279,24 +9279,14 @@ AlterSubscriptionStmt:
|
|||||||
n->options = $6;
|
n->options = $6;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list REFRESH opt_definition
|
| ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list opt_definition
|
||||||
{
|
|
||||||
AlterSubscriptionStmt *n =
|
|
||||||
makeNode(AlterSubscriptionStmt);
|
|
||||||
n->kind = ALTER_SUBSCRIPTION_PUBLICATION_REFRESH;
|
|
||||||
n->subname = $3;
|
|
||||||
n->publication = $6;
|
|
||||||
n->options = $8;
|
|
||||||
$$ = (Node *)n;
|
|
||||||
}
|
|
||||||
| ALTER SUBSCRIPTION name SET PUBLICATION publication_name_list SKIP REFRESH
|
|
||||||
{
|
{
|
||||||
AlterSubscriptionStmt *n =
|
AlterSubscriptionStmt *n =
|
||||||
makeNode(AlterSubscriptionStmt);
|
makeNode(AlterSubscriptionStmt);
|
||||||
n->kind = ALTER_SUBSCRIPTION_PUBLICATION;
|
n->kind = ALTER_SUBSCRIPTION_PUBLICATION;
|
||||||
n->subname = $3;
|
n->subname = $3;
|
||||||
n->publication = $6;
|
n->publication = $6;
|
||||||
n->options = NIL;
|
n->options = $7;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| ALTER SUBSCRIPTION name ENABLE_P
|
| ALTER SUBSCRIPTION name ENABLE_P
|
||||||
|
@ -3382,7 +3382,6 @@ typedef enum AlterSubscriptionType
|
|||||||
ALTER_SUBSCRIPTION_OPTIONS,
|
ALTER_SUBSCRIPTION_OPTIONS,
|
||||||
ALTER_SUBSCRIPTION_CONNECTION,
|
ALTER_SUBSCRIPTION_CONNECTION,
|
||||||
ALTER_SUBSCRIPTION_PUBLICATION,
|
ALTER_SUBSCRIPTION_PUBLICATION,
|
||||||
ALTER_SUBSCRIPTION_PUBLICATION_REFRESH,
|
|
||||||
ALTER_SUBSCRIPTION_REFRESH,
|
ALTER_SUBSCRIPTION_REFRESH,
|
||||||
ALTER_SUBSCRIPTION_ENABLED
|
ALTER_SUBSCRIPTION_ENABLED
|
||||||
} AlterSubscriptionType;
|
} AlterSubscriptionType;
|
||||||
|
@ -82,7 +82,7 @@ ERROR: invalid connection string syntax: missing "=" after "foobar" in connecti
|
|||||||
testsub | regress_subscription_user | f | {testpub} | off | dbname=doesnotexist
|
testsub | regress_subscription_user | f | {testpub} | off | dbname=doesnotexist
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
|
ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false);
|
||||||
ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
|
ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
|
||||||
ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
|
ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
|
||||||
-- fail
|
-- fail
|
||||||
|
@ -61,7 +61,7 @@ ALTER SUBSCRIPTION testsub CONNECTION 'foobar';
|
|||||||
|
|
||||||
\dRs+
|
\dRs+
|
||||||
|
|
||||||
ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 SKIP REFRESH;
|
ALTER SUBSCRIPTION testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false);
|
||||||
ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
|
ALTER SUBSCRIPTION testsub CONNECTION 'dbname=doesnotexist2';
|
||||||
ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
|
ALTER SUBSCRIPTION testsub SET (slot_name = 'newname');
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ $oldpid = $node_publisher->safe_psql('postgres',
|
|||||||
"SELECT pid FROM pg_stat_replication WHERE application_name = '$appname';"
|
"SELECT pid FROM pg_stat_replication WHERE application_name = '$appname';"
|
||||||
);
|
);
|
||||||
$node_subscriber->safe_psql('postgres',
|
$node_subscriber->safe_psql('postgres',
|
||||||
"ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_ins_only REFRESH WITH (copy_data = false)"
|
"ALTER SUBSCRIPTION tap_sub SET PUBLICATION tap_pub_ins_only WITH (copy_data = false)"
|
||||||
);
|
);
|
||||||
$node_publisher->poll_query_until('postgres',
|
$node_publisher->poll_query_until('postgres',
|
||||||
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname';"
|
"SELECT pid != $oldpid FROM pg_stat_replication WHERE application_name = '$appname';"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user