Subject: Re: GUC names in messages

From: Peter Smith <[email-masked]>
Date: Thu, 9 Nov 2023 09:53:55 +1100

On Wed, Nov 8, 2023 at 7:40 AM Peter Smith <[email-masked]> wrote:
>
> FWIW, I am halfway through doing regex checking of the PG16 source for
> all GUC names in messages to see what current styles are in use today.
>
> Not sure if those numbers will influence the decision.
>
> I hope I can post my findings today or tomorrow.
>

Here are my findings from the current PG16 source messages.

I used a regex search:
".*GUCNAME

to find how each GUCNAME is used in the messages in *.c files.

The GUC names are taken from the guc_tables.c code, so they are
grouped accordingly below.

~TOTALS:

messages where GUC names are QUOTED:
- bool = 11
- int = 11
- real = 0
- string = 10
- enum = 7
TOTAL = 39

messages where GUC names are NOT QUOTED:
- bool = 14
- int = 60
- real = 0
- string = 59
- enum = 31
TOTAL = 164

~~~

Details are in the attached file. PSA.

I've categorised them as being currently QUOTED, NOT QUOTED, and NONE
(most are not used in any messages).

Notice that NOT QUOTED is the far more common pattern, so my vote
would be just to standardise on making everything this way. I know
there was some concern raised about ambiguous words like "timezone"
and "datestyle" etc but in practice, those are rare. Also, those GUCs
are different in that they are written as camel-case (e.g.
"DateStyle") in the guc_tables.c, so if they were also written
camel-case in the messages that could remove ambiguities with normal
words. YMMV.

Anyway, I will await a verdict about what to do.

======
Kind Regards,
Peter Smith.
Fujitsu Australia

---

From: Alvaro Herrera <[email-masked]>
Date: Thu, 9 Nov 2023 12:04:21 +0100

> camel-case in the messages that could remove ambiguities with normal

Well, I think camel-casing is also a sufficient differentiator for these
identifiers not being English words.  We'd need to ensure they're always
written that way, when not quoted.  However, in cases where arbitrary
values are expanded, I don't know that they would be expanded that way,
so I would still go for quoting in that case.

There's also a few that are not camel-cased nor have any underscores --
looking at postgresql.conf.sample, we have "port", "bonjour", "ssl",
"fsync", "geqo", "jit", "autovacuum", "xmlbinary", "xmloption".  (We also
have "include", but I doubt that's ever used in an error message).  But
actually, there's more: every reloption is a candidate, and there we
have "fillfactor", "autosummarize", "fastupdate", "buffering".  So if we
want to make generic advice on how to deal with option names in error
messages, I think the wording on conditional quoting I proposed should
go in (adding CamelCase as a reason not to quote), and then we can fix
the code to match.  Looking at your list, I think the changes to make
are not too numerous.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
"Nadie está tan esclavizado como el que se cree libre no siéndolo" (Goethe)

---

From: Peter Smith <[email-masked]>
Date: Thu, 23 Nov 2023 18:27:04 +1100

> the code to match.  Looking at your list, I think the changes to make

Sorry for my delay in getting back to this thread.

PSA a patch for this work.

There may be some changes I've missed, but hopefully, this is a nudge
in the right direction.

======
Kind Regards,
Peter Smith.
Fujitsu Australia.

---

From: Michael Paquier <[email-masked]>
Date: Fri, 24 Nov 2023 12:11:19 +0900

> There may be some changes I've missed, but hopefully, this is a nudge

Thanks for spending some time on that.

    <para>
+    In messages containing configuration variable names, do not include quotes
+    when the names are visibly not English natural words, such as when they
+    have underscores or are all-uppercase or have mixed case. Otherwise, quotes
+    must be added.  Do include quotes in a message where an arbitrary variable
+    name is to be expanded.
+   </para>

That seems to describe clearly the consensus reached on the thread
(quotes for GUCs that are single terms, no quotes for names that are
obviously parameters).

In terms of messages that have predictible names, 0002 moves in the
needle in the right direction.  There seem to be more:
src/backend/postmaster/bgworker.c:  errhint("Consider increasing the
configuration parameter \"max_worker_processes\".")));
contrib/pg_prewarm/autoprewarm.c:  errhint("Consider increasing
configuration parameter \"max_worker_processes\".")));

Things like parse_and_validate_value() and set_config_option_ext()
include log strings about GUC and these use quotes.  Could these areas
be made smarter with a routine to check if quotes are applied
automatically when we have a "simple" GUC name, aka I guess made of
only lower-case characters?  This could be done with a islower() on
the string name, for instance.
--
Michael

---

From: Alvaro Herrera <[email-masked]>
Date: Fri, 24 Nov 2023 10:53:40 +0100

> Thanks for spending some time on that.

+1

> (quotes for GUCs that are single terms, no quotes for names that are

Yeah, this is pretty much the patch I proposed earlier.

> configuration parameter \"max_worker_processes\".")));

Yeah.  Also, these could be changed to have the GUC name outside the
message proper, which would reduce the total number of messages.  (But
care must be given to the word "the" there.)

> the string name, for instance.

I think we could leave these improvements for a second round.  They
don't need to hold back the improvement we already have.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
"You're _really_ hosed if the person doing the hiring doesn't understand
relational systems: you end up with a whole raft of programmers, none of
whom has had a Date with the clue stick."              (Andrew Sullivan)
https://postgr.es/m/[email-masked]

---

From: Michael Paquier <[email-masked]>
Date: Fri, 24 Nov 2023 23:01:54 +0900

> don't need to hold back the improvement we already have.

Of course, no problem here to do things one step at a time.
--
Michael

---

From: Peter Smith <[email-masked]>
Date: Mon, 27 Nov 2023 09:41:51 +1100

> configuration parameter \"max_worker_processes\".")));

Done in patch 0002

> the string name, for instance.

See what you think of patch 0003

~~

PSA v2 patches.

======
Kind Regards,
Peter Smith.
Fujitsu Australia

---

From: Peter Smith <[email-masked]>
Date: Tue, 28 Nov 2023 11:54:33 +1100

Here is patch set v3.

Patches 0001 and 0002 are unchanged from v2.

Patch 0003 now uses a "%s%s%s" format specifier with GUC_FORMAT macro
in guc.c, as recently suggested by Michael [1].

~

(Meanwhile, the MixedCase stuff is still an open question, to be
addressed in a later patch version)

======
[1] https://www.postgresql.org/message-id/ZWQVxu8zWIx64V7l%40paquier.xyz

Kind Regards,
Peter Smith.
Fujitsu Australia

---

From: Michael Paquier <[email-masked]>
Date: Thu, 30 Nov 2023 14:59:21 +0900

> Patches 0001 and 0002 are unchanged from v2.

After some grepping, I've noticed that 0002 had a mistake with
track_commit_timestamp: some alternate output of modules/commit_ts/
was not updated.  meson was able to reproduce the failure as well.

I am not sure regarding what we should do a mixed cases as well, so I
have discarded DateStyle for now, and applied the rest.

Also applied 0001 from Alvaro.

> in guc.c, as recently suggested by Michael [1].

I cannot think about a better idea as these strings need to be
translated so they need three %s.

+		if (*p == '_')
+			underscore = true;
+		else if ('a' <= *p && *p <= 'z')
+			lowercase = true;

An issue with this code is that it would forget to quote GUCs that use
dots, like the ones from an extension.  I don't really see why we
cannot just make the macro return true only if all the characters of a
GUC name is made of lower-case alpha characters?

With an extra indentation applied, I finish with the attached for
0003.
--
Michael
From 77bd6b6f58ab1b0671f6afa12dc4e00900b456a8 Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email-masked]>
Date: Thu, 30 Nov 2023 14:58:32 +0900
Subject: [PATCH v4] GUC names - maybe add quotes

---
 src/backend/utils/misc/guc.c                  | 278 ++++++++++++------
 .../expected/test_oat_hooks.out               |  16 +-
 .../unsafe_tests/expected/guc_privs.out       |  58 ++--
 .../unsafe_tests/expected/rolenames.out       |   2 +-
 src/test/regress/expected/compression.out     |   4 +-
 src/test/regress/expected/compression_1.out   |   6 +-
 src/test/regress/expected/create_am.out       |   4 +-
 src/test/regress/expected/guc.out             |  30 +-
 src/test/regress/expected/password.out        |   4 +-
 src/test/regress/expected/subscription.out    |   2 +-
 src/test/regress/expected/transactions.out    |   8 +-
 contrib/auto_explain/t/001_auto_explain.pl    |   2 +-
 src/pl/plperl/expected/plperl_init.out        |   4 +-
 13 files changed, 259 insertions(+), 159 deletions(-)

diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e76c083003..aad72db9e5 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -265,6 +265,30 @@ static bool call_string_check_hook(struct config_string *conf, char **newval,
 static bool call_enum_check_hook(struct config_enum *conf, int *newval,
 								 void **extra, GucSource source, int elevel);
 
+/* Macro for handling optional quotes around GUC names */
+#define GUC_FORMAT(s)\
+	quotes_needed_for_GUC_name(s) ? "\"" : "",\
+	s,\
+	quotes_needed_for_GUC_name(s) ? "\"" : ""
+
+/*
+ * Return whether the GUC name should be enclosed in double-quotes.
+ *
+ * Quoting is intended for names which could be mistaken for normal English
+ * words.  Quotes are only applied to GUC names that are written entirely with
+ * lower-case alphabetical characters.
+ */
+static bool
+quotes_needed_for_GUC_name(const char *name)
+{
+	for (const char *p = name; *p; p++)
+	{
+		if ('a' > *p || *p > 'z')
+			return false;
+	}
+
+	return true;
+}
 
 /*
  * This function handles both actual config file (re)loads and execution of
@@ -420,8 +444,9 @@ ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
 			/* Invalid non-custom variable, so complain */
 			ereport(elevel,
 					(errcode(ERRCODE_UNDEFINED_OBJECT),
-					 errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
-							item->name,
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("unrecognized configuration parameter %s%s%s in file \"%s\" line %d",
+							GUC_FORMAT(item->name),
 							item->filename, item->sourceline)));
 			item->errmsg = pstrdup("unrecognized configuration parameter");
 			error = true;
@@ -460,10 +485,13 @@ ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
 			gconf->status |= GUC_PENDING_RESTART;
 			ereport(elevel,
 					(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-					 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-							gconf->name)));
-			record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
-											  gconf->name),
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+							GUC_FORMAT(gconf->name))));
+			record_config_file_error(
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+									 psprintf("parameter %s%s%s cannot be changed without restarting the server",
+											  GUC_FORMAT(gconf->name)),
 									 NULL, 0,
 									 &head, &tail);
 			error = true;
@@ -496,8 +524,9 @@ ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
 			/* Log the change if appropriate */
 			if (context == PGC_SIGHUP)
 				ereport(elevel,
-						(errmsg("parameter \"%s\" removed from configuration file, reset to default",
-								gconf->name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						(errmsg("parameter %s%s%s removed from configuration file, reset to default",
+								GUC_FORMAT(gconf->name))));
 		}
 	}
 
@@ -561,8 +590,10 @@ ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
 					post_value = "";
 				if (strcmp(pre_value, post_value) != 0)
 					ereport(elevel,
-							(errmsg("parameter \"%s\" changed to \"%s\"",
-									item->name, item->value)));
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							(errmsg("parameter %s%s%s changed to \"%s\"",
+									GUC_FORMAT(item->name),
+									item->value)));
 			}
 			item->applied = true;
 		}
