diff options
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 118 |
1 files changed, 20 insertions, 98 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 2c90df205af..72acab0f1eb 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, 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.81 2002/07/20 05:16:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.82 2002/07/20 05:49:27 momjian Exp $ * */ @@ -15,6 +15,7 @@ #include "access/heapam.h" #include "catalog/pg_type.h" #include "commands/explain.h" +#include "executor/executor.h" #include "executor/instrument.h" #include "lib/stringinfo.h" #include "nodes/print.h" @@ -38,15 +39,9 @@ typedef struct ExplainState List *rtable; /* range table */ } ExplainState; -typedef struct TextOutputState -{ - TupleDesc tupdesc; - DestReceiver *destfunc; -} TextOutputState; - static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es); static void ExplainOneQuery(Query *query, ExplainStmt *stmt, - TextOutputState *tstate); + TupOutputState *tstate); static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, int indent, ExplainState *es); static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, @@ -59,11 +54,6 @@ static void show_upper_qual(List *qual, const char *qlabel, static void show_sort_keys(List *tlist, int nkeys, const char *qlabel, StringInfo str, int indent, ExplainState *es); static Node *make_ors_ands_explicit(List *orclauses); -static TextOutputState *begin_text_output(CommandDest dest, char *title); -static void do_text_output(TextOutputState *tstate, char *aline); -static void do_text_output_multiline(TextOutputState *tstate, char *text); -static void end_text_output(TextOutputState *tstate); - /* * ExplainQuery - @@ -73,16 +63,23 @@ void ExplainQuery(ExplainStmt *stmt, CommandDest dest) { Query *query = stmt->query; - TextOutputState *tstate; + TupOutputState *tstate; + TupleDesc tupdesc; List *rewritten; List *l; - tstate = begin_text_output(dest, "QUERY PLAN"); + /* need a tuple descriptor representing a single TEXT column */ + tupdesc = CreateTemplateTupleDesc(1); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN", + TEXTOID, -1, 0, false); + + /* prepare for projection of tuples */ + tstate = begin_tup_output_tupdesc(dest, tupdesc); if (query->commandType == CMD_UTILITY) { /* rewriter will not cope with utility statements */ - do_text_output(tstate, "Utility statements have no plan structure"); + PROJECT_LINE_OF_TEXT("Utility statements have no plan structure"); } else { @@ -92,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) if (rewritten == NIL) { /* In the case of an INSTEAD NOTHING, tell at least that */ - do_text_output(tstate, "Query rewrites to nothing"); + PROJECT_LINE_OF_TEXT("Query rewrites to nothing"); } else { @@ -102,12 +99,12 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) ExplainOneQuery(lfirst(l), stmt, tstate); /* put a blank line between plans */ if (lnext(l) != NIL) - do_text_output(tstate, ""); + PROJECT_LINE_OF_TEXT(""); } } } - end_text_output(tstate); + end_tup_output(tstate); } /* @@ -115,7 +112,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) * print out the execution plan for one query */ static void -ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate) +ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) { Plan *plan; ExplainState *es; @@ -125,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate) if (query->commandType == CMD_UTILITY) { if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) - do_text_output(tstate, "NOTIFY"); + PROJECT_LINE_OF_TEXT("NOTIFY"); else - do_text_output(tstate, "UTILITY"); + PROJECT_LINE_OF_TEXT("UTILITY"); return; } @@ -192,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate) do_text_output_multiline(tstate, f); pfree(f); if (es->printCost) - do_text_output(tstate, ""); /* separator line */ + PROJECT_LINE_OF_TEXT(""); /* separator line */ } } @@ -837,78 +834,3 @@ make_ors_ands_explicit(List *orclauses) return (Node *) make_orclause(args); } } - - -/* - * Functions for sending text to the frontend (or other specified destination) - * as though it is a SELECT result. - * - * We tell the frontend that the table structure is a single TEXT column. - */ - -static TextOutputState * -begin_text_output(CommandDest dest, char *title) -{ - TextOutputState *tstate; - TupleDesc tupdesc; - - tstate = (TextOutputState *) palloc(sizeof(TextOutputState)); - - /* need a tuple descriptor representing a single TEXT column */ - tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, title, - TEXTOID, -1, 0, false); - - tstate->tupdesc = tupdesc; - tstate->destfunc = DestToFunction(dest); - - (*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT, - NULL, tupdesc); - - return tstate; -} - -/* write a single line of text */ -static void -do_text_output(TextOutputState *tstate, char *aline) -{ - HeapTuple tuple; - Datum values[1]; - char nulls[1]; - - /* form a tuple and send it to the receiver */ - values[0] = DirectFunctionCall1(textin, CStringGetDatum(aline)); - nulls[0] = ' '; - tuple = heap_formtuple(tstate->tupdesc, values, nulls); - (*tstate->destfunc->receiveTuple) (tuple, - tstate->tupdesc, - tstate->destfunc); - pfree(DatumGetPointer(values[0])); - heap_freetuple(tuple); -} - -/* write a chunk of text, breaking at newline characters */ -/* NB: scribbles on its input! */ -static void -do_text_output_multiline(TextOutputState *tstate, char *text) -{ - while (*text) - { - char *eol; - - eol = strchr(text, '\n'); - if (eol) - *eol++ = '\0'; - else - eol = text + strlen(text); - do_text_output(tstate, text); - text = eol; - } -} - -static void -end_text_output(TextOutputState *tstate) -{ - (*tstate->destfunc->cleanup) (tstate->destfunc); - pfree(tstate); -} |