77 * Portions Copyright (c) 1994-5, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.195 2009/12/12 00:35:33 rhaas Exp $
10+ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.196 2009/12/15 04:57:47 rhaas Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -125,6 +125,8 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
125125es .verbose = defGetBoolean (opt );
126126else if (strcmp (opt -> defname ,"costs" )== 0 )
127127es .costs = defGetBoolean (opt );
128+ else if (strcmp (opt -> defname ,"buffers" )== 0 )
129+ es .buffers = defGetBoolean (opt );
128130else if (strcmp (opt -> defname ,"format" )== 0 )
129131{
130132char * p = defGetString (opt );
@@ -150,6 +152,11 @@ ExplainQuery(ExplainStmt *stmt, const char *queryString,
150152opt -> defname )));
151153}
152154
155+ if (es .buffers && !es .analyze )
156+ ereport (ERROR ,
157+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
158+ errmsg ("EXPLAIN option BUFFERS requires ANALYZE" )));
159+
153160/*
154161 * Run parse analysis and rewrite.Note this also acquires sufficient
155162 * locks on the source table(s).
@@ -339,6 +346,12 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
339346instr_time starttime ;
340347double totaltime = 0 ;
341348int eflags ;
349+ int instrument_option = 0 ;
350+
351+ if (es -> analyze )
352+ instrument_option |=INSTRUMENT_TIMER ;
353+ if (es -> buffers )
354+ instrument_option |=INSTRUMENT_BUFFERS ;
342355
343356/*
344357 * Use a snapshot with an updated command ID to ensure this query sees
@@ -349,7 +362,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, ExplainState *es,
349362/* Create a QueryDesc requesting no output */
350363queryDesc = CreateQueryDesc (plannedstmt ,queryString ,
351364GetActiveSnapshot (),InvalidSnapshot ,
352- None_Receiver ,params ,es -> analyze );
365+ None_Receiver ,params ,instrument_option );
353366
354367INSTR_TIME_SET_CURRENT (starttime );
355368
@@ -1042,6 +1055,84 @@ ExplainNode(Plan *plan, PlanState *planstate,
10421055break ;
10431056}
10441057
1058+ /* Show buffer usage */
1059+ if (es -> buffers )
1060+ {
1061+ const BufferUsage * usage = & planstate -> instrument -> bufusage ;
1062+
1063+ if (es -> format == EXPLAIN_FORMAT_TEXT )
1064+ {
1065+ bool has_shared = (usage -> shared_blks_hit > 0 ||
1066+ usage -> shared_blks_read > 0 ||
1067+ usage -> shared_blks_written );
1068+ bool has_local = (usage -> local_blks_hit > 0 ||
1069+ usage -> local_blks_read > 0 ||
1070+ usage -> local_blks_written );
1071+ bool has_temp = (usage -> temp_blks_read > 0 ||
1072+ usage -> temp_blks_written );
1073+
1074+ /* Show only positive counter values. */
1075+ if (has_shared || has_local || has_temp )
1076+ {
1077+ appendStringInfoSpaces (es -> str ,es -> indent * 2 );
1078+ appendStringInfoString (es -> str ,"Buffers:" );
1079+
1080+ if (has_shared )
1081+ {
1082+ appendStringInfoString (es -> str ," shared" );
1083+ if (usage -> shared_blks_hit > 0 )
1084+ appendStringInfo (es -> str ," hit=%ld" ,
1085+ usage -> shared_blks_hit );
1086+ if (usage -> shared_blks_read > 0 )
1087+ appendStringInfo (es -> str ," read=%ld" ,
1088+ usage -> shared_blks_read );
1089+ if (usage -> shared_blks_written > 0 )
1090+ appendStringInfo (es -> str ," written=%ld" ,
1091+ usage -> shared_blks_written );
1092+ if (has_local || has_temp )
1093+ appendStringInfoChar (es -> str ,',' );
1094+ }
1095+ if (has_local )
1096+ {
1097+ appendStringInfoString (es -> str ," local" );
1098+ if (usage -> local_blks_hit > 0 )
1099+ appendStringInfo (es -> str ," hit=%ld" ,
1100+ usage -> local_blks_hit );
1101+ if (usage -> local_blks_read > 0 )
1102+ appendStringInfo (es -> str ," read=%ld" ,
1103+ usage -> local_blks_read );
1104+ if (usage -> local_blks_written > 0 )
1105+ appendStringInfo (es -> str ," written=%ld" ,
1106+ usage -> local_blks_written );
1107+ if (has_temp )
1108+ appendStringInfoChar (es -> str ,',' );
1109+ }
1110+ if (has_temp )
1111+ {
1112+ appendStringInfoString (es -> str ," temp" );
1113+ if (usage -> temp_blks_read > 0 )
1114+ appendStringInfo (es -> str ," read=%ld" ,
1115+ usage -> temp_blks_read );
1116+ if (usage -> temp_blks_written > 0 )
1117+ appendStringInfo (es -> str ," written=%ld" ,
1118+ usage -> temp_blks_written );
1119+ }
1120+ appendStringInfoChar (es -> str ,'\n' );
1121+ }
1122+ }
1123+ else
1124+ {
1125+ ExplainPropertyLong ("Shared Hit Blocks" ,usage -> shared_blks_hit ,es );
1126+ ExplainPropertyLong ("Shared Read Blocks" ,usage -> shared_blks_read ,es );
1127+ ExplainPropertyLong ("Shared Written Blocks" ,usage -> shared_blks_written ,es );
1128+ ExplainPropertyLong ("Local Hit Blocks" ,usage -> local_blks_hit ,es );
1129+ ExplainPropertyLong ("Local Read Blocks" ,usage -> local_blks_read ,es );
1130+ ExplainPropertyLong ("Local Written Blocks" ,usage -> local_blks_written ,es );
1131+ ExplainPropertyLong ("Temp Read Blocks" ,usage -> temp_blks_read ,es );
1132+ ExplainPropertyLong ("Temp Written Blocks" ,usage -> temp_blks_written ,es );
1133+ }
1134+ }
1135+
10451136/* Get ready to display the child plans */
10461137haschildren = plan -> initPlan ||
10471138outerPlan (plan )||