@@ -1129,8 +1160,9 @@ assignable_custom_variable_name(const char *name, bool skip_errors, int elevel)
 			if (!skip_errors)
 				ereport(elevel,
 						(errcode(ERRCODE_INVALID_NAME),
-						 errmsg("invalid configuration parameter name \"%s\"",
-								name),
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("invalid configuration parameter name %s%s%s",
+								GUC_FORMAT(name)),
 						 errdetail("Custom parameter names must be two or more simple identifiers separated by dots.")));
 			return false;
 		}
@@ -1145,8 +1177,9 @@ assignable_custom_variable_name(const char *name, bool skip_errors, int elevel)
 				if (!skip_errors)
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_NAME),
-							 errmsg("invalid configuration parameter name \"%s\"",
-									name),
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("invalid configuration parameter name %s%s%s",
+									GUC_FORMAT(name)),
 							 errdetail("\"%s\" is a reserved prefix.",
 									   rcprefix)));
 				return false;
@@ -1160,8 +1193,9 @@ assignable_custom_variable_name(const char *name, bool skip_errors, int elevel)
 	if (!skip_errors)
 		ereport(elevel,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("unrecognized configuration parameter \"%s\"",
-						name)));
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("unrecognized configuration parameter %s%s%s",
+						GUC_FORMAT(name))));
 	return false;
 }
 
@@ -1270,8 +1304,9 @@ find_option(const char *name, bool create_placeholders, bool skip_errors,
 	if (!skip_errors)
 		ereport(elevel,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("unrecognized configuration parameter \"%s\"",
-						name)));
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("unrecognized configuration parameter %s%s%s",
+						GUC_FORMAT(name))));
 	return NULL;
 }
 
@@ -3125,8 +3160,9 @@ parse_and_validate_value(struct config_generic *record,
 				{
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("parameter \"%s\" requires a Boolean value",
-									name)));
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("parameter %s%s%s requires a Boolean value",
+									GUC_FORMAT(name))));
 					return false;
 				}
 
@@ -3145,8 +3181,9 @@ parse_and_validate_value(struct config_generic *record,
 				{
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for parameter \"%s\": \"%s\"",
-									name, value),
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+									GUC_FORMAT(name), value),
 							 hintmsg ? errhint("%s", _(hintmsg)) : 0));
 					return false;
 				}
@@ -3157,11 +3194,12 @@ parse_and_validate_value(struct config_generic *record,
 
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("%d%s%s is outside the valid range for parameter \"%s\" (%d .. %d)",
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("%d%s%s is outside the valid range for parameter %s%s%s (%d .. %d)",
 									newval->intval,
 									unit ? " " : "",
 									unit ? unit : "",
-									name,
+									GUC_FORMAT(name),
 									conf->min, conf->max)));
 					return false;
 				}
@@ -3181,8 +3219,9 @@ parse_and_validate_value(struct config_generic *record,
 				{
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for parameter \"%s\": \"%s\"",
-									name, value),
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+									GUC_FORMAT(name), value),
 							 hintmsg ? errhint("%s", _(hintmsg)) : 0));
 					return false;
 				}
@@ -3193,11 +3232,12 @@ parse_and_validate_value(struct config_generic *record,
 
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("%g%s%s is outside the valid range for parameter \"%s\" (%g .. %g)",
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("%g%s%s is outside the valid range for parameter %s%s%s (%g .. %g)",
 									newval->realval,
 									unit ? " " : "",
 									unit ? unit : "",
-									name,
+									GUC_FORMAT(name),
 									conf->min, conf->max)));
 					return false;
 				}
@@ -3251,8 +3291,9 @@ parse_and_validate_value(struct config_generic *record,
 
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for parameter \"%s\": \"%s\"",
-									name, value),
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+									GUC_FORMAT(name), value),
 							 hintmsg ? errhint("%s", _(hintmsg)) : 0));
 
 					if (hintmsg)
@@ -3410,8 +3451,9 @@ set_config_option_ext(const char *name, const char *value,
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-						 errmsg("parameter \"%s\" cannot be changed",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("parameter %s%s%s cannot be changed",
+								GUC_FORMAT(name))));
 				return 0;
 			}
 			break;
@@ -3433,8 +3475,9 @@ set_config_option_ext(const char *name, const char *value,
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-						 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+								GUC_FORMAT(name))));
 				return 0;
 			}
 			break;
@@ -3443,8 +3486,9 @@ set_config_option_ext(const char *name, const char *value,
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-						 errmsg("parameter \"%s\" cannot be changed now",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("parameter %s%s%s cannot be changed now",
+								GUC_FORMAT(name))));
 				return 0;
 			}
 
@@ -3470,8 +3514,9 @@ set_config_option_ext(const char *name, const char *value,
 					/* No granted privilege */
 					ereport(elevel,
 							(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-							 errmsg("permission denied to set parameter \"%s\"",
-									name)));
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("permission denied to set parameter %s%s%s",
+									GUC_FORMAT(name))));
 					return 0;
 				}
 			}
@@ -3508,8 +3553,9 @@ set_config_option_ext(const char *name, const char *value,
 			{
 				ereport(elevel,
 						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-						 errmsg("parameter \"%s\" cannot be set after connection start",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("parameter %s%s%s cannot be set after connection start",
+								GUC_FORMAT(name))));
 				return 0;
 			}
 			break;
@@ -3528,8 +3574,9 @@ set_config_option_ext(const char *name, const char *value,
 					/* No granted privilege */
 					ereport(elevel,
 							(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-							 errmsg("permission denied to set parameter \"%s\"",
-									name)));
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("permission denied to set parameter %s%s%s",
+									GUC_FORMAT(name))));
 					return 0;
 				}
 			}
@@ -3567,16 +3614,18 @@ set_config_option_ext(const char *name, const char *value,
 			 */
 			ereport(elevel,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-					 errmsg("cannot set parameter \"%s\" within security-definer function",
-							name)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("cannot set parameter %s%s%s within security-definer function",
+							GUC_FORMAT(name))));
 			return 0;
 		}
 		if (InSecurityRestrictedOperation())
 		{
 			ereport(elevel,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-					 errmsg("cannot set parameter \"%s\" within security-restricted operation",
-							name)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("cannot set parameter %s%s%s within security-restricted operation",
+							GUC_FORMAT(name))));
 			return 0;
 		}
 	}
@@ -3588,15 +3637,18 @@ set_config_option_ext(const char *name, const char *value,
 		{
 			ereport(elevel,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("parameter \"%s\" cannot be reset", name)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("parameter %s%s%s cannot be reset",
+							GUC_FORMAT(name))));
 			return 0;
 		}
 		if (action == GUC_ACTION_SAVE)
 		{
 			ereport(elevel,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("parameter \"%s\" cannot be set locally in functions",
-							name)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("parameter %s%s%s cannot be set locally in functions",
+							GUC_FORMAT(name))));
 			return 0;
 		}
 	}
@@ -3621,8 +3673,8 @@ set_config_option_ext(const char *name, const char *value,
 	{
 		if (changeVal && !makeDefault)
 		{
-			elog(DEBUG3, "\"%s\": setting ignored because previous source is higher priority",
-				 name);
+			elog(DEBUG3, "%s%s%s: setting ignored because previous source is higher priority",
+				 GUC_FORMAT(name));
 			return -1;
 		}
 		changeVal = false;
@@ -3673,8 +3725,13 @@ set_config_option_ext(const char *name, const char *value,
 						record->status |= GUC_PENDING_RESTART;
 						ereport(elevel,
 								(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-								 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-										name)));
+
+						/*
+						 * translator: %s%s%s is for an optionally quoted GUC
+						 * name
+						 */
+								 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+										GUC_FORMAT(name))));
 						return 0;
 					}
 					record->status &= ~GUC_PENDING_RESTART;
@@ -3771,8 +3828,13 @@ set_config_option_ext(const char *name, const char *value,
 						record->status |= GUC_PENDING_RESTART;
 						ereport(elevel,
 								(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-								 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-										name)));
+
+						/*
+						 * translator: %s%s%s is for an optionally quoted GUC
+						 * name
+						 */
+								 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+										GUC_FORMAT(name))));
 						return 0;
 					}
 					record->status &= ~GUC_PENDING_RESTART;
@@ -3869,8 +3931,13 @@ set_config_option_ext(const char *name, const char *value,
 						record->status |= GUC_PENDING_RESTART;
 						ereport(elevel,
 								(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-								 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-										name)));
+
+						/*
+						 * translator: %s%s%s is for an optionally quoted GUC
+						 * name
+						 */
+								 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+										GUC_FORMAT(name))));
 						return 0;
 					}
 					record->status &= ~GUC_PENDING_RESTART;
@@ -3993,8 +4060,13 @@ set_config_option_ext(const char *name, const char *value,
 						record->status |= GUC_PENDING_RESTART;
 						ereport(elevel,
 								(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-								 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-										name)));
+
+						/*
+						 * translator: %s%s%s is for an optionally quoted GUC
+						 * name
+						 */
+								 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+										GUC_FORMAT(name))));
 						return 0;
 					}
 					record->status &= ~GUC_PENDING_RESTART;
@@ -4096,8 +4168,13 @@ set_config_option_ext(const char *name, const char *value,
 						record->status |= GUC_PENDING_RESTART;
 						ereport(elevel,
 								(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-								 errmsg("parameter \"%s\" cannot be changed without restarting the server",
-										name)));
+
+						/*
+						 * translator: %s%s%s is for an optionally quoted GUC
+						 * name
+						 */
+								 errmsg("parameter %s%s%s cannot be changed without restarting the server",
+										GUC_FORMAT(name))));
 						return 0;
 					}
 					record->status &= ~GUC_PENDING_RESTART;
@@ -4238,7 +4315,9 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
 		!ConfigOptionIsVisible(record))
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("permission denied to examine \"%s\"", name),
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("permission denied to examine %s%s%s",
+						GUC_FORMAT(name)),
 				 errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
 						   "pg_read_all_settings")));
 
@@ -4534,8 +4613,9 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 			if (aclresult != ACLCHECK_OK)
 				ereport(ERROR,
 						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-						 errmsg("permission denied to set parameter \"%s\"",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("permission denied to set parameter %s%s%s",
+								GUC_FORMAT(name))));
 		}
 	}
 
@@ -4559,8 +4639,9 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 				(record->flags & GUC_DISALLOW_IN_AUTO_FILE))
 				ereport(ERROR,
 						(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
-						 errmsg("parameter \"%s\" cannot be changed",
-								name)));
+				/* translator: %s%s%s is for an optionally quoted GUC name */
+						 errmsg("parameter %s%s%s cannot be changed",
+								GUC_FORMAT(name))));
 
 			/*
 			 * If a value is specified, verify that it's sane.
@@ -4575,8 +4656,9 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
 											  &newval, &newextra))
 					ereport(ERROR,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-							 errmsg("invalid value for parameter \"%s\": \"%s\"",
-									name, value)));
+					/* translator: %s%s%s is for an optionally quoted GUC name */
+							 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+									GUC_FORMAT(name), value)));
 
 				if (record->vartype == PGC_STRING && newval.stringval != NULL)
 					guc_free(newval.stringval);
@@ -4830,7 +4912,9 @@ define_custom_variable(struct config_generic *variable)
 	if ((hentry->gucvar->flags & GUC_CUSTOM_PLACEHOLDER) == 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INTERNAL_ERROR),
