diff options
-rw-r--r-- | contrib/auto_explain/auto_explain.c | 15 | ||||
-rw-r--r-- | contrib/auto_explain/t/001_auto_explain.pl | 48 | ||||
-rw-r--r-- | doc/src/sgml/auto-explain.sgml | 19 | ||||
-rw-r--r-- | src/backend/commands/explain.c | 22 | ||||
-rw-r--r-- | src/include/commands/explain.h | 1 |
5 files changed, 105 insertions, 0 deletions
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c index c9a0d947c83..1ba7536879d 100644 --- a/contrib/auto_explain/auto_explain.c +++ b/contrib/auto_explain/auto_explain.c @@ -19,12 +19,14 @@ #include "common/pg_prng.h" #include "executor/instrument.h" #include "jit/jit.h" +#include "nodes/params.h" #include "utils/guc.h" PG_MODULE_MAGIC; /* GUC variables */ static int auto_explain_log_min_duration = -1; /* msec or -1 */ +static int auto_explain_log_parameter_max_length = -1; /* bytes or -1 */ static bool auto_explain_log_analyze = false; static bool auto_explain_log_verbose = false; static bool auto_explain_log_buffers = false; @@ -105,6 +107,18 @@ _PG_init(void) NULL, NULL); + DefineCustomIntVariable("auto_explain.log_parameter_max_length", + "Sets the maximum length of query parameters to log.", + "Zero logs no query parameters, -1 logs them in full.", + &auto_explain_log_parameter_max_length, + -1, + -1, INT_MAX, + PGC_SUSET, + GUC_UNIT_BYTE, + NULL, + NULL, + NULL); + DefineCustomBoolVariable("auto_explain.log_analyze", "Use EXPLAIN ANALYZE for plan logging.", NULL, @@ -389,6 +403,7 @@ explain_ExecutorEnd(QueryDesc *queryDesc) ExplainBeginOutput(es); ExplainQueryText(es, queryDesc); + ExplainQueryParameters(es, queryDesc->params, auto_explain_log_parameter_max_length); ExplainPrintPlan(es, queryDesc); if (es->analyze && auto_explain_log_triggers) ExplainPrintTriggers(es, queryDesc); diff --git a/contrib/auto_explain/t/001_auto_explain.pl b/contrib/auto_explain/t/001_auto_explain.pl index 1523ac2d46e..1d952fb54d3 100644 --- a/contrib/auto_explain/t/001_auto_explain.pl +++ b/contrib/auto_explain/t/001_auto_explain.pl @@ -60,6 +60,11 @@ like( qr/Query Text: SELECT \* FROM pg_class;/, "query text logged, text mode"); +unlike( + $log_contents, + qr/Query Parameters:/, + "no query parameters logged when none, text mode"); + like( $log_contents, qr/Seq Scan on pg_class/, @@ -77,9 +82,47 @@ like( like( $log_contents, + qr/Query Parameters: \$1 = 'int4pl'/, + "query parameters logged, text mode"); + +like( + $log_contents, qr/Index Scan using pg_proc_proname_args_nsp_index on pg_proc/, "index scan logged, text mode"); + +# Prepared query with truncated parameters. +$log_contents = query_log( + $node, + q{PREPARE get_type(name) AS SELECT * FROM pg_type WHERE typname = $1; EXECUTE get_type('float8');}, + { "auto_explain.log_parameter_max_length" => 3 }); + +like( + $log_contents, + qr/Query Text: PREPARE get_type\(name\) AS SELECT \* FROM pg_type WHERE typname = \$1;/, + "prepared query text logged, text mode"); + +like( + $log_contents, + qr/Query Parameters: \$1 = 'flo\.\.\.'/, + "query parameters truncated, text mode"); + +# Prepared query with parameter logging disabled. +$log_contents = query_log( + $node, + q{PREPARE get_type(name) AS SELECT * FROM pg_type WHERE typname = $1; EXECUTE get_type('float8');}, + { "auto_explain.log_parameter_max_length" => 0 }); + +like( + $log_contents, + qr/Query Text: PREPARE get_type\(name\) AS SELECT \* FROM pg_type WHERE typname = \$1;/, + "prepared query text logged, text mode"); + +unlike( + $log_contents, + qr/Query Parameters:/, + "query parameters not logged when disabled, text mode"); + # JSON format. $log_contents = query_log( $node, @@ -91,6 +134,11 @@ like( qr/"Query Text": "SELECT \* FROM pg_proc;"/, "query text logged, json mode"); +unlike( + $log_contents, + qr/"Query Parameters":/, + "query parameters not logged when none, json mode"); + like( $log_contents, qr/"Node Type": "Seq Scan"[^}]*"Relation Name": "pg_proc"/s, diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index 30e35a714a5..394fec94e88 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -65,6 +65,25 @@ LOAD 'auto_explain'; <varlistentry> <term> + <varname>auto_explain.log_parameter_max_length</varname> (<type>integer</type>) + <indexterm> + <primary><varname>auto_explain.log_parameter_max_length</varname> configuration parameter</primary> + </indexterm> + </term> + <listitem> + <para> + <varname>auto_explain.log_parameter_max_length</varname> controls the + logging of query parameter values. A value of<literal>-1</literal> (the + default) logs the parameter values in full. <literal>0</literal> disables + logging of parameter values. A value greater than zero truncates each + parameter value to that many bytes. Only superusers can change this + setting. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term> <varname>auto_explain.log_analyze</varname> (<type>boolean</type>) <indexterm> <primary><varname>auto_explain.log_analyze</varname> configuration parameter</primary> diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 5d1f7089daf..e29c2ae206f 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -973,6 +973,28 @@ ExplainQueryText(ExplainState *es, QueryDesc *queryDesc) } /* + * ExplainQueryParameters - + * add a "Query Parameters" node that describes the parameters of the query + * + * The caller should have set up the options fields of *es, as well as + * initializing the output buffer es->str. + * + */ +void +ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen) +{ + char *str; + + /* This check is consistent with errdetail_params() */ + if (params == NULL || params->numParams <= 0 || maxlen == 0) + return; + + str = BuildParamLogString(params, NULL, maxlen); + if (str && str[0] != '\0') + ExplainPropertyText("Query Parameters", str, es); +} + +/* * report_triggers - * report execution stats for a single relation's triggers */ diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h index 666977fb1f8..9ebde089aed 100644 --- a/src/include/commands/explain.h +++ b/src/include/commands/explain.h @@ -99,6 +99,7 @@ extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc); extern void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc); extern void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc); +extern void ExplainQueryParameters(ExplainState *es, ParamListInfo params, int maxlen); extern void ExplainBeginOutput(ExplainState *es); extern void ExplainEndOutput(ExplainState *es); |