I wrote:
> After sleeping on it, I think the right answer is to introduce the new
> error-message field (and not worry about 9.5).  Will work on a patch
> for that, unless I hear objections pretty soon.

So far as I can find, the attached is all we need to do to introduce a
new message field.  (This patch doesn't address the memory-context
questions, but it does fix the localization-driven failure demonstrated
upthread.)

Any objections?  Anyone want to bikeshed the field name?  I considered
PG_DIAG_SEVERITY_NONLOCALIZED and PG_DIAG_SEVERITY_ENGLISH before settling
on PG_DIAG_SEVERITY_ASCII, but I can't say I'm in love with that.

                        regards, tom lane

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index f22e3da..40ae0ff 100644
*** a/doc/src/sgml/libpq.sgml
--- b/doc/src/sgml/libpq.sgml
*************** char *PQresultErrorField(const PGresult 
*** 2767,2772 ****
--- 2767,2788 ----
            </listitem>
           </varlistentry>
  
+          <varlistentry id="libpq-pg-diag-severity-ascii">
+           <term><symbol>PG_DIAG_SEVERITY_ASCII</></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</>
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 9c96d8f..9bddb19 100644
*** a/doc/src/sgml/protocol.sgml
--- b/doc/src/sgml/protocol.sgml
*************** message.
*** 4884,4889 ****
--- 4884,4908 ----
  
  <varlistentry>
  <term>
+ <literal>A</>
+ </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</>
  </term>
  <listitem>
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index 921242f..b04a7ef 100644
*** a/src/backend/libpq/pqmq.c
--- b/src/backend/libpq/pqmq.c
*************** pq_parse_errornotice(StringInfo msg, Err
*** 237,246 ****
  		switch (code)
  		{
  			case PG_DIAG_SEVERITY:
  				if (strcmp(value, "DEBUG") == 0)
! 					edata->elevel = DEBUG1;		/* or some other DEBUG level */
  				else if (strcmp(value, "LOG") == 0)
! 					edata->elevel = LOG;		/* can't be COMMERROR */
  				else if (strcmp(value, "INFO") == 0)
  					edata->elevel = INFO;
  				else if (strcmp(value, "NOTICE") == 0)
--- 237,262 ----
  		switch (code)
  		{
  			case PG_DIAG_SEVERITY:
+ 				/* ignore, trusting we'll get a nonlocalized version */
+ 				break;
+ 			case PG_DIAG_SEVERITY_ASCII:
  				if (strcmp(value, "DEBUG") == 0)
! 				{
! 					/*
! 					 * 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)
! 				{
! 					/*
! 					 * 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)
*************** pq_parse_errornotice(StringInfo msg, Err
*** 254,264 ****
  				else if (strcmp(value, "PANIC") == 0)
  					edata->elevel = PANIC;
  				else
! 					elog(ERROR, "unknown error severity");
  				break;
  			case PG_DIAG_SQLSTATE:
  				if (strlen(value) != 5)
! 					elog(ERROR, "malformed sql state");
  				edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2],
  												  value[3], value[4]);
  				break;
--- 270,280 ----
  				else if (strcmp(value, "PANIC") == 0)
  					edata->elevel = PANIC;
  				else
! 					elog(ERROR, "unrecognized error severity: \"%s\"", value);
  				break;
  			case PG_DIAG_SQLSTATE:
  				if (strlen(value) != 5)
! 					elog(ERROR, "invalid SQLSTATE: \"%s\"", value);
  				edata->sqlerrcode = MAKE_SQLSTATE(value[0], value[1], value[2],
  												  value[3], value[4]);
  				break;
*************** pq_parse_errornotice(StringInfo msg, Err
*** 308,314 ****
  				edata->funcname = pstrdup(value);
  				break;
  			default:
! 				elog(ERROR, "unknown error field: %d", (int) code);
  				break;
  		}
  	}
--- 324,330 ----
  				edata->funcname = pstrdup(value);
  				break;
  			default:
! 				elog(ERROR, "unrecognized error field code: %d", (int) code);
  				break;
  		}
  	}
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 78d441d..ab71b50 100644
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
*************** write_csvlog(ErrorData *edata)
*** 2744,2750 ****
  	appendStringInfoChar(&buf, ',');
  
  	/* Error severity */
! 	appendStringInfoString(&buf, error_severity(edata->elevel));
  	appendStringInfoChar(&buf, ',');
  
  	/* SQL state code */
--- 2744,2750 ----
  	appendStringInfoChar(&buf, ',');
  
  	/* Error severity */
! 	appendStringInfoString(&buf, gettext(error_severity(edata->elevel)));
  	appendStringInfoChar(&buf, ',');
  
  	/* SQL state code */
*************** send_message_to_server_log(ErrorData *ed
*** 2861,2867 ****
  	formatted_log_time[0] = '\0';
  
  	log_line_prefix(&buf, edata);
! 	appendStringInfo(&buf, "%s:  ", error_severity(edata->elevel));
  
  	if (Log_error_verbosity >= PGERROR_VERBOSE)
  		appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
--- 2861,2867 ----
  	formatted_log_time[0] = '\0';
  
  	log_line_prefix(&buf, edata);
! 	appendStringInfo(&buf, "%s:  ", gettext(error_severity(edata->elevel)));
  
  	if (Log_error_verbosity >= PGERROR_VERBOSE)
  		appendStringInfo(&buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
*************** send_message_to_frontend(ErrorData *edat
*** 3144,3155 ****
  	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
  	{
  		/* New style with separate fields */
  		char		tbuf[12];
  		int			ssval;
  		int			i;
  
  		pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY);
! 		err_sendstring(&msgbuf, error_severity(edata->elevel));
  
  		/* unpack MAKE_SQLSTATE code */
  		ssval = edata->sqlerrcode;
--- 3144,3159 ----
  	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, gettext(sev));
! 		pq_sendbyte(&msgbuf, PG_DIAG_SEVERITY_ASCII);
! 		err_sendstring(&msgbuf, sev);
  
  		/* unpack MAKE_SQLSTATE code */
  		ssval = edata->sqlerrcode;
*************** send_message_to_frontend(ErrorData *edat
*** 3268,3274 ****
  
  		initStringInfo(&buf);
  
! 		appendStringInfo(&buf, "%s:  ", error_severity(edata->elevel));
  
  		if (edata->show_funcname && edata->funcname)
  			appendStringInfo(&buf, "%s: ", edata->funcname);
--- 3272,3278 ----
  
  		initStringInfo(&buf);
  
! 		appendStringInfo(&buf, "%s:  ", gettext(error_severity(edata->elevel)));
  
  		if (edata->show_funcname && edata->funcname)
  			appendStringInfo(&buf, "%s: ", edata->funcname);
*************** get_errno_symbol(int errnum)
*** 3578,3584 ****
  
  
  /*
!  * error_severity --- get localized string representing elevel
   */
  static const char *
  error_severity(int elevel)
--- 3582,3591 ----
  
  
  /*
!  * error_severity --- get string representing elevel
!  *
!  * The string is not localized here, but we mark the strings for translation
!  * so that callers can invoke gettext on the result.
   */
  static const char *
  error_severity(int elevel)
*************** error_severity(int elevel)
*** 3592,3620 ****
  		case DEBUG3:
  		case DEBUG4:
  		case DEBUG5:
! 			prefix = _("DEBUG");
  			break;
  		case LOG:
  		case LOG_SERVER_ONLY:
! 			prefix = _("LOG");
  			break;
  		case INFO:
! 			prefix = _("INFO");
  			break;
  		case NOTICE:
! 			prefix = _("NOTICE");
  			break;
  		case WARNING:
! 			prefix = _("WARNING");
  			break;
  		case ERROR:
! 			prefix = _("ERROR");
  			break;
  		case FATAL:
! 			prefix = _("FATAL");
  			break;
  		case PANIC:
! 			prefix = _("PANIC");
  			break;
  		default:
  			prefix = "???";
--- 3599,3627 ----
  		case DEBUG3:
  		case DEBUG4:
  		case DEBUG5:
! 			prefix = gettext_noop("DEBUG");
  			break;
  		case LOG:
  		case LOG_SERVER_ONLY:
! 			prefix = gettext_noop("LOG");
  			break;
  		case INFO:
! 			prefix = gettext_noop("INFO");
  			break;
  		case NOTICE:
! 			prefix = gettext_noop("NOTICE");
  			break;
  		case WARNING:
! 			prefix = gettext_noop("WARNING");
  			break;
  		case ERROR:
! 			prefix = gettext_noop("ERROR");
  			break;
  		case FATAL:
! 			prefix = gettext_noop("FATAL");
  			break;
  		case PANIC:
! 			prefix = gettext_noop("PANIC");
  			break;
  		default:
  			prefix = "???";
diff --git a/src/include/postgres_ext.h b/src/include/postgres_ext.h
index 74c344c..e318e18 100644
*** a/src/include/postgres_ext.h
--- b/src/include/postgres_ext.h
*************** typedef PG_INT64_TYPE pg_int64;
*** 49,54 ****
--- 49,55 ----
   * applications.
   */
  #define PG_DIAG_SEVERITY		'S'
+ #define PG_DIAG_SEVERITY_ASCII	'A'
  #define PG_DIAG_SQLSTATE		'C'
  #define PG_DIAG_MESSAGE_PRIMARY 'M'
  #define PG_DIAG_MESSAGE_DETAIL	'D'
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index d1b91c8..58c8cab 100644
*** a/src/interfaces/libpq/fe-exec.c
--- b/src/interfaces/libpq/fe-exec.c
*************** pqInternalNotice(const PGNoticeHooks *ho
*** 824,829 ****
--- 824,830 ----
  	 */
  	pqSaveMessageField(res, PG_DIAG_MESSAGE_PRIMARY, msgBuf);
  	pqSaveMessageField(res, PG_DIAG_SEVERITY, libpq_gettext("NOTICE"));
+ 	pqSaveMessageField(res, PG_DIAG_SEVERITY_ASCII, "NOTICE");
  	/* XXX should provide a SQLSTATE too? */
  
  	/*
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to