| 1989 | } |
| 1990 | |
| 1991 | static void |
| 1992 | ExecParallelHashJoinPartitionOuter(HashJoinState *hjstate) |
| 1993 | { |
| 1994 | PlanState *outerState = outerPlanState(hjstate); |
| 1995 | ExprContext *econtext = hjstate->js.ps.ps_ExprContext; |
| 1996 | HashJoinTable hashtable = hjstate->hj_HashTable; |
| 1997 | TupleTableSlot *slot; |
| 1998 | uint32 hashvalue; |
| 1999 | int i; |
| 2000 | HashState *hashState = (HashState *) innerPlanState(hjstate); |
| 2001 | |
| 2002 | Assert(hjstate->hj_FirstOuterTupleSlot == NULL); |
| 2003 | |
| 2004 | /* Execute outer plan, writing all tuples to shared tuplestores. */ |
| 2005 | for (;;) |
| 2006 | { |
| 2007 | slot = ExecProcNode(outerState); |
| 2008 | if (TupIsNull(slot)) |
| 2009 | break; |
| 2010 | econtext->ecxt_outertuple = slot; |
| 2011 | |
| 2012 | bool hashkeys_null = false; |
| 2013 | bool keep_nulls = HJ_FILL_OUTER(hjstate) || |
| 2014 | hjstate->hj_nonequijoin; |
| 2015 | if (ExecHashGetHashValue(hashState, hashtable, econtext, |
| 2016 | hjstate->hj_OuterHashKeys, |
| 2017 | true, /* outer tuple */ |
| 2018 | keep_nulls, |
| 2019 | &hashvalue, |
| 2020 | &hashkeys_null)) |
| 2021 | { |
| 2022 | int batchno; |
| 2023 | int bucketno; |
| 2024 | bool shouldFree; |
| 2025 | MinimalTuple mintup = ExecFetchSlotMinimalTuple(slot, &shouldFree); |
| 2026 | |
| 2027 | ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno, |
| 2028 | &batchno); |
| 2029 | sts_puttuple(hashtable->batches[batchno].outer_tuples, |
| 2030 | &hashvalue, mintup); |
| 2031 | |
| 2032 | if (shouldFree) |
| 2033 | heap_free_minimal_tuple(mintup); |
| 2034 | } |
| 2035 | CHECK_FOR_INTERRUPTS(); |
| 2036 | } |
| 2037 | |
| 2038 | /* Make sure all outer partitions are readable by any backend. */ |
| 2039 | for (i = 0; i < hashtable->nbatch; ++i) |
| 2040 | sts_end_write(hashtable->batches[i].outer_tuples); |
| 2041 | } |
| 2042 | |
| 2043 | void |
| 2044 | ExecHashJoinEstimate(HashJoinState *state, ParallelContext *pcxt) |
no test coverage detected