From 17858570833871373057530005f1477352b47af6 Mon Sep 17 00:00:00 2001
From: ChangAo Chen <cca5507@qq.com>
Date: Sun, 2 Aug 2026 23:00:48 +0800
Subject: [PATCH v1] Avoid building stderr message if possible.

---
 src/backend/utils/error/elog.c | 130 +++++++++++++++++++++------------
 1 file changed, 82 insertions(+), 48 deletions(-)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index b9d2c96b97a..d77cf84648a 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -3667,98 +3667,94 @@ unpack_sql_state(int sql_state)
 	return buf;
 }
 
-
 /*
- * Write error report to server's log
+ * Build a message formatted for stderr
  */
 static void
-send_message_to_server_log(ErrorData *edata)
+build_stderr_message(StringInfo buf, ErrorData *edata)
 {
-	StringInfoData buf;
-	bool		fallback_to_stderr = false;
+	initStringInfo(buf);
 
-	initStringInfo(&buf);
-
-	log_line_prefix(&buf, edata);
-	appendStringInfo(&buf, "%s:  ", _(error_severity(edata->elevel)));
+	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));
+		appendStringInfo(buf, "%s: ", unpack_sql_state(edata->sqlerrcode));
 
 	if (edata->message)
-		append_with_tabs(&buf, edata->message);
+		append_with_tabs(buf, edata->message);
 	else
-		append_with_tabs(&buf, _("missing error text"));
+		append_with_tabs(buf, _("missing error text"));
 
 	if (edata->cursorpos > 0)
-		appendStringInfo(&buf, _(" at character %d"),
+		appendStringInfo(buf, _(" at character %d"),
 						 edata->cursorpos);
 	else if (edata->internalpos > 0)
-		appendStringInfo(&buf, _(" at character %d"),
+		appendStringInfo(buf, _(" at character %d"),
 						 edata->internalpos);
 
-	appendStringInfoChar(&buf, '\n');
+	appendStringInfoChar(buf, '\n');
 
 	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');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("DETAIL:  "));
+			append_with_tabs(buf, edata->detail_log);
+			appendStringInfoChar(buf, '\n');
 		}
 		else if (edata->detail)
 		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("DETAIL:  "));
-			append_with_tabs(&buf, edata->detail);
-			appendStringInfoChar(&buf, '\n');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("DETAIL:  "));
+			append_with_tabs(buf, edata->detail);
+			appendStringInfoChar(buf, '\n');
 		}
 		if (edata->hint)
 		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("HINT:  "));
-			append_with_tabs(&buf, edata->hint);
-			appendStringInfoChar(&buf, '\n');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("HINT:  "));
+			append_with_tabs(buf, edata->hint);
+			appendStringInfoChar(buf, '\n');
 		}
 		if (edata->internalquery)
 		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("QUERY:  "));
-			append_with_tabs(&buf, edata->internalquery);
-			appendStringInfoChar(&buf, '\n');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("QUERY:  "));
+			append_with_tabs(buf, edata->internalquery);
+			appendStringInfoChar(buf, '\n');
 		}
 		if (edata->context && !edata->hide_ctx)
 		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("CONTEXT:  "));
-			append_with_tabs(&buf, edata->context);
-			appendStringInfoChar(&buf, '\n');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("CONTEXT:  "));
+			append_with_tabs(buf, edata->context);
+			appendStringInfoChar(buf, '\n');
 		}
 		if (Log_error_verbosity >= PGERROR_VERBOSE)
 		{
 			/* assume no newlines in funcname or filename... */
 			if (edata->funcname && edata->filename)
 			{
-				log_line_prefix(&buf, edata);
-				appendStringInfo(&buf, _("LOCATION:  %s, %s:%d\n"),
+				log_line_prefix(buf, edata);
+				appendStringInfo(buf, _("LOCATION:  %s, %s:%d\n"),
 								 edata->funcname, edata->filename,
 								 edata->lineno);
 			}
 			else if (edata->filename)
 			{
-				log_line_prefix(&buf, edata);
-				appendStringInfo(&buf, _("LOCATION:  %s:%d\n"),
+				log_line_prefix(buf, edata);
+				appendStringInfo(buf, _("LOCATION:  %s:%d\n"),
 								 edata->filename, edata->lineno);
 			}
 		}
 		if (edata->backtrace)
 		{
-			log_line_prefix(&buf, edata);
-			appendStringInfoString(&buf, _("BACKTRACE:  "));
-			append_with_tabs(&buf, edata->backtrace);
-			appendStringInfoChar(&buf, '\n');
+			log_line_prefix(buf, edata);
+			appendStringInfoString(buf, _("BACKTRACE:  "));
+			append_with_tabs(buf, edata->backtrace);
+			appendStringInfoChar(buf, '\n');
 		}
 	}
 
@@ -3767,11 +3763,22 @@ send_message_to_server_log(ErrorData *edata)
 	 */
 	if (check_log_of_query(edata))
 	{
-		log_line_prefix(&buf, edata);
-		appendStringInfoString(&buf, _("STATEMENT:  "));
-		append_with_tabs(&buf, debug_query_string);
-		appendStringInfoChar(&buf, '\n');
+		log_line_prefix(buf, edata);
+		appendStringInfoString(buf, _("STATEMENT:  "));
+		append_with_tabs(buf, debug_query_string);
+		appendStringInfoChar(buf, '\n');
 	}
+}
+
+/*
+ * Write error report to server's log
+ */
+static void
+send_message_to_server_log(ErrorData *edata)
+{
+	StringInfoData buf;
+	bool		fallback_to_stderr = false;
+	bool		has_stderr_message = false;
 
 #ifdef HAVE_SYSLOG
 	/* Write to syslog, if enabled */
@@ -3811,6 +3818,12 @@ send_message_to_server_log(ErrorData *edata)
 				break;
 		}
 
+		if (!has_stderr_message)
+		{
+			build_stderr_message(&buf, edata);
+			has_stderr_message = true;
+		}
+
 		write_syslog(syslog_level, buf.data);
 	}
 #endif							/* HAVE_SYSLOG */
@@ -3819,6 +3832,12 @@ send_message_to_server_log(ErrorData *edata)
 	/* Write to eventlog, if enabled */
 	if (Log_destination & LOG_DESTINATION_EVENTLOG)
 	{
+		if (!has_stderr_message)
+		{
+			build_stderr_message(&buf, edata);
+			has_stderr_message = true;
+		}
+
 		write_eventlog(edata->elevel, buf.data, buf.len);
 	}
 #endif							/* WIN32 */
@@ -3861,6 +3880,12 @@ send_message_to_server_log(ErrorData *edata)
 		whereToSendOutput == DestDebug ||
 		fallback_to_stderr)
 	{
+		if (!has_stderr_message)
+		{
+			build_stderr_message(&buf, edata);
+			has_stderr_message = true;
+		}
+
 		/*
 		 * Use the chunking protocol if we know the syslogger should be
 		 * catching stderr output, and we are not ourselves the syslogger.
@@ -3886,10 +3911,19 @@ send_message_to_server_log(ErrorData *edata)
 
 	/* If in the syslogger process, try to write messages direct to file */
 	if (syslogger_setup_done)
+	{
+		if (!has_stderr_message)
+		{
+			build_stderr_message(&buf, edata);
+			has_stderr_message = true;
+		}
+
 		write_syslogger_file(buf.data, buf.len, LOG_DESTINATION_STDERR);
+	}
 
 	/* No more need of the message formatted for stderr */
-	pfree(buf.data);
+	if (has_stderr_message)
+		pfree(buf.data);
 }
 
 /*
-- 
2.34.1

