]> granicus.if.org Git - postgresql/blobdiff - src/backend/executor/nodeHashjoin.c
Make some small planner API cleanups.
[postgresql] / src / backend / executor / nodeHashjoin.c
index 8f2b634b124ad7ad5fcacd14ad6b4c10cb1f13d9..209870886400645312e74c33ae6dbecb5149a3bb 100644 (file)
@@ -3,7 +3,7 @@
  * nodeHashjoin.c
  *       Routines to handle hash join nodes
  *
- * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
@@ -161,8 +161,7 @@ static void ExecParallelHashJoinPartitionOuter(HashJoinState *node);
  *                       the other one is "outer".
  * ----------------------------------------------------------------
  */
-pg_attribute_always_inline
-static inline TupleTableSlot *
+static pg_attribute_always_inline TupleTableSlot *
 ExecHashJoinImpl(PlanState *pstate, bool parallel)
 {
        HashJoinState *node = castNode(HashJoinState, pstate);
@@ -390,16 +389,22 @@ ExecHashJoinImpl(PlanState *pstate, bool parallel)
                                if (batchno != hashtable->curbatch &&
                                        node->hj_CurSkewBucketNo == INVALID_SKEW_BUCKET_NO)
                                {
+                                       bool            shouldFree;
+                                       MinimalTuple mintuple = ExecFetchSlotMinimalTuple(outerTupleSlot,
+                                                                                                                                         &shouldFree);
+
                                        /*
                                         * Need to postpone this outer tuple to a later batch.
                                         * Save it in the corresponding outer-batch file.
                                         */
                                        Assert(parallel_state == NULL);
                                        Assert(batchno > hashtable->curbatch);
-                                       ExecHashJoinSaveTuple(ExecFetchSlotMinimalTuple(outerTupleSlot),
-                                                                                 hashvalue,
+                                       ExecHashJoinSaveTuple(mintuple, hashvalue,
                                                                                  &hashtable->outerBatchFile[batchno]);
 
+                                       if (shouldFree)
+                                               heap_free_minimal_tuple(mintuple);
+
                                        /* Loop around, staying in HJ_NEED_NEW_OUTER state */
                                        continue;
                                }
@@ -596,8 +601,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
        Hash       *hashNode;
        List       *lclauses;
        List       *rclauses;
+       List       *rhclauses;
        List       *hoperators;
+       TupleDesc       outerDesc,
+                               innerDesc;
        ListCell   *l;
+       const TupleTableSlotOps *ops;
 
        /* check for unsupported flags */
        Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -615,6 +624,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
         * managed to launch a parallel query.
         */
        hjstate->js.ps.ExecProcNode = ExecHashJoin;
+       hjstate->js.jointype = node->join.jointype;
 
        /*
         * Miscellaneous initialization
@@ -623,17 +633,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
         */
        ExecAssignExprContext(estate, &hjstate->js.ps);
 
-       /*
-        * initialize child expressions
-        */
-       hjstate->js.ps.qual =
-               ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
-       hjstate->js.jointype = node->join.jointype;
-       hjstate->js.joinqual =
-               ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
-       hjstate->hashclauses =
-               ExecInitQual(node->hashclauses, (PlanState *) hjstate);
-
        /*
         * initialize child nodes
         *
@@ -645,13 +644,22 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
        hashNode = (Hash *) innerPlan(node);
 
        outerPlanState(hjstate) = ExecInitNode(outerNode, estate, eflags);
+       outerDesc = ExecGetResultType(outerPlanState(hjstate));
        innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate, eflags);
+       innerDesc = ExecGetResultType(innerPlanState(hjstate));
+
+       /*
+        * Initialize result slot, type and projection.
+        */
+       ExecInitResultTupleSlotTL(&hjstate->js.ps, &TTSOpsVirtual);
+       ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
 
        /*
         * tuple table initialization
         */
-       ExecInitResultTupleSlot(estate, &hjstate->js.ps);
-       hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
+       ops = ExecGetResultSlotOps(outerPlanState(hjstate), NULL);
+       hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
+                                                                                                               ops);
 
        /*
         * detect whether we need only consider the first matching inner tuple
@@ -668,21 +676,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
                case JOIN_LEFT:
                case JOIN_ANTI:
                        hjstate->hj_NullInnerTupleSlot =
-                               ExecInitNullTupleSlot(estate,
-                                                                         ExecGetResultType(innerPlanState(hjstate)));
+                               ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
                        break;
                case JOIN_RIGHT:
                        hjstate->hj_NullOuterTupleSlot =
-                               ExecInitNullTupleSlot(estate,
-                                                                         ExecGetResultType(outerPlanState(hjstate)));
+                               ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
                        break;
                case JOIN_FULL:
                        hjstate->hj_NullOuterTupleSlot =
-                               ExecInitNullTupleSlot(estate,
-                                                                         ExecGetResultType(outerPlanState(hjstate)));
+                               ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
                        hjstate->hj_NullInnerTupleSlot =
-                               ExecInitNullTupleSlot(estate,
-                                                                         ExecGetResultType(innerPlanState(hjstate)));
+                               ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
                        break;
                default:
                        elog(ERROR, "unrecognized join type: %d",
@@ -704,13 +708,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
        }
 
        /*
-        * initialize tuple type and projection info
+        * initialize child expressions
         */
-       ExecAssignResultTypeFromTL(&hjstate->js.ps);
-       ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
-
-       ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
-                                                 ExecGetResultType(outerPlanState(hjstate)));
+       hjstate->js.ps.qual =
+               ExecInitQual(node->join.plan.qual, (PlanState *) hjstate);
+       hjstate->js.joinqual =
+               ExecInitQual(node->join.joinqual, (PlanState *) hjstate);
+       hjstate->hashclauses =
+               ExecInitQual(node->hashclauses, (PlanState *) hjstate);
 
        /*
         * initialize hash-specific info
@@ -731,6 +736,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
         */
        lclauses = NIL;
        rclauses = NIL;
