|
30 | 30 | #include "gtest/gtest.h" |
31 | 31 | #include "paimon/common/data/binary_row.h" |
32 | 32 | #include "paimon/common/data/data_define.h" |
| 33 | +#include "paimon/common/utils/checked_cast.h" |
33 | 34 | #include "paimon/core/io/data_file_meta.h" |
| 35 | +#include "paimon/core/io/meta_to_arrow_array_converter.h" |
34 | 36 | #include "paimon/core/manifest/file_kind.h" |
35 | 37 | #include "paimon/core/manifest/file_source.h" |
36 | 38 | #include "paimon/core/manifest/manifest_entry.h" |
@@ -530,6 +532,73 @@ TEST_F(ManifestFileTest, TestReadBucketEntriesSkipsDeserializingOtherBuckets) { |
530 | 532 | } |
531 | 533 | } |
532 | 534 |
|
| 535 | +TEST_F(ManifestFileTest, TestReadBucketEntriesWithReorderedFields) { |
| 536 | + auto pool = GetDefaultPool(); |
| 537 | + auto source = |
| 538 | + ReadManifestEntry("orc", paimon::test::GetDataDir() + "/orc/append_09.db/append_09", |
| 539 | + "manifest-3a44a0da-1008-463c-914e-28d271375e24-0", pool); |
| 540 | + ASSERT_EQ(source.size(), 2); |
| 541 | + std::vector<ManifestEntry> entries; |
| 542 | + std::vector<BinaryRow> rows; |
| 543 | + ManifestEntrySerializer serializer(pool); |
| 544 | + for (int32_t bucket = 0; bucket < 2; ++bucket) { |
| 545 | + entries.emplace_back(FileKind::Add(), source[bucket].Partition(), bucket, 2, |
| 546 | + source[bucket].File()); |
| 547 | + ASSERT_OK_AND_ASSIGN(BinaryRow row, serializer.ToRow(entries.back())); |
| 548 | + rows.push_back(std::move(row)); |
| 549 | + } |
| 550 | + ASSERT_OK_AND_ASSIGN(std::unique_ptr<MetaToArrowArrayConverter> converter, |
| 551 | + MetaToArrowArrayConverter::Create(serializer.GetDataType(), pool)); |
| 552 | + ASSERT_OK_AND_ASSIGN(std::shared_ptr<arrow::Array> array, converter->NextBatch(rows)); |
| 553 | + auto struct_array = checked_pointer_cast<arrow::StructArray>(array); |
| 554 | + ASSERT_OK_AND_ASSIGN(std::shared_ptr<FileFormat> format, FileFormatFactory::Get("avro", {})); |
| 555 | + // Move each selector field away from its standard position. Ordinary schema alignment |
| 556 | + // must still restore the fields before version validation and bucket filtering. |
| 557 | + for (int32_t field_index : {0, 3, 4}) { |
| 558 | + SCOPED_TRACE(field_index); |
| 559 | + auto fields = serializer.GetDataType()->fields(); |
| 560 | + auto columns = struct_array->fields(); |
| 561 | + std::swap(fields[1], fields[field_index]); |
| 562 | + std::swap(columns[1], columns[field_index]); |
| 563 | + auto reordered_result = arrow::StructArray::Make(columns, fields); |
| 564 | + ASSERT_TRUE(reordered_result.ok()) << reordered_result.status().ToString(); |
| 565 | + std::shared_ptr<arrow::StructArray> reordered = reordered_result.ValueOrDie(); |
| 566 | + auto dir = UniqueTestDirectory::Create(); |
| 567 | + ASSERT_TRUE(dir); |
| 568 | + auto fs = dir->GetFileSystem(); |
| 569 | + const std::string manifest_dir = FileStorePathFactory::ManifestPath(dir->Str()); |
| 570 | + ASSERT_OK(fs->Mkdirs(manifest_dir)); |
| 571 | + const std::string file_name = "manifest-reordered"; |
| 572 | + ArrowSchema c_schema; |
| 573 | + ASSERT_TRUE(arrow::ExportSchema(*arrow::schema(fields), &c_schema).ok()); |
| 574 | + ASSERT_OK_AND_ASSIGN(std::shared_ptr<WriterBuilder> builder, |
| 575 | + format->CreateWriterBuilder(&c_schema, 2)); |
| 576 | + ASSERT_OK_AND_ASSIGN(std::shared_ptr<OutputStream> output, |
| 577 | + fs->Create(manifest_dir + "/" + file_name, false)); |
| 578 | + ASSERT_OK_AND_ASSIGN(std::unique_ptr<FormatWriter> writer, builder->Build(output, "null")); |
| 579 | + ArrowArray c_array; |
| 580 | + ASSERT_TRUE(arrow::ExportArray(*reordered, &c_array).ok()); |
| 581 | + ASSERT_OK(writer->AddBatch(&c_array)); |
| 582 | + ASSERT_OK(writer->Flush()); |
| 583 | + ASSERT_OK(writer->Finish()); |
| 584 | + ASSERT_OK(output->Close()); |
| 585 | + for (bool cache_enabled : {false, true}) { |
| 586 | + for (bool inferred_bucket : {false, true}) { |
| 587 | + for (int32_t bucket : {0, 1, 2}) { |
| 588 | + ASSERT_OK_AND_ASSIGN( |
| 589 | + std::vector<ManifestEntry> actual, |
| 590 | + TryReadManifestEntry("avro", dir->Str(), file_name, pool, bucket, |
| 591 | + cache_enabled, inferred_bucket)); |
| 592 | + const std::vector<ManifestEntry> expected = |
| 593 | + bucket < 2 ? std::vector<ManifestEntry>{entries[bucket]} |
| 594 | + : std::vector<ManifestEntry>{}; |
| 595 | + ASSERT_EQ(actual, expected); |
| 596 | + } |
| 597 | + } |
| 598 | + } |
| 599 | + } |
| 600 | +} |
| 601 | + |
533 | 602 | TEST_F(ManifestFileTest, TestReadBucketEntriesValidatesAllVersions) { |
534 | 603 | auto pool = GetDefaultPool(); |
535 | 604 | ManifestEntrySerializer serializer(pool); |
|
0 commit comments