Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ public void testOverwritePartitionSerializableIsolation() throws Exception {
Table table = validationCatalog.loadTable(tableIdent);
final long snapshotId = table.currentSnapshot().snapshotId();

List<SimpleRecord> records = Lists.newArrayList(
new SimpleRecord(1, "a"));
List<SimpleRecord> records = Lists.newArrayList(new SimpleRecord(1, "a"));
spark.createDataFrame(records, SimpleRecord.class).writeTo(tableName).append();

// Validating from previous snapshot finds conflicts
Expand Down Expand Up @@ -165,6 +164,22 @@ public void testOverwritePartitionSnapshotIsolation2() throws Exception {
.overwritePartitions();
}

@Test
public void testOverwritePartitionSnapshotIsolation3() throws Exception {
Table table = validationCatalog.loadTable(tableIdent);
final long snapshotId = table.currentSnapshot().snapshotId();

List<SimpleRecord> records = Lists.newArrayList(new SimpleRecord(1, "a"));
spark.createDataFrame(records, SimpleRecord.class).writeTo(tableName).append();

// Validation should not find conflicting data file in snapshot isolation mode
Dataset<Row> conflictingDf = spark.createDataFrame(records, SimpleRecord.class);
conflictingDf.writeTo(tableName)
.option(SparkWriteOptions.VALIDATE_FROM_SNAPSHOT_ID, String.valueOf(snapshotId))
.option(SparkWriteOptions.ISOLATION_LEVEL, IsolationLevel.SNAPSHOT.toString())
.overwritePartitions();
}

@Test
public void testOverwritePartitionNoSnapshotIdValidation() throws Exception {
Table table = validationCatalog.loadTable(tableIdent);
Expand All @@ -173,7 +188,7 @@ public void testOverwritePartitionNoSnapshotIdValidation() throws Exception {
new SimpleRecord(1, "a"));
spark.createDataFrame(records, SimpleRecord.class).writeTo(tableName).append();

// Validating from previous snapshot finds conflicts
// Validating from null snapshot is equivalent to validating from beginning
Dataset<Row> conflictingDf = spark.createDataFrame(records, SimpleRecord.class);
AssertHelpers.assertThrowsCause("Conflicting deleted data files should throw exception",
ValidationException.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,17 +277,15 @@ public void commit(WriterCommitMessage[] messages) {
IsolationLevel isolationLevel = writeConf.isolationLevel();
Long validateFromSnapshotId = writeConf.validateFromSnapshotId();

if (isolationLevel != null && validateFromSnapshotId != null) {
dynamicOverwrite.validateFromSnapshot(validateFromSnapshotId);
}

if (isolationLevel == SERIALIZABLE) {
if (validateFromSnapshotId != null) {
dynamicOverwrite.validateFromSnapshot(validateFromSnapshotId);
}
dynamicOverwrite.validateNoConflictingData();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: It seems like this one is repeated in both cases. Since there's no existing else clause, it's probably not worth reducing the duplication as we might need more if statements but thought I'd call it out.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks yea good catch, I was thinking to leave it here to make it more clear in each validation mode what we are validating, and maybe there are future modes where we do not do this as you said. As opposed to the validationSnapshotId which is the basis of all validations.

dynamicOverwrite.validateNoConflictingDeletes();

} else if (isolationLevel == SNAPSHOT) {
if (validateFromSnapshotId != null) {
dynamicOverwrite.validateFromSnapshot(validateFromSnapshotId);
}
dynamicOverwrite.validateNoConflictingDeletes();
}

Expand Down