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


##########
core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java:
##########
@@ -971,4 +996,250 @@ public void commitTransaction(SessionContext context, 
List<TableCommit> commits)
         headers(context),
         ErrorHandlers.tableCommitHandler());
   }
+
+  @Override
+  public List<TableIdentifier> listViews(SessionContext context, Namespace 
namespace) {
+    checkNamespaceIsValid(namespace);
+
+    ListTablesResponse response =
+        client.get(
+            paths.views(namespace),
+            ListTablesResponse.class,
+            headers(context),
+            ErrorHandlers.namespaceErrorHandler());
+    return response.identifiers();
+  }
+
+  @Override
+  public View loadView(SessionContext context, TableIdentifier identifier) {
+    checkViewIdentifierIsValid(identifier);
+
+    LoadViewResponse response =
+        client.get(
+            paths.view(identifier),
+            LoadViewResponse.class,
+            headers(context),
+            ErrorHandlers.viewErrorHandler());
+
+    AuthSession session = tableSession(response.config(), session(context));
+    ViewMetadata metadata = response.metadata();
+
+    RESTViewOperations ops =
+        new RESTViewOperations(
+            client,
+            paths.view(identifier),
+            session::headers,
+            tableFileIO(context, response.config()),
+            metadata);
+
+    trackFileIO(ops);
+
+    return new BaseView(ops, ViewUtil.fullViewName(name(), identifier));
+  }
+
+  @Override
+  public RESTViewBuilder buildView(SessionContext context, TableIdentifier 
identifier) {
+    return new RESTViewBuilder(context, identifier);
+  }
+
+  @Override
+  public boolean dropView(SessionContext context, TableIdentifier identifier) {
+    checkViewIdentifierIsValid(identifier);
+
+    try {
+      client.delete(
+          paths.view(identifier), null, headers(context), 
ErrorHandlers.viewErrorHandler());
+      return true;
+    } catch (NoSuchViewException e) {
+      return false;
+    }
+  }
+
+  @Override
+  public void renameView(SessionContext context, TableIdentifier from, 
TableIdentifier to) {
+    checkViewIdentifierIsValid(from);
+    checkViewIdentifierIsValid(to);
+
+    RenameTableRequest request =
+        
RenameTableRequest.builder().withSource(from).withDestination(to).build();
+
+    client.post(
+        paths.renameView(), request, null, headers(context), 
ErrorHandlers.viewErrorHandler());
+  }
+
+  private class RESTViewBuilder implements ViewBuilder {
+    private final SessionContext context;
+    private final TableIdentifier identifier;
+    private final ImmutableViewVersion.Builder viewVersionBuilder = 
ImmutableViewVersion.builder();
+    private final Map<String, String> properties = Maps.newHashMap();
+    private final List<ViewRepresentation> representations = 
Lists.newArrayList();
+    private Namespace defaultNamespace = null;
+    private Schema schema = null;
+
+    private RESTViewBuilder(SessionContext context, TableIdentifier 
identifier) {
+      checkViewIdentifierIsValid(identifier);
+      this.identifier = identifier;
+      this.context = context;
+    }
+
+    @Override
+    public ViewBuilder withSchema(Schema newSchema) {
+      this.schema = newSchema;
+      viewVersionBuilder.schemaId(newSchema.schemaId());
+      return this;
+    }
+
+    @Override
+    public ViewBuilder withQuery(String dialect, String sql) {
+      representations.add(
+          
ImmutableSQLViewRepresentation.builder().dialect(dialect).sql(sql).build());
+      return this;
+    }
+
+    @Override
+    public ViewBuilder withDefaultCatalog(String defaultCatalog) {
+      viewVersionBuilder.defaultCatalog(defaultCatalog);
+      return this;
+    }
+
+    @Override
+    public ViewBuilder withDefaultNamespace(Namespace namespace) {
+      this.defaultNamespace = namespace;
+      return this;
+    }
+
+    @Override
+    public ViewBuilder withProperties(Map<String, String> newProperties) {
+      this.properties.putAll(newProperties);
+      return this;
+    }
+
+    @Override
+    public ViewBuilder withProperty(String key, String value) {
+      this.properties.put(key, value);
+      return this;
+    }
+
+    @Override
+    public View create() {
+      Preconditions.checkState(
+          !representations.isEmpty(), "Cannot create view without specifying a 
query");
+      Preconditions.checkState(null != schema, "Cannot create view without 
specifying schema");
+      Preconditions.checkState(
+          null != defaultNamespace, "Cannot create view without specifying a 
default namespace");
+
+      ViewVersion viewVersion =
+          viewVersionBuilder
+              .versionId(1)
+              .timestampMillis(System.currentTimeMillis())
+              .addAllRepresentations(representations)
+              .defaultNamespace(defaultNamespace)
+              .putSummary("operation", "create")
+              .build();
+
+      ViewMetadata viewMetadata =
+          ViewMetadata.builder()
+              .setProperties(properties)
+              .setLocation("dummy")
+              .setCurrentVersion(viewVersion, schema)
+              .build();
+
+      CreateViewRequest request =
+          ImmutableCreateViewRequest.builder()
+              .metadata(viewMetadata)
+              .name(identifier.name())
+              .build();
+
+      LoadViewResponse response =
+          client.post(
+              paths.views(identifier.namespace()),
+              request,
+              LoadViewResponse.class,
+              headers(context),
+              ErrorHandlers.viewErrorHandler());
+
+      return viewFromResponse(response);
+    }
+
+    @Override
+    public View replace() {
+      Preconditions.checkState(
+          !representations.isEmpty(), "Cannot replace view without specifying 
a query");
+      Preconditions.checkState(null != schema, "Cannot replace view without 
specifying schema");
+      Preconditions.checkState(
+          null != defaultNamespace, "Cannot replace view without specifying a 
default namespace");
+
+      LoadViewResponse response =
+          client.get(
+              paths.view(identifier),
+              LoadViewResponse.class,
+              headers(context),
+              ErrorHandlers.viewErrorHandler());
+
+      ViewMetadata metadata = response.metadata();
+
+      int maxVersionId =
+          metadata.versions().stream()
+              .map(ViewVersion::versionId)
+              .max(Integer::compareTo)
+              .orElseGet(metadata::currentVersionId);
+
+      ViewVersion viewVersion =
+          viewVersionBuilder
+              .versionId(maxVersionId + 1)
+              .timestampMillis(System.currentTimeMillis())
+              .addAllRepresentations(representations)
+              .defaultNamespace(defaultNamespace)
+              .putSummary("operation", "replace")
+              .build();
+
+      ViewMetadata replacement =
+          ViewMetadata.buildFrom(metadata)
+              .setProperties(properties)
+              .setCurrentVersion(viewVersion, schema)
+              .build();
+
+      UpdateTableRequest request =
+          UpdateTableRequest.create(identifier, ImmutableList.of(), 
replacement.changes());
+
+      response =
+          client.post(
+              paths.view(identifier),
+              request,
+              LoadViewResponse.class,
+              headers(context),
+              ErrorHandlers.viewErrorHandler());
+
+      return viewFromResponse(response);
+    }
+
+    private BaseView viewFromResponse(LoadViewResponse response) {
+      AuthSession session = tableSession(response.config(), session(context));
+      RESTViewOperations ops =
+          new RESTViewOperations(
+              client,
+              paths.view(identifier),
+              session::headers,
+              tableFileIO(context, response.config()),
+              response.metadata());
+
+      trackFileIO(ops);
+
+      return new BaseView(ops, ViewUtil.fullViewName(name(), identifier));
+    }
+
+    @Override
+    public View createOrReplace() {
+      try {
+        client.get(
+            paths.view(identifier),
+            LoadViewResponse.class,
+            headers(context),
+            ErrorHandlers.viewErrorHandler());
+        return replace();

Review Comment:
   Like the other builder, this should not load the view twice just to 
determine whether to use replace or create. The replace method should be 
refactored to accept a LoadViewResponse.



-- 
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