* hashagg_spill_tuple * * No room for new groups in the hash table. Save for later in the appropriate * partition. */
| 3243 | * partition. |
| 3244 | */ |
| 3245 | static Size |
| 3246 | hashagg_spill_tuple(AggState *aggstate, HashAggSpill *spill, |
| 3247 | TupleTableSlot *inputslot, uint32 hash) |
| 3248 | { |
| 3249 | LogicalTapeSet *tapeset = spill->tapeset; |
| 3250 | TupleTableSlot *spillslot; |
| 3251 | int partition; |
| 3252 | MinimalTuple tuple; |
| 3253 | int tapenum; |
| 3254 | int total_written = 0; |
| 3255 | bool shouldFree; |
| 3256 | |
| 3257 | Assert(spill->partitions != NULL); |
| 3258 | |
| 3259 | /* spill only attributes that we actually need */ |
| 3260 | if (!aggstate->all_cols_needed) |
| 3261 | { |
| 3262 | spillslot = aggstate->hash_spill_wslot; |
| 3263 | slot_getsomeattrs(inputslot, aggstate->max_colno_needed); |
| 3264 | ExecClearTuple(spillslot); |
| 3265 | for (int i = 0; i < spillslot->tts_tupleDescriptor->natts; i++) |
| 3266 | { |
| 3267 | if (bms_is_member(i + 1, aggstate->colnos_needed)) |
| 3268 | { |
| 3269 | spillslot->tts_values[i] = inputslot->tts_values[i]; |
| 3270 | spillslot->tts_isnull[i] = inputslot->tts_isnull[i]; |
| 3271 | } |
| 3272 | else |
| 3273 | spillslot->tts_isnull[i] = true; |
| 3274 | } |
| 3275 | ExecStoreVirtualTuple(spillslot); |
| 3276 | } |
| 3277 | else |
| 3278 | spillslot = inputslot; |
| 3279 | |
| 3280 | tuple = ExecFetchSlotMinimalTuple(spillslot, &shouldFree); |
| 3281 | |
| 3282 | partition = (hash & spill->mask) >> spill->shift; |
| 3283 | spill->ntuples[partition]++; |
| 3284 | |
| 3285 | /* |
| 3286 | * All hash values destined for a given partition have some bits in |
| 3287 | * common, which causes bad HLL cardinality estimates. Hash the hash to |
| 3288 | * get a more uniform distribution. |
| 3289 | */ |
| 3290 | addHyperLogLog(&spill->hll_card[partition], hash_bytes_uint32(hash)); |
| 3291 | |
| 3292 | tapenum = spill->partitions[partition]; |
| 3293 | |
| 3294 | LogicalTapeWrite(tapeset, tapenum, (void *) &hash, sizeof(uint32)); |
| 3295 | total_written += sizeof(uint32); |
| 3296 | |
| 3297 | LogicalTapeWrite(tapeset, tapenum, (void *) tuple, tuple->t_len); |
| 3298 | total_written += tuple->t_len; |
| 3299 | |
| 3300 | if (shouldFree) |
| 3301 | pfree(tuple); |
| 3302 |
no test coverage detected