-				 errmsg("attempt to redefine parameter \"%s\"", name)));
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("attempt to redefine parameter %s%s%s",
+						GUC_FORMAT(name))));
 
 	Assert(hentry->gucvar->vartype == PGC_STRING);
 	pHolder = (struct config_string *) hentry->gucvar;
@@ -5169,8 +5253,9 @@ MarkGUCPrefixReserved(const char *className)
 		{
 			ereport(WARNING,
 					(errcode(ERRCODE_INVALID_NAME),
-					 errmsg("invalid configuration parameter name \"%s\", removing it",
-							var->name),
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("invalid configuration parameter name %s%s%s, removing it",
+							GUC_FORMAT(var->name)),
 					 errdetail("\"%s\" is now a reserved prefix.",
 							   className)));
 			/* Remove it from the hash table */
@@ -5313,7 +5398,9 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
 	if (!ConfigOptionIsVisible(record))
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("permission denied to examine \"%s\"", name),
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("permission denied to examine %s%s%s",
+						GUC_FORMAT(name)),
 				 errdetail("Only roles with privileges of the \"%s\" role may examine this parameter.",
 						   "pg_read_all_settings")));
 
@@ -5639,7 +5726,8 @@ read_nondefault_variables(void)
 			break;
 
 		if (find_option(varname, true, false, FATAL) == NULL)
-			elog(FATAL, "failed to locate variable \"%s\" in exec config params file", varname);
+			elog(FATAL, "failed to locate variable %s%s%s in exec config params file",
+				 GUC_FORMAT(varname));
 
 		if ((varvalue = read_string_with_null(fp)) == NULL)
 			elog(FATAL, "invalid format of exec config params file");
@@ -6048,8 +6136,9 @@ guc_restore_error_context_callback(void *arg)
 	char	  **error_context_name_and_value = (char **) arg;
 
 	if (error_context_name_and_value)
-		errcontext("while setting parameter \"%s\" to \"%s\"",
-				   error_context_name_and_value[0],
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+		errcontext("while setting parameter %s%s%s to \"%s\"",
+				   GUC_FORMAT(error_context_name_and_value[0]),
 				   error_context_name_and_value[1]);
 }
 
@@ -6217,7 +6306,9 @@ RestoreGUCState(void *gucstate)
 		if (result <= 0)
 			ereport(ERROR,
 					(errcode(ERRCODE_INTERNAL_ERROR),
-					 errmsg("parameter \"%s\" could not be set", varname)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("parameter %s%s%s could not be set",
+							GUC_FORMAT(varname))));
 		if (varsourcefile[0])
 			set_config_sourcefile(varname, varsourcefile, varsourceline);
 		error_context_callback.arg = NULL;
@@ -6307,8 +6398,9 @@ TransformGUCArray(ArrayType *array, List **names, List **values)
 		{
 			ereport(WARNING,
 					(errcode(ERRCODE_SYNTAX_ERROR),
-					 errmsg("could not parse setting for parameter \"%s\"",
-							name)));
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("could not parse setting for parameter %s%s%s",
+							GUC_FORMAT(name))));
 			pfree(name);
 			continue;
 		}
@@ -6625,7 +6717,9 @@ validate_option_array_item(const char *name, const char *value,
 			return false;
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 errmsg("permission denied to set parameter \"%s\"", name)));
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("permission denied to set parameter %s%s%s",
+						GUC_FORMAT(name))));
 	}
 
 	/* manual permissions check so we can avoid an error being thrown */
