From 9fd842c4b20d55746d34a96bc6baec7d2242c2cf Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 2 Sep 2002 05:42:54 +0000
Subject: [PATCH] Add GUC variable to print original query to the server logs
 when there is an error, warning, etc.

Gavin Sherry
---
 doc/src/sgml/runtime.sgml                     | 29 ++++++-
 src/backend/utils/error/elog.c                | 87 +++----------------
 src/backend/utils/misc/guc.c                  | 74 +++++++++++++++-
 src/backend/utils/misc/postgresql.conf.sample |  3 +
 src/bin/psql/tab-complete.c                   |  4 +-
 src/include/utils/elog.h                      | 14 +--
 src/include/utils/guc.h                       | 24 ++++-
 7 files changed, 139 insertions(+), 96 deletions(-)

diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 42677b20e14..d43461e61b7 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.132 2002/09/01 23:26:06 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.133 2002/09/02 05:42:54 momjian Exp $
 -->
 
 <Chapter Id="runtime">
@@ -942,7 +942,6 @@ env PGOPTIONS='-c geqo=off' psql
        </para>
       </listitem>
      </varlistentry>
-
      <varlistentry>
       <term><varname>EXPLAIN_PRETTY_PRINT</varname> (<type>boolean</type>)</term>
       <listitem>
@@ -978,6 +977,28 @@ env PGOPTIONS='-c geqo=off' psql
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><varname>LOG_MIN_ERROR_STATEMENT</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+        This controls which log messages are accompanied by the original
+        query which generated the message. All queries matching the setting
+        or which are of a higher severity than the setting are logged. The
+        default is <literal>ERROR</literal>. Valid values are
+        <literal>DEBUG5</literal>, <literal>DEBUG4</literal>, 
+        <literal>DEBUG3</literal>, <literal>DEBUG2</literal>, 
+        <literal>DEBUG1</literal>, <literal>INFO</literal>,
+        <literal>NOTICE</literal>, <literal>WARNING</literal>
+        and <literal>ERROR</literal>.
+       </para>
+       <para>
+        It is recommended you enable <literal>LOG_PID</literal> as well
+        so you can more easily match the error statement with the error
+        message.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><varname>LOG_PID</varname> (<type>boolean</type>)</term>
       <listitem>
@@ -1005,8 +1026,8 @@ env PGOPTIONS='-c geqo=off' psql
       <listitem>
        <para>
         Prints the duration of every completed query.  To use this option, 
-        enable LOG_STATEMENT and LOG_PID so you can link the original query
-        to the duration using the process id.
+        enable <literal>LOG_STATEMENT</> and <literal>LOG_PID</> so you 
+        can link the original query to the duration using the process id.
        </para>
       </listitem>
      </varlistentry>
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 61ce577536d..9258dd9fbc3 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.101 2002/09/02 02:47:05 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.102 2002/09/02 05:42:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,17 +33,10 @@
 #include "storage/proc.h"
 #include "tcop/tcopprot.h"
 #include "utils/memutils.h"
+#include "utils/guc.h"
 
 #include "mb/pg_wchar.h"
 
-int			server_min_messages;
-char	   *server_min_messages_str = NULL;
-const char	server_min_messages_str_default[] = "notice";
-
-int			client_min_messages;
-char	   *client_min_messages_str = NULL;
-const char	client_min_messages_str_default[] = "notice";
-
 #ifdef HAVE_SYSLOG
 /*
  * 0 = only stdout/stderr
@@ -345,6 +338,7 @@ elog(int lev, const char *fmt,...)
 		}
 	}
 
+
 	/*
 	 * Message prepared; send it where it should go
 	 */
@@ -433,6 +427,14 @@ elog(int lev, const char *fmt,...)
 	if (msg_buf != msg_fixedbuf)
 		free(msg_buf);
 
+	/* If the user wants this elog() generating query logged,
+	 * do so. We only want to log if the query has been
+	 * written to debug_query_string. Also, avoid infinite loops.
+	 */
+
+	if(lev != LOG && lev >= log_min_error_statement && debug_query_string)
+		elog(LOG,"statement: %s",debug_query_string);
+
 	/*
 	 * Perform error recovery action as specified by lev.
 	 */
@@ -835,71 +837,4 @@ elog_message_prefix(int lev)
 }
 
 
