Attached a POC adding a new variable ECHO_ERROR
\set ECHO_ERROR text|none|psqlstate

On Mon, Dec 3, 2018 at 2:47 AM Andrew Gierth
<and...@tao11.riddles.org.uk> wrote:
>
> >>>>> "Tom" == Tom Lane <t...@sss.pgh.pa.us> writes:
>
>  Tom> I don't buy that argument. We use psql's normal display in all the
>  Tom> regular regression tests, and it's not a big maintenance problem.
>
> The regular regression tests have the advantage that they don't need to
> work across pg versions.
>
> It is more of a problem for extensions; I just ran into this myself in
> fact, with a test failing because "invalid input syntax for integer" got
> changed to "invalid input syntax for type integer".
>
> --
> Andrew (irc:RhodiumToad)
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index 62c2928e6b..049d43086f 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -536,10 +536,22 @@ AcceptResult(const PGresult *result)
 
 	if (!OK)
 	{
-		const char *error = PQerrorMessage(pset.db);
+		const char *error = "";
+		const char *err_fmt = "%s";
+		switch (pset.echo_error) {
+		case PSQL_ECHO_ERROR_NONE:
+			break;
+		case PSQL_ECHO_ERROR_PSQLSTATE:
+			err_fmt = "%s\n";
+			error = PQresultErrorField(result, PG_DIAG_SQLSTATE);
+			break;
+		default:
+			error = PQerrorMessage(pset.db);
+			break;
+		}
 
 		if (strlen(error))
-			psql_error("%s", error);
+			psql_error(err_fmt, error);
 
 		CheckConnection();
 	}
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 2e9fe760eb..b653e37526 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -339,7 +339,7 @@ helpVariables(unsigned short int pager)
 	 * Windows builds currently print one more line than non-Windows builds.
 	 * Using the larger number is fine.
 	 */
-	output = PageOutput(156, pager ? &(pset.popt.topt) : NULL);
+	output = PageOutput(159, pager ? &(pset.popt.topt) : NULL);
 
 	fprintf(output, _("List of specially treated variables\n\n"));
 
@@ -360,6 +360,9 @@ helpVariables(unsigned short int pager)
 	fprintf(output, _("  ECHO_HIDDEN\n"
 					  "    if set, display internal queries executed by backslash commands;\n"
 					  "    if set to \"noexec\", just show them without execution\n"));
+	fprintf(output, _("  ECHO_ERROR\n"
+					  "    controls what error msg is written to standard error\n"
+					  "    [text, sqlstate, none]\n"));
 	fprintf(output, _("  ENCODING\n"
 					  "    current client character set encoding\n"));
 	fprintf(output, _("  ERROR\n"
@@ -411,7 +414,7 @@ helpVariables(unsigned short int pager)
 	fprintf(output, _("  USER\n"
 					  "    the currently connected database user\n"));
 	fprintf(output, _("  VERBOSITY\n"
-					  "    controls verbosity of error reports [default, verbose, terse]\n"));
+					  "    controls verbosity of server error reports [default, verbose, terse]\n"));
 	fprintf(output, _("  VERSION\n"
 					  "  VERSION_NAME\n"
 					  "  VERSION_NUM\n"
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 176c85afd0..dd1f5f2c55 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -48,6 +48,13 @@ typedef enum
 	PSQL_ECHO_HIDDEN_NOEXEC
 } PSQL_ECHO_HIDDEN;
 
+typedef enum
+{
+	PSQL_ECHO_ERROR_NONE,
+	PSQL_ECHO_ERROR_TEXT,
+	PSQL_ECHO_ERROR_PSQLSTATE
+} PSQL_ECHO_ERROR;
+
 typedef enum
 {
 	PSQL_ERROR_ROLLBACK_OFF,
@@ -132,6 +139,7 @@ typedef struct _psqlSettings
 	int			ignoreeof;
 	PSQL_ECHO	echo;
 	PSQL_ECHO_HIDDEN echo_hidden;
+	PSQL_ECHO_ERROR echo_error;
 	PSQL_ERROR_ROLLBACK on_error_rollback;
 	PSQL_COMP_CASE comp_case;
 	HistControl histcontrol;
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index e7536a8a06..156b4665ac 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -949,6 +949,33 @@ echo_hook(const char *newval)
 	return true;
 }
 
+static char *
+echo_error_substitute_hook(char *newval)
+{
+	if (newval == NULL)
+		newval = pg_strdup("text");
+	return newval;
+}
+
+static bool
+echo_error_hook(const char *newval)
+{
+	Assert(newval != NULL);		/* else substitute hook messed up */
+	if (pg_strcasecmp(newval, "text") == 0)
+		pset.echo_error = PSQL_ECHO_ERROR_TEXT;
+	else if (pg_strcasecmp(newval, "none") == 0)
+		pset.echo_error = PSQL_ECHO_ERROR_NONE;
+	else if (pg_strcasecmp(newval, "psqlstate") == 0)
+		pset.echo_error = PSQL_ECHO_ERROR_PSQLSTATE;
+	else
+	{
+		PsqlVarEnumError("ECHO_ERROR", newval, "none, psqlstate, text");
+		return false;
+	}
+	return true;
+}
+
+
 static bool
 echo_hidden_hook(const char *newval)
 {
@@ -1167,6 +1194,9 @@ EstablishVariableSpace(void)
 	SetVariableHooks(pset.vars, "ECHO_HIDDEN",
 					 bool_substitute_hook,
 					 echo_hidden_hook);
+	SetVariableHooks(pset.vars, "ECHO_ERROR",
+					 echo_error_substitute_hook,
+					 echo_error_hook);
 	SetVariableHooks(pset.vars, "ON_ERROR_ROLLBACK",
 					 bool_substitute_hook,
 					 on_error_rollback_hook);
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index fa44b2820b..bf23c1f4bb 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3561,6 +3561,8 @@ psql_completion(const char *text, int start, int end)
 							 "preserve-lower", "preserve-upper");
 		else if (TailMatchesCS("ECHO"))
 			COMPLETE_WITH_CS("errors", "queries", "all", "none");
+		else if (TailMatchesCS("ECHO_ERROR"))
+			COMPLETE_WITH_CS("text", "sqlstate", "none");
 		else if (TailMatchesCS("ECHO_HIDDEN"))
 			COMPLETE_WITH_CS("noexec", "off", "on");
 		else if (TailMatchesCS("HISTCONTROL"))

Reply via email to