Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e990b9c

Browse files
committed
The original patch to avoid building a hash join's hashtable when the
outer relation is empty did not work, per test case from Patrick Welche. It tried to use nodeHashjoin.c's high-level mechanisms for fetching an outer-relation tuple, but that code expected the hash table to be filled already. As patched, the code failed in corner cases such as having no outer-relation tuples for the first hash batch. Revert and rewrite.
1 parent dd102d3 commit e990b9c

File tree

3 files changed

+94
-163
lines changed

3 files changed

+94
-163
lines changed

src/backend/executor/nodeHash.c

+8-44
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.94 2005/06/15 07:27:44 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.95 2005/09/25 19:37:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -37,22 +37,14 @@ static void ExecHashIncreaseNumBatches(HashJoinTable hashtable);
3737
/* ----------------------------------------------------------------
3838
* ExecHash
3939
*
40-
* produce the first tuple from our child node (and _only_ the
41-
* first tuple). This is of limited general use -- it does not
42-
* hash its output, and produces only a single tuple. It is
43-
* provided so that hash join can probe the inner hash input to
44-
* determine whether it is empty without needing to build the
45-
* entire hash table first, which is what MultiExecHash() would
46-
* do.
40+
* stub for pro forma compliance
4741
* ----------------------------------------------------------------
4842
*/
4943
TupleTableSlot *
5044
ExecHash(HashState *node)
5145
{
52-
if (TupIsNull(node->firstTuple))
53-
node->firstTuple = ExecProcNode(outerPlanState(node));
54-
55-
return node->firstTuple;
46+
elog(ERROR, "Hash node does not support ExecProcNode call convention");
47+
return NULL;
5648
}
5749

5850
/* ----------------------------------------------------------------
@@ -71,7 +63,6 @@ MultiExecHash(HashState *node)
7163
TupleTableSlot *slot;
7264
ExprContext *econtext;
7365
uint32 hashvalue;
74-
bool cleared_first_tuple = false;
7566

7667
/* must provide our own instrumentation support */
7768
if (node->ps.instrument)
@@ -94,19 +85,9 @@ MultiExecHash(HashState *node)
9485
*/
9586
for (;;)
9687
{
97-
/* use and clear the tuple produced by ExecHash(), if any */
98-
if (!TupIsNull(node->firstTuple))
99-
{
100-
slot = node->firstTuple;
101-
node->firstTuple = NULL;
102-
cleared_first_tuple = true;
103-
}
104-
else
105-
{
106-
slot = ExecProcNode(outerNode);
107-
if (TupIsNull(slot))
108-
break;
109-
}
88+
slot = ExecProcNode(outerNode);
89+
if (TupIsNull(slot))
90+
break;
11091
hashtable->totalTuples += 1;
11192
/* We have to compute the hash value */
11293
econtext->ecxt_innertuple = slot;
@@ -116,19 +97,7 @@ MultiExecHash(HashState *node)
11697

11798
/* must provide our own instrumentation support */
11899
if (node->ps.instrument)
119-
{
120-
/*
121-
* XXX: kludge -- if ExecHash() was invoked, we've already
122-
* included the tuple that it produced in the row output count
123-
* for this node, so subtract 1 from the # of hashed tuples.
124-
*/
125-
if (cleared_first_tuple)
126-
InstrStopNodeMulti(node->ps.instrument,
127-
hashtable->totalTuples - 1);
128-
else
129-
InstrStopNodeMulti(node->ps.instrument,
130-
hashtable->totalTuples);
131-
}
100+
InstrStopNodeMulti(node->ps.instrument, hashtable->totalTuples);
132101

133102
/*
134103
* We do not return the hash table directly because it's not a subtype
@@ -161,7 +130,6 @@ ExecInitHash(Hash *node, EState *estate)
161130
hashstate->ps.state = estate;
162131
hashstate->hashtable = NULL;
163132
hashstate->hashkeys = NIL; /* will be set by parent HashJoin */
164-
hashstate->firstTuple = NULL;
165133

166134
/*
167135
* Miscellaneous initialization
@@ -221,8 +189,6 @@ ExecEndHash(HashState *node)
221189
{
222190
PlanState *outerPlan;
223191

224-
node->firstTuple = NULL;
225-
226192
/*
227193
* free exprcontext
228194
*/
@@ -864,8 +830,6 @@ ExecHashTableReset(HashJoinTable hashtable)
864830
void
865831
ExecReScanHash(HashState *node, ExprContext *exprCtxt)
866832
{
867-
node->firstTuple = NULL;
868-
869833
/*
870834
* if chgParam of subnode is not null then plan will be re-scanned by
871835
* first ExecProcNode.

0 commit comments

Comments
 (0)