@@ -6689,8 +6783,9 @@ call_bool_check_hook(struct config_bool *conf, bool *newval, void **extra,
 				(errcode(GUC_check_errcode_value),
 				 GUC_check_errmsg_string ?
 				 errmsg_internal("%s", GUC_check_errmsg_string) :
-				 errmsg("invalid value for parameter \"%s\": %d",
-						conf->gen.name, (int) *newval),
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("invalid value for parameter %s%s%s: %d",
+						GUC_FORMAT(conf->gen.name), (int) *newval),
 				 GUC_check_errdetail_string ?
 				 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
 				 GUC_check_errhint_string ?
@@ -6723,8 +6818,9 @@ call_int_check_hook(struct config_int *conf, int *newval, void **extra,
 				(errcode(GUC_check_errcode_value),
 				 GUC_check_errmsg_string ?
 				 errmsg_internal("%s", GUC_check_errmsg_string) :
-				 errmsg("invalid value for parameter \"%s\": %d",
-						conf->gen.name, *newval),
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("invalid value for parameter %s%s%s: %d",
+						GUC_FORMAT(conf->gen.name), *newval),
 				 GUC_check_errdetail_string ?
 				 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
 				 GUC_check_errhint_string ?
@@ -6757,8 +6853,9 @@ call_real_check_hook(struct config_real *conf, double *newval, void **extra,
 				(errcode(GUC_check_errcode_value),
 				 GUC_check_errmsg_string ?
 				 errmsg_internal("%s", GUC_check_errmsg_string) :
-				 errmsg("invalid value for parameter \"%s\": %g",
-						conf->gen.name, *newval),
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("invalid value for parameter %s%s%s: %g",
+						GUC_FORMAT(conf->gen.name), *newval),
 				 GUC_check_errdetail_string ?
 				 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
 				 GUC_check_errhint_string ?
@@ -6800,8 +6897,10 @@ call_string_check_hook(struct config_string *conf, char **newval, void **extra,
 					(errcode(GUC_check_errcode_value),
 					 GUC_check_errmsg_string ?
 					 errmsg_internal("%s", GUC_check_errmsg_string) :
-					 errmsg("invalid value for parameter \"%s\": \"%s\"",
-							conf->gen.name, *newval ? *newval : ""),
+			/* translator: %s%s%s is for an optionally quoted GUC name */
+					 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+							GUC_FORMAT(conf->gen.name),
+							*newval ? *newval : ""),
 					 GUC_check_errdetail_string ?
 					 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
 					 GUC_check_errhint_string ?
@@ -6841,8 +6940,9 @@ call_enum_check_hook(struct config_enum *conf, int *newval, void **extra,
 				(errcode(GUC_check_errcode_value),
 				 GUC_check_errmsg_string ?
 				 errmsg_internal("%s", GUC_check_errmsg_string) :
-				 errmsg("invalid value for parameter \"%s\": \"%s\"",
-						conf->gen.name,
+		/* translator: %s%s%s is for an optionally quoted GUC name */
+				 errmsg("invalid value for parameter %s%s%s: \"%s\"",
+						GUC_FORMAT(conf->gen.name),
 						config_enum_lookup_by_value(conf, *newval)),
 				 GUC_check_errdetail_string ?
 				 errdetail_internal("%s", GUC_check_errdetail_string) : 0,
diff --git a/src/test/modules/test_oat_hooks/expected/test_oat_hooks.out b/src/test/modules/test_oat_hooks/expected/test_oat_hooks.out
index f80373aecc..042569d27a 100644
--- a/src/test/modules/test_oat_hooks/expected/test_oat_hooks.out
+++ b/src/test/modules/test_oat_hooks/expected/test_oat_hooks.out
@@ -180,10 +180,10 @@ NOTICE:  in object_access_hook_str: non-superuser finished alter (subId=0x1000,
 NOTICE:  in process utility: non-superuser finished RESET
 ALTER SYSTEM SET work_mem = 8192;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "work_mem"
+ERROR:  permission denied to set parameter work_mem
 ALTER SYSTEM RESET work_mem;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "work_mem"
+ERROR:  permission denied to set parameter work_mem
 SET test_oat_hooks.user_var1 = true;
 NOTICE:  in process utility: non-superuser attempting SET
 NOTICE:  in object_access_hook_str: non-superuser attempting alter (subId=0x1000, set) [test_oat_hooks.user_var1]
@@ -191,13 +191,13 @@ NOTICE:  in object_access_hook_str: non-superuser finished alter (subId=0x1000,
 NOTICE:  in process utility: non-superuser finished SET
 SET test_oat_hooks.super_var1 = true;
 NOTICE:  in process utility: non-superuser attempting SET
-ERROR:  permission denied to set parameter "test_oat_hooks.super_var1"
+ERROR:  permission denied to set parameter test_oat_hooks.super_var1
 ALTER SYSTEM SET test_oat_hooks.user_var1 = true;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "test_oat_hooks.user_var1"
+ERROR:  permission denied to set parameter test_oat_hooks.user_var1
 ALTER SYSTEM SET test_oat_hooks.super_var1 = true;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "test_oat_hooks.super_var1"
+ERROR:  permission denied to set parameter test_oat_hooks.super_var1
 SET test_oat_hooks.user_var2 = true;
 NOTICE:  in process utility: non-superuser attempting SET
 NOTICE:  in object_access_hook_str: non-superuser attempting alter (subId=0x1000, set) [test_oat_hooks.user_var2]
@@ -205,13 +205,13 @@ NOTICE:  in object_access_hook_str: non-superuser finished alter (subId=0x1000,
 NOTICE:  in process utility: non-superuser finished SET
 SET test_oat_hooks.super_var2 = true;
 NOTICE:  in process utility: non-superuser attempting SET
-ERROR:  permission denied to set parameter "test_oat_hooks.super_var2"
+ERROR:  permission denied to set parameter test_oat_hooks.super_var2
 ALTER SYSTEM SET test_oat_hooks.user_var2 = true;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "test_oat_hooks.user_var2"
+ERROR:  permission denied to set parameter test_oat_hooks.user_var2
 ALTER SYSTEM SET test_oat_hooks.super_var2 = true;
 NOTICE:  in process utility: non-superuser attempting ALTER SYSTEM
-ERROR:  permission denied to set parameter "test_oat_hooks.super_var2"
+ERROR:  permission denied to set parameter test_oat_hooks.super_var2
 RESET SESSION AUTHORIZATION;
 NOTICE:  in process utility: non-superuser attempting RESET
 NOTICE:  in object_access_hook_str: superuser attempting alter (subId=0x1000, set) [session_authorization]
diff --git a/src/test/modules/unsafe_tests/expected/guc_privs.out b/src/test/modules/unsafe_tests/expected/guc_privs.out
index 6c0ad89834..6c594a4b40 100644
--- a/src/test/modules/unsafe_tests/expected/guc_privs.out
+++ b/src/test/modules/unsafe_tests/expected/guc_privs.out
@@ -8,31 +8,31 @@ CREATE ROLE regress_admin SUPERUSER;
 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
+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
+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
+ERROR:  parameter block_size cannot be changed
 RESET block_size;  -- fail, cannot be changed
-ERROR:  parameter "block_size" 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
+ERROR:  parameter block_size cannot be changed
 ALTER SYSTEM RESET block_size;  -- fail, cannot be changed
-ERROR:  parameter "block_size" 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
+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
+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
+ERROR:  parameter config_file cannot be changed
 ALTER SYSTEM RESET config_file;  -- fail, cannot be changed
-ERROR:  parameter "config_file" 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
@@ -47,9 +47,9 @@ ALTER SYSTEM SET lc_messages = 'C';  -- 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
+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
+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
@@ -58,9 +58,9 @@ 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
+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
+ERROR:  parameter ssl_renegotiation_limit cannot be changed
 -- Finished testing superuser
 -- Create non-superuser with privileges to configure host resource usage
 CREATE ROLE regress_host_resource_admin NOSUPERUSER;
@@ -224,7 +224,7 @@ SELECT 1 FROM pg_parameter_acl WHERE parname = 'none.such';
 ALTER SYSTEM SET none.such = 'whiz bang';
 -- None of the above should have created a placeholder GUC for none.such.
 SHOW none.such;  -- error
-ERROR:  unrecognized configuration parameter "none.such"
+ERROR:  unrecognized configuration parameter none.such
 -- However, if we reload ...
 SELECT pg_reload_conf();
  pg_reload_conf 
@@ -244,7 +244,7 @@ SHOW none.such;
 
 -- Can't grant on a non-existent core GUC.
 GRANT ALL ON PARAMETER no_such_guc TO regress_host_resource_admin;  -- fail
-ERROR:  unrecognized configuration parameter "no_such_guc"
+ERROR:  unrecognized configuration parameter no_such_guc
 -- Initially there are no privileges and no catalog entry for this GUC.
 SELECT has_parameter_privilege('regress_host_resource_admin', 'enable_material', 'SET');
  has_parameter_privilege 
@@ -446,17 +446,17 @@ ALTER ROLE regress_host_resource_admin SET lc_messages = 'C';
 SET SESSION AUTHORIZATION regress_host_resource_admin;
 ALTER SYSTEM SET autovacuum_work_mem = 32;  -- ok, privileges have been granted
 ALTER SYSTEM SET ignore_system_indexes = OFF;  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "ignore_system_indexes"
+ERROR:  permission denied to set parameter ignore_system_indexes
 ALTER SYSTEM RESET autovacuum_multixact_freeze_max_age;  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "autovacuum_multixact_freeze_max_age"
+ERROR:  permission denied to set parameter autovacuum_multixact_freeze_max_age
 SET jit_provider = 'llvmjit';  -- fail, insufficient privileges
-ERROR:  parameter "jit_provider" cannot be changed without restarting the server
+ERROR:  parameter jit_provider cannot be changed without restarting the server
 SELECT set_config ('jit_provider', 'llvmjit', true); -- fail, insufficient privileges
-ERROR:  parameter "jit_provider" cannot be changed without restarting the server
+ERROR:  parameter jit_provider cannot be changed without restarting the server
 ALTER SYSTEM SET shared_buffers = 50;  -- ok
 ALTER SYSTEM RESET shared_buffers;  -- ok
 SET autovacuum_work_mem = 50;  -- cannot be changed now
-ERROR:  parameter "autovacuum_work_mem" cannot be changed now
+ERROR:  parameter autovacuum_work_mem cannot be changed now
 ALTER SYSTEM RESET temp_file_limit;  -- ok
 SET TimeZone = 'Europe/Helsinki';  -- ok
 RESET TimeZone;  -- ok
@@ -465,13 +465,13 @@ RESET max_stack_depth;  -- ok, privileges have been granted
 ALTER SYSTEM SET max_stack_depth = '100kB';  -- ok, privileges have been granted
 ALTER SYSTEM RESET max_stack_depth;  -- ok, privileges have been granted
 SET lc_messages = 'C';  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "lc_messages"
+ERROR:  permission denied to set parameter lc_messages
 RESET lc_messages;  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "lc_messages"
+ERROR:  permission denied to set parameter lc_messages
 ALTER SYSTEM SET lc_messages = 'C';  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "lc_messages"
+ERROR:  permission denied to set parameter lc_messages
 ALTER SYSTEM RESET lc_messages;  -- fail, insufficient privileges
-ERROR:  permission denied to set parameter "lc_messages"
+ERROR:  permission denied to set parameter lc_messages
 SELECT set_config ('temp_buffers', '8192', false); -- ok
  set_config 
 ------------
@@ -482,9 +482,9 @@ ALTER SYSTEM RESET autovacuum_work_mem;  -- ok, privileges have been granted
 ALTER SYSTEM RESET ALL;  -- fail, insufficient privileges
 ERROR:  permission denied to perform ALTER SYSTEM RESET ALL
 ALTER SYSTEM SET none.such2 = 'whiz bang';  -- fail, not superuser
-ERROR:  permission denied to set parameter "none.such2"
+ERROR:  permission denied to set parameter none.such2
 ALTER ROLE regress_host_resource_admin SET lc_messages = 'POSIX';  -- fail
-ERROR:  permission denied to set parameter "lc_messages"
+ERROR:  permission denied to set parameter lc_messages
 ALTER ROLE regress_host_resource_admin SET max_stack_depth = '1MB';  -- ok
 SELECT setconfig FROM pg_db_role_setting
   WHERE setrole = 'regress_host_resource_admin'::regrole;
@@ -537,7 +537,7 @@ DROP ROLE regress_host_resource_admin;  -- ok
 CREATE ROLE regress_host_resource_admin NOSUPERUSER;
 SET SESSION AUTHORIZATION regress_host_resource_admin;
 ALTER SYSTEM SET autovacuum_work_mem = 32;  -- fail, privileges not yet granted
-ERROR:  permission denied to set parameter "autovacuum_work_mem"
+ERROR:  permission denied to set parameter autovacuum_work_mem
 SET SESSION AUTHORIZATION regress_admin;
 GRANT SET, ALTER SYSTEM ON PARAMETER
     autovacuum_work_mem, hash_mem_multiplier, max_stack_depth,
@@ -554,7 +554,7 @@ privileges for parameter work_mem
 DROP OWNED BY regress_host_resource_admin RESTRICT; -- cascade should not be needed
 SET SESSION AUTHORIZATION regress_host_resource_admin;
 ALTER SYSTEM SET autovacuum_work_mem = 32;  -- fail, "drop owned" has dropped privileges
-ERROR:  permission denied to set parameter "autovacuum_work_mem"
+ERROR:  permission denied to set parameter autovacuum_work_mem
 SET SESSION AUTHORIZATION regress_admin;
 DROP ROLE regress_host_resource_admin;  -- ok
 -- Check that "reassign owned" doesn't affect privileges
diff --git a/src/test/modules/unsafe_tests/expected/rolenames.out b/src/test/modules/unsafe_tests/expected/rolenames.out
index 61396b2a80..21d2bac322 100644
--- a/src/test/modules/unsafe_tests/expected/rolenames.out
+++ b/src/test/modules/unsafe_tests/expected/rolenames.out
@@ -1077,7 +1077,7 @@ SHOW session_preload_libraries;
 SET SESSION AUTHORIZATION regress_role_nopriv;
 -- fails with role not member of pg_read_all_settings
 SHOW session_preload_libraries;
-ERROR:  permission denied to examine "session_preload_libraries"
+ERROR:  permission denied to examine session_preload_libraries
 DETAIL:  Only roles with privileges of the "pg_read_all_settings" role may examine this parameter.
 RESET SESSION AUTHORIZATION;
 ERROR:  current transaction is aborted, commands ignored until end of transaction block
diff --git a/src/test/regress/expected/compression.out b/src/test/regress/expected/compression.out
index 834b7555cb..7426504e20 100644
--- a/src/test/regress/expected/compression.out
+++ b/src/test/regress/expected/compression.out
@@ -234,10 +234,10 @@ ERROR:  column "f1" has a compression method conflict
 DETAIL:  pglz versus lz4
 -- test default_toast_compression GUC
 SET default_toast_compression = '';
-ERROR:  invalid value for parameter "default_toast_compression": ""
+ERROR:  invalid value for parameter default_toast_compression: ""
 HINT:  Available values: pglz, lz4.
 SET default_toast_compression = 'I do not exist compression';
-ERROR:  invalid value for parameter "default_toast_compression": "I do not exist compression"
+ERROR:  invalid value for parameter default_toast_compression: "I do not exist compression"
 HINT:  Available values: pglz, lz4.
 SET default_toast_compression = 'lz4';
 SET default_toast_compression = 'pglz';
diff --git a/src/test/regress/expected/compression_1.out b/src/test/regress/expected/compression_1.out
index ddcd137c49..5234e47b44 100644
--- a/src/test/regress/expected/compression_1.out
+++ b/src/test/regress/expected/compression_1.out
@@ -225,13 +225,13 @@ ERROR:  column "f1" has a compression method conflict
 DETAIL:  pglz versus lz4
 -- test default_toast_compression GUC
 SET default_toast_compression = '';
-ERROR:  invalid value for parameter "default_toast_compression": ""
+ERROR:  invalid value for parameter default_toast_compression: ""
 HINT:  Available values: pglz.
 SET default_toast_compression = 'I do not exist compression';
-ERROR:  invalid value for parameter "default_toast_compression": "I do not exist compression"
+ERROR:  invalid value for parameter default_toast_compression: "I do not exist compression"
 HINT:  Available values: pglz.
 SET default_toast_compression = 'lz4';
-ERROR:  invalid value for parameter "default_toast_compression": "lz4"
+ERROR:  invalid value for parameter default_toast_compression: "lz4"
 HINT:  Available values: pglz.
 SET default_toast_compression = 'pglz';
 -- test alter compression method
diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out
index b50293d514..afa11a6dc9 100644
--- a/src/test/regress/expected/create_am.out
+++ b/src/test/regress/expected/create_am.out
@@ -112,11 +112,11 @@ COMMIT;
 --
 -- prevent empty values
 SET default_table_access_method = '';
-ERROR:  invalid value for parameter "default_table_access_method": ""
+ERROR:  invalid value for parameter default_table_access_method: ""
 DETAIL:  default_table_access_method cannot be empty.
 -- prevent nonexistent values
 SET default_table_access_method = 'I do not exist AM';
-ERROR:  invalid value for parameter "default_table_access_method": "I do not exist AM"
+ERROR:  invalid value for parameter default_table_access_method: "I do not exist AM"
 DETAIL:  Table access method "I do not exist AM" does not exist.
 -- prevent setting it to an index AM
 SET default_table_access_method = 'btree';
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 127c953297..95b2414bd1 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -508,15 +508,15 @@ SELECT '2006-08-13 12:34:56'::timestamptz;
 
 -- Test some simple error cases
 SET seq_page_cost TO 'NaN';
-ERROR:  invalid value for parameter "seq_page_cost": "NaN"
+ERROR:  invalid value for parameter seq_page_cost: "NaN"
 SET vacuum_cost_delay TO '10s';
-ERROR:  10000 ms is outside the valid range for parameter "vacuum_cost_delay" (0 .. 100)
+ERROR:  10000 ms is outside the valid range for parameter vacuum_cost_delay (0 .. 100)
 SET no_such_variable TO 42;
-ERROR:  unrecognized configuration parameter "no_such_variable"
+ERROR:  unrecognized configuration parameter no_such_variable
 -- Test "custom" GUCs created on the fly (which aren't really an
 -- intended feature, but many people use them).
 SHOW custom.my_guc;  -- error, not known yet
-ERROR:  unrecognized configuration parameter "custom.my_guc"
+ERROR:  unrecognized configuration parameter custom.my_guc
 SET custom.my_guc = 42;
 SHOW custom.my_guc;
  custom.my_guc 
@@ -539,26 +539,26 @@ SHOW custom.my.qualified.guc;
 (1 row)
 
 SET custom."bad-guc" = 42;  -- disallowed because -c cannot set this name
-ERROR:  invalid configuration parameter name "custom.bad-guc"
+ERROR:  invalid configuration parameter name custom.bad-guc
 DETAIL:  Custom parameter names must be two or more simple identifiers separated by dots.
 SHOW custom."bad-guc";
-ERROR:  unrecognized configuration parameter "custom.bad-guc"
+ERROR:  unrecognized configuration parameter custom.bad-guc
 SET special."weird name" = 'foo';  -- could be allowed, but we choose not to
-ERROR:  invalid configuration parameter name "special.weird name"
+ERROR:  invalid configuration parameter name special.weird name
 DETAIL:  Custom parameter names must be two or more simple identifiers separated by dots.
 SHOW special."weird name";
-ERROR:  unrecognized configuration parameter "special.weird name"
+ERROR:  unrecognized configuration parameter special.weird name
 -- Check what happens when you try to set a "custom" GUC within the
 -- namespace of an extension.
 SET plpgsql.extra_foo_warnings = true;  -- allowed if plpgsql is not loaded yet
 LOAD 'plpgsql';  -- this will throw a warning and delete the variable
-WARNING:  invalid configuration parameter name "plpgsql.extra_foo_warnings", removing it
+WARNING:  invalid configuration parameter name plpgsql.extra_foo_warnings, removing it
 DETAIL:  "plpgsql" is now a reserved prefix.
 SET plpgsql.extra_foo_warnings = true;  -- now, it's an error
-ERROR:  invalid configuration parameter name "plpgsql.extra_foo_warnings"
+ERROR:  invalid configuration parameter name plpgsql.extra_foo_warnings
 DETAIL:  "plpgsql" is a reserved prefix.
 SHOW plpgsql.extra_foo_warnings;
-ERROR:  unrecognized configuration parameter "plpgsql.extra_foo_warnings"
+ERROR:  unrecognized configuration parameter plpgsql.extra_foo_warnings
 --
 -- Test DISCARD TEMP
 --
@@ -775,9 +775,9 @@ select myfunc(1), current_setting('work_mem');
 
 -- check current_setting()'s behavior with invalid setting name
 select current_setting('nosuch.setting');  -- FAIL
-ERROR:  unrecognized configuration parameter "nosuch.setting"
+ERROR:  unrecognized configuration parameter nosuch.setting
 select current_setting('nosuch.setting', false);  -- FAIL
-ERROR:  unrecognized configuration parameter "nosuch.setting"
+ERROR:  unrecognized configuration parameter nosuch.setting
 select current_setting('nosuch.setting', true) is null;
  ?column? 
 ----------
@@ -811,14 +811,14 @@ create function func_with_bad_set() returns int as $$ select 1 $$
 language sql
 set default_text_search_config = no_such_config;
 NOTICE:  text search configuration "no_such_config" does not exist
-ERROR:  invalid value for parameter "default_text_search_config": "no_such_config"
+ERROR:  invalid value for parameter default_text_search_config: "no_such_config"
 set check_function_bodies = off;
 create function func_with_bad_set() returns int as $$ select 1 $$
 language sql
 set default_text_search_config = no_such_config;
 NOTICE:  text search configuration "no_such_config" does not exist
 select func_with_bad_set();
-ERROR:  invalid value for parameter "default_text_search_config": "no_such_config"
+ERROR:  invalid value for parameter default_text_search_config: "no_such_config"
 reset check_function_bodies;
 set default_with_oids to f;
 -- Should not allow to set it to true.
diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out
index 924d6e001d..752cffcda0 100644
--- a/src/test/regress/expected/password.out
+++ b/src/test/regress/expected/password.out
@@ -3,10 +3,10 @@
 --
 -- Tests for GUC password_encryption
 SET password_encryption = 'novalue'; -- error
-ERROR:  invalid value for parameter "password_encryption": "novalue"
+ERROR:  invalid value for parameter password_encryption: "novalue"
 HINT:  Available values: md5, scram-sha-256.
 SET password_encryption = true; -- error
-ERROR:  invalid value for parameter "password_encryption": "true"
+ERROR:  invalid value for parameter password_encryption: "true"
 HINT:  Available values: md5, scram-sha-256.
 SET password_encryption = 'md5'; -- ok
 SET password_encryption = 'scram-sha-256'; -- ok
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index b15eddbff3..8d9229a932 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -220,7 +220,7 @@ RESET ROLE;
 ALTER SUBSCRIPTION regress_testsub RENAME TO regress_testsub_foo;
 ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = local);
 ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = foobar);
-ERROR:  invalid value for parameter "synchronous_commit": "foobar"
+ERROR:  invalid value for parameter synchronous_commit: "foobar"
 HINT:  Available values: local, remote_write, remote_apply, on, off.
 \dRs+
                                                                                                                  List of subscriptions
diff --git a/src/test/regress/expected/transactions.out b/src/test/regress/expected/transactions.out
index 7f5757e89c..5939ad4d2e 100644
--- a/src/test/regress/expected/transactions.out
+++ b/src/test/regress/expected/transactions.out
@@ -53,7 +53,7 @@ SELECT COUNT(*) FROM xacttest;
 (1 row)
 
 RESET transaction_isolation; -- error
-ERROR:  parameter "transaction_isolation" cannot be reset
+ERROR:  parameter transaction_isolation cannot be reset
 END;
 BEGIN TRANSACTION READ ONLY;
 SELECT COUNT(*) FROM xacttest;
@@ -63,7 +63,7 @@ SELECT COUNT(*) FROM xacttest;
 (1 row)
 
 RESET transaction_read_only; -- error
-ERROR:  parameter "transaction_read_only" cannot be reset
+ERROR:  parameter transaction_read_only cannot be reset
 END;
 BEGIN TRANSACTION DEFERRABLE;
 SELECT COUNT(*) FROM xacttest;
@@ -73,11 +73,11 @@ SELECT COUNT(*) FROM xacttest;
 (1 row)
 
 RESET transaction_deferrable; -- error
-ERROR:  parameter "transaction_deferrable" cannot be reset
+ERROR:  parameter transaction_deferrable cannot be reset
 END;
 CREATE FUNCTION errfunc() RETURNS int LANGUAGE SQL AS 'SELECT 1'
 SET transaction_read_only = on; -- error
-ERROR:  parameter "transaction_read_only" cannot be set locally in functions
+ERROR:  parameter transaction_read_only cannot be set locally in functions
 -- Read-only tests
 CREATE TABLE writetest (a int);
 CREATE TEMPORARY TABLE temptest (a int);
diff --git a/contrib/auto_explain/t/001_auto_explain.pl b/contrib/auto_explain/t/001_auto_explain.pl
index abb422f8de..056001a0d6 100644
--- a/contrib/auto_explain/t/001_auto_explain.pl
+++ b/contrib/auto_explain/t/001_auto_explain.pl
@@ -201,7 +201,7 @@ GRANT SET ON PARAMETER auto_explain.log_format TO regress_user1;
 
 	like(
 		$log_contents,
-		qr/WARNING: ( 42501:)? permission denied to set parameter "auto_explain\.log_level"/,
+		qr/WARNING: ( 42501:)? permission denied to set parameter auto_explain\.log_level/,
 		"permission failure logged");
 
 }    # end queries run as regress_user1
diff --git a/src/pl/plperl/expected/plperl_init.out b/src/pl/plperl/expected/plperl_init.out
index 4b7e925419..6d6825cfed 100644
--- a/src/pl/plperl/expected/plperl_init.out
+++ b/src/pl/plperl/expected/plperl_init.out
@@ -23,7 +23,7 @@ SET ROLE regress_plperl_user;
 SET SESSION plperl.on_plperl_init = 'test';
 RESET ROLE;
 LOAD 'plperl';
-WARNING:  permission denied to set parameter "plperl.on_plperl_init"
+WARNING:  permission denied to set parameter plperl.on_plperl_init
 SHOW plperl.on_plperl_init;
  plperl.on_plperl_init 
 -----------------------
@@ -35,6 +35,6 @@ WARNING:  42 at line 1.
 -- now we won't be allowed to set it in the first place
 SET ROLE regress_plperl_user;
 SET SESSION plperl.on_plperl_init = 'test';
-ERROR:  permission denied to set parameter "plperl.on_plperl_init"
+ERROR:  permission denied to set parameter plperl.on_plperl_init
 RESET ROLE;
 DROP ROLE regress_plperl_user;
-- 
2.42.0

---

From: Kyotaro Horiguchi <[email-masked]>
Date: Thu, 30 Nov 2023 15:29:49 +0900 (JST)

At Thu, 30 Nov 2023 14:59:21 +0900, Michael Paquier <[email-masked]> wrote in 
> translated so they need three %s.

In this patch, the quotation marks cannot be changed from double
quotes.

After a brief review of the use of quotation marks in various
languages, it's observed that French uses guillemets (« »), German
uses lower qutation marks („ “), Spanish uses angular quotation marks
(« ») or alternatively, lower quotetaion marks. Japanese commonly uses
corner brackets (「」), but can also adopt double or single quotation
marks in certain contexts. I took a look at the backend's fr.po file
for a trial, and it indeed seems that guillemets are being used.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center

---

From: Michael Paquier <[email-masked]>
Date: Thu, 30 Nov 2023 16:03:44 +0900

> In this patch, the quotation marks cannot be changed from double

Indeed, that's a good point.  I completely forgot about that.
--
Michael

---

From: Peter Smith <[email-masked]>
Date: Thu, 30 Nov 2023 18:39:32 +1100

> Also applied 0001 from Alvaro.

Thanks for pushing those parts.

> GUC name is made of lower-case alpha characters?

Not forgotten. I felt the dot separator in such names might be
mistaken for a period in a sentence which is why I left quotes for
those ones. YMMV.

======
Kind Regards,
Peter. Smith.
Fujitsu Australia

---

From: Alvaro Herrera <[email-masked]>
Date: Thu, 30 Nov 2023 11:57:05 +0100

> +		if ('a' > *p || *p > 'z')

I think you need a function that the name possibly quoted, in a way that
lets the translator handle the quoting:

  static char buffer[SOMEMAXLEN];

  quotes_needed = ...;

  if (quotes_needed)
     /* translator: a quoted configuration parameter name */
     snprintf(buffer, _("\"%s\""), name);
     return buffer
  else
     /* no translation needed in this case */
     return name;

then the calling code just does a single %s that prints the string
returned by this function.  (Do note that the function is not reentrant,
like pg_dump's fmtId.  Shouldn't be a problem ...)

> +			elog(DEBUG3, "%s%s%s: setting ignored because previous source is higher priority",

Note that elog() doesn't do translation, and DEBUG doesn't really need
to worry too much about style anyway.  I'd leave these as-is.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
"La primera ley de las demostraciones en vivo es: no trate de usar el sistema.
Escriba un guión que no toque nada para no causar daños." (Jakob Nielsen)

---

From: Peter Eisentraut <[email-masked]>
Date: Thu, 30 Nov 2023 21:38:03 +0100

>   							item->filename, item->sourceline)));

I think this is completely over-engineered and wrong.  If we start down 
this road, then the next person is going to start engineering some rules 
by which we should quote file names and other things.  Which will lead 
to more confusion, not less.  The whole point of this quoting thing is 
that you do it all the time or not, not dynamically based on what's 
inside of it.

The original version of this string (and similar ones) seems the most 
correct, simple, and useful one to me.

---

From: Peter Smith <[email-masked]>
Date: Fri, 8 Dec 2023 15:10:29 +1100

> correct, simple, and useful one to me.

Yeah, trying to manipulate the quoting dynamically seems like it was
an overreach...

Removing that still leaves some other changes needed to "fix" the
messages using MixedCase GUCs.

PSA v4

======
Details:

Patch 0001 -- "datestyle" becomes DateStyle in messages
Rebased this again, which was part of an earlier patch set
- I think any GUC names documented as MixedCase should keep that same
case in messages; this also obeys the guidelines recently pushed [1].
- Some others agreed, expecting the exact GUC name (in the message)
can be found in pg_settings [2].
- OTOH, Michael didn't like the diff churn [3] caused by this patch.

~~~

Patch 0002 -- use mixed case for intervalstyle error message
I found that the GUC name substituted to the error message was coming
from the statement, not from the original name in the guc_tables, so
there was a case mismatch:

BEFORE Patch 0002 (see the lowercase in the error message)
2023-12-08 13:21:32.897 AEDT [32609] STATEMENT:  set intervalstyle = 1234;
ERROR:  invalid value for parameter "intervalstyle": "1234"
HINT:  Available values: postgres, postgres_verbose, sql_standard, iso_8601.

AFTER Patch 0002
2023-12-08 13:38:48.638 AEDT [29684] STATEMENT:  set intervalstyle = 1234;
ERROR:  invalid value for parameter "IntervalStyle": "1234"
HINT:  Available values: postgres, postgres_verbose, sql_standard, iso_8601.

======
[1] GUC quoting guidelines -
https://github.com/postgres/postgres/commit/a243569bf65c5664436e8f63d870b7ee9c014dcb
[2] The case should match pg_settings -
https://www.postgresql.org/message-id/db3e4290ced77111c17e7a2adfb1d660734f5f78.camel%40cybertec.at
[3] Dislike of diff churn -
https://www.postgresql.org/message-id/ZWUd8dYYA9v83KvI%40paquier.xyz

Kind Regards,
Peter Smith.
Fujitsu Australia

---

From: Alvaro Herrera <[email-masked]>
Date: Fri, 8 Dec 2023 13:55:28 +0100

> case in messages; this also obeys the guidelines recently pushed [1].

I agree.

> there was a case mismatch:

I agree.  Let's also add a test that shows this difference (my 0002
here).

I'm annoyed that this saga has transiently created a few untranslated
strings by removing unnecessary quotes but failing to move the variable
names outside the translatable part of the string.  I change a few of
those in 0003 -- mostly the ones in strings already touched by commit
8d9978a7176a, but also a few others.  Didn't go out of my way to grep
for other possible messages to fix, though.  (I feel like this is
missing some "translator:" comments.)

-- 
Álvaro Herrera         PostgreSQL Developer  —  https://www.EnterpriseDB.com/
"We’ve narrowed the problem down to the customer’s pants being in a situation
 of vigorous combustion" (Robert Haas, Postgres expert extraordinaire)
>From 0ccf4f8342d49d42116a1b1b872b15aeeddaf568 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email-masked]>
Date: Fri, 8 Dec 2023 12:59:20 +1100
Subject: [PATCH v5 1/3] GUC names - use mixed case for datestyle in messages

---
 src/backend/commands/variable.c        |  2 +-
 src/backend/utils/adt/datetime.c       |  2 +-
 src/test/regress/expected/date.out     | 58 +++++++++++++-------------
 src/test/regress/expected/horology.out |  2 +-
 4 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index c361bb2079..2703d2edc4 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -182,7 +182,7 @@ check_datestyle(char **newval, void **extra, GucSource source)
 
 	if (!ok)
 	{
-		GUC_check_errdetail("Conflicting \"datestyle\" specifications.");
+		GUC_check_errdetail("Conflicting DateStyle specifications.");
 		return false;
 	}
 
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index fca9a2a6e9..8ef5bf0076 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -4022,7 +4022,7 @@ DateTimeParseError(int dterr, DateTimeErrorExtra *extra,
 					(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
 					 errmsg("date/time field value out of range: \"%s\"",
 							str),
-					 errhint("Perhaps you need a different \"datestyle\" setting.")));
+					 errhint("Perhaps you need a different DateStyle setting.")));
 			break;
 		case DTERR_INTERVAL_OVERFLOW:
 			errsave(escontext,
diff --git a/src/test/regress/expected/date.out b/src/test/regress/expected/date.out
index f5949f3d17..99650bf231 100644
--- a/src/test/regress/expected/date.out
+++ b/src/test/regress/expected/date.out
@@ -94,17 +94,17 @@ SELECT date '1/8/1999';
 ERROR:  date/time field value out of range: "1/8/1999"
 LINE 1: SELECT date '1/8/1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1/18/1999';
 ERROR:  date/time field value out of range: "1/18/1999"
 LINE 1: SELECT date '1/18/1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '18/1/1999';
 ERROR:  date/time field value out of range: "18/1/1999"
 LINE 1: SELECT date '18/1/1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01/02/03';
     date    
 ------------
@@ -139,7 +139,7 @@ SELECT date 'January 8, 99 BC';
 ERROR:  date/time field value out of range: "January 8, 99 BC"
 LINE 1: SELECT date 'January 8, 99 BC';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '99-Jan-08';
     date    
 ------------
@@ -156,7 +156,7 @@ SELECT date '08-Jan-99';
 ERROR:  date/time field value out of range: "08-Jan-99"
 LINE 1: SELECT date '08-Jan-99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '08-Jan-1999';
     date    
 ------------
@@ -167,7 +167,7 @@ SELECT date 'Jan-08-99';
 ERROR:  date/time field value out of range: "Jan-08-99"
 LINE 1: SELECT date 'Jan-08-99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date 'Jan-08-1999';
     date    
 ------------
@@ -198,7 +198,7 @@ SELECT date '08 Jan 99';
 ERROR:  date/time field value out of range: "08 Jan 99"
 LINE 1: SELECT date '08 Jan 99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '08 Jan 1999';
     date    
 ------------
@@ -209,7 +209,7 @@ SELECT date 'Jan 08 99';
 ERROR:  date/time field value out of range: "Jan 08 99"
 LINE 1: SELECT date 'Jan 08 99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date 'Jan 08 1999';
     date    
 ------------
@@ -244,22 +244,22 @@ SELECT date '08-01-99';
 ERROR:  date/time field value out of range: "08-01-99"
 LINE 1: SELECT date '08-01-99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '08-01-1999';
 ERROR:  date/time field value out of range: "08-01-1999"
 LINE 1: SELECT date '08-01-1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01-08-99';
 ERROR:  date/time field value out of range: "01-08-99"
 LINE 1: SELECT date '01-08-99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01-08-1999';
 ERROR:  date/time field value out of range: "01-08-1999"
 LINE 1: SELECT date '01-08-1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '99-08-01';
     date    
 ------------
@@ -288,22 +288,22 @@ SELECT date '08 01 99';
 ERROR:  date/time field value out of range: "08 01 99"
 LINE 1: SELECT date '08 01 99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '08 01 1999';
 ERROR:  date/time field value out of range: "08 01 1999"
 LINE 1: SELECT date '08 01 1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01 08 99';
 ERROR:  date/time field value out of range: "01 08 99"
 LINE 1: SELECT date '01 08 99';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01 08 1999';
 ERROR:  date/time field value out of range: "01 08 1999"
 LINE 1: SELECT date '01 08 1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '99 08 01';
     date    
 ------------
@@ -345,7 +345,7 @@ SELECT date '1/18/1999';
 ERROR:  date/time field value out of range: "1/18/1999"
 LINE 1: SELECT date '1/18/1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '18/1/1999';
     date    
 ------------
@@ -392,7 +392,7 @@ SELECT date '99-Jan-08';
 ERROR:  date/time field value out of range: "99-Jan-08"
 LINE 1: SELECT date '99-Jan-08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-Jan-08';
     date    
 ------------
@@ -435,7 +435,7 @@ SELECT date '99 Jan 08';
 ERROR:  date/time field value out of range: "99 Jan 08"
 LINE 1: SELECT date '99 Jan 08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999 Jan 08';
     date    
 ------------
@@ -480,7 +480,7 @@ SELECT date '99-01-08';
 ERROR:  date/time field value out of range: "99-01-08"
 LINE 1: SELECT date '99-01-08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-01-08';
     date    
 ------------
@@ -515,7 +515,7 @@ SELECT date '99-08-01';
 ERROR:  date/time field value out of range: "99-08-01"
 LINE 1: SELECT date '99-08-01';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-08-01';
     date    
 ------------
@@ -526,7 +526,7 @@ SELECT date '99 01 08';
 ERROR:  date/time field value out of range: "99 01 08"
 LINE 1: SELECT date '99 01 08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999 01 08';
     date    
 ------------
@@ -561,7 +561,7 @@ SELECT date '99 08 01';
 ERROR:  date/time field value out of range: "99 08 01"
 LINE 1: SELECT date '99 08 01';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999 08 01';
     date    
 ------------
@@ -603,7 +603,7 @@ SELECT date '18/1/1999';
 ERROR:  date/time field value out of range: "18/1/1999"
 LINE 1: SELECT date '18/1/1999';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '01/02/03';
     date    
 ------------
@@ -644,7 +644,7 @@ SELECT date '99-Jan-08';
 ERROR:  date/time field value out of range: "99-Jan-08"
 LINE 1: SELECT date '99-Jan-08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-Jan-08';
     date    
 ------------
@@ -731,7 +731,7 @@ SELECT date '99-01-08';
 ERROR:  date/time field value out of range: "99-01-08"
 LINE 1: SELECT date '99-01-08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-01-08';
     date    
 ------------
@@ -766,7 +766,7 @@ SELECT date '99-08-01';
 ERROR:  date/time field value out of range: "99-08-01"
 LINE 1: SELECT date '99-08-01';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999-08-01';
     date    
 ------------
@@ -777,7 +777,7 @@ SELECT date '99 01 08';
 ERROR:  date/time field value out of range: "99 01 08"
 LINE 1: SELECT date '99 01 08';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999 01 08';
     date    
 ------------
@@ -812,7 +812,7 @@ SELECT date '99 08 01';
 ERROR:  date/time field value out of range: "99 08 01"
 LINE 1: SELECT date '99 08 01';
                     ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 SELECT date '1999 08 01';
     date    
 ------------
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index cfb4b205e4..4aeefd53bd 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -100,7 +100,7 @@ SELECT timestamp with time zone '27/12/2001 04:05:06.789-08';
 ERROR:  date/time field value out of range: "27/12/2001 04:05:06.789-08"
 LINE 1: SELECT timestamp with time zone '27/12/2001 04:05:06.789-08'...
                                         ^
-HINT:  Perhaps you need a different "datestyle" setting.
+HINT:  Perhaps you need a different DateStyle setting.
 set datestyle to dmy;
 SELECT timestamp with time zone '27/12/2001 04:05:06.789-08';
            timestamptz            
-- 
2.39.2

>From 8b5bd09c818590afd858b9c8159887339db8e456 Mon Sep 17 00:00:00 2001
From: Peter Smith <[email-masked]>
Date: Fri, 8 Dec 2023 14:41:02 +1100
Subject: [PATCH v5 2/3] Ensure we use documented CamelCase in error messages

Author: Peter Smith
---
 src/backend/utils/misc/guc.c      | 2 +-
 src/test/regress/expected/guc.out | 4 ++++
 src/test/regress/sql/guc.sql      | 3 +++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e76c083003..c134024fd5 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3252,7 +3252,7 @@ parse_and_validate_value(struct config_generic *record,
 					ereport(elevel,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 							 errmsg("invalid value for parameter \"%s\": \"%s\"",
-									name, value),
+									conf->gen.name, value),
 							 hintmsg ? errhint("%s", _(hintmsg)) : 0));
 
 					if (hintmsg)
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 127c953297..66ddc4c938 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -6,6 +6,10 @@ SHOW datestyle;
  Postgres, MDY
 (1 row)
 
+-- Check output style of CamelCase enum options
+SET intervalstyle to 'asd';
+ERROR:  invalid value for parameter "IntervalStyle": "asd"
+HINT:  Available values: postgres, postgres_verbose, sql_standard, iso_8601.
 -- SET to some nondefault value
 SET vacuum_cost_delay TO 40;
 SET datestyle = 'ISO, YMD';
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index dc79761955..e540495fc1 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -2,6 +2,9 @@
 -- we can't rely on any specific default value of vacuum_cost_delay
 SHOW datestyle;
 
+-- Check output style of CamelCase enum options
+SET intervalstyle to 'asd';
+
 -- SET to some nondefault value
 SET vacuum_cost_delay TO 40;
 SET datestyle = 'ISO, YMD';
-- 
2.39.2

>From 86402523bc1783d8cc508418bb4be796d3aa7dae Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <[email-masked]>
Date: Fri, 8 Dec 2023 13:46:41 +0100
Subject: [PATCH v5 3/3] move variable names out of translatable message string

---
 contrib/pg_prewarm/autoprewarm.c          |  3 +-
 src/backend/access/transam/xlog.c         | 75 +++++++++++++----------
 src/backend/access/transam/xlogrecovery.c |  2 +-
 src/backend/commands/vacuum.c             | 10 +--
 src/backend/commands/variable.c           | 11 ++--
 src/backend/port/sysv_shmem.c             |  3 +-
 src/backend/postmaster/bgworker.c         |  3 +-
 src/backend/postmaster/checkpointer.c     |  3 +-
 src/backend/replication/syncrep.c         |  3 +-
 src/backend/storage/buffer/localbuf.c     |  3 +-
 src/backend/storage/file/fd.c             |  9 ++-
 src/backend/storage/lmgr/predicate.c      |  6 +-
 src/backend/tcop/postgres.c               | 15 +++--
 src/backend/utils/fmgr/dfmgr.c            | 16 ++---
 14 files changed, 97 insertions(+), 65 deletions(-)

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 0993bd2453..fcc8debb0b 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -877,7 +877,8 @@ apw_start_database_worker(void)
 		ereport(ERROR,
 				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
 				 errmsg("registering dynamic bgworker autoprewarm failed"),
-				 errhint("Consider increasing configuration parameter max_worker_processes.")));
+				 errhint("Consider increasing the configuration parameter %s.",
+						 "max_worker_processes")));
 
 	/*
 	 * Ignore return value; if it fails, postmaster has died, but we have
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index daed1a7a49..d3831ea978 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4161,16 +4161,21 @@ ReadControlFile(void)
 	if (ControlFile->catalog_version_no != CATALOG_VERSION_NO)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with CATALOG_VERSION_NO %d,"
-						   " but the server was compiled with CATALOG_VERSION_NO %d.",
-						   ControlFile->catalog_version_no, CATALOG_VERSION_NO),
+				 /*- translator: %s is a variable name and %d is its value */
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "CATALOG_VERSION_NO",
+						   ControlFile->catalog_version_no,
+						   "CATALOG_VERSION_NO",
+						   CATALOG_VERSION_NO),
 				 errhint("It looks like you need to initdb.")));
 	if (ControlFile->maxAlign != MAXIMUM_ALIGNOF)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with MAXALIGN %d,"
