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.