diff --git a/core/src/main/java/org/apache/iceberg/FileMetadata.java b/core/src/main/java/org/apache/iceberg/FileMetadata.java index 15936ec8760c..a8a0791cdc0d 100644 --- a/core/src/main/java/org/apache/iceberg/FileMetadata.java +++ b/core/src/main/java/org/apache/iceberg/FileMetadata.java @@ -255,6 +255,8 @@ public DeleteFile build() { if (format == FileFormat.PUFFIN) { Preconditions.checkArgument(contentOffset != null, "Content offset is required for DV"); Preconditions.checkArgument(contentSizeInBytes != null, "Content size is required for DV"); + Preconditions.checkArgument( + referencedDataFile != null, "Referenced data file is required for DV"); } else { Preconditions.checkArgument(contentOffset == null, "Content offset can only be set for DV"); Preconditions.checkArgument( diff --git a/core/src/test/java/org/apache/iceberg/TestDeleteFiles.java b/core/src/test/java/org/apache/iceberg/TestDeleteFiles.java index 4928f998f3b1..41dfc3ed7d89 100644 --- a/core/src/test/java/org/apache/iceberg/TestDeleteFiles.java +++ b/core/src/test/java/org/apache/iceberg/TestDeleteFiles.java @@ -37,6 +37,7 @@ import org.apache.iceberg.relocated.com.google.common.collect.Lists; import org.apache.iceberg.types.Types; import org.apache.iceberg.util.StructLikeWrapper; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestTemplate; import org.junit.jupiter.api.extension.ExtendWith; @@ -443,6 +444,31 @@ public void testDeleteFilesNoValidation() { assertThat(delete2.removedDataFiles(FILE_IO)).isEmpty(); } + @Test + public void testRequiredFieldsForDV() { + FileMetadata.Builder builder = + FileMetadata.deleteFileBuilder(PartitionSpec.unpartitioned()) + .ofPositionDeletes() + .withFormat(FileFormat.PUFFIN) + .withPath("/path/to/data-d-deletes.puffin") + .withFileSizeInBytes(4) + .withRecordCount(4); + + assertThatThrownBy(builder::build) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Content offset is required for DV"); + + builder.withContentOffset(1); + assertThatThrownBy(builder::build) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Content size is required for DV"); + + builder.withContentSizeInBytes(10); + assertThatThrownBy(builder::build) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Referenced data file is required for DV"); + } + private static ByteBuffer longToBuffer(long value) { return ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(0, value); }