>From 4865950d8bb66ee29cead3ecb17b07812677bfdf Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 22 May 2009 15:37:13 +0200
Subject: [PATCH] Feature: discarded tuple count display in EXPLAIN ANALYZE

---
 src/backend/commands/explain.c    |    5 +++--
 src/backend/executor/execScan.c   |    9 +++++++++
 src/backend/executor/instrument.c |    2 ++
 src/include/executor/instrument.h |    5 ++++-
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index b334e2b..13644a8 100644
*** a/src/backend/commands/explain.c
--- b/src/backend/commands/explain.c
*************** explain_outNode(StringInfo str,
*** 805,815 ****
  	{
  		double		nloops = planstate->instrument->nloops;
  
! 		appendStringInfo(str, " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
  						 1000.0 * planstate->instrument->startup / nloops,
  						 1000.0 * planstate->instrument->total / nloops,
  						 planstate->instrument->ntuples / nloops,
! 						 planstate->instrument->nloops);
  	}
  	else if (es->printAnalyze)
  		appendStringInfo(str, " (never executed)");
--- 805,816 ----
  	{
  		double		nloops = planstate->instrument->nloops;
  
! 		appendStringInfo(str, " (actual time=%.3f..%.3f rows=%.0f loops=%.0f, discarded=%.0f)",
  						 1000.0 * planstate->instrument->startup / nloops,
  						 1000.0 * planstate->instrument->total / nloops,
  						 planstate->instrument->ntuples / nloops,
! 						 planstate->instrument->nloops,
! 						 planstate->instrument->ntuples_disc / nloops);
  	}
  	else if (es->printAnalyze)
  		appendStringInfo(str, " (never executed)");
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index 19fa4e6..9592554 100644
*** a/src/backend/executor/execScan.c
--- b/src/backend/executor/execScan.c
***************
*** 21,26 ****
--- 21,27 ----
  #include "executor/executor.h"
  #include "miscadmin.h"
  #include "utils/memutils.h"
+ #include "executor/instrument.h"
  
  
  static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
*************** ExecScan(ScanState *node,
*** 157,162 ****
--- 158,171 ----
  		}
  
  		/*
+ 		 * At this point the tuple has to be discarded by qualifier, so
+ 		 * increase discarded tuple count
+ 		 */
+ 		if(node->ps.instrument)
+ 			node->ps.instrument->tuplecount_disc += 1;
+ 
+ 
+ 		/*
  		 * Tuple fails qual, so free per-tuple memory and try again.
  		 */
  		ResetExprContext(econtext);
diff --git a/src/backend/executor/instrument.c b/src/backend/executor/instrument.c
index d8d7039..d8ccaae 100644
*** a/src/backend/executor/instrument.c
--- b/src/backend/executor/instrument.c
*************** InstrEndLoop(Instrumentation *instr)
*** 86,91 ****
--- 86,92 ----
  	instr->startup += instr->firsttuple;
  	instr->total += totaltime;
  	instr->ntuples += instr->tuplecount;
+ 	instr->ntuples_disc += instr->tuplecount_disc;
  	instr->nloops += 1;
  
  	/* Reset for next cycle (if any) */
*************** InstrEndLoop(Instrumentation *instr)
*** 94,97 ****
--- 95,99 ----
  	INSTR_TIME_SET_ZERO(instr->counter);
  	instr->firsttuple = 0;
  	instr->tuplecount = 0;
+ 	instr->tuplecount_disc = 0;
  }
diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h
index 9846f6f..3b567ad 100644
*** a/src/include/executor/instrument.h
--- b/src/include/executor/instrument.h
*************** typedef struct Instrumentation
*** 24,39 ****
  	instr_time	counter;		/* Accumulated runtime for this node */
  	double		firsttuple;		/* Time for first tuple of this cycle */
  	double		tuplecount;		/* Tuples emitted so far this cycle */
  	/* Accumulated statistics across all completed cycles: */
  	double		startup;		/* Total startup time (in seconds) */
  	double		total;			/* Total total time (in seconds) */
  	double		ntuples;		/* Total tuples produced */
  	double		nloops;			/* # of run cycles for this node */
  } Instrumentation;
  
  extern Instrumentation *InstrAlloc(int n);
  extern void InstrStartNode(Instrumentation *instr);
! extern void InstrStopNode(Instrumentation *instr, double nTuples);
  extern void InstrEndLoop(Instrumentation *instr);
  
  #endif   /* INSTRUMENT_H */
--- 24,42 ----
  	instr_time	counter;		/* Accumulated runtime for this node */
  	double		firsttuple;		/* Time for first tuple of this cycle */
  	double		tuplecount;		/* Tuples emitted so far this cycle */
+ 	double		tuplecount_disc;/* Tuples emitted so far this cycle */
  	/* Accumulated statistics across all completed cycles: */
  	double		startup;		/* Total startup time (in seconds) */
  	double		total;			/* Total total time (in seconds) */
  	double		ntuples;		/* Total tuples produced */
+ 	double		ntuples_disc;	/* Total number of discarded tuples produced */
  	double		nloops;			/* # of run cycles for this node */
  } Instrumentation;
  
  extern Instrumentation *InstrAlloc(int n);
  extern void InstrStartNode(Instrumentation *instr);
! extern void InstrStopNode(Instrumentation *instr,
! 						  double nTuples);
  extern void InstrEndLoop(Instrumentation *instr);
  
  #endif   /* INSTRUMENT_H */
-- 
1.6.3.rc4.30.g7b9ea

