aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/auto_explain/auto_explain.c43
-rw-r--r--src/backend/commands/explain.c66
-rw-r--r--src/include/commands/explain.h2
3 files changed, 55 insertions, 56 deletions
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c
index 179b33a7938..2a184ed886f 100644
--- a/contrib/auto_explain/auto_explain.c
+++ b/contrib/auto_explain/auto_explain.c
@@ -294,32 +294,31 @@ explain_ExecutorEnd(QueryDesc *queryDesc)
msec = queryDesc->totaltime->total * 1000.0;
if (msec >= auto_explain_log_min_duration)
{
- ExplainState es;
-
- ExplainInitState(&es);
- es.analyze = (queryDesc->instrument_options && auto_explain_log_analyze);
- es.verbose = auto_explain_log_verbose;
- es.buffers = (es.analyze && auto_explain_log_buffers);
- es.timing = (es.analyze && auto_explain_log_timing);
- es.summary = es.analyze;
- es.format = auto_explain_log_format;
-
- ExplainBeginOutput(&es);
- ExplainQueryText(&es, queryDesc);
- ExplainPrintPlan(&es, queryDesc);
- if (es.analyze && auto_explain_log_triggers)
- ExplainPrintTriggers(&es, queryDesc);
- ExplainEndOutput(&es);
+ ExplainState *es = NewExplainState();
+
+ es->analyze = (queryDesc->instrument_options && auto_explain_log_analyze);
+ es->verbose = auto_explain_log_verbose;
+ es->buffers = (es->analyze && auto_explain_log_buffers);
+ es->timing = (es->analyze && auto_explain_log_timing);
+ es->summary = es->analyze;
+ es->format = auto_explain_log_format;
+
+ ExplainBeginOutput(es);
+ ExplainQueryText(es, queryDesc);
+ ExplainPrintPlan(es, queryDesc);
+ if (es->analyze && auto_explain_log_triggers)
+ ExplainPrintTriggers(es, queryDesc);
+ ExplainEndOutput(es);
/* Remove last line break */
- if (es.str->len > 0 && es.str->data[es.str->len - 1] == '\n')
- es.str->data[--es.str->len] = '\0';
+ if (es->str->len > 0 && es->str->data[es->str->len - 1] == '\n')
+ es->str->data[--es->str->len] = '\0';
/* Fix JSON to output an object */
if (auto_explain_log_format == EXPLAIN_FORMAT_JSON)
{
- es.str->data[0] = '{';
- es.str->data[es.str->len - 1] = '}';
+ es->str->data[0] = '{';
+ es->str->data[es->str->len - 1] = '}';
}
/*
@@ -330,10 +329,10 @@ explain_ExecutorEnd(QueryDesc *queryDesc)
*/
ereport(LOG,
(errmsg("duration: %.3f ms plan:\n%s",
- msec, es.str->data),
+ msec, es->str->data),
errhidestmt(true)));
- pfree(es.str->data);
+ pfree(es->str->data);
}
}
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 39ceaf26639..2b84ac8af37 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -125,45 +125,42 @@ void
ExplainQuery(ExplainStmt *stmt, const char *queryString,
ParamListInfo params, DestReceiver *dest)
{
- ExplainState es;
+ ExplainState *es = NewExplainState();
TupOutputState *tstate;
List *rewritten;
ListCell *lc;
bool timing_set = false;
- /* Initialize ExplainState. */
- ExplainInitState(&es);
-
/* Parse options list. */
foreach(lc, stmt->options)
{
DefElem *opt = (DefElem *) lfirst(lc);
if (strcmp(opt->defname, "analyze") == 0)
- es.analyze = defGetBoolean(opt);
+ es->analyze = defGetBoolean(opt);
else if (strcmp(opt->defname, "verbose") == 0)
- es.verbose = defGetBoolean(opt);
+ es->verbose = defGetBoolean(opt);
else if (strcmp(opt->defname, "costs") == 0)
- es.costs = defGetBoolean(opt);
+ es->costs = defGetBoolean(opt);
else if (strcmp(opt->defname, "buffers") == 0)
- es.buffers = defGetBoolean(opt);
+ es->buffers = defGetBoolean(opt);
else if (strcmp(opt->defname, "timing") == 0)
{
timing_set = true;
- es.timing = defGetBoolean(opt);
+ es->timing = defGetBoolean(opt);
}
else if (strcmp(opt->defname, "format") == 0)
{
char *p = defGetString(opt);
if (strcmp(p, "text") == 0)
- es.format = EXPLAIN_FORMAT_TEXT;
+ es->format = EXPLAIN_FORMAT_TEXT;
else if (strcmp(p, "xml") == 0)
- es.format = EXPLAIN_FORMAT_XML;
+ es->format = EXPLAIN_FORMAT_XML;
else if (strcmp(p, "json") == 0)
- es.format = EXPLAIN_FORMAT_JSON;
+ es->format = EXPLAIN_FORMAT_JSON;
else if (strcmp(p, "yaml") == 0)
- es.format = EXPLAIN_FORMAT_YAML;
+ es->format = EXPLAIN_FORMAT_YAML;
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -177,22 +174,22 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
opt->defname)));
}
- if (es.buffers && !es.analyze)
+ if (es->buffers && !es->analyze)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("EXPLAIN option BUFFERS requires ANALYZE")));
/* if the timing was not set explicitly, set default value */
- es.timing = (timing_set) ? es.timing : es.analyze;
+ es->timing = (timing_set) ? es->timing : es->analyze;
/* check that timing is used with EXPLAIN ANALYZE */
- if (es.timing && !es.analyze)
+ if (es->timing && !es->analyze)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("EXPLAIN option TIMING requires ANALYZE")));
/* currently, summary option is not exposed to users; just set it */
- es.summary = es.analyze;
+ es->summary = es->analyze;
/*
* Parse analysis was done already, but we still have to run the rule
@@ -210,7 +207,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
rewritten = QueryRewrite((Query *) copyObject(stmt->query));
/* emit opening boilerplate */
- ExplainBeginOutput(&es);
+ ExplainBeginOutput(es);
if (rewritten == NIL)
{
@@ -218,8 +215,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
* In the case of an INSTEAD NOTHING, tell at least that. But in
* non-text format, the output is delimited, so this isn't necessary.
*/
- if (es.format == EXPLAIN_FORMAT_TEXT)
- appendStringInfoString(es.str, "Query rewrites to nothing\n");
+ if (es->format == EXPLAIN_FORMAT_TEXT)
+ appendStringInfoString(es->str, "Query rewrites to nothing\n");
}
else
{
@@ -228,41 +225,44 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
/* Explain every plan */
foreach(l, rewritten)
{
- ExplainOneQuery((Query *) lfirst(l), NULL, &es,
+ ExplainOneQuery((Query *) lfirst(l), NULL, es,
queryString, params);
/* Separate plans with an appropriate separator */
if (lnext(l) != NULL)
- ExplainSeparatePlans(&es);
+ ExplainSeparatePlans(es);
}
}
/* emit closing boilerplate */
- ExplainEndOutput(&es);
- Assert(es.indent == 0);
+ ExplainEndOutput(es);
+ Assert(es->indent == 0);
/* output tuples */
tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
- if (es.format == EXPLAIN_FORMAT_TEXT)
- do_text_output_multiline(tstate, es.str->data);
+ if (es->format == EXPLAIN_FORMAT_TEXT)
+ do_text_output_multiline(tstate, es->str->data);
else
- do_text_output_oneline(tstate, es.str->data);
+ do_text_output_oneline(tstate, es->str->data);
end_tup_output(tstate);
- pfree(es.str->data);
+ pfree(es->str->data);
}
/*
- * Initialize ExplainState.
+ * Create a new ExplainState struct initialized with default options.
*/
-void
-ExplainInitState(ExplainState *es)
+ExplainState *
+NewExplainState(void)
{
- /* Set default options. */
- memset(es, 0, sizeof(ExplainState));
+ ExplainState *es = (ExplainState *) palloc0(sizeof(ExplainState));
+
+ /* Set default options (most fields can be left as zeroes). */
es->costs = true;
/* Prepare output buffer. */
es->str = makeStringInfo();
+
+ return es;
}
/*
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index 598f37428d2..c9f722361a1 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -60,7 +60,7 @@ extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook;
extern void ExplainQuery(ExplainStmt *stmt, const char *queryString,
ParamListInfo params, DestReceiver *dest);
-extern void ExplainInitState(ExplainState *es);
+extern ExplainState *NewExplainState(void);
extern TupleDesc ExplainResultDesc(ExplainStmt *stmt);