-/*
- * GUC support routines
- */
-const char *
-assign_server_min_messages(const char *newval,
-						   bool doit, bool interactive)
-{
-	if (strcasecmp(newval, "debug") == 0)
-		{ if (doit) server_min_messages = DEBUG1; }
-	else if (strcasecmp(newval, "debug5") == 0)
-		{ if (doit) server_min_messages = DEBUG5; }
-	else if (strcasecmp(newval, "debug4") == 0)
-		{ if (doit) server_min_messages = DEBUG4; }
-	else if (strcasecmp(newval, "debug3") == 0)
-		{ if (doit) server_min_messages = DEBUG3; }
-	else if (strcasecmp(newval, "debug2") == 0)
-		{ if (doit) server_min_messages = DEBUG2; }
-	else if (strcasecmp(newval, "debug1") == 0)
-		{ if (doit) server_min_messages = DEBUG1; }
-	else if (strcasecmp(newval, "info") == 0)
-		{ if (doit) server_min_messages = INFO; }
-	else if (strcasecmp(newval, "notice") == 0)
-		{ if (doit) server_min_messages = NOTICE; }
-	else if (strcasecmp(newval, "warning") == 0)
-		{ if (doit) server_min_messages = WARNING; }
-	else if (strcasecmp(newval, "error") == 0)
-		{ if (doit) server_min_messages = ERROR; }
-	else if (strcasecmp(newval, "log") == 0)
-		{ if (doit) server_min_messages = LOG; }
-	else if (strcasecmp(newval, "fatal") == 0)
-		{ if (doit) server_min_messages = FATAL; }
-	else if (strcasecmp(newval, "panic") == 0)
-		{ if (doit) server_min_messages = PANIC; }
-	else
-		return NULL;			/* fail */
-	return newval;				/* OK */
-}
 
-const char *
-assign_client_min_messages(const char *newval,
-						   bool doit, bool interactive)
-{
-	if (strcasecmp(newval, "debug") == 0)
-		{ if (doit) client_min_messages = DEBUG1; }
-	else if (strcasecmp(newval, "debug5") == 0)
-		{ if (doit) client_min_messages = DEBUG5; }
-	else if (strcasecmp(newval, "debug4") == 0)
-		{ if (doit) client_min_messages = DEBUG4; }
-	else if (strcasecmp(newval, "debug3") == 0)
-		{ if (doit) client_min_messages = DEBUG3; }
-	else if (strcasecmp(newval, "debug2") == 0)
-		{ if (doit) client_min_messages = DEBUG2; }
-	else if (strcasecmp(newval, "debug1") == 0)
-		{ if (doit) client_min_messages = DEBUG1; }
-	else if (strcasecmp(newval, "log") == 0)
-		{ if (doit) client_min_messages = LOG; }
-	else if (strcasecmp(newval, "info") == 0)
-		{ if (doit) client_min_messages = INFO; }
-	else if (strcasecmp(newval, "notice") == 0)
-		{ if (doit) client_min_messages = NOTICE; }
-	else if (strcasecmp(newval, "warning") == 0)
-		{ if (doit) client_min_messages = WARNING; }
-	else if (strcasecmp(newval, "error") == 0)
-		{ if (doit) client_min_messages = ERROR; }
-	else
-		return NULL;			/* fail */
-	return newval;				/* OK */
-}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0c24034b5f2..a1c2f24b77f 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -5,7 +5,7 @@
  * command, configuration file, and command line options.
  * See src/backend/utils/misc/README for more information.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.91 2002/09/02 01:05:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.92 2002/09/02 05:42:54 momjian Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -71,6 +71,9 @@ static const char *assign_facility(const char *facility,
 								   bool doit, bool interactive);
 #endif
 
+static const char *assign_msglvl(int *var, const char *newval,
+									bool doit, bool interactive);
+
 /*
  * Debugging options
  */
@@ -99,6 +102,19 @@ bool		Australian_timezones = false;
 
 bool		Password_encryption = true;
 
+int			log_min_error_statement;
+char		*log_min_error_statement_str = NULL;
+const char	log_min_error_statement_str_default[] = "error";
+
+int         server_min_messages;
+char       *server_min_messages_str = NULL;
+const char  server_min_messages_str_default[] = "notice";
+
+int         client_min_messages;
+char       *client_min_messages_str = NULL;
+const char  client_min_messages_str_default[] = "notice";
+
+
 #ifndef PG_KRB_SRVTAB
 #define PG_KRB_SRVTAB ""
 #endif
@@ -726,6 +742,11 @@ static struct config_string
 		client_min_messages_str_default, assign_client_min_messages, NULL
 	},
 
+	{
+		{ "log_min_error_statement", PGC_USERSET }, &log_min_error_statement_str,
+		log_min_error_statement_str_default, assign_min_error_statement, NULL
+	},
+
 	{
 		{ "DateStyle", PGC_USERSET, GUC_LIST_INPUT }, &datestyle_string,
 		"ISO, US", assign_datestyle, show_datestyle
@@ -2877,3 +2898,54 @@ GUCArrayDelete(ArrayType *array, const char *name)
 
 	return newarray;
 }
