* ExecScanHashTableForUnmatched * scan the hash table for unmatched inner tuples * * On success, the inner tuple is stored into hjstate->hj_CurTuple and * econtext->ecxt_innertuple, using hjstate->hj_HashTupleSlot as the slot * for the latter. */
| 2397 | * for the latter. |
| 2398 | */ |
| 2399 | bool |
| 2400 | ExecScanHashTableForUnmatched(HashJoinState *hjstate, ExprContext *econtext) |
| 2401 | { |
| 2402 | HashJoinTable hashtable = hjstate->hj_HashTable; |
| 2403 | HashJoinTuple hashTuple = hjstate->hj_CurTuple; |
| 2404 | |
| 2405 | for (;;) |
| 2406 | { |
| 2407 | /* |
| 2408 | * hj_CurTuple is the address of the tuple last returned from the |
| 2409 | * current bucket, or NULL if it's time to start scanning a new |
| 2410 | * bucket. |
| 2411 | */ |
| 2412 | if (hashTuple != NULL) |
| 2413 | hashTuple = hashTuple->next.unshared; |
| 2414 | else if (hjstate->hj_CurBucketNo < hashtable->nbuckets) |
| 2415 | { |
| 2416 | hashTuple = hashtable->buckets.unshared[hjstate->hj_CurBucketNo]; |
| 2417 | hjstate->hj_CurBucketNo++; |
| 2418 | } |
| 2419 | else if (hjstate->hj_CurSkewBucketNo < hashtable->nSkewBuckets) |
| 2420 | { |
| 2421 | int j = hashtable->skewBucketNums[hjstate->hj_CurSkewBucketNo]; |
| 2422 | |
| 2423 | hashTuple = hashtable->skewBucket[j]->tuples; |
| 2424 | hjstate->hj_CurSkewBucketNo++; |
| 2425 | } |
| 2426 | else |
| 2427 | break; /* finished all buckets */ |
| 2428 | |
| 2429 | while (hashTuple != NULL) |
| 2430 | { |
| 2431 | if (!HeapTupleHeaderHasMatch(HJTUPLE_MINTUPLE(hashTuple))) |
| 2432 | { |
| 2433 | TupleTableSlot *inntuple; |
| 2434 | |
| 2435 | /* insert hashtable's tuple into exec slot */ |
| 2436 | inntuple = ExecStoreMinimalTuple(HJTUPLE_MINTUPLE(hashTuple), |
| 2437 | hjstate->hj_HashTupleSlot, |
| 2438 | false); /* do not pfree */ |
| 2439 | econtext->ecxt_innertuple = inntuple; |
| 2440 | |
| 2441 | /* |
| 2442 | * Reset temp memory each time; although this function doesn't |
| 2443 | * do any qual eval, the caller will, so let's keep it |
| 2444 | * parallel to ExecScanHashBucket. |
| 2445 | */ |
| 2446 | ResetExprContext(econtext); |
| 2447 | |
| 2448 | hjstate->hj_CurTuple = hashTuple; |
| 2449 | return true; |
| 2450 | } |
| 2451 | |
| 2452 | hashTuple = hashTuple->next.unshared; |
| 2453 | } |
| 2454 | |
| 2455 | /* allow this loop to be cancellable */ |
| 2456 | CHECK_FOR_INTERRUPTS(); |
no test coverage detected