Recent changes to allow hash join to exit early given empty input from
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Nov 2005 17:14:23 +0000 (17:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Nov 2005 17:14:23 +0000 (17:14 +0000)
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.

src/backend/executor/nodeHashjoin.c

index 86c63da4f760c74e78e49c93b2fee914fce663c5..ee2809a8b45640a6921190ed9eb8856f85a3c080 100644 (file)
@@ -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)
-   {
-       /* okay to reuse the hash table; needn't rescan inner, either */
-   }
-   else
+   if (node->hj_HashTable != NULL)
    {
-       /* 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