aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-04-04 17:22:02 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2019-04-04 17:22:02 -0400
commit7bac3acab4d5c3f2c35aa3a7bea08411d83fd5bc (patch)
treec6d41d068592bc1d566c035e5f0d52828f738acf /src
parent413ccaa74d9a126b042727c826e65e2844adadac (diff)
downloadpostgresql-7bac3acab4d5c3f2c35aa3a7bea08411d83fd5bc.tar.gz
postgresql-7bac3acab4d5c3f2c35aa3a7bea08411d83fd5bc.zip
Add a "SQLSTATE-only" error verbosity option to libpq and psql.
This is intended for use mostly in test scripts for external tools, which could do without cross-PG-version variations in error message wording. Of course, the SQLSTATE isn't guaranteed stable either, but it should be more so than the error message text. Note: there's a bit of an ABI change for libpq here, but it seems OK because if somebody compiles against a newer version of libpq-fe.h, and then tries to pass PQERRORS_SQLSTATE to PQsetErrorVerbosity() of an older libpq library, it will be accepted and then act like PQERRORS_DEFAULT, thanks to the way the tests in pqBuildErrorMessage3 have historically been phrased. That seems acceptable. Didier Gautheron, reviewed by Dagfinn Ilmari Mannsåker Discussion: https://postgr.es/m/CAJRYxuKyj4zA+JGVrtx8OWAuBfE-_wN4sUMK4H49EuPed=mOBw@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/help.c4
-rw-r--r--src/bin/psql/startup.c8
-rw-r--r--src/bin/psql/tab-complete.c2
-rw-r--r--src/interfaces/libpq/fe-protocol3.c18
-rw-r--r--src/interfaces/libpq/libpq-fe.h3
-rw-r--r--src/test/regress/expected/psql.out20
-rw-r--r--src/test/regress/sql/psql.sql15
7 files changed, 63 insertions, 7 deletions
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index eb3a0f36d94..63b115fe018 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -340,7 +340,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(158, pager ? &(pset.popt.topt) : NULL);
fprintf(output, _("List of specially treated variables\n\n"));
@@ -414,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 error reports [default, verbose, terse, sqlstate]\n"));
fprintf(output, _(" VERSION\n"
" VERSION_NAME\n"
" VERSION_NUM\n"
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index ac82087445e..855133bbcb4 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -1110,13 +1110,15 @@ verbosity_hook(const char *newval)
Assert(newval != NULL); /* else substitute hook messed up */
if (pg_strcasecmp(newval, "default") == 0)
pset.verbosity = PQERRORS_DEFAULT;
- else if (pg_strcasecmp(newval, "terse") == 0)
- pset.verbosity = PQERRORS_TERSE;
else if (pg_strcasecmp(newval, "verbose") == 0)
pset.verbosity = PQERRORS_VERBOSE;
+ else if (pg_strcasecmp(newval, "terse") == 0)
+ pset.verbosity = PQERRORS_TERSE;
+ else if (pg_strcasecmp(newval, "sqlstate") == 0)
+ pset.verbosity = PQERRORS_SQLSTATE;
else
{
- PsqlVarEnumError("VERBOSITY", newval, "default, terse, verbose");
+ PsqlVarEnumError("VERBOSITY", newval, "default, verbose, terse, sqlstate");
return false;
}
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 22576adc51e..7c4e5fbacbe 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3652,7 +3652,7 @@ psql_completion(const char *text, int start, int end)
else if (TailMatchesCS("SHOW_CONTEXT"))
COMPLETE_WITH_CS("never", "errors", "always");
else if (TailMatchesCS("VERBOSITY"))
- COMPLETE_WITH_CS("default", "verbose", "terse");
+ COMPLETE_WITH_CS("default", "verbose", "terse", "sqlstate");
}
else if (TailMatchesCS("\\sf*"))
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_routines, NULL);
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index ec51fee383d..d582cfd4e9c 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -1017,6 +1017,24 @@ pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
val = PQresultErrorField(res, PG_DIAG_SEVERITY);
if (val)
appendPQExpBuffer(msg, "%s: ", val);
+
+ if (verbosity == PQERRORS_SQLSTATE)
+ {
+ /*
+ * If we have a SQLSTATE, print that and nothing else. If not (which
+ * shouldn't happen for server-generated errors, but might possibly
+ * happen for libpq-generated ones), fall back to TERSE format, as
+ * that seems better than printing nothing at all.
+ */
+ val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
+ if (val)
+ {
+ appendPQExpBuffer(msg, "%s\n", val);
+ return;
+ }
+ verbosity = PQERRORS_TERSE;
+ }
+
if (verbosity == PQERRORS_VERBOSE)
{
val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 27047ddd1f3..f44030b4b0d 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -112,7 +112,8 @@ typedef enum
{
PQERRORS_TERSE, /* single-line error messages */
PQERRORS_DEFAULT, /* recommended style */
- PQERRORS_VERBOSE /* all the facts, ma'am */
+ PQERRORS_VERBOSE, /* all the facts, ma'am */
+ PQERRORS_SQLSTATE /* only error severity and SQLSTATE code */
} PGVerbosity;
typedef enum
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index aa101de9063..c8b0ae3ede4 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -4491,6 +4491,26 @@ number of rows: 0
last error message: table "this_table_does_not_exist" does not exist
\echo 'last error code:' :LAST_ERROR_SQLSTATE
last error code: 42P01
+-- nondefault verbosity error settings (except verbose, which is too unstable)
+\set VERBOSITY terse
+SELECT 1 UNION;
+ERROR: syntax error at or near ";" at character 15
+\echo 'error:' :ERROR
+error: true
+\echo 'error code:' :SQLSTATE
+error code: 42601
+\echo 'last error message:' :LAST_ERROR_MESSAGE
+last error message: syntax error at or near ";"
+\set VERBOSITY sqlstate
+SELECT 1/0;
+ERROR: 22012
+\echo 'error:' :ERROR
+error: true
+\echo 'error code:' :SQLSTATE
+error code: 22012
+\echo 'last error message:' :LAST_ERROR_MESSAGE
+last error message: division by zero
+\set VERBOSITY default
-- working \gdesc
SELECT 3 AS three, 4 AS four \gdesc
Column | Type
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index fb7d17fc76e..a8b2cdc7416 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -1001,6 +1001,21 @@ DROP TABLE this_table_does_not_exist;
\echo 'last error message:' :LAST_ERROR_MESSAGE
\echo 'last error code:' :LAST_ERROR_SQLSTATE
+-- nondefault verbosity error settings (except verbose, which is too unstable)
+\set VERBOSITY terse
+SELECT 1 UNION;
+\echo 'error:' :ERROR
+\echo 'error code:' :SQLSTATE
+\echo 'last error message:' :LAST_ERROR_MESSAGE
+
+\set VERBOSITY sqlstate
+SELECT 1/0;
+\echo 'error:' :ERROR
+\echo 'error code:' :SQLSTATE
+\echo 'last error message:' :LAST_ERROR_MESSAGE
+
+\set VERBOSITY default
+
-- working \gdesc
SELECT 3 AS three, 4 AS four \gdesc
\echo 'error:' :ERROR