diff --git a/.palantir/revapi.yml b/.palantir/revapi.yml index d6f09d177ddf..ffbcbeee156e 100644 --- a/.palantir/revapi.yml +++ b/.palantir/revapi.yml @@ -40,6 +40,9 @@ acceptedBreaks: - code: "java.method.removed" old: "method org.apache.iceberg.RowDelta org.apache.iceberg.RowDelta::validateNoConflictingAppends(org.apache.iceberg.expressions.Expression)" justification: "Deprecations for 1.0 release" + - code: "java.method.addedToInterface" + new: "method org.apache.iceberg.TableScan org.apache.iceberg.TableScan::useRef(java.lang.String)" + justification: "Adding table scan APIs to support scanning from refs" release-base-0.13.0: org.apache.iceberg:iceberg-api: - code: "java.class.defaultSerializationChanged" diff --git a/api/src/main/java/org/apache/iceberg/TableScan.java b/api/src/main/java/org/apache/iceberg/TableScan.java index 5f55b82d9682..ebff7ad51bf8 100644 --- a/api/src/main/java/org/apache/iceberg/TableScan.java +++ b/api/src/main/java/org/apache/iceberg/TableScan.java @@ -39,13 +39,25 @@ public interface TableScan extends Scan table.newScan().useSnapshot(table.currentSnapshot().snapshotId()).useRef("tagB")); + } + + @Test + public void testSettingSnapshotWhenRefSetFails() { + table.newFastAppend().appendFile(FILE_A).commit(); + Snapshot snapshotA = table.currentSnapshot(); + table.newFastAppend().appendFile(FILE_B).commit(); + table.manageSnapshots().createTag("tagB", table.currentSnapshot().snapshotId()).commit(); + + AssertHelpers.assertThrows( + "Should throw when attempting to use a snapshot for scanning when a ref is set", + IllegalArgumentException.class, + "Cannot override snapshot, already set snapshot id=2", + () -> table.newScan().useRef("tagB").useSnapshot(snapshotA.snapshotId())); + } + + @Test + public void testBranchTimeTravelFails() { + table.newFastAppend().appendFile(FILE_A).appendFile(FILE_B).commit(); + table + .manageSnapshots() + .createBranch("testBranch", table.currentSnapshot().snapshotId()) + .commit(); + AssertHelpers.assertThrows( + "Should throw when attempting to use a snapshot for scanning when a ref is set", + IllegalArgumentException.class, + "Cannot override snapshot, already set snapshot id=1", + () -> table.newScan().useRef("testBranch").asOfTime(System.currentTimeMillis())); + } + + @Test + public void testSettingMultipleRefsFails() { + table.newFastAppend().appendFile(FILE_A).commit(); + table.manageSnapshots().createTag("tagA", table.currentSnapshot().snapshotId()).commit(); + table.newFastAppend().appendFile(FILE_B).commit(); + table.manageSnapshots().createTag("tagB", table.currentSnapshot().snapshotId()).commit(); + + AssertHelpers.assertThrows( + "Should throw when attempting to use multiple refs", + IllegalArgumentException.class, + "Cannot override ref, already set snapshot id=2", + () -> table.newScan().useRef("tagB").useRef("tagA")); + } + + @Test + public void testSettingInvalidRefFails() { + AssertHelpers.assertThrows( + "Should throw when attempting to use an invalid ref for scanning", + IllegalArgumentException.class, + "Cannot find ref nonexisting", + () -> table.newScan().useRef("nonexisting")); + } + + private void validateExpectedFileScanTasks( + TableScan scan, List expectedFileScanPaths) throws IOException { + try (CloseableIterable scanTasks = scan.planFiles()) { + Assert.assertEquals(expectedFileScanPaths.size(), Iterables.size(scanTasks)); + List actualFiles = Lists.newArrayList(); + scanTasks.forEach(task -> actualFiles.add(task.file().path())); + Assert.assertTrue(actualFiles.containsAll(expectedFileScanPaths)); + } + } }