From 11bbdec931481ffc02ce147db2c7c8b08e6503e4 Mon Sep 17 00:00:00 2001
From: Pierre Ducroquet <pducroquet@entrouvert.com>
Date: Tue, 26 Jul 2022 14:39:59 +0200
Subject: [PATCH] log the search_path of statements (configurable)

Introduce a new GUC, log_statement_search_path, to make it possible
to log the search_path of queries.
---
 src/backend/catalog/namespace.c |  4 ++++
 src/backend/tcop/postgres.c     | 34 ++++++++++++++++++++++++++++-----
 src/backend/utils/misc/guc.c    | 11 +++++++++++
 src/include/catalog/namespace.h |  2 ++
 src/include/tcop/tcopprot.h     |  8 ++++++++
 src/include/utils/guc.h         |  1 +
 6 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index fafb9349cc..ec6c260f15 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -197,6 +197,7 @@ static SubTransactionId myTempNamespaceSubID = InvalidSubTransactionId;
  * of the GUC variable 'search_path'.
  */
 char	   *namespace_search_path = NULL;
+GucSource	namespace_search_path_source = 0;
 
 
 /* Local functions */
@@ -4348,6 +4349,9 @@ check_search_path(char **newval, void **extra, GucSource source)
 	pfree(rawname);
 	list_free(namelist);
 
+	/* Store the source */
+	namespace_search_path_source = source;
+
 	return true;
 }
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index d0bbd30d2b..4fa6260f63 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -39,6 +39,7 @@
 #include "access/parallel.h"
 #include "access/printtup.h"
 #include "access/xact.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_type.h"
 #include "commands/async.h"
 #include "commands/prepare.h"
@@ -96,6 +97,15 @@ bool		Log_disconnections = false;
 
 int			log_statement = LOGSTMT_NONE;
 
+const struct config_enum_entry log_statement_search_path_options[] = {
+        {"never", LOG_STATEMENT_SEARCH_PATH_NEVER, false},
+        {"non_default", LOG_STATEMENT_SEARCH_PATH_NON_DEFAULT, false},
+        {"always", LOG_STATEMENT_SEARCH_PATH_ALWAYS, false},
+        {NULL, 0, false}
+};
+
+int			log_statement_search_path = LOG_STATEMENT_SEARCH_PATH_NEVER;
+
 /* GUC variable for maximum stack depth (measured in kilobytes) */
 int			max_stack_depth = 100;
 
@@ -1328,11 +1338,25 @@ exec_simple_query(const char *query_string)
 					 errhidestmt(true)));
 			break;
 		case 2:
-			ereport(LOG,
-					(errmsg("duration: %s ms  statement: %s",
-							msec_str, query_string),
-					 errhidestmt(true),
-					 errdetail_execute(parsetree_list)));
+			if ((log_statement_search_path > LOG_STATEMENT_SEARCH_PATH_NEVER)
+				&& (
+					namespace_search_path_source > PGC_S_INTERACTIVE
+					||
+					log_statement_search_path > LOG_STATEMENT_SEARCH_PATH_NON_DEFAULT
+				)) {
+				ereport(LOG,
+						(errmsg("duration: %s ms  statement: %s",
+								msec_str, query_string),
+						errhidestmt(true),
+						errdetail("search_path: %s", namespace_search_path),
+						errdetail_execute(parsetree_list)));
+			} else {
+				ereport(LOG,
+						(errmsg("duration: %s ms  statement: %s",
+								msec_str, query_string),
+						errhidestmt(true),
+						errdetail_execute(parsetree_list)));
+			}
 			break;
 	}
 
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index af4a1c3068..524d6befa6 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -604,6 +604,7 @@ extern const struct config_enum_entry archive_mode_options[];
 extern const struct config_enum_entry recovery_target_action_options[];
 extern const struct config_enum_entry sync_method_options[];
 extern const struct config_enum_entry dynamic_shared_memory_options[];
+extern const struct config_enum_entry log_statement_search_path_options[];
 
 /*
  * GUC option variables that are exported from this module
@@ -4836,6 +4837,16 @@ static struct config_enum ConfigureNamesEnum[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"log_statement_search_path", PGC_SUSET, LOGGING_WHEN,
+			gettext_noop("Sets whether to log the search path of logged statements."),
+			NULL
+		},
+		&log_statement_search_path,
+		LOG_STATEMENT_SEARCH_PATH_NEVER, log_statement_search_path_options,
+		NULL, NULL, NULL
+	},
+
 	{
 		{"log_min_messages", PGC_SUSET, LOGGING_WHEN,
 			gettext_noop("Sets the message levels that are logged."),
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 1bc55c01a5..903531b231 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -16,6 +16,7 @@
 
 #include "nodes/primnodes.h"
 #include "storage/lock.h"
+#include "utils/guc.h"
 
 
 /*
@@ -183,6 +184,7 @@ extern void AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
 
 /* stuff for search_path GUC variable */
 extern PGDLLIMPORT char *namespace_search_path;
+extern PGDLLIMPORT GucSource namespace_search_path_source;
 
 extern List *fetch_search_path(bool includeImplicit);
 extern int	fetch_search_path_array(Oid *sarray, int sarray_len);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 70d9dab25b..0d3d7bf4e0 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -41,6 +41,14 @@ typedef enum
 	LOGSTMT_ALL					/* log all statements */
 } LogStmtLevel;
 
+typedef enum 
+{
+	LOG_STATEMENT_SEARCH_PATH_NEVER = 0,
+	LOG_STATEMENT_SEARCH_PATH_NON_DEFAULT,
+	LOG_STATEMENT_SEARCH_PATH_ALWAYS
+} LogStmtSearchPathOptions;
+
+
 extern PGDLLIMPORT int log_statement;
 
 extern List *pg_parse_query(const char *query_string);
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index e734493a48..34b406092b 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -270,6 +270,7 @@ extern PGDLLIMPORT double log_statement_sample_rate;
 extern PGDLLIMPORT double log_xact_sample_rate;
 extern PGDLLIMPORT char *backtrace_functions;
 extern PGDLLIMPORT char *backtrace_symbol_list;
+extern PGDLLIMPORT int log_statement_search_path;
 
 extern PGDLLIMPORT int temp_file_limit;
 
-- 
2.35.1

