mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Recent changes to allow hash join to exit early given empty input from
one child or the other had a problem: they did not leave the node in a state that ExecReScanHashJoin would understand. In particular it would tend to fail to reset the child plans when needed. Per report from Mario Weilguni.
This commit is contained in:
parent
d4fc4ac4c7
commit
b79cb1eea1
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.77 2005/11/22 18:17:10 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.78 2005/11/28 17:14:23 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -152,12 +152,7 @@ ExecHashJoin(HashJoinState *node)
|
||||
* outer join, we can quit without scanning the outer relation.
|
||||
*/
|
||||
if (hashtable->totalTuples == 0 && node->js.jointype != JOIN_LEFT)
|
||||
{
|
||||
ExecHashTableDestroy(hashtable);
|
||||
node->hj_HashTable = NULL;
|
||||
node->hj_FirstOuterTupleSlot = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* need to remember whether nbatch has increased since we began
|
||||
@ -487,7 +482,6 @@ ExecEndHashJoin(HashJoinState *node)
|
||||
{
|
||||
ExecHashTableDestroy(node->hj_HashTable);
|
||||
node->hj_HashTable = NULL;
|
||||
node->hj_FirstOuterTupleSlot = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -803,13 +797,6 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
|
||||
void
|
||||
ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
|
||||
{
|
||||
/*
|
||||
* If we haven't yet built the hash table then we can just return; nothing
|
||||
* done yet, so nothing to undo.
|
||||
*/
|
||||
if (node->hj_HashTable == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* In a multi-batch join, we currently have to do rescans the hard way,
|
||||
* primarily because batch temp files may have already been released. But
|
||||
@ -817,24 +804,26 @@ ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
|
||||
* inner subnode, then we can just re-use the existing hash table without
|
||||
* rebuilding it.
|
||||
*/
|
||||
if (node->hj_HashTable->nbatch == 1 &&
|
||||
((PlanState *) node)->righttree->chgParam == NULL)
|
||||
if (node->hj_HashTable != NULL)
|
||||
{
|
||||
/* okay to reuse the hash table; needn't rescan inner, either */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* must destroy and rebuild hash table */
|
||||
ExecHashTableDestroy(node->hj_HashTable);
|
||||
node->hj_HashTable = NULL;
|
||||
node->hj_FirstOuterTupleSlot = NULL;
|
||||
if (node->hj_HashTable->nbatch == 1 &&
|
||||
((PlanState *) node)->righttree->chgParam == NULL)
|
||||
{
|
||||
/* okay to reuse the hash table; needn't rescan inner, either */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* must destroy and rebuild hash table */
|
||||
ExecHashTableDestroy(node->hj_HashTable);
|
||||
node->hj_HashTable = NULL;
|
||||
|
||||
/*
|
||||
* if chgParam of subnode is not null then plan will be re-scanned by
|
||||
* first ExecProcNode.
|
||||
*/
|
||||
if (((PlanState *) node)->righttree->chgParam == NULL)
|
||||
ExecReScan(((PlanState *) node)->righttree, exprCtxt);
|
||||
/*
|
||||
* if chgParam of subnode is not null then plan will be re-scanned
|
||||
* by first ExecProcNode.
|
||||
*/
|
||||
if (((PlanState *) node)->righttree->chgParam == NULL)
|
||||
ExecReScan(((PlanState *) node)->righttree, exprCtxt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Always reset intra-tuple state */
|
||||
@ -846,6 +835,7 @@ ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
node->hj_NeedNewOuter = true;
|
||||
node->hj_MatchedOuter = false;
|
||||
node->hj_FirstOuterTupleSlot = NULL;
|
||||
|
||||
/*
|
||||
* if chgParam of subnode is not null then plan will be re-scanned by
|
||||
|
Loading…
Reference in New Issue
Block a user