| 91 | |
| 92 | template <bool AGGREGATED_ROWS> |
| 93 | Status GroupingAggregator::ProcessRow( |
| 94 | TupleRow* __restrict__ row, HashTableCtx* __restrict__ ht_ctx, bool has_more_rows) { |
| 95 | HashTableCtx::ExprValuesCache* expr_vals_cache = ht_ctx->expr_values_cache(); |
| 96 | // Hoist lookups out of non-null branch to speed up non-null case. |
| 97 | const uint32_t hash = expr_vals_cache->CurExprValuesHash(); |
| 98 | const uint32_t partition_idx = hash >> (32 - NUM_PARTITIONING_BITS); |
| 99 | if (expr_vals_cache->IsRowNull()) return Status::OK(); |
| 100 | // To process this row, we first see if it can be aggregated or inserted into this |
| 101 | // partition's hash table. If we need to insert it and that fails, due to OOM, we |
| 102 | // spill the partition. The partition to spill is not necessarily dst_partition, |
| 103 | // so we can try again to insert the row. |
| 104 | HashTable* hash_tbl = GetHashTable(partition_idx); |
| 105 | Partition* dst_partition = hash_partitions_[partition_idx]; |
| 106 | DCHECK(dst_partition != nullptr); |
| 107 | DCHECK_EQ(dst_partition->is_spilled(), hash_tbl == nullptr); |
| 108 | if (hash_tbl == nullptr) { |
| 109 | // This partition is already spilled, just append the row. |
| 110 | return AppendSpilledRow<AGGREGATED_ROWS>(dst_partition, row); |
| 111 | } |
| 112 | |
| 113 | DCHECK(dst_partition->aggregated_row_stream->is_pinned()); |
| 114 | bool found; |
| 115 | // Find the appropriate bucket in the hash table. There will always be a free |
| 116 | // bucket because we checked the size above. |
| 117 | HashTable::Iterator it = |
| 118 | hash_tbl->FindBuildRowBucket<BucketType::MATCH_UNSET>(ht_ctx, &found); |
| 119 | DCHECK(!it.AtEnd()) << "Hash table had no free buckets"; |
| 120 | if (AGGREGATED_ROWS) { |
| 121 | // If the row is already an aggregate row, it cannot match anything in the |
| 122 | // hash table since we process the aggregate rows first. These rows should |
| 123 | // have been aggregated in the initial pass. |
| 124 | DCHECK(!found); |
| 125 | } else if (found) { |
| 126 | // Row is already in hash table. Do the aggregation and we're done. |
| 127 | UpdateTuple( |
| 128 | dst_partition->agg_fn_evals.data(), it.GetTuple<BucketType::MATCH_UNSET>(), row); |
| 129 | return Status::OK(); |
| 130 | } |
| 131 | |
| 132 | // If we are seeing this result row for the first time, we need to construct the |
| 133 | // result row and initialize it. |
| 134 | return AddIntermediateTuple<AGGREGATED_ROWS>(dst_partition, row, hash, it, |
| 135 | has_more_rows); |
| 136 | } |
| 137 | |
| 138 | template <bool AGGREGATED_ROWS> |
| 139 | Status GroupingAggregator::AddIntermediateTuple(Partition* __restrict__ partition, |
nothing calls this directly
no test coverage detected