|
26 | 26 | #include <gtest/gtest.h> |
27 | 27 |
|
28 | 28 | #include "iceberg/arrow/arrow_io_internal.h" |
| 29 | +#include "iceberg/arrow_c_data_guard_internal.h" |
29 | 30 | #include "iceberg/avro/avro_register.h" |
30 | 31 | #include "iceberg/data/equality_delete_writer.h" |
31 | 32 | #include "iceberg/data/position_delete_writer.h" |
@@ -344,18 +345,12 @@ class PositionDeleteWriterTest : public DataWriterTest { |
344 | 345 | }; |
345 | 346 | } |
346 | 347 |
|
347 | | - std::shared_ptr<::arrow::Array> CreatePositionDeleteData() { |
| 348 | + std::shared_ptr<::arrow::Array> CreatePositionDeleteData( |
| 349 | + std::string_view json = |
| 350 | + R"([["data_file_1.parquet", 0], ["data_file_1.parquet", 5], ["data_file_1.parquet", 10]])") { |
348 | 351 | auto delete_schema = std::make_shared<Schema>(std::vector<SchemaField>{ |
349 | 352 | MetadataColumns::kDeleteFilePath, MetadataColumns::kDeleteFilePos}); |
350 | | - |
351 | | - ArrowSchema arrow_c_schema; |
352 | | - ICEBERG_THROW_NOT_OK(ToArrowSchema(*delete_schema, &arrow_c_schema)); |
353 | | - auto arrow_type = ::arrow::ImportType(&arrow_c_schema).ValueOrDie(); |
354 | | - |
355 | | - return ::arrow::json::ArrayFromJSONString( |
356 | | - ::arrow::struct_(arrow_type->fields()), |
357 | | - R"([["data_file_1.parquet", 0], ["data_file_1.parquet", 5], ["data_file_1.parquet", 10]])") |
358 | | - .ValueOrDie(); |
| 353 | + return CreateArray(*delete_schema, json); |
359 | 354 | } |
360 | 355 | }; |
361 | 356 |
|
@@ -458,6 +453,92 @@ TEST_F(PositionDeleteWriterTest, WriteBatchData) { |
458 | 453 | const auto& data_file = metadata_result.value().data_files[0]; |
459 | 454 | EXPECT_EQ(data_file->content, DataFile::Content::kPositionDeletes); |
460 | 455 | EXPECT_GT(data_file->file_size_in_bytes, 0); |
| 456 | + ASSERT_TRUE(data_file->referenced_data_file.has_value()); |
| 457 | + EXPECT_EQ(data_file->referenced_data_file.value(), "data_file_1.parquet"); |
| 458 | +} |
| 459 | + |
| 460 | +TEST_F(PositionDeleteWriterTest, WriteBatchDataForMultipleFiles) { |
| 461 | + auto writer_result = PositionDeleteWriter::Make(MakeDeleteOptions()); |
| 462 | + ASSERT_THAT(writer_result, IsOk()); |
| 463 | + auto writer = std::move(writer_result.value()); |
| 464 | + |
| 465 | + auto test_data = CreatePositionDeleteData( |
| 466 | + R"([["data_file_1.parquet", 0], ["data_file_2.parquet", 5]])"); |
| 467 | + ArrowArray arrow_array; |
| 468 | + ASSERT_TRUE(::arrow::ExportArray(*test_data, &arrow_array).ok()); |
| 469 | + ASSERT_THAT(writer->Write(&arrow_array), IsOk()); |
| 470 | + ASSERT_THAT(writer->Close(), IsOk()); |
| 471 | + |
| 472 | + auto metadata_result = writer->Metadata(); |
| 473 | + ASSERT_THAT(metadata_result, IsOk()); |
| 474 | + |
| 475 | + const auto& data_file = metadata_result.value().data_files[0]; |
| 476 | + EXPECT_FALSE(data_file->referenced_data_file.has_value()); |
| 477 | + EXPECT_FALSE( |
| 478 | + data_file->lower_bounds.contains(MetadataColumns::kDeleteFilePathColumnId)); |
| 479 | + EXPECT_FALSE(data_file->lower_bounds.contains(MetadataColumns::kDeleteFilePosColumnId)); |
| 480 | + EXPECT_FALSE( |
| 481 | + data_file->upper_bounds.contains(MetadataColumns::kDeleteFilePathColumnId)); |
| 482 | + EXPECT_FALSE(data_file->upper_bounds.contains(MetadataColumns::kDeleteFilePosColumnId)); |
| 483 | +} |
| 484 | + |
| 485 | +TEST_F(PositionDeleteWriterTest, WriteBatchThenDeleteTracksAllReferencedFiles) { |
| 486 | + auto writer_result = PositionDeleteWriter::Make(MakeDeleteOptions()); |
| 487 | + ASSERT_THAT(writer_result, IsOk()); |
| 488 | + auto writer = std::move(writer_result.value()); |
| 489 | + |
| 490 | + auto test_data = CreatePositionDeleteData(R"([["data_file_1.parquet", 0]])"); |
| 491 | + ArrowArray arrow_array; |
| 492 | + ASSERT_TRUE(::arrow::ExportArray(*test_data, &arrow_array).ok()); |
| 493 | + ASSERT_THAT(writer->Write(&arrow_array), IsOk()); |
| 494 | + ASSERT_THAT(writer->WriteDelete("data_file_2.parquet", 5), IsOk()); |
| 495 | + ASSERT_THAT(writer->Close(), IsOk()); |
| 496 | + |
| 497 | + auto metadata_result = writer->Metadata(); |
| 498 | + ASSERT_THAT(metadata_result, IsOk()); |
| 499 | + EXPECT_FALSE(metadata_result.value().data_files[0]->referenced_data_file.has_value()); |
| 500 | +} |
| 501 | + |
| 502 | +TEST_F(PositionDeleteWriterTest, WriteBatchRejectsNullFilePath) { |
| 503 | + auto writer_result = PositionDeleteWriter::Make(MakeDeleteOptions()); |
| 504 | + ASSERT_THAT(writer_result, IsOk()); |
| 505 | + auto writer = std::move(writer_result.value()); |
| 506 | + |
| 507 | + auto test_data = CreatePositionDeleteData(R"([[null, 0]])"); |
| 508 | + ArrowArray arrow_array; |
| 509 | + ASSERT_TRUE(::arrow::ExportArray(*test_data, &arrow_array).ok()); |
| 510 | + internal::ArrowArrayGuard array_guard(&arrow_array); |
| 511 | + |
| 512 | + auto result = writer->Write(&arrow_array); |
| 513 | + ASSERT_THAT(result, IsError(ErrorKind::kInvalidArrowData)); |
| 514 | + EXPECT_THAT(result, |
| 515 | + HasErrorMessage("Position delete file paths must not contain null values")); |
| 516 | +} |
| 517 | + |
| 518 | +TEST_F(PositionDeleteWriterTest, WriteBatchRejectsNullData) { |
| 519 | + auto writer_result = PositionDeleteWriter::Make(MakeDeleteOptions()); |
| 520 | + ASSERT_THAT(writer_result, IsOk()); |
| 521 | + auto writer = std::move(writer_result.value()); |
| 522 | + |
| 523 | + auto result = writer->Write(nullptr); |
| 524 | + ASSERT_THAT(result, IsError(ErrorKind::kInvalidArgument)); |
| 525 | + EXPECT_THAT(result, HasErrorMessage("Position delete data must not be null")); |
| 526 | +} |
| 527 | + |
| 528 | +TEST_F(PositionDeleteWriterTest, WriteEmptyBatchDoesNotAddReferencedFiles) { |
| 529 | + auto writer_result = PositionDeleteWriter::Make(MakeDeleteOptions()); |
| 530 | + ASSERT_THAT(writer_result, IsOk()); |
| 531 | + auto writer = std::move(writer_result.value()); |
| 532 | + |
| 533 | + auto test_data = CreatePositionDeleteData("[]"); |
| 534 | + ArrowArray arrow_array; |
| 535 | + ASSERT_TRUE(::arrow::ExportArray(*test_data, &arrow_array).ok()); |
| 536 | + ASSERT_THAT(writer->Write(&arrow_array), IsOk()); |
| 537 | + ASSERT_THAT(writer->Close(), IsOk()); |
| 538 | + |
| 539 | + auto metadata_result = writer->Metadata(); |
| 540 | + ASSERT_THAT(metadata_result, IsOk()); |
| 541 | + EXPECT_FALSE(metadata_result.value().data_files[0]->referenced_data_file.has_value()); |
461 | 542 | } |
462 | 543 |
|
463 | 544 | TEST_F(PositionDeleteWriterTest, AutoFlushOnThreshold) { |
|
0 commit comments