* Copyright (c) 2008-2009, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/auto_explain/auto_explain.c,v 1.5 2009/06/11 14:48:50 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/auto_explain/auto_explain.c,v 1.6 2009/07/26 23:34:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
msec = queryDesc->totaltime->total * 1000.0;
if (msec >= auto_explain_log_min_duration)
{
- StringInfoData buf;
+ ExplainState es;
- initStringInfo(&buf);
- ExplainPrintPlan(&buf, queryDesc,
- queryDesc->doInstrument && auto_explain_log_analyze,
- auto_explain_log_verbose);
+ ExplainInitState(&es);
+ es.analyze = (queryDesc->doInstrument && auto_explain_log_analyze);
+ es.verbose = auto_explain_log_verbose;
+
+ ExplainPrintPlan(&es, queryDesc);
/* Remove last line break */
- if (buf.len > 0 && buf.data[buf.len - 1] == '\n')
- buf.data[--buf.len] = '\0';
+ if (es.str->len > 0 && es.str->data[es.str->len - 1] == '\n')
+ es.str->data[--es.str->len] = '\0';
/*
* Note: we rely on the existing logging of context or
*/
ereport(LOG,
(errmsg("duration: %.3f ms plan:\n%s",
- msec, buf.data)));
+ msec, es.str->data)));
- pfree(buf.data);
+ pfree(es.str->data);
}
}
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/explain.sgml,v 1.44 2008/11/14 10:22:47 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/explain.sgml,v 1.45 2009/07/26 23:34:17 tgl Exp $
PostgreSQL documentation
-->
<refsynopsisdiv>
<synopsis>
+EXPLAIN [ ( { ANALYZE <replaceable class="parameter">boolean</replaceable> | VERBOSE <replaceable class="parameter">boolean</replaceable> | COSTS <replaceable class="parameter">boolean</replaceable> } [, ...] ) ] <replaceable class="parameter">statement</replaceable>
EXPLAIN [ ANALYZE ] [ VERBOSE ] <replaceable class="parameter">statement</replaceable>
</synopsis>
</refsynopsisdiv>
</programlisting>
</para>
</important>
+
+ <para>
+ Only the <literal>ANALYZE</literal> and <literal>VERBOSE</literal> options
+ can be specified, and only in that order, without surrounding the option
+ list in parentheses. Prior to <productname>PostgreSQL</productname> 8.5,
+ the unparenthesized syntax was the only one supported. It is expected that
+ all new options will be supported only in the parenthesized syntax.
+ </para>
</refsect1>
<refsect1>
<term><literal>ANALYZE</literal></term>
<listitem>
<para>
- Carry out the command and show the actual run times.
+ Carry out the command and show the actual run times. This
+ parameter defaults to <command>FALSE</command>.
</para>
</listitem>
</varlistentry>
<term><literal>VERBOSE</literal></term>
<listitem>
<para>
- Include the output column list for each node in the plan tree.
+ Include the output column list for each node in the plan tree. This
+ parameter defaults to <command>FALSE</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>COSTS</literal></term>
+ <listitem>
+ <para>
+ Include information on the estimated startup and total cost of each
+ plan node, as well as the estimated number of rows and the estimated
+ width of each row. This parameter defaults to <command>TRUE</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="parameter">boolean</replaceable></term>
+ <listitem>
+ <para>
+ Specifies whether the selected option should be turned on or off.
+ You can write <literal>TRUE</literal>, <literal>ON</>, or
+ <literal>1</literal> to enable the option, and <literal>FALSE</literal>,
+ <literal>OFF</>, or <literal>0</literal> to disable it. The
+ <replaceable class="parameter">boolean</replaceable> value can also
+ be omitted, in which case <literal>TRUE</literal> is assumed.
</para>
</listitem>
</varlistentry>
might be chosen.
</para>
- <para>
- Genetic query optimization (<acronym>GEQO</acronym>) randomly tests
- execution plans. Therefore, when the number of join relations
- exceeds <xref linkend="guc-geqo-threshold"> causing genetic query
- optimization to be used, the execution plan is likely to change
- each time the statement is executed.
- </para>
-
<para>
In order to measure the run-time cost of each node in the execution
plan, the current implementation of <command>EXPLAIN
</programlisting>
</para>
+ <para>
+ Here is the same plan with costs suppressed:
+
+<programlisting>
+EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4;
+
+ QUERY PLAN
+----------------------------
+ Index Scan using fi on foo
+ Index Cond: (i = 4)
+(2 rows)
+</programlisting>
+ </para>
+
<para>
Here is an example of a query plan for a query using an aggregate
function:
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.104 2009/04/04 21:12:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.105 2009/07/26 23:34:17 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
return true;
/*
- * Allow 0, 1, "true", "false"
+ * Allow 0, 1, "true", "false", "on", "off"
*/
switch (nodeTag(def->arg))
{
{
char *sval = defGetString(def);
+ /*
+ * The set of strings accepted here should match up with
+ * the grammar's opt_boolean production.
+ */
if (pg_strcasecmp(sval, "true") == 0)
return true;
if (pg_strcasecmp(sval, "false") == 0)
return false;
-
+ if (pg_strcasecmp(sval, "on") == 0)
+ return true;
+ if (pg_strcasecmp(sval, "off") == 0)
+ return false;
}
break;
}
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.187 2009/07/24 21:08:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.188 2009/07/26 23:34:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/xact.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_type.h"
+#include "commands/defrem.h"
#include "commands/explain.h"
#include "commands/prepare.h"
#include "commands/trigger.h"
explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
-typedef struct ExplainState
-{
- StringInfo str; /* output buffer */
- /* options */
- bool printTList; /* print plan targetlists */
- bool printAnalyze; /* print actual times */
- /* other states */
- PlannedStmt *pstmt; /* top of plan */
- List *rtable; /* range table */
-} ExplainState;
-
-static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params, TupOutputState *tstate);
+static void ExplainOneQuery(Query *query, ExplainState *es,
+ const char *queryString, ParamListInfo params);
static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
StringInfo buf);
static double elapsed_time(instr_time *starttime);
ExplainQuery(ExplainStmt *stmt, const char *queryString,
ParamListInfo params, DestReceiver *dest)
{
+ ExplainState es;
Oid *param_types;
int num_params;
TupOutputState *tstate;
List *rewritten;
- ListCell *l;
+ ListCell *lc;
+
+ /* 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);
+ else if (strcmp(opt->defname, "verbose") == 0)
+ es.verbose = defGetBoolean(opt);
+ else if (strcmp(opt->defname, "costs") == 0)
+ es.costs = defGetBoolean(opt);
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("unrecognized EXPLAIN option \"%s\"",
+ opt->defname)));
+ }
/* Convert parameter type data to the form parser wants */
getParamListTypes(params, ¶m_types, &num_params);
rewritten = pg_analyze_and_rewrite((Node *) copyObject(stmt->query),
queryString, param_types, num_params);
- /* prepare for projection of tuples */
- tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
-
if (rewritten == NIL)
{
/* In the case of an INSTEAD NOTHING, tell at least that */
- do_text_output_oneline(tstate, "Query rewrites to nothing");
+ appendStringInfoString(es.str, "Query rewrites to nothing\n");
}
else
{
+ ListCell *l;
+
/* Explain every plan */
foreach(l, rewritten)
{
- ExplainOneQuery((Query *) lfirst(l), stmt,
- queryString, params, tstate);
+ ExplainOneQuery((Query *) lfirst(l), &es, queryString, params);
/* put a blank line between plans */
if (lnext(l) != NULL)
- do_text_output_oneline(tstate, "");
+ appendStringInfoChar(es.str, '\n');
}
}
+ /* output tuples */
+ tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
+ do_text_output_multiline(tstate, es.str->data);
end_tup_output(tstate);
+
+ pfree(es.str->data);
+}
+
+/*
+ * Initialize ExplainState.
+ */
+void
+ExplainInitState(ExplainState *es)
+{
+ /* Set default options. */
+ memset(es, 0, sizeof(ExplainState));
+ es->costs = true;
+ /* Prepare output buffer. */
+ es->str = makeStringInfo();
}
/*
* print out the execution plan for one Query
*/
static void
-ExplainOneQuery(Query *query, ExplainStmt *stmt, const char *queryString,
- ParamListInfo params, TupOutputState *tstate)
+ExplainOneQuery(Query *query, ExplainState *es,
+ const char *queryString, ParamListInfo params)
{
/* planner will not cope with utility statements */
if (query->commandType == CMD_UTILITY)
{
- ExplainOneUtility(query->utilityStmt, stmt,
- queryString, params, tstate);
+ ExplainOneUtility(query->utilityStmt, es, queryString, params);
return;
}
/* if an advisor plugin is present, let it manage things */
if (ExplainOneQuery_hook)
- (*ExplainOneQuery_hook) (query, stmt, queryString, params, tstate);
+ (*ExplainOneQuery_hook) (query, es, queryString, params);
else
{
PlannedStmt *plan;
plan = pg_plan_query(query, 0, params);
/* run it (if needed) and produce output */
- ExplainOnePlan(plan, stmt, queryString, params, tstate);
+ ExplainOnePlan(plan, es, queryString, params);
}
}
* EXPLAIN EXECUTE case
*/
void
-ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt,
- const char *queryString, ParamListInfo params,
- TupOutputState *tstate)
+ExplainOneUtility(Node *utilityStmt, ExplainState *es,
+ const char *queryString, ParamListInfo params)
{
if (utilityStmt == NULL)
return;
if (IsA(utilityStmt, ExecuteStmt))
- ExplainExecuteQuery((ExecuteStmt *) utilityStmt, stmt,
- queryString, params, tstate);
+ ExplainExecuteQuery((ExecuteStmt *) utilityStmt, es,
+ queryString, params);
else if (IsA(utilityStmt, NotifyStmt))
- do_text_output_oneline(tstate, "NOTIFY");
+ appendStringInfoString(es->str, "NOTIFY\n");
else
- do_text_output_oneline(tstate,
- "Utility statements have no plan structure");
+ appendStringInfoString(es->str,
+ "Utility statements have no plan structure\n");
}
/*
* to call it.
*/
void
-ExplainOnePlan(PlannedStmt *plannedstmt, ExplainStmt *stmt,
- const char *queryString, ParamListInfo params,
- TupOutputState *tstate)
+ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
+ const char *queryString, ParamListInfo params)
{
QueryDesc *queryDesc;
instr_time starttime;
double totaltime = 0;
- StringInfoData buf;
int eflags;
/*
/* Create a QueryDesc requesting no output */
queryDesc = CreateQueryDesc(plannedstmt, queryString,
GetActiveSnapshot(), InvalidSnapshot,
- None_Receiver, params,
- stmt->analyze);
+ None_Receiver, params, es->analyze);
INSTR_TIME_SET_CURRENT(starttime);
/* If analyzing, we need to cope with queued triggers */
- if (stmt->analyze)
+ if (es->analyze)
AfterTriggerBeginQuery();
/* Select execution options */
- if (stmt->analyze)
+ if (es->analyze)
eflags = 0; /* default run-to-completion flags */
else
eflags = EXEC_FLAG_EXPLAIN_ONLY;
ExecutorStart(queryDesc, eflags);
/* Execute the plan for statistics if asked for */
- if (stmt->analyze)
+ if (es->analyze)
{
/* run the plan */
ExecutorRun(queryDesc, ForwardScanDirection, 0L);
}
/* Create textual dump of plan tree */
- initStringInfo(&buf);
- ExplainPrintPlan(&buf, queryDesc, stmt->analyze, stmt->verbose);
+ ExplainPrintPlan(es, queryDesc);
/*
* If we ran the command, run any AFTER triggers it queued. (Note this
* will not include DEFERRED triggers; since those don't run until end of
* transaction, we can't measure them.) Include into total runtime.
*/
- if (stmt->analyze)
+ if (es->analyze)
{
INSTR_TIME_SET_CURRENT(starttime);
AfterTriggerEndQuery(queryDesc->estate);
}
/* Print info about runtime of triggers */
- if (stmt->analyze)
+ if (es->analyze)
{
ResultRelInfo *rInfo;
bool show_relname;
show_relname = (numrels > 1 || targrels != NIL);
rInfo = queryDesc->estate->es_result_relations;
for (nr = 0; nr < numrels; rInfo++, nr++)
- report_triggers(rInfo, show_relname, &buf);
+ report_triggers(rInfo, show_relname, es->str);
foreach(l, targrels)
{
rInfo = (ResultRelInfo *) lfirst(l);
- report_triggers(rInfo, show_relname, &buf);
+ report_triggers(rInfo, show_relname, es->str);
}
}
PopActiveSnapshot();
/* We need a CCI just in case query expanded to multiple plans */
- if (stmt->analyze)
+ if (es->analyze)
CommandCounterIncrement();
totaltime += elapsed_time(&starttime);
- if (stmt->analyze)
- appendStringInfo(&buf, "Total runtime: %.3f ms\n",
+ if (es->analyze)
+ appendStringInfo(es->str, "Total runtime: %.3f ms\n",
1000.0 * totaltime);
- do_text_output_multiline(tstate, buf.data);
-
- pfree(buf.data);
}
/*
* ExplainPrintPlan -
- * convert a QueryDesc's plan tree to text and append it to 'str'
+ * convert a QueryDesc's plan tree to text and append it to es->str
*
- * 'analyze' means to include runtime instrumentation results
- * 'verbose' means a verbose printout (currently, it shows targetlists)
+ * The caller should have set up the options fields of *es, as well as
+ * initializing the output buffer es->str. Other fields in *es are
+ * initialized here.
*
* NB: will not work on utility statements
*/
void
-ExplainPrintPlan(StringInfo str, QueryDesc *queryDesc,
- bool analyze, bool verbose)
+ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc)
{
- ExplainState es;
-
Assert(queryDesc->plannedstmt != NULL);
-
- memset(&es, 0, sizeof(es));
- es.str = str;
- es.printTList = verbose;
- es.printAnalyze = analyze;
- es.pstmt = queryDesc->plannedstmt;
- es.rtable = queryDesc->plannedstmt->rtable;
-
+ es->pstmt = queryDesc->plannedstmt;
+ es->rtable = queryDesc->plannedstmt->rtable;
ExplainNode(queryDesc->plannedstmt->planTree, queryDesc->planstate,
- NULL, 0, &es);
+ NULL, 0, es);
}
/*
break;
}
- appendStringInfo(es->str, " (cost=%.2f..%.2f rows=%.0f width=%d)",
- plan->startup_cost, plan->total_cost,
- plan->plan_rows, plan->plan_width);
+ if (es->costs)
+ appendStringInfo(es->str, " (cost=%.2f..%.2f rows=%.0f width=%d)",
+ plan->startup_cost, plan->total_cost,
+ plan->plan_rows, plan->plan_width);
/*
* We have to forcibly clean up the instrumentation state because we
planstate->instrument->ntuples / nloops,
planstate->instrument->nloops);
}
- else if (es->printAnalyze)
+ else if (es->analyze)
appendStringInfoString(es->str, " (never executed)");
appendStringInfoChar(es->str, '\n');
/* target list */
- if (es->printTList)
+ if (es->verbose)
show_plan_tlist(plan, indent, es);
/* quals, sort keys, etc */
show_sort_info(SortState *sortstate, int indent, ExplainState *es)
{
Assert(IsA(sortstate, SortState));
- if (es->printAnalyze && sortstate->sort_Done &&
+ if (es->analyze && sortstate->sort_Done &&
sortstate->tuplesortstate != NULL)
{
char *sortinfo;
* Copyright (c) 2002-2009, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.97 2009/06/11 14:48:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.98 2009/07/26 23:34:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "access/xact.h"
#include "catalog/pg_type.h"
-#include "commands/explain.h"
#include "commands/prepare.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
* not the original PREPARE; we get the latter string from the plancache.
*/
void
-ExplainExecuteQuery(ExecuteStmt *execstmt, ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params, TupOutputState *tstate)
+ExplainExecuteQuery(ExecuteStmt *execstmt, ExplainState *es,
+ const char *queryString, ParamListInfo params)
{
PreparedStatement *entry;
const char *query_string;
pstmt->intoClause = execstmt->into;
}
- ExplainOnePlan(pstmt, stmt, query_string,
- paramLI, tstate);
+ ExplainOnePlan(pstmt, es, query_string, paramLI);
}
else
{
- ExplainOneUtility((Node *) pstmt, stmt, query_string,
- params, tstate);
+ ExplainOneUtility((Node *) pstmt, es, query_string, params);
}
/* No need for CommandCounterIncrement, as ExplainOnePlan did it */
/* put a blank line between plans */
if (!is_last_query)
- do_text_output_oneline(tstate, "");
+ appendStringInfoChar(es->str, '\n');
}
if (estate)
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.434 2009/07/20 02:42:27 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.435 2009/07/26 23:34:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExplainStmt *newnode = makeNode(ExplainStmt);
COPY_NODE_FIELD(query);
- COPY_SCALAR_FIELD(verbose);
- COPY_SCALAR_FIELD(analyze);
+ COPY_NODE_FIELD(options);
return newnode;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.357 2009/07/20 02:42:27 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.358 2009/07/26 23:34:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
_equalExplainStmt(ExplainStmt *a, ExplainStmt *b)
{
COMPARE_NODE_FIELD(query);
- COMPARE_SCALAR_FIELD(verbose);
- COMPARE_SCALAR_FIELD(analyze);
+ COMPARE_NODE_FIELD(options);
return true;
}
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.672 2009/07/25 00:07:11 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.673 2009/07/26 23:34:18 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
%type <list> opt_interval interval_second
%type <node> overlay_placing substr_from substr_for
-%type <boolean> opt_instead opt_analyze
+%type <boolean> opt_instead
%type <boolean> index_opt_unique opt_verbose opt_full
%type <boolean> opt_freeze opt_default opt_recheck
%type <defelt> opt_binary opt_oids copy_delimiter
%type <node> generic_option_arg
%type <defelt> generic_option_elem alter_generic_option_elem
%type <list> generic_option_list alter_generic_option_list
+%type <str> explain_option_name
+%type <node> explain_option_arg
+%type <defelt> explain_option_elem
+%type <list> explain_option_list
%type <typnam> Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
;
NumericOnly:
- FCONST { $$ = makeFloat($1); }
+ FCONST { $$ = makeFloat($1); }
| '-' FCONST
{
$$ = makeFloat($2);
doNegateFloat($$);
}
- | SignedIconst { $$ = makeInteger($1); };
+ | SignedIconst { $$ = makeInteger($1); }
;
/*****************************************************************************
*
* QUERY:
* EXPLAIN [ANALYZE] [VERBOSE] query
+ * EXPLAIN ( options ) query
*
*****************************************************************************/
-ExplainStmt: EXPLAIN opt_analyze opt_verbose ExplainableStmt
+ExplainStmt:
+ EXPLAIN ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $2;
+ n->options = NIL;
+ $$ = (Node *) n;
+ }
+ | EXPLAIN analyze_keyword opt_verbose ExplainableStmt
{
ExplainStmt *n = makeNode(ExplainStmt);
- n->analyze = $2;
- n->verbose = $3;
n->query = $4;
- $$ = (Node *)n;
+ n->options = list_make1(makeDefElem("analyze", NULL));
+ if ($3)
+ n->options = lappend(n->options,
+ makeDefElem("verbose", NULL));
+ $$ = (Node *) n;
+ }
+ | EXPLAIN VERBOSE ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $3;
+ n->options = list_make1(makeDefElem("verbose", NULL));
+ $$ = (Node *) n;
+ }
+ | EXPLAIN '(' explain_option_list ')' ExplainableStmt
+ {
+ ExplainStmt *n = makeNode(ExplainStmt);
+ n->query = $5;
+ n->options = $3;
+ $$ = (Node *) n;
}
;
| ExecuteStmt /* by default all are $$=$1 */
;
-opt_analyze:
- analyze_keyword { $$ = TRUE; }
- | /* EMPTY */ { $$ = FALSE; }
+explain_option_list:
+ explain_option_elem
+ {
+ $$ = list_make1($1);
+ }
+ | explain_option_list ',' explain_option_elem
+ {
+ $$ = lappend($1, $3);
+ }
+ ;
+
+explain_option_elem:
+ explain_option_name explain_option_arg
+ {
+ $$ = makeDefElem($1, $2);
+ }
+ ;
+
+explain_option_name:
+ ColId { $$ = $1; }
+ | analyze_keyword { $$ = "analyze"; }
+ | VERBOSE { $$ = "verbose"; }
+ ;
+
+explain_option_arg:
+ opt_boolean { $$ = (Node *) makeString($1); }
+ | ColId_or_Sconst { $$ = (Node *) makeString($1); }
+ | NumericOnly { $$ = (Node *) $1; }
+ | /* EMPTY */ { $$ = NULL; }
;
/*****************************************************************************
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.310 2009/07/16 06:33:44 petere Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.311 2009/07/26 23:34:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
case T_ExplainStmt:
{
ExplainStmt *stmt = (ExplainStmt *) parsetree;
+ bool analyze = false;
+ ListCell *lc;
/* Look through an EXPLAIN ANALYZE to the contained stmt */
- if (stmt->analyze)
+ foreach(lc, stmt->options)
+ {
+ DefElem *opt = (DefElem *) lfirst(lc);
+
+ if (strcmp(opt->defname, "analyze") == 0)
+ analyze = defGetBoolean(opt);
+ }
+ if (analyze)
return GetCommandLogLevel(stmt->query);
+
/* Plain EXPLAIN isn't so interesting */
lev = LOGSTMT_ALL;
}
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/commands/explain.h,v 1.39 2009/06/11 14:49:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/explain.h,v 1.40 2009/07/26 23:34:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/executor.h"
+typedef struct ExplainState
+{
+ StringInfo str; /* output buffer */
+ /* options */
+ bool verbose; /* print plan targetlists */
+ bool analyze; /* print actual times */
+ bool costs; /* print costs */
+ /* other states */
+ PlannedStmt *pstmt; /* top of plan */
+ List *rtable; /* range table */
+} ExplainState;
+
/* Hook for plugins to get control in ExplainOneQuery() */
typedef void (*ExplainOneQuery_hook_type) (Query *query,
- ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params,
- TupOutputState *tstate);
+ ExplainState *es,
+ const char *queryString,
+ ParamListInfo params);
extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
/* Hook for plugins to get control in explain_get_index_name() */
extern void ExplainQuery(ExplainStmt *stmt, const char *queryString,
ParamListInfo params, DestReceiver *dest);
+extern void ExplainInitState(ExplainState *es);
+
extern TupleDesc ExplainResultDesc(ExplainStmt *stmt);
-extern void ExplainOneUtility(Node *utilityStmt, ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params,
- TupOutputState *tstate);
+extern void ExplainOneUtility(Node *utilityStmt, ExplainState *es,
+ const char *queryString, ParamListInfo params);
-extern void ExplainOnePlan(PlannedStmt *plannedstmt, ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params,
- TupOutputState *tstate);
+extern void ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
+ const char *queryString, ParamListInfo params);
-extern void ExplainPrintPlan(StringInfo str, QueryDesc *queryDesc,
- bool analyze, bool verbose);
+extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
#endif /* EXPLAIN_H */
*
* Copyright (c) 2002-2009, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.30 2009/01/01 17:23:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.31 2009/07/26 23:34:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PREPARE_H
#define PREPARE_H
-#include "executor/executor.h"
+#include "commands/explain.h"
#include "utils/plancache.h"
#include "utils/timestamp.h"
ParamListInfo params,
DestReceiver *dest, char *completionTag);
extern void DeallocateQuery(DeallocateStmt *stmt);
-extern void ExplainExecuteQuery(ExecuteStmt *execstmt, ExplainStmt *stmt,
- const char *queryString,
- ParamListInfo params, TupOutputState *tstate);
+extern void ExplainExecuteQuery(ExecuteStmt *execstmt, ExplainState *es,
+ const char *queryString, ParamListInfo params);
/* Low-level access to stored prepared statements */
extern void StorePreparedStatement(const char *stmt_name,
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.397 2009/07/20 02:42:28 adunstan Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.398 2009/07/26 23:34:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
NodeTag type;
Node *query; /* the query (as a raw parse tree) */
- bool verbose; /* print plan info */
- bool analyze; /* get statistics by executing plan */
+ List *options; /* list of DefElem nodes */
} ExplainStmt;
/* ----------------------