@@ -116,6 +116,7 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
116
116
TupOutputState * tstate ;
117
117
List * rewritten ;
118
118
ListCell * lc ;
119
+ bool timing_set = false;
119
120
120
121
/* Initialize ExplainState. */
121
122
ExplainInitState (& es );
@@ -133,6 +134,11 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
133
134
es .costs = defGetBoolean (opt );
134
135
else if (strcmp (opt -> defname , "buffers" ) == 0 )
135
136
es .buffers = defGetBoolean (opt );
137
+ else if (strcmp (opt -> defname , "timing" ) == 0 )
138
+ {
139
+ timing_set = true;
140
+ es .timing = defGetBoolean (opt );
141
+ }
136
142
else if (strcmp (opt -> defname , "format" ) == 0 )
137
143
{
138
144
char * p = defGetString (opt );
@@ -162,6 +168,15 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
162
168
ereport (ERROR ,
163
169
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
164
170
errmsg ("EXPLAIN option BUFFERS requires ANALYZE" )));
171
+
172
+ /* if the timing was not set explicitly, set default value */
173
+ es .timing = (timing_set ) ? es .timing : es .analyze ;
174
+
175
+ /* check that timing is used with EXPLAIN ANALYZE */
176
+ if (es .timing && !es .analyze )
177
+ ereport (ERROR ,
178
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
179
+ errmsg ("EXPLAIN option TIMING requires ANALYZE" )));
165
180
166
181
/*
167
182
* Parse analysis was done already, but we still have to run the rule
@@ -360,8 +375,11 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
360
375
int eflags ;
361
376
int instrument_option = 0 ;
362
377
363
- if (es -> analyze )
378
+ if (es -> analyze && es -> timing )
364
379
instrument_option |= INSTRUMENT_TIMER ;
380
+ else if (es -> analyze )
381
+ instrument_option |= INSTRUMENT_ROWS ;
382
+
365
383
if (es -> buffers )
366
384
instrument_option |= INSTRUMENT_BUFFERS ;
367
385
@@ -956,29 +974,42 @@ ExplainNode(PlanState *planstate, List *ancestors,
956
974
957
975
if (es -> format == EXPLAIN_FORMAT_TEXT )
958
976
{
959
- appendStringInfo (es -> str ,
960
- " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)" ,
961
- startup_sec , total_sec , rows , nloops );
977
+ if (planstate -> instrument -> need_timer )
978
+ appendStringInfo (es -> str ,
979
+ " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)" ,
980
+ startup_sec , total_sec , rows , nloops );
981
+ else
982
+ appendStringInfo (es -> str ,
983
+ " (actual rows=%.0f loops=%.0f)" ,
984
+ rows , nloops );
962
985
}
963
986
else
964
987
{
965
- ExplainPropertyFloat ("Actual Startup Time" , startup_sec , 3 , es );
966
- ExplainPropertyFloat ("Actual Total Time" , total_sec , 3 , es );
988
+ if (planstate -> instrument -> need_timer )
989
+ {
990
+ ExplainPropertyFloat ("Actual Startup Time" , startup_sec , 3 , es );
991
+ ExplainPropertyFloat ("Actual Total Time" , total_sec , 3 , es );
992
+ }
967
993
ExplainPropertyFloat ("Actual Rows" , rows , 0 , es );
968
994
ExplainPropertyFloat ("Actual Loops" , nloops , 0 , es );
969
995
}
970
996
}
971
997
else if (es -> analyze )
972
998
{
999
+
973
1000
if (es -> format == EXPLAIN_FORMAT_TEXT )
974
1001
appendStringInfo (es -> str , " (never executed)" );
975
- else
1002
+ else if ( planstate -> instrument -> need_timer )
976
1003
{
977
1004
ExplainPropertyFloat ("Actual Startup Time" , 0.0 , 3 , es );
978
1005
ExplainPropertyFloat ("Actual Total Time" , 0.0 , 3 , es );
1006
+ }
1007
+ else
1008
+ {
979
1009
ExplainPropertyFloat ("Actual Rows" , 0.0 , 0 , es );
980
1010
ExplainPropertyFloat ("Actual Loops" , 0.0 , 0 , es );
981
1011
}
1012
+
982
1013
}
983
1014
984
1015
/* in text format, first line ends here */
0 commit comments