|
19 | 19 |
|
20 | 20 | #include "paimon/common/global_index/offset_global_index_reader.h" |
21 | 21 |
|
| 22 | +#include <limits> |
22 | 23 | #include <utility> |
| 24 | +#include <vector> |
| 25 | + |
| 26 | +#include "paimon/global_index/bitmap_scored_global_index_result.h" |
| 27 | +#include "paimon/utils/roaring_bitmap64.h" |
23 | 28 |
|
24 | 29 | namespace paimon { |
| 30 | +namespace { |
| 31 | +std::shared_ptr<ScoredGlobalIndexResult> EmptyScoredResult() { |
| 32 | + return std::make_shared<BitmapScoredGlobalIndexResult>(RoaringBitmap64(), std::vector<float>()); |
| 33 | +} |
| 34 | +} // namespace |
| 35 | + |
| 36 | +OffsetGlobalIndexReader::OffsetGlobalIndexReader(std::shared_ptr<GlobalIndexReader>&& wrapped, |
| 37 | + int64_t offset, int64_t to) |
| 38 | + : OffsetGlobalIndexReader(std::move(wrapped), offset, to, |
| 39 | + /*skip_to=*/std::numeric_limits<int64_t>::min()) {} |
25 | 40 |
|
26 | 41 | OffsetGlobalIndexReader::OffsetGlobalIndexReader(std::shared_ptr<GlobalIndexReader>&& wrapped, |
27 | | - int64_t offset) |
28 | | - : wrapped_(std::move(wrapped)), offset_(offset) {} |
| 42 | + int64_t offset, int64_t to, int64_t skip_to) |
| 43 | + : wrapped_(std::move(wrapped)), offset_(offset), to_(to), skip_to_(skip_to) {} |
29 | 44 |
|
30 | 45 | Result<std::shared_ptr<GlobalIndexResult>> OffsetGlobalIndexReader::VisitIsNotNull() { |
31 | 46 | PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<GlobalIndexResult> result, wrapped_->VisitIsNotNull()); |
@@ -137,11 +152,34 @@ Result<std::shared_ptr<ScoredGlobalIndexResult>> OffsetGlobalIndexReader::VisitV |
137 | 152 |
|
138 | 153 | Result<std::shared_ptr<ScoredGlobalIndexResult>> OffsetGlobalIndexReader::VisitFullTextSearch( |
139 | 154 | const std::shared_ptr<FullTextSearch>& full_text_search) { |
140 | | - // Convert global include row ids to local row ids. The shard end is unknown here, so row ids |
141 | | - // past the shard are kept; they match no local row. |
142 | 155 | std::shared_ptr<FullTextSearch> local_search = full_text_search; |
143 | | - if (full_text_search && full_text_search->include_row_ids) { |
144 | | - local_search = full_text_search->OffsetRange(offset_, RoaringBitmap64::MAX_VALUE); |
| 156 | + if (full_text_search) { |
| 157 | + if (full_text_search->limit <= 0) { |
| 158 | + return Status::Invalid("full-text search requires a positive limit"); |
| 159 | + } |
| 160 | + // Rows up to `skip_to_` are ranked by a reader over an overlapping row range. |
| 161 | + if (skip_to_ >= to_) { |
| 162 | + return EmptyScoredResult(); |
| 163 | + } |
| 164 | + bool skips_rows = skip_to_ >= offset_; |
| 165 | + if (full_text_search->include_row_ids) { |
| 166 | + local_search = full_text_search->OffsetRange(offset_, to_); |
| 167 | + if (skips_rows) { |
| 168 | + local_search->include_row_ids->RemoveRange(0, skip_to_ - offset_ + 1); |
| 169 | + } |
| 170 | + if (local_search->include_row_ids->IsEmpty()) { |
| 171 | + return EmptyScoredResult(); |
| 172 | + } |
| 173 | + } else if (skips_rows) { |
| 174 | + // `local_to` may be the largest int64 value, so add it apart from the half-open range. |
| 175 | + int64_t local_to = to_ - offset_; |
| 176 | + RoaringBitmap64 local_row_ids; |
| 177 | + local_row_ids.AddRange(skip_to_ - offset_ + 1, local_to); |
| 178 | + local_row_ids.Add(local_to); |
| 179 | + local_search = std::make_shared<FullTextSearch>( |
| 180 | + full_text_search->field_name, full_text_search->query, full_text_search->limit, |
| 181 | + std::move(local_row_ids)); |
| 182 | + } |
145 | 183 | } |
146 | 184 | PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<ScoredGlobalIndexResult> result, |
147 | 185 | wrapped_->VisitFullTextSearch(local_search)); |
|
0 commit comments