aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/explain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r--src/backend/commands/explain.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 672ec54cb02..91282ffc3f6 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -5,18 +5,20 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.65 2001/03/22 03:59:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.66 2001/09/18 01:59:06 tgl Exp $
*
*/
#include "postgres.h"
#include "commands/explain.h"
+#include "executor/instrument.h"
#include "lib/stringinfo.h"
#include "nodes/print.h"
#include "optimizer/planner.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteHandler.h"
+#include "tcop/pquery.h"
#include "utils/relcache.h"
typedef struct ExplainState
@@ -28,8 +30,8 @@ typedef struct ExplainState
List *rtable; /* range table */
} ExplainState;
-static char *Explain_PlanToString(Plan *plan, ExplainState *es);
-static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest);
+static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es);
+static void ExplainOneQuery(Query *query, bool verbose, bool analyze, CommandDest dest);
/* Convert a null string pointer into "<>" */
#define stringStringInfo(s) (((s) == NULL) ? "<>" : (s))
@@ -41,7 +43,7 @@ static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest);
*
*/
void
-ExplainQuery(Query *query, bool verbose, CommandDest dest)
+ExplainQuery(Query *query, bool verbose, bool analyze, CommandDest dest)
{
List *rewritten;
List *l;
@@ -73,7 +75,7 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
/* Explain every plan */
foreach(l, rewritten)
- ExplainOneQuery(lfirst(l), verbose, dest);
+ ExplainOneQuery(lfirst(l), verbose, analyze, dest);
}
/*
@@ -82,11 +84,11 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
*
*/
static void
-ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
+ExplainOneQuery(Query *query, bool verbose, bool analyze, CommandDest dest)
{
- char *s;
Plan *plan;
ExplainState *es;
+ double totaltime = 0;
/* planner will not cope with utility statements */
if (query->commandType == CMD_UTILITY)
@@ -105,6 +107,34 @@ ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
if (plan == NULL)
return;
+ /* Execute the plan for statistics if asked for */
+ if (analyze)
+ {
+ struct timeval starttime;
+ struct timeval endtime;
+
+ /*
+ * Set up the instrumentation for the top node.
+ * This will cascade during plan initialisation
+ */
+ plan->instrument = InstrAlloc();
+
+ gettimeofday(&starttime, NULL);
+ ProcessQuery(query, plan, None);
+ CommandCounterIncrement();
+ gettimeofday(&endtime, NULL);
+
+ endtime.tv_sec -= starttime.tv_sec;
+ endtime.tv_usec -= starttime.tv_usec;
+ while (endtime.tv_usec < 0)
+ {
+ endtime.tv_usec += 1000000;
+ endtime.tv_sec--;
+ }
+ totaltime = (double) endtime.tv_sec +
+ (double) endtime.tv_usec / 1000000.0;
+ }
+
es = (ExplainState *) palloc(sizeof(ExplainState));
MemSet(es, 0, sizeof(ExplainState));
@@ -117,6 +147,8 @@ ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
if (es->printNodes)
{
+ char *s;
+
s = nodeToString(plan);
if (s)
{
@@ -127,12 +159,15 @@ ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
if (es->printCost)
{
- s = Explain_PlanToString(plan, es);
- if (s)
- {
- elog(NOTICE, "QUERY PLAN:\n\n%s", s);
- pfree(s);
- }
+ StringInfo str;
+
+ str = Explain_PlanToString(plan, es);
+ if (analyze)
+ appendStringInfo(str, "Total runtime: %.2f msec\n",
+ 1000.0 * totaltime);
+ elog(NOTICE, "QUERY PLAN:\n\n%s", str->data);
+ pfree(str->data);
+ pfree(str);
}
if (es->printNodes)
@@ -292,6 +327,17 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
appendStringInfo(str, " (cost=%.2f..%.2f rows=%.0f width=%d)",
plan->startup_cost, plan->total_cost,
plan->plan_rows, plan->plan_width);
+
+ if ( plan->instrument && plan->instrument->nloops > 0 )
+ {
+ double nloops = plan->instrument->nloops;
+
+ appendStringInfo(str, " (actual time=%.2f..%.2f rows=%.0f loops=%.0f)",
+ 1000.0 * plan->instrument->startup / nloops,
+ 1000.0 * plan->instrument->total / nloops,
+ plan->instrument->ntuples / nloops,
+ plan->instrument->nloops);
+ }
}
appendStringInfo(str, "\n");
@@ -393,14 +439,12 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
}
}
-static char *
+static StringInfo
Explain_PlanToString(Plan *plan, ExplainState *es)
{
- StringInfoData str;
+ StringInfo str = makeStringInfo();
- /* see stringinfo.h for an explanation of this maneuver */
- initStringInfo(&str);
if (plan != NULL)
- explain_outNode(&str, plan, 0, es);
- return str.data;
+ explain_outNode(str, plan, 0, es);
+ return str;
}