* ExecHashTableInsert * insert a tuple into the hash table depending on the hash value * it may just go to a temp file for later batches * * Note: the passed TupleTableSlot may contain a regular, minimal, or virtual * tuple; the minimal case in particular is certain to happen while reloading * tuples from batch files. We could save some cycles in the regular-tuple * case by not forcing t
| 1874 | * was pushed to a temp file. |
| 1875 | */ |
| 1876 | bool |
| 1877 | ExecHashTableInsert(HashState *hashState, HashJoinTable hashtable, |
| 1878 | TupleTableSlot *slot, |
| 1879 | uint32 hashvalue) |
| 1880 | { |
| 1881 | bool shouldFree; |
| 1882 | MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree); |
| 1883 | int bucketno; |
| 1884 | int batchno; |
| 1885 | PlanState *ps = &hashState->ps; |
| 1886 | |
| 1887 | ExecHashGetBucketAndBatch(hashtable, hashvalue, |
| 1888 | &bucketno, &batchno); |
| 1889 | |
| 1890 | /* |
| 1891 | * decide whether to put the tuple in the hash table or a temp file |
| 1892 | */ |
| 1893 | if (batchno == hashtable->curbatch) |
| 1894 | { |
| 1895 | /* |
| 1896 | * put the tuple in hash table |
| 1897 | */ |
| 1898 | HashJoinTuple hashTuple; |
| 1899 | int hashTupleSize; |
| 1900 | double ntuples = (hashtable->totalTuples - hashtable->skewTuples); |
| 1901 | |
| 1902 | /* Create the HashJoinTuple */ |
| 1903 | hashTupleSize = HJTUPLE_OVERHEAD + tuple->t_len; |
| 1904 | hashTuple = (HashJoinTuple) dense_alloc(hashtable, hashTupleSize); |
| 1905 | |
| 1906 | hashTuple->hashvalue = hashvalue; |
| 1907 | memcpy(HJTUPLE_MINTUPLE(hashTuple), tuple, tuple->t_len); |
| 1908 | |
| 1909 | /* |
| 1910 | * We always reset the tuple-matched flag on insertion. This is okay |
| 1911 | * even when reloading a tuple from a batch file, since the tuple |
| 1912 | * could not possibly have been matched to an outer tuple before it |
| 1913 | * went into the batch file. |
| 1914 | */ |
| 1915 | HeapTupleHeaderClearMatch(HJTUPLE_MINTUPLE(hashTuple)); |
| 1916 | |
| 1917 | /* Push it onto the front of the bucket's list */ |
| 1918 | hashTuple->next.unshared = hashtable->buckets.unshared[bucketno]; |
| 1919 | hashtable->buckets.unshared[bucketno] = hashTuple; |
| 1920 | |
| 1921 | /* |
| 1922 | * Increase the (optimal) number of buckets if we just exceeded the |
| 1923 | * NTUP_PER_BUCKET threshold, but only when there's still a single |
| 1924 | * batch. |
| 1925 | */ |
| 1926 | if (hashtable->nbatch == 1 && |
| 1927 | ntuples > (hashtable->nbuckets_optimal * gp_hashjoin_tuples_per_bucket)) |
| 1928 | { |
| 1929 | /* Guard against integer overflow and alloc size overflow */ |
| 1930 | if (hashtable->nbuckets_optimal <= INT_MAX / 2 && |
| 1931 | hashtable->nbuckets_optimal * 2 <= MaxAllocSize / sizeof(HashJoinTuple)) |
| 1932 | { |
| 1933 | hashtable->nbuckets_optimal *= 2; |
no test coverage detected