* ExecHashJoinOuterGetTuple * * get the next outer tuple for a parallel oblivious hashjoin: either by * executing the outer plan node in the first pass, or from the temp * files for the hashjoin batches. * * Returns a null slot if no more outer tuples (within the current batch). * * On success, the tuple's hash value is stored at *hashvalue --- this is * either originally computed, or
| 1078 | * either originally computed, or re-read from the temp file. |
| 1079 | */ |
| 1080 | static TupleTableSlot * |
| 1081 | ExecHashJoinOuterGetTuple(PlanState *outerNode, |
| 1082 | HashJoinState *hjstate, |
| 1083 | uint32 *hashvalue) |
| 1084 | { |
| 1085 | HashJoinTable hashtable = hjstate->hj_HashTable; |
| 1086 | int curbatch = hashtable->curbatch; |
| 1087 | TupleTableSlot *slot; |
| 1088 | ExprContext *econtext; |
| 1089 | HashState *hashState = (HashState *) innerPlanState(hjstate); |
| 1090 | |
| 1091 | /* Read tuples from outer relation only if it's the first batch */ |
| 1092 | if (curbatch == 0) |
| 1093 | { |
| 1094 | /* |
| 1095 | * Check to see if first outer tuple was already fetched by |
| 1096 | * ExecHashJoin() and not used yet. |
| 1097 | */ |
| 1098 | slot = hjstate->hj_FirstOuterTupleSlot; |
| 1099 | if (!TupIsNull(slot)) |
| 1100 | hjstate->hj_FirstOuterTupleSlot = NULL; |
| 1101 | else |
| 1102 | slot = ExecProcNode(outerNode); |
| 1103 | |
| 1104 | while (!TupIsNull(slot)) |
| 1105 | { |
| 1106 | /* |
| 1107 | * We have to compute the tuple's hash value. |
| 1108 | */ |
| 1109 | econtext = hjstate->js.ps.ps_ExprContext; |
| 1110 | econtext->ecxt_outertuple = slot; |
| 1111 | |
| 1112 | bool hashkeys_null = false; |
| 1113 | bool keep_nulls = HJ_FILL_OUTER(hjstate) || |
| 1114 | hjstate->hj_nonequijoin; |
| 1115 | if (ExecHashGetHashValue(hashState, hashtable, econtext, |
| 1116 | hjstate->hj_OuterHashKeys, |
| 1117 | true, /* outer tuple */ |
| 1118 | keep_nulls, |
| 1119 | hashvalue, |
| 1120 | &hashkeys_null)) |
| 1121 | { |
| 1122 | /* remember outer relation is not empty for possible rescan */ |
| 1123 | hjstate->hj_OuterNotEmpty = true; |
| 1124 | |
| 1125 | return slot; |
| 1126 | } |
| 1127 | |
| 1128 | /* |
| 1129 | * That tuple couldn't match because of a NULL, so discard it and |
| 1130 | * continue with the next one. |
| 1131 | */ |
| 1132 | slot = ExecProcNode(outerNode); |
| 1133 | } |
| 1134 | |
| 1135 | #ifdef HJDEBUG |
| 1136 | elog(gp_workfile_caching_loglevel, "HashJoin built table with %.1f tuples for batch %d", hashtable->totalTuples, curbatch); |
| 1137 | #endif |
no test coverage detected