From bd0df4139bf045edd3400ee1b321009a4d2754d3 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 13 Feb 2010 22:21:15 +0100
Subject: [PATCH 1/3] Support transporting flags in the 'elevel' argument of ereport(). The
 reason is the wish to support avoiding the error to the client which
 was only possible using the COMERROR level - which is not a error but
 just a log message.
 The only supported flag till now is LOG_NO_CLIENT which does what
 COMERROR did for all error levels

---
 src/backend/utils/error/elog.c |    8 +++++---
 src/include/utils/elog.h       |   29 ++++++++++++++++++++---------
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index e321b99..6e174d8 100644
*** a/src/backend/utils/error/elog.c
--- b/src/backend/utils/error/elog.c
*************** errstart(int elevel, const char *filenam
*** 214,220 ****
  	bool		output_to_server;
  	bool		output_to_client = false;
  	int			i;
! 
  	/*
  	 * Check some cases in which we want to promote an error into a more
  	 * severe error.  None of this logic applies for non-error messages.
--- 214,221 ----
  	bool		output_to_server;
  	bool		output_to_client = false;
  	int			i;
! 	int			eflags = elevel & LOG_FLAG_MASK;
! 	elevel = elevel & ~LOG_FLAG_MASK;
  	/*
  	 * Check some cases in which we want to promote an error into a more
  	 * severe error.  None of this logic applies for non-error messages.
*************** errstart(int elevel, const char *filenam
*** 274,280 ****
  		output_to_server = (elevel >= log_min_messages);
  
  	/* Determine whether message is enabled for client output */
! 	if (whereToSendOutput == DestRemote && elevel != COMMERROR)
  	{
  		/*
  		 * client_min_messages is honored only after we complete the
--- 275,281 ----
  		output_to_server = (elevel >= log_min_messages);
  
  	/* Determine whether message is enabled for client output */
! 	if (whereToSendOutput == DestRemote)
  	{
  		/*
  		 * client_min_messages is honored only after we complete the
*************** errstart(int elevel, const char *filenam
*** 333,338 ****
--- 334,340 ----
  	edata = &errordata[errordata_stack_depth];
  	MemSet(edata, 0, sizeof(ErrorData));
  	edata->elevel = elevel;
+ 	edata->eflags = eflags;
  	edata->output_to_server = output_to_server;
  	edata->output_to_client = output_to_client;
  	edata->filename = filename;
*************** EmitErrorReport(void)
*** 1168,1174 ****
  		send_message_to_server_log(edata);
  
  	/* Send to client, if enabled */
! 	if (edata->output_to_client)
  		send_message_to_frontend(edata);
  
  	MemoryContextSwitchTo(oldcontext);
--- 1170,1176 ----
  		send_message_to_server_log(edata);
  
  	/* Send to client, if enabled */
! 	if (edata->output_to_client && !(edata->eflags & LOG_NO_CLIENT))
  		send_message_to_frontend(edata);
  
  	MemoryContextSwitchTo(oldcontext);
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 92641ba..1853e1d 100644
*** a/src/include/utils/elog.h
--- b/src/include/utils/elog.h
***************
*** 16,21 ****
--- 16,28 ----
  
  #include <setjmp.h>
  
+ #define LOG_FLAG_MASK ((~0)<<20)
+ 
+ /* logging flags */
+ #define LOG_NO_CLIENT (2<<30)   /* Don't send to the client. Helpfull
+                                  * if it would confuse the client at
+                                  * that moment */
+ 
  /* Error level codes */
  #define DEBUG5		10			/* Debugging messages, in categories of
  								 * decreasing detail. */
***************
*** 25,54 ****
  #define DEBUG1		14			/* used by GUC debug_* variables */
  #define LOG			15			/* Server operational messages; sent only to
  								 * server log by default. */
! #define COMMERROR	16			/* Client communication problems; same as LOG
  								 * for server reporting, but never sent to
! 								 * client. */
! #define INFO		17			/* Messages specifically requested by user (eg
  								 * VACUUM VERBOSE output); always sent to
  								 * client regardless of client_min_messages,
  								 * but by default not sent to server log. */
! #define NOTICE		18			/* Helpful messages to users about query
  								 * operation; sent to client and server log by
  								 * default. */
! #define WARNING		19			/* Warnings.  NOTICE is for expected messages
  								 * like implicit sequence creation by SERIAL.
  								 * WARNING is for unexpected messages. */
! #define ERROR		20			/* user error - abort transaction; return to
  								 * known state */
  /* Save ERROR value in PGERROR so it can be restored when Win32 includes
   * modify it.  We have to use a constant rather than ERROR because macros
   * are expanded only when referenced outside macros.
   */
  #ifdef WIN32
! #define PGERROR		20
  #endif
! #define FATAL		21			/* fatal error - abort process */
! #define PANIC		22			/* take down the other backends with me */
  
   /* #define DEBUG DEBUG1 */	/* Backward compatibility with pre-7.3 */
  
--- 32,64 ----
  #define DEBUG1		14			/* used by GUC debug_* variables */
  #define LOG			15			/* Server operational messages; sent only to
  								 * server log by default. */
! #define COMMERROR	(LOG|LOG_NO_CLIENT)/* Client communication problems; same as LOG
  								 * for server reporting, but never sent to
! 								 * client. For backward compatibility this is
! 								 * is available without explicitly specifying
! 								 * LOG_NO_CLIENT.*/
! #define INFO		16			/* Messages specifically requested by user (eg
  								 * VACUUM VERBOSE output); always sent to
  								 * client regardless of client_min_messages,
  								 * but by default not sent to server log. */
! #define NOTICE		17			/* Helpful messages to users about query
  								 * operation; sent to client and server log by
  								 * default. */
! #define WARNING		18			/* Warnings.  NOTICE is for expected messages
  								 * like implicit sequence creation by SERIAL.
  								 * WARNING is for unexpected messages. */
! #define ERROR		19			/* user error - abort transaction; return to
  								 * known state */
  /* Save ERROR value in PGERROR so it can be restored when Win32 includes
   * modify it.  We have to use a constant rather than ERROR because macros
   * are expanded only when referenced outside macros.
   */
  #ifdef WIN32
! #define PGERROR		19
  #endif
! #define FATAL		20			/* fatal error - abort process */
! #define PANIC		21			/* take down the other backends with me */
! 
  
   /* #define DEBUG DEBUG1 */	/* Backward compatibility with pre-7.3 */
  
*************** extern PGDLLIMPORT sigjmp_buf *PG_except
*** 291,296 ****
--- 301,307 ----
  typedef struct ErrorData
  {
  	int			elevel;			/* error level */
+ 	int			eflags;			/* error flags */
  	bool		output_to_server;		/* will report to server log? */
  	bool		output_to_client;		/* will report to client? */
  	bool		show_funcname;	/* true to force funcname inclusion */
-- 
1.7.3.rc1.5.g73aa2