-						   " but the server was compiled with MAXALIGN %d.",
-						   ControlFile->maxAlign, MAXIMUM_ALIGNOF),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "MAXALIGN", ControlFile->maxAlign,
+						   "MAXALIGN", MAXIMUM_ALIGNOF),
 				 errhint("It looks like you need to initdb.")));
 	if (ControlFile->floatFormat != FLOATFORMAT_VALUE)
 		ereport(FATAL,
@@ -4180,51 +4185,57 @@ ReadControlFile(void)
 	if (ControlFile->blcksz != BLCKSZ)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with BLCKSZ %d,"
-						   " but the server was compiled with BLCKSZ %d.",
-						   ControlFile->blcksz, BLCKSZ),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "BLCKSZ", ControlFile->blcksz, "BLCKSZ", BLCKSZ),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->relseg_size != RELSEG_SIZE)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with RELSEG_SIZE %d,"
-						   " but the server was compiled with RELSEG_SIZE %d.",
-						   ControlFile->relseg_size, RELSEG_SIZE),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "RELSEG_SIZE", ControlFile->relseg_size,
+						   "RELSEG_SIZE", RELSEG_SIZE),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->xlog_blcksz != XLOG_BLCKSZ)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with XLOG_BLCKSZ %d,"
-						   " but the server was compiled with XLOG_BLCKSZ %d.",
-						   ControlFile->xlog_blcksz, XLOG_BLCKSZ),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "XLOG_BLCKSZ", ControlFile->xlog_blcksz,
+						   "XLOG_BLCKSZ", XLOG_BLCKSZ),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->nameDataLen != NAMEDATALEN)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with NAMEDATALEN %d,"
-						   " but the server was compiled with NAMEDATALEN %d.",
-						   ControlFile->nameDataLen, NAMEDATALEN),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "NAMEDATALEN", ControlFile->nameDataLen,
+						   "NAMEDATALEN", NAMEDATALEN),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->indexMaxKeys != INDEX_MAX_KEYS)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with INDEX_MAX_KEYS %d,"
-						   " but the server was compiled with INDEX_MAX_KEYS %d.",
-						   ControlFile->indexMaxKeys, INDEX_MAX_KEYS),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "INDEX_MAX_KEYS", ControlFile->indexMaxKeys,
+						   "INDEX_MAX_KEYS", INDEX_MAX_KEYS),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->toast_max_chunk_size != TOAST_MAX_CHUNK_SIZE)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d,"
-						   " but the server was compiled with TOAST_MAX_CHUNK_SIZE %d.",
-						   ControlFile->toast_max_chunk_size, (int) TOAST_MAX_CHUNK_SIZE),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "TOAST_MAX_CHUNK_SIZE", ControlFile->toast_max_chunk_size,
+						   "TOAST_MAX_CHUNK_SIZE", (int) TOAST_MAX_CHUNK_SIZE),
 				 errhint("It looks like you need to recompile or initdb.")));
 	if (ControlFile->loblksize != LOBLKSIZE)
 		ereport(FATAL,
 				(errmsg("database files are incompatible with server"),
-				 errdetail("The database cluster was initialized with LOBLKSIZE %d,"
-						   " but the server was compiled with LOBLKSIZE %d.",
-						   ControlFile->loblksize, (int) LOBLKSIZE),
+				 errdetail("The database cluster was initialized with %s %d,"
+						   " but the server was compiled with %s %d.",
+						   "LOBLKSIZE", ControlFile->loblksize,
+						   "LOBLKSIZE", (int) LOBLKSIZE),
 				 errhint("It looks like you need to recompile or initdb.")));
 
 #ifdef USE_FLOAT8_BYVAL
