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)

