snazy commented on code in PR #8909:
URL: https://github.com/apache/iceberg/pull/8909#discussion_r1410794852


##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieCatalog.java:
##########
@@ -347,4 +327,73 @@ private TableIdentifier identifierWithoutTableReference(
   protected Map<String, String> properties() {
     return catalogOptions;
   }
+
+  @Override
+  protected ViewOperations newViewOps(TableIdentifier identifier) {
+    TableReference tr = parseTableReference(identifier);
+    return new NessieViewOperations(
+        ContentKey.of(
+            
org.projectnessie.model.Namespace.of(identifier.namespace().levels()), 
tr.getName()),
+        client.withReference(tr.getReference(), tr.getHash()),
+        fileIO);
+  }
+
+  @Override
+  public List<TableIdentifier> listViews(Namespace namespace) {
+    return client.listViews(namespace);
+  }
+
+  @Override
+  public boolean dropView(TableIdentifier identifier) {
+    TableReference tableReference = parseTableReference(identifier);
+    return client
+        .withReference(tableReference.getReference(), tableReference.getHash())
+        .dropView(identifierWithoutTableReference(identifier, tableReference), 
false);
+  }
+
+  @Override
+  public void renameView(TableIdentifier from, TableIdentifier to) {
+    renameContent(from, to, Content.Type.ICEBERG_VIEW);
+  }
+
+  private void renameContent(TableIdentifier from, TableIdentifier to, 
Content.Type type) {
+    TableReference fromTableReference = parseTableReference(from);
+    TableReference toTableReference = parseTableReference(to);
+    String fromReference =
+        fromTableReference.hasReference()
+            ? fromTableReference.getReference()
+            : client.getRef().getName();
+    String toReference =
+        toTableReference.hasReference()
+            ? toTableReference.getReference()
+            : client.getRef().getName();
+    Preconditions.checkArgument(
+        fromReference.equalsIgnoreCase(toReference),
+        "Cannot rename %s '%s' on reference '%s' to '%s' on reference '%s':"
+            + " source and target references must be the same.",
+        NessieUtil.contentTypeString(type).toLowerCase(),
+        fromTableReference.getName(),
+        fromReference,
+        toTableReference.getName(),
+        toReference);
+
+    TableIdentifier fromIdentifier =
+        NessieUtil.removeCatalogName(
+            identifierWithoutTableReference(from, fromTableReference), name());
+    TableIdentifier toIdentifier =
+        NessieUtil.removeCatalogName(identifierWithoutTableReference(to, 
toTableReference), name());
+
+    if (type == Content.Type.ICEBERG_TABLE) {

Review Comment:
   Overly complex: This if-else cascade and the method chains are confusing. 
Above it "consolidates" table+view renames to `renameContent()` to call 
specialized functions on `NessieIcebergClient` which then call a generic 
function.
   
   Similar to the `dropTable/View` above.



##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieTableOperations.java:
##########
@@ -132,74 +130,42 @@ protected void doRefresh() {
 
   @Override
   protected void doCommit(TableMetadata base, TableMetadata metadata) {
+    try {
+      Content content =
+          
client.getApi().getContent().key(key).reference(client.getReference()).get().get(key);
+      if (content != null) {

Review Comment:
   Still, why is this _always_ run and not only when a conflict happened?



##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieIcebergClient.java:
##########
@@ -136,15 +142,26 @@ private UpdateableReference loadReference(String 
requestedRef, String hash) {
   }
 
   public List<TableIdentifier> listTables(Namespace namespace) {
+    return listContents(namespace, Content.Type.ICEBERG_TABLE);
+  }
+
+  public List<TableIdentifier> listViews(Namespace namespace) {
+    return listContents(namespace, Content.Type.ICEBERG_VIEW);
+  }
+
+  private List<TableIdentifier> listContents(Namespace namespace, Content.Type 
type) {
     try {
       return withReference(api.getEntries()).get().getEntries().stream()
           .filter(namespacePredicate(namespace))
-          .filter(e -> Content.Type.ICEBERG_TABLE == e.getType())
+          .filter(e -> type == e.getType())

Review Comment:
   Should use `.equals` here, Content.Type is _not_ an enum



##########
nessie/src/test/java/org/apache/iceberg/nessie/BaseTestIceberg.java:
##########
@@ -180,6 +188,33 @@ protected Table createTable(TableIdentifier 
tableIdentifier, Schema schema) {
     return catalog.createTable(tableIdentifier, schema);
   }
 
+  protected View createView(NessieCatalog nessieCatalog, TableIdentifier 
tableIdentifier) {
+    createMissingNamespaces(tableIdentifier);

Review Comment:
   Why is this done twice?



##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieUtil.java:
##########
@@ -165,4 +180,95 @@ public static TableMetadata 
updateTableMetadataWithNessieSpecificProperties(
 
     return builder.discardChanges().build();
   }
+
+  public static ViewMetadata loadViewMetadata(

Review Comment:
   That similarity is IMO not a reason. Also not sure why Trino's related.



##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieViewOperations.java:
##########
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iceberg.nessie;
+
+import java.util.Map;
+import org.apache.iceberg.exceptions.AlreadyExistsException;
+import org.apache.iceberg.exceptions.NoSuchViewException;
+import org.apache.iceberg.io.FileIO;
+import org.apache.iceberg.view.BaseViewOperations;
+import org.apache.iceberg.view.ViewMetadata;
+import org.apache.iceberg.view.ViewMetadataParser;
+import org.projectnessie.client.http.HttpClientException;
+import org.projectnessie.error.NessieConflictException;
+import org.projectnessie.error.NessieNotFoundException;
+import org.projectnessie.model.Content;
+import org.projectnessie.model.ContentKey;
+import org.projectnessie.model.IcebergTable;
+import org.projectnessie.model.IcebergView;
+import org.projectnessie.model.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NessieViewOperations extends BaseViewOperations {

Review Comment:
   I don't understand the reason that two classes cant implement the same 
interface???



##########
nessie/src/main/java/org/apache/iceberg/nessie/NessieViewOperations.java:
##########
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iceberg.nessie;
+
+import org.apache.iceberg.exceptions.AlreadyExistsException;
+import org.apache.iceberg.exceptions.NoSuchViewException;
+import org.apache.iceberg.io.FileIO;
+import org.apache.iceberg.view.BaseViewOperations;
+import org.apache.iceberg.view.ViewMetadata;
+import org.apache.iceberg.view.ViewMetadataParser;
+import org.projectnessie.client.http.HttpClientException;
+import org.projectnessie.error.NessieConflictException;
+import org.projectnessie.error.NessieNotFoundException;
+import org.projectnessie.model.Content;
+import org.projectnessie.model.ContentKey;
+import org.projectnessie.model.IcebergTable;
+import org.projectnessie.model.IcebergView;
+import org.projectnessie.model.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NessieViewOperations extends BaseViewOperations {
+
+  private static final Logger LOG = 
LoggerFactory.getLogger(NessieViewOperations.class);
+
+  private final NessieIcebergClient client;
+  private final ContentKey key;
+  private final FileIO fileIO;
+  private IcebergView icebergView;
+
+  NessieViewOperations(ContentKey key, NessieIcebergClient client, FileIO 
fileIO) {
+    this.key = key;
+    this.client = client;
+    this.fileIO = fileIO;
+  }
+
+  @Override
+  public void doRefresh() {
+    try {
+      client.refresh();
+    } catch (NessieNotFoundException e) {
+      throw new RuntimeException(
+          String.format(
+              "Failed to refresh as ref '%s' is no longer valid.", 
client.getRef().getName()),
+          e);
+    }
+    String metadataLocation = null;
+    Reference reference = client.getRef().getReference();
+    try {
+      Content content = 
client.getApi().getContent().key(key).reference(reference).get().get(key);
+      LOG.debug("Content '{}' at '{}': {}", key, reference, content);
+      if (content == null) {
+        if (currentMetadataLocation() != null) {
+          throw new NoSuchViewException("View does not exist: %s in %s", key, 
reference);
+        }
+      } else {
+        this.icebergView =
+            content
+                .unwrap(IcebergView.class)
+                .orElseThrow(
+                    () -> {
+                      if (content instanceof IcebergTable) {
+                        return new AlreadyExistsException(
+                            "Table with same name already exists: %s in %s", 
key, reference);
+                      } else {
+                        return new AlreadyExistsException(
+                            "Cannot refresh Iceberg view: Nessie points to a 
non-Iceberg object for path: %s in %s",
+                            key, reference);
+                      }
+                    });
+        metadataLocation = icebergView.getMetadataLocation();
+      }
+    } catch (NessieNotFoundException ex) {
+      if (currentMetadataLocation() != null) {
+        throw new NoSuchViewException("View does not exist: %s in %s", key, 
reference);
+      }
+    }
+    refreshFromMetadataLocation(
+        metadataLocation,
+        null,
+        2,
+        location ->
+            NessieUtil.loadViewMetadata(
+                ViewMetadataParser.read(io().newInputFile(location)), 
location, reference));
+  }
+
+  @Override
+  public void doCommit(ViewMetadata base, ViewMetadata metadata) {
+    try {
+      Content content =
+          
client.getApi().getContent().key(key).reference(client.getReference()).get().get(key);

Review Comment:
   Same concern as for tables: This check is _only_ needed when a conflict 
happened - it should _not_ be in the good-case code-path. 



-- 
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: issues-unsubscr...@iceberg.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@iceberg.apache.org
For additional commands, e-mail: issues-h...@iceberg.apache.org

Reply via email to