blob: d2d755a8ce57b9f23dd5e8e3533839c2c4f0eb2d [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 "paimon/testing/utils/testharness.h"
namespace paimon::test {
// ======================== Create ========================
TEST(RowRangeIndexTest, CreateWithEmptyRangesReturnsEmptyIndex) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({}));
ASSERT_TRUE(index.Ranges().empty());
}
TEST(RowRangeIndexTest, CreateWithSingleRange) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_EQ(index.Ranges().size(), 1);
ASSERT_EQ(index.Ranges()[0], Range(10, 20));
}
TEST(RowRangeIndexTest, CreateSortsAndMergesOverlappingRanges) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(20, 30), Range(0, 10), Range(5, 15)}));
std::vector<Range> expected = {Range(0, 15), Range(20, 30)};
ASSERT_EQ(index.Ranges(), expected);
}
TEST(RowRangeIndexTest, CreateMergesAdjacentRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(11, 20)}));
std::vector<Range> expected = {Range(0, 20)};
ASSERT_EQ(index.Ranges(), expected);
}
TEST(RowRangeIndexTest, CreateMergesDuplicateRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(0, 10)}));
std::vector<Range> expected = {Range(0, 10)};
ASSERT_EQ(index.Ranges(), expected);
}
TEST(RowRangeIndexTest, CreateWithMultipleDisjointRanges) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 5), Range(10, 15), Range(20, 25)}));
std::vector<Range> expected = {Range(0, 5), Range(10, 15), Range(20, 25)};
ASSERT_EQ(index.Ranges(), expected);
}
// ======================== Ranges ========================
TEST(RowRangeIndexTest, RangesReturnsUnmodifiableReference) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30)}));
const auto& ranges1 = index.Ranges();
const auto& ranges2 = index.Ranges();
ASSERT_EQ(&ranges1, &ranges2);
}
// ======================== Intersects ========================
TEST(RowRangeIndexTest, IntersectsExactMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(10, 20));
}
TEST(RowRangeIndexTest, IntersectsPartialOverlapFromLeft) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(5, 15));
}
TEST(RowRangeIndexTest, IntersectsPartialOverlapFromRight) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(15, 25));
}
TEST(RowRangeIndexTest, IntersectsContainedRange) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(12, 18));
}
TEST(RowRangeIndexTest, IntersectsContainingRange) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(0, 30));
}
TEST(RowRangeIndexTest, IntersectsTouchingLeftBoundary) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(5, 10));
}
TEST(RowRangeIndexTest, IntersectsTouchingRightBoundary) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Intersects(20, 25));
}
TEST(RowRangeIndexTest, IntersectsNoOverlapBefore) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_FALSE(index.Intersects(0, 9));
}
TEST(RowRangeIndexTest, IntersectsNoOverlapAfter) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_FALSE(index.Intersects(21, 30));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesHitsFirst) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
ASSERT_TRUE(index.Intersects(5, 8));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesHitsMiddle) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
ASSERT_TRUE(index.Intersects(22, 28));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesHitsLast) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
ASSERT_TRUE(index.Intersects(42, 48));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesSpansGap) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30)}));
ASSERT_TRUE(index.Intersects(8, 22));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesFallsInGap) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30)}));
ASSERT_FALSE(index.Intersects(11, 19));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesBeforeAll) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20), Range(30, 40)}));
ASSERT_FALSE(index.Intersects(0, 5));
}
TEST(RowRangeIndexTest, IntersectsMultipleRangesAfterAll) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20), Range(30, 40)}));
ASSERT_FALSE(index.Intersects(50, 60));
}
TEST(RowRangeIndexTest, IntersectsSinglePointMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 10)}));
ASSERT_TRUE(index.Intersects(10, 10));
}
TEST(RowRangeIndexTest, IntersectsSinglePointNoMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 10)}));
ASSERT_FALSE(index.Intersects(11, 11));
}
// ======================== Contains ========================
TEST(RowRangeIndexTest, ContainsAndContainsExactlyExactRange) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20), Range(30, 40)}));
Range query(10, 20);
ASSERT_TRUE(index.Contains(query));
ASSERT_TRUE(index.ContainsExactly(query));
}
TEST(RowRangeIndexTest, ContainsAndContainsExactlyBoundarySubRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_TRUE(index.Contains(Range(10, 19)));
ASSERT_FALSE(index.ContainsExactly(Range(10, 19)));
ASSERT_TRUE(index.Contains(Range(11, 20)));
ASSERT_FALSE(index.ContainsExactly(Range(11, 20)));
}
TEST(RowRangeIndexTest, ContainsAndContainsExactlyOutOfBoundaryRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
ASSERT_FALSE(index.Contains(Range(9, 20)));
ASSERT_FALSE(index.ContainsExactly(Range(9, 20)));
ASSERT_FALSE(index.Contains(Range(10, 21)));
ASSERT_FALSE(index.ContainsExactly(Range(10, 21)));
}
TEST(RowRangeIndexTest, ContainsAndContainsExactlyRangeAcrossTwoDisjointRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(11, 20)}, false));
ASSERT_FALSE(index.Contains(Range(10, 11)));
ASSERT_FALSE(index.ContainsExactly(Range(10, 11)));
ASSERT_FALSE(index.ContainsExactly(Range(0, 20)));
}
TEST(RowRangeIndexTest, ContainsAndContainsExactlyAdjacentMergeFlagDifference) {
ASSERT_OK_AND_ASSIGN(auto merged_index,
RowRangeIndex::Create({Range(0, 10), Range(11, 20)}, true));
ASSERT_OK_AND_ASSIGN(auto non_merged_index,
RowRangeIndex::Create({Range(0, 10), Range(11, 20)}, false));
Range query(10, 11);
ASSERT_TRUE(merged_index.Contains(query));
ASSERT_FALSE(merged_index.ContainsExactly(query));
ASSERT_FALSE(non_merged_index.Contains(query));
ASSERT_FALSE(non_merged_index.ContainsExactly(query));
}
// ======================== merge_adjacent ========================
TEST(RowRangeIndexTest, CreateDoesNotMergeAdjacentRangesWhenDisabled) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(11, 20)}, false));
std::vector<Range> expected = {Range(0, 10), Range(11, 20)};
ASSERT_EQ(index.Ranges(), expected);
}
// ======================== IntersectedRanges ========================
TEST(RowRangeIndexTest, IntersectedRangesExactMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(10, 20);
std::vector<Range> expected = {Range(10, 20)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesClippedFromLeft) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(5, 15);
std::vector<Range> expected = {Range(10, 15)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesClippedFromRight) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(15, 25);
std::vector<Range> expected = {Range(15, 20)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesClippedBothSides) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(12, 18);
std::vector<Range> expected = {Range(12, 18)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesContainingRange) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(0, 30);
std::vector<Range> expected = {Range(10, 20)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesNoOverlapBefore) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(0, 9);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesNoOverlapAfter) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(21, 30);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesTouchingLeftBoundary) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(5, 10);
std::vector<Range> expected = {Range(10, 10)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesTouchingRightBoundary) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(20, 25);
std::vector<Range> expected = {Range(20, 20)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesMultipleRangesHitsFirst) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
auto intersected = index.IntersectedRanges(3, 8);
std::vector<Range> expected = {Range(3, 8)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesMultipleRangesHitsLast) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
auto intersected = index.IntersectedRanges(42, 48);
std::vector<Range> expected = {Range(42, 48)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSpansTwoRanges) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30)}));
auto intersected = index.IntersectedRanges(5, 25);
std::vector<Range> expected = {Range(5, 10), Range(20, 25)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSpansThreeRangesMiddleFullyContained) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
auto intersected = index.IntersectedRanges(5, 45);
std::vector<Range> expected = {Range(5, 10), Range(20, 30), Range(40, 45)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSpansAllRanges) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50)}));
auto intersected = index.IntersectedRanges(0, 50);
std::vector<Range> expected = {Range(0, 10), Range(20, 30), Range(40, 50)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSpansAllRangesWider) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(10, 20), Range(30, 40), Range(50, 60)}));
auto intersected = index.IntersectedRanges(0, 100);
std::vector<Range> expected = {Range(10, 20), Range(30, 40), Range(50, 60)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesFallsInGap) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30)}));
auto intersected = index.IntersectedRanges(11, 19);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesBeforeAll) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20), Range(30, 40)}));
auto intersected = index.IntersectedRanges(0, 5);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesAfterAll) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20), Range(30, 40)}));
auto intersected = index.IntersectedRanges(50, 60);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesSinglePointMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 20)}));
auto intersected = index.IntersectedRanges(15, 15);
std::vector<Range> expected = {Range(15, 15)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSinglePointRangeMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 10)}));
auto intersected = index.IntersectedRanges(10, 10);
std::vector<Range> expected = {Range(10, 10)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesSinglePointRangeNoMatch) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(10, 10)}));
auto intersected = index.IntersectedRanges(11, 11);
ASSERT_TRUE(intersected.empty());
}
TEST(RowRangeIndexTest, IntersectedRangesLastRangeStartsBeyondEnd) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(30, 40)}));
auto intersected = index.IntersectedRanges(5, 25);
std::vector<Range> expected = {Range(5, 10)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesFourRangesClipBothEnds) {
ASSERT_OK_AND_ASSIGN(auto index, RowRangeIndex::Create({Range(0, 10), Range(20, 30),
Range(40, 50), Range(60, 70)}));
auto intersected = index.IntersectedRanges(5, 65);
std::vector<Range> expected = {Range(5, 10), Range(20, 30), Range(40, 50), Range(60, 65)};
ASSERT_EQ(intersected, expected);
}
TEST(RowRangeIndexTest, IntersectedRangesFiveRangesThreeMiddleFullyContained) {
ASSERT_OK_AND_ASSIGN(auto index,
RowRangeIndex::Create({Range(0, 10), Range(20, 30), Range(40, 50),
Range(60, 70), Range(80, 90)}));
auto intersected = index.IntersectedRanges(5, 85);
std::vector<Range> expected = {Range(5, 10), Range(20, 30), Range(40, 50), Range(60, 70),
Range(80, 85)};
ASSERT_EQ(intersected, expected);
}
} // namespace paimon::test