]> granicus.if.org Git - postgresql/commitdiff
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