void MergingSortedBlockInputStream::init(MutableColumns & merged_columns) { /// Read the first blocks, initialize the queue. if (first) { first = false; for (size_t i = 0; i < source_blocks.size(); ++i) { SharedBlockPtr & shared_block_ptr = source_blocks[i]; if (shared_block_ptr.get()) continue; shared_block_ptr = new detail::SharedBlock(children[i]->read()); const size_t rows = shared_block_ptr->rows(); if (rows == 0) continue; if (expected_block_size < rows) expected_block_size = std::min(rows, max_block_size); cursors[i] = SortCursorImpl(*shared_block_ptr, description, i); shared_block_ptr->all_columns = cursors[i].all_columns; shared_block_ptr->sort_columns = cursors[i].sort_columns; has_collation |= cursors[i].has_collation; } if (has_collation) initQueue(queue_with_collation); else initQueue(queue_without_collation); } /// Let's check that all source blocks have the same structure. for (const SharedBlockPtr & shared_block_ptr : source_blocks) { if (!*shared_block_ptr) continue; assertBlocksHaveEqualStructure(*shared_block_ptr, header, getName()); } merged_columns.resize(num_columns); for (size_t i = 0; i < num_columns; ++i) { merged_columns[i] = header.safeGetByPosition(i).column->cloneEmpty(); merged_columns[i]->reserve(expected_block_size); } }
void MergingSortedBlockInputStream::init(Block & merged_block, ColumnPlainPtrs & merged_columns) { /// Читаем первые блоки, инициализируем очередь. if (first) { first = false; size_t i = 0; for (auto it = source_blocks.begin(); it != source_blocks.end(); ++it, ++i) { SharedBlockPtr & shared_block_ptr = *it; if (shared_block_ptr.get()) continue; shared_block_ptr = new detail::SharedBlock(children[i]->read()); if (shared_block_ptr->rowsInFirstColumn() == 0) continue; if (!num_columns) num_columns = shared_block_ptr->columns(); cursors[i] = SortCursorImpl(*shared_block_ptr, description, i); has_collation |= cursors[i].has_collation; } if (has_collation) initQueue(queue_with_collation); else initQueue(queue); } /// Инициализируем результат. /// Клонируем структуру первого непустого блока источников. { auto it = source_blocks.cbegin(); for (; it != source_blocks.cend(); ++it) { const SharedBlockPtr & shared_block_ptr = *it; if (*shared_block_ptr) { merged_block = shared_block_ptr->cloneEmpty(); break; } } /// Если все входные блоки пустые. if (it == source_blocks.cend()) return; } /// Проверим, что у всех блоков-источников одинаковая структура. for (auto it = source_blocks.cbegin(); it != source_blocks.cend(); ++it) { const SharedBlockPtr & shared_block_ptr = *it; if (!*shared_block_ptr) continue; size_t src_columns = shared_block_ptr->columns(); size_t dst_columns = merged_block.columns(); if (src_columns != dst_columns) throw Exception("Merging blocks has different number of columns", ErrorCodes::NUMBER_OF_COLUMNS_DOESNT_MATCH); for (size_t i = 0; i < src_columns; ++i) if (shared_block_ptr->getByPosition(i).name != merged_block.getByPosition(i).name || shared_block_ptr->getByPosition(i).type->getName() != merged_block.getByPosition(i).type->getName() || shared_block_ptr->getByPosition(i).column->getName() != merged_block.getByPosition(i).column->getName()) throw Exception("Merging blocks has different names or types of columns", ErrorCodes::BLOCKS_HAS_DIFFERENT_STRUCTURE); } for (size_t i = 0; i < num_columns; ++i) merged_columns.emplace_back(merged_block.getByPosition(i).column.get()); }