New privileged roles which can SET and ALTER SYSTEM SET

Started by Mark Dilgerabout 4 years ago1 messages
#1Mark Dilger
mark.dilger@enterprisedb.com
12 attachment(s)

These patches have been split off the now deprecated monolithic "Delegating superuser tasks to new security roles" thread at [1].

The purpose of these patches is to allow non-superusers to configure most aspects of a system, so long as they belong to the appropriate privileged role(s):

Attachments:

v1-0001-Allow-SET-and-ALTER-SYSTEM-SET-per-role.patchapplication/octet-stream; name=v1-0001-Allow-SET-and-ALTER-SYSTEM-SET-per-role.patch; x-unix-mode=0644Download
From adf58244b65d138d2f4d64c05dbaca0255225f1d Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:47:04 -0700
Subject: [PATCH v1 01/12] Allow SET and ALTER SYSTEM SET per role.

Lay the groundwork for delegating to built-in roles the privilege to
perform SET and ALTER SYSTEM SET on GUC variables which otherwise
can only be changed by superuser.  Do not delegate any variables
here.  We anticipate follow-on patches to reduce the number of
operations which require superuser by creating built-in roles with
privilege to manage portions of the set of all GUC variables.
---
 contrib/auth_delay/auth_delay.c               |   1 +
 contrib/auto_explain/auto_explain.c           |  12 +
 contrib/pg_prewarm/autoprewarm.c              |   2 +
 .../pg_stat_statements/pg_stat_statements.c   |   5 +
 contrib/pg_trgm/trgm_op.c                     |   3 +
 contrib/postgres_fdw/option.c                 |   1 +
 contrib/sepgsql/hooks.c                       |   2 +
 src/backend/utils/misc/guc.c                  | 717 +++++++++++++-----
 src/include/utils/guc.h                       |   9 +
 src/include/utils/guc_tables.h                |   1 +
 src/pl/plperl/plperl.c                        |   8 +-
 src/pl/plpgsql/src/pl_handler.c               |  10 +-
 src/pl/tcl/pltcl.c                            |   4 +-
 .../modules/delay_execution/delay_execution.c |   1 +
 .../ssl_passphrase_func.c                     |   1 +
 src/test/modules/worker_spi/worker_spi.c      |   3 +
 src/test/regress/expected/guc_privs.out       |  64 ++
 src/test/regress/parallel_schedule            |   2 +-
 src/test/regress/sql/guc_privs.sql            |  48 ++
 19 files changed, 713 insertions(+), 181 deletions(-)
 create mode 100644 src/test/regress/expected/guc_privs.out
 create mode 100644 src/test/regress/sql/guc_privs.sql

diff --git a/contrib/auth_delay/auth_delay.c b/contrib/auth_delay/auth_delay.c
index 5820ac328d..4b151a10ba 100644
--- a/contrib/auth_delay/auth_delay.c
+++ b/contrib/auth_delay/auth_delay.c
@@ -63,6 +63,7 @@ _PG_init(void)
 							0,
 							0, INT_MAX / 1000,
 							PGC_SIGHUP,
+							GUC_SUPERUSER_ONLY,
 							GUC_UNIT_MS,
 							NULL,
 							NULL,
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c
index e9092ba359..e349066375 100644
--- a/contrib/auto_explain/auto_explain.c
+++ b/contrib/auto_explain/auto_explain.c
@@ -100,6 +100,7 @@ _PG_init(void)
 							-1,
 							-1, INT_MAX,
 							PGC_SUSET,
+							GUC_SUPERUSER_ONLY,
 							GUC_UNIT_MS,
 							NULL,
 							NULL,
@@ -111,6 +112,7 @@ _PG_init(void)
 							 &auto_explain_log_analyze,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -122,6 +124,7 @@ _PG_init(void)
 							 &auto_explain_log_settings,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -133,6 +136,7 @@ _PG_init(void)
 							 &auto_explain_log_verbose,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -144,6 +148,7 @@ _PG_init(void)
 							 &auto_explain_log_buffers,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -155,6 +160,7 @@ _PG_init(void)
 							 &auto_explain_log_wal,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -166,6 +172,7 @@ _PG_init(void)
 							 &auto_explain_log_triggers,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -178,6 +185,7 @@ _PG_init(void)
 							 EXPLAIN_FORMAT_TEXT,
 							 format_options,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -190,6 +198,7 @@ _PG_init(void)
 							 LOG,
 							 loglevel_options,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -201,6 +210,7 @@ _PG_init(void)
 							 &auto_explain_log_nested_statements,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -212,6 +222,7 @@ _PG_init(void)
 							 &auto_explain_log_timing,
 							 true,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -225,6 +236,7 @@ _PG_init(void)
 							 0.0,
 							 1.0,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 0289ea657c..b00fcfe7f6 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -116,6 +116,7 @@ _PG_init(void)
 							300,
 							0, INT_MAX / 1000,
 							PGC_SIGHUP,
+							GUC_SUPERUSER_ONLY,
 							GUC_UNIT_S,
 							NULL,
 							NULL,
@@ -131,6 +132,7 @@ _PG_init(void)
 							 &autoprewarm,
 							 true,
 							 PGC_POSTMASTER,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 07fe0e7cda..be32e8613b 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -387,6 +387,7 @@ _PG_init(void)
 							100,
 							INT_MAX,
 							PGC_POSTMASTER,
+							GUC_SUPERUSER_ONLY,
 							0,
 							NULL,
 							NULL,
@@ -399,6 +400,7 @@ _PG_init(void)
 							 PGSS_TRACK_TOP,
 							 track_options,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -410,6 +412,7 @@ _PG_init(void)
 							 &pgss_track_utility,
 							 true,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -421,6 +424,7 @@ _PG_init(void)
 							 &pgss_track_planning,
 							 false,
 							 PGC_SUSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -432,6 +436,7 @@ _PG_init(void)
 							 &pgss_save,
 							 true,
 							 PGC_SIGHUP,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index fb38135f7a..c24d8243c1 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -72,6 +72,7 @@ _PG_init(void)
 							 0.0,
 							 1.0,
 							 PGC_USERSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -84,6 +85,7 @@ _PG_init(void)
 							 0.0,
 							 1.0,
 							 PGC_USERSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
@@ -96,6 +98,7 @@ _PG_init(void)
 							 0.0,
 							 1.0,
 							 PGC_USERSET,
+							 GUC_SUPERUSER_ONLY,
 							 0,
 							 NULL,
 							 NULL,
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index 5bb1af4084..eacee582a8 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -463,6 +463,7 @@ _PG_init(void)
 							   &pgfdw_application_name,
 							   NULL,
 							   PGC_USERSET,
+							   GUC_SUPERUSER_ONLY,
 							   0,
 							   NULL,
 							   NULL,
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index 19a3ffb7ff..df7984de9c 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -432,6 +432,7 @@ _PG_init(void)
 							 &sepgsql_permissive,
 							 false,
 							 PGC_SIGHUP,
+							 GUC_SUPERUSER_ONLY,
 							 GUC_NOT_IN_SAMPLE,
 							 NULL,
 							 NULL,
@@ -450,6 +451,7 @@ _PG_init(void)
 							 &sepgsql_debug_audit,
 							 false,
 							 PGC_USERSET,
+							 GUC_SUPERUSER_ONLY,
 							 GUC_NOT_IN_SAMPLE,
 							 NULL,
 							 NULL,
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d2ce4a8450..04ce8b9d5e 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -974,6 +974,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of sequential-scan plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_seqscan,
@@ -984,6 +985,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of index-scan plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_indexscan,
@@ -994,6 +996,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_indexonlyscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of index-only-scan plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_indexonlyscan,
@@ -1004,6 +1007,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of bitmap-scan plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_bitmapscan,
@@ -1014,6 +1018,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of TID scan plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_tidscan,
@@ -1024,6 +1029,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of explicit sort steps."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_sort,
@@ -1033,7 +1039,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"enable_incremental_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of incremental sort steps."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&enable_incremental_sort,
 		true,
@@ -1043,6 +1050,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of hashed aggregation plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_hashagg,
@@ -1053,6 +1061,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of materialization."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_material,
@@ -1063,6 +1072,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_memoize", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of memoization."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_memoize,
@@ -1073,6 +1083,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of nested-loop join plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_nestloop,
@@ -1083,6 +1094,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of merge join plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_mergejoin,
@@ -1093,6 +1105,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of hash join plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_hashjoin,
@@ -1103,6 +1116,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_gathermerge", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of gather merge plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_gathermerge,
@@ -1113,6 +1127,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_partitionwise_join", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables partitionwise join."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_partitionwise_join,
@@ -1123,6 +1138,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_partitionwise_aggregate", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables partitionwise aggregation and grouping."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_partitionwise_aggregate,
@@ -1133,6 +1149,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_parallel_append", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of parallel append plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_parallel_append,
@@ -1143,6 +1160,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_parallel_hash", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of parallel hash plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_parallel_hash,
@@ -1155,6 +1173,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Allows the query planner and executor to compare partition "
 						 "bounds to conditions in the query to determine which "
 						 "partitions must be scanned."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_partition_pruning,
@@ -1165,6 +1184,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_async_append", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of async append plans."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_async_append,
@@ -1176,6 +1196,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Enables genetic query optimization."),
 			gettext_noop("This algorithm attempts to do planning without "
 						 "exhaustive searching."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&enable_geqo,
@@ -1187,6 +1208,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"is_superuser", PGC_INTERNAL, UNGROUPED,
 			gettext_noop("Shows whether the current user is a superuser."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&session_auth_is_superuser,
@@ -1196,7 +1218,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Enables advertising the server via Bonjour."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&enable_bonjour,
 		false,
@@ -1205,7 +1228,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"track_commit_timestamp", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Collects transaction commit time."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&track_commit_timestamp,
 		false,
@@ -1214,7 +1238,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"ssl", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Enables SSL connections."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&EnableSSL,
 		false,
@@ -1223,7 +1248,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"ssl_passphrase_command_supports_reload", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Also use ssl_passphrase_command during server reload."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_passphrase_command_supports_reload,
 		false,
@@ -1232,7 +1258,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"ssl_prefer_server_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Give priority to server ciphersuite order."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&SSLPreferServerCiphers,
 		true,
@@ -1244,7 +1271,8 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("The server will use the fsync() system call in several places to make "
 						 "sure that updates are physically written to disk. This insures "
 						 "that a database cluster will recover to a consistent state after "
-						 "an operating system or hardware crash.")
+						 "an operating system or hardware crash."),
+			GUC_SUPERUSER_ONLY
 		},
 		&enableFsync,
 		true,
@@ -1259,6 +1287,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "(but still report a warning), and continue processing. This "
 						 "behavior could cause crashes or other serious problems. Only "
 						 "has an effect if checksums are enabled."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&ignore_checksum_failure,
@@ -1273,6 +1302,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "zero_damaged_pages to true causes the system to instead report a "
 						 "warning, zero out the damaged page, and continue processing. This "
 						 "behavior will destroy data, namely all the rows on the damaged page."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&zero_damaged_pages,
@@ -1292,6 +1322,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "crashes, data loss, propagate or hide corruption, "
 						 "or other serious problems. Only has an effect "
 						 "during recovery or in standby mode."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&ignore_invalid_pages,
@@ -1305,7 +1336,8 @@ static struct config_bool ConfigureNamesBool[] =
 						 "only partially written to disk.  During recovery, the row changes "
 						 "stored in WAL are not enough to recover.  This option writes "
 						 "pages when first modified after a checkpoint to WAL so full recovery "
-						 "is possible.")
+						 "is possible."),
+			GUC_SUPERUSER_ONLY
 		},
 		&fullPageWrites,
 		true,
@@ -1315,7 +1347,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"wal_log_hints", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_log_hints,
 		false,
@@ -1325,7 +1358,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"wal_init_zero", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Writes zeroes to new WAL files before first use."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_init_zero,
 		true,
@@ -1335,7 +1369,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"wal_recycle", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Recycles WAL files by renaming them."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_recycle,
 		true,
@@ -1345,7 +1380,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Logs each checkpoint."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_checkpoints,
 		false,
@@ -1354,7 +1390,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_connections", PGC_SU_BACKEND, LOGGING_WHAT,
 			gettext_noop("Logs each successful connection."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_connections,
 		false,
@@ -1363,7 +1400,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_disconnections", PGC_SU_BACKEND, LOGGING_WHAT,
 			gettext_noop("Logs end of a session, including duration."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_disconnections,
 		false,
@@ -1372,7 +1410,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_replication_commands", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs each replication command."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_replication_commands,
 		false,
@@ -1382,6 +1421,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows whether the running server has assertion checks enabled."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&assert_enabled,
@@ -1396,7 +1436,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Terminate session on any error."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ExitOnAnyError,
 		false,
@@ -1405,7 +1446,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Reinitialize server after backend crash."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&restart_after_crash,
 		true,
@@ -1415,6 +1457,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"remove_temp_files_after_crash", PGC_SIGHUP, DEVELOPER_OPTIONS,
 			gettext_noop("Remove temporary files after backend crash."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&remove_temp_files_after_crash,
@@ -1425,7 +1468,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_duration", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs the duration of each completed SQL statement."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_duration,
 		false,
@@ -1434,7 +1478,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's parse tree."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Debug_print_parse,
 		false,
@@ -1443,7 +1488,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's rewritten parse tree."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Debug_print_rewritten,
 		false,
@@ -1452,7 +1498,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's execution plan."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Debug_print_plan,
 		false,
@@ -1461,7 +1508,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Indents parse and plan tree displays."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Debug_pretty_print,
 		true,
@@ -1470,7 +1518,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_parser_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes parser performance statistics to the server log."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_parser_stats,
 		false,
@@ -1479,7 +1528,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_planner_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes planner performance statistics to the server log."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_planner_stats,
 		false,
@@ -1488,7 +1538,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_executor_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes executor performance statistics to the server log."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_executor_stats,
 		false,
@@ -1497,7 +1548,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_statement_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes cumulative performance statistics to the server log."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_statement_stats,
 		false,
@@ -1508,6 +1560,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_btree_build_stats", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Logs system resource usage statistics (memory and CPU) on various B-tree operations."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&log_btree_build_stats,
@@ -1521,7 +1574,8 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Collects information about executing commands."),
 			gettext_noop("Enables the collection of information on the currently "
 						 "executing command of each session, along with "
-						 "the time at which that command began execution.")
+						 "the time at which that command began execution."),
+			GUC_SUPERUSER_ONLY
 		},
 		&pgstat_track_activities,
 		true,
@@ -1530,7 +1584,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"track_counts", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects statistics on database activity."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&pgstat_track_counts,
 		true,
@@ -1539,7 +1594,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects timing statistics for database I/O activity."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&track_io_timing,
 		false,
@@ -1548,7 +1604,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"track_wal_io_timing", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects timing statistics for WAL I/O activity."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&track_wal_io_timing,
 		false,
@@ -1558,7 +1615,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"update_process_title", PGC_SUSET, PROCESS_TITLE,
 			gettext_noop("Updates the process title to show the active SQL command."),
-			gettext_noop("Enables updating of the process title every time a new SQL command is received by the server.")
+			gettext_noop("Enables updating of the process title every time a new SQL command is received by the server."),
+			GUC_SUPERUSER_ONLY
 		},
 		&update_process_title,
 #ifdef WIN32
@@ -1572,7 +1630,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"autovacuum", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Starts the autovacuum subprocess."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_start_daemon,
 		true,
@@ -1583,6 +1642,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_notify,
@@ -1595,6 +1655,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about lock usage."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_locks,
@@ -1605,6 +1666,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about user lock usage."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_userlocks,
@@ -1615,6 +1677,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about lightweight lock usage."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lwlocks,
@@ -1625,6 +1688,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_deadlocks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Dumps information about all current locks when a deadlock timeout occurs."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Debug_deadlocks,
@@ -1636,7 +1700,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs long lock waits."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_lock_waits,
 		false,
@@ -1645,7 +1710,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_recovery_conflict_waits", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Logs standby recovery conflict waits."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_recovery_conflict_waits,
 		false,
@@ -1657,7 +1723,8 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("By default, connection logs only show the IP address "
 						 "of the connecting host. If you want them to show the host name you "
 						 "can turn this on, but depending on your host name resolution "
-						 "setup it might impose a non-negligible performance penalty.")
+						 "setup it might impose a non-negligible performance penalty."),
+			GUC_SUPERUSER_ONLY
 		},
 		&log_hostname,
 		false,
@@ -1670,7 +1737,8 @@ static struct config_bool ConfigureNamesBool[] =
 						 "(or NULL = expr) are treated as expr IS NULL, that is, they "
 						 "return true if expr evaluates to the null value, and false "
 						 "otherwise. The correct behavior of expr = NULL is to always "
-						 "return null (unknown).")
+						 "return null (unknown)."),
+			GUC_SUPERUSER_ONLY
 		},
 		&Transform_null_equals,
 		false,
@@ -1679,7 +1747,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"db_user_namespace", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Enables per-database user names."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Db_user_namespace,
 		false,
@@ -1689,6 +1758,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"default_transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the default read-only status of new transactions."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT
 		},
 		&DefaultXactReadOnly,
@@ -1699,6 +1769,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"transaction_read_only", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the current transaction's read-only status."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&XactReadOnly,
@@ -1708,7 +1779,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"default_transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the default deferrable status of new transactions."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&DefaultXactDeferrable,
 		false,
@@ -1718,6 +1790,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"transaction_deferrable", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Whether to defer a read-only serializable transaction until it can be executed with no possible serialization failures."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&XactDeferrable,
@@ -1727,7 +1800,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"row_security", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Enable row security."),
-			gettext_noop("When enabled, row security will be applied to all users.")
+			gettext_noop("When enabled, row security will be applied to all users."),
+			GUC_SUPERUSER_ONLY
 		},
 		&row_security,
 		true,
@@ -1736,7 +1810,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"check_function_bodies", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Check routine bodies during CREATE FUNCTION and CREATE PROCEDURE."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&check_function_bodies,
 		true,
@@ -1747,7 +1822,8 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Enable input of NULL elements in arrays."),
 			gettext_noop("When turned on, unquoted NULL in an array input "
 						 "value means a null value; "
-						 "otherwise it is taken literally.")
+						 "otherwise it is taken literally."),
+			GUC_SUPERUSER_ONLY
 		},
 		&Array_nulls,
 		true,
@@ -1763,6 +1839,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"default_with_oids", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("WITH OIDS is no longer supported; this can only be false."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE
 		},
 		&default_with_oids,
@@ -1772,7 +1849,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
 			gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Logging_collector,
 		false,
@@ -1781,7 +1859,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Truncate existing log files of same name during log rotation."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_truncate_on_rotation,
 		false,
@@ -1793,6 +1872,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emit information about resource usage in sorting."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&trace_sort,
@@ -1807,6 +1887,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Generate debugging output for synchronized scanning."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&trace_syncscan,
@@ -1822,6 +1903,7 @@ static struct config_bool ConfigureNamesBool[] =
 			"optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enable bounded sorting using heap sort."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
 		},
 		&optimize_bounded_sort,
@@ -1835,6 +1917,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emit WAL-related debugging output."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&XLOG_DEBUG,
@@ -1847,6 +1930,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"integer_datetimes", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows whether datetimes are integer based."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&integer_datetimes,
@@ -1857,7 +1941,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&pg_krb_caseins_users,
 		false,
@@ -1867,7 +1952,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Warn about backslash escapes in ordinary string literals."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&escape_string_warning,
 		true,
@@ -1878,6 +1964,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"standard_conforming_strings", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Causes '...' strings to treat backslashes literally."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT
 		},
 		&standard_conforming_strings,
@@ -1888,7 +1975,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"synchronize_seqscans", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Enable synchronized sequential scans."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&synchronize_seqscans,
 		true,
@@ -1898,7 +1986,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"recovery_target_inclusive", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets whether to include or exclude transaction with recovery target."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recoveryTargetInclusive,
 		true,
@@ -1908,7 +1997,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
 			gettext_noop("Allows connections and queries during recovery."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&EnableHotStandby,
 		true,
@@ -1918,7 +2008,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"hot_standby_feedback", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Allows feedback from a hot standby to the primary that will avoid query conflicts."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&hot_standby_feedback,
 		false,
@@ -1929,6 +2020,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"in_hot_standby", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows whether hot standby is currently active."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&in_hot_standby,
@@ -1940,6 +2032,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"allow_system_table_mods", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Allows modifications of the structure of system tables."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&allowSystemTableMods,
@@ -1952,6 +2045,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Disables reading from system indexes."),
 			gettext_noop("It does not prevent updating the indexes, so it is safe "
 						 "to use.  The worst consequence is slowness."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&IgnoreSystemIndexes,
@@ -1963,7 +2057,8 @@ static struct config_bool ConfigureNamesBool[] =
 		{"lo_compat_privileges", PGC_SUSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Enables backward compatibility mode for privilege checks on large objects."),
 			gettext_noop("Skips privilege checks when reading or modifying large objects, "
-						 "for compatibility with PostgreSQL releases prior to 9.0.")
+						 "for compatibility with PostgreSQL releases prior to 9.0."),
+			GUC_SUPERUSER_ONLY
 		},
 		&lo_compat_privileges,
 		false,
@@ -1974,6 +2069,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"quote_all_identifiers", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("When generating SQL fragments, quote all identifiers."),
 			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&quote_all_identifiers,
 		false,
@@ -1984,6 +2080,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"data_checksums", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows whether data checksums are turned on for this cluster."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
 		},
 		&data_checksums,
@@ -1994,7 +2091,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"syslog_sequence_numbers", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Add sequence number to syslog messages to avoid duplicate suppression."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&syslog_sequence_numbers,
 		true,
@@ -2004,7 +2102,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"syslog_split_messages", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Split messages sent to syslog by lines and to fit into 1024 bytes."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&syslog_split_messages,
 		true,
@@ -2015,6 +2114,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"parallel_leader_participation", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Controls whether Gather and Gather Merge also run subplans."),
 			gettext_noop("Should gather nodes also run subplans or just gather tuples?"),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&parallel_leader_participation,
