rdblue commented on code in PR #8147:
URL: https://github.com/apache/iceberg/pull/8147#discussion_r1296153384


##########
core/src/main/java/org/apache/iceberg/view/ViewMetadata.java:
##########
@@ -117,13 +128,187 @@ default ViewMetadata checkAndNormalize() {
           ViewProperties.VERSION_HISTORY_SIZE,
           versionHistorySizeToKeep);
     } else if (versions().size() > versionHistorySizeToKeep) {
-      List<ViewVersion> versions =
+      List<ViewVersion> versionsToKeep =
           versions().subList(versions().size() - versionHistorySizeToKeep, 
versions().size());
-      List<ViewHistoryEntry> history =
+      List<ViewHistoryEntry> historyToKeep =
           history().subList(history().size() - versionHistorySizeToKeep, 
history().size());
-      return 
ImmutableViewMetadata.builder().from(this).versions(versions).history(history).build();
+      List<MetadataUpdate> changesToKeep = Lists.newArrayList(changes());
+      Set<MetadataUpdate.AddViewVersion> toRemove =
+          changesToKeep.stream()
+              .filter(update -> update instanceof 
MetadataUpdate.AddViewVersion)
+              .map(update -> (MetadataUpdate.AddViewVersion) update)
+              .filter(
+                  update ->
+                      update.viewVersion().versionId() != currentVersionId()
+                          && !versionsToKeep.contains(update.viewVersion()))
+              .collect(Collectors.toSet());
+      changesToKeep.removeAll(toRemove);
+
+      return ImmutableViewMetadata.of(
+          formatVersion(),
+          location(),
+          currentSchemaId(),
+          schemas(),
+          currentVersionId(),
+          versionsToKeep,
+          historyToKeep,
+          properties(),
+          changesToKeep);
     }
 
     return this;
   }
+
+  static Builder builder() {
+    return new Builder();
+  }
+
+  static Builder buildFrom(ViewMetadata base) {
+    return new Builder(base);
+  }
+
+  class Builder {
+    private int formatVersion = DEFAULT_VIEW_FORMAT_VERSION;
+    private String location;
+    private Integer currentSchemaId;
+    private List<Schema> schemas = Lists.newArrayList();
+    private int currentVersionId;
+    private List<ViewVersion> versions = Lists.newArrayList();
+    private List<ViewHistoryEntry> history = Lists.newArrayList();
+    private Map<String, String> properties = Maps.newHashMap();
+    private List<MetadataUpdate> changes = Lists.newArrayList();
+
+    private Builder() {}
+
+    private Builder(ViewMetadata base) {
+      this.formatVersion = base.formatVersion();
+      this.location = base.location();
+      this.currentSchemaId = base.currentSchemaId();
+      this.schemas = Lists.newArrayList(base.schemas());
+      this.currentVersionId = base.currentVersionId();
+      this.versions = Lists.newArrayList(base.versions());
+      this.history = Lists.newArrayList(base.history());
+      this.properties = Maps.newHashMap(base.properties());
+      this.changes = Lists.newArrayList(base.changes());
+    }
+
+    public Builder upgradeFormatVersion(int newFormatVersion) {
+      Preconditions.checkArgument(
+          newFormatVersion >= this.formatVersion,
+          "Cannot downgrade v%s view to v%s",
+          formatVersion,
+          newFormatVersion);
+
+      if (this.formatVersion == newFormatVersion) {
+        return this;
+      }
+
+      this.formatVersion = newFormatVersion;
+      this.changes.add(new 
MetadataUpdate.UpgradeFormatVersion(newFormatVersion));
+      return this;
+    }
+
+    public Builder setLocation(String newLocation) {
+      if (null != this.location && this.location.equals(newLocation)) {
+        return this;
+      }
+
+      this.location = newLocation;
+      this.changes.add(new MetadataUpdate.SetLocation(newLocation));
+      return this;
+    }
+
+    public Builder setCurrentVersionId(int newVersionId) {

Review Comment:
   @nastra, I think this needs to be done here for the reasons we talked about.
   
   > it should not affect and should not cause any issues when re-applying 
SetCurrentViewVersion, because that then translates to the same Builder calls 
that were done to cause the changes in the first place
   
   This is a mistaken assumption. There is no guarantee that a REST catalog 
service is using this code. We cannot assume things like that and should always 
produce requests that are reasonable and correct.
   
   > this would require to always set the list of versions first on the Builder 
before one would be able to call setCurrentVersionId(), which would result in 
awkward API behavior.
   
   Many other builders work this way so I don't think it is too awkward. When 
there are no dependencies between calls then allowing an arbitrary order is 
definitely a best practice. But when there are dependencies it's reasonable to 
expect that a version has been added before it is referenced.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to