1
- /*
1
+ /*-------------------------------------------------------------------------
2
+ *
2
3
* explain.c
3
- * Explain the query execution plan
4
+ * Explain query execution plans
4
5
*
5
6
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
6
7
* Portions Copyright (c) 1994-5, Regents of the University of California
7
8
*
8
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.99 2002/12/15 16:17:38 tgl Exp $
9
+ * IDENTIFICATION
10
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.100 2003/02/02 23:46:38 tgl Exp $
9
11
*
12
+ *-------------------------------------------------------------------------
10
13
*/
11
-
12
14
#include "postgres.h"
13
15
14
16
#include "access/genam.h"
15
17
#include "access/heapam.h"
16
18
#include "catalog/pg_type.h"
17
19
#include "commands/explain.h"
20
+ #include "commands/prepare.h"
18
21
#include "executor/executor.h"
19
22
#include "executor/instrument.h"
20
23
#include "lib/stringinfo.h"
@@ -81,8 +84,11 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
81
84
82
85
if (query -> commandType == CMD_UTILITY )
83
86
{
84
- /* rewriter will not cope with utility statements */
85
- do_text_output_oneline (tstate , "Utility statements have no plan structure" );
87
+ /* Rewriter will not cope with utility statements */
88
+ if (query -> utilityStmt && IsA (query -> utilityStmt , ExecuteStmt ))
89
+ ExplainExecuteQuery (stmt , tstate );
90
+ else
91
+ do_text_output_oneline (tstate , "Utility statements have no plan structure" );
86
92
}
87
93
else
88
94
{
@@ -119,10 +125,6 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
119
125
{
120
126
Plan * plan ;
121
127
QueryDesc * queryDesc ;
122
- ExplainState * es ;
123
- StringInfo str ;
124
- double totaltime = 0 ;
125
- struct timeval starttime ;
126
128
127
129
/* planner will not cope with utility statements */
128
130
if (query -> commandType == CMD_UTILITY )
@@ -134,22 +136,48 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
134
136
return ;
135
137
}
136
138
139
+ /*
140
+ * We don't support DECLARE CURSOR in EXPLAIN, but parser will take it
141
+ * because it's an OptimizableStmt
142
+ */
143
+ if (query -> isPortal )
144
+ elog (ERROR , "EXPLAIN / DECLARE CURSOR is not supported" );
145
+
137
146
/* plan the query */
138
147
plan = planner (query );
139
148
140
149
/* pg_plan could have failed */
141
150
if (plan == NULL )
142
151
return ;
143
152
144
- /* We don't support DECLARE CURSOR here */
145
- Assert (!query -> isPortal );
146
-
147
- gettimeofday (& starttime , NULL );
148
-
149
153
/* Create a QueryDesc requesting no output */
150
154
queryDesc = CreateQueryDesc (query , plan , None , NULL , NULL ,
151
155
stmt -> analyze );
152
156
157
+ ExplainOnePlan (queryDesc , stmt , tstate );
158
+ }
159
+
160
+ /*
161
+ * ExplainOnePlan -
162
+ * given a planned query, execute it if needed, and then print
163
+ * EXPLAIN output
164
+ *
165
+ * This is exported because it's called back from prepare.c in the
166
+ * EXPLAIN EXECUTE case
167
+ *
168
+ * Note: the passed-in QueryDesc is freed when we're done with it
169
+ */
170
+ void
171
+ ExplainOnePlan (QueryDesc * queryDesc , ExplainStmt * stmt ,
172
+ TupOutputState * tstate )
173
+ {
174
+ struct timeval starttime ;
175
+ double totaltime = 0 ;
176
+ ExplainState * es ;
177
+ StringInfo str ;
178
+
179
+ gettimeofday (& starttime , NULL );
180
+
153
181
/* call ExecutorStart to prepare the plan for execution */
154
182
ExecutorStart (queryDesc );
155
183
@@ -160,7 +188,6 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
160
188
ExecutorRun (queryDesc , ForwardScanDirection , 0L );
161
189
162
190
/* We can't clean up 'till we're done printing the stats... */
163
-
164
191
totaltime += elapsed_time (& starttime );
165
192
}
166
193
@@ -169,14 +196,14 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
169
196
es -> printCost = true; /* default */
170
197
es -> printNodes = stmt -> verbose ;
171
198
es -> printAnalyze = stmt -> analyze ;
172
- es -> rtable = query -> rtable ;
199
+ es -> rtable = queryDesc -> parsetree -> rtable ;
173
200
174
201
if (es -> printNodes )
175
202
{
176
203
char * s ;
177
204
char * f ;
178
205
179
- s = nodeToString (plan );
206
+ s = nodeToString (queryDesc -> plantree );
180
207
if (s )
181
208
{
182
209
if (Explain_pretty_print )
@@ -195,7 +222,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
195
222
196
223
if (es -> printCost )
197
224
{
198
- explain_outNode (str , plan , queryDesc -> planstate ,
225
+ explain_outNode (str , queryDesc -> plantree , queryDesc -> planstate ,
199
226
NULL , 0 , es );
200
227
}
201
228
0 commit comments