@@ -2026,6 +2126,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit", PGC_USERSET, QUERY_TUNING_OTHER,
 			gettext_noop("Allow JIT compilation."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&jit_enabled,
@@ -2037,6 +2138,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Register JIT-compiled functions with debugger."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&jit_debugging_support,
@@ -2054,6 +2156,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit_dump_bitcode", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Write out LLVM bitcode to facilitate JIT debugging."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&jit_dump_bitcode,
@@ -2065,6 +2168,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit_expressions", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Allow JIT compilation of expressions."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&jit_expressions,
@@ -2076,6 +2180,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit_profiling_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Register JIT-compiled functions with perf profiler."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&jit_profiling_support,
@@ -2093,6 +2198,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit_tuple_deforming", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Allow JIT compilation of tuple deforming."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&jit_tuple_deforming,
@@ -2103,6 +2209,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"data_sync_retry", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Whether to continue running after a failure to sync data files."),
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&data_sync_retry,
 		false,
@@ -2112,6 +2220,8 @@ static struct config_bool ConfigureNamesBool[] =
 	{
 		{"wal_receiver_create_temp_slot", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured."),
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_receiver_create_temp_slot,
 		false,
@@ -2132,6 +2242,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Forces a switch to the next WAL file if a "
 						 "new file has not been started within N seconds."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&XLogArchiveTimeout,
@@ -2142,6 +2253,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"post_auth_delay", PGC_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Waits N seconds on connection startup after authentication."),
 			gettext_noop("This allows attaching a debugger to the process."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_UNIT_S
 		},
 		&PostAuthDelay,
@@ -2152,7 +2264,8 @@ static struct config_int ConfigureNamesInt[] =
 		{"default_statistics_target", PGC_USERSET, QUERY_TUNING_OTHER,
 			gettext_noop("Sets the default statistics target."),
 			gettext_noop("This applies to table columns that have not had a "
-						 "column-specific target set via ALTER TABLE SET STATISTICS.")
+						 "column-specific target set via ALTER TABLE SET STATISTICS."),
+			GUC_SUPERUSER_ONLY
 		},
 		&default_statistics_target,
 		100, 1, 10000,
@@ -2165,6 +2278,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The planner will merge subqueries into upper "
 						 "queries if the resulting FROM list would have no more than "
 						 "this many items."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&from_collapse_limit,
@@ -2178,6 +2292,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The planner will flatten explicit JOIN "
 						 "constructs into lists of FROM items whenever a "
 						 "list of no more than this many items would result."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&join_collapse_limit,
@@ -2188,6 +2303,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&geqo_threshold,
@@ -2198,6 +2314,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&Geqo_effort,
@@ -2208,6 +2325,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: number of individuals in the population."),
 			gettext_noop("Zero selects a suitable default value."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&Geqo_pool_size,
@@ -2218,6 +2336,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: number of iterations of the algorithm."),
 			gettext_noop("Zero selects a suitable default value."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&Geqo_generations,
@@ -2230,6 +2349,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"deadlock_timeout", PGC_SUSET, LOCK_MANAGEMENT,
 			gettext_noop("Sets the time to wait on a lock before checking for deadlock."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&DeadlockTimeout,
@@ -2241,6 +2361,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&max_standby_archive_delay,
@@ -2252,6 +2373,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&max_standby_streaming_delay,
@@ -2263,6 +2385,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"recovery_min_apply_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the minimum delay for applying changes during recovery."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&recovery_min_apply_delay,
@@ -2274,6 +2397,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum interval between WAL receiver status reports to the sending server."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&wal_receiver_status_interval,
@@ -2285,6 +2409,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum wait time to receive data from the sending server."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&wal_receiver_timeout,
@@ -2295,7 +2420,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the maximum number of concurrent connections."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&MaxConnections,
 		100, 1, MAX_BACKENDS,
@@ -2306,7 +2432,8 @@ static struct config_int ConfigureNamesInt[] =
 		/* see max_connections */
 		{"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the number of connection slots reserved for superusers."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ReservedBackends,
 		3, 0, MAX_BACKENDS,
@@ -2317,6 +2444,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_dynamic_shared_memory", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Amount of dynamic shared memory reserved at startup."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MB
 		},
 		&min_dynamic_shared_memory,
@@ -2332,6 +2460,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Sets the number of shared memory buffers used by the server."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS
 		},
 		&NBuffers,
@@ -2343,6 +2472,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"shared_memory_size", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the size of the server's main shared memory area (rounded up to the nearest MB)."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_UNIT_MB | GUC_RUNTIME_COMPUTED
 		},
 		&shared_memory_size_mb,
@@ -2354,6 +2484,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"shared_memory_size_in_huge_pages", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the number of huge pages needed for the main shared memory area."),
 			gettext_noop("-1 indicates that the value could not be determined."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
 		},
 		&shared_memory_size_in_huge_pages,
@@ -2365,6 +2496,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"temp_buffers", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum number of temporary buffers used by each session."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN
 		},
 		&num_temp_buffers,
@@ -2375,7 +2507,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the TCP port the server listens on."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&PostPortNumber,
 		DEF_PGPORT, 1, 65535,
@@ -2390,7 +2523,8 @@ static struct config_int ConfigureNamesInt[] =
 						 "to be a numeric mode specification in the form "
 						 "accepted by the chmod and umask system calls. "
 						 "(To use the customary octal format the number must "
-						 "start with a 0 (zero).)")
+						 "start with a 0 (zero).)"),
+			GUC_SUPERUSER_ONLY
 		},
 		&Unix_socket_permissions,
 		0777, 0000, 0777,
@@ -2404,7 +2538,8 @@ static struct config_int ConfigureNamesInt[] =
 						 "to be a numeric mode specification in the form "
 						 "accepted by the chmod and umask system calls. "
 						 "(To use the customary octal format the number must "
-						 "start with a 0 (zero).)")
+						 "start with a 0 (zero).)"),
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_file_mode,
 		0600, 0000, 0777,
@@ -2419,6 +2554,7 @@ static struct config_int ConfigureNamesInt[] =
 						 "in the form accepted by the chmod and umask system "
 						 "calls. (To use the customary octal format the number "
 						 "must start with a 0 (zero).)"),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
 		},
 		&data_directory_mode,
@@ -2432,6 +2568,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("This much memory can be used by each internal "
 						 "sort operation and hash table before switching to "
 						 "temporary disk files."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB | GUC_EXPLAIN
 		},
 		&work_mem,
@@ -2443,6 +2580,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum memory to be used for maintenance operations."),
 			gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&maintenance_work_mem,
@@ -2455,6 +2593,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum memory to be used for logical decoding."),
 			gettext_noop("This much memory can be used by each internal "
 						 "reorder buffer before spilling to disk."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&logical_decoding_work_mem,
@@ -2471,6 +2610,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum stack depth, in kilobytes."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&max_stack_depth,
@@ -2482,6 +2622,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
 			gettext_noop("Limits the total size of all temporary files used by each process."),
 			gettext_noop("-1 means no limit."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&temp_file_limit,
@@ -2492,7 +2633,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page found in the buffer cache."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&VacuumCostPageHit,
 		1, 0, 10000,
@@ -2502,7 +2644,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page not found in the buffer cache."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&VacuumCostPageMiss,
 		2, 0, 10000,
@@ -2512,7 +2655,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page dirtied by vacuum."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&VacuumCostPageDirty,
 		20, 0, 10000,
@@ -2522,7 +2666,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost amount available before napping."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&VacuumCostLimit,
 		200, 1, 10000,
@@ -2532,7 +2677,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_vac_cost_limit,
 		-1, -1, 10000,
@@ -2542,7 +2688,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
 			gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_files_per_process,
 		1000, 64, INT_MAX,
@@ -2555,7 +2702,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"max_prepared_transactions", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_prepared_xacts,
 		0, 0, MAX_BACKENDS,
@@ -2567,6 +2715,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the minimum OID of tables for tracking locks."),
 			gettext_noop("Is used to avoid output on system tables."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lock_oidmin,
@@ -2577,6 +2726,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the OID of the table with unconditionally lock tracing."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lock_table,
@@ -2589,6 +2739,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"statement_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum allowed duration of any statement."),
 			gettext_noop("A value of 0 turns off the timeout."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&StatementTimeout,
@@ -2600,6 +2751,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum allowed duration of any wait for a lock."),
 			gettext_noop("A value of 0 turns off the timeout."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&LockTimeout,
@@ -2611,6 +2763,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"idle_in_transaction_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum allowed idle time between queries, when in a transaction."),
 			gettext_noop("A value of 0 turns off the timeout."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&IdleInTransactionSessionTimeout,
@@ -2622,6 +2775,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"idle_session_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum allowed idle time between queries, when not in a transaction."),
 			gettext_noop("A value of 0 turns off the timeout."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&IdleSessionTimeout,
@@ -2632,7 +2786,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Minimum age at which VACUUM should freeze a table row."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_freeze_min_age,
 		50000000, 0, 1000000000,
@@ -2642,7 +2797,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_freeze_table_age,
 		150000000, 0, 2000000000,
@@ -2652,7 +2808,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_multixact_freeze_min_age,
 		5000000, 0, 1000000000,
@@ -2662,7 +2819,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_multixact_freeze_table_age,
 		150000000, 0, 2000000000,
@@ -2672,7 +2830,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_PRIMARY,
 			gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_defer_cleanup_age,
 		0, 0, 1000000,			/* see ComputeXidHorizons */
@@ -2681,7 +2840,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Age at which VACUUM should trigger failsafe to avoid a wraparound outage."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_failsafe_age,
 		1600000000, 0, 2100000000,
@@ -2690,7 +2850,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"vacuum_multixact_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&vacuum_multixact_failsafe_age,
 		1600000000, 0, 2100000000,
@@ -2705,7 +2866,8 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum number of locks per transaction."),
 			gettext_noop("The shared lock table is sized on the assumption that "
 						 "at most max_locks_per_transaction * max_connections distinct "
-						 "objects will need to be locked at any one time.")
+						 "objects will need to be locked at any one time."),
+			GUC_SUPERUSER_ONLY
 		},
 		&max_locks_per_xact,
 		64, 10, INT_MAX,
@@ -2717,7 +2879,8 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum number of predicate locks per transaction."),
 			gettext_noop("The shared predicate lock table is sized on the assumption that "
 						 "at most max_pred_locks_per_transaction * max_connections distinct "
-						 "objects will need to be locked at any one time.")
+						 "objects will need to be locked at any one time."),
+			GUC_SUPERUSER_ONLY
 		},
 		&max_predicate_locks_per_xact,
 		64, 10, INT_MAX,
@@ -2728,7 +2891,8 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_pred_locks_per_relation", PGC_SIGHUP, LOCK_MANAGEMENT,
 			gettext_noop("Sets the maximum number of predicate-locked pages and tuples per relation."),
 			gettext_noop("If more than this total of pages and tuples in the same relation are locked "
-						 "by a connection, those locks are replaced by a relation-level lock.")
+						 "by a connection, those locks are replaced by a relation-level lock."),
+			GUC_SUPERUSER_ONLY
 		},
 		&max_predicate_locks_per_relation,
 		-2, INT_MIN, INT_MAX,
@@ -2739,7 +2903,8 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_pred_locks_per_page", PGC_SIGHUP, LOCK_MANAGEMENT,
 			gettext_noop("Sets the maximum number of predicate-locked tuples per page."),
 			gettext_noop("If more than this number of tuples on the same page are locked "
-						 "by a connection, those locks are replaced by a page-level lock.")
+						 "by a connection, those locks are replaced by a page-level lock."),
+			GUC_SUPERUSER_ONLY
 		},
 		&max_predicate_locks_per_page,
 		2, 0, INT_MAX,
@@ -2750,6 +2915,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"authentication_timeout", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Sets the maximum allowed time to complete client authentication."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&AuthenticationTimeout,
@@ -2762,6 +2928,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"pre_auth_delay", PGC_SIGHUP, DEVELOPER_OPTIONS,
 			gettext_noop("Waits N seconds on connection startup before authentication."),
 			gettext_noop("This allows attaching a debugger to the process."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_UNIT_S
 		},
 		&PreAuthDelay,
@@ -2773,6 +2940,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_keep_size", PGC_SIGHUP, REPLICATION_SENDING,
 			gettext_noop("Sets the size of WAL files held for standby servers."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MB
 		},
 		&wal_keep_size_mb,
@@ -2784,6 +2952,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the minimum size to shrink the WAL to."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MB
 		},
 		&min_wal_size_mb,
@@ -2796,6 +2965,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the WAL size that triggers a checkpoint."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MB
 		},
 		&max_wal_size_mb,
@@ -2808,6 +2978,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&CheckPointTimeout,
@@ -2822,6 +2993,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Write a message to the server log if checkpoints "
 						 "caused by the filling of checkpoint segment files happens more "
 						 "frequently than this number of seconds. Zero turns off the warning."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&CheckPointWarning,
@@ -2833,6 +3005,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"checkpoint_flush_after", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS
 		},
 		&checkpoint_flush_after,
@@ -2844,6 +3017,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_XBLOCKS
 		},
 		&XLOGbuffers,
@@ -2855,6 +3029,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Time between WAL flushes performed in the WAL writer."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&WalWriterDelay,
@@ -2866,6 +3041,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_writer_flush_after", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Amount of WAL written out by WAL writer that triggers a flush."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_XBLOCKS
 		},
 		&WalWriterFlushAfter,
@@ -2877,6 +3053,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_skip_threshold", PGC_USERSET, WAL_SETTINGS,
 			gettext_noop("Minimum size of new file to fsync instead of writing WAL."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&wal_skip_threshold,
@@ -2887,7 +3064,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_wal_senders,
 		10, 0, MAX_BACKENDS,
@@ -2898,7 +3076,8 @@ static struct config_int ConfigureNamesInt[] =
 		/* see max_wal_senders */
 		{"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_replication_slots,
 		10, 0, MAX_BACKENDS /* XXX? */ ,
@@ -2911,6 +3090,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Replication slots will be marked as failed, and segments released "
 						 "for deletion or recycling, if this much space is occupied by WAL "
 						 "on disk."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MB
 		},
 		&max_slot_wal_keep_size_mb,
@@ -2922,6 +3102,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_sender_timeout", PGC_USERSET, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum time to wait for WAL replication."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&wal_sender_timeout,
@@ -2933,7 +3114,8 @@ static struct config_int ConfigureNamesInt[] =
 		{"commit_delay", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Sets the delay in microseconds between transaction commit and "
 						 "flushing WAL to disk."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 			/* we have no microseconds designation, so can't supply units here */
 		},
 		&CommitDelay,
@@ -2945,7 +3127,8 @@ static struct config_int ConfigureNamesInt[] =
 		{"commit_siblings", PGC_USERSET, WAL_SETTINGS,
 			gettext_noop("Sets the minimum concurrent open transactions before performing "
 						 "commit_delay."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&CommitSiblings,
 		5, 0, 1000,
@@ -2958,7 +3141,8 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("This affects real, double precision, and geometric data types. "
 						 "A zero or negative parameter value is added to the standard "
 						 "number of digits (FLT_DIG or DBL_DIG as appropriate). "
-						 "Any value greater than zero selects precise output mode.")
+						 "Any value greater than zero selects precise output mode."),
+			GUC_SUPERUSER_ONLY
 		},
 		&extra_float_digits,
 		1, -15, 3,
@@ -2971,6 +3155,7 @@ static struct config_int ConfigureNamesInt[] =
 						 "a sample of statements will be logged."
 						 " Sampling is determined by log_statement_sample_rate."),
 			gettext_noop("Zero logs a sample of all queries. -1 turns this feature off."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&log_min_duration_sample,
@@ -2983,6 +3168,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the minimum execution time above which "
 						 "all statements will be logged."),
 			gettext_noop("Zero prints all queries. -1 turns this feature off."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&log_min_duration_statement,
@@ -2995,6 +3181,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the minimum execution time above which "
 						 "autovacuum actions will be logged."),
 			gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&Log_autovacuum_min_duration,
@@ -3006,6 +3193,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_parameter_max_length", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("When logging statements, limit logged parameter values to first N bytes."),
 			gettext_noop("-1 to print values in full."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BYTE
 		},
 		&log_parameter_max_length,
@@ -3017,6 +3205,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_parameter_max_length_on_error", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("When reporting an error, limit logged parameter values to first N bytes."),
 			gettext_noop("-1 to print values in full."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BYTE
 		},
 		&log_parameter_max_length_on_error,
@@ -3028,6 +3217,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"bgwriter_delay", PGC_SIGHUP, RESOURCES_BGWRITER,
 			gettext_noop("Background writer sleep time between rounds."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&BgWriterDelay,
@@ -3038,7 +3228,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES_BGWRITER,
 			gettext_noop("Background writer maximum number of LRU pages to flush per round."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&bgwriter_lru_maxpages,
 		100, 0, INT_MAX / 2,	/* Same upper limit as shared_buffers */
@@ -3049,6 +3240,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"bgwriter_flush_after", PGC_SIGHUP, RESOURCES_BGWRITER,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS
 		},
 		&bgwriter_flush_after,
@@ -3062,6 +3254,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&effective_io_concurrency,
@@ -3080,6 +3273,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("A variant of effective_io_concurrency that is used for maintenance work."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&maintenance_io_concurrency,
@@ -3096,6 +3290,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS
 		},
 		&backend_flush_after,
@@ -3109,6 +3304,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Maximum number of concurrent worker processes."),
 			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_worker_processes,
 		8, 0, MAX_BACKENDS,
@@ -3121,6 +3317,7 @@ static struct config_int ConfigureNamesInt[] =
 			REPLICATION_SUBSCRIBERS,
 			gettext_noop("Maximum number of logical replication worker processes."),
 			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_logical_replication_workers,
 		4, 0, MAX_BACKENDS,
@@ -3133,6 +3330,7 @@ static struct config_int ConfigureNamesInt[] =
 			REPLICATION_SUBSCRIBERS,
 			gettext_noop("Maximum number of table synchronization workers per subscription."),
 			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_sync_workers_per_subscription,
 		2, 0, MAX_BACKENDS,
@@ -3143,6 +3341,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Automatic log file rotation will occur after N minutes."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MIN
 		},
 		&Log_RotationAge,
@@ -3154,6 +3353,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Automatic log file rotation will occur after N kilobytes."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&Log_RotationSize,
@@ -3165,6 +3365,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_function_args", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the maximum number of function arguments."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&max_function_args,
@@ -3176,6 +3377,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_index_keys", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the maximum number of index keys."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&max_index_keys,
@@ -3187,6 +3389,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_identifier_length", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the maximum identifier length."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&max_identifier_length,
@@ -3198,6 +3401,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"block_size", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the size of a disk block."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&block_size,
@@ -3209,6 +3413,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"segment_size", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the number of pages per disk file."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&segment_size,
@@ -3220,6 +3425,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the block size in the write ahead log."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&wal_block_size,
@@ -3232,6 +3438,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the time to wait before retrying to retrieve WAL "
 						 "after a failed attempt."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&wal_retrieve_retry_interval,
@@ -3243,6 +3450,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_segment_size", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the size of write ahead log segments."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BYTE | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_RUNTIME_COMPUTED
 		},
 		&wal_segment_size,
@@ -3256,6 +3464,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Time to sleep between autovacuum runs."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&autovacuum_naptime,
@@ -3265,7 +3474,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_vac_thresh,
 		50, 0, INT_MAX,
@@ -3274,7 +3484,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_vac_ins_thresh,
 		1000, -1, INT_MAX,
@@ -3283,7 +3494,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_anl_thresh,
 		50, 0, INT_MAX,
