Skip to content

Commit 7407990

Browse files
authored
feat: implement RangeBitmapGlobalIndex for global range-bitmap index support (alibaba#199)
1 parent 2696377 commit 7407990

14 files changed

Lines changed: 904 additions & 94 deletions

src/paimon/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,8 @@ if(PAIMON_BUILD_TESTS)
396396
common/global_index/bitmap_global_index_result_test.cpp
397397
common/global_index/bitmap_scored_global_index_result_test.cpp
398398
common/global_index/bitmap/bitmap_global_index_test.cpp
399+
common/global_index/rangebitmap/range_bitmap_global_index_test.cpp
400+
common/global_index/wrap/file_index_reader_wrapper_test.cpp
399401
common/io/byte_array_input_stream_test.cpp
400402
common/io/data_input_output_stream_test.cpp
401403
common/io/buffered_input_stream_test.cpp

src/paimon/common/file_index/rangebitmap/range_bitmap_file_index.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
#include "paimon/predicate/literal.h"
2929
#include "paimon/result.h"
3030
#include "paimon/status.h"
31+
#include "paimon/visibility.h"
3132

3233
namespace paimon {
3334

3435
class RangeBitmapFileIndexWriter;
3536
class RangeBitmapFileIndexReader;
3637

37-
class RangeBitmapFileIndex final : public FileIndexer {
38+
class PAIMON_EXPORT RangeBitmapFileIndex final : public FileIndexer {
3839
public:
3940
explicit RangeBitmapFileIndex(const std::map<std::string, std::string>& options);
4041

src/paimon/common/global_index/CMakeLists.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
set(PAIMON_GLOBAL_INDEX_SRC bitmap/bitmap_global_index.cpp
16-
bitmap/bitmap_global_index_factory.cpp)
15+
set(PAIMON_GLOBAL_INDEX_SRC
16+
bitmap/bitmap_global_index.cpp bitmap/bitmap_global_index_factory.cpp
17+
rangebitmap/range_bitmap_global_index.cpp
18+
rangebitmap/range_bitmap_global_index_factory.cpp)
1719

1820
add_paimon_lib(paimon_global_index
1921
SOURCES
2022
${PAIMON_GLOBAL_INDEX_SRC}
2123
DEPENDENCIES
2224
paimon_shared
25+
paimon_file_index_shared
2326
STATIC_LINK_LIBS
2427
arrow
2528
fmt

src/paimon/common/global_index/bitmap/bitmap_global_index.cpp

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717

1818
#include "paimon/common/global_index/wrap/file_index_reader_wrapper.h"
1919
#include "paimon/common/global_index/wrap/file_index_writer_wrapper.h"
20-
#include "paimon/file_index/bitmap_index_result.h"
21-
#include "paimon/global_index/bitmap_global_index_result.h"
22-
#include "paimon/utils/roaring_bitmap64.h"
2320

2421
namespace paimon {
2522
Result<std::shared_ptr<GlobalIndexWriter>> BitmapGlobalIndex::CreateWriter(
@@ -47,31 +44,9 @@ Result<std::shared_ptr<GlobalIndexReader>> BitmapGlobalIndex::CreateReader(
4744
index_->CreateReader(arrow_schema, /*start=*/0, meta.file_size, in, pool));
4845
auto transform = [range_end = meta.range_end](const std::shared_ptr<FileIndexResult>& result)
4946
-> Result<std::shared_ptr<GlobalIndexResult>> {
50-
return ToGlobalIndexResult(range_end, result);
47+
return FileIndexReaderWrapper::ToGlobalIndexResult(range_end, result);
5148
};
5249
return std::make_shared<BitmapGlobalIndexReader>(reader, transform);
5350
}
5451

55-
Result<std::shared_ptr<GlobalIndexResult>> BitmapGlobalIndex::ToGlobalIndexResult(
56-
int64_t range_end, const std::shared_ptr<FileIndexResult>& result) {
57-
if (auto remain = std::dynamic_pointer_cast<Remain>(result)) {
58-
return std::make_shared<BitmapGlobalIndexResult>([range_end]() -> Result<RoaringBitmap64> {
59-
RoaringBitmap64 bitmap;
60-
bitmap.AddRange(0, range_end + 1);
61-
return bitmap;
62-
});
63-
} else if (auto skip = std::dynamic_pointer_cast<Skip>(result)) {
64-
return std::make_shared<BitmapGlobalIndexResult>(
65-
[]() -> Result<RoaringBitmap64> { return RoaringBitmap64(); });
66-
} else if (auto bitmap_result = std::dynamic_pointer_cast<BitmapIndexResult>(result)) {
67-
return std::make_shared<BitmapGlobalIndexResult>(
68-
[bitmap_result]() -> Result<RoaringBitmap64> {
69-
PAIMON_ASSIGN_OR_RAISE(const RoaringBitmap32* bitmap, bitmap_result->GetBitmap());
70-
return RoaringBitmap64(*bitmap);
71-
});
72-
}
73-
return Status::Invalid(
74-
"invalid FileIndexResult, supposed to be Remain or Skip or BitmapIndexResult");
75-
}
76-
7752
} // namespace paimon

src/paimon/common/global_index/bitmap/bitmap_global_index.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ class BitmapGlobalIndex : public GlobalIndexer {
3939
const std::vector<GlobalIndexIOMeta>& files,
4040
const std::shared_ptr<MemoryPool>& pool) const override;
4141

42-
private:
43-
static Result<std::shared_ptr<GlobalIndexResult>> ToGlobalIndexResult(
44-
int64_t range_end, const std::shared_ptr<FileIndexResult>& result);
45-
4642
private:
4743
std::shared_ptr<BitmapFileIndex> index_;
4844
};

src/paimon/common/global_index/bitmap/bitmap_global_index_test.cpp

Lines changed: 4 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -30,41 +30,20 @@
3030
#include "paimon/common/utils/path_util.h"
3131
#include "paimon/common/utils/string_utils.h"
3232
#include "paimon/core/global_index/global_index_file_manager.h"
33-
#include "paimon/core/index/index_path_factory.h"
3433
#include "paimon/data/timestamp.h"
3534
#include "paimon/file_index/bitmap_index_result.h"
3635
#include "paimon/fs/local/local_file_system.h"
3736
#include "paimon/global_index/bitmap_global_index_result.h"
3837
#include "paimon/global_index/global_index_result.h"
38+
#include "paimon/testing/mock/mock_index_path_factory.h"
3939
#include "paimon/testing/utils/testharness.h"
40+
4041
namespace paimon::test {
4142
class BitmapGlobalIndexTest : public ::testing::Test {
4243
public:
4344
void SetUp() override {}
4445
void TearDown() override {}
4546

46-
class FakeIndexPathFactory : public IndexPathFactory {
47-
public:
48-
explicit FakeIndexPathFactory(const std::string& index_path) : index_path_(index_path) {}
49-
std::string NewPath() const override {
50-
assert(false);
51-
return "";
52-
}
53-
std::string ToPath(const std::shared_ptr<IndexFileMeta>& file) const override {
54-
assert(false);
55-
return "";
56-
}
57-
std::string ToPath(const std::string& file_name) const override {
58-
return PathUtil::JoinPath(index_path_, file_name);
59-
}
60-
bool IsExternalPath() const override {
61-
return false;
62-
}
63-
64-
private:
65-
std::string index_path_;
66-
};
67-
6847
std::unique_ptr<::ArrowSchema> CreateArrowSchema(
6948
const std::shared_ptr<arrow::DataType>& data_type) const {
7049
auto schema = arrow::schema({arrow::field("f0", data_type)});
@@ -83,7 +62,7 @@ class BitmapGlobalIndexTest : public ::testing::Test {
8362
auto file_index = std::make_shared<BitmapFileIndex>(options);
8463
auto global_index = std::make_shared<BitmapGlobalIndex>(file_index);
8564

86-
auto path_factory = std::make_shared<FakeIndexPathFactory>(index_root);
65+
auto path_factory = std::make_shared<MockIndexPathFactory>(index_root);
8766
auto file_writer = std::make_shared<GlobalIndexFileManager>(fs_, path_factory);
8867

8968
PAIMON_ASSIGN_OR_RAISE(
@@ -125,7 +104,7 @@ class BitmapGlobalIndexTest : public ::testing::Test {
125104
auto file_index = std::make_shared<BitmapFileIndex>(std::map<std::string, std::string>());
126105
auto global_index = std::make_shared<BitmapGlobalIndex>(file_index);
127106

128-
auto path_factory = std::make_shared<FakeIndexPathFactory>(index_root);
107+
auto path_factory = std::make_shared<MockIndexPathFactory>(index_root);
129108
auto file_reader = std::make_shared<GlobalIndexFileManager>(fs_, path_factory);
130109
EXPECT_OK_AND_ASSIGN(
131110
auto global_index_reader,
@@ -139,42 +118,6 @@ class BitmapGlobalIndexTest : public ::testing::Test {
139118
std::shared_ptr<FileSystem> fs_ = std::make_shared<LocalFileSystem>();
140119
};
141120

142-
TEST_F(BitmapGlobalIndexTest, TestToGlobalIndexResult) {
143-
{
144-
ASSERT_OK_AND_ASSIGN(auto global_result, BitmapGlobalIndex::ToGlobalIndexResult(
145-
/*range_end=*/5l, FileIndexResult::Remain()));
146-
CheckResult(global_result, {0l, 1l, 2l, 3l, 4l, 5l});
147-
}
148-
{
149-
ASSERT_OK_AND_ASSIGN(auto global_result, BitmapGlobalIndex::ToGlobalIndexResult(
150-
/*range_end=*/5l, FileIndexResult::Skip()));
151-
CheckResult(global_result, {});
152-
}
153-
{
154-
auto bitmap_supplier = []() -> Result<RoaringBitmap32> {
155-
return RoaringBitmap32::From({1, 4, 2147483647});
156-
};
157-
auto file_result = std::make_shared<BitmapIndexResult>(bitmap_supplier);
158-
ASSERT_OK_AND_ASSIGN(auto global_result, BitmapGlobalIndex::ToGlobalIndexResult(
159-
/*range_end=*/2147483647l, file_result));
160-
CheckResult(global_result, {1l, 4l, 2147483647l});
161-
}
162-
{
163-
class FakeFileIndexResult : public FileIndexResult {
164-
Result<bool> IsRemain() const override {
165-
return true;
166-
}
167-
std::string ToString() const override {
168-
return "fake file index result";
169-
}
170-
};
171-
auto file_result = std::make_shared<FakeFileIndexResult>();
172-
ASSERT_NOK_WITH_MSG(
173-
BitmapGlobalIndex::ToGlobalIndexResult(/*range_end=*/10l, file_result),
174-
"invalid FileIndexResult, supposed to be Remain or Skip or BitmapIndexResult");
175-
}
176-
}
177-
178121
TEST_F(BitmapGlobalIndexTest, TestStringType) {
179122
auto test_root_dir = UniqueTestDirectory::Create();
180123
ASSERT_TRUE(test_root_dir);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "paimon/common/global_index/rangebitmap/range_bitmap_global_index.h"
17+
18+
#include "paimon/common/global_index/wrap/file_index_reader_wrapper.h"
19+
#include "paimon/common/global_index/wrap/file_index_writer_wrapper.h"
20+
21+
namespace paimon {
22+
Result<std::shared_ptr<GlobalIndexWriter>> RangeBitmapGlobalIndex::CreateWriter(
23+
const std::string& field_name, ::ArrowSchema* arrow_schema,
24+
const std::shared_ptr<GlobalIndexFileWriter>& file_writer,
25+
const std::shared_ptr<MemoryPool>& pool) const {
26+
PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<FileIndexWriter> writer,
27+
index_->CreateWriter(arrow_schema, pool));
28+
return std::make_shared<FileIndexWriterWrapper>(
29+
/*index_type=*/"range-bitmap", file_writer, writer);
30+
}
31+
32+
Result<std::shared_ptr<GlobalIndexReader>> RangeBitmapGlobalIndex::CreateReader(
33+
::ArrowSchema* arrow_schema, const std::shared_ptr<GlobalIndexFileReader>& file_reader,
34+
const std::vector<GlobalIndexIOMeta>& files, const std::shared_ptr<MemoryPool>& pool) const {
35+
if (files.size() != 1) {
36+
return Status::Invalid(
37+
"invalid GlobalIndexIOMeta for RangeBitmapGlobalIndex, exist multiple metas");
38+
}
39+
const auto& meta = files[0];
40+
PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<InputStream> in,
41+
file_reader->GetInputStream(meta.file_path));
42+
PAIMON_ASSIGN_OR_RAISE(
43+
std::shared_ptr<FileIndexReader> reader,
44+
index_->CreateReader(arrow_schema, /*start=*/0, meta.file_size, in, pool));
45+
auto transform = [range_end = meta.range_end](const std::shared_ptr<FileIndexResult>& result)
46+
-> Result<std::shared_ptr<GlobalIndexResult>> {
47+
return FileIndexReaderWrapper::ToGlobalIndexResult(range_end, result);
48+
};
49+
return std::make_shared<RangeBitmapGlobalIndexReader>(reader, transform);
50+
}
51+
52+
} // namespace paimon
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <memory>
20+
#include <string>
21+
#include <vector>
22+
23+
#include "paimon/common/file_index/rangebitmap/range_bitmap_file_index.h"
24+
#include "paimon/common/global_index/wrap/file_index_reader_wrapper.h"
25+
#include "paimon/global_index/global_indexer.h"
26+
27+
namespace paimon {
28+
class RangeBitmapGlobalIndex : public GlobalIndexer {
29+
public:
30+
explicit RangeBitmapGlobalIndex(const std::shared_ptr<RangeBitmapFileIndex>& index)
31+
: index_(index) {}
32+
33+
Result<std::shared_ptr<GlobalIndexWriter>> CreateWriter(
34+
const std::string& field_name, ::ArrowSchema* arrow_schema,
35+
const std::shared_ptr<GlobalIndexFileWriter>& file_writer,
36+
const std::shared_ptr<MemoryPool>& pool) const override;
37+
38+
Result<std::shared_ptr<GlobalIndexReader>> CreateReader(
39+
::ArrowSchema* arrow_schema, const std::shared_ptr<GlobalIndexFileReader>& file_reader,
40+
const std::vector<GlobalIndexIOMeta>& files,
41+
const std::shared_ptr<MemoryPool>& pool) const override;
42+
43+
private:
44+
std::shared_ptr<RangeBitmapFileIndex> index_;
45+
};
46+
47+
class RangeBitmapGlobalIndexReader : public FileIndexReaderWrapper {
48+
public:
49+
RangeBitmapGlobalIndexReader(const std::shared_ptr<FileIndexReader>& reader,
50+
const std::function<Result<std::shared_ptr<GlobalIndexResult>>(
51+
const std::shared_ptr<FileIndexResult>&)>& transform)
52+
: FileIndexReaderWrapper(reader, transform) {}
53+
54+
static inline const char kIdentifier[] = "range-bitmap";
55+
56+
bool IsThreadSafe() const override {
57+
return false;
58+
}
59+
60+
std::string GetIndexType() const override {
61+
return kIdentifier;
62+
}
63+
};
64+
65+
} // namespace paimon
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "paimon/common/global_index/rangebitmap/range_bitmap_global_index_factory.h"
18+
19+
#include <utility>
20+
21+
#include "paimon/common/file_index/rangebitmap/range_bitmap_file_index.h"
22+
#include "paimon/common/global_index/rangebitmap/range_bitmap_global_index.h"
23+
24+
namespace paimon {
25+
26+
const char RangeBitmapGlobalIndexFactory::IDENTIFIER[] = "range-bitmap-global";
27+
28+
Result<std::unique_ptr<GlobalIndexer>> RangeBitmapGlobalIndexFactory::Create(
29+
const std::map<std::string, std::string>& options) const {
30+
auto range_bitmap_file_index = std::make_shared<RangeBitmapFileIndex>(options);
31+
return std::make_unique<RangeBitmapGlobalIndex>(range_bitmap_file_index);
32+
}
33+
34+
REGISTER_PAIMON_FACTORY(RangeBitmapGlobalIndexFactory);
35+
36+
} // namespace paimon
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <map>
20+
#include <memory>
21+
#include <string>
22+
23+
#include "paimon/global_index/global_indexer_factory.h"
24+
25+
namespace paimon {
26+
/// Factory for creating range-bitmap global indexers.
27+
class RangeBitmapGlobalIndexFactory : public GlobalIndexerFactory {
28+
public:
29+
static const char IDENTIFIER[];
30+
31+
const char* Identifier() const override {
32+
return IDENTIFIER;
33+
}
34+
35+
Result<std::unique_ptr<GlobalIndexer>> Create(
36+
const std::map<std::string, std::string>& options) const override;
37+
};
38+
39+
} // namespace paimon

0 commit comments

Comments
 (0)