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

Lines changed: 8 additions & 44 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy