1818#include "commands/defrem.h"
1919#include "commands/prepare.h"
2020#include "executor/hashjoin.h"
21- #include "executor/instrument.h"
2221#include "foreign/fdwapi.h"
2322#include "optimizer/clauses.h"
2423#include "parser/parsetree.h"
@@ -76,6 +75,8 @@ static void show_sort_keys_common(PlanState *planstate,
7675List * ancestors ,ExplainState * es );
7776static void show_sort_info (SortState * sortstate ,ExplainState * es );
7877static void show_hash_info (HashState * hashstate ,ExplainState * es );
78+ static void show_instrumentation_count (const char * qlabel ,int which ,
79+ PlanState * planstate ,ExplainState * es );
7980static void show_foreignscan_info (ForeignScanState * fsstate ,ExplainState * es );
8081static const char * explain_get_index_name (Oid indexId );
8182static void ExplainScanTarget (Scan * plan ,ExplainState * es );
@@ -1000,9 +1001,15 @@ ExplainNode(PlanState *planstate, List *ancestors,
10001001case T_IndexScan :
10011002show_scan_qual (((IndexScan * )plan )-> indexqualorig ,
10021003"Index Cond" ,planstate ,ancestors ,es );
1004+ if (((IndexScan * )plan )-> indexqualorig )
1005+ show_instrumentation_count ("Rows Removed by Index Recheck" ,2 ,
1006+ planstate ,es );
10031007show_scan_qual (((IndexScan * )plan )-> indexorderbyorig ,
10041008"Order By" ,planstate ,ancestors ,es );
10051009show_scan_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1010+ if (plan -> qual )
1011+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1012+ planstate ,es );
10061013break ;
10071014case T_BitmapIndexScan :
10081015show_scan_qual (((BitmapIndexScan * )plan )-> indexqualorig ,
@@ -1011,20 +1018,29 @@ ExplainNode(PlanState *planstate, List *ancestors,
10111018case T_BitmapHeapScan :
10121019show_scan_qual (((BitmapHeapScan * )plan )-> bitmapqualorig ,
10131020"Recheck Cond" ,planstate ,ancestors ,es );
1021+ if (((BitmapHeapScan * )plan )-> bitmapqualorig )
1022+ show_instrumentation_count ("Rows Removed by Index Recheck" ,2 ,
1023+ planstate ,es );
10141024/* FALL THRU */
10151025case T_SeqScan :
10161026case T_ValuesScan :
10171027case T_CteScan :
10181028case T_WorkTableScan :
10191029case T_SubqueryScan :
10201030show_scan_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1031+ if (plan -> qual )
1032+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1033+ planstate ,es );
10211034break ;
10221035case T_FunctionScan :
10231036if (es -> verbose )
10241037show_expression (((FunctionScan * )plan )-> funcexpr ,
10251038"Function Call" ,planstate ,ancestors ,
10261039es -> verbose ,es );
10271040show_scan_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1041+ if (plan -> qual )
1042+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1043+ planstate ,es );
10281044break ;
10291045case T_TidScan :
10301046{
@@ -1038,34 +1054,61 @@ ExplainNode(PlanState *planstate, List *ancestors,
10381054tidquals = list_make1 (make_orclause (tidquals ));
10391055show_scan_qual (tidquals ,"TID Cond" ,planstate ,ancestors ,es );
10401056show_scan_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1057+ if (plan -> qual )
1058+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1059+ planstate ,es );
10411060}
10421061break ;
10431062case T_ForeignScan :
10441063show_scan_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1064+ if (plan -> qual )
1065+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1066+ planstate ,es );
10451067show_foreignscan_info ((ForeignScanState * )planstate ,es );
10461068break ;
10471069case T_NestLoop :
10481070show_upper_qual (((NestLoop * )plan )-> join .joinqual ,
10491071"Join Filter" ,planstate ,ancestors ,es );
1072+ if (((NestLoop * )plan )-> join .joinqual )
1073+ show_instrumentation_count ("Rows Removed by Join Filter" ,1 ,
1074+ planstate ,es );
10501075show_upper_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1076+ if (plan -> qual )
1077+ show_instrumentation_count ("Rows Removed by Filter" ,2 ,
1078+ planstate ,es );
10511079break ;
10521080case T_MergeJoin :
10531081show_upper_qual (((MergeJoin * )plan )-> mergeclauses ,
10541082"Merge Cond" ,planstate ,ancestors ,es );
10551083show_upper_qual (((MergeJoin * )plan )-> join .joinqual ,
10561084"Join Filter" ,planstate ,ancestors ,es );
1085+ if (((MergeJoin * )plan )-> join .joinqual )
1086+ show_instrumentation_count ("Rows Removed by Join Filter" ,1 ,
1087+ planstate ,es );
10571088show_upper_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1089+ if (plan -> qual )
1090+ show_instrumentation_count ("Rows Removed by Filter" ,2 ,
1091+ planstate ,es );
10581092break ;
10591093case T_HashJoin :
10601094show_upper_qual (((HashJoin * )plan )-> hashclauses ,
10611095"Hash Cond" ,planstate ,ancestors ,es );
10621096show_upper_qual (((HashJoin * )plan )-> join .joinqual ,
10631097"Join Filter" ,planstate ,ancestors ,es );
1098+ if (((HashJoin * )plan )-> join .joinqual )
1099+ show_instrumentation_count ("Rows Removed by Join Filter" ,1 ,
1100+ planstate ,es );
10641101show_upper_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1102+ if (plan -> qual )
1103+ show_instrumentation_count ("Rows Removed by Filter" ,2 ,
1104+ planstate ,es );
10651105break ;
10661106case T_Agg :
10671107case T_Group :
10681108show_upper_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1109+ if (plan -> qual )
1110+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1111+ planstate ,es );
10691112break ;
10701113case T_Sort :
10711114show_sort_keys ((SortState * )planstate ,ancestors ,es );
@@ -1079,6 +1122,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
10791122show_upper_qual ((List * ) ((Result * )plan )-> resconstantqual ,
10801123"One-Time Filter" ,planstate ,ancestors ,es );
10811124show_upper_qual (plan -> qual ,"Filter" ,planstate ,ancestors ,es );
1125+ if (plan -> qual )
1126+ show_instrumentation_count ("Rows Removed by Filter" ,1 ,
1127+ planstate ,es );
10821128break ;
10831129case T_Hash :
10841130show_hash_info ((HashState * )planstate ,es );
@@ -1508,6 +1554,37 @@ show_hash_info(HashState *hashstate, ExplainState *es)
15081554}
15091555}
15101556
1557+ /*
1558+ * If it's EXPLAIN ANALYZE, show instrumentation information for a plan node
1559+ *
1560+ * "which" identifies which instrumentation counter to print
1561+ */
1562+ static void
1563+ show_instrumentation_count (const char * qlabel ,int which ,
1564+ PlanState * planstate ,ExplainState * es )
1565+ {
1566+ double nfiltered ;
1567+ double nloops ;
1568+
1569+ if (!es -> analyze || !planstate -> instrument )
1570+ return ;
1571+
1572+ if (which == 2 )
1573+ nfiltered = planstate -> instrument -> nfiltered2 ;
1574+ else
1575+ nfiltered = planstate -> instrument -> nfiltered1 ;
1576+ nloops = planstate -> instrument -> nloops ;
1577+
1578+ /* In text mode, suppress zero counts; they're not interesting enough */
1579+ if (nfiltered > 0 || es -> format != EXPLAIN_FORMAT_TEXT )
1580+ {
1581+ if (nloops > 0 )
1582+ ExplainPropertyFloat (qlabel ,nfiltered /nloops ,0 ,es );
1583+ else
1584+ ExplainPropertyFloat (qlabel ,0.0 ,0 ,es );
1585+ }
1586+ }
1587+
15111588/*
15121589 * Show extra information for a ForeignScan node.
15131590 */