blob: 87bff084e117bce38b1a221d9f9775a6e3efe924 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "paimon/utils/row_range_index.h"
#include <algorithm>
#include <utility>
namespace paimon {
RowRangeIndex::RowRangeIndex(std::vector<Range> ranges) : ranges_(std::move(ranges)) {
starts_.reserve(ranges_.size());
ends_.reserve(ranges_.size());
for (const auto& range : ranges_) {
starts_.push_back(range.from);
ends_.push_back(range.to);
}
}
Result<RowRangeIndex> RowRangeIndex::Create(const std::vector<Range>& ranges) {
if (ranges.empty()) {
return Status::Invalid("Ranges cannot be empty in RowRangeIndex");
}
return RowRangeIndex(Range::SortAndMergeOverlap(ranges, /*adjacent=*/true));
}
const std::vector<Range>& RowRangeIndex::Ranges() const {
return ranges_;
}
bool RowRangeIndex::Intersects(int64_t start, int64_t end) const {
int32_t candidate = LowerBound(start);
return candidate < static_cast<int32_t>(starts_.size()) && starts_[candidate] <= end;
}
std::vector<Range> RowRangeIndex::IntersectedRanges(int64_t start, int64_t end) const {
int32_t left = LowerBound(start);
if (left >= static_cast<int32_t>(ranges_.size())) {
return {};
}
int32_t right = LowerBound(end);
if (right >= static_cast<int32_t>(ranges_.size())) {
right = static_cast<int32_t>(ranges_.size()) - 1;
}
if (starts_[left] > end) {
return {};
}
std::vector<Range> expected;
// Add the first intersecting range, clipped to [start, end].
const Range& first_range = ranges_[left];
expected.emplace_back(std::max(start, first_range.from), std::min(end, first_range.to));
// Add all fully contained ranges between first and last.
for (int32_t i = left + 1; i < right; ++i) {
expected.push_back(ranges_[i]);
}
// Add the last intersecting range (if different from the first), clipped to [start, end].
if (right != left) {
const Range& last_range = ranges_[right];
if (last_range.from <= end) {
expected.emplace_back(std::max(start, last_range.from), std::min(end, last_range.to));
}
}
return expected;
}
int32_t RowRangeIndex::LowerBound(int64_t target) const {
int32_t left = 0;
auto right = static_cast<int32_t>(ends_.size());
while (left < right) {
int32_t mid = left + (right - left) / 2;
if (ends_[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
} // namespace paimon