@@ -4259,12 +4270,14 @@ ReadControlFile(void)
 
 	/* check and update variables dependent on wal_segment_size */
 	if (ConvertToXSegs(min_wal_size_mb, wal_segment_size) < 2)
-		ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						errmsg("min_wal_size must be at least twice wal_segment_size")));
+		ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				errmsg("%s must be at least twice %s",
+					   "min_wal_size", "wal_segment_size"));
 
 	if (ConvertToXSegs(max_wal_size_mb, wal_segment_size) < 2)
-		ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						errmsg("max_wal_size must be at least twice wal_segment_size")));
+		ereport(ERROR, errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				errmsg("%s must be at least twice %s",
+					   "max_wal_size", "wal_segment_size"));
 
 	UsableBytesInSegment =
 		(wal_segment_size / XLOG_BLCKSZ * UsableBytesInPage) -
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 4bc4d3e323..524d792ae9 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -4726,7 +4726,7 @@ check_recovery_target(char **newval, void **extra, GucSource source)
 {
 	if (strcmp(*newval, "immediate") != 0 && strcmp(*newval, "") != 0)
 	{
-		GUC_check_errdetail("The only allowed value is \"immediate\".");
+		GUC_check_errdetail("The only allowed value is \"%s\".", "immediate");
 		return false;
 	}
 	return true;
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index be43b46c04..a80438f30b 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -134,8 +134,9 @@ check_vacuum_buffer_usage_limit(int *newval, void **extra,
 		return true;
 
 	/* Value does not fall within any allowable range */
-	GUC_check_errdetail("vacuum_buffer_usage_limit must be 0 or between %d kB and %d kB",
-						MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB);
+	GUC_check_errdetail("%s must be 0 or between %d kB and %d kB.",
+						"vacuum_buffer_usage_limit", MIN_BAS_VAC_RING_SIZE_KB,
+						MAX_BAS_VAC_RING_SIZE_KB);
 
 	return false;
 }
@@ -206,8 +207,9 @@ ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
 			{
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						 errmsg("BUFFER_USAGE_LIMIT option must be 0 or between %d kB and %d kB",
-								MIN_BAS_VAC_RING_SIZE_KB, MAX_BAS_VAC_RING_SIZE_KB),
+						 errmsg("%s option must be 0 or between %d kB and %d kB",
+								"BUFFER_USAGE_LIMIT", MIN_BAS_VAC_RING_SIZE_KB,
+								MAX_BAS_VAC_RING_SIZE_KB),
 						 hintmsg ? errhint("%s", _(hintmsg)) : 0));
 			}
 
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 2703d2edc4..da5e2de310 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -182,7 +182,7 @@ check_datestyle(char **newval, void **extra, GucSource source)
 
 	if (!ok)
 	{
-		GUC_check_errdetail("Conflicting DateStyle specifications.");
+		GUC_check_errdetail("Conflicting %s specifications.", "DateStyle");
 		return false;
 	}
 
