#include #include namespace DB { LimitBlockInputStream::LimitBlockInputStream(BlockInputStreamPtr input_, size_t limit_, size_t offset_, bool always_read_till_end_) : limit(limit_), offset(offset_), always_read_till_end(always_read_till_end_) { children.push_back(input_); } Block LimitBlockInputStream::readImpl() { Block res; size_t rows = 0; /// pos - сколько строк было прочитано, включая последний прочитанный блок if (pos >= offset + limit) { if (!always_read_till_end) return res; else { while (children.back()->read()) ; return res; } } do { res = children.back()->read(); if (!res) return res; rows = res.rows(); pos += rows; } while (pos <= offset); /// отдать целый блок if (pos >= offset + rows && pos <= offset + limit) return res; /// отдать кусок блока size_t start = std::max( static_cast(0), static_cast(offset) - static_cast(pos) + static_cast(rows)); size_t length = std::min( static_cast(limit), std::min( static_cast(pos) - static_cast(offset), static_cast(limit) + static_cast(offset) - static_cast(pos) + static_cast(rows))); for (size_t i = 0; i < res.columns(); ++i) res.safeGetByPosition(i).column = res.safeGetByPosition(i).column->cut(start, length); return res; } }