+
+const char *
+assign_server_min_messages(const char *newval,
+						   bool doit, bool interactive)
+{
+	return(assign_msglvl(&server_min_messages,newval,doit,interactive));
+}
+
+const char *
+assign_client_min_messages(const char *newval,
+						   bool doit, bool interactive)
+{
+	return(assign_msglvl(&client_min_messages,newval,doit,interactive));
+}
+
+const char *
+assign_min_error_statement(const char *newval, bool doit, bool interactive)
+{
+	return(assign_msglvl(&log_min_error_statement,newval,doit,interactive));
+}
+
+static const char *
+assign_msglvl(int *var, const char *newval, bool doit, bool interactive)
+{
+	if (strcasecmp(newval, "debug") == 0)
+		{ if (doit) (*var) = DEBUG1; }
+	else if (strcasecmp(newval, "debug5") == 0)
+		{ if (doit) (*var) = DEBUG5; }
+	else if (strcasecmp(newval, "debug4") == 0)
+		{ if (doit) (*var) = DEBUG4; }
+	else if (strcasecmp(newval, "debug3") == 0)
+		{ if (doit) (*var) = DEBUG3; }
+	else if (strcasecmp(newval, "debug2") == 0)
+		{ if (doit) (*var) = DEBUG2; }
+	else if (strcasecmp(newval, "debug1") == 0)
+		{ if (doit) (*var) = DEBUG1; }
+	else if (strcasecmp(newval, "log") == 0)
+		{ if (doit) (*var) = LOG; }
+	else if (strcasecmp(newval, "info") == 0)
+		{ if (doit) (*var) = INFO; }
+	else if (strcasecmp(newval, "notice") == 0)
+		{ if (doit) (*var) = NOTICE; }
+	else if (strcasecmp(newval, "warning") == 0)
+		{ if (doit) (*var) = WARNING; }
+	else if (strcasecmp(newval, "error") == 0)
+		{ if (doit) (*var) = ERROR; }
+	else
+		return NULL;			/* fail */
+	return newval;				/* OK */
+}
+
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 3bcf77c52ce..c5973422635 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -127,6 +127,9 @@
 #log_duration = false
 #log_timestamp = false
 
+#log_min_error_statement = error		# Values in order of increasing severity:
+									# debug5, debug4, debug3, debug2, debug1,
+					                # info, notice, warning, error
 #debug_print_parse = false
 #debug_print_rewritten = false
 #debug_print_plan = false
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 3611eaec442..72a24e38348 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000-2002 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.61 2002/09/01 23:26:06 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.62 2002/09/02 05:42:54 momjian Exp $
  */
 
 /*----------------------------------------------------------------------
@@ -271,7 +271,7 @@ psql_completion(char *text, int start, int end)
 		"default_transaction_isolation",
 		"search_path",
 		"statement_timeout",
-
+		"log_min_error_statement",
 		NULL
 	};
 
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 8b0414dc3fa..ba78aa3629f 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: elog.h,v 1.38 2002/06/20 20:29:52 momjian Exp $
+ * $Id: elog.h,v 1.39 2002/09/02 05:42:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,22 +47,12 @@ extern int	Use_syslog;
 extern bool Log_timestamp;
 extern bool Log_pid;
 
-extern char	   *server_min_messages_str;
-extern char	   *client_min_messages_str;
-extern const char server_min_messages_str_default[];
-extern const char client_min_messages_str_default[];
-
 extern void
 elog(int lev, const char *fmt,...)
 /* This extension allows gcc to check the format string for consistency with
    the supplied arguments. */
 __attribute__((format(printf, 2, 3)));
 
-extern int	DebugFileOpen(void);
-
-extern const char *assign_server_min_messages(const char *newval,
-											  bool doit, bool interactive);
-extern const char *assign_client_min_messages(const char *newval,
-											  bool doit, bool interactive);
+extern int  DebugFileOpen(void);
 
 #endif   /* ELOG_H */
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index ad511f50a6f..5e63bb512f8 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -4,7 +4,7 @@
  * External declarations pertaining to backend/utils/misc/guc.c and
  * backend/utils/misc/guc-file.l
  *
- * $Id: guc.h,v 1.21 2002/09/01 23:26:06 momjian Exp $
+ * $Id: guc.h,v 1.22 2002/09/02 05:42:54 momjian Exp $
  */
 #ifndef GUC_H
 #define GUC_H
@@ -100,6 +100,13 @@ extern void ProcessGUCArray(ArrayType *array, GucSource source);
 extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
 extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
 
+extern const char *assign_min_error_statement(const char *newval, bool doit,
+			bool interactive);
+
+extern const char *assign_server_min_messages(const char *newval,
+                                              bool doit, bool interactive);
+extern const char *assign_client_min_messages(const char *newval,
+                                              bool doit, bool interactive);
 extern bool Log_statement;
 extern bool Log_duration;
 extern bool Debug_print_plan;
@@ -118,4 +125,19 @@ extern bool Explain_pretty_print;
 extern bool SQL_inheritance;
 extern bool Australian_timezones;
 
+extern char *debug_query_string;
+
+extern int	log_min_error_statement;
+extern char *log_min_error_statement_str;
+extern const char log_min_error_statement_str_default[];
+
+extern int	server_min_messages;
+extern char    *server_min_messages_str;
+extern const char server_min_messages_str_default[];
+
+extern int client_min_messages;
+extern char    *client_min_messages_str;
+
+extern const char client_min_messages_str_default[];
+
 #endif   /* GUC_H */
-- 
GitLab