@@ -717,7 +717,8 @@ check_client_encoding(char **newval, void **extra, GucSource source)
 		else
 		{
 			/* Provide a useful complaint */
-			GUC_check_errdetail("Cannot change client_encoding now.");
+			GUC_check_errdetail("Cannot change %s now.",
+								"client_encoding");
 		}
 		return false;
 	}
@@ -1202,7 +1203,8 @@ check_effective_io_concurrency(int *newval, void **extra, GucSource source)
 #ifndef USE_PREFETCH
 	if (*newval != 0)
 	{
-		GUC_check_errdetail("effective_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
+		GUC_check_errdetail("%s must be set to 0 on platforms that lack posix_fadvise().",
+							"effective_io_concurrency");
 		return false;
 	}
 #endif							/* USE_PREFETCH */
@@ -1215,7 +1217,8 @@ check_maintenance_io_concurrency(int *newval, void **extra, GucSource source)
 #ifndef USE_PREFETCH
 	if (*newval != 0)
 	{
-		GUC_check_errdetail("maintenance_io_concurrency must be set to 0 on platforms that lack posix_fadvise().");
+		GUC_check_errdetail("%s must be set to 0 on platforms that lack posix_fadvise().",
+							"maintenance_io_concurrency");
 		return false;
 	}
 #endif							/* USE_PREFETCH */
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 2de280ecb6..88c39f577d 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -580,7 +580,8 @@ check_huge_page_size(int *newval, void **extra, GucSource source)
 	/* Recent enough Linux only, for now.  See GetHugePageSize(). */
 	if (*newval != 0)
 	{
-		GUC_check_errdetail("huge_page_size must be 0 on this platform.");
+		GUC_check_errdetail("%s must be 0 on this platform.",
+							"huge_page_size");
 		return false;
 	}
 #endif
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index c345639086..f2dc53ac85 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -919,7 +919,8 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
 								  "Up to %d background workers can be registered with the current settings.",
 								  max_worker_processes,
 								  max_worker_processes),
