| 654 | } |
| 655 | |
| 656 | Status GroupingAggregator::CreateHashPartitions(int level, int single_partition_idx) { |
| 657 | if (is_streaming_preagg_) DCHECK_EQ(level, 0); |
| 658 | if (UNLIKELY(level >= MAX_PARTITION_DEPTH)) { |
| 659 | return Status( |
| 660 | TErrorCode::PARTITIONED_AGG_MAX_PARTITION_DEPTH, id_, MAX_PARTITION_DEPTH); |
| 661 | } |
| 662 | ht_ctx_->set_level(level); |
| 663 | |
| 664 | DCHECK(hash_partitions_.empty()); |
| 665 | int num_partitions_created = 0; |
| 666 | for (int i = 0; i < PARTITION_FANOUT; ++i) { |
| 667 | hash_tbls_[i] = nullptr; |
| 668 | if (single_partition_idx == -1 || i == single_partition_idx) { |
| 669 | Partition* new_partition = partition_pool_->Add(new Partition(this, level, i)); |
| 670 | ++num_partitions_created; |
| 671 | hash_partitions_.push_back(new_partition); |
| 672 | RETURN_IF_ERROR(new_partition->InitStreams()); |
| 673 | } else { |
| 674 | hash_partitions_.push_back(nullptr); |
| 675 | } |
| 676 | } |
| 677 | // Now that all the streams are reserved (meaning we have enough memory to execute |
| 678 | // the algorithm), allocate the hash tables. These can fail and we can still continue. |
| 679 | for (int i = 0; i < PARTITION_FANOUT; ++i) { |
| 680 | Partition* partition = hash_partitions_[i]; |
| 681 | if (partition == nullptr) continue; |
| 682 | if (partition->aggregated_row_stream == nullptr) { |
| 683 | // Failed to create the aggregated row stream - cannot create a hash table. |
| 684 | // Just continue with a NULL hash table so rows will be passed through. |
| 685 | DCHECK(is_streaming_preagg_); |
| 686 | } else { |
| 687 | bool got_memory; |
| 688 | RETURN_IF_ERROR(partition->InitHashTable(&got_memory)); |
| 689 | // Spill the partition if we cannot create a hash table for a merge aggregation. |
| 690 | if (UNLIKELY(!got_memory)) { |
| 691 | DCHECK(!is_streaming_preagg_) << "Preagg reserves enough memory for hash tables"; |
| 692 | // If we're repartitioning, we will be writing aggregated rows first. |
| 693 | RETURN_IF_ERROR(partition->Spill(level > 0)); |
| 694 | } |
| 695 | } |
| 696 | hash_tbls_[i] = partition->hash_tbl.get(); |
| 697 | } |
| 698 | // In this case we did not have to repartition, so ensure that while building the hash |
| 699 | // table all rows will be inserted into the partition at 'single_partition_idx' in case |
| 700 | // a non deterministic grouping expression causes a row to hash to a different |
| 701 | // partition index. |
| 702 | if (single_partition_idx != -1) { |
| 703 | Partition* partition = hash_partitions_[single_partition_idx]; |
| 704 | for (int i = 0; i < PARTITION_FANOUT; ++i) { |
| 705 | hash_partitions_[i] = partition; |
| 706 | hash_tbls_[i] = partition->hash_tbl.get(); |
| 707 | } |
| 708 | } |
| 709 | |
| 710 | COUNTER_ADD(partitions_created_, num_partitions_created); |
| 711 | if (!is_streaming_preagg_) { |
| 712 | COUNTER_SET(max_partition_level_, level); |
| 713 | } |
nothing calls this directly
no test coverage detected