88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.92 2005/03/31 02:02:52 neilc Exp $
11+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.93 2005/04/16 20:07:35 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
1515/*
1616 * INTERFACE ROUTINES
17- *ExecHash - generate an in-memory hash table of the relation
17+ *MultiExecHash - generate an in-memory hash table of the relation
1818 *ExecInitHash- initialize node and subnodes
1919 *ExecEndHash- shutdown node and subnodes
2020 */
2121#include "postgres.h"
2222
2323#include "executor/execdebug.h"
2424#include "executor/hashjoin.h"
25+ #include "executor/instrument.h"
2526#include "executor/nodeHash.h"
2627#include "executor/nodeHashjoin.h"
2728#include "miscadmin.h"
@@ -36,12 +37,25 @@ static void ExecHashIncreaseNumBatches(HashJoinTable hashtable);
3637/* ----------------------------------------------------------------
3738 *ExecHash
3839 *
39- *build hash table for hashjoin, doing partitioning if more
40- *than one batch is required.
40+ *stub for pro forma compliance
4141 * ----------------------------------------------------------------
4242 */
4343TupleTableSlot *
4444ExecHash (HashState * node )
45+ {
46+ elog (ERROR ,"Hash node does not support ExecProcNode call convention" );
47+ return NULL ;
48+ }
49+
50+ /* ----------------------------------------------------------------
51+ *MultiExecHash
52+ *
53+ *build hash table for hashjoin, doing partitioning if more
54+ *than one batch is required.
55+ * ----------------------------------------------------------------
56+ */
57+ Node *
58+ MultiExecHash (HashState * node )
4559{
4660PlanState * outerNode ;
4761List * hashkeys ;
@@ -50,6 +64,10 @@ ExecHash(HashState *node)
5064ExprContext * econtext ;
5165uint32 hashvalue ;
5266
67+ /* must provide our own instrumentation support */
68+ if (node -> ps .instrument )
69+ InstrStartNode (node -> ps .instrument );
70+
5371/*
5472 * get state info from node
5573 */
@@ -70,14 +88,24 @@ ExecHash(HashState *node)
7088slot = ExecProcNode (outerNode );
7189if (TupIsNull (slot ))
7290break ;
73- hashtable -> hashNonEmpty = true ;
91+ hashtable -> totalTuples += 1 ;
7492/* We have to compute the hash value */
7593econtext -> ecxt_innertuple = slot ;
7694hashvalue = ExecHashGetHashValue (hashtable ,econtext ,hashkeys );
7795ExecHashTableInsert (hashtable ,ExecFetchSlotTuple (slot ),hashvalue );
7896}
7997
80- /* We needn't return a tuple slot or anything else */
98+ /* must provide our own instrumentation support */
99+ if (node -> ps .instrument )
100+ InstrStopNodeMulti (node -> ps .instrument ,hashtable -> totalTuples );
101+
102+ /*
103+ * We do not return the hash table directly because it's not a subtype
104+ * of Node, and so would violate the MultiExecProcNode API. Instead,
105+ * our parent Hashjoin node is expected to know how to fish it out
106+ * of our node state. Ugly but not really worth cleaning up, since
107+ * Hashjoin knows quite a bit more about Hash besides that.
108+ */
81109return NULL ;
82110}
83111
@@ -220,7 +248,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
220248hashtable -> nbatch_original = nbatch ;
221249hashtable -> nbatch_outstart = nbatch ;
222250hashtable -> growEnabled = true;
223- hashtable -> hashNonEmpty = false ;
251+ hashtable -> totalTuples = 0 ;
224252hashtable -> innerBatchFile = NULL ;
225253hashtable -> outerBatchFile = NULL ;
226254hashtable -> spaceUsed = 0 ;