55 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
66 * Portions Copyright (c) 1994-5, Regents of the University of California
77 *
8- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.81 2002/07/20 05:16:57 momjian Exp $
8+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.82 2002/07/20 05:49:27 momjian Exp $
99 *
1010 */
1111
1515#include "access/heapam.h"
1616#include "catalog/pg_type.h"
1717#include "commands/explain.h"
18+ #include "executor/executor.h"
1819#include "executor/instrument.h"
1920#include "lib/stringinfo.h"
2021#include "nodes/print.h"
@@ -38,15 +39,9 @@ typedef struct ExplainState
3839List * rtable ;/* range table */
3940}ExplainState ;
4041
41- typedef struct TextOutputState
42- {
43- TupleDesc tupdesc ;
44- DestReceiver * destfunc ;
45- }TextOutputState ;
46-
4742static StringInfo Explain_PlanToString (Plan * plan ,ExplainState * es );
4843static void ExplainOneQuery (Query * query ,ExplainStmt * stmt ,
49- TextOutputState * tstate );
44+ TupOutputState * tstate );
5045static void explain_outNode (StringInfo str ,Plan * plan ,Plan * outer_plan ,
5146int indent ,ExplainState * es );
5247static 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,
5954static void show_sort_keys (List * tlist ,int nkeys ,const char * qlabel ,
6055StringInfo str ,int indent ,ExplainState * es );
6156static Node * make_ors_ands_explicit (List * orclauses );
62- static TextOutputState * begin_text_output (CommandDest dest ,char * title );
63- static void do_text_output (TextOutputState * tstate ,char * aline );
64- static void do_text_output_multiline (TextOutputState * tstate ,char * text );
65- static void end_text_output (TextOutputState * tstate );
66-
6757
6858/*
6959 * ExplainQuery -
7363ExplainQuery (ExplainStmt * stmt ,CommandDest dest )
7464{
7565Query * query = stmt -> query ;
76- TextOutputState * tstate ;
66+ TupOutputState * tstate ;
67+ TupleDesc tupdesc ;
7768List * rewritten ;
7869List * l ;
7970
80- tstate = begin_text_output (dest ,"QUERY PLAN" );
71+ /* need a tuple descriptor representing a single TEXT column */
72+ tupdesc = CreateTemplateTupleDesc (1 );
73+ TupleDescInitEntry (tupdesc , (AttrNumber )1 ,"QUERY PLAN" ,
74+ TEXTOID ,-1 ,0 , false);
75+
76+ /* prepare for projection of tuples */
77+ tstate = begin_tup_output_tupdesc (dest ,tupdesc );
8178
8279if (query -> commandType == CMD_UTILITY )
8380{
8481/* rewriter will not cope with utility statements */
85- do_text_output ( tstate , "Utility statements have no plan structure" );
82+ PROJECT_LINE_OF_TEXT ( "Utility statements have no plan structure" );
8683}
8784else
8885{
@@ -92,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
9289if (rewritten == NIL )
9390{
9491/* In the case of an INSTEAD NOTHING, tell at least that */
95- do_text_output ( tstate , "Query rewrites to nothing" );
92+ PROJECT_LINE_OF_TEXT ( "Query rewrites to nothing" );
9693}
9794else
9895{
@@ -102,20 +99,20 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
10299ExplainOneQuery (lfirst (l ),stmt ,tstate );
103100/* put a blank line between plans */
104101if (lnext (l )!= NIL )
105- do_text_output ( tstate , "" );
102+ PROJECT_LINE_OF_TEXT ( "" );
106103}
107104}
108105}
109106
110- end_text_output (tstate );
107+ end_tup_output (tstate );
111108}
112109
113110/*
114111 * ExplainOneQuery -
115112 * print out the execution plan for one query
116113 */
117114static void
118- ExplainOneQuery (Query * query ,ExplainStmt * stmt ,TextOutputState * tstate )
115+ ExplainOneQuery (Query * query ,ExplainStmt * stmt ,TupOutputState * tstate )
119116{
120117Plan * plan ;
121118ExplainState * es ;
@@ -125,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate)
125122if (query -> commandType == CMD_UTILITY )
126123{
127124if (query -> utilityStmt && IsA (query -> utilityStmt ,NotifyStmt ))
128- do_text_output ( tstate , "NOTIFY" );
125+ PROJECT_LINE_OF_TEXT ( "NOTIFY" );
129126else
130- do_text_output ( tstate , "UTILITY" );
127+ PROJECT_LINE_OF_TEXT ( "UTILITY" );
131128return ;
132129}
133130
@@ -192,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate)
192189do_text_output_multiline (tstate ,f );
193190pfree (f );
194191if (es -> printCost )
195- do_text_output ( tstate , "" );/* separator line */
192+ PROJECT_LINE_OF_TEXT ( "" );/* separator line */
196193}
197194}
198195
@@ -837,78 +834,3 @@ make_ors_ands_explicit(List *orclauses)
837834return (Node * )make_orclause (args );
838835}
839836}
840-
841-
842- /*
843- * Functions for sending text to the frontend (or other specified destination)
844- * as though it is a SELECT result.
845- *
846- * We tell the frontend that the table structure is a single TEXT column.
847- */
848-
849- static TextOutputState *
850- begin_text_output (CommandDest dest ,char * title )
851- {
852- TextOutputState * tstate ;
853- TupleDesc tupdesc ;
854-
855- tstate = (TextOutputState * )palloc (sizeof (TextOutputState ));
856-
857- /* need a tuple descriptor representing a single TEXT column */
858- tupdesc = CreateTemplateTupleDesc (1 ,WITHOUTOID );
859- TupleDescInitEntry (tupdesc , (AttrNumber )1 ,title ,
860- TEXTOID ,-1 ,0 , false);
861-
862- tstate -> tupdesc = tupdesc ;
863- tstate -> destfunc = DestToFunction (dest );
864-
865- (* tstate -> destfunc -> setup ) (tstate -> destfunc , (int )CMD_SELECT ,
866- NULL ,tupdesc );
867-
868- return tstate ;
869- }
870-
871- /* write a single line of text */
872- static void
873- do_text_output (TextOutputState * tstate ,char * aline )
874- {
875- HeapTuple tuple ;
876- Datum values [1 ];
877- char nulls [1 ];
878-
879- /* form a tuple and send it to the receiver */
880- values [0 ]= DirectFunctionCall1 (textin ,CStringGetDatum (aline ));
881- nulls [0 ]= ' ' ;
882- tuple = heap_formtuple (tstate -> tupdesc ,values ,nulls );
883- (* tstate -> destfunc -> receiveTuple ) (tuple ,
884- tstate -> tupdesc ,
885- tstate -> destfunc );
886- pfree (DatumGetPointer (values [0 ]));
887- heap_freetuple (tuple );
888- }
889-
890- /* write a chunk of text, breaking at newline characters */
891- /* NB: scribbles on its input! */
892- static void
893- do_text_output_multiline (TextOutputState * tstate ,char * text )
894- {
895- while (* text )
896- {
897- char * eol ;
898-
899- eol = strchr (text ,'\n' );
900- if (eol )
901- * eol ++ = '\0' ;
902- else
903- eol = text + strlen (text );
904- do_text_output (tstate ,text );
905- text = eol ;
906- }
907- }
908-
909- static void
910- end_text_output (TextOutputState * tstate )
911- {
912- (* tstate -> destfunc -> cleanup ) (tstate -> destfunc );
913- pfree (tstate );
914- }