From 08d7d8564c1a311116949d561fc122ee7c138f09 Mon Sep 17 00:00:00 2001 From: Eduard Tudenhoefner Date: Tue, 17 Sep 2024 11:16:43 +0200 Subject: [PATCH] Core: Update metadata location without updating lastUpdatedMillis Using `TableMetadata.buildFrom(metadata).withMetadataLocation(metadataLocation).build()` would do the following things: - update `lastUpdatedMillis` - write a new `metadata-log` entry However, in `LoadTableResponse` the goal is to only update the metadata location without updating the two mentioned things above. updates --- .../org/apache/iceberg/TableMetadata.java | 9 +++++ .../org/apache/iceberg/TestTableMetadata.java | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/core/src/main/java/org/apache/iceberg/TableMetadata.java b/core/src/main/java/org/apache/iceberg/TableMetadata.java index c0bb16bc109d..d20dd59d2b97 100644 --- a/core/src/main/java/org/apache/iceberg/TableMetadata.java +++ b/core/src/main/java/org/apache/iceberg/TableMetadata.java @@ -966,6 +966,15 @@ private Builder(TableMetadata base) { public Builder withMetadataLocation(String newMetadataLocation) { this.metadataLocation = newMetadataLocation; + if (null != base) { + // carry over lastUpdatedMillis from base and set previousFileLocation to null to avoid + // writing a new metadata log entry + // this is safe since setting metadata location doesn't cause any changes and no other + // changes can be added when metadata location is configured + this.lastUpdatedMillis = base.lastUpdatedMillis(); + this.previousFileLocation = null; + } + return this; } diff --git a/core/src/test/java/org/apache/iceberg/TestTableMetadata.java b/core/src/test/java/org/apache/iceberg/TestTableMetadata.java index bcde7a7f31d3..5ada35765773 100644 --- a/core/src/test/java/org/apache/iceberg/TestTableMetadata.java +++ b/core/src/test/java/org/apache/iceberg/TestTableMetadata.java @@ -1685,4 +1685,38 @@ public void testV3TimestampNanoTypeSupport() { ImmutableMap.of(), 3); } + + @Test + public void onlyMetadataLocationIsUpdatedWithoutTimestampAndMetadataLogEntry() { + String uuid = "386b9f01-002b-4d8c-b77f-42c3fd3b7c9b"; + TableMetadata metadata = + TableMetadata.buildFromEmpty() + .assignUUID(uuid) + .setLocation("location") + .setCurrentSchema(TEST_SCHEMA, 3) + .addPartitionSpec(PartitionSpec.unpartitioned()) + .addSortOrder(SortOrder.unsorted()) + .discardChanges() + .withMetadataLocation("original-metadata-location") + .build(); + + assertThat(metadata.previousFiles()).isEmpty(); + assertThat(metadata.metadataFileLocation()).isEqualTo("original-metadata-location"); + + // this will only update the metadata location without writing a new metadata log entry or + // updating lastUpdatedMillis + TableMetadata newMetadata = + TableMetadata.buildFrom(metadata).withMetadataLocation("new-metadata-location").build(); + assertThat(newMetadata.lastUpdatedMillis()).isEqualTo(metadata.lastUpdatedMillis()); + assertThat(newMetadata.metadataFileLocation()).isEqualTo("new-metadata-location"); + assertThat(newMetadata.previousFiles()).isEmpty(); + + TableMetadata updatedMetadata = + TableMetadata.buildFrom(newMetadata) + .withMetadataLocation("updated-metadata-location") + .build(); + assertThat(updatedMetadata.lastUpdatedMillis()).isEqualTo(newMetadata.lastUpdatedMillis()); + assertThat(updatedMetadata.metadataFileLocation()).isEqualTo("updated-metadata-location"); + assertThat(updatedMetadata.previousFiles()).isEmpty(); + } }