-				 errhint("Consider increasing the configuration parameter max_worker_processes.")));
+				 errhint("Consider increasing the configuration parameter %s.",
+						 "max_worker_processes")));
 		return;
 	}
 
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index dc2da5a2cd..9060eeea67 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -423,7 +423,8 @@ CheckpointerMain(void)
 									   "checkpoints are occurring too frequently (%d seconds apart)",
 									   elapsed_secs,
 									   elapsed_secs),
-						 errhint("Consider increasing the configuration parameter max_wal_size.")));
+						 errhint("Consider increasing the configuration parameter %s.",
+								 "max_wal_size")));
 
 			/*
 			 * Initialize checkpointer-private variables used during
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index 0ea71b5c43..7d1fecb607 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -1016,7 +1016,8 @@ check_synchronous_standby_names(char **newval, void **extra, GucSource source)
 			if (syncrep_parse_error_msg)
 				GUC_check_errdetail("%s", syncrep_parse_error_msg);
 			else
-				GUC_check_errdetail("synchronous_standby_names parser failed");
+				GUC_check_errdetail("%s parser failed",
+									"synchronous_standby_names");
 			return false;
 		}
 
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index aebcf146b4..5b9cc850a2 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -705,7 +705,8 @@ check_temp_buffers(int *newval, void **extra, GucSource source)
 	 */
 	if (source != PGC_S_TEST && NLocBuffer && NLocBuffer != *newval)
 	{
-		GUC_check_errdetail("temp_buffers cannot be changed after any temporary tables have been accessed in the session.");
+		GUC_check_errdetail("%s cannot be changed after any temporary tables have been accessed in the session.",
+							"temp_buffers");
 		return false;
 	}
 	return true;
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index a185fb3d08..3b5d395a0f 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -3917,7 +3917,8 @@ check_debug_io_direct(char **newval, void **extra, GucSource source)
 #if PG_O_DIRECT == 0
 	if (strcmp(*newval, "") != 0)
 	{
-		GUC_check_errdetail("debug_io_direct is not supported on this platform.");
+		GUC_check_errdetail("%s is not supported on this platform.",
+							"debug_io_direct");
 		result = false;
 	}
 	flags = 0;
@@ -3964,14 +3965,16 @@ check_debug_io_direct(char **newval, void **extra, GucSource source)
 #if XLOG_BLCKSZ < PG_IO_ALIGN_SIZE
 	if (result && (flags & (IO_DIRECT_WAL | IO_DIRECT_WAL_INIT)))
 	{
-		GUC_check_errdetail("debug_io_direct is not supported for WAL because XLOG_BLCKSZ is too small");
+		GUC_check_errdetail("%s is not supported for WAL because %s is too small",
+							"debug_io_direct", "XLOG_BLCKSZ");
 		result = false;
 	}
 #endif
 #if BLCKSZ < PG_IO_ALIGN_SIZE
 	if (result && (flags & IO_DIRECT_DATA))
 	{
-		GUC_check_errdetail("debug_io_direct is not supported for data because BLCKSZ is too small");
+		GUC_check_errdetail("%s is not supported for data because %s is too small",
+							"debug_io_direct", "BLCKSZ");
 		result = false;
 	}
 #endif
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 1129b8e4f2..b8d3df1a3b 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1644,8 +1644,10 @@ GetSerializableTransactionSnapshot(Snapshot snapshot)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot use serializable mode in a hot standby"),
-				 errdetail("default_transaction_isolation is set to \"serializable\"."),
-				 errhint("You can use \"SET default_transaction_isolation = 'repeatable read'\" to change the default.")));
+				 errdetail("%s is set to \"%s\".",
+						   "default_transaction_isolation", "serializable"),
+				 errhint("You can use \"%s\" to change the default.",
+						 "SET default_transaction_isolation = 'repeatable read'")));
 
 	/*
 	 * A special optimization is available for SERIALIZABLE READ ONLY
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7298a187d1..9b55a584ed 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3571,7 +3571,8 @@ check_max_stack_depth(int *newval, void **extra, GucSource source)
 
 	if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
 	{
-		GUC_check_errdetail("max_stack_depth must not exceed %ldkB.",
+		GUC_check_errdetail("%s must not exceed %ldkB.",
+							"max_stack_depth",
 							(stack_rlimit - STACK_DEPTH_SLOP) / 1024L);
 		GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
 		return false;
@@ -3596,7 +3597,8 @@ check_client_connection_check_interval(int *newval, void **extra, GucSource sour
 {
 	if (!WaitEventSetCanReportClosed() && *newval != 0)
 	{
-		GUC_check_errdetail("client_connection_check_interval must be set to 0 on this platform.");
+		GUC_check_errdetail("%s must be set to 0 on this platform.",
+							"client_connection_check_interval");
 		return false;
 	}
 	return true;
@@ -3617,7 +3619,8 @@ check_stage_log_stats(bool *newval, void **extra, GucSource source)
 {
 	if (*newval && log_statement_stats)
 	{
-		GUC_check_errdetail("Cannot enable parameter when \"log_statement_stats\" is true.");
+		GUC_check_errdetail("Cannot enable parameter when %s is true.",
+							"log_statement_stats");
 		return false;
 	}
 	return true;
@@ -3632,9 +3635,9 @@ check_log_stats(bool *newval, void **extra, GucSource source)
 	if (*newval &&
 		(log_parser_stats || log_planner_stats || log_executor_stats))
 	{
-		GUC_check_errdetail("Cannot enable log_statement_stats when "
-							"log_parser_stats, log_planner_stats, "
-							"or log_executor_stats is true.");
+		GUC_check_errdetail("Cannot enable %s when %s, %s, or %s is true.",
+							"log_statement_stats", "log_parser_stats",
+							"log_planner_stats", "log_executor_stats");
 		return false;
 	}
 	return true;
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 56724ff815..60469e6258 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -358,8 +358,8 @@ incompatible_module_error(const char *libname,
 		if (details.len)
 			appendStringInfoChar(&details, '\n');
 		appendStringInfo(&details,
-						 _("Server has FUNC_MAX_ARGS = %d, library has %d."),
-						 magic_data.funcmaxargs,
+						 _("Server has %s = %d, library has %d."),
+						 "FUNC_MAX_ARGS", magic_data.funcmaxargs,
 						 module_magic_data->funcmaxargs);
 	}
 	if (module_magic_data->indexmaxkeys != magic_data.indexmaxkeys)
@@ -367,8 +367,8 @@ incompatible_module_error(const char *libname,
 		if (details.len)
 			appendStringInfoChar(&details, '\n');
 		appendStringInfo(&details,
-						 _("Server has INDEX_MAX_KEYS = %d, library has %d."),
-						 magic_data.indexmaxkeys,
+						 _("Server has %s = %d, library has %d."),
+						 "INDEX_MAX_KEYS", magic_data.indexmaxkeys,
 						 module_magic_data->indexmaxkeys);
 	}
 	if (module_magic_data->namedatalen != magic_data.namedatalen)
@@ -376,8 +376,8 @@ incompatible_module_error(const char *libname,
 		if (details.len)
 			appendStringInfoChar(&details, '\n');
 		appendStringInfo(&details,
-						 _("Server has NAMEDATALEN = %d, library has %d."),
-						 magic_data.namedatalen,
+						 _("Server has %s = %d, library has %d."),
+						 "NAMEDATALEN", magic_data.namedatalen,
 						 module_magic_data->namedatalen);
 	}
 	if (module_magic_data->float8byval != magic_data.float8byval)
@@ -385,8 +385,8 @@ incompatible_module_error(const char *libname,
 		if (details.len)
 			appendStringInfoChar(&details, '\n');
 		appendStringInfo(&details,
-						 _("Server has FLOAT8PASSBYVAL = %s, library has %s."),
-						 magic_data.float8byval ? "true" : "false",
+						 _("Server has %s = %s, library has %s."),
+						 "FLOAT8PASSBYVAL", magic_data.float8byval ? "true" : "false",
 						 module_magic_data->float8byval ? "true" : "false");
 	}
 
-- 
2.39.2

---

From: Peter Eisentraut <[email-masked]>
Date: Fri, 8 Dec 2023 15:48:43 +0100

> - OTOH, Michael didn't like the diff churn [3] caused by this patch.

I'm fine with adjusting the mixed-case stuff, but intuitively, I don't 
think removing the quotes in this is an improvement:

---

From: Peter Smith <[email-masked]>
Date: Mon, 11 Dec 2023 10:07:59 +1100

> + GUC_check_errdetail("Conflicting DateStyle specifications.");

My original intention of this thread was only to document the GUC name
quoting guidelines and then apply those consistently in the code.

I'm happy either way for the MixedCase names to be quoted or not
quoted, whatever is the consensus.

If the rule is changed to quote those MixedCase GUCs then the docs
will require minor tweaking

CURRENT
   <para>
    In messages containing configuration variable names, do not include quotes
    when the names are visibly not natural English words, such as when they
    have underscores, are all-uppercase or have mixed case. Otherwise, quotes
    must be added. Do include quotes in a message where an arbitrary variable
    name is to be expanded.
   </para>

"are all-uppercase or have mixed case." --> "or are all-uppercase."

======
Kind Regards,
Peter Smith.
Fujitsu Australia

---

From: Peter Eisentraut <[email-masked]>
Date: Thu, 14 Dec 2023 09:38:40 +0100

> "are all-uppercase or have mixed case." --> "or are all-uppercase."

After these discussions, I think this rule change was not a good idea. 
It effectively enforces these kinds of inconsistencies.  For example, if 
you ever refactored

     "DateStyle is wrong"

to

     "%s is wrong"

you'd need to adjust the quotes, and thus user-visible behavior, for 
entirely internal reasons.  This is not good.  And then came the idea to 
determine the quoting dynamically, which I think everyone agreed was too 
much.  So I don't see a way to make this work well.

---

From: Michael Paquier <[email-masked]>
Date: Sat, 16 Dec 2023 10:33:45 +0100

On Thu, Dec 14, 2023 at 09:38:40AM +0100, Peter Eisentraut wrote:
> After these discussions, I think this rule change was not a good idea. It
> effectively enforces these kinds of inconsistencies.  For example, if you
> ever refactored
> 
>     "DateStyle is wrong"
> 
> to
> 
>     "%s is wrong"
> 
> entirely internal reasons.  This is not good.

So, what are you suggesting?  Should the encouraged rule be removed
from the docs?  Or do you object to some of the changes done in the
latest patch series v5?

FWIW, I am a bit meh with v5-0001, because I don't see the benefits.
On the contrary v5-0003 is useful, because it reduces a bit the number
of strings to translate.  That's always good to take.  I don't have a
problem with v5-0002, either, where we'd begin using the name of the 
GUC as stored in the static tables rather than the name provided in
the SET query, particularly for the reason that it makes the GUC name
a bit more consistent even when using double-quotes around the
parameter name in the query, where the error messages would not force
a lower-case conversion.  The patch would, AFAIU, change HEAD from
that:
=# SET "intervalstylE" to popo;
ERROR:  22023: invalid value for parameter "intervalstylE": "popo"
To that:
=# SET "intervalstylE" to popo;
ERROR:  22023: invalid value for parameter "IntervalStyle": "popo"

> And then came the idea to

Yeah, with the quotes being language-dependent, any idea I can think
of is as good as unreliable and dead.
--
Michael