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());
}