diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 353 |
1 files changed, 184 insertions, 169 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 7d1f34d0327..192076e3911 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * explain.c-- - * Explain the query execution plan + * Explain the query execution plan * * Copyright (c) 1994-5, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.10 1997/08/18 20:52:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.11 1997/09/07 04:40:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include <postgres.h> #include <parser/catalog_utils.h> -#include <parser/parse_query.h> /* for MakeTimeRange() */ +#include <parser/parse_query.h> /* for MakeTimeRange() */ #include <nodes/plannodes.h> #include <tcop/tcopprot.h> #include <lib/stringinfo.h> @@ -25,79 +25,86 @@ #include <optimizer/planner.h> #include <access/xact.h> -typedef struct ExplainState { - /* options */ - bool printCost; /* print cost */ - bool printNodes; /* do nodeToString() instead */ - /* other states */ - List *rtable; /* range table */ -} ExplainState; +typedef struct ExplainState +{ + /* options */ + bool printCost; /* print cost */ + bool printNodes; /* do nodeToString() instead */ + /* other states */ + List *rtable; /* range table */ +} ExplainState; -static char *Explain_PlanToString(Plan *plan, ExplainState *es); +static char *Explain_PlanToString(Plan * plan, ExplainState * es); /* * ExplainQuery - - * print out the execution plan for a given query + * print out the execution plan for a given query * */ void -ExplainQuery(Query *query, bool verbose, CommandDest dest) +ExplainQuery(Query * query, bool verbose, CommandDest dest) { - char *s = NULL, *s2; - Plan *plan; - ExplainState *es; - int len; - - if (IsAbortedTransactionBlockState()) { - char *tag = "*ABORT STATE*"; - EndCommand(tag, dest); - - elog(NOTICE, "(transaction aborted): %s", - "queries ignored until END"); - - return; - } + char *s = NULL, + *s2; + Plan *plan; + ExplainState *es; + int len; - /* plan the queries (XXX we've ignored rewrite!!) */ - plan = planner(query); + if (IsAbortedTransactionBlockState()) + { + char *tag = "*ABORT STATE*"; - /* pg_plan could have failed */ - if (plan == NULL) - return; + EndCommand(tag, dest); + + elog(NOTICE, "(transaction aborted): %s", + "queries ignored until END"); + + return; + } - es = (ExplainState*)malloc(sizeof(ExplainState)); - memset(es, 0, sizeof(ExplainState)); + /* plan the queries (XXX we've ignored rewrite!!) */ + plan = planner(query); - es->printCost = true; /* default */ + /* pg_plan could have failed */ + if (plan == NULL) + return; - if (verbose) - es->printNodes = true; + es = (ExplainState *) malloc(sizeof(ExplainState)); + memset(es, 0, sizeof(ExplainState)); - es->rtable = query->rtable; + es->printCost = true; /* default */ - if (es->printNodes) - s = nodeToString(plan); + if (verbose) + es->printNodes = true; - if (es->printCost) { - s2 = Explain_PlanToString(plan, es); - if (s == NULL) - s = s2; - else { - strcat(s, "\n\n"); - strcat(s, s2); + es->rtable = query->rtable; + + if (es->printNodes) + s = nodeToString(plan); + + if (es->printCost) + { + s2 = Explain_PlanToString(plan, es); + if (s == NULL) + s = s2; + else + { + strcat(s, "\n\n"); + strcat(s, s2); + } } - } - - /* output the plan */ - len = strlen(s); - elog(NOTICE, "QUERY PLAN:\n\n%.*s", ELOG_MAXLEN-64, s); - len -= ELOG_MAXLEN-64; - while (len > 0) { - s += ELOG_MAXLEN-64; - elog(NOTICE, "%.*s", ELOG_MAXLEN-64, s); - len -= ELOG_MAXLEN-64; - } - free(es); + + /* output the plan */ + len = strlen(s); + elog(NOTICE, "QUERY PLAN:\n\n%.*s", ELOG_MAXLEN - 64, s); + len -= ELOG_MAXLEN - 64; + while (len > 0) + { + s += ELOG_MAXLEN - 64; + elog(NOTICE, "%.*s", ELOG_MAXLEN - 64, s); + len -= ELOG_MAXLEN - 64; + } + free(es); } /***************************************************************************** @@ -106,122 +113,130 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest) /* * explain_outNode - - * converts a Node into ascii string and append it to 'str' + * converts a Node into ascii string and append it to 'str' */ static void -explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) +explain_outNode(StringInfo str, Plan * plan, int indent, ExplainState * es) { - char *pname; - char buf[1000]; - int i; - - if (plan==NULL) { + char *pname; + char buf[1000]; + int i; + + if (plan == NULL) + { + appendStringInfo(str, "\n"); + return; + } + + switch (nodeTag(plan)) + { + case T_Result: + pname = "Result"; + break; + case T_Append: + pname = "Append"; + break; + case T_NestLoop: + pname = "Nested Loop"; + break; + case T_MergeJoin: + pname = "Merge Join"; + break; + case T_HashJoin: + pname = "Hash Join"; + break; + case T_SeqScan: + pname = "Seq Scan"; + break; + case T_IndexScan: + pname = "Index Scan"; + break; + case T_Temp: + pname = "Temp Scan"; + break; + case T_Sort: + pname = "Sort"; + break; + case T_Group: + pname = "Group"; + break; + case T_Agg: + pname = "Aggregate"; + break; + case T_Unique: + pname = "Unique"; + break; + case T_Hash: + pname = "Hash"; + break; + case T_Tee: + pname = "Tee"; + break; + default: + pname = ""; + break; + } + + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + + appendStringInfo(str, pname); + switch (nodeTag(plan)) + { + case T_SeqScan: + case T_IndexScan: + if (((Scan *) plan)->scanrelid > 0) + { + RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable); + + sprintf(buf, " on %s", rte->refname); + appendStringInfo(str, buf); + } + break; + default: + break; + } + if (es->printCost) + { + sprintf(buf, " (cost=%.2f size=%d width=%d)", + plan->cost, plan->plan_size, plan->plan_width); + appendStringInfo(str, buf); + } appendStringInfo(str, "\n"); - return; - } - - switch(nodeTag(plan)) { - case T_Result: - pname = "Result"; - break; - case T_Append: - pname = "Append"; - break; - case T_NestLoop: - pname = "Nested Loop"; - break; - case T_MergeJoin: - pname = "Merge Join"; - break; - case T_HashJoin: - pname = "Hash Join"; - break; - case T_SeqScan: - pname = "Seq Scan"; - break; - case T_IndexScan: - pname = "Index Scan"; - break; - case T_Temp: - pname = "Temp Scan"; - break; - case T_Sort: - pname = "Sort"; - break; - case T_Group: - pname = "Group"; - break; - case T_Agg: - pname = "Aggregate"; - break; - case T_Unique: - pname = "Unique"; - break; - case T_Hash: - pname = "Hash"; - break; - case T_Tee: - pname = "Tee"; - break; - default: - pname = ""; - break; - } - - for(i=0; i < indent; i++) - appendStringInfo(str, " "); - - appendStringInfo(str, pname); - switch(nodeTag(plan)) { - case T_SeqScan: - case T_IndexScan: - if (((Scan*)plan)->scanrelid > 0) { - RangeTblEntry *rte = nth(((Scan*)plan)->scanrelid-1, es->rtable); - sprintf(buf, " on %s", rte->refname); - appendStringInfo(str, buf); + + /* lefttree */ + if (outerPlan(plan)) + { + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + appendStringInfo(str, " -> "); + explain_outNode(str, outerPlan(plan), indent + 1, es); } - break; - default: - break; - } - if (es->printCost) { - sprintf(buf, " (cost=%.2f size=%d width=%d)", - plan->cost, plan->plan_size, plan->plan_width); - appendStringInfo(str, buf); - } - appendStringInfo(str, "\n"); - - /* lefttree */ - if (outerPlan(plan)) { - for(i=0; i < indent; i++) - appendStringInfo(str, " "); - appendStringInfo(str, " -> "); - explain_outNode(str, outerPlan(plan), indent+1, es); - } - - /* righttree */ - if (innerPlan(plan)) { - for(i=0; i < indent; i++) - appendStringInfo(str, " "); - appendStringInfo(str, " -> "); - explain_outNode(str, innerPlan(plan), indent+1, es); - } - return; + + /* righttree */ + if (innerPlan(plan)) + { + for (i = 0; i < indent; i++) + appendStringInfo(str, " "); + appendStringInfo(str, " -> "); + explain_outNode(str, innerPlan(plan), indent + 1, es); + } + return; } -static char * -Explain_PlanToString(Plan *plan, ExplainState *es) +static char * +Explain_PlanToString(Plan * plan, ExplainState * es) { - StringInfo str; - char *s; - - if (plan==NULL) - return ""; - Assert(plan!=NULL); - str = makeStringInfo(); - explain_outNode(str, plan, 0, es); - s = str->data; - pfree(str); - - return s; + StringInfo str; + char *s; + + if (plan == NULL) + return ""; + Assert(plan != NULL); + str = makeStringInfo(); + explain_outNode(str, plan, 0, es); + s = str->data; + pfree(str); + + return s; } |