I find the business with OPT_NONE a bit uselessly verbose. It's like we
haven't completely made up our minds that zero means no options set.
Wouldn't it be simpler to remove that #define and leave the variable
uninitialized until we want to set the options we want, and then use
plain assignment instead of |= ?
I propose the attached cleanup. Some comments seem a bit too obvious;
the use of a local variable for specified_opts instead of directly
assigning to the one in the struct seemed unnecessary; places that call
parse_subscription_options() with only one bit set don't need a separate
variable for the allowed options; added some whitespace.
--
Álvaro Herrera 39°49'30"S 73°17'W — https://www.EnterpriseDB.com/
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index edfef9f14f..eb88d877a5 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -50,16 +50,15 @@
* Options that can be specified by the user in CREATE/ALTER SUBSCRIPTION
* command.
*/
-#define SUBOPT_NONE 0x00000000
-#define SUBOPT_CONNECT 0x00000001
-#define SUBOPT_ENABLED 0x00000002
-#define SUBOPT_CREATE_SLOT 0x00000004
-#define SUBOPT_SLOT_NAME 0x00000008
-#define SUBOPT_COPY_DATA 0x00000010
-#define SUBOPT_SYNCHRONOUS_COMMIT 0x00000020
-#define SUBOPT_REFRESH 0x00000040
-#define SUBOPT_BINARY 0x00000080
-#define SUBOPT_STREAMING 0x00000100
+#define SUBOPT_CONNECT 0x00000001
+#define SUBOPT_ENABLED 0x00000002
+#define SUBOPT_CREATE_SLOT 0x00000004
+#define SUBOPT_SLOT_NAME 0x00000008
+#define SUBOPT_COPY_DATA 0x00000010
+#define SUBOPT_SYNCHRONOUS_COMMIT 0x00000020
+#define SUBOPT_REFRESH 0x00000040
+#define SUBOPT_BINARY 0x00000080
+#define SUBOPT_STREAMING 0x00000100
/* check if the 'val' has 'bits' set */
#define IsSet(val, bits) (((val) & (bits)) == (bits))
@@ -93,48 +92,35 @@ static void ReportSlotConnectionError(List *rstates, Oid subid, char *slotname,
*
* Since not all options can be specified in both commands, this function
* will report an error if mutually exclusive options are specified.
+ *
+ * Caller is expected to have cleared 'opts'.
*/
static void
parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *opts)
{
ListCell *lc;
- bits32 specified_opts;
-
- specified_opts = SUBOPT_NONE;
/* caller must expect some option */
- Assert(supported_opts != SUBOPT_NONE);
+ Assert(supported_opts != 0);
- /* If connect option is supported, the others also need to be. */
+ /* If connect option is supported, these others also need to be. */
Assert(!IsSet(supported_opts, SUBOPT_CONNECT) ||
IsSet(supported_opts, SUBOPT_ENABLED | SUBOPT_CREATE_SLOT |
SUBOPT_COPY_DATA));
- /* Set default values for the supported options. */
+ /* Set default values for the boolean supported options. */
if (IsSet(supported_opts, SUBOPT_CONNECT))
opts->connect = true;
-
if (IsSet(supported_opts, SUBOPT_ENABLED))
opts->enabled = true;
-
if (IsSet(supported_opts, SUBOPT_CREATE_SLOT))
opts->create_slot = true;
-
- if (IsSet(supported_opts, SUBOPT_SLOT_NAME))
- opts->slot_name = NULL;
-
if (IsSet(supported_opts, SUBOPT_COPY_DATA))
opts->copy_data = true;
-
- if (IsSet(supported_opts, SUBOPT_SYNCHRONOUS_COMMIT))
- opts->synchronous_commit = NULL;
-
if (IsSet(supported_opts, SUBOPT_REFRESH))
opts->refresh = true;
-
if (IsSet(supported_opts, SUBOPT_BINARY))
opts->binary = false;
-
if (IsSet(supported_opts, SUBOPT_STREAMING))
opts->streaming = false;
@@ -146,45 +132,45 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
if (IsSet(supported_opts, SUBOPT_CONNECT) &&
strcmp(defel->defname, "connect") == 0)
{
- if (IsSet(specified_opts, SUBOPT_CONNECT))
+ if (IsSet(opts->specified_opts, SUBOPT_CONNECT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_CONNECT;
+ opts->specified_opts |= SUBOPT_CONNECT;
opts->connect = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_ENABLED) &&
strcmp(defel->defname, "enabled") == 0)
{
- if (IsSet(specified_opts, SUBOPT_ENABLED))
+ if (IsSet(opts->specified_opts, SUBOPT_ENABLED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_ENABLED;
+ opts->specified_opts |= SUBOPT_ENABLED;
opts->enabled = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
strcmp(defel->defname, "create_slot") == 0)
{
- if (IsSet(specified_opts, SUBOPT_CREATE_SLOT))
+ if (IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_CREATE_SLOT;
+ opts->specified_opts |= SUBOPT_CREATE_SLOT;
opts->create_slot = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_SLOT_NAME) &&
strcmp(defel->defname, "slot_name") == 0)
{
- if (IsSet(specified_opts, SUBOPT_SLOT_NAME))
+ if (IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_SLOT_NAME;
+ opts->specified_opts |= SUBOPT_SLOT_NAME;
opts->slot_name = defGetString(defel);
/* Setting slot_name = NONE is treated as no slot name. */
@@ -194,23 +180,23 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
else if (IsSet(supported_opts, SUBOPT_COPY_DATA) &&
strcmp(defel->defname, "copy_data") == 0)
{
- if (IsSet(specified_opts, SUBOPT_COPY_DATA))
+ if (IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_COPY_DATA;
+ opts->specified_opts |= SUBOPT_COPY_DATA;
opts->copy_data = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_SYNCHRONOUS_COMMIT) &&
strcmp(defel->defname, "synchronous_commit") == 0)
{
- if (IsSet(specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
+ if (IsSet(opts->specified_opts, SUBOPT_SYNCHRONOUS_COMMIT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
+ opts->specified_opts |= SUBOPT_SYNCHRONOUS_COMMIT;
opts->synchronous_commit = defGetString(defel);
/* Test if the given value is valid for synchronous_commit GUC. */
@@ -221,34 +207,34 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
else if (IsSet(supported_opts, SUBOPT_REFRESH) &&
strcmp(defel->defname, "refresh") == 0)
{
- if (IsSet(specified_opts, SUBOPT_REFRESH))
+ if (IsSet(opts->specified_opts, SUBOPT_REFRESH))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_REFRESH;
+ opts->specified_opts |= SUBOPT_REFRESH;
opts->refresh = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_BINARY) &&
strcmp(defel->defname, "binary") == 0)
{
- if (IsSet(specified_opts, SUBOPT_BINARY))
+ if (IsSet(opts->specified_opts, SUBOPT_BINARY))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_BINARY;
+ opts->specified_opts |= SUBOPT_BINARY;
opts->binary = defGetBoolean(defel);
}
else if (IsSet(supported_opts, SUBOPT_STREAMING) &&
strcmp(defel->defname, "streaming") == 0)
{
- if (IsSet(specified_opts, SUBOPT_STREAMING))
+ if (IsSet(opts->specified_opts, SUBOPT_STREAMING))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("conflicting or redundant options")));
- specified_opts |= SUBOPT_STREAMING;
+ opts->specified_opts |= SUBOPT_STREAMING;
opts->streaming = defGetBoolean(defel);
}
else
@@ -264,23 +250,26 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
if (!opts->connect && IsSet(supported_opts, SUBOPT_CONNECT))
{
/* Check for incompatible options from the user. */
- if (opts->enabled && IsSet(supported_opts, SUBOPT_ENABLED) &&
- IsSet(specified_opts, SUBOPT_ENABLED))
+ if (opts->enabled &&
+ IsSet(supported_opts, SUBOPT_ENABLED) &&
+ IsSet(opts->specified_opts, SUBOPT_ENABLED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/*- translator: both %s are strings of the form "option = value" */
errmsg("%s and %s are mutually exclusive options",
"connect = false", "enabled = true")));
- if (opts->create_slot && IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
- IsSet(specified_opts, SUBOPT_CREATE_SLOT))
+ if (opts->create_slot &&
+ IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
+ IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("%s and %s are mutually exclusive options",
"connect = false", "create_slot = true")));
- if (opts->copy_data && IsSet(supported_opts, SUBOPT_COPY_DATA) &&
- IsSet(specified_opts, SUBOPT_COPY_DATA))
+ if (opts->copy_data &&
+ IsSet(supported_opts, SUBOPT_COPY_DATA) &&
+ IsSet(opts->specified_opts, SUBOPT_COPY_DATA))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("%s and %s are mutually exclusive options",
@@ -296,41 +285,46 @@ parse_subscription_options(List *stmt_options, bits32 supported_opts, SubOpts *o
* Do additional checking for disallowed combination when slot_name = NONE
* was used.
*/
- if (!opts->slot_name && IsSet(supported_opts, SUBOPT_SLOT_NAME) &&
- IsSet(specified_opts, SUBOPT_SLOT_NAME))
+ if (!opts->slot_name &&
+ IsSet(supported_opts, SUBOPT_SLOT_NAME) &&
+ IsSet(opts->specified_opts, SUBOPT_SLOT_NAME))
{
- if (opts->enabled && IsSet(supported_opts, SUBOPT_ENABLED) &&
- IsSet(specified_opts, SUBOPT_ENABLED))
+ if (opts->enabled &&
+ IsSet(supported_opts, SUBOPT_ENABLED) &&
+ IsSet(opts->specified_opts, SUBOPT_ENABLED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/*- translator: both %s are strings of the form "option = value" */
errmsg("%s and %s are mutually exclusive options",
"slot_name = NONE", "enabled = true")));
- if (opts->create_slot && IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
- IsSet(specified_opts, SUBOPT_CREATE_SLOT))
+ if (opts->create_slot &&
+ IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
+ IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
+ /*- translator: both %s are strings of the form "option = value" */
errmsg("%s and %s are mutually exclusive options",
"slot_name = NONE", "create_slot = true")));
- if (opts->enabled && IsSet(supported_opts, SUBOPT_ENABLED) &&
- !IsSet(specified_opts, SUBOPT_ENABLED))
+ if (opts->enabled &&
+ IsSet(supported_opts, SUBOPT_ENABLED) &&
+ !IsSet(opts->specified_opts, SUBOPT_ENABLED))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
/*- translator: both %s are strings of the form "option = value" */
errmsg("subscription with %s must also set %s",
"slot_name = NONE", "enabled = false")));
- if (opts->create_slot && IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
- !IsSet(specified_opts, SUBOPT_CREATE_SLOT))
+ if (opts->create_slot &&
+ IsSet(supported_opts, SUBOPT_CREATE_SLOT) &&
+ !IsSet(opts->specified_opts, SUBOPT_CREATE_SLOT))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
+ /*- translator: both %s are strings of the form "option = value" */
errmsg("subscription with %s must also set %s",
"slot_name = NONE", "create_slot = false")));
}
-
- opts->specified_opts = specified_opts;
}
/*
@@ -383,17 +377,15 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
bits32 supported_opts;
SubOpts opts = {0};
- /* Options that can be specified by CREATE SUBSCRIPTION command. */
- supported_opts = (SUBOPT_CONNECT | SUBOPT_ENABLED | SUBOPT_CREATE_SLOT |
- SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
- SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
- SUBOPT_STREAMING);
-
/*
* Parse and check options.
*
* Connection and publication should not be specified here.
*/
+ supported_opts = (SUBOPT_CONNECT | SUBOPT_ENABLED | SUBOPT_CREATE_SLOT |
+ SUBOPT_SLOT_NAME | SUBOPT_COPY_DATA |
+ SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
+ SUBOPT_STREAMING);
parse_subscription_options(stmt->options, supported_opts, &opts);
/*
@@ -798,7 +790,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
bool update_tuple = false;
Subscription *sub;
Form_pg_subscription form;
- bits32 supported_opts = SUBOPT_NONE;
+ bits32 supported_opts;
SubOpts opts = {0};
rel = table_open(SubscriptionRelationId, RowExclusiveLock);
@@ -835,13 +827,9 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
{
case ALTER_SUBSCRIPTION_OPTIONS:
{
- /*
- * Options that can be specified by this ALTER SUBSCRIPTION
- * kind.
- */
- supported_opts |= (SUBOPT_SLOT_NAME |
- SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
- SUBOPT_STREAMING);
+ supported_opts = (SUBOPT_SLOT_NAME |
+ SUBOPT_SYNCHRONOUS_COMMIT | SUBOPT_BINARY |
+ SUBOPT_STREAMING);
parse_subscription_options(stmt->options, supported_opts, &opts);
@@ -888,13 +876,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_ENABLED:
{
- /*
- * Option that can be specified by this ALTER SUBSCRIPTION
- * kind.
- */
- supported_opts |= SUBOPT_ENABLED;
-
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(stmt->options, SUBOPT_ENABLED, &opts);
Assert(IsSet(opts.specified_opts, SUBOPT_ENABLED));
if (!sub->slotname && opts.enabled)
@@ -927,12 +909,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_SET_PUBLICATION:
{
- /*
- * Options that can be specified by this ALTER SUBSCRIPTION
- * kind.
- */
- supported_opts |= (SUBOPT_COPY_DATA | SUBOPT_REFRESH);
-
+ supported_opts = SUBOPT_COPY_DATA | SUBOPT_REFRESH;
parse_subscription_options(stmt->options, supported_opts, &opts);
values[Anum_pg_subscription_subpublications - 1] =
@@ -967,13 +944,9 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
List *publist;
bool isadd = stmt->kind == ALTER_SUBSCRIPTION_ADD_PUBLICATION;
- /*
- * Options that can be specified by this ALTER SUBSCRIPTION
- * kind.
- */
+ supported_opts = SUBOPT_REFRESH;
if (isadd)
supported_opts |= SUBOPT_COPY_DATA;
- supported_opts |= SUBOPT_REFRESH;
parse_subscription_options(stmt->options, supported_opts, &opts);
@@ -1006,18 +979,12 @@ AlterSubscription(AlterSubscriptionStmt *stmt, bool isTopLevel)
case ALTER_SUBSCRIPTION_REFRESH:
{
- /*
- * Option that can be specified by this ALTER SUBSCRIPTION
- * kind.
- */
- supported_opts |= SUBOPT_COPY_DATA;
-
if (!sub->enabled)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("ALTER SUBSCRIPTION ... REFRESH is not allowed for disabled subscriptions")));
- parse_subscription_options(stmt->options, supported_opts, &opts);
+ parse_subscription_options(stmt->options, SUBOPT_COPY_DATA, &opts);
PreventInTransactionBlock(isTopLevel, "ALTER SUBSCRIPTION ... REFRESH");