| 785 | } |
| 786 | |
| 787 | Status GroupingAggregator::BuildSpilledPartition(Partition** built_partition) { |
| 788 | DCHECK(!spilled_partitions_.empty()); |
| 789 | DCHECK(!is_streaming_preagg_); |
| 790 | // Leave the partition in 'spilled_partitions_' to be closed if we hit an error. |
| 791 | Partition* src_partition = spilled_partitions_.front(); |
| 792 | DCHECK(src_partition->is_spilled()); |
| 793 | |
| 794 | // Create a new hash partition from the rows of the spilled partition. This is simpler |
| 795 | // than trying to finish building a partially-built partition in place. We only |
| 796 | // initialise one hash partition that all rows in 'src_partition' will hash to. |
| 797 | RETURN_IF_ERROR(CreateHashPartitions(src_partition->level, src_partition->idx)); |
| 798 | Partition* dst_partition = hash_partitions_[src_partition->idx]; |
| 799 | DCHECK(dst_partition != nullptr); |
| 800 | |
| 801 | // Rebuild the hash table over spilled aggregate rows then start adding unaggregated |
| 802 | // rows to the hash table. It's possible the partition will spill at either stage. |
| 803 | // In that case we need to finish processing 'src_partition' so that all rows are |
| 804 | // appended to 'dst_partition'. |
| 805 | // TODO: if the partition spills again but the aggregation reduces the input |
| 806 | // significantly, we could do better here by keeping the incomplete hash table in |
| 807 | // memory and only spilling unaggregated rows that didn't fit in the hash table |
| 808 | // (somewhat similar to the passthrough pre-aggregation). |
| 809 | RETURN_IF_ERROR(ProcessStream<true>(src_partition->aggregated_row_stream.get(), |
| 810 | /* has_more_streams */ src_partition->unaggregated_row_stream->num_rows() > 0)); |
| 811 | RETURN_IF_ERROR(ProcessStream<false>(src_partition->unaggregated_row_stream.get(), |
| 812 | /* has_more_streams */ false)); |
| 813 | src_partition->Close(false); |
| 814 | spilled_partitions_.pop_front(); |
| 815 | hash_partitions_.clear(); |
| 816 | |
| 817 | if (dst_partition->is_spilled()) { |
| 818 | RETURN_IF_ERROR(PushSpilledPartition(dst_partition)); |
| 819 | *built_partition = nullptr; |
| 820 | // Spilled the partition - we should not be using any reservation except from |
| 821 | // 'serialize_stream_'. |
| 822 | DCHECK_EQ(serialize_stream_ != nullptr ? serialize_stream_->BytesPinned(false) : 0, |
| 823 | buffer_pool_client()->GetUsedReservation()) |
| 824 | << buffer_pool_client()->DebugString(); |
| 825 | } else { |
| 826 | *built_partition = dst_partition; |
| 827 | } |
| 828 | return Status::OK(); |
| 829 | } |
| 830 | |
| 831 | Status GroupingAggregator::RepartitionSpilledPartition() { |
| 832 | DCHECK(!spilled_partitions_.empty()); |
nothing calls this directly
no test coverage detected