mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-28 15:07:20 +02:00
Add a nonlocalized version of the severity field to client error messages.
This has been requested a few times, but the use-case for it was never entirely clear. The reason for adding it now is that transmission of error reports from parallel workers fails when NLS is active, because pq_parse_errornotice() wrongly assumes that the existing severity field is nonlocalized. There are other ways we could have fixed that, but the other options were basically kluges, whereas this way provides something that's at least arguably a useful feature along with the bug fix. Per report from Jakob Egger. Back-patch into 9.6, because otherwise parallel query is essentially unusable in non-English locales. The problem exists in 9.5 as well, but we don't want to risk changing on-the-wire behavior in 9.5 (even though the possibility of new error fields is specifically called out in the protocol document). It may be sufficient to leave the issue unfixed in 9.5, given the very limited usefulness of pq_parse_errornotice in that version. Discussion: <A88E0006-13CB-49C6-95CC-1A77D717213C@eggerapps.at>
This commit is contained in:
parent
bef2d627f3
commit
e796d0abab
@ -2767,6 +2767,22 @@ char *PQresultErrorField(const PGresult *res, int fieldcode);
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="libpq-pg-diag-severity-nonlocalized">
|
||||
<term><symbol>PG_DIAG_SEVERITY_NONLOCALIZED</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The severity; the field contents are <literal>ERROR</>,
|
||||
<literal>FATAL</>, or <literal>PANIC</> (in an error message),
|
||||
or <literal>WARNING</>, <literal>NOTICE</>, <literal>DEBUG</>,
|
||||
<literal>INFO</>, or <literal>LOG</> (in a notice message).
|
||||
This is identical to the <symbol>PG_DIAG_SEVERITY</> field except
|
||||
that the contents are never localized. This is present only in
|
||||
reports generated by <productname>PostgreSQL</> versions 9.6
|
||||
and later.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="libpq-pg-diag-sqlstate">
|
||||
<term>
|
||||
<symbol>PG_DIAG_SQLSTATE</>
|
||||
|
@ -4882,6 +4882,25 @@ message.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>V</>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Severity: the field contents are
|
||||
<literal>ERROR</>, <literal>FATAL</>, or
|
||||
<literal>PANIC</> (in an error message), or
|
||||
<literal>WARNING</>, <literal>NOTICE</>, <literal>DEBUG</>,
|
||||
<literal>INFO</>, or <literal>LOG</> (in a notice message).
|
||||
This is identical to the <literal>S</> field except
|
||||
that the contents are never localized. This is present only in
|
||||
messages generated by <productname>PostgreSQL</> versions 9.6
|
||||
and later.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
<literal>C</>
|
||||
|
@ -237,10 +237,26 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
|
||||
switch (code)
|
||||
{
|
||||
case PG_DIAG_SEVERITY:
|
||||
/* ignore, trusting we'll get a nonlocalized version */
|
||||
break;
|
||||
case PG_DIAG_SEVERITY_NONLOCALIZED:
|
||||
if (strcmp(value, "DEBUG") == 0)
|
||||
edata->elevel = DEBUG1; /* or some other DEBUG level */
|
||||
{
|
||||
/*
|
||||
* We can't reconstruct the exact DEBUG level, but
|
||||
* presumably it was >= client_min_messages, so select
|
||||
* DEBUG1 to ensure we'll pass it on to the client.
|
||||
*/
|
||||
edata->elevel = DEBUG1;
|
||||
}
|
||||
else if (strcmp(value, "LOG") == 0)
|
||||
edata->elevel = LOG; /* can't be COMMERROR */
|
||||
{
|
||||
/*
|
||||
* It can't be LOG_SERVER_ONLY, or the worker wouldn't
|
||||
* have sent it to us; so LOG is the correct value.
|
||||
*/
|
||||
edata->elevel = LOG;
|
||||
}
|
||||
else if (strcmp(value, "INFO") == 0)
|
||||
edata->elevel = INFO;
|
||||
else if (strcmp(value, "NOTICE") == 0)
|
||||
@ -254,11 +270,11 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
|
||||
else if (strcmp(value, "PANIC") == 0)
|
||||
edata->elevel = PANIC;
|
||||
else
|
||||
elog(ERROR, "unknown error severity");
|
||||
elog(ERROR, "unrecognized error severity: \"%s\"", value);
|
||||
break;
|
||||
case PG_DIAG_SQLSTATE:
|
||||
if (strlen(value) != 5)
|
||||
elog(ERROR, "malformed sql state");
|
||||
elog(ERROR, "invalid SQLSTATE: \"%s\"", value);
|
||||
edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2],
|
||||
value[3], value[4]);
|
||||
break;
|
||||
@ -308,7 +324,7 @@ pq_parse_errornotice(StringInfo msg, ErrorData *edata)
|
||||
edata->funcname = pstrdup(value);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unknown error field: %d", (int) code);
|
||||
elog(ERROR, "unrecognized error field code: %d", (int) code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2753,7 +2753,7 @@ write_csvlog(ErrorData *edata)
|
||||
appendStringInfoChar(&buf, ',');
|
||||
|
||||
/* Error severity */
|
||||
appendStringInfoString(&buf, error_severity(edata->elevel));
|
||||
appendStringInfoString(&buf, _(error_severity(edata->elevel)));
|
||||
appendStringInfoChar(&buf, ',');
|
||||
|
||||
/* SQL state code */
|
||||
@ -2870,7 +2870,7 @@ send_message_to_server_log(ErrorData *edata)
|
||||
formatted_log_time[0] = '\0';
|
||||
|
||||
log_line_prefix(&buf, edata);
|
||||
appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
|
||||
appendStringInfo(&buf, "%s: ", _(error_severity(edata->elevel)));
|
||||
|
||||
if (Log_error_verbosity >= PGERROR_VERBOSE)
|
||||
appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
|
||||
@ -3153,12 +3153,16 @@ send_message_to_frontend(ErrorData *edata)
|
||||
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
|
||||
{
|
||||
/* New style with separate fields */
|
||||
const char *sev;
|
||||
char tbuf[12];
|
||||
int ssval;
|
||||
int i;
|
||||
|
||||
sev = error_severity(edata->elevel);
|
||||
pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
|
||||
err_sendstring(&msgbuf, error_severity(edata->elevel));
|
||||
err_sendstring(&msgbuf, _(sev));
|
||||
pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY_NONLOCALIZED);
|
||||
err_sendstring(&msgbuf, sev);
|
||||
|
||||
/* unpack MAKE_SQLSTATE code */
|
||||
ssval = edata->sqlerrcode;
|
||||
@ -3277,7 +3281,7 @@ send_message_to_frontend(ErrorData *edata)
|
||||
|
||||
initStringInfo(&buf);
|
||||
|
||||
appendStringInfo(&buf, "%s: ", error_severity(edata->elevel));
|
||||
appendStringInfo(&buf, "%s: ", _(error_severity(edata->elevel)));
|
||||
|
||||
if (edata->show_funcname && edata->funcname)
|
||||
appendStringInfo(&buf, "%s: ", edata->funcname);
|
||||
@ -3587,7 +3591,10 @@ get_errno_symbol(int errnum)
|
||||
|
||||
|
||||
/*
|
||||
* error_severity --- get localized string representing elevel
|
||||
* error_severity --- get string representing elevel
|
||||
*
|
||||
* The string is not localized here, but we mark the strings for translation
|
||||
* so that callers can invoke _() on the result.
|
||||
*/
|
||||
static const char *
|
||||
error_severity(int elevel)
|
||||
@ -3601,29 +3608,29 @@ error_severity(int elevel)
|
||||
case DEBUG3:
|
||||
case DEBUG4:
|
||||
case DEBUG5:
|
||||
prefix = _("DEBUG");
|
||||
prefix = gettext_noop("DEBUG");
|
||||
break;
|
||||
case LOG:
|
||||
case LOG_SERVER_ONLY:
|
||||
prefix = _("LOG");
|
||||
prefix = gettext_noop("LOG");
|
||||
break;
|
||||
case INFO:
|
||||
prefix = _("INFO");
|
||||
prefix = gettext_noop("INFO");
|
||||
break;
|
||||
case NOTICE:
|
||||
prefix = _("NOTICE");
|
||||
prefix = gettext_noop("NOTICE");
|
||||
break;
|
||||
case WARNING:
|
||||
prefix = _("WARNING");
|
||||
prefix = gettext_noop("WARNING");
|
||||
break;
|
||||
case ERROR:
|
||||
prefix = _("ERROR");
|
||||
prefix = gettext_noop("ERROR");
|
||||
break;
|
||||
case FATAL:
|
||||
prefix = _("FATAL");
|
||||
prefix = gettext_noop("FATAL");
|
||||
break;
|
||||
case PANIC:
|
||||
prefix = _("PANIC");
|
||||
prefix = gettext_noop("PANIC");
|
||||
break;
|
||||
default:
|
||||
prefix = "???";
|
||||
|
@ -49,6 +49,7 @@ typedef PG_INT64_TYPE pg_int64;
|
||||
* applications.
|
||||
*/
|
||||
#define PG_DIAG_SEVERITY 'S'
|
||||
#define PG_DIAG_SEVERITY_NONLOCALIZED 'V'
|
||||
#define PG_DIAG_SQLSTATE 'C'
|
||||
#define PG_DIAG_MESSAGE_PRIMARY 'M'
|
||||
#define PG_DIAG_MESSAGE_DETAIL 'D'
|
||||
|
@ -824,6 +824,7 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
|
||||
*/
|
||||
pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
|
||||
pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
|
||||
pqSaveMessageField(res, PG_DIAG_SEVERITY_NONLOCALIZED, "NOTICE");
|
||||
/* XXX should provide a SQLSTATE too? */
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user