void AggregatingSortedBlockInputStream::merge(MutableColumns & merged_columns, std::priority_queue<SortCursor> & queue) { size_t merged_rows = 0; /// We take the rows in the correct order and put them in `merged_block`, while the rows are no more than `max_block_size` while (!queue.empty()) { SortCursor current = queue.top(); setPrimaryKeyRef(next_key, current); bool key_differs; if (current_key.empty()) /// The first key encountered. { setPrimaryKeyRef(current_key, current); key_differs = true; } else key_differs = next_key != current_key; /// if there are enough rows accumulated and the last one is calculated completely if (key_differs && merged_rows >= max_block_size) return; queue.pop(); if (key_differs) { current_key.swap(next_key); /// We will write the data for the group. We copy the values of ordinary columns. for (size_t i = 0, size = column_numbers_not_to_aggregate.size(); i < size; ++i) { size_t j = column_numbers_not_to_aggregate[i]; merged_columns[j]->insertFrom(*current->all_columns[j], current->pos); } /// Add the empty aggregation state to the aggregate columns. The state will be updated in the `addRow` function. for (auto & column_to_aggregate : columns_to_aggregate) column_to_aggregate->insertDefault(); ++merged_rows; } addRow(current); if (!current->isLast()) { current->next(); queue.push(current); } else { /// We fetch the next block from the appropriate source, if there is one. fetchNextBlock(current, queue); } } finished = true; }
void AggregatingSortedBlockInputStream::merge(ColumnPlainPtrs & merged_columns, std::priority_queue<TSortCursor> & queue) { size_t merged_rows = 0; /// Вынимаем строки в нужном порядке и кладём в merged_block, пока строк не больше max_block_size while (!queue.empty()) { TSortCursor current = queue.top(); setPrimaryKeyRef(next_key, current); bool key_differs; if (current_key.empty()) /// Первый встретившийся ключ. { current_key.columns.resize(description.size()); setPrimaryKeyRef(current_key, current); key_differs = true; } else key_differs = next_key != current_key; /// если накопилось достаточно строк и последняя посчитана полностью if (key_differs && merged_rows >= max_block_size) return; queue.pop(); if (key_differs) { current_key.swap(next_key); /// Запишем данные для очередной группы. Копируем значения обычных столбцов. for (size_t i = 0, size = column_numbers_not_to_aggregate.size(); i < size; ++i) { size_t j = column_numbers_not_to_aggregate[i]; merged_columns[j]->insertFrom(*current->all_columns[j], current->pos); } /// Добавляем в агрегатные столбцы пустое состояние агрегации. Состояние будет обновлено в функции addRow. for (auto & column_to_aggregate : columns_to_aggregate) column_to_aggregate->insertDefault(); ++merged_rows; } addRow(current); if (!current->isLast()) { current->next(); queue.push(current); } else { /// Достаём из соответствующего источника следующий блок, если есть. fetchNextBlock(current, queue); } } finished = true; }