diff --git a/core/src/main/java/org/apache/iceberg/BaseRowDelta.java b/core/src/main/java/org/apache/iceberg/BaseRowDelta.java index b819d03dd5f8..92386ee42159 100644 --- a/core/src/main/java/org/apache/iceberg/BaseRowDelta.java +++ b/core/src/main/java/org/apache/iceberg/BaseRowDelta.java @@ -48,6 +48,10 @@ protected BaseRowDelta self() { @Override protected String operation() { + if (addsDataFiles() && !addsDeleteFiles() && !deletesDataFiles()) { + return DataOperations.APPEND; + } + if (addsDeleteFiles() && !addsDataFiles()) { return DataOperations.DELETE; } diff --git a/core/src/test/java/org/apache/iceberg/TestRowDelta.java b/core/src/test/java/org/apache/iceberg/TestRowDelta.java index 4d1d11081d4b..397e1ac56dc4 100644 --- a/core/src/test/java/org/apache/iceberg/TestRowDelta.java +++ b/core/src/test/java/org/apache/iceberg/TestRowDelta.java @@ -76,6 +76,25 @@ public void addOnlyDeleteFilesProducesDeleteOperation() { assertThat(snap.deleteManifests(table.io())).hasSize(1); } + @TestTemplate + public void addOnlyDataFilesProducesAppendOperation() { + SnapshotUpdate rowDelta = table.newRowDelta().addRows(FILE_A).addRows(FILE_B); + + commit(table, rowDelta, branch); + Snapshot snap = latestSnapshot(table, branch); + assertThat(snap.sequenceNumber()).isEqualTo(1); + assertThat(snap.operation()).isEqualTo(DataOperations.APPEND); + assertThat(snap.dataManifests(table.io())).hasSize(1); + + validateManifest( + snap.dataManifests(table.io()).get(0), + dataSeqs(1L, 1L), + fileSeqs(1L, 1L), + ids(snap.snapshotId(), snap.snapshotId()), + files(FILE_A, FILE_B), + statuses(Status.ADDED, Status.ADDED)); + } + @TestTemplate public void testAddRemoveRows() { SnapshotUpdate rowDelta = @@ -108,6 +127,29 @@ public void testAddRemoveRows() { statuses(Status.ADDED, Status.ADDED)); } + @TestTemplate + public void testAddRowsRemoveDataFile() { + table.newRowDelta().addRows(FILE_A).commit(); + SnapshotUpdate rowDelta = table.newRowDelta().addRows(FILE_B).removeRows(FILE_A); + + commit(table, rowDelta, branch); + Snapshot snap = latestSnapshot(table, branch); + assertThat(snap.sequenceNumber()).isEqualTo(2); + assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(2); + assertThat(snap.operation()) + .as("Delta commit should use operation 'overwrite'") + .isEqualTo(DataOperations.OVERWRITE); + assertThat(snap.dataManifests(table.io())).hasSize(2); + + validateManifest( + snap.dataManifests(table.io()).get(0), + dataSeqs(2L), + fileSeqs(2L), + ids(snap.snapshotId()), + files(FILE_B), + statuses(Status.ADDED)); + } + @TestTemplate public void testValidateDataFilesExistDefaults() { SnapshotUpdate rowDelta1 = table.newAppend().appendFile(FILE_A).appendFile(FILE_B); @@ -599,6 +641,7 @@ public void testOverwriteWithRemoveRows() { long deltaSnapshotId = latestSnapshot(table, branch).snapshotId(); assertThat(latestSnapshot(table, branch).sequenceNumber()).isEqualTo(1); + assertThat(latestSnapshot(table, branch).operation()).isEqualTo(DataOperations.OVERWRITE); assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(1); // overwriting by a filter will also remove delete files that match because all matching data @@ -642,6 +685,7 @@ public void testReplacePartitionsWithRemoveRows() { long deltaSnapshotId = latestSnapshot(table, branch).snapshotId(); assertThat(latestSnapshot(table, branch).sequenceNumber()).isEqualTo(1); + assertThat(latestSnapshot(table, branch).operation()).isEqualTo(DataOperations.OVERWRITE); assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(1); // overwriting the partition will also remove delete files that match because all matching data @@ -688,6 +732,7 @@ public void testDeleteByExpressionWithRemoveRows() { branch); assertThat(latestSnapshot(table, branch).sequenceNumber()).isEqualTo(1); + assertThat(latestSnapshot(table, branch).operation()).isEqualTo(DataOperations.OVERWRITE); assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(1); // deleting with a filter will also remove delete files that match because all matching data @@ -726,6 +771,7 @@ public void testDeleteDataFileWithRemoveRows() { long deltaSnapshotId = latestSnapshot(table, branch).snapshotId(); assertThat(latestSnapshot(table, branch).sequenceNumber()).isEqualTo(1); + assertThat(latestSnapshot(table, branch).operation()).isEqualTo(DataOperations.OVERWRITE); assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(1); // deleting a specific data file will not affect a delete file in v2 or less @@ -786,6 +832,7 @@ public void testFastAppendDoesNotRemoveStaleDeleteFiles() { long deltaSnapshotId = latestSnapshot(table, branch).snapshotId(); assertThat(latestSnapshot(table, branch).sequenceNumber()).isEqualTo(1); + assertThat(latestSnapshot(table, branch).operation()).isEqualTo(DataOperations.OVERWRITE); assertThat(table.ops().current().lastSequenceNumber()).isEqualTo(1); // deleting a specific data file will not affect a delete file