diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2015-01-15 13:39:33 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2015-01-15 13:39:33 -0500 |
commit | 8e166e164c7c4531d7eb150d836aa2357989237a (patch) | |
tree | 1cf5abe76f86c4a4bee68e714b03aeebbe0dafa8 /src/backend/commands/explain.c | |
parent | a5cd70dcbc268381e13cb0b2973b5732856d186f (diff) | |
download | postgresql-8e166e164c7c4531d7eb150d836aa2357989237a.tar.gz postgresql-8e166e164c7c4531d7eb150d836aa2357989237a.zip |
Rearrange explain.c's API so callers need not embed sizeof(ExplainState).
The folly of the previous arrangement was just demonstrated: there's no
convenient way to add fields to ExplainState without breaking ABI, even
if callers have no need to touch those fields. Since we might well need
to do that again someday in back branches, let's change things so that
only explain.c has to have sizeof(ExplainState) compiled into it. This
costs one extra palloc() per EXPLAIN operation, which is surely pretty
negligible.
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 66 |
1 files changed, 33 insertions, 33 deletions
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; } /* |