// Copyright 2024 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include namespace DB::DM { template ConcatSkippableBlockInputStream::ConcatSkippableBlockInputStream( SkippableBlockInputStreams && inputs_, std::vector && rows_, const ScanContextPtr & scan_context_) : rows(std::move(rows_)) , precede_stream_rows(0) , scan_context(scan_context_) , lac_bytes_collector(scan_context_ ? scan_context_->resource_group_name : "") { children.insert(children.end(), inputs_.begin(), inputs_.end()); current_stream = children.begin(); } template void ConcatSkippableBlockInputStream::appendChild(SkippableBlockInputStreamPtr child, size_t rows_) { children.emplace_back(std::move(child)); rows.push_back(rows_); current_stream = children.begin(); } template bool ConcatSkippableBlockInputStream::getSkippedRows(size_t & skip_rows) { skip_rows = 0; while (current_stream != children.end()) { auto * skippable_stream = dynamic_cast((*current_stream).get()); size_t skip; bool has_next_block = skippable_stream->getSkippedRows(skip); skip_rows += skip; if (has_next_block) { return true; } else { (*current_stream)->readSuffix(); precede_stream_rows += rows[current_stream - children.begin()]; ++current_stream; } } return false; } template size_t ConcatSkippableBlockInputStream::skipNextBlock() { while (current_stream != children.end()) { auto * skippable_stream = dynamic_cast((*current_stream).get()); size_t skipped_rows = skippable_stream->skipNextBlock(); if (skipped_rows > 0) { return skipped_rows; } else { (*current_stream)->readSuffix(); precede_stream_rows += rows[current_stream - children.begin()]; ++current_stream; } } return 0; } template Block ConcatSkippableBlockInputStream::readWithFilter(const IColumn::Filter & filter) { Block res; while (current_stream != children.end()) { auto * skippable_stream = dynamic_cast((*current_stream).get()); res = skippable_stream->readWithFilter(filter); if (res) { res.setStartOffset(res.startOffset() + precede_stream_rows); addReadBytes(res.bytes()); break; } else { (*current_stream)->readSuffix(); precede_stream_rows += rows[current_stream - children.begin()]; ++current_stream; } } return res; } template Block ConcatSkippableBlockInputStream::read() { Block res; while (current_stream != children.end()) { res = (*current_stream)->read(); if (res) { res.setStartOffset(res.startOffset() + precede_stream_rows); if constexpr (need_row_id) { res.setSegmentRowIdCol(createSegmentRowIdCol(res.startOffset(), res.rows())); } addReadBytes(res.bytes()); break; } else { (*current_stream)->readSuffix(); precede_stream_rows += rows[current_stream - children.begin()]; ++current_stream; } } return res; } template ColumnPtr ConcatSkippableBlockInputStream::createSegmentRowIdCol(UInt64 start, UInt64 limit) { auto seg_row_id_col = ColumnUInt32::create(); ColumnUInt32::Container & res = seg_row_id_col->getData(); res.resize(limit); for (UInt64 i = 0; i < limit; ++i) { res[i] = i + start; } return seg_row_id_col; } template void ConcatSkippableBlockInputStream::addReadBytes(UInt64 bytes) { if (likely(scan_context != nullptr)) { scan_context->user_read_bytes += bytes; if constexpr (!need_row_id) { lac_bytes_collector.collect(bytes); } } } template class ConcatSkippableBlockInputStream; template class ConcatSkippableBlockInputStream; } // namespace DB::DM