>From 8b2bf6ae615d716ca9857017fd862386c6bdcd1f Mon Sep 17 00:00:00 2001
From: Craig Ringer <craig@2ndquadrant.com>
Date: Fri, 17 Oct 2014 11:18:18 +0800
Subject: [PATCH 1/2] Add an errhint_log, akin to errdetail_log

This allows a different HINT to be sent to the server error log
and to the client, which will be useful where there's security
sensitive information that's more appropriate for a HINT than
a DETAIL message.
---
 src/backend/utils/error/elog.c | 54 ++++++++++++++++++++++++++++++++----------
 src/include/utils/elog.h       |  7 ++++++
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 32a9663..59be8a6 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -1015,6 +1015,26 @@ errhint(const char *fmt,...)
 	return 0;					/* return value does not matter */
 }
 
+/*
+ * errhint_log --- add a hint_log error message text to the current error
+ */
+int
+errhint_log(const char *fmt,...)
+{
+	ErrorData  *edata = &errordata[errordata_stack_depth];
+	MemoryContext oldcontext;
+
+	recursion_depth++;
+	CHECK_STACK_DEPTH();
+	oldcontext = MemoryContextSwitchTo(edata->assoc_context);
+
+	EVALUATE_MESSAGE(edata->domain, hint_log, false, true);
+
+	MemoryContextSwitchTo(oldcontext);
+	recursion_depth--;
+	return 0;					/* return value does not matter */
+}
+
 
 /*
  * errcontext_msg --- add a context error message text to the current error
@@ -1498,6 +1518,8 @@ CopyErrorData(void)
 		newedata->detail_log = pstrdup(newedata->detail_log);
 	if (newedata->hint)
 		newedata->hint = pstrdup(newedata->hint);
+	if (newedata->hint_log)
+		newedata->hint_log = pstrdup(newedata->hint_log);
 	if (newedata->context)
 		newedata->context = pstrdup(newedata->context);
 	if (newedata->schema_name)
@@ -1536,6 +1558,8 @@ FreeErrorData(ErrorData *edata)
 		pfree(edata->detail_log);
 	if (edata->hint)
 		pfree(edata->hint);
+	if (edata->hint_log)
+		pfree(edata->hint_log);
 	if (edata->context)
 		pfree(edata->context);
 	if (edata->schema_name)
@@ -1618,6 +1642,8 @@ ReThrowError(ErrorData *edata)
 		newedata->detail_log = pstrdup(newedata->detail_log);
 	if (newedata->hint)
 		newedata->hint = pstrdup(newedata->hint);
+	if (newedata->hint_log)
+		newedata->hint_log = pstrdup(newedata->hint_log);
 	if (newedata->context)
 		newedata->context = pstrdup(newedata->context);
 	if (newedata->schema_name)
@@ -2659,8 +2685,11 @@ write_csvlog(ErrorData *edata)
 		appendCSVLiteral(&buf, edata->detail);
 	appendStringInfoChar(&buf, ',');
 
-	/* errhint */
-	appendCSVLiteral(&buf, edata->hint);
+	/* errhint or errhint_log */
+	if (edata->hint_log)
+		appendCSVLiteral(&buf, edata->hint_log);
+	else
+		appendCSVLiteral(&buf, edata->hint);
 	appendStringInfoChar(&buf, ',');
 
 	/* internal query */
@@ -2777,25 +2806,22 @@ send_message_to_server_log(ErrorData *edata)
 
 	if (Log_error_verbosity >= PGERROR_DEFAULT)
 	{
-		if (edata->detail_log)
-		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("DETAIL:  "));
-			append_with_tabs(&buf, edata->detail_log);
-			appendStringInfoChar(&buf, '\n');
-		}
-		else if (edata->detail)
+		const char * const detail 
+			= edata->detail_log != NULL ? edata->detail_log : edata->detail;
+		const char * const hint
+			= edata->hint_log != NULL ? edata->hint_log : edata->hint;
+		if (detail)
 		{
 			log_line_prefix(&buf, edata);
 			appendStringInfoString(&buf, _("DETAIL:  "));
-			append_with_tabs(&buf, edata->detail);
+			append_with_tabs(&buf, detail);
 			appendStringInfoChar(&buf, '\n');
 		}
-		if (edata->hint)
+		if (hint)
 		{
 			log_line_prefix(&buf, edata);
 			appendStringInfoString(&buf, _("HINT:  "));
-			append_with_tabs(&buf, edata->hint);
+			append_with_tabs(&buf, hint);
 			appendStringInfoChar(&buf, '\n');
 		}
 		if (edata->internalquery)
@@ -3079,6 +3105,8 @@ send_message_to_frontend(ErrorData *edata)
 			err_sendstring(&msgbuf, edata->hint);
 		}
 
+		/* hint_log is intentionally not used here */
+
 		if (edata->context)
 		{
 			pq_sendbyte(&msgbuf, PG_DIAG_CONTEXT);
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 92073be..3828c93 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -203,6 +203,12 @@ errhint(const char *fmt,...)
    the supplied arguments. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
 
+extern int
+errhint_log(const char *fmt,...)
+/* This extension allows gcc to check the format string for consistency with
+   the supplied arguments. */
+__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
+
 /*
  * errcontext() is typically called in error context callback functions, not
  * within an ereport() invocation. The callback function can be in a different
@@ -395,6 +401,7 @@ typedef struct ErrorData
 	char	   *detail;			/* detail error message */
 	char	   *detail_log;		/* detail error message for server log only */
 	char	   *hint;			/* hint message */
+	char	   *hint_log;		/* hint message for server log only */
 	char	   *context;		/* context message */
 	char	   *schema_name;	/* name of schema */
 	char	   *table_name;		/* name of table */
-- 
1.9.3

