|
36 | 36 | #include "paimon/core/stats/simple_stats.h" |
37 | 37 | #include "paimon/core/table/bucket_mode.h" |
38 | 38 | #include "paimon/core/table/source/append_only_split_generator.h" |
| 39 | +#include "paimon/core/table/source/data_evolution_split_generator.h" |
39 | 40 | #include "paimon/core/table/source/merge_tree_split_generator.h" |
40 | 41 | #include "paimon/data/timestamp.h" |
41 | 42 | #include "paimon/memory/memory_pool.h" |
@@ -116,6 +117,21 @@ class SplitGeneratorTest : public testing::Test { |
116 | 117 | /*write_cols=*/std::nullopt); |
117 | 118 | } |
118 | 119 |
|
| 120 | + std::shared_ptr<DataFileMeta> CreateDataFileMetaWithRowId(const std::string& file_name, |
| 121 | + int64_t file_size, int64_t row_count, |
| 122 | + int64_t first_row_id) { |
| 123 | + return std::make_shared<DataFileMeta>( |
| 124 | + file_name, file_size, row_count, /*min_key=*/BinaryRow::EmptyRow(), |
| 125 | + /*max_key=*/BinaryRow::EmptyRow(), /*key_stats=*/SimpleStats::EmptyStats(), |
| 126 | + /*value_stats=*/SimpleStats::EmptyStats(), /*min_sequence_number=*/0, |
| 127 | + /*max_sequence_number=*/0, /*schema_id=*/0, |
| 128 | + /*level=*/0, /*extra_files=*/std::vector<std::optional<std::string>>(), |
| 129 | + /*creation_time=*/Timestamp(0, 0), /*delete_row_count=*/0, |
| 130 | + /*embedded_index=*/nullptr, FileSource::Append(), /*value_stats_cols=*/std::nullopt, |
| 131 | + /*external_path=*/std::nullopt, first_row_id, |
| 132 | + /*write_cols=*/std::nullopt); |
| 133 | + } |
| 134 | + |
119 | 135 | static void CheckResult(const std::vector<SplitGenerator::SplitGroup>& result_groups, |
120 | 136 | const std::vector<std::vector<std::string>>& expected_file_names, |
121 | 137 | const std::vector<bool>& expected_raw_convertible) { |
@@ -206,6 +222,41 @@ TEST_F(SplitGeneratorTest, TestAppend) { |
206 | 222 | } |
207 | 223 | } |
208 | 224 |
|
| 225 | +TEST_F(SplitGeneratorTest, TestDataEvolutionBlobSplitByFileSize) { |
| 226 | + // two row id ranges, each with one data file and one much larger blob file |
| 227 | + auto create_files = [&]() { |
| 228 | + return std::vector<std::shared_ptr<DataFileMeta>>{ |
| 229 | + CreateDataFileMetaWithRowId("f1", /*file_size=*/100, /*row_count=*/100, |
| 230 | + /*first_row_id=*/0), |
| 231 | + CreateDataFileMetaWithRowId("blob1.blob", /*file_size=*/1000, /*row_count=*/100, |
| 232 | + /*first_row_id=*/0), |
| 233 | + CreateDataFileMetaWithRowId("f2", /*file_size=*/100, /*row_count=*/100, |
| 234 | + /*first_row_id=*/100), |
| 235 | + CreateDataFileMetaWithRowId("blob2.blob", /*file_size=*/1000, /*row_count=*/100, |
| 236 | + /*first_row_id=*/100)}; |
| 237 | + }; |
| 238 | + { |
| 239 | + // blob file size counts in splitting: each range weighs 1100, so the two ranges cannot |
| 240 | + // be packed into one split of target size 1200 |
| 241 | + DataEvolutionSplitGenerator split_generator(/*target_split_size=*/1200, |
| 242 | + /*open_file_cost=*/10, |
| 243 | + /*count_blob_size=*/true); |
| 244 | + ASSERT_OK_AND_ASSIGN(std::vector<SplitGenerator::SplitGroup> split_groups, |
| 245 | + split_generator.SplitForBatch(create_files())); |
| 246 | + CheckResult(split_groups, {{"f1", "blob1.blob"}, {"f2", "blob2.blob"}}, {false, false}); |
| 247 | + } |
| 248 | + { |
| 249 | + // blob file only weighs the open file cost: each range weighs 110, both ranges fit in |
| 250 | + // one split of target size 1200 |
| 251 | + DataEvolutionSplitGenerator split_generator(/*target_split_size=*/1200, |
| 252 | + /*open_file_cost=*/10, |
| 253 | + /*count_blob_size=*/false); |
| 254 | + ASSERT_OK_AND_ASSIGN(std::vector<SplitGenerator::SplitGroup> split_groups, |
| 255 | + split_generator.SplitForBatch(create_files())); |
| 256 | + CheckResult(split_groups, {{"f1", "blob1.blob", "f2", "blob2.blob"}}, {false}); |
| 257 | + } |
| 258 | +} |
| 259 | + |
209 | 260 | TEST_F(SplitGeneratorTest, TestMergeTree) { |
210 | 261 | std::vector<std::shared_ptr<DataFileMeta>> files = { |
211 | 262 | CreateDataFileMeta("1", 0, 10), CreateDataFileMeta("2", 0, 12), |
|
0 commit comments