Hello all
We already have feature to logging query parameters. If we use log_statement = 
'all' we write parameters before execution and all is fine here. If we use 
log_min_duration_statement statement is logged obviously after execution, but 
currently we have no parameters if query was terminated by statement_timeout, 
lock_timeout or by pg_terminate_backend.

I would like have parameters in logs at least for such three cases.

Simple way achieve this is just add errdetail_params to such ereport as in 
attached patch.
Another way is add something like printing global variable debug_query_string 
in send_message_to_server_log (src/backend/utils/error/elog.c). But i have no 
good idea how print ParamListInfo correctly. We can not use 
OidOutputFunctionCall in all cases, right?

Another small question is why errdetail_params uses errdetail instead 
errdetail_log? We assume that the user wants to get their own parameters back 
(if he set client_min_messages to LOG)?

Any feedback is strongly appreciated. Thank you!

regards, Sergei
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index f413395..ef6877e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -171,6 +171,9 @@ static ProcSignalReason RecoveryConflictReason;
 static MemoryContext row_description_context = NULL;
 static StringInfoData row_description_buf;
 
+/* current portal parameters */
+static ParamListInfo debug_query_params = NULL;
+
 /* ----------------------------------------------------------------
  *		decls for routines only used in this file
  * ----------------------------------------------------------------
@@ -183,7 +186,7 @@ static void forbidden_in_wal_sender(char firstchar);
 static List *pg_rewrite_query(Query *query);
 static bool check_log_statement(List *stmt_list);
 static int	errdetail_execute(List *raw_parsetree_list);
-static int	errdetail_params(ParamListInfo params);
+static int	errdetail_log_params(ParamListInfo params);
 static int	errdetail_abort(void);
 static int	errdetail_recovery_conflict(void);
 static void start_xact_command(void);
@@ -1850,7 +1853,7 @@ exec_bind_message(StringInfo input_message)
 							*portal_name ? portal_name : "",
 							psrc->query_string),
 					 errhidestmt(true),
-					 errdetail_params(params)));
+					 errdetail_log_params(params)));
 			break;
 	}
 
@@ -1934,6 +1937,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 		else
 			prepStmtName = "<unnamed>";
 		portalParams = portal->portalParams;
+		debug_query_params = portalParams;
 	}
 
 	/*
@@ -1985,7 +1989,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 						*portal_name ? portal_name : "",
 						sourceText),
 				 errhidestmt(true),
-				 errdetail_params(portalParams)));
+				 errdetail_log_params(portalParams)));
 		was_logged = true;
 	}
 
@@ -2074,7 +2078,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 							*portal_name ? portal_name : "",
 							sourceText),
 					 errhidestmt(true),
-					 errdetail_params(portalParams)));
+					 errdetail_log_params(portalParams)));
 			break;
 	}
 
@@ -2082,6 +2086,7 @@ exec_execute_message(const char *portal_name, long max_rows)
 		ShowUsage("EXECUTE MESSAGE STATISTICS");
 
 	debug_query_string = NULL;
+	debug_query_params = NULL;
 }
 
 /*
@@ -2200,12 +2205,12 @@ errdetail_execute(List *raw_parsetree_list)
 }
 
 /*
- * errdetail_params
+ * errdetail_log_params
  *
- * Add an errdetail() line showing bind-parameter data, if available.
+ * Add an errdetail_log() line showing bind-parameter data, if available.
  */
 static int
-errdetail_params(ParamListInfo params)
+errdetail_log_params(ParamListInfo params)
 {
 	/* We mustn't call user-defined I/O functions when in an aborted xact */
 	if (params && params->numParams > 0 && !IsAbortedTransactionBlockState())
@@ -2256,7 +2261,7 @@ errdetail_params(ParamListInfo params)
 			pfree(pstring);
 		}
 
-		errdetail("parameters: %s", param_str.data);
+		errdetail_log("parameters: %s", param_str.data);
 
 		pfree(param_str.data);
 
@@ -2925,7 +2930,8 @@ ProcessInterrupts(void)
 		else
 			ereport(FATAL,
 					(errcode(ERRCODE_ADMIN_SHUTDOWN),
-					 errmsg("terminating connection due to administrator command")));
+					 errmsg("terminating connection due to administrator command"),
+					 errdetail_log_params(debug_query_params)));
 	}
 	if (ClientConnectionLost)
 	{
@@ -3001,14 +3007,16 @@ ProcessInterrupts(void)
 			LockErrorCleanup();
 			ereport(ERROR,
 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
-					 errmsg("canceling statement due to lock timeout")));
+					 errmsg("canceling statement due to lock timeout"),
+					 errdetail_log_params(debug_query_params)));
 		}
 		if (stmt_timeout_occurred)
 		{
 			LockErrorCleanup();
 			ereport(ERROR,
 					(errcode(ERRCODE_QUERY_CANCELED),
-					 errmsg("canceling statement due to statement timeout")));
+					 errmsg("canceling statement due to statement timeout"),
+					 errdetail_log_params(debug_query_params)));
 		}
 		if (IsAutoVacuumWorkerProcess())
 		{
@@ -3932,6 +3940,7 @@ PostgresMain(int argc, char *argv[],
 		 * the storage it points at.
 		 */
 		debug_query_string = NULL;
+		debug_query_params = NULL;
 
 		/*
 		 * Abort the current transaction in order to recover.

Reply via email to