From c52b394c811ec980096d248b227552ce854631f5 Mon Sep 17 00:00:00 2001
From: Nitin Jadhav <nitinjadhav@microsoft.com>
Date: Mon, 23 Jan 2023 09:54:13 +0000
Subject: [PATCH] Refactor GetConfigOptionValues function.

GetConfigOptionValues function extracts the config parameters for the given
variable irrespective of whether it results in noshow or not. But the parent
function show_all_settings ignores the values parameter if it results in
noshow. Its unnecessary to fetch all the values during noshow. Hence refactored
GetConfigOptionValues function. Added a new function ConfigOptionIsShowable
which decides whether the parameter is visible or not.
---
 src/backend/utils/misc/guc.c       |  4 +--
 src/backend/utils/misc/guc_funcs.c | 56 ++++++++++++++----------------
 src/include/utils/guc_tables.h     |  3 ++
 3 files changed, 31 insertions(+), 32 deletions(-)

diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d52069f446..7add80dfa7 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5160,9 +5160,7 @@ get_explain_guc_options(int *num)
 			continue;
 
 		/* return only options visible to the current user */
-		if ((conf->flags & GUC_NO_SHOW_ALL) ||
-			((conf->flags & GUC_SUPERUSER_ONLY) &&
-			 !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
+		if (!ConfigOptionIsShowable(conf))
 			continue;
 
 		/* return only options that are different from their boot values */
diff --git a/src/backend/utils/misc/guc_funcs.c b/src/backend/utils/misc/guc_funcs.c
index d59706231b..3cd991688f 100644
--- a/src/backend/utils/misc/guc_funcs.c
+++ b/src/backend/utils/misc/guc_funcs.c
@@ -492,9 +492,7 @@ ShowAllGUCConfig(DestReceiver *dest)
 		struct config_generic *conf = guc_vars[i];
 		char	   *setting;
 
-		if ((conf->flags & GUC_NO_SHOW_ALL) ||
-			((conf->flags & GUC_SUPERUSER_ONLY) &&
-			 !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
+		if (!ConfigOptionIsShowable(conf))
 			continue;
 
 		/* assign to the values array */
@@ -581,25 +579,28 @@ pg_settings_get_flags(PG_FUNCTION_ARGS)
 	PG_RETURN_ARRAYTYPE_P(a);
 }
 
+/*
+ * Return whether the GUC variable is visible or not.
+ */
+bool
+ConfigOptionIsShowable(struct config_generic *conf)
+{
+	if ((conf->flags & GUC_NO_SHOW_ALL) ||
+		((conf->flags & GUC_SUPERUSER_ONLY) &&
+		 !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
+		return false;
+	else
+		return true;
+}
+
 /*
  * Extract fields to show in pg_settings for given variable.
  */
 static void
-GetConfigOptionValues(struct config_generic *conf, const char **values,
-					  bool *noshow)
+GetConfigOptionValues(struct config_generic *conf, const char **values)
 {
 	char		buffer[256];
 
-	if (noshow)
-	{
-		if ((conf->flags & GUC_NO_SHOW_ALL) ||
-			((conf->flags & GUC_SUPERUSER_ONLY) &&
-			 !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_SETTINGS)))
-			*noshow = true;
-		else
-			*noshow = false;
-	}
-
 	/* first get the generic attributes */
 
 	/* name */
@@ -943,27 +944,24 @@ show_all_settings(PG_FUNCTION_ARGS)
 	if (call_cntr < max_calls)	/* do when there is more left to send */
 	{
 		char	   *values[NUM_PG_SETTINGS_ATTS];
-		bool		noshow;
 		HeapTuple	tuple;
 		Datum		result;
 
 		/*
-		 * Get the next visible GUC variable name and value
+		 * Get the next visible GUC variable name
 		 */
-		do
+		while (!ConfigOptionIsShowable(guc_vars[call_cntr]))
 		{
-			GetConfigOptionValues(guc_vars[call_cntr], (const char **) values,
-								  &noshow);
-			if (noshow)
-			{
-				/* bump the counter and get the next config setting */
-				call_cntr = ++funcctx->call_cntr;
+			/* bump the counter and get the next config setting */
+			call_cntr = ++funcctx->call_cntr;
 
-				/* make sure we haven't gone too far now */
-				if (call_cntr >= max_calls)
-					SRF_RETURN_DONE(funcctx);
-			}
-		} while (noshow);
+			/* make sure we haven't gone too far now */
+			if (call_cntr >= max_calls)
+				SRF_RETURN_DONE(funcctx);
+		}
+
+		/* Extract values for the given variable */
+		GetConfigOptionValues(guc_vars[call_cntr], (const char **) values);
 
 		/* build a tuple */
 		tuple = BuildTupleFromCStrings(attinmeta, values);
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 1195abaa3d..b579967168 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -306,4 +306,7 @@ extern char *config_enum_get_options(struct config_enum *record,
 									 const char *suffix,
 									 const char *separator);
 
+/* return whether the GUC variable is visible or not */
+extern bool ConfigOptionIsShowable(struct config_generic *conf);
+
 #endif							/* GUC_TABLES_H */
-- 
2.25.1

