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");
 

Reply via email to