+       rhclauses = NIL;
        hoperators = NIL;
        foreach(l, node->hashclauses)
        {
@@ -740,13 +746,15 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
                                                                                                  (PlanState *) hjstate));
                rclauses = lappend(rclauses, ExecInitExpr(lsecond(hclause->args),
                                                                                                  (PlanState *) hjstate));
+               rhclauses = lappend(rhclauses, ExecInitExpr(lsecond(hclause->args),
+                                                                                                  innerPlanState(hjstate)));
                hoperators = lappend_oid(hoperators, hclause->opno);
        }
        hjstate->hj_OuterHashKeys = lclauses;
        hjstate->hj_InnerHashKeys = rclauses;
        hjstate->hj_HashOperators = hoperators;
        /* child Hash node needs to evaluate inner hash keys, too */
-       ((HashState *) innerPlanState(hjstate))->hashkeys = rclauses;
+       ((HashState *) innerPlanState(hjstate))->hashkeys = rhclauses;
 
        hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
        hjstate->hj_MatchedOuter = false;
@@ -923,9 +931,10 @@ ExecParallelHashJoinOuterGetTuple(PlanState *outerNode,
                                                                           hashvalue);
                if (tuple != NULL)
                {
-                       slot = ExecStoreMinimalTuple(tuple,
-                                                                                hjstate->hj_OuterTupleSlot,
-                                                                                false);
+                       ExecForceStoreMinimalTuple(tuple,
+                                                                          hjstate->hj_OuterTupleSlot,
+                                                                          false);
+                       slot = hjstate->hj_OuterTupleSlot;
                        return slot;
                }
                else
@@ -1152,9 +1161,10 @@ ExecParallelHashJoinNewBatch(HashJoinState *hjstate)
                                        while ((tuple = sts_parallel_scan_next(inner_tuples,
                                                                                                                   &hashvalue)))
                                        {
-                                               slot = ExecStoreMinimalTuple(tuple,
-                                                                                                        hjstate->hj_HashTupleSlot,
-                                                                                                        false);
+                                               ExecForceStoreMinimalTuple(tuple,
+                                                                                                  hjstate->hj_HashTupleSlot,
+                                                                                                  false);
+                                               slot = hjstate->hj_HashTupleSlot;
                                                ExecParallelHashTableInsertCurrentBatch(hashtable, slot,
                                                                                                                                hashvalue);
                                        }
@@ -1288,7 +1298,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
                ereport(ERROR,
                                (errcode_for_file_access(),
                                 errmsg("could not read from hash-join temporary file: %m")));
-       return ExecStoreMinimalTuple(tuple, tupleSlot, true);
+       ExecForceStoreMinimalTuple(tuple, tupleSlot, true);
+       return tupleSlot;
 }
 
 
@@ -1400,16 +1411,21 @@ ExecParallelHashJoinPartitionOuter(HashJoinState *hjstate)
                if (ExecHashGetHashValue(hashtable, econtext,
                                                                 hjstate->hj_OuterHashKeys,
                                                                 true,  /* outer tuple */
-                                                                false, /* outer join, currently unsupported */
+                                                                HJ_FILL_OUTER(hjstate),
                                                                 &hashvalue))
                {
                        int                     batchno;
                        int                     bucketno;
+                       bool            shouldFree;
+                       MinimalTuple mintup = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 
                        ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno,
                                                                          &batchno);
                        sts_puttuple(hashtable->batches[batchno].outer_tuples,
-                                                &hashvalue, ExecFetchSlotMinimalTuple(slot));
+                                                &hashvalue, mintup);
+
+                       if (shouldFree)
+                               heap_free_minimal_tuple(mintup);
                }
                CHECK_FOR_INTERRUPTS();
        }