@@ -3293,7 +3505,8 @@ static struct config_int ConfigureNamesInt[] =
 		/* see varsup.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
 		{"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_freeze_max_age,
 
@@ -3308,7 +3521,8 @@ static struct config_int ConfigureNamesInt[] =
 		/* see multixact.c for why this is PGC_POSTMASTER not PGC_SIGHUP */
 		{"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_multixact_freeze_max_age,
 		400000000, 10000, 2000000000,
@@ -3318,7 +3532,8 @@ static struct config_int ConfigureNamesInt[] =
 		/* see max_connections */
 		{"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_max_workers,
 		3, 1, MAX_BACKENDS,
@@ -3328,7 +3543,8 @@ static struct config_int ConfigureNamesInt[] =
 	{
 		{"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel processes per maintenance operation."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&max_parallel_maintenance_workers,
 		2, 0, 1024,
@@ -3339,6 +3555,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel processes per executor node."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&max_parallel_workers_per_gather,
@@ -3350,6 +3567,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel workers that can be active at one time."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&max_parallel_workers,
@@ -3361,6 +3579,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
 			gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&autovacuum_work_mem,
@@ -3372,6 +3591,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"old_snapshot_threshold", PGC_POSTMASTER, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Time before a snapshot is too old to read pages changed after the snapshot was taken."),
 			gettext_noop("A value of -1 disables this feature."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MIN
 		},
 		&old_snapshot_threshold,
@@ -3383,6 +3603,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_keepalives_idle", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Time between issuing TCP keepalives."),
 			gettext_noop("A value of 0 uses the system default."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&tcp_keepalives_idle,
@@ -3394,6 +3615,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_keepalives_interval", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Time between TCP keepalive retransmits."),
 			gettext_noop("A value of 0 uses the system default."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_S
 		},
 		&tcp_keepalives_interval,
@@ -3405,6 +3627,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SSL,
 			gettext_noop("SSL renegotiation is no longer supported; this can only be 0."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE,
 		},
 		&ssl_renegotiation_limit,
@@ -3418,6 +3641,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
 						 "lost before a connection is considered dead. A value of 0 uses the "
 						 "system default."),
+			GUC_SUPERUSER_ONLY
 		},
 		&tcp_keepalives_count,
 		0, 0, INT_MAX,
@@ -3428,6 +3652,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER,
 			gettext_noop("Sets the maximum allowed result for exact search by GIN."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			0
 		},
 		&GinFuzzySearchLimit,
@@ -3440,6 +3665,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the planner's assumption about the total size of the data caches."),
 			gettext_noop("That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. "
 						 "This is measured in disk pages, which are normally 8 kB each."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&effective_cache_size,
@@ -3451,6 +3677,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_parallel_table_scan_size", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Sets the minimum amount of table data for a parallel scan."),
 			gettext_noop("If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&min_parallel_table_scan_size,
@@ -3462,6 +3689,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_parallel_index_scan_size", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Sets the minimum amount of index data for a parallel scan."),
 			gettext_noop("If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&min_parallel_index_scan_size,
@@ -3474,6 +3702,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"server_version_num", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the server version as an integer."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&server_version_num,
@@ -3485,6 +3714,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_temp_files", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
 			gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&log_temp_files,
@@ -3496,6 +3726,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"track_activity_query_size", PGC_POSTMASTER, STATS_COLLECTOR,
 			gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_BYTE
 		},
 		&pgstat_track_activity_query_size,
@@ -3507,6 +3738,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"gin_pending_list_limit", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the maximum size of the pending list for GIN index."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&gin_pending_list_limit,
@@ -3518,6 +3750,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_user_timeout", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("TCP user timeout."),
 			gettext_noop("A value of 0 uses the system default."),
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&tcp_user_timeout,
@@ -3529,6 +3762,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"huge_page_size", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("The size of huge page that should be requested."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_KB
 		},
 		&huge_page_size,
@@ -3540,6 +3774,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"debug_discard_caches", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Aggressively flush system caches for debugging purposes."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&debug_discard_caches,
@@ -3563,6 +3798,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"client_connection_check_interval", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the time interval between checks for disconnection while running queries."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&client_connection_check_interval,
@@ -3584,6 +3820,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of a "
 						 "sequentially fetched disk page."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&seq_page_cost,
@@ -3595,6 +3832,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of a "
 						 "nonsequentially fetched disk page."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&random_page_cost,
@@ -3606,6 +3844,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each tuple (row)."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&cpu_tuple_cost,
@@ -3617,6 +3856,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each index entry during an index scan."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&cpu_index_tuple_cost,
@@ -3628,6 +3868,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each operator or function call."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&cpu_operator_cost,
@@ -3639,6 +3880,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "passing each tuple (row) from worker to leader backend."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&parallel_tuple_cost,
@@ -3650,6 +3892,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "starting up worker processes for parallel query."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&parallel_setup_cost,
@@ -3661,6 +3904,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Perform JIT compilation if query is more expensive."),
 			gettext_noop("-1 disables JIT compilation."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&jit_above_cost,
@@ -3672,6 +3916,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_optimize_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Optimize JIT-compiled functions if query is more expensive."),
 			gettext_noop("-1 disables optimization."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&jit_optimize_above_cost,
@@ -3683,6 +3928,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_inline_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Perform JIT inlining if query is more expensive."),
 			gettext_noop("-1 disables inlining."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&jit_inline_above_cost,
@@ -3695,6 +3941,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the fraction of "
 						 "a cursor's rows that will be retrieved."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&cursor_tuple_fraction,
@@ -3706,6 +3953,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: selective pressure within the population."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&Geqo_selection_bias,
@@ -3717,6 +3965,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: seed for random path selection."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&Geqo_seed,
@@ -3728,6 +3977,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"hash_mem_multiplier", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Multiple of work_mem to use for hash tables."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&hash_mem_multiplier,
@@ -3738,7 +3988,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES_BGWRITER,
 			gettext_noop("Multiple of the average buffer usage to free per round."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&bgwriter_lru_multiplier,
 		2.0, 0.0, 10.0,
@@ -3749,6 +4000,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"seed", PGC_USERSET, UNGROUPED,
 			gettext_noop("Sets the seed for random-number generation."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&phony_random_seed,
@@ -3760,6 +4012,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost delay in milliseconds."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&VacuumCostDelay,
@@ -3771,6 +4024,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_UNIT_MS
 		},
 		&autovacuum_vac_cost_delay,
@@ -3781,7 +4035,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_vac_scale,
 		0.2, 0.0, 100.0,
@@ -3791,7 +4046,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"autovacuum_vacuum_insert_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple inserts prior to vacuum as a fraction of reltuples."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_vac_ins_scale,
 		0.2, 0.0, 100.0,
@@ -3801,7 +4057,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&autovacuum_anl_scale,
 		0.1, 0.0, 100.0,
@@ -3811,7 +4068,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&CheckPointCompletionTarget,
 		0.9, 0.0, 1.0,
@@ -3821,7 +4079,8 @@ static struct config_real ConfigureNamesReal[] =
 	{
 		{"log_statement_sample_rate", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Fraction of statements exceeding log_min_duration_sample to be logged."),
-			gettext_noop("Use a value between 0.0 (never log) and 1.0 (always log).")
+			gettext_noop("Use a value between 0.0 (never log) and 1.0 (always log)."),
+			GUC_SUPERUSER_ONLY
 		},
 		&log_statement_sample_rate,
 		1.0, 0.0, 1.0,
@@ -3832,7 +4091,8 @@ static struct config_real ConfigureNamesReal[] =
 		{"log_transaction_sample_rate", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Sets the fraction of transactions from which to log all statements."),
 			gettext_noop("Use a value between 0.0 (never log) and 1.0 (log all "
-						 "statements for all transactions).")
+						 "statements for all transactions)."),
+			GUC_SUPERUSER_ONLY
 		},
 		&log_xact_sample_rate,
 		0.0, 0.0, 1.0,
@@ -3851,7 +4111,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
 			gettext_noop("Sets the shell command that will be called to archive a WAL file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&XLogArchiveCommand,
 		"",
@@ -3861,7 +4122,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"restore_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be called to retrieve an archived WAL file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recoveryRestoreCommand,
 		"",
@@ -3871,7 +4133,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"archive_cleanup_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be executed at every restart point."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&archiveCleanupCommand,
 		"",
@@ -3881,7 +4144,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_end_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be executed once at the end of recovery."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recoveryEndCommand,
 		"",
@@ -3891,7 +4155,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Specifies the timeline to recover into."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_timeline_string,
 		"latest",
@@ -3901,7 +4166,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Set to \"immediate\" to end recovery as soon as a consistent state is reached."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_string,
 		"",
@@ -3910,7 +4176,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target_xid", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the transaction ID up to which recovery will proceed."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_xid_string,
 		"",
@@ -3919,7 +4186,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target_time", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the time stamp up to which recovery will proceed."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_time_string,
 		"",
@@ -3928,7 +4196,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target_name", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the named restore point up to which recovery will proceed."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_name_string,
 		"",
@@ -3937,7 +4206,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"recovery_target_lsn", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the LSN of the write-ahead log location up to which recovery will proceed."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_target_lsn_string,
 		"",
@@ -3947,7 +4217,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"promote_trigger_file", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Specifies a file name whose presence ends recovery in the standby."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&PromoteTriggerFile,
 		"",
@@ -3968,7 +4239,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"primary_slot_name", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the name of the replication slot to use on the sending server."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&PrimarySlotName,
 		"",
@@ -3979,6 +4251,7 @@ static struct config_string ConfigureNamesString[] =
 		{"client_encoding", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the client's character set encoding."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME | GUC_REPORT
 		},
 		&client_encoding_string,
@@ -3989,7 +4262,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Controls information prefixed to each log line."),
-			gettext_noop("If blank, no prefix is used.")
+			gettext_noop("If blank, no prefix is used."),
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_line_prefix,
 		"%m [%p] ",
@@ -3999,7 +4273,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Sets the time zone to use in log messages."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_timezone_string,
 		"GMT",
@@ -4011,6 +4286,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Sets the display format for date and time values."),
 			gettext_noop("Also controls interpretation of ambiguous "
 						 "date inputs."),
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_REPORT
 		},
 		&datestyle_string,
@@ -4022,6 +4298,7 @@ static struct config_string ConfigureNamesString[] =
 		{"default_table_access_method", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the default table access method for new tables."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME
 		},
 		&default_table_access_method,
@@ -4033,6 +4310,7 @@ static struct config_string ConfigureNamesString[] =
 		{"default_tablespace", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the default tablespace to create tables and indexes in."),
 			gettext_noop("An empty string selects the database's default tablespace."),
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME
 		},
 		&default_tablespace,
@@ -4044,6 +4322,7 @@ static struct config_string ConfigureNamesString[] =
 		{"temp_tablespaces", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the tablespace(s) to use for temporary tables and sort files."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE
 		},
 		&temp_tablespaces,
@@ -4079,7 +4358,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the Bonjour service name."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&bonjour_name,
 		"",
@@ -4092,6 +4372,7 @@ static struct config_string ConfigureNamesString[] =
 		{"lc_collate", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the collation order locale."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&locale_collate,
@@ -4103,6 +4384,7 @@ static struct config_string ConfigureNamesString[] =
 		{"lc_ctype", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the character classification and case conversion locale."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&locale_ctype,
@@ -4113,7 +4395,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"lc_messages", PGC_SUSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the language in which messages are displayed."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&locale_messages,
 		"",
@@ -4123,7 +4406,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"lc_monetary", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the locale for formatting monetary amounts."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&locale_monetary,
 		"C",
@@ -4133,7 +4417,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"lc_numeric", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the locale for formatting numbers."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&locale_numeric,
 		"C",
@@ -4143,7 +4428,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"lc_time", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the locale for formatting date and time values."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&locale_time,
 		"C",
@@ -4154,6 +4440,7 @@ static struct config_string ConfigureNamesString[] =
 		{"session_preload_libraries", PGC_SUSET, CLIENT_CONN_PRELOAD,
 			gettext_noop("Lists shared libraries to preload into each backend."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
 		},
 		&session_preload_libraries_string,
@@ -4165,6 +4452,7 @@ static struct config_string ConfigureNamesString[] =
 		{"shared_preload_libraries", PGC_POSTMASTER, CLIENT_CONN_PRELOAD,
 			gettext_noop("Lists shared libraries to preload into server."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
 		},
 		&shared_preload_libraries_string,
@@ -4176,6 +4464,7 @@ static struct config_string ConfigureNamesString[] =
 		{"local_preload_libraries", PGC_USERSET, CLIENT_CONN_PRELOAD,
 			gettext_noop("Lists unprivileged shared libraries to preload into each backend."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE
 		},
 		&local_preload_libraries_string,
@@ -4187,6 +4476,7 @@ static struct config_string ConfigureNamesString[] =
 		{"search_path", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the schema search order for names that are not schema-qualified."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_EXPLAIN
 		},
 		&namespace_search_path,
@@ -4199,6 +4489,7 @@ static struct config_string ConfigureNamesString[] =
 		{"server_encoding", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the server (database) character set encoding."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&server_encoding_string,
@@ -4211,6 +4502,7 @@ static struct config_string ConfigureNamesString[] =
 		{"server_version", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the server version."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&server_version_string,
@@ -4223,6 +4515,7 @@ static struct config_string ConfigureNamesString[] =
 		{"role", PGC_USERSET, UNGROUPED,
 			gettext_noop("Sets the current role."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
 		},
 		&role_string,
@@ -4235,6 +4528,7 @@ static struct config_string ConfigureNamesString[] =
 		{"session_authorization", PGC_USERSET, UNGROUPED,
 			gettext_noop("Sets the session user name."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME | GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_NOT_WHILE_SEC_REST
 		},
 		&session_authorization_string,
@@ -4248,6 +4542,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Valid values are combinations of \"stderr\", "
 						 "\"syslog\", \"csvlog\", and \"eventlog\", "
 						 "depending on the platform."),
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT
 		},
 		&Log_destination_string,
@@ -4280,7 +4575,8 @@ static struct config_string ConfigureNamesString[] =
 		{"syslog_ident", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Sets the program name used to identify PostgreSQL "
 						 "messages in syslog."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&syslog_ident_str,
 		"postgres",
@@ -4291,7 +4587,8 @@ static struct config_string ConfigureNamesString[] =
 		{"event_source", PGC_POSTMASTER, LOGGING_WHERE,
 			gettext_noop("Sets the application name used to identify "
 						 "PostgreSQL messages in the event log."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&event_source,
 		DEFAULT_EVENT_SOURCE,
@@ -4302,6 +4599,7 @@ static struct config_string ConfigureNamesString[] =
 		{"TimeZone", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the time zone for displaying and interpreting time stamps."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT
 		},
 		&timezone_string,
@@ -4311,7 +4609,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"timezone_abbreviations", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Selects a file of time zone abbreviations."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&timezone_abbreviations_string,
 		NULL,
@@ -4322,7 +4621,8 @@ static struct config_string ConfigureNamesString[] =
 		{"unix_socket_group", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the owning group of the Unix-domain socket."),
 			gettext_noop("The owning user of the socket is always the user "
-						 "that starts the server.")
+						 "that starts the server."),
+			GUC_SUPERUSER_ONLY
 		},
 		&Unix_socket_group,
 		"",
@@ -4333,6 +4633,7 @@ static struct config_string ConfigureNamesString[] =
 		{"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the directories where Unix-domain sockets will be created."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
 		},
 		&Unix_socket_directories,
@@ -4348,6 +4649,7 @@ static struct config_string ConfigureNamesString[] =
 		{"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the host name or IP address(es) to listen to."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT
 		},
 		&ListenAddresses,
@@ -4363,6 +4665,7 @@ static struct config_string ConfigureNamesString[] =
 		{"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
 			gettext_noop("Sets the server's data directory."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_SUPERUSER_ONLY | GUC_DISALLOW_IN_AUTO_FILE
 		},
 		&data_directory,
@@ -4374,6 +4677,7 @@ static struct config_string ConfigureNamesString[] =
 		{"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
 			gettext_noop("Sets the server's main configuration file."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
 		},
 		&ConfigFileName,
@@ -4418,6 +4722,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_library", PGC_INTERNAL, PRESET_OPTIONS,
 			gettext_noop("Shows the name of the SSL library."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&ssl_library,
@@ -4432,7 +4737,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"ssl_cert_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL server certificate file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_cert_file,
 		"server.crt",
@@ -4442,7 +4748,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"ssl_key_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL server private key file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_key_file,
 		"server.key",
@@ -4452,7 +4759,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"ssl_ca_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate authority file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_ca_file,
 		"",
@@ -4462,7 +4770,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"ssl_crl_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate revocation list file."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_crl_file,
 		"",
@@ -4472,7 +4781,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"ssl_crl_dir", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate revocation list directory."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&ssl_crl_dir,
 		"",
@@ -4494,6 +4804,7 @@ static struct config_string ConfigureNamesString[] =
 		{"synchronous_standby_names", PGC_SIGHUP, REPLICATION_PRIMARY,
 			gettext_noop("Number of synchronous standbys and list of names of potential synchronous ones."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT
 		},
 		&SyncRepStandbyNames,
@@ -4504,7 +4815,8 @@ static struct config_string ConfigureNamesString[] =
 	{
 		{"default_text_search_config", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets default text search configuration."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&TSCurrentConfig,
 		"pg_catalog.simple",
@@ -4567,6 +4879,7 @@ static struct config_string ConfigureNamesString[] =
 		{"application_name", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Sets the application name to be reported in statistics and logs."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
 		},
 		&application_name,
@@ -4578,6 +4891,7 @@ static struct config_string ConfigureNamesString[] =
 		{"cluster_name", PGC_POSTMASTER, PROCESS_TITLE,
 			gettext_noop("Sets the name of the cluster, which is included in the process title."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_IS_NAME
 		},
 		&cluster_name,
@@ -4589,6 +4903,7 @@ static struct config_string ConfigureNamesString[] =
 		{"wal_consistency_checking", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the WAL resource managers for which WAL consistency checks are done."),
 			gettext_noop("Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay."),
+			GUC_SUPERUSER_ONLY,
 			GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE
 		},
 		&wal_consistency_checking_string,
@@ -4611,6 +4926,7 @@ static struct config_string ConfigureNamesString[] =
 		{"backtrace_functions", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Log backtrace for errors in these functions."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE
 		},
 		&backtrace_functions,
@@ -4630,7 +4946,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"backslash_quote", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Sets whether \"\\'\" is allowed in string literals."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&backslash_quote,
 		BACKSLASH_QUOTE_SAFE_ENCODING, backslash_quote_options,
@@ -4640,7 +4957,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"bytea_output", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the output format for bytea."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&bytea_output,
 		BYTEA_OUTPUT_HEX, bytea_output_options,
@@ -4651,7 +4969,8 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"client_min_messages", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the message levels that are sent to the client."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
-						 " the level, the fewer messages are sent.")
+						 " the level, the fewer messages are sent."),
+			GUC_SUPERUSER_ONLY
 		},
 		&client_min_messages,
 		NOTICE, client_message_level_options,
@@ -4661,7 +4980,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"compute_query_id", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Compute query identifiers."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&compute_query_id,
 		COMPUTE_QUERY_ID_AUTO, compute_query_id_options,
@@ -4673,6 +4993,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Enables the planner to use constraints to optimize queries."),
 			gettext_noop("Table scans will be skipped if their constraints"
 						 " guarantee that no rows match the query."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&constraint_exclusion,
@@ -4683,7 +5004,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"default_toast_compression", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the default compression method for compressible values."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&default_toast_compression,
 		TOAST_PGLZ_COMPRESSION,
@@ -4694,7 +5016,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"default_transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the transaction isolation level of each new transaction."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&DefaultXactIsoLevel,
 		XACT_READ_COMMITTED, isolation_level_options,
@@ -4705,6 +5028,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"transaction_isolation", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the current transaction's isolation level."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
 		},
 		&XactIsoLevel,
@@ -4716,6 +5040,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"IntervalStyle", PGC_USERSET, CLIENT_CONN_LOCALE,
 			gettext_noop("Sets the display format for interval values."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_REPORT
 		},
 		&IntervalStyle,
@@ -4726,7 +5051,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Sets the verbosity of logged messages."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Log_error_verbosity,
 		PGERROR_DEFAULT, log_error_verbosity_options,
@@ -4737,7 +5063,8 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"log_min_messages", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Sets the message levels that are logged."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
-						 " the level, the fewer messages are sent.")
+						 " the level, the fewer messages are sent."),
+			GUC_SUPERUSER_ONLY
 		},
 		&log_min_messages,
 		WARNING, server_message_level_options,
@@ -4748,7 +5075,8 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"log_min_error_statement", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Causes all statements generating error at or above this level to be logged."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
-						 " the level, the fewer messages are sent.")
+						 " the level, the fewer messages are sent."),
+			GUC_SUPERUSER_ONLY
 		},
 		&log_min_error_statement,
 		ERROR, server_message_level_options,
@@ -4758,7 +5086,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"log_statement", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Sets the type of statements logged."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&log_statement,
 		LOGSTMT_NONE, log_statement_options,
@@ -4768,7 +5097,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&syslog_facility,
 #ifdef HAVE_SYSLOG
@@ -4783,7 +5113,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"session_replication_role", PGC_SUSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets the session's behavior for triggers and rewrite rules."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&SessionReplicationRole,
 		SESSION_REPLICATION_ROLE_ORIGIN, session_replication_role_options,
@@ -4793,7 +5124,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
 			gettext_noop("Sets the current transaction's synchronization level."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&synchronous_commit,
 		SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
@@ -4803,7 +5135,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
 			gettext_noop("Allows archiving of WAL files using archive_command."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&XLogArchiveMode,
 		ARCHIVE_MODE_OFF, archive_mode_options,
@@ -4813,7 +5146,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"recovery_target_action", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the action to perform upon reaching the recovery target."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recoveryTargetAction,
 		RECOVERY_TARGET_ACTION_PAUSE, recovery_target_action_options,
@@ -4824,7 +5158,8 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"trace_recovery_messages", PGC_SIGHUP, DEVELOPER_OPTIONS,
 			gettext_noop("Enables logging of recovery-related debugging information."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
-						 " the level, the fewer messages are sent.")
+						 " the level, the fewer messages are sent."),
+			GUC_SUPERUSER_ONLY
 		},
 		&trace_recovery_messages,
 
@@ -4839,7 +5174,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"track_functions", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects function-level statistics on database activity."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&pgstat_track_functions,
 		TRACK_FUNC_OFF, track_function_options,
@@ -4849,7 +5185,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"wal_compression", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Compresses full-page writes written in WAL file with specified method."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_compression,
 		WAL_COMPRESSION_NONE, wal_compression_options,
@@ -4859,7 +5196,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Sets the level of information written to the WAL."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&wal_level,
 		WAL_LEVEL_REPLICA, wal_level_options,
@@ -4869,7 +5207,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Selects the dynamic shared memory implementation used."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&dynamic_shared_memory_type,
 		DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options,
@@ -4879,7 +5218,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Selects the shared memory implementation used for the main shared memory region."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&shared_memory_type,
 		DEFAULT_SHARED_MEMORY_TYPE, shared_memory_options,
@@ -4889,7 +5229,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Selects the method used for forcing WAL updates to disk."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&sync_method,
 		DEFAULT_SYNC_METHOD, sync_method_options,
@@ -4899,7 +5240,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"xmlbinary", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets how binary values are to be encoded in XML."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&xmlbinary,
 		XMLBINARY_BASE64, xmlbinary_options,
@@ -4910,7 +5252,8 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"xmloption", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Sets whether XML data in implicit parsing and serialization "
 						 "operations is to be considered as documents or content fragments."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&xmloption,
 		XMLOPTION_CONTENT, xmloption_options,
@@ -4920,7 +5263,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Use of huge pages on Linux or Windows."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&huge_pages,
 		HUGE_PAGES_TRY, huge_pages_options,
@@ -4931,6 +5275,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"force_parallel_mode", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Forces use of parallel query facilities."),
 			gettext_noop("If possible, run query using a parallel worker and with parallel restrictions."),
+			GUC_SUPERUSER_ONLY,
 			GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
 		},
 		&force_parallel_mode,
@@ -4941,7 +5286,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"password_encryption", PGC_USERSET, CONN_AUTH_AUTH,
 			gettext_noop("Chooses the algorithm for encrypting passwords."),
-			NULL
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&Password_encryption,
 		PASSWORD_TYPE_SCRAM_SHA_256, password_encryption_options,
@@ -4954,6 +5300,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Prepared statements can have custom and generic plans, and the planner "
 						 "will attempt to choose which is better.  This can be set to override "
 						 "the default behavior."),
+			GUC_SUPERUSER_ONLY,
 			GUC_EXPLAIN
 		},
 		&plan_cache_mode,
@@ -4977,6 +5324,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
 			NULL,
+			GUC_SUPERUSER_ONLY,
 			GUC_SUPERUSER_ONLY
 		},
 		&ssl_max_protocol_version,
@@ -4988,6 +5336,8 @@ static struct config_enum ConfigureNamesEnum[] =
 	{
 		{"recovery_init_sync_method", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Sets the method for synchronizing the data directory before crash recovery."),
+			NULL,
+			GUC_SUPERUSER_ONLY
 		},
 		&recovery_init_sync_method,
 		RECOVERY_INIT_SYNC_METHOD_FSYNC, recovery_init_sync_method_options,
@@ -7275,6 +7625,15 @@ parse_and_validate_value(struct config_generic *record,
 	return true;
 }
 
+static bool
+role_has_privileges(Oid roleid, int privileges)
+{
+	if ((privileges & GUC_SUPERUSER_ONLY) && !superuser_arg(roleid))
+		return false;
+
+	return true;
+}
+
 
 /*
  * Sets option `name' to given value.
@@ -7422,7 +7781,8 @@ set_config_option(const char *name, const char *value,
 			break;
 		case PGC_SU_BACKEND:
 			/* Reject if we're connecting but user is not superuser */
-			if (context == PGC_BACKEND)
+			if (context == PGC_BACKEND &&
+				!role_has_privileges(GetUserId(), record->privileges))
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -7469,7 +7829,8 @@ set_config_option(const char *name, const char *value,
 			}
 			break;
 		case PGC_SUSET:
-			if (context == PGC_USERSET || context == PGC_BACKEND)
+			if ((context == PGC_USERSET || context == PGC_BACKEND) &&
+				!role_has_privileges(GetUserId(), record->privileges))
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -8511,6 +8872,7 @@ replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
 void
 AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 {
+	VariableSetKind kind;
 	char	   *name;
 	char	   *value;
 	bool		resetall = false;
@@ -8520,17 +8882,18 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 	char		AutoConfFileName[MAXPGPATH];
 	char		AutoConfTmpFileName[MAXPGPATH];
 
-	if (!superuser())
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("must be superuser to execute ALTER SYSTEM command")));
-
 	/*
 	 * Extract statement arguments
 	 */
 	name = altersysstmt->setstmt->name;
+	kind = altersysstmt->setstmt->kind;
 
-	switch (altersysstmt->setstmt->kind)
+	if (!superuser() && kind == VAR_RESET_ALL)
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("must be superuser to execute ALTER SYSTEM RESET ALL command")));
+
+	switch (kind)
 	{
 		case VAR_SET_VALUE:
 			value = ExtractSetVariableArgs(altersysstmt->setstmt);
@@ -8574,6 +8937,15 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 					 errmsg("parameter \"%s\" cannot be changed",
 							name)));
 
+		/*
+		 * Deny non-superusers trying to run ALTER SYSTEM SET on variables
+		 * unless they belong to a role intended for the purpose.
+		 */
+		if (!role_has_privileges(GetUserId(), record->privileges))
+			ereport(ERROR,
+					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+					 errmsg("permission denied to set parameter \"%s\"", name)));
+
 		/*
 		 * If a value is specified, verify that it's sane.
 		 */
@@ -8934,6 +9306,7 @@ init_custom_variable(const char *name,
 					 const char *short_desc,
 					 const char *long_desc,
 					 GucContext context,
+					 int privileges,
 					 int flags,
 					 enum config_type type,
 					 size_t sz)
@@ -8979,6 +9352,7 @@ init_custom_variable(const char *name,
 	gen->group = CUSTOM_OPTIONS;
 	gen->short_desc = short_desc;
 	gen->long_desc = long_desc;
+	gen->privileges = privileges;
 	gen->flags = flags;
 	gen->vartype = type;
 
@@ -9177,6 +9551,7 @@ DefineCustomBoolVariable(const char *name,
 						 bool *valueAddr,
 						 bool bootValue,
 						 GucContext context,
+						 int privileges,
 						 int flags,
 						 GucBoolCheckHook check_hook,
 						 GucBoolAssignHook assign_hook,
@@ -9185,8 +9560,8 @@ DefineCustomBoolVariable(const char *name,
 	struct config_bool *var;
 
 	var = (struct config_bool *)
-		init_custom_variable(name, short_desc, long_desc, context, flags,
-							 PGC_BOOL, sizeof(struct config_bool));
+		init_custom_variable(name, short_desc, long_desc, context, privileges,
+							 flags, PGC_BOOL, sizeof(struct config_bool));
 	var->variable = valueAddr;
 	var->boot_val = bootValue;
 	var->reset_val = bootValue;
@@ -9205,6 +9580,7 @@ DefineCustomIntVariable(const char *name,
 						int minValue,
 						int maxValue,
 						GucContext context,
+						int privileges,
 						int flags,
 						GucIntCheckHook check_hook,
 						GucIntAssignHook assign_hook,
@@ -9213,8 +9589,8 @@ DefineCustomIntVariable(const char *name,
 	struct config_int *var;
 
 	var = (struct config_int *)
-		init_custom_variable(name, short_desc, long_desc, context, flags,
-							 PGC_INT, sizeof(struct config_int));
+		init_custom_variable(name, short_desc, long_desc, context, privileges,
+							 flags, PGC_INT, sizeof(struct config_int));
 	var->variable = valueAddr;
 	var->boot_val = bootValue;
 	var->reset_val = bootValue;
@@ -9235,6 +9611,7 @@ DefineCustomRealVariable(const char *name,
 						 double minValue,
 						 double maxValue,
 						 GucContext context,
+						 int privileges,
 						 int flags,
 						 GucRealCheckHook check_hook,
 						 GucRealAssignHook assign_hook,
@@ -9243,8 +9620,8 @@ DefineCustomRealVariable(const char *name,
 	struct config_real *var;
 
 	var = (struct config_real *)
-		init_custom_variable(name, short_desc, long_desc, context, flags,
-							 PGC_REAL, sizeof(struct config_real));
+		init_custom_variable(name, short_desc, long_desc, context, privileges,
+							 flags, PGC_REAL, sizeof(struct config_real));
 	var->variable = valueAddr;
 	var->boot_val = bootValue;
 	var->reset_val = bootValue;
@@ -9263,6 +9640,7 @@ DefineCustomStringVariable(const char *name,
 						   char **valueAddr,
 						   const char *bootValue,
 						   GucContext context,
+						   int privileges,
 						   int flags,
 						   GucStringCheckHook check_hook,
 						   GucStringAssignHook assign_hook,
@@ -9271,8 +9649,8 @@ DefineCustomStringVariable(const char *name,
 	struct config_string *var;
 
 	var = (struct config_string *)
-		init_custom_variable(name, short_desc, long_desc, context, flags,
-							 PGC_STRING, sizeof(struct config_string));
+		init_custom_variable(name, short_desc, long_desc, context, privileges,
+							 flags, PGC_STRING, sizeof(struct config_string));
 	var->variable = valueAddr;
 	var->boot_val = bootValue;
 	var->check_hook = check_hook;
@@ -9289,6 +9667,7 @@ DefineCustomEnumVariable(const char *name,
 						 int bootValue,
 						 const struct config_enum_entry *options,
 						 GucContext context,
+						 int privileges,
 						 int flags,
 						 GucEnumCheckHook check_hook,
 						 GucEnumAssignHook assign_hook,
@@ -9297,8 +9676,8 @@ DefineCustomEnumVariable(const char *name,
 	struct config_enum *var;
 
 	var = (struct config_enum *)
-		init_custom_variable(name, short_desc, long_desc, context, flags,
-							 PGC_ENUM, sizeof(struct config_enum));
+		init_custom_variable(name, short_desc, long_desc, context, privileges,
+							 flags, PGC_ENUM, sizeof(struct config_enum));
 	var->variable = valueAddr;
 	var->boot_val = bootValue;
 	var->reset_val = bootValue;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index aa18d304ac..7d2c3e051e 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -198,6 +198,10 @@ typedef enum
 
 #define GUC_QUALIFIER_SEPARATOR '.'
 
+/*
+ * privilege bits required to modify a GUC variable
+ */
+
 /*
  * bit values in "flags" of a GUC variable
  */
@@ -300,6 +304,7 @@ extern void DefineCustomBoolVariable(const char *name,
 									 bool *valueAddr,
 									 bool bootValue,
 									 GucContext context,
+									 int privileges,
 									 int flags,
 									 GucBoolCheckHook check_hook,
 									 GucBoolAssignHook assign_hook,
@@ -313,6 +318,7 @@ extern void DefineCustomIntVariable(const char *name,
 									int minValue,
 									int maxValue,
 									GucContext context,
+									int privileges,
 									int flags,
 									GucIntCheckHook check_hook,
 									GucIntAssignHook assign_hook,
@@ -326,6 +332,7 @@ extern void DefineCustomRealVariable(const char *name,
 									 double minValue,
 									 double maxValue,
 									 GucContext context,
+									 int privileges,
 									 int flags,
 									 GucRealCheckHook check_hook,
 									 GucRealAssignHook assign_hook,
@@ -337,6 +344,7 @@ extern void DefineCustomStringVariable(const char *name,
 									   char **valueAddr,
 									   const char *bootValue,
 									   GucContext context,
+									   int privileges,
 									   int flags,
 									   GucStringCheckHook check_hook,
 									   GucStringAssignHook assign_hook,
@@ -349,6 +357,7 @@ extern void DefineCustomEnumVariable(const char *name,
 									 int bootValue,
 									 const struct config_enum_entry *options,
 									 GucContext context,
+									 int privileges,
 									 int flags,
 									 GucEnumCheckHook check_hook,
 									 GucEnumAssignHook assign_hook,
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index 6b40f1eeb8..27288236ae 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -143,6 +143,7 @@ struct config_generic
 	enum config_group group;	/* to help organize variables by function */
 	const char *short_desc;		/* short desc. of this variable's purpose */
 	const char *long_desc;		/* long desc. of this variable's purpose */
+	int			privileges;		/* privileges bits, see guc.h */
 	int			flags;			/* flag bits, see guc.h */
 	/* variable fields, initialized at runtime: */
 	enum config_type vartype;	/* type of variable (set only at startup) */
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 1c77211ac4..f7a4aa9fe3 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -406,7 +406,7 @@ _PG_init(void)
 							 NULL,
 							 &plperl_use_strict,
 							 false,
-							 PGC_USERSET, 0,
+							 PGC_USERSET, GUC_SUPERUSER_ONLY, 0,
 							 NULL, NULL, NULL);
 
 	/*
@@ -420,7 +420,7 @@ _PG_init(void)
 							   NULL,
 							   &plperl_on_init,
 							   NULL,
-							   PGC_SIGHUP, 0,
+							   PGC_SIGHUP, GUC_SUPERUSER_ONLY, 0,
 							   NULL, NULL, NULL);
 
 	/*
@@ -442,7 +442,7 @@ _PG_init(void)
 							   NULL,
 							   &plperl_on_plperl_init,
 							   NULL,
-							   PGC_SUSET, 0,
+							   PGC_SUSET, GUC_SUPERUSER_ONLY, 0,
 							   NULL, NULL, NULL);
 
 	DefineCustomStringVariable("plperl.on_plperlu_init",
@@ -450,7 +450,7 @@ _PG_init(void)
 							   NULL,
 							   &plperl_on_plperlu_init,
 							   NULL,
-							   PGC_SUSET, 0,
+							   PGC_SUSET, GUC_SUPERUSER_ONLY, 0,
 							   NULL, NULL, NULL);
 
 	EmitWarningsOnPlaceholders("plperl");
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 00aace2f39..2fe38ffc24 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -158,7 +158,7 @@ _PG_init(void)
 							 &plpgsql_variable_conflict,
 							 PLPGSQL_RESOLVE_ERROR,
 							 variable_conflict_options,
-							 PGC_SUSET, 0,
+							 PGC_SUSET, GUC_SUPERUSER_ONLY, 0,
 							 NULL, NULL, NULL);
 
 	DefineCustomBoolVariable("plpgsql.print_strict_params",
@@ -166,7 +166,7 @@ _PG_init(void)
 							 NULL,
 							 &plpgsql_print_strict_params,
 							 false,
-							 PGC_USERSET, 0,
+							 PGC_USERSET, GUC_SUPERUSER_ONLY, 0,
 							 NULL, NULL, NULL);
 
 	DefineCustomBoolVariable("plpgsql.check_asserts",
@@ -174,7 +174,7 @@ _PG_init(void)
 							 NULL,
 							 &plpgsql_check_asserts,
 							 true,
-							 PGC_USERSET, 0,
+							 PGC_USERSET, GUC_SUPERUSER_ONLY, 0,
 							 NULL, NULL, NULL);
 
 	DefineCustomStringVariable("plpgsql.extra_warnings",
@@ -182,7 +182,7 @@ _PG_init(void)
 							   NULL,
 							   &plpgsql_extra_warnings_string,
 							   "none",
-							   PGC_USERSET, GUC_LIST_INPUT,
+							   PGC_USERSET, GUC_SUPERUSER_ONLY, GUC_LIST_INPUT,
 							   plpgsql_extra_checks_check_hook,
 							   plpgsql_extra_warnings_assign_hook,
 							   NULL);
@@ -192,7 +192,7 @@ _PG_init(void)
 							   NULL,
 							   &plpgsql_extra_errors_string,
 							   "none",
-							   PGC_USERSET, GUC_LIST_INPUT,
+							   PGC_USERSET, GUC_SUPERUSER_ONLY, GUC_LIST_INPUT,
 							   plpgsql_extra_checks_check_hook,
 							   plpgsql_extra_errors_assign_hook,
 							   NULL);
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index e11837559d..d72506aa26 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -464,14 +464,14 @@ _PG_init(void)
 							   NULL,
 							   &pltcl_start_proc,
 							   NULL,
-							   PGC_SUSET, 0,
+							   PGC_SUSET, GUC_SUPERUSER_ONLY, 0,
 							   NULL, NULL, NULL);
 	DefineCustomStringVariable("pltclu.start_proc",
 							   gettext_noop("PL/TclU function to call once when pltclu is first used."),
 							   NULL,
 							   &pltclu_start_proc,
 							   NULL,
-							   PGC_SUSET, 0,
+							   PGC_SUSET, GUC_SUPERUSER_ONLY, 0,
 							   NULL, NULL, NULL);
 
 	pltcl_pm_init_done = true;
diff --git a/src/test/modules/delay_execution/delay_execution.c b/src/test/modules/delay_execution/delay_execution.c
index b3d0841ba8..e8f983c2c4 100644
--- a/src/test/modules/delay_execution/delay_execution.c
+++ b/src/test/modules/delay_execution/delay_execution.c
@@ -86,6 +86,7 @@ _PG_init(void)
 							0,
 							0, INT_MAX,
 							PGC_USERSET,
+							GUC_SUPERUSER_ONLY,
 							0,
 							NULL,
 							NULL,
diff --git a/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c b/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
index 6b0a3db104..e6bc2b0a6a 100644
--- a/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
+++ b/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
@@ -44,6 +44,7 @@ _PG_init(void)
 							   &ssl_passphrase,
 							   NULL,
 							   PGC_SIGHUP,
+							   GUC_SUPERUSER_ONLY,
 							   0,	/* no flags required */
 							   NULL,
 							   NULL,
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 0b6246676b..6c15205b67 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -292,6 +292,7 @@ _PG_init(void)
 							1,
 							INT_MAX,
 							PGC_SIGHUP,
+							GUC_SUPERUSER_ONLY,
 							0,
 							NULL,
 							NULL,
@@ -308,6 +309,7 @@ _PG_init(void)
 							1,
 							100,
 							PGC_POSTMASTER,
+							GUC_SUPERUSER_ONLY,
 							0,
 							NULL,
 							NULL,
@@ -319,6 +321,7 @@ _PG_init(void)
 							   &worker_spi_database,
 							   "postgres",
 							   PGC_POSTMASTER,
+							   GUC_SUPERUSER_ONLY,
 							   0,
 							   NULL, NULL, NULL);
 
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
new file mode 100644
index 0000000000..6dc5ae3148
--- /dev/null
+++ b/src/test/regress/expected/guc_privs.out
@@ -0,0 +1,64 @@
+-- Test superuser
+-- Superuser DBA
+CREATE ROLE regress_admin SUPERUSER;
+-- Perform all operations as user 'regress_admin' --
+SET SESSION AUTHORIZATION regress_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- ok
+ALTER SYSTEM RESET ignore_system_indexes;  -- ok
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- ok
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- ok
+ALTER SYSTEM RESET autovacuum;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- ok
+RESET lc_messages;  -- ok
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- ok
+ALTER SYSTEM RESET lc_messages;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- ok
+ALTER SYSTEM RESET jit_debugging_support;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- ok
+ALTER SYSTEM RESET DateStyle;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing superuser
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_admin;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 7be89178f0..f451f69c3e 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -86,7 +86,7 @@ test: brin_bloom brin_multi
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort
+test: create_table_like alter_generic alter_operator misc async dbsize misc_functions sysviews tsrf tid tidscan tidrangescan collate.icu.utf8 incremental_sort guc_privs
 
 # rules cannot run concurrently with any test that creates
 # a view or rule in the public schema
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
new file mode 100644
index 0000000000..a8fafe4fa1
--- /dev/null
+++ b/src/test/regress/sql/guc_privs.sql
@@ -0,0 +1,48 @@
+-- Test superuser
+-- Superuser DBA
+CREATE ROLE regress_admin SUPERUSER;
+-- Perform all operations as user 'regress_admin' --
+SET SESSION AUTHORIZATION regress_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- ok
+ALTER SYSTEM RESET ignore_system_indexes;  -- ok
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- ok
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- ok
+ALTER SYSTEM RESET autovacuum;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- ok
+RESET lc_messages;  -- ok
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- ok
+ALTER SYSTEM RESET lc_messages;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- ok
+ALTER SYSTEM RESET jit_debugging_support;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- ok
+ALTER SYSTEM RESET DateStyle;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing superuser
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0002-Adding-role-pg_manage_host_resource_settings.patchapplication/octet-stream; name=v1-0002-Adding-role-pg_manage_host_resource_settings.patch; x-unix-mode=0644Download
From 61de61cbbc9e618a71d4dd2c35ca362c2f5872d3 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:47:53 -0700
Subject: [PATCH v1 02/12] Adding role pg_manage_host_resource_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls server resource usage (memory, disk, cpu, etc.)
---
 doc/src/sgml/user-manag.sgml            | 12 +++-
 src/backend/utils/misc/guc.c            | 50 +++++++-------
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 89 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 59 ++++++++++++++++
 6 files changed, 190 insertions(+), 26 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index afbf67c28c..25c97e4e5b 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -582,6 +582,10 @@ DROP ROLE doomed_role;
        <entry>Allow executing programs on the database server as the user the database runs as with
        COPY and other functions which allow executing a server-side program.</entry>
       </row>
+      <row>
+       <entry>pg_manage_host_resource_settings</entry>
+       <entry>Allow changing settings which control host resource usage.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -626,10 +630,16 @@ DROP ROLE doomed_role;
   great care should be taken when granting these roles to users.
   </para>
 
+  <para>
+  The <literal>pg_manage_host_resource_settings</literal> role is intended to
+  allow administrators to have a trusted, but non-superuser, role to configure
+  memory, cpu, disk and filehandle usage.
+  </para>
+
   <para>
   Care should be taken when granting these roles to ensure they are only used where
   needed and with the understanding that these roles grant access to privileged
-  information.
+  information or the ability to misconfigure the server.
   </para>
 
   <para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 04ce8b9d5e..be3fb60e9e 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2444,7 +2444,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_dynamic_shared_memory", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Amount of dynamic shared memory reserved at startup."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_MB
 		},
 		&min_dynamic_shared_memory,
@@ -2460,7 +2460,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"shared_buffers", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Sets the number of shared memory buffers used by the server."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_BLOCKS
 		},
 		&NBuffers,
@@ -2496,7 +2496,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"temp_buffers", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum number of temporary buffers used by each session."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN
 		},
 		&num_temp_buffers,
@@ -2568,7 +2568,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("This much memory can be used by each internal "
 						 "sort operation and hash table before switching to "
 						 "temporary disk files."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB | GUC_EXPLAIN
 		},
 		&work_mem,
@@ -2580,7 +2580,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"maintenance_work_mem", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum memory to be used for maintenance operations."),
 			gettext_noop("This includes operations such as VACUUM and CREATE INDEX."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&maintenance_work_mem,
@@ -2593,7 +2593,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum memory to be used for logical decoding."),
 			gettext_noop("This much memory can be used by each internal "
 						 "reorder buffer before spilling to disk."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&logical_decoding_work_mem,
@@ -2610,7 +2610,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_stack_depth", PGC_SUSET, RESOURCES_MEM,
 			gettext_noop("Sets the maximum stack depth, in kilobytes."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&max_stack_depth,
@@ -2622,7 +2622,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
 			gettext_noop("Limits the total size of all temporary files used by each process."),
 			gettext_noop("-1 means no limit."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&temp_file_limit,
@@ -2689,7 +2689,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_files_per_process", PGC_POSTMASTER, RESOURCES_KERNEL,
 			gettext_noop("Sets the maximum number of simultaneously open files for each server process."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_files_per_process,
 		1000, 64, INT_MAX,
@@ -2703,7 +2703,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_prepared_transactions", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Sets the maximum number of simultaneously prepared transactions."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_prepared_xacts,
 		0, 0, MAX_BACKENDS,
@@ -2867,7 +2867,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The shared lock table is sized on the assumption that "
 						 "at most max_locks_per_transaction * max_connections distinct "
 						 "objects will need to be locked at any one time."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_locks_per_xact,
 		64, 10, INT_MAX,
@@ -2880,7 +2880,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The shared predicate lock table is sized on the assumption that "
 						 "at most max_pred_locks_per_transaction * max_connections distinct "
 						 "objects will need to be locked at any one time."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_predicate_locks_per_xact,
 		64, 10, INT_MAX,
@@ -2892,7 +2892,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum number of predicate-locked pages and tuples per relation."),
 			gettext_noop("If more than this total of pages and tuples in the same relation are locked "
 						 "by a connection, those locks are replaced by a relation-level lock."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_predicate_locks_per_relation,
 		-2, INT_MIN, INT_MAX,
@@ -2904,7 +2904,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the maximum number of predicate-locked tuples per page."),
 			gettext_noop("If more than this number of tuples on the same page are locked "
 						 "by a connection, those locks are replaced by a page-level lock."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_predicate_locks_per_page,
 		2, 0, INT_MAX,
@@ -3290,7 +3290,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"backend_flush_after", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_BLOCKS
 		},
 		&backend_flush_after,
@@ -3304,7 +3304,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Maximum number of concurrent worker processes."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_worker_processes,
 		8, 0, MAX_BACKENDS,
@@ -3544,7 +3544,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_parallel_maintenance_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel processes per maintenance operation."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&max_parallel_maintenance_workers,
 		2, 0, 1024,
@@ -3555,7 +3555,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_parallel_workers_per_gather", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel processes per executor node."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&max_parallel_workers_per_gather,
@@ -3567,7 +3567,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_parallel_workers", PGC_USERSET, RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Sets the maximum number of parallel workers that can be active at one time."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&max_parallel_workers,
@@ -3579,7 +3579,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_work_mem", PGC_SIGHUP, RESOURCES_MEM,
 			gettext_noop("Sets the maximum memory to be used by each autovacuum worker process."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&autovacuum_work_mem,
@@ -3762,7 +3762,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"huge_page_size", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("The size of huge page that should be requested."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&huge_page_size,
@@ -3977,7 +3977,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"hash_mem_multiplier", PGC_USERSET, RESOURCES_MEM,
 			gettext_noop("Multiple of work_mem to use for hash tables."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&hash_mem_multiplier,
@@ -5208,7 +5208,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Selects the dynamic shared memory implementation used."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&dynamic_shared_memory_type,
 		DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options,
@@ -5219,7 +5219,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Selects the shared memory implementation used for the main shared memory region."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&shared_memory_type,
 		DEFAULT_SHARED_MEMORY_TYPE, shared_memory_options,
@@ -5264,7 +5264,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"huge_pages", PGC_POSTMASTER, RESOURCES_MEM,
 			gettext_noop("Use of huge pages on Linux or Windows."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_HOST_RESOURCE_SETTINGS
 		},
 		&huge_pages,
 		HUGE_PAGES_TRY, huge_pages_options,
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 3da68016b6..daf62c2061 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -79,5 +79,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9279', oid_symbol => 'ROLE_PG_MANAGE_HOST_RESOURCE_SETTINGS',
+  rolname => 'pg_manage_host_resource_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 7d2c3e051e..7b0aac2216 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -201,6 +201,7 @@ typedef enum
 /*
  * privilege bits required to modify a GUC variable
  */
+#define GUC_MANAGE_HOST_RESOURCE_SETTINGS	0x0001
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 6dc5ae3148..34a0dcfc0b 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -62,3 +62,92 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_admin;
+-- Test role pg_manage_host_resource_settings
+-- Non-superuser with privileges to configure host resource usage
+CREATE ROLE regress_host_resource_admin NOSUPERUSER;
+GRANT pg_manage_host_resource_settings TO regress_host_resource_admin;
+-- Perform all operations as user 'regress_host_resource_admin' --
+SET SESSION AUTHORIZATION regress_host_resource_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET max_locks_per_transaction = 50;  -- ok
+ALTER SYSTEM RESET max_locks_per_transaction;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET max_pred_locks_per_page = 50;  -- ok
+ALTER SYSTEM RESET max_pred_locks_per_page;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET temp_file_limit = 50;  -- ok
+RESET temp_file_limit;  -- ok
+ALTER SYSTEM SET temp_file_limit = 50;  -- ok
+ALTER SYSTEM RESET temp_file_limit;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_host_resource_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM SET backend_flush_after = 128;  -- ok
+ALTER SYSTEM RESET backend_flush_after;  -- ok
+-- Finished testing role pg_manage_host_resource_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_host_resource_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index a8fafe4fa1..a8a78e61de 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -46,3 +46,62 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_admin;
+-- Test role pg_manage_host_resource_settings
+-- Non-superuser with privileges to configure host resource usage
+CREATE ROLE regress_host_resource_admin NOSUPERUSER;
+GRANT pg_manage_host_resource_settings TO regress_host_resource_admin;
+-- Perform all operations as user 'regress_host_resource_admin' --
+SET SESSION AUTHORIZATION regress_host_resource_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_host_resource_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET max_locks_per_transaction = 50;  -- ok
+ALTER SYSTEM RESET max_locks_per_transaction;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM SET max_pred_locks_per_page = 50;  -- ok
+ALTER SYSTEM RESET max_pred_locks_per_page;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_host_resource_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_host_resource_admin has insufficient privileges
+SET temp_file_limit = 50;  -- ok
+RESET temp_file_limit;  -- ok
+ALTER SYSTEM SET temp_file_limit = 50;  -- ok
+ALTER SYSTEM RESET temp_file_limit;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_host_resource_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_host_resource_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ALTER SYSTEM SET backend_flush_after = 128;  -- ok
+ALTER SYSTEM RESET backend_flush_after;  -- ok
+-- Finished testing role pg_manage_host_resource_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_host_resource_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0003-Adding-role-pg_manage_vacuum_settings.patchapplication/octet-stream; name=v1-0003-Adding-role-pg_manage_vacuum_settings.patch; x-unix-mode=0644Download
From 2835bd62e2779e7b12bd5dbfe4ad09a8edbf96d9 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:48:38 -0700
Subject: [PATCH v1 03/12] Adding role pg_manage_vacuum_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls vacuum behavior or resource usage.
---
 doc/src/sgml/user-manag.sgml            | 11 +++-
 src/backend/utils/misc/guc.c            | 26 ++++----
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 81 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 51 ++++++++++++++++
 6 files changed, 161 insertions(+), 14 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 25c97e4e5b..1d91d419e3 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -586,6 +586,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_host_resource_settings</entry>
        <entry>Allow changing settings which control host resource usage.</entry>
       </row>
+      <row>
+       <entry>pg_manage_vacuum_settings</entry>
+       <entry>Allow changing settings which control vacuum behavior.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -631,9 +635,10 @@ DROP ROLE doomed_role;
   </para>
 
   <para>
-  The <literal>pg_manage_host_resource_settings</literal> role is intended to
-  allow administrators to have a trusted, but non-superuser, role to configure
-  memory, cpu, disk and filehandle usage.
+  The <literal>pg_manage_host_resource_settings</literal> and
+  <literal>pg_manage_vacuum_settings</literal> roles are intended to allow
+  administrators to have trusted, but non-superuser, roles to configure the
+  server.
   </para>
 
   <para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index be3fb60e9e..80265559b0 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2634,7 +2634,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_cost_page_hit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page found in the buffer cache."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&VacuumCostPageHit,
 		1, 0, 10000,
@@ -2645,7 +2645,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_cost_page_miss", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page not found in the buffer cache."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&VacuumCostPageMiss,
 		2, 0, 10000,
@@ -2656,7 +2656,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_cost_page_dirty", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost for a page dirtied by vacuum."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&VacuumCostPageDirty,
 		20, 0, 10000,
@@ -2667,7 +2667,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_cost_limit", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost amount available before napping."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&VacuumCostLimit,
 		200, 1, 10000,
@@ -2787,7 +2787,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Minimum age at which VACUUM should freeze a table row."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_freeze_min_age,
 		50000000, 0, 1000000000,
@@ -2798,7 +2798,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Age at which VACUUM should scan whole table to freeze tuples."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_freeze_table_age,
 		150000000, 0, 2000000000,
@@ -2809,7 +2809,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_multixact_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Minimum age at which VACUUM should freeze a MultiXactId in a table row."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_multixact_freeze_min_age,
 		5000000, 0, 1000000000,
@@ -2820,7 +2820,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_multixact_freeze_table_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Multixact age at which VACUUM should scan whole table to freeze tuples."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_multixact_freeze_table_age,
 		150000000, 0, 2000000000,
@@ -2841,7 +2841,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Age at which VACUUM should trigger failsafe to avoid a wraparound outage."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_failsafe_age,
 		1600000000, 0, 2100000000,
@@ -2851,7 +2851,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_multixact_failsafe_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
 			gettext_noop("Multixact age at which VACUUM should trigger failsafe to avoid a wraparound outage."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_VACUUM_SETTINGS
 		},
 		&vacuum_multixact_failsafe_age,
 		1600000000, 0, 2100000000,
@@ -4012,7 +4012,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"vacuum_cost_delay", PGC_USERSET, RESOURCES_VACUUM_DELAY,
 			gettext_noop("Vacuum cost delay in milliseconds."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_VACUUM_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&VacuumCostDelay,
@@ -7631,6 +7631,10 @@ role_has_privileges(Oid roleid, int privileges)
 	if ((privileges & GUC_SUPERUSER_ONLY) && !superuser_arg(roleid))
 		return false;
 
+	if ((privileges & GUC_MANAGE_VACUUM_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_VACUUM_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index daf62c2061..cef9b7f015 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -84,5 +84,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9280', oid_symbol => 'ROLE_PG_MANAGE_VACUUM_SETTINGS',
+  rolname => 'pg_manage_vacuum_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 7b0aac2216..8555e3f7b8 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -202,6 +202,7 @@ typedef enum
  * privilege bits required to modify a GUC variable
  */
 #define GUC_MANAGE_HOST_RESOURCE_SETTINGS	0x0001
+#define GUC_MANAGE_VACUUM_SETTINGS			0x0002
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 34a0dcfc0b..6887a6664a 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -151,3 +151,84 @@ ALTER SYSTEM RESET backend_flush_after;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_host_resource_admin;
+-- Test role pg_manage_vacuum_settings
+-- Non-superuser with privileges to configure vacuum processes
+CREATE ROLE regress_vacuum_admin NOSUPERUSER;
+GRANT pg_manage_vacuum_settings TO regress_vacuum_admin;
+-- Perform all operations as user 'regress_vacuum_admin' --
+SET SESSION AUTHORIZATION regress_vacuum_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_vacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET vacuum_failsafe_age = 50;  -- ok
+ALTER SYSTEM RESET vacuum_failsafe_age;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_vacuum_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_vacuum_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index a8a78e61de..6e7494cb3e 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -105,3 +105,54 @@ ALTER SYSTEM RESET backend_flush_after;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_host_resource_admin;
+-- Test role pg_manage_vacuum_settings
+-- Non-superuser with privileges to configure vacuum processes
+CREATE ROLE regress_vacuum_admin NOSUPERUSER;
+GRANT pg_manage_vacuum_settings TO regress_vacuum_admin;
+-- Perform all operations as user 'regress_vacuum_admin' --
+SET SESSION AUTHORIZATION regress_vacuum_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_vacuum_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_vacuum_admin has insufficient privileges
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_vacuum_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_vacuum_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_vacuum_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_vacuum_admin has insufficient privileges
+ALTER SYSTEM SET vacuum_failsafe_age = 50;  -- ok
+ALTER SYSTEM RESET vacuum_failsafe_age;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_vacuum_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_vacuum_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0004-Adding-role-pg_manage_autovacuum_settings.patchapplication/octet-stream; name=v1-0004-Adding-role-pg_manage_autovacuum_settings.patch; x-unix-mode=0644Download
From e849c44f71946b8724bcbcc38e78dbeab6a361ba Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:49:08 -0700
Subject: [PATCH v1 04/12] Adding role pg_manage_autovacuum_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls autovacuum behavior or resource usage.
---
 doc/src/sgml/user-manag.sgml            |  9 ++-
 src/backend/utils/misc/guc.c            | 30 +++++----
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 83 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 53 ++++++++++++++++
 6 files changed, 166 insertions(+), 15 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 1d91d419e3..42d386b18f 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -590,6 +590,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_vacuum_settings</entry>
        <entry>Allow changing settings which control vacuum behavior.</entry>
       </row>
+      <row>
+       <entry>pg_manage_autovacuum_settings</entry>
+       <entry>Allow changing settings which control autovacuum behavior.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -635,8 +639,9 @@ DROP ROLE doomed_role;
   </para>
 
   <para>
-  The <literal>pg_manage_host_resource_settings</literal> and
-  <literal>pg_manage_vacuum_settings</literal> roles are intended to allow
+  The <literal>pg_manage_host_resource_settings</literal>,
+  <literal>pg_manage_vacuum_settings</literal> and
+  <literal>pg_manage_autovacuum_settings</literal> roles are intended to allow
   administrators to have trusted, but non-superuser, roles to configure the
   server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 80265559b0..94a1843825 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1631,7 +1631,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"autovacuum", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Starts the autovacuum subprocess."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_start_daemon,
 		true,
@@ -2678,7 +2678,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_vacuum_cost_limit", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Vacuum cost amount available before napping, for autovacuum."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_vac_cost_limit,
 		-1, -1, 10000,
@@ -3464,7 +3464,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_naptime", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Time to sleep between autovacuum runs."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_AUTOVACUUM_SETTINGS,
 			GUC_UNIT_S
 		},
 		&autovacuum_naptime,
@@ -3475,7 +3475,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_vacuum_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple updates or deletes prior to vacuum."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_vac_thresh,
 		50, 0, INT_MAX,
@@ -3485,7 +3485,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_vacuum_insert_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple inserts prior to vacuum, or -1 to disable insert vacuums."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_vac_ins_thresh,
 		1000, -1, INT_MAX,
@@ -3495,7 +3495,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_analyze_threshold", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Minimum number of tuple inserts, updates, or deletes prior to analyze."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_anl_thresh,
 		50, 0, INT_MAX,
@@ -3506,7 +3506,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Age at which to autovacuum a table to prevent transaction ID wraparound."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_freeze_max_age,
 
@@ -3522,7 +3522,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_multixact_freeze_max_age", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Multixact age at which to autovacuum a table to prevent multixact wraparound."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_multixact_freeze_max_age,
 		400000000, 10000, 2000000000,
@@ -3533,7 +3533,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"autovacuum_max_workers", PGC_POSTMASTER, AUTOVACUUM,
 			gettext_noop("Sets the maximum number of simultaneously running autovacuum worker processes."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_max_workers,
 		3, 1, MAX_BACKENDS,
@@ -4024,7 +4024,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"autovacuum_vacuum_cost_delay", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Vacuum cost delay in milliseconds, for autovacuum."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_AUTOVACUUM_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&autovacuum_vac_cost_delay,
@@ -4036,7 +4036,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_vac_scale,
 		0.2, 0.0, 100.0,
@@ -4047,7 +4047,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"autovacuum_vacuum_insert_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple inserts prior to vacuum as a fraction of reltuples."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_vac_ins_scale,
 		0.2, 0.0, 100.0,
@@ -4058,7 +4058,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
 			gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_AUTOVACUUM_SETTINGS
 		},
 		&autovacuum_anl_scale,
 		0.1, 0.0, 100.0,
@@ -7635,6 +7635,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_VACUUM_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_AUTOVACUUM_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_AUTOVACUUM_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index cef9b7f015..588b0954d8 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -89,5 +89,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9281', oid_symbol => 'ROLE_PG_MANAGE_AUTOVACUUM_SETTINGS',
+  rolname => 'pg_manage_autovacuum_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 8555e3f7b8..0a24261156 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -203,6 +203,7 @@ typedef enum
  */
 #define GUC_MANAGE_HOST_RESOURCE_SETTINGS	0x0001
 #define GUC_MANAGE_VACUUM_SETTINGS			0x0002
+#define GUC_MANAGE_AUTOVACUUM_SETTINGS		0x0004
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 6887a6664a..5841558ada 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -232,3 +232,86 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_vacuum_admin;
+-- Test role pg_manage_autovacuum_settings
+-- Non-superuser with privileges to configure autovacuum processes
+CREATE ROLE regress_autovacuum_admin NOSUPERUSER;
+GRANT pg_manage_autovacuum_settings TO regress_autovacuum_admin;
+-- Perform all operations as user 'regress_autovacuum_admin' --
+SET SESSION AUTHORIZATION regress_autovacuum_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- ok
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- ok
+ALTER SYSTEM SET jit_provider = 'llvmjit';  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_provider"
+ALTER SYSTEM RESET jit_provider;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_provider"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- ok
+ALTER SYSTEM RESET autovacuum;  -- ok
+ALTER SYSTEM SET authentication_timeout = 50;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "authentication_timeout"
+ALTER SYSTEM RESET authentication_timeout;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "authentication_timeout"
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_autovacuum_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_autovacuum_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_autovacuum_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 6e7494cb3e..9579299097 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -156,3 +156,56 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_vacuum_admin;
+-- Test role pg_manage_autovacuum_settings
+-- Non-superuser with privileges to configure autovacuum processes
+CREATE ROLE regress_autovacuum_admin NOSUPERUSER;
+GRANT pg_manage_autovacuum_settings TO regress_autovacuum_admin;
+-- Perform all operations as user 'regress_autovacuum_admin' --
+SET SESSION AUTHORIZATION regress_autovacuum_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_autovacuum_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- ok
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- ok
+ALTER SYSTEM SET jit_provider = 'llvmjit';  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET jit_provider;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- ok
+ALTER SYSTEM RESET autovacuum;  -- ok
+ALTER SYSTEM SET authentication_timeout = 50;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET authentication_timeout;  -- fail, regress_autovacuum_admin has insufficient privileges
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_autovacuum_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_autovacuum_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_autovacuum_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_autovacuum_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_autovacuum_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_autovacuum_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0005-Adding-role-pg_manage_logging_settings.patchapplication/octet-stream; name=v1-0005-Adding-role-pg_manage_logging_settings.patch; x-unix-mode=0644Download
From 2bd3f11a27f9d0e7ca875ec0f7e1642df44058f7 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:49:40 -0700
Subject: [PATCH v1 05/12] Adding role pg_manage_logging_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls what and when to log.  Note that variables controlling
where to log may not be set by this role unless the user also has
membership in role pg_write_server_files.
---
 doc/src/sgml/user-manag.sgml            |   9 +-
 src/backend/utils/misc/guc.c            | 120 ++++++++--------
 src/include/catalog/pg_authid.dat       |   5 +
 src/include/utils/guc.h                 |   2 +
 src/test/regress/expected/guc_privs.out | 181 ++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 121 ++++++++++++++++
 6 files changed, 380 insertions(+), 58 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 42d386b18f..75e2dda5d2 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -594,6 +594,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_autovacuum_settings</entry>
        <entry>Allow changing settings which control autovacuum behavior.</entry>
       </row>
+      <row>
+       <entry>pg_manage_logging_settings</entry>
+       <entry>Allow changing settings which control logging behavior.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -640,8 +644,9 @@ DROP ROLE doomed_role;
 
   <para>
   The <literal>pg_manage_host_resource_settings</literal>,
-  <literal>pg_manage_vacuum_settings</literal> and
-  <literal>pg_manage_autovacuum_settings</literal> roles are intended to allow
+  <literal>pg_manage_vacuum_settings</literal>,
+  <literal>pg_manage_autovacuum_settings</literal> and
+  <literal>pg_manage_logging_settings</literal> roles are intended to allow
   administrators to have trusted, but non-superuser, roles to configure the
   server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 94a1843825..409d68943a 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1381,7 +1381,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Logs each checkpoint."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_checkpoints,
 		false,
@@ -1391,7 +1391,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_connections", PGC_SU_BACKEND, LOGGING_WHAT,
 			gettext_noop("Logs each successful connection."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Log_connections,
 		false,
@@ -1401,7 +1401,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_disconnections", PGC_SU_BACKEND, LOGGING_WHAT,
 			gettext_noop("Logs end of a session, including duration."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Log_disconnections,
 		false,
@@ -1411,7 +1411,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_replication_commands", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs each replication command."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_replication_commands,
 		false,
@@ -1469,7 +1469,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_duration", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs the duration of each completed SQL statement."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_duration,
 		false,
@@ -1479,7 +1479,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_print_parse", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's parse tree."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Debug_print_parse,
 		false,
@@ -1489,7 +1489,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_print_rewritten", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's rewritten parse tree."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Debug_print_rewritten,
 		false,
@@ -1499,7 +1499,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_print_plan", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Logs each query's execution plan."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Debug_print_plan,
 		false,
@@ -1509,7 +1509,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"debug_pretty_print", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Indents parse and plan tree displays."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Debug_pretty_print,
 		true,
@@ -1519,7 +1519,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_parser_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes parser performance statistics to the server log."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_parser_stats,
 		false,
@@ -1529,7 +1529,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_planner_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes planner performance statistics to the server log."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_planner_stats,
 		false,
@@ -1539,7 +1539,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_executor_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes executor performance statistics to the server log."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_executor_stats,
 		false,
@@ -1549,7 +1549,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_statement_stats", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Writes cumulative performance statistics to the server log."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_statement_stats,
 		false,
@@ -1642,7 +1642,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_notify", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Generates debugging output for LISTEN and NOTIFY."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_notify,
@@ -1655,7 +1655,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_locks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about lock usage."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_locks,
@@ -1666,7 +1666,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_userlocks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about user lock usage."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_userlocks,
@@ -1677,7 +1677,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_lwlocks", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emits information about lightweight lock usage."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lwlocks,
@@ -1701,7 +1701,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_lock_waits", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Logs long lock waits."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_lock_waits,
 		false,
@@ -1711,7 +1711,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_recovery_conflict_waits", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Logs standby recovery conflict waits."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_recovery_conflict_waits,
 		false,
@@ -1724,7 +1724,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "of the connecting host. If you want them to show the host name you "
 						 "can turn this on, but depending on your host name resolution "
 						 "setup it might impose a non-negligible performance penalty."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_hostname,
 		false,
@@ -1850,7 +1850,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"logging_collector", PGC_POSTMASTER, LOGGING_WHERE,
 			gettext_noop("Start a subprocess to capture stderr output and/or csvlogs into log files."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&Logging_collector,
 		false,
@@ -1860,7 +1860,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"log_truncate_on_rotation", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Truncate existing log files of same name during log rotation."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&Log_truncate_on_rotation,
 		false,
@@ -1872,7 +1872,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_sort", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emit information about resource usage in sorting."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&trace_sort,
@@ -1887,7 +1887,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"trace_syncscan", PGC_USERSET, DEVELOPER_OPTIONS,
 			gettext_noop("Generate debugging output for synchronized scanning."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&trace_syncscan,
@@ -1953,7 +1953,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"escape_string_warning", PGC_USERSET, COMPAT_OPTIONS_PREVIOUS,
 			gettext_noop("Warn about backslash escapes in ordinary string literals."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&escape_string_warning,
 		true,
@@ -2092,7 +2092,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"syslog_sequence_numbers", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Add sequence number to syslog messages to avoid duplicate suppression."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&syslog_sequence_numbers,
 		true,
@@ -2103,7 +2103,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"syslog_split_messages", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Split messages sent to syslog by lines and to fit into 1024 bytes."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&syslog_split_messages,
 		true,
@@ -2539,7 +2539,7 @@ static struct config_int ConfigureNamesInt[] =
 						 "accepted by the chmod and umask system calls. "
 						 "(To use the customary octal format the number must "
 						 "start with a 0 (zero).)"),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&Log_file_mode,
 		0600, 0000, 0777,
@@ -2715,7 +2715,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the minimum OID of tables for tracking locks."),
 			gettext_noop("Is used to avoid output on system tables."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lock_oidmin,
@@ -2726,7 +2726,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"trace_lock_table", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Sets the OID of the table with unconditionally lock tracing."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&Trace_lock_table,
@@ -2993,7 +2993,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Write a message to the server log if checkpoints "
 						 "caused by the filling of checkpoint segment files happens more "
 						 "frequently than this number of seconds. Zero turns off the warning."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_S
 		},
 		&CheckPointWarning,
@@ -3155,7 +3155,7 @@ static struct config_int ConfigureNamesInt[] =
 						 "a sample of statements will be logged."
 						 " Sampling is determined by log_statement_sample_rate."),
 			gettext_noop("Zero logs a sample of all queries. -1 turns this feature off."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&log_min_duration_sample,
@@ -3168,7 +3168,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the minimum execution time above which "
 						 "all statements will be logged."),
 			gettext_noop("Zero prints all queries. -1 turns this feature off."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&log_min_duration_statement,
@@ -3181,7 +3181,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the minimum execution time above which "
 						 "autovacuum actions will be logged."),
 			gettext_noop("Zero prints all actions. -1 turns autovacuum logging off."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&Log_autovacuum_min_duration,
@@ -3193,7 +3193,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_parameter_max_length", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("When logging statements, limit logged parameter values to first N bytes."),
 			gettext_noop("-1 to print values in full."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_BYTE
 		},
 		&log_parameter_max_length,
@@ -3205,7 +3205,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_parameter_max_length_on_error", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("When reporting an error, limit logged parameter values to first N bytes."),
 			gettext_noop("-1 to print values in full."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_BYTE
 		},
 		&log_parameter_max_length_on_error,
@@ -3341,7 +3341,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Automatic log file rotation will occur after N minutes."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES,
 			GUC_UNIT_MIN
 		},
 		&Log_RotationAge,
@@ -3353,7 +3353,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Automatic log file rotation will occur after N kilobytes."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES,
 			GUC_UNIT_KB
 		},
 		&Log_RotationSize,
@@ -3714,7 +3714,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"log_temp_files", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Log the use of temporary files larger than this number of kilobytes."),
 			gettext_noop("Zero logs all files. The default is -1 (turning this feature off)."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&log_temp_files,
@@ -4080,7 +4080,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"log_statement_sample_rate", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Fraction of statements exceeding log_min_duration_sample to be logged."),
 			gettext_noop("Use a value between 0.0 (never log) and 1.0 (always log)."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_statement_sample_rate,
 		1.0, 0.0, 1.0,
@@ -4092,7 +4092,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the fraction of transactions from which to log all statements."),
 			gettext_noop("Use a value between 0.0 (never log) and 1.0 (log all "
 						 "statements for all transactions)."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_xact_sample_rate,
 		0.0, 0.0, 1.0,
@@ -4263,7 +4263,7 @@ static struct config_string ConfigureNamesString[] =
 		{"log_line_prefix", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Controls information prefixed to each log line."),
 			gettext_noop("If blank, no prefix is used."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Log_line_prefix,
 		"%m [%p] ",
@@ -4274,7 +4274,7 @@ static struct config_string ConfigureNamesString[] =
 		{"log_timezone", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Sets the time zone to use in log messages."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_timezone_string,
 		"GMT",
@@ -4542,7 +4542,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Valid values are combinations of \"stderr\", "
 						 "\"syslog\", \"csvlog\", and \"eventlog\", "
 						 "depending on the platform."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES,
 			GUC_LIST_INPUT
 		},
 		&Log_destination_string,
@@ -4554,7 +4554,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Sets the destination directory for log files."),
 			gettext_noop("Can be specified as relative to the data directory "
 						 "or as absolute path."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&Log_directory,
 		"log",
@@ -4588,7 +4588,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Sets the application name used to identify "
 						 "PostgreSQL messages in the event log."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&event_source,
 		DEFAULT_EVENT_SOURCE,
@@ -4879,7 +4879,7 @@ static struct config_string ConfigureNamesString[] =
 		{"application_name", PGC_USERSET, LOGGING_WHAT,
 			gettext_noop("Sets the application name to be reported in statistics and logs."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_IS_NAME | GUC_REPORT | GUC_NOT_IN_SAMPLE
 		},
 		&application_name,
@@ -4926,7 +4926,7 @@ static struct config_string ConfigureNamesString[] =
 		{"backtrace_functions", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Log backtrace for errors in these functions."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&backtrace_functions,
@@ -5052,7 +5052,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"log_error_verbosity", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Sets the verbosity of logged messages."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&Log_error_verbosity,
 		PGERROR_DEFAULT, log_error_verbosity_options,
@@ -5064,7 +5064,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Sets the message levels that are logged."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
 						 " the level, the fewer messages are sent."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_min_messages,
 		WARNING, server_message_level_options,
@@ -5076,7 +5076,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Causes all statements generating error at or above this level to be logged."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
 						 " the level, the fewer messages are sent."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_min_error_statement,
 		ERROR, server_message_level_options,
@@ -5087,7 +5087,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"log_statement", PGC_SUSET, LOGGING_WHAT,
 			gettext_noop("Sets the type of statements logged."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&log_statement,
 		LOGSTMT_NONE, log_statement_options,
@@ -5098,7 +5098,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"syslog_facility", PGC_SIGHUP, LOGGING_WHERE,
 			gettext_noop("Sets the syslog \"facility\" to be used when syslog enabled."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&syslog_facility,
 #ifdef HAVE_SYSLOG
@@ -5159,7 +5159,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Enables logging of recovery-related debugging information."),
 			gettext_noop("Each level includes all the levels that follow it. The later"
 						 " the level, the fewer messages are sent."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS
 		},
 		&trace_recovery_messages,
 
@@ -5324,7 +5324,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES,
 			GUC_SUPERUSER_ONLY
 		},
 		&ssl_max_protocol_version,
@@ -5337,7 +5337,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"recovery_init_sync_method", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Sets the method for synchronizing the data directory before crash recovery."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&recovery_init_sync_method,
 		RECOVERY_INIT_SYNC_METHOD_FSYNC, recovery_init_sync_method_options,
@@ -7639,6 +7639,14 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_AUTOVACUUM_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_LOGGING_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_LOGGING_SETTINGS))
+		return false;
+
+	if ((privileges & GUC_WRITE_SERVER_FILES) &&
+		! has_privs_of_role(roleid, ROLE_PG_WRITE_SERVER_FILES))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 588b0954d8..41d119f7b2 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -94,5 +94,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9282', oid_symbol => 'ROLE_PG_MANAGE_LOGGING_SETTINGS',
+  rolname => 'pg_manage_logging_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 0a24261156..94d0b3c19d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -204,6 +204,8 @@ typedef enum
 #define GUC_MANAGE_HOST_RESOURCE_SETTINGS	0x0001
 #define GUC_MANAGE_VACUUM_SETTINGS			0x0002
 #define GUC_MANAGE_AUTOVACUUM_SETTINGS		0x0004
+#define GUC_MANAGE_LOGGING_SETTINGS			0x0008
+#define GUC_WRITE_SERVER_FILES				0x0010
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 5841558ada..443c0237bd 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -315,3 +315,184 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_autovacuum_admin;
+-- Test role pg_manage_logging_settings
+-- Non-superuser with privileges to configure what and when to log
+CREATE ROLE regress_log_whatwhen_admin NOSUPERUSER;
+GRANT pg_manage_logging_settings TO regress_log_whatwhen_admin;
+-- Perform all operations as user 'regress_log_whatwhen_admin' --
+SET SESSION AUTHORIZATION regress_log_whatwhen_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET trace_recovery_messages = 'log';  -- ok
+ALTER SYSTEM RESET trace_recovery_messages;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+RESET backtrace_functions;  -- ok
+ALTER SYSTEM SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+ALTER SYSTEM RESET backtrace_functions;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM SET log_connections = OFF;  -- ok
+ALTER SYSTEM RESET log_connections;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET escape_string_warning = OFF;  -- ok
+ALTER SYSTEM RESET escape_string_warning;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_logging_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_log_whatwhen_admin;
+-- Test combination of roles pg_manage_logging_settings and pg_write_server_files
+-- Non-superuser with privileges to configure what, when and where to log
+CREATE ROLE regress_log_full_admin NOSUPERUSER;
+GRANT pg_manage_logging_settings TO regress_log_full_admin;
+GRANT pg_write_server_files TO regress_log_full_admin;
+-- Perform all operations as user 'regress_log_full_admin' --
+SET SESSION AUTHORIZATION regress_log_full_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET event_source = 'PostgreSQL';  -- ok
+ALTER SYSTEM RESET event_source;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET trace_recovery_messages = 'log';  -- ok
+ALTER SYSTEM RESET trace_recovery_messages;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+RESET backtrace_functions;  -- ok
+ALTER SYSTEM SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+ALTER SYSTEM RESET backtrace_functions;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM SET log_connections = OFF;  -- ok
+ALTER SYSTEM RESET log_connections;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_log_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET escape_string_warning = OFF;  -- ok
+ALTER SYSTEM RESET escape_string_warning;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing combination of roles pg_manage_logging_settings and pg_write_server_files
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_log_full_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 9579299097..767c5ecc46 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -209,3 +209,124 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_autovacuum_admin;
+-- Test role pg_manage_logging_settings
+-- Non-superuser with privileges to configure what and when to log
+CREATE ROLE regress_log_whatwhen_admin NOSUPERUSER;
+GRANT pg_manage_logging_settings TO regress_log_whatwhen_admin;
+-- Perform all operations as user 'regress_log_whatwhen_admin' --
+SET SESSION AUTHORIZATION regress_log_whatwhen_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM SET trace_recovery_messages = 'log';  -- ok
+ALTER SYSTEM RESET trace_recovery_messages;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+RESET backtrace_functions;  -- ok
+ALTER SYSTEM SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+ALTER SYSTEM RESET backtrace_functions;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM SET log_connections = OFF;  -- ok
+ALTER SYSTEM RESET log_connections;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_log_whatwhen_admin has insufficient privileges
+ALTER SYSTEM SET escape_string_warning = OFF;  -- ok
+ALTER SYSTEM RESET escape_string_warning;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_logging_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_log_whatwhen_admin;
+-- Test combination of roles pg_manage_logging_settings and pg_write_server_files
+-- Non-superuser with privileges to configure what, when and where to log
+CREATE ROLE regress_log_full_admin NOSUPERUSER;
+GRANT pg_manage_logging_settings TO regress_log_full_admin;
+GRANT pg_write_server_files TO regress_log_full_admin;
+-- Perform all operations as user 'regress_log_full_admin' --
+SET SESSION AUTHORIZATION regress_log_full_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_log_full_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET event_source = 'PostgreSQL';  -- ok
+ALTER SYSTEM RESET event_source;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM SET trace_recovery_messages = 'log';  -- ok
+ALTER SYSTEM RESET trace_recovery_messages;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_full_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_log_full_admin has insufficient privileges
+SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+RESET backtrace_functions;  -- ok
+ALTER SYSTEM SET backtrace_functions = 'partition_list_bsearch,partition_range_datum_bsearch,partition_hash_bsearch';  -- ok
+ALTER SYSTEM RESET backtrace_functions;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM SET log_connections = OFF;  -- ok
+ALTER SYSTEM RESET log_connections;  -- ok
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_log_full_admin has insufficient privileges
+ALTER SYSTEM SET escape_string_warning = OFF;  -- ok
+ALTER SYSTEM RESET escape_string_warning;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing combination of roles pg_manage_logging_settings and pg_write_server_files
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_log_full_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0006-Adding-role-pg_manage_replication_settings.patchapplication/octet-stream; name=v1-0006-Adding-role-pg_manage_replication_settings.patch; x-unix-mode=0644Download
From 6ab463391006f871fcd111d744e09f1030b10e2c Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:50:10 -0700
Subject: [PATCH v1 06/12] Adding role pg_manage_replication_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls replication behavior or resource usage.
---
 doc/src/sgml/user-manag.sgml            |  9 ++-
 src/backend/utils/misc/guc.c            | 48 +++++++-------
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 85 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 55 ++++++++++++++++
 6 files changed, 179 insertions(+), 24 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 75e2dda5d2..ed586cc260 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -598,6 +598,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_logging_settings</entry>
        <entry>Allow changing settings which control logging behavior.</entry>
       </row>
+      <row>
+       <entry>pg_manage_replication_settings</entry>
+       <entry>Allow changing settings which control replication behavior.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -645,8 +649,9 @@ DROP ROLE doomed_role;
   <para>
   The <literal>pg_manage_host_resource_settings</literal>,
   <literal>pg_manage_vacuum_settings</literal>,
-  <literal>pg_manage_autovacuum_settings</literal> and
-  <literal>pg_manage_logging_settings</literal> roles are intended to allow
+  <literal>pg_manage_autovacuum_settings</literal>,
+  <literal>pg_manage_logging_settings</literal> and
+  <literal>pg_manage_replication_settings</literal> roles are intended to allow
   administrators to have trusted, but non-superuser, roles to configure the
   server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 409d68943a..e40445f06a 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1229,7 +1229,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"track_commit_timestamp", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Collects transaction commit time."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&track_commit_timestamp,
 		false,
@@ -1998,7 +1998,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"hot_standby", PGC_POSTMASTER, REPLICATION_STANDBY,
 			gettext_noop("Allows connections and queries during recovery."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&EnableHotStandby,
 		true,
@@ -2009,7 +2009,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"hot_standby_feedback", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Allows feedback from a hot standby to the primary that will avoid query conflicts."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&hot_standby_feedback,
 		false,
@@ -2221,7 +2221,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_receiver_create_temp_slot", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets whether a WAL receiver should create a temporary replication slot if no permanent slot is configured."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&wal_receiver_create_temp_slot,
 		false,
@@ -2361,7 +2361,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_standby_archive_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing archived WAL data."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&max_standby_archive_delay,
@@ -2373,7 +2373,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_standby_streaming_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum delay before canceling queries when a hot standby server is processing streamed WAL data."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&max_standby_streaming_delay,
@@ -2385,7 +2385,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"recovery_min_apply_delay", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the minimum delay for applying changes during recovery."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&recovery_min_apply_delay,
@@ -2397,7 +2397,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_receiver_status_interval", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum interval between WAL receiver status reports to the sending server."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_S
 		},
 		&wal_receiver_status_interval,
@@ -2409,7 +2409,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_receiver_timeout", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the maximum wait time to receive data from the sending server."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&wal_receiver_timeout,
@@ -2831,7 +2831,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"vacuum_defer_cleanup_age", PGC_SIGHUP, REPLICATION_PRIMARY,
 			gettext_noop("Number of transactions by which VACUUM and HOT cleanup should be deferred, if any."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&vacuum_defer_cleanup_age,
 		0, 0, 1000000,			/* see ComputeXidHorizons */
@@ -2940,7 +2940,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_keep_size", PGC_SIGHUP, REPLICATION_SENDING,
 			gettext_noop("Sets the size of WAL files held for standby servers."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MB
 		},
 		&wal_keep_size_mb,
@@ -3065,7 +3065,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_wal_senders", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum number of simultaneously running WAL sender processes."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&max_wal_senders,
 		10, 0, MAX_BACKENDS,
@@ -3077,7 +3077,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_replication_slots", PGC_POSTMASTER, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum number of simultaneously defined replication slots."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&max_replication_slots,
 		10, 0, MAX_BACKENDS /* XXX? */ ,
@@ -3090,7 +3090,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Replication slots will be marked as failed, and segments released "
 						 "for deletion or recycling, if this much space is occupied by WAL "
 						 "on disk."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MB
 		},
 		&max_slot_wal_keep_size_mb,
@@ -3102,7 +3102,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_sender_timeout", PGC_USERSET, REPLICATION_SENDING,
 			gettext_noop("Sets the maximum time to wait for WAL replication."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&wal_sender_timeout,
@@ -3317,7 +3317,7 @@ static struct config_int ConfigureNamesInt[] =
 			REPLICATION_SUBSCRIBERS,
 			gettext_noop("Maximum number of logical replication worker processes."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&max_logical_replication_workers,
 		4, 0, MAX_BACKENDS,
@@ -3330,7 +3330,7 @@ static struct config_int ConfigureNamesInt[] =
 			REPLICATION_SUBSCRIBERS,
 			gettext_noop("Maximum number of table synchronization workers per subscription."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&max_sync_workers_per_subscription,
 		2, 0, MAX_BACKENDS,
@@ -3438,7 +3438,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the time to wait before retrying to retrieve WAL "
 						 "after a failed attempt."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&wal_retrieve_retry_interval,
@@ -4218,7 +4218,7 @@ static struct config_string ConfigureNamesString[] =
 		{"promote_trigger_file", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Specifies a file name whose presence ends recovery in the standby."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&PromoteTriggerFile,
 		"",
@@ -4229,7 +4229,7 @@ static struct config_string ConfigureNamesString[] =
 		{"primary_conninfo", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the connection string to be used to connect to the sending server."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&PrimaryConnInfo,
 		"",
@@ -4240,7 +4240,7 @@ static struct config_string ConfigureNamesString[] =
 		{"primary_slot_name", PGC_SIGHUP, REPLICATION_STANDBY,
 			gettext_noop("Sets the name of the replication slot to use on the sending server."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_REPLICATION_SETTINGS
 		},
 		&PrimarySlotName,
 		"",
@@ -4804,7 +4804,7 @@ static struct config_string ConfigureNamesString[] =
 		{"synchronous_standby_names", PGC_SIGHUP, REPLICATION_PRIMARY,
 			gettext_noop("Number of synchronous standbys and list of names of potential synchronous ones."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_REPLICATION_SETTINGS,
 			GUC_LIST_INPUT
 		},
 		&SyncRepStandbyNames,
@@ -7647,6 +7647,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_WRITE_SERVER_FILES))
 		return false;
 
+	if ((privileges & GUC_MANAGE_REPLICATION_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_REPLICATION_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 41d119f7b2..b36c81bf95 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -99,5 +99,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9283', oid_symbol => 'ROLE_PG_MANAGE_REPLICATION_SETTINGS',
+  rolname => 'pg_manage_replication_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 94d0b3c19d..ad75ac1e97 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -206,6 +206,7 @@ typedef enum
 #define GUC_MANAGE_AUTOVACUUM_SETTINGS		0x0004
 #define GUC_MANAGE_LOGGING_SETTINGS			0x0008
 #define GUC_WRITE_SERVER_FILES				0x0010
+#define GUC_MANAGE_REPLICATION_SETTINGS		0x0020
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 443c0237bd..82dcdb7133 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -496,3 +496,88 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_log_full_admin;
+-- Test role pg_manage_replication_settings
+-- Non-superuser with privileges to configure replication settings
+CREATE ROLE regress_replication_admin NOSUPERUSER;
+GRANT pg_manage_replication_settings TO regress_replication_admin;
+-- Perform all operations as user 'regress_replication_admin' --
+SET SESSION AUTHORIZATION regress_replication_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET max_replication_slots = 50;  -- ok
+ALTER SYSTEM RESET max_replication_slots;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET synchronous_standby_names = 'fee, fi, fo, fum';  -- ok
+ALTER SYSTEM RESET synchronous_standby_names;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_replication_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM SET wal_sender_timeout = 50;  -- ok
+ALTER SYSTEM RESET wal_sender_timeout;  -- ok
+-- Finished testing role pg_manage_replication_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_replication_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 767c5ecc46..3b652fea2d 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -330,3 +330,58 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_log_full_admin;
+-- Test role pg_manage_replication_settings
+-- Non-superuser with privileges to configure replication settings
+CREATE ROLE regress_replication_admin NOSUPERUSER;
+GRANT pg_manage_replication_settings TO regress_replication_admin;
+-- Perform all operations as user 'regress_replication_admin' --
+SET SESSION AUTHORIZATION regress_replication_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_replication_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET max_replication_slots = 50;  -- ok
+ALTER SYSTEM RESET max_replication_slots;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM SET synchronous_standby_names = 'fee, fi, fo, fum';  -- ok
+ALTER SYSTEM RESET synchronous_standby_names;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_replication_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_replication_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_replication_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_replication_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ALTER SYSTEM SET wal_sender_timeout = 50;  -- ok
+ALTER SYSTEM RESET wal_sender_timeout;  -- ok
+-- Finished testing role pg_manage_replication_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_replication_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0007-Adding-role-pg_manage_connection_settings.patchapplication/octet-stream; name=v1-0007-Adding-role-pg_manage_connection_settings.patch; x-unix-mode=0644Download
From 9da451eddf23ac96bd7e3db1408e6beaf24d28a0 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:50:45 -0700
Subject: [PATCH v1 07/12] Adding role pg_manage_connection_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls connection or authentication behavior or resource usage.
---
 doc/src/sgml/user-manag.sgml            |  9 ++-
 src/backend/utils/misc/guc.c            | 72 +++++++++++----------
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 85 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 55 ++++++++++++++++
 6 files changed, 191 insertions(+), 36 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index ed586cc260..827312d3f0 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -602,6 +602,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_replication_settings</entry>
        <entry>Allow changing settings which control replication behavior.</entry>
       </row>
+      <row>
+       <entry>pg_manage_connection_settings</entry>
+       <entry>Allow changing settings which control connections and authentication.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -650,8 +654,9 @@ DROP ROLE doomed_role;
   The <literal>pg_manage_host_resource_settings</literal>,
   <literal>pg_manage_vacuum_settings</literal>,
   <literal>pg_manage_autovacuum_settings</literal>,
-  <literal>pg_manage_logging_settings</literal> and
-  <literal>pg_manage_replication_settings</literal> roles are intended to allow
+  <literal>pg_manage_logging_settings</literal>,
+  <literal>pg_manage_replication_settings</literal> and
+  <literal>pg_manage_connection_settings</literal> roles are intended to allow
   administrators to have trusted, but non-superuser, roles to configure the
   server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e40445f06a..f87c2d390e 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1219,7 +1219,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"bonjour", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Enables advertising the server via Bonjour."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&enable_bonjour,
 		false,
@@ -1239,7 +1239,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"ssl", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Enables SSL connections."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&EnableSSL,
 		false,
@@ -1249,7 +1249,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"ssl_passphrase_command_supports_reload", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Also use ssl_passphrase_command during server reload."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_passphrase_command_supports_reload,
 		false,
@@ -1259,7 +1259,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"ssl_prefer_server_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Give priority to server ciphersuite order."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&SSLPreferServerCiphers,
 		true,
@@ -1748,7 +1748,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"db_user_namespace", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Enables per-database user names."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&Db_user_namespace,
 		false,
@@ -1942,7 +1942,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"krb_caseins_users", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Sets whether Kerberos and GSSAPI user names should be treated as case-insensitive."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&pg_krb_caseins_users,
 		false,
@@ -2421,7 +2421,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the maximum number of concurrent connections."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&MaxConnections,
 		100, 1, MAX_BACKENDS,
@@ -2433,7 +2433,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"superuser_reserved_connections", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the number of connection slots reserved for superusers."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ReservedBackends,
 		3, 0, MAX_BACKENDS,
@@ -2508,7 +2508,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"port", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the TCP port the server listens on."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&PostPortNumber,
 		DEF_PGPORT, 1, 65535,
@@ -2524,7 +2524,7 @@ static struct config_int ConfigureNamesInt[] =
 						 "accepted by the chmod and umask system calls. "
 						 "(To use the customary octal format the number must "
 						 "start with a 0 (zero).)"),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&Unix_socket_permissions,
 		0777, 0000, 0777,
@@ -2915,7 +2915,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"authentication_timeout", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Sets the maximum allowed time to complete client authentication."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_UNIT_S
 		},
 		&AuthenticationTimeout,
@@ -3603,7 +3603,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_keepalives_idle", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Time between issuing TCP keepalives."),
 			gettext_noop("A value of 0 uses the system default."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_UNIT_S
 		},
 		&tcp_keepalives_idle,
@@ -3615,7 +3615,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_keepalives_interval", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Time between TCP keepalive retransmits."),
 			gettext_noop("A value of 0 uses the system default."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_UNIT_S
 		},
 		&tcp_keepalives_interval,
@@ -3627,7 +3627,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"ssl_renegotiation_limit", PGC_USERSET, CONN_AUTH_SSL,
 			gettext_noop("SSL renegotiation is no longer supported; this can only be 0."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE,
 		},
 		&ssl_renegotiation_limit,
@@ -3641,7 +3641,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("This controls the number of consecutive keepalive retransmits that can be "
 						 "lost before a connection is considered dead. A value of 0 uses the "
 						 "system default."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&tcp_keepalives_count,
 		0, 0, INT_MAX,
@@ -3750,7 +3750,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"tcp_user_timeout", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("TCP user timeout."),
 			gettext_noop("A value of 0 uses the system default."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&tcp_user_timeout,
@@ -3798,7 +3798,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"client_connection_check_interval", PGC_USERSET, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the time interval between checks for disconnection while running queries."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&client_connection_check_interval,
@@ -4348,7 +4348,7 @@ static struct config_string ConfigureNamesString[] =
 		{"krb_server_keyfile", PGC_SIGHUP, CONN_AUTH_AUTH,
 			gettext_noop("Sets the location of the Kerberos server key file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&pg_krb_server_keyfile,
 		PG_KRB_SRVTAB,
@@ -4359,7 +4359,7 @@ static struct config_string ConfigureNamesString[] =
 		{"bonjour_name", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the Bonjour service name."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&bonjour_name,
 		"",
@@ -4622,7 +4622,7 @@ static struct config_string ConfigureNamesString[] =
 			gettext_noop("Sets the owning group of the Unix-domain socket."),
 			gettext_noop("The owning user of the socket is always the user "
 						 "that starts the server."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&Unix_socket_group,
 		"",
@@ -4633,7 +4633,7 @@ static struct config_string ConfigureNamesString[] =
 		{"unix_socket_directories", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the directories where Unix-domain sockets will be created."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
 		},
 		&Unix_socket_directories,
@@ -4649,7 +4649,7 @@ static struct config_string ConfigureNamesString[] =
 		{"listen_addresses", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
 			gettext_noop("Sets the host name or IP address(es) to listen to."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_LIST_INPUT
 		},
 		&ListenAddresses,
@@ -4738,7 +4738,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_cert_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL server certificate file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_cert_file,
 		"server.crt",
@@ -4749,7 +4749,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_key_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL server private key file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_key_file,
 		"server.key",
@@ -4760,7 +4760,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_ca_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate authority file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_ca_file,
 		"",
@@ -4771,7 +4771,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_crl_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate revocation list file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_crl_file,
 		"",
@@ -4782,7 +4782,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_crl_dir", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL certificate revocation list directory."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_crl_dir,
 		"",
@@ -4827,7 +4827,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_ciphers", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the list of allowed SSL ciphers."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&SSLCipherSuites,
 #ifdef USE_OPENSSL
@@ -4842,7 +4842,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_ecdh_curve", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the curve to use for ECDH."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&SSLECDHCurve,
 #ifdef USE_SSL
@@ -4857,7 +4857,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_dh_params_file", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Location of the SSL DH parameters file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_dh_params_file,
 		"",
@@ -4868,7 +4868,7 @@ static struct config_string ConfigureNamesString[] =
 		{"ssl_passphrase_command", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Command to obtain passphrases for SSL."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_passphrase_command,
 		"",
@@ -5287,7 +5287,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"password_encryption", PGC_USERSET, CONN_AUTH_AUTH,
 			gettext_noop("Chooses the algorithm for encrypting passwords."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&Password_encryption,
 		PASSWORD_TYPE_SCRAM_SHA_256, password_encryption_options,
@@ -5312,7 +5312,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"ssl_min_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the minimum SSL/TLS protocol version to use."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_CONNECTION_SETTINGS
 		},
 		&ssl_min_protocol_version,
 		PG_TLS1_2_VERSION,
@@ -5324,7 +5324,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"ssl_max_protocol_version", PGC_SIGHUP, CONN_AUTH_SSL,
 			gettext_noop("Sets the maximum SSL/TLS protocol version to use."),
 			NULL,
-			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES,
+			GUC_MANAGE_CONNECTION_SETTINGS,
 			GUC_SUPERUSER_ONLY
 		},
 		&ssl_max_protocol_version,
@@ -7651,6 +7651,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_REPLICATION_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_CONNECTION_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_CONNECTION_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index b36c81bf95..1885823710 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -104,5 +104,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9284', oid_symbol => 'ROLE_PG_MANAGE_CONNECTION_SETTINGS',
+  rolname => 'pg_manage_connection_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index ad75ac1e97..507ef40a5d 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -207,6 +207,7 @@ typedef enum
 #define GUC_MANAGE_LOGGING_SETTINGS			0x0008
 #define GUC_WRITE_SERVER_FILES				0x0010
 #define GUC_MANAGE_REPLICATION_SETTINGS		0x0020
+#define GUC_MANAGE_CONNECTION_SETTINGS		0x0040
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 82dcdb7133..02f9b89e17 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -581,3 +581,88 @@ ALTER SYSTEM RESET wal_sender_timeout;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_replication_admin;
+-- Test role pg_manage_connection_settings
+-- Non-superuser with privileges to configure connections and authentication
+CREATE ROLE regress_connection_admin NOSUPERUSER;
+GRANT pg_manage_connection_settings TO regress_connection_admin;
+-- Perform all operations as user 'regress_connection_admin' --
+SET SESSION AUTHORIZATION regress_connection_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET bonjour = OFF;  -- ok
+ALTER SYSTEM RESET bonjour;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET authentication_timeout = 50;  -- ok
+ALTER SYSTEM RESET authentication_timeout;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_connection_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET password_encryption = 'scram-sha-256';  -- ok
+ALTER SYSTEM RESET password_encryption;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_connection_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_connection_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 3b652fea2d..9dfe504c69 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -385,3 +385,58 @@ ALTER SYSTEM RESET wal_sender_timeout;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_replication_admin;
+-- Test role pg_manage_connection_settings
+-- Non-superuser with privileges to configure connections and authentication
+CREATE ROLE regress_connection_admin NOSUPERUSER;
+GRANT pg_manage_connection_settings TO regress_connection_admin;
+-- Perform all operations as user 'regress_connection_admin' --
+SET SESSION AUTHORIZATION regress_connection_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_connection_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM SET bonjour = OFF;  -- ok
+ALTER SYSTEM RESET bonjour;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM SET authentication_timeout = 50;  -- ok
+ALTER SYSTEM RESET authentication_timeout;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_connection_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_connection_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_connection_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_connection_admin has insufficient privileges
+ALTER SYSTEM SET password_encryption = 'scram-sha-256';  -- ok
+ALTER SYSTEM RESET password_encryption;  -- ok
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_connection_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_connection_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0008-Adding-role-pg_manage_wal_settings.patchapplication/octet-stream; name=v1-0008-Adding-role-pg_manage_wal_settings.patch; x-unix-mode=0644Download
From f2f3bdd619f51a0c441473684deb160c2440fca3 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:51:13 -0700
Subject: [PATCH v1 08/12] Adding role pg_manage_wal_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls write ahead log behavior or resource usage.
---
 doc/src/sgml/user-manag.sgml            |  9 ++-
 src/backend/utils/misc/guc.c            | 74 ++++++++++----------
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 89 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 59 ++++++++++++++++
 6 files changed, 200 insertions(+), 37 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 827312d3f0..4c577f9ca8 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -606,6 +606,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_connection_settings</entry>
        <entry>Allow changing settings which control connections and authentication.</entry>
       </row>
+      <row>
+       <entry>pg_manage_wal_settings</entry>
+       <entry>Allow changing settings which control write ahead log behavior.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -655,8 +659,9 @@ DROP ROLE doomed_role;
   <literal>pg_manage_vacuum_settings</literal>,
   <literal>pg_manage_autovacuum_settings</literal>,
   <literal>pg_manage_logging_settings</literal>,
-  <literal>pg_manage_replication_settings</literal> and
-  <literal>pg_manage_connection_settings</literal> roles are intended to allow
+  <literal>pg_manage_replication_settings</literal>,
+  <literal>pg_manage_connection_settings</literal> and
+  <literal>pg_manage_wal_settings</literal> roles are intended to allow
   administrators to have trusted, but non-superuser, roles to configure the
   server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f87c2d390e..f5ad9f37d5 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1272,7 +1272,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "sure that updates are physically written to disk. This insures "
 						 "that a database cluster will recover to a consistent state after "
 						 "an operating system or hardware crash."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&enableFsync,
 		true,
@@ -1337,7 +1337,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "stored in WAL are not enough to recover.  This option writes "
 						 "pages when first modified after a checkpoint to WAL so full recovery "
 						 "is possible."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&fullPageWrites,
 		true,
@@ -1348,7 +1348,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_log_hints", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Writes full pages to WAL when first modified after a checkpoint, even for a non-critical modification."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&wal_log_hints,
 		false,
@@ -1359,7 +1359,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_init_zero", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Writes zeroes to new WAL files before first use."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&wal_init_zero,
 		true,
@@ -1370,7 +1370,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_recycle", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Recycles WAL files by renaming them."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&wal_recycle,
 		true,
@@ -1917,7 +1917,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"wal_debug", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Emit WAL-related debugging output."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&XLOG_DEBUG,
@@ -1987,7 +1987,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"recovery_target_inclusive", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets whether to include or exclude transaction with recovery target."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recoveryTargetInclusive,
 		true,
@@ -2242,7 +2242,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Forces a switch to the next WAL file if a "
 						 "new file has not been started within N seconds."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_S
 		},
 		&XLogArchiveTimeout,
@@ -2952,7 +2952,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the minimum size to shrink the WAL to."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_MB
 		},
 		&min_wal_size_mb,
@@ -2965,7 +2965,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"max_wal_size", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the WAL size that triggers a checkpoint."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_MB
 		},
 		&max_wal_size_mb,
@@ -2978,7 +2978,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Sets the maximum time between automatic WAL checkpoints."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_S
 		},
 		&CheckPointTimeout,
@@ -3005,7 +3005,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"checkpoint_flush_after", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Number of pages after which previously performed writes are flushed to disk."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_BLOCKS
 		},
 		&checkpoint_flush_after,
@@ -3017,7 +3017,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_XBLOCKS
 		},
 		&XLOGbuffers,
@@ -3029,7 +3029,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_writer_delay", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Time between WAL flushes performed in the WAL writer."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_MS
 		},
 		&WalWriterDelay,
@@ -3041,7 +3041,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_writer_flush_after", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Amount of WAL written out by WAL writer that triggers a flush."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_XBLOCKS
 		},
 		&WalWriterFlushAfter,
@@ -3053,7 +3053,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"wal_skip_threshold", PGC_USERSET, WAL_SETTINGS,
 			gettext_noop("Minimum size of new file to fsync instead of writing WAL."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_WAL_SETTINGS,
 			GUC_UNIT_KB
 		},
 		&wal_skip_threshold,
@@ -3115,7 +3115,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the delay in microseconds between transaction commit and "
 						 "flushing WAL to disk."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 			/* we have no microseconds designation, so can't supply units here */
 		},
 		&CommitDelay,
@@ -3128,7 +3128,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the minimum concurrent open transactions before performing "
 						 "commit_delay."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&CommitSiblings,
 		5, 0, 1000,
@@ -4069,7 +4069,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
 			gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&CheckPointCompletionTarget,
 		0.9, 0.0, 1.0,
@@ -4112,7 +4112,7 @@ static struct config_string ConfigureNamesString[] =
 		{"archive_command", PGC_SIGHUP, WAL_ARCHIVING,
 			gettext_noop("Sets the shell command that will be called to archive a WAL file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&XLogArchiveCommand,
 		"",
@@ -4123,7 +4123,7 @@ static struct config_string ConfigureNamesString[] =
 		{"restore_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be called to retrieve an archived WAL file."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recoveryRestoreCommand,
 		"",
@@ -4134,7 +4134,7 @@ static struct config_string ConfigureNamesString[] =
 		{"archive_cleanup_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be executed at every restart point."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&archiveCleanupCommand,
 		"",
@@ -4145,7 +4145,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_end_command", PGC_SIGHUP, WAL_ARCHIVE_RECOVERY,
 			gettext_noop("Sets the shell command that will be executed once at the end of recovery."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recoveryEndCommand,
 		"",
@@ -4156,7 +4156,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target_timeline", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Specifies the timeline to recover into."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_timeline_string,
 		"latest",
@@ -4167,7 +4167,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Set to \"immediate\" to end recovery as soon as a consistent state is reached."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_string,
 		"",
@@ -4177,7 +4177,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target_xid", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the transaction ID up to which recovery will proceed."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_xid_string,
 		"",
@@ -4187,7 +4187,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target_time", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the time stamp up to which recovery will proceed."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_time_string,
 		"",
@@ -4197,7 +4197,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target_name", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the named restore point up to which recovery will proceed."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_name_string,
 		"",
@@ -4207,7 +4207,7 @@ static struct config_string ConfigureNamesString[] =
 		{"recovery_target_lsn", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the LSN of the write-ahead log location up to which recovery will proceed."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recovery_target_lsn_string,
 		"",
@@ -5125,7 +5125,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
 			gettext_noop("Sets the current transaction's synchronization level."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&synchronous_commit,
 		SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
@@ -5136,7 +5136,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"archive_mode", PGC_POSTMASTER, WAL_ARCHIVING,
 			gettext_noop("Allows archiving of WAL files using archive_command."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&XLogArchiveMode,
 		ARCHIVE_MODE_OFF, archive_mode_options,
@@ -5147,7 +5147,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"recovery_target_action", PGC_POSTMASTER, WAL_RECOVERY_TARGET,
 			gettext_noop("Sets the action to perform upon reaching the recovery target."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&recoveryTargetAction,
 		RECOVERY_TARGET_ACTION_PAUSE, recovery_target_action_options,
@@ -5186,7 +5186,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"wal_compression", PGC_SUSET, WAL_SETTINGS,
 			gettext_noop("Compresses full-page writes written in WAL file with specified method."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&wal_compression,
 		WAL_COMPRESSION_NONE, wal_compression_options,
@@ -5197,7 +5197,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"wal_level", PGC_POSTMASTER, WAL_SETTINGS,
 			gettext_noop("Sets the level of information written to the WAL."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&wal_level,
 		WAL_LEVEL_REPLICA, wal_level_options,
@@ -5230,7 +5230,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
 			gettext_noop("Selects the method used for forcing WAL updates to disk."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_WAL_SETTINGS
 		},
 		&sync_method,
 		DEFAULT_SYNC_METHOD, sync_method_options,
@@ -7655,6 +7655,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_CONNECTION_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_WAL_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_WAL_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 1885823710..cde919bee8 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -109,5 +109,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9285', oid_symbol => 'ROLE_PG_MANAGE_WAL_SETTINGS',
+  rolname => 'pg_manage_wal_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 507ef40a5d..a79c617bbe 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -208,6 +208,7 @@ typedef enum
 #define GUC_WRITE_SERVER_FILES				0x0010
 #define GUC_MANAGE_REPLICATION_SETTINGS		0x0020
 #define GUC_MANAGE_CONNECTION_SETTINGS		0x0040
+#define GUC_MANAGE_WAL_SETTINGS				0x0080
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 02f9b89e17..aadeb5b26c 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -666,3 +666,92 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_connection_admin;
+-- Test role pg_manage_wal_settings
+-- Non-superuser with privileges to configure write ahead log settings
+CREATE ROLE regress_wal_admin NOSUPERUSER;
+GRANT pg_manage_wal_settings TO regress_wal_admin;
+-- Perform all operations as user 'regress_wal_admin' --
+SET SESSION AUTHORIZATION regress_wal_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET archive_mode = 'off';  -- ok
+ALTER SYSTEM RESET archive_mode;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET archive_cleanup_command = '/bin/cleanup my stuff';  -- ok
+ALTER SYSTEM RESET archive_cleanup_command;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET commit_delay = 50;  -- ok
+RESET commit_delay;  -- ok
+ALTER SYSTEM SET commit_delay = 50;  -- ok
+ALTER SYSTEM RESET commit_delay;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_wal_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM SET commit_siblings = 50;  -- ok
+ALTER SYSTEM RESET commit_siblings;  -- ok
+-- Finished testing role pg_manage_wal_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_wal_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 9dfe504c69..3932abc28f 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -440,3 +440,62 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_connection_admin;
+-- Test role pg_manage_wal_settings
+-- Non-superuser with privileges to configure write ahead log settings
+CREATE ROLE regress_wal_admin NOSUPERUSER;
+GRANT pg_manage_wal_settings TO regress_wal_admin;
+-- Perform all operations as user 'regress_wal_admin' --
+SET SESSION AUTHORIZATION regress_wal_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_wal_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET archive_mode = 'off';  -- ok
+ALTER SYSTEM RESET archive_mode;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM SET archive_cleanup_command = '/bin/cleanup my stuff';  -- ok
+ALTER SYSTEM RESET archive_cleanup_command;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_wal_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_wal_admin has insufficient privileges
+SET commit_delay = 50;  -- ok
+RESET commit_delay;  -- ok
+ALTER SYSTEM SET commit_delay = 50;  -- ok
+ALTER SYSTEM RESET commit_delay;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_wal_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_wal_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ALTER SYSTEM SET commit_siblings = 50;  -- ok
+ALTER SYSTEM RESET commit_siblings;  -- ok
+-- Finished testing role pg_manage_wal_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_wal_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0009-Adding-role-pg_manage_query_tuning_settings.patchapplication/octet-stream; name=v1-0009-Adding-role-pg_manage_query_tuning_settings.patch; x-unix-mode=0644Download
From 8d4b066723db8c7aa6a5125a4df7d3dc51b47dfc Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:51:42 -0700
Subject: [PATCH v1 09/12] Adding role pg_manage_query_tuning_settings

This new role can ALTER SYSTEM SET any GUC variable which controls
query planning and execution tuning.
---
 doc/src/sgml/user-manag.sgml            |  13 ++-
 src/backend/utils/misc/guc.c            | 104 ++++++++++++------------
 src/include/catalog/pg_authid.dat       |   5 ++
 src/include/utils/guc.h                 |   1 +
 src/test/regress/expected/guc_privs.out |  81 ++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      |  51 ++++++++++++
 6 files changed, 201 insertions(+), 54 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 4c577f9ca8..3bd08d6aef 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -610,6 +610,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_wal_settings</entry>
        <entry>Allow changing settings which control write ahead log behavior.</entry>
       </row>
+      <row>
+       <entry>pg_manage_query_tuning_settings</entry>
+       <entry>Allow changing settings which control tuning of query planning and execution.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -660,10 +664,11 @@ DROP ROLE doomed_role;
   <literal>pg_manage_autovacuum_settings</literal>,
   <literal>pg_manage_logging_settings</literal>,
   <literal>pg_manage_replication_settings</literal>,
-  <literal>pg_manage_connection_settings</literal> and
-  <literal>pg_manage_wal_settings</literal> roles are intended to allow
-  administrators to have trusted, but non-superuser, roles to configure the
-  server.
+  <literal>pg_manage_connection_settings</literal>,
+  <literal>pg_manage_wal_settings</literal> and
+  <literal>pg_manage_query_tuning_settings</literal> roles are intended to
+  allow administrators to have trusted, but non-superuser, roles to configure
+  the server.
   </para>
 
   <para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index f5ad9f37d5..65f371138f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -974,7 +974,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of sequential-scan plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_seqscan,
@@ -985,7 +985,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_indexscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of index-scan plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_indexscan,
@@ -996,7 +996,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_indexonlyscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of index-only-scan plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_indexonlyscan,
@@ -1007,7 +1007,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_bitmapscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of bitmap-scan plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_bitmapscan,
@@ -1018,7 +1018,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_tidscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of TID scan plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_tidscan,
@@ -1029,7 +1029,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of explicit sort steps."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_sort,
@@ -1040,7 +1040,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_incremental_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of incremental sort steps."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_QUERY_TUNING_SETTINGS
 		},
 		&enable_incremental_sort,
 		true,
@@ -1050,7 +1050,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_hashagg", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of hashed aggregation plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_hashagg,
@@ -1061,7 +1061,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_material", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of materialization."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_material,
@@ -1072,7 +1072,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_memoize", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of memoization."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_memoize,
@@ -1083,7 +1083,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_nestloop", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of nested-loop join plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_nestloop,
@@ -1094,7 +1094,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_mergejoin", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of merge join plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_mergejoin,
@@ -1105,7 +1105,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_hashjoin", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of hash join plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_hashjoin,
@@ -1116,7 +1116,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_gathermerge", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of gather merge plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_gathermerge,
@@ -1127,7 +1127,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_partitionwise_join", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables partitionwise join."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_partitionwise_join,
@@ -1138,7 +1138,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_partitionwise_aggregate", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables partitionwise aggregation and grouping."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_partitionwise_aggregate,
@@ -1149,7 +1149,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_parallel_append", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of parallel append plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_parallel_append,
@@ -1160,7 +1160,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_parallel_hash", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of parallel hash plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_parallel_hash,
@@ -1173,7 +1173,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Allows the query planner and executor to compare partition "
 						 "bounds to conditions in the query to determine which "
 						 "partitions must be scanned."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_partition_pruning,
@@ -1184,7 +1184,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"enable_async_append", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of async append plans."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_async_append,
@@ -1196,7 +1196,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Enables genetic query optimization."),
 			gettext_noop("This algorithm attempts to do planning without "
 						 "exhaustive searching."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&enable_geqo,
@@ -1903,7 +1903,7 @@ static struct config_bool ConfigureNamesBool[] =
 			"optimize_bounded_sort", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enable bounded sorting using heap sort."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_NOT_IN_SAMPLE | GUC_EXPLAIN
 		},
 		&optimize_bounded_sort,
@@ -2126,7 +2126,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"jit", PGC_USERSET, QUERY_TUNING_OTHER,
 			gettext_noop("Allow JIT compilation."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&jit_enabled,
@@ -2265,7 +2265,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the default statistics target."),
 			gettext_noop("This applies to table columns that have not had a "
 						 "column-specific target set via ALTER TABLE SET STATISTICS."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_QUERY_TUNING_SETTINGS
 		},
 		&default_statistics_target,
 		100, 1, 10000,
@@ -2278,7 +2278,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The planner will merge subqueries into upper "
 						 "queries if the resulting FROM list would have no more than "
 						 "this many items."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&from_collapse_limit,
@@ -2292,7 +2292,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("The planner will flatten explicit JOIN "
 						 "constructs into lists of FROM items whenever a "
 						 "list of no more than this many items would result."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&join_collapse_limit,
@@ -2303,7 +2303,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_threshold", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("Sets the threshold of FROM items beyond which GEQO is used."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&geqo_threshold,
@@ -2314,7 +2314,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_effort", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: effort is used to set the default for other GEQO parameters."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&Geqo_effort,
@@ -2325,7 +2325,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_pool_size", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: number of individuals in the population."),
 			gettext_noop("Zero selects a suitable default value."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&Geqo_pool_size,
@@ -2336,7 +2336,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"geqo_generations", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: number of iterations of the algorithm."),
 			gettext_noop("Zero selects a suitable default value."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&Geqo_generations,
@@ -3254,7 +3254,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("Number of simultaneous requests that can be handled efficiently by the disk subsystem."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&effective_io_concurrency,
@@ -3273,7 +3273,7 @@ static struct config_int ConfigureNamesInt[] =
 			RESOURCES_ASYNCHRONOUS,
 			gettext_noop("A variant of effective_io_concurrency that is used for maintenance work."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&maintenance_io_concurrency,
@@ -3665,7 +3665,7 @@ static struct config_int ConfigureNamesInt[] =
 			gettext_noop("Sets the planner's assumption about the total size of the data caches."),
 			gettext_noop("That is, the total size of the caches (kernel cache and shared buffers) used for PostgreSQL data files. "
 						 "This is measured in disk pages, which are normally 8 kB each."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&effective_cache_size,
@@ -3677,7 +3677,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_parallel_table_scan_size", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Sets the minimum amount of table data for a parallel scan."),
 			gettext_noop("If the planner estimates that it will read a number of table pages too small to reach this limit, a parallel scan will not be considered."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&min_parallel_table_scan_size,
@@ -3689,7 +3689,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"min_parallel_index_scan_size", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Sets the minimum amount of index data for a parallel scan."),
 			gettext_noop("If the planner estimates that it will read a number of index pages too small to reach this limit, a parallel scan will not be considered."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_UNIT_BLOCKS | GUC_EXPLAIN,
 		},
 		&min_parallel_index_scan_size,
@@ -3820,7 +3820,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of a "
 						 "sequentially fetched disk page."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&seq_page_cost,
@@ -3832,7 +3832,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of a "
 						 "nonsequentially fetched disk page."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&random_page_cost,
@@ -3844,7 +3844,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each tuple (row)."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&cpu_tuple_cost,
@@ -3856,7 +3856,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each index entry during an index scan."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&cpu_index_tuple_cost,
@@ -3868,7 +3868,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "processing each operator or function call."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&cpu_operator_cost,
@@ -3880,7 +3880,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "passing each tuple (row) from worker to leader backend."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&parallel_tuple_cost,
@@ -3892,7 +3892,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the cost of "
 						 "starting up worker processes for parallel query."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&parallel_setup_cost,
@@ -3904,7 +3904,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Perform JIT compilation if query is more expensive."),
 			gettext_noop("-1 disables JIT compilation."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&jit_above_cost,
@@ -3916,7 +3916,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_optimize_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Optimize JIT-compiled functions if query is more expensive."),
 			gettext_noop("-1 disables optimization."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&jit_optimize_above_cost,
@@ -3928,7 +3928,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"jit_inline_above_cost", PGC_USERSET, QUERY_TUNING_COST,
 			gettext_noop("Perform JIT inlining if query is more expensive."),
 			gettext_noop("-1 disables inlining."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&jit_inline_above_cost,
@@ -3941,7 +3941,7 @@ static struct config_real ConfigureNamesReal[] =
 			gettext_noop("Sets the planner's estimate of the fraction of "
 						 "a cursor's rows that will be retrieved."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&cursor_tuple_fraction,
@@ -3953,7 +3953,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"geqo_selection_bias", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: selective pressure within the population."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&Geqo_selection_bias,
@@ -3965,7 +3965,7 @@ static struct config_real ConfigureNamesReal[] =
 		{"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO,
 			gettext_noop("GEQO: seed for random path selection."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&Geqo_seed,
@@ -4993,7 +4993,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Enables the planner to use constraints to optimize queries."),
 			gettext_noop("Table scans will be skipped if their constraints"
 						 " guarantee that no rows match the query."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&constraint_exclusion,
@@ -5300,7 +5300,7 @@ static struct config_enum ConfigureNamesEnum[] =
 			gettext_noop("Prepared statements can have custom and generic plans, and the planner "
 						 "will attempt to choose which is better.  This can be set to override "
 						 "the default behavior."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_QUERY_TUNING_SETTINGS,
 			GUC_EXPLAIN
 		},
 		&plan_cache_mode,
@@ -7659,6 +7659,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_WAL_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_QUERY_TUNING_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_QUERY_TUNING_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index cde919bee8..68e305c34f 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -114,5 +114,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9286', oid_symbol => 'ROLE_PG_MANAGE_QUERY_TUNING_SETTINGS',
+  rolname => 'pg_manage_query_tuning_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index a79c617bbe..bca2c113de 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -209,6 +209,7 @@ typedef enum
 #define GUC_MANAGE_REPLICATION_SETTINGS		0x0020
 #define GUC_MANAGE_CONNECTION_SETTINGS		0x0040
 #define GUC_MANAGE_WAL_SETTINGS				0x0080
+#define GUC_MANAGE_QUERY_TUNING_SETTINGS	0x0200	/* 0x0100 = superuser */
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index aadeb5b26c..e748b6531b 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -755,3 +755,84 @@ ALTER SYSTEM RESET commit_siblings;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_wal_admin;
+-- Test role pg_manage_query_tuning_settings
+-- Non-superuser with privileges to tune query planning and execution
+CREATE ROLE regress_query_tuning_admin NOSUPERUSER;
+GRANT pg_manage_query_tuning_settings TO regress_query_tuning_admin;
+-- Perform all operations as user 'regress_query_tuning_admin' --
+SET SESSION AUTHORIZATION regress_query_tuning_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_query_tuning_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM SET cpu_index_tuple_cost = 50;  -- ok
+ALTER SYSTEM RESET cpu_index_tuple_cost;  -- ok
+-- Finished testing role pg_manage_query_tuning_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_query_tuning_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 3932abc28f..d30284f4c9 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -499,3 +499,54 @@ ALTER SYSTEM RESET commit_siblings;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_wal_admin;
+-- Test role pg_manage_query_tuning_settings
+-- Non-superuser with privileges to tune query planning and execution
+CREATE ROLE regress_query_tuning_admin NOSUPERUSER;
+GRANT pg_manage_query_tuning_settings TO regress_query_tuning_admin;
+-- Perform all operations as user 'regress_query_tuning_admin' --
+SET SESSION AUTHORIZATION regress_query_tuning_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_query_tuning_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_query_tuning_admin has insufficient privileges
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_query_tuning_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_query_tuning_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_query_tuning_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_query_tuning_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ALTER SYSTEM SET cpu_index_tuple_cost = 50;  -- ok
+ALTER SYSTEM RESET cpu_index_tuple_cost;  -- ok
+-- Finished testing role pg_manage_query_tuning_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_query_tuning_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0010-Adding-role-pg_manage_stats_settings.patchapplication/octet-stream; name=v1-0010-Adding-role-pg_manage_stats_settings.patch; x-unix-mode=0644Download
From 9df87255f47107c03bf2531bb018e84a69e1fa07 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:52:22 -0700
Subject: [PATCH v1 10/12] Adding role pg_manage_stats_settings

This new role can SET and ALTER SYSTEM SET any GUC variable which
controls stats collection.  Note that variables controlling where to
write stats to the server filesystem may not be set by this role
unless the user also has membership in role pg_write_server_files.
---
 doc/src/sgml/user-manag.sgml            |   9 +-
 src/backend/utils/misc/guc.c            |  20 +--
 src/include/catalog/pg_authid.dat       |   5 +
 src/include/utils/guc.h                 |   1 +
 src/test/regress/expected/guc_privs.out | 173 ++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 113 ++++++++++++++++
 6 files changed, 311 insertions(+), 10 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 3bd08d6aef..548ece3acb 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -614,6 +614,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_query_tuning_settings</entry>
        <entry>Allow changing settings which control tuning of query planning and execution.</entry>
       </row>
+      <row>
+       <entry>pg_manage_stats_settings</entry>
+       <entry>Allow changing settings which control collection of statistics.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -665,8 +669,9 @@ DROP ROLE doomed_role;
   <literal>pg_manage_logging_settings</literal>,
   <literal>pg_manage_replication_settings</literal>,
   <literal>pg_manage_connection_settings</literal>,
-  <literal>pg_manage_wal_settings</literal> and
-  <literal>pg_manage_query_tuning_settings</literal> roles are intended to
+  <literal>pg_manage_wal_settings</literal>,
+  <literal>pg_manage_query_tuning_settings</literal> and
+  <literal>pg_manage_stats_settings</literal> roles are intended to
   allow administrators to have trusted, but non-superuser, roles to configure
   the server.
   </para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 65f371138f..a676c4af09 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1575,7 +1575,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Enables the collection of information on the currently "
 						 "executing command of each session, along with "
 						 "the time at which that command began execution."),
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&pgstat_track_activities,
 		true,
@@ -1585,7 +1585,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"track_counts", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects statistics on database activity."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&pgstat_track_counts,
 		true,
@@ -1595,7 +1595,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"track_io_timing", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects timing statistics for database I/O activity."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&track_io_timing,
 		false,
@@ -1605,7 +1605,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"track_wal_io_timing", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects timing statistics for WAL I/O activity."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&track_wal_io_timing,
 		false,
@@ -3726,7 +3726,7 @@ static struct config_int ConfigureNamesInt[] =
 		{"track_activity_query_size", PGC_POSTMASTER, STATS_COLLECTOR,
 			gettext_noop("Sets the size reserved for pg_stat_activity.query, in bytes."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_STATS_SETTINGS,
 			GUC_UNIT_BYTE
 		},
 		&pgstat_track_activity_query_size,
@@ -4793,7 +4793,7 @@ static struct config_string ConfigureNamesString[] =
 		{"stats_temp_directory", PGC_SIGHUP, STATS_COLLECTOR,
 			gettext_noop("Writes temporary statistics files to the specified directory."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS | GUC_WRITE_SERVER_FILES
 		},
 		&pgstat_temp_directory,
 		PG_STAT_TMP_DIR,
@@ -4981,7 +4981,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"compute_query_id", PGC_SUSET, STATS_MONITORING,
 			gettext_noop("Compute query identifiers."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&compute_query_id,
 		COMPUTE_QUERY_ID_AUTO, compute_query_id_options,
@@ -5175,7 +5175,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"track_functions", PGC_SUSET, STATS_COLLECTOR,
 			gettext_noop("Collects function-level statistics on database activity."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_STATS_SETTINGS
 		},
 		&pgstat_track_functions,
 		TRACK_FUNC_OFF, track_function_options,
@@ -7663,6 +7663,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_QUERY_TUNING_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_STATS_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_STATS_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 68e305c34f..3f80cbd59b 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -119,5 +119,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9287', oid_symbol => 'ROLE_PG_MANAGE_STATS_SETTINGS',
+  rolname => 'pg_manage_stats_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index bca2c113de..3e91f13cb8 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -210,6 +210,7 @@ typedef enum
 #define GUC_MANAGE_CONNECTION_SETTINGS		0x0040
 #define GUC_MANAGE_WAL_SETTINGS				0x0080
 #define GUC_MANAGE_QUERY_TUNING_SETTINGS	0x0200	/* 0x0100 = superuser */
+#define GUC_MANAGE_STATS_SETTINGS			0x0400
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index e748b6531b..4b8d50d93c 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -836,3 +836,176 @@ ALTER SYSTEM RESET cpu_index_tuple_cost;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_query_tuning_admin;
+-- Test role pg_manage_stats_settings
+-- Non-superuser with privileges to configure stats collection
+CREATE ROLE regress_stats_collation_admin NOSUPERUSER;
+GRANT pg_manage_stats_settings TO regress_stats_collation_admin;
+-- Perform all operations as user 'regress_stats_collation_admin' --
+SET SESSION AUTHORIZATION regress_stats_collation_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET track_activity_query_size = 524338;  -- ok
+ALTER SYSTEM RESET track_activity_query_size;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET track_activities = OFF;  -- ok
+RESET track_activities;  -- ok
+ALTER SYSTEM SET track_activities = OFF;  -- ok
+ALTER SYSTEM RESET track_activities;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_stats_collation_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_stats_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_stats_collation_admin;
+-- Test combination of roles pg_manage_stats_settings and pg_write_server_files
+-- Non-superuser with privileges to configure stats collection and recording
+CREATE ROLE regress_stats_full_admin NOSUPERUSER;
+GRANT pg_manage_stats_settings TO regress_stats_full_admin;
+GRANT pg_write_server_files TO regress_stats_full_admin;
+-- Perform all operations as user 'regress_stats_full_admin' --
+SET SESSION AUTHORIZATION regress_stats_full_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM SET track_activity_query_size = 524338;  -- ok
+ALTER SYSTEM RESET track_activity_query_size;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET stats_temp_directory = 'pg_stat_tmp';  -- ok
+ALTER SYSTEM RESET stats_temp_directory;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET track_activities = OFF;  -- ok
+RESET track_activities;  -- ok
+ALTER SYSTEM SET track_activities = OFF;  -- ok
+ALTER SYSTEM RESET track_activities;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_stats_full_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing combination of roles pg_manage_stats_settings and pg_write_server_files
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_stats_full_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index d30284f4c9..78b6df76cf 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -550,3 +550,116 @@ ALTER SYSTEM RESET cpu_index_tuple_cost;  -- ok
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_query_tuning_admin;
+-- Test role pg_manage_stats_settings
+-- Non-superuser with privileges to configure stats collection
+CREATE ROLE regress_stats_collation_admin NOSUPERUSER;
+GRANT pg_manage_stats_settings TO regress_stats_collation_admin;
+-- Perform all operations as user 'regress_stats_collation_admin' --
+SET SESSION AUTHORIZATION regress_stats_collation_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_stats_collation_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET track_activity_query_size = 524338;  -- ok
+ALTER SYSTEM RESET track_activity_query_size;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_stats_collation_admin has insufficient privileges
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_collation_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_stats_collation_admin has insufficient privileges
+SET track_activities = OFF;  -- ok
+RESET track_activities;  -- ok
+ALTER SYSTEM SET track_activities = OFF;  -- ok
+ALTER SYSTEM RESET track_activities;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_stats_collation_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_stats_collation_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_stats_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_stats_collation_admin;
+-- Test combination of roles pg_manage_stats_settings and pg_write_server_files
+-- Non-superuser with privileges to configure stats collection and recording
+CREATE ROLE regress_stats_full_admin NOSUPERUSER;
+GRANT pg_manage_stats_settings TO regress_stats_full_admin;
+GRANT pg_write_server_files TO regress_stats_full_admin;
+-- Perform all operations as user 'regress_stats_full_admin' --
+SET SESSION AUTHORIZATION regress_stats_full_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_stats_full_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ALTER SYSTEM SET track_activity_query_size = 524338;  -- ok
+ALTER SYSTEM RESET track_activity_query_size;  -- ok
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM SET stats_temp_directory = 'pg_stat_tmp';  -- ok
+ALTER SYSTEM RESET stats_temp_directory;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_full_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_stats_full_admin has insufficient privileges
+SET track_activities = OFF;  -- ok
+RESET track_activities;  -- ok
+ALTER SYSTEM SET track_activities = OFF;  -- ok
+ALTER SYSTEM RESET track_activities;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_stats_full_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_stats_full_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing combination of roles pg_manage_stats_settings and pg_write_server_files
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_stats_full_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0011-Adding-role-pg_manage_recovery_settings.patchapplication/octet-stream; name=v1-0011-Adding-role-pg_manage_recovery_settings.patch; x-unix-mode=0644Download
From ca6bada86f76943e732db66aee9cf02c565d22f8 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:52:49 -0700
Subject: [PATCH v1 11/12] Adding role pg_manage_recovery_settings

This new role can SET or ALTER SYSTEM SET any GUC variable which
controls crash recovery settings.
---
 doc/src/sgml/user-manag.sgml            | 13 ++--
 src/backend/utils/misc/guc.c            | 20 +++---
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 89 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 59 ++++++++++++++++
 6 files changed, 175 insertions(+), 12 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index 548ece3acb..c97350ee92 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -618,6 +618,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_stats_settings</entry>
        <entry>Allow changing settings which control collection of statistics.</entry>
       </row>
+      <row>
+       <entry>pg_manage_recovery_settings</entry>
+       <entry>Allow changing settings which control or are generally used for recovery.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -670,10 +674,11 @@ DROP ROLE doomed_role;
   <literal>pg_manage_replication_settings</literal>,
   <literal>pg_manage_connection_settings</literal>,
   <literal>pg_manage_wal_settings</literal>,
-  <literal>pg_manage_query_tuning_settings</literal> and
-  <literal>pg_manage_stats_settings</literal> roles are intended to
-  allow administrators to have trusted, but non-superuser, roles to configure
-  the server.
+  <literal>pg_manage_query_tuning_settings</literal>,
+  <literal>pg_manage_stats_settings</literal> and
+  <literal>pg_manage_recovery_settings</literal> roles are intended to allow
+  administrators to have trusted, but non-superuser, roles to configure the
+  server.
   </para>
 
   <para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index a676c4af09..5e52b5544d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1287,7 +1287,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "(but still report a warning), and continue processing. This "
 						 "behavior could cause crashes or other serious problems. Only "
 						 "has an effect if checksums are enabled."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&ignore_checksum_failure,
@@ -1302,7 +1302,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "zero_damaged_pages to true causes the system to instead report a "
 						 "warning, zero out the damaged page, and continue processing. This "
 						 "behavior will destroy data, namely all the rows on the damaged page."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&zero_damaged_pages,
@@ -1322,7 +1322,7 @@ static struct config_bool ConfigureNamesBool[] =
 						 "crashes, data loss, propagate or hide corruption, "
 						 "or other serious problems. Only has an effect "
 						 "during recovery or in standby mode."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&ignore_invalid_pages,
@@ -1447,7 +1447,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"restart_after_crash", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Reinitialize server after backend crash."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_RECOVERY_SETTINGS
 		},
 		&restart_after_crash,
 		true,
@@ -1457,7 +1457,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"remove_temp_files_after_crash", PGC_SIGHUP, DEVELOPER_OPTIONS,
 			gettext_noop("Remove temporary files after backend crash."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&remove_temp_files_after_crash,
@@ -2032,7 +2032,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"allow_system_table_mods", PGC_SUSET, DEVELOPER_OPTIONS,
 			gettext_noop("Allows modifications of the structure of system tables."),
 			NULL,
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&allowSystemTableMods,
@@ -2045,7 +2045,7 @@ static struct config_bool ConfigureNamesBool[] =
 			gettext_noop("Disables reading from system indexes."),
 			gettext_noop("It does not prevent updating the indexes, so it is safe "
 						 "to use.  The worst consequence is slowness."),
-			GUC_SUPERUSER_ONLY,
+			GUC_MANAGE_RECOVERY_SETTINGS,
 			GUC_NOT_IN_SAMPLE
 		},
 		&IgnoreSystemIndexes,
@@ -5337,7 +5337,7 @@ static struct config_enum ConfigureNamesEnum[] =
 		{"recovery_init_sync_method", PGC_SIGHUP, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Sets the method for synchronizing the data directory before crash recovery."),
 			NULL,
-			GUC_MANAGE_LOGGING_SETTINGS | GUC_WRITE_SERVER_FILES
+			GUC_MANAGE_RECOVERY_SETTINGS
 		},
 		&recovery_init_sync_method,
 		RECOVERY_INIT_SYNC_METHOD_FSYNC, recovery_init_sync_method_options,
@@ -7667,6 +7667,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_STATS_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_RECOVERY_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_RECOVERY_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 3f80cbd59b..05ac06ccc9 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -124,5 +124,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9288', oid_symbol => 'ROLE_PG_MANAGE_RECOVERY_SETTINGS',
+  rolname => 'pg_manage_recovery_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 3e91f13cb8..fe1e4b0c4c 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -211,6 +211,7 @@ typedef enum
 #define GUC_MANAGE_WAL_SETTINGS				0x0080
 #define GUC_MANAGE_QUERY_TUNING_SETTINGS	0x0200	/* 0x0100 = superuser */
 #define GUC_MANAGE_STATS_SETTINGS			0x0400
+#define GUC_MANAGE_RECOVERY_SETTINGS		0x0800
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 4b8d50d93c..91f28d4b75 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -1009,3 +1009,92 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_full_admin;
+-- Test role pg_manage_recovery_settings
+-- Non-superuser with privileges to configure recovery
+CREATE ROLE regress_recovery_admin NOSUPERUSER;
+GRANT pg_manage_recovery_settings TO regress_recovery_admin;
+-- Perform all operations as user 'regress_recovery_admin' --
+SET SESSION AUTHORIZATION regress_recovery_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- ok
+ALTER SYSTEM RESET ignore_system_indexes;  -- ok
+ALTER SYSTEM SET post_auth_delay = 50;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "post_auth_delay"
+ALTER SYSTEM RESET post_auth_delay;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "post_auth_delay"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET ignore_invalid_pages = OFF;  -- ok
+ALTER SYSTEM RESET ignore_invalid_pages;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM SET remove_temp_files_after_crash = OFF;  -- ok
+ALTER SYSTEM RESET remove_temp_files_after_crash;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+SET allow_system_table_mods = OFF;  -- ok
+RESET allow_system_table_mods;  -- ok
+ALTER SYSTEM SET allow_system_table_mods = OFF;  -- ok
+ALTER SYSTEM RESET allow_system_table_mods;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_recovery_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+-- Finished testing role pg_manage_recovery_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_recovery_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index 78b6df76cf..bb25b00e2a 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -663,3 +663,62 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_stats_full_admin;
+-- Test role pg_manage_recovery_settings
+-- Non-superuser with privileges to configure recovery
+CREATE ROLE regress_recovery_admin NOSUPERUSER;
+GRANT pg_manage_recovery_settings TO regress_recovery_admin;
+-- Perform all operations as user 'regress_recovery_admin' --
+SET SESSION AUTHORIZATION regress_recovery_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- ok
+ALTER SYSTEM RESET ignore_system_indexes;  -- ok
+ALTER SYSTEM SET post_auth_delay = 50;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET post_auth_delay;  -- fail, regress_recovery_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM SET ignore_invalid_pages = OFF;  -- ok
+ALTER SYSTEM RESET ignore_invalid_pages;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM SET remove_temp_files_after_crash = OFF;  -- ok
+ALTER SYSTEM RESET remove_temp_files_after_crash;  -- ok
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_recovery_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_recovery_admin has insufficient privileges
+SET allow_system_table_mods = OFF;  -- ok
+RESET allow_system_table_mods;  -- ok
+ALTER SYSTEM SET allow_system_table_mods = OFF;  -- ok
+ALTER SYSTEM RESET allow_system_table_mods;  -- ok
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_recovery_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_recovery_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+-- Finished testing role pg_manage_recovery_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_recovery_admin;
-- 
2.21.1 (Apple Git-122.3)

v1-0012-Adding-role-pg_manage_error_handling_settings.patchapplication/octet-stream; name=v1-0012-Adding-role-pg_manage_error_handling_settings.patch; x-unix-mode=0644Download
From fc1291d980626f34e8be8524d871c5f2c401bc71 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 20 Oct 2021 07:53:28 -0700
Subject: [PATCH v1 12/12] Adding role pg_manage_error_handling_settings

This new role can SET or ALTER SYSTEM SET any GUC variable which
controls error handling settings.
---
 doc/src/sgml/user-manag.sgml            | 13 ++--
 src/backend/utils/misc/guc.c            |  8 ++-
 src/include/catalog/pg_authid.dat       |  5 ++
 src/include/utils/guc.h                 |  1 +
 src/test/regress/expected/guc_privs.out | 83 +++++++++++++++++++++++++
 src/test/regress/sql/guc_privs.sql      | 53 ++++++++++++++++
 6 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml
index c97350ee92..b459a4e3c0 100644
--- a/doc/src/sgml/user-manag.sgml
+++ b/doc/src/sgml/user-manag.sgml
@@ -622,6 +622,10 @@ DROP ROLE doomed_role;
        <entry>pg_manage_recovery_settings</entry>
        <entry>Allow changing settings which control or are generally used for recovery.</entry>
       </row>
+      <row>
+       <entry>pg_manage_error_handling_settings</entry>
+       <entry>Allow changing settings which control how errors are handled.</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
@@ -675,10 +679,11 @@ DROP ROLE doomed_role;
   <literal>pg_manage_connection_settings</literal>,
   <literal>pg_manage_wal_settings</literal>,
   <literal>pg_manage_query_tuning_settings</literal>,
-  <literal>pg_manage_stats_settings</literal> and
-  <literal>pg_manage_recovery_settings</literal> roles are intended to allow
-  administrators to have trusted, but non-superuser, roles to configure the
-  server.
+  <literal>pg_manage_stats_settings</literal>,
+  <literal>pg_manage_recovery_settings</literal> and
+  <literal>pg_manage_error_handling_settings</literal> roles are intended to
+  allow administrators to have trusted, but non-superuser, roles to configure
+  the server.
   </para>
 
   <para>
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 5e52b5544d..bc9ddeae38 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1437,7 +1437,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"exit_on_error", PGC_USERSET, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Terminate session on any error."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_ERROR_HANDLING_SETTINGS
 		},
 		&ExitOnAnyError,
 		false,
@@ -2210,7 +2210,7 @@ static struct config_bool ConfigureNamesBool[] =
 		{"data_sync_retry", PGC_POSTMASTER, ERROR_HANDLING_OPTIONS,
 			gettext_noop("Whether to continue running after a failure to sync data files."),
 			NULL,
-			GUC_SUPERUSER_ONLY
+			GUC_MANAGE_ERROR_HANDLING_SETTINGS
 		},
 		&data_sync_retry,
 		false,
@@ -7671,6 +7671,10 @@ role_has_privileges(Oid roleid, int privileges)
 		! has_privs_of_role(roleid, ROLE_PG_MANAGE_RECOVERY_SETTINGS))
 		return false;
 
+	if ((privileges & GUC_MANAGE_ERROR_HANDLING_SETTINGS) &&
+		! has_privs_of_role(roleid, ROLE_PG_MANAGE_ERROR_HANDLING_SETTINGS))
+		return false;
+
 	return true;
 }
 
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 05ac06ccc9..88505dc6d0 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -129,5 +129,10 @@
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
   rolpassword => '_null_', rolvaliduntil => '_null_' },
+{ oid => '9289', oid_symbol => 'ROLE_PG_MANAGE_ERROR_HANDLING_SETTINGS',
+  rolname => 'pg_manage_error_handling_settings', rolsuper => 'f', rolinherit => 't',
+  rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
+  rolreplication => 'f', rolbypassrls => 't', rolconnlimit => '-1',
+  rolpassword => '_null_', rolvaliduntil => '_null_' },
 
 ]
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index fe1e4b0c4c..d090518b14 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -212,6 +212,7 @@ typedef enum
 #define GUC_MANAGE_QUERY_TUNING_SETTINGS	0x0200	/* 0x0100 = superuser */
 #define GUC_MANAGE_STATS_SETTINGS			0x0400
 #define GUC_MANAGE_RECOVERY_SETTINGS		0x0800
+#define GUC_MANAGE_ERROR_HANDLING_SETTINGS	0x1000
 
 /*
  * bit values in "flags" of a GUC variable
diff --git a/src/test/regress/expected/guc_privs.out b/src/test/regress/expected/guc_privs.out
index 91f28d4b75..ee6665a795 100644
--- a/src/test/regress/expected/guc_privs.out
+++ b/src/test/regress/expected/guc_privs.out
@@ -1098,3 +1098,86 @@ ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_recovery_admin;
+-- Test role pg_manage_error_handling_settings
+-- Non-superuser with privileges to configure error handling
+CREATE ROLE regress_error_handling_admin NOSUPERUSER;
+GRANT pg_manage_error_handling_settings TO regress_error_handling_admin;
+-- Perform all operations as user 'regress_error_handling_admin' --
+SET SESSION AUTHORIZATION regress_error_handling_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ERROR:  parameter "ignore_system_indexes" cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "ignore_system_indexes"
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+ERROR:  parameter "block_size" cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ERROR:  parameter "autovacuum_freeze_max_age" cannot be changed without restarting the server
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum_freeze_max_age"
+ALTER SYSTEM SET data_sync_retry = OFF;  -- ok
+ALTER SYSTEM RESET data_sync_retry;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+ERROR:  parameter "config_file" cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+RESET autovacuum;  -- fail, requires reload
+ERROR:  parameter "autovacuum" cannot be changed now
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "autovacuum"
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+RESET lc_messages;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "lc_messages"
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ERROR:  parameter "jit_debugging_support" cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "jit_debugging_support"
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_error_handling_admin has insufficient privileges
+ERROR:  permission denied to set parameter "datestyle"
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ERROR:  parameter "ssl_renegotiation_limit" cannot be changed
+ALTER SYSTEM SET exit_on_error = OFF;  -- ok
+ALTER SYSTEM RESET exit_on_error;  -- ok
+-- Finished testing role pg_manage_error_handling_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_error_handling_admin;
diff --git a/src/test/regress/sql/guc_privs.sql b/src/test/regress/sql/guc_privs.sql
index bb25b00e2a..5c21ac3a78 100644
--- a/src/test/regress/sql/guc_privs.sql
+++ b/src/test/regress/sql/guc_privs.sql
@@ -722,3 +722,56 @@ ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
 RESET statement_timeout;
 RESET SESSION AUTHORIZATION;
 DROP ROLE regress_recovery_admin;
+-- Test role pg_manage_error_handling_settings
+-- Non-superuser with privileges to configure error handling
+CREATE ROLE regress_error_handling_admin NOSUPERUSER;
+GRANT pg_manage_error_handling_settings TO regress_error_handling_admin;
+-- Perform all operations as user 'regress_error_handling_admin' --
+SET SESSION AUTHORIZATION regress_error_handling_admin;
+-- PGC_BACKEND
+SET ignore_system_indexes = OFF;  -- fail, cannot be set after connection start
+RESET ignore_system_indexes;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET ignore_system_indexes;  -- fail, regress_error_handling_admin has insufficient privileges
+-- PGC_INTERNAL
+SET block_size = 50;  -- fail, cannot be changed
+RESET block_size;  -- fail, cannot be changed
+ALTER SYSTEM SET block_size = 50;  -- fail, cannot be changed
+ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
+-- PGC_POSTMASTER
+SET autovacuum_freeze_max_age = 1000050000;  -- fail, requires restart
+RESET autovacuum_freeze_max_age;  -- fail, requires restart
+ALTER SYSTEM SET autovacuum_freeze_max_age = 1000050000;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum_freeze_max_age;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM SET data_sync_retry = OFF;  -- ok
+ALTER SYSTEM RESET data_sync_retry;  -- ok
+ALTER SYSTEM SET config_file = '/usr/local/data/postgresql.conf';  -- fail, cannot be changed
+ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
+-- PGC_SIGHUP
+SET autovacuum = OFF;  -- fail, requires reload
+RESET autovacuum;  -- fail, requires reload
+ALTER SYSTEM SET autovacuum = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET autovacuum;  -- fail, regress_error_handling_admin has insufficient privileges
+-- PGC_SUSET
+SET lc_messages = 'en_US.UTF-8';  -- fail, regress_error_handling_admin has insufficient privileges
+RESET lc_messages;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM SET lc_messages = 'en_US.UTF-8';  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET lc_messages;  -- fail, regress_error_handling_admin has insufficient privileges
+-- PGC_SU_BACKEND
+SET jit_debugging_support = OFF;  -- fail, cannot be set after connection start
+RESET jit_debugging_support;  -- fail, cannot be set after connection start
+ALTER SYSTEM SET jit_debugging_support = OFF;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET jit_debugging_support;  -- fail, regress_error_handling_admin has insufficient privileges
+-- PGC_USERSET
+SET DateStyle = 'ISO, MDY';  -- ok
+RESET DateStyle;  -- ok
+ALTER SYSTEM SET DateStyle = 'ISO, MDY';  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM RESET DateStyle;  -- fail, regress_error_handling_admin has insufficient privileges
+ALTER SYSTEM SET ssl_renegotiation_limit = 0;  -- fail, cannot be changed
+ALTER SYSTEM RESET ssl_renegotiation_limit;  -- fail, cannot be changed
+ALTER SYSTEM SET exit_on_error = OFF;  -- ok
+ALTER SYSTEM RESET exit_on_error;  -- ok
+-- Finished testing role pg_manage_error_handling_settings
+RESET statement_timeout;
+RESET SESSION AUTHORIZATION;
+DROP ROLE regress_error_handling_admin;
-- 
2.21.1 (Apple Git-122.3)