mchades commented on code in PR #10879:
URL: https://github.com/apache/gravitino/pull/10879#discussion_r3151942647


##########
core/src/main/java/org/apache/gravitino/storage/relational/mapper/ViewMetaMapper.java:
##########
@@ -21,26 +21,69 @@
 
 import java.util.List;
 import org.apache.gravitino.storage.relational.po.ViewPO;
+import org.apache.gravitino.storage.relational.po.ViewVersionInfoPO;
 import org.apache.ibatis.annotations.DeleteProvider;
 import org.apache.ibatis.annotations.InsertProvider;
+import org.apache.ibatis.annotations.One;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.ResultMap;
+import org.apache.ibatis.annotations.Results;
+import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.SelectProvider;
 import org.apache.ibatis.annotations.UpdateProvider;
 
-/**
- * A MyBatis Mapper for view meta operation SQLs.
- *
- * <p>This interface class is a specification defined by MyBatis. It requires 
this interface class
- * to identify the corresponding SQLs for execution. We can write SQLs in an 
additional XML file, or
- * write SQLs with annotations in this interface Mapper. See: <a
- * href="https://mybatis.org/mybatis-3/getting-started.html";></a>
- */
+/** A MyBatis Mapper for view meta operation SQLs. */
 public interface ViewMetaMapper {
   String TABLE_NAME = "view_meta";
-
+  String VERSION_TABLE_NAME = "view_version_info";
+
+  @Results(
+      id = "mapToViewVersionInfoPO",
+      value = {
+        @Result(property = "id", column = "id", id = true),
+        @Result(property = "metalakeId", column = "version_metalake_id"),
+        @Result(property = "catalogId", column = "version_catalog_id"),
+        @Result(property = "schemaId", column = "version_schema_id"),
+        @Result(property = "viewId", column = "version_view_id"),
+        @Result(property = "version", column = "version"),
+        @Result(property = "viewComment", column = "view_comment"),
+        @Result(property = "columns", column = "columns"),
+        @Result(property = "properties", column = "properties"),
+        @Result(property = "defaultCatalog", column = "default_catalog"),
+        @Result(property = "defaultSchema", column = "default_schema"),
+        @Result(property = "representations", column = "representations"),
+        @Result(property = "auditInfo", column = "version_audit_info"),
+        @Result(property = "deletedAt", column = "version_deleted_at")
+      })
+  @Select("SELECT 1") // Dummy SQL to avoid MyBatis error, never be executed
+  ViewVersionInfoPO mapToViewVersionInfoPO();
+
+  @Results(
+      id = "viewPOResultMap",
+      value = {
+        @Result(property = "viewId", column = "view_id", id = true),
+        @Result(property = "viewName", column = "view_name"),
+        @Result(property = "metalakeId", column = "metalake_id"),
+        @Result(property = "catalogId", column = "catalog_id"),
+        @Result(property = "schemaId", column = "schema_id"),
+        @Result(property = "currentVersion", column = "current_version"),
+        @Result(property = "lastVersion", column = "last_version"),
+        @Result(property = "auditInfo", column = "audit_info"),
+        @Result(property = "deletedAt", column = "deleted_at"),
+        @Result(
+            property = "viewVersionInfoPO",
+            javaType = ViewVersionInfoPO.class,
+            column =
+                
"{id,version_metalake_id,version_catalog_id,version_schema_id,version_view_id,"
+                    + 
"version,view_comment,columns,properties,default_catalog,default_schema,"
+                    + "representations,version_audit_info,version_deleted_at}",
+            one = @One(resultMap = "mapToViewVersionInfoPO"))
+      })

Review Comment:
   Checked this against the current runtime rather than changing it 
speculatively. `TestViewMetaService` still passes for insert/get/list/update on 
the supported relational backends, so this mapping is working as-is in the 
environments this PR targets. Since this PR is scoped to the ViewEntity storage 
changes, I am leaving the mapper shape unchanged here.



##########
core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java:
##########
@@ -158,104 +151,81 @@ public GenericEntity getViewByIdentifier(NameIdentifier 
identifier) {
       metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
       baseMetricName = "insertViewFromEntity")
   public void insertView(GenericEntity entity, boolean overwrite) throws 
IOException {
-    Namespace namespace = entity.namespace();
-    NamespaceUtil.checkView(namespace);
-
-    ViewPO.Builder builder = createViewPOBuilder(namespace);
-    ViewPO viewPO =
-        builder
-            .withViewId(entity.id())
-            .withViewName(entity.name())
-            .withCurrentVersion(1L)
-            .withLastVersion(1L)
-            .withDeletedAt(0L)
+    NamespaceUtil.checkView(entity.namespace());
+
+    ViewEntity viewEntity =
+        ViewEntity.builder()
+            .withId(entity.id())
+            .withName(entity.name())
+            .withNamespace(entity.namespace())
+            .withColumns(new Column[0])
+            .withRepresentations(
+                new Representation[] {
+                  
SQLRepresentation.builder().withDialect("unknown").withSql("placeholder").build()
+                })
+            .withAuditInfo(AuditInfo.EMPTY)
             .build();
-
-    insertView(viewPO, overwrite);
+    insertView(viewEntity, overwrite);
   }
 
-  /**
-   * Update a view.
-   *
-   * @param ident The identifier of the view.
-   * @param updater The function to update the view entity.
-   * @return The updated GenericEntity.
-   * @throws IOException If an I/O error occurs.
-   */
   @Monitored(
       metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
       baseMetricName = "updateViewByIdentifier")
-  public <E extends HasIdentifier> GenericEntity updateView(
+  public <E extends Entity & HasIdentifier> ViewEntity updateView(
       NameIdentifier ident, Function<E, E> updater) throws IOException {
     NameIdentifierUtil.checkView(ident);
 
     ViewPO oldViewPO = viewPOFetcher().apply(ident);
+    ViewEntity oldViewEntity = fromViewPO(oldViewPO, ident.namespace());
+    ViewEntity newEntity = (ViewEntity) updater.apply((E) oldViewEntity);
+    Preconditions.checkArgument(
+        Objects.equals(oldViewEntity.id(), newEntity.id()),
+        "The updated view entity id: %s should be same with the entity id 
before: %s",
+        newEntity.id(),
+        oldViewEntity.id());
 
-    GenericEntity oldEntity =
-        GenericEntity.builder()
-            .withId(oldViewPO.getViewId())
-            .withName(oldViewPO.getViewName())
-            .withNamespace(ident.namespace())
-            .withEntityType(Entity.EntityType.VIEW)
-            .build();
-
-    GenericEntity newEntity = (GenericEntity) updater.apply((E) oldEntity);
-
-    // Check if the namespace (schema) has changed and resolve new schema ID 
if needed
-    boolean isSchemaChanged =
-        newEntity.namespace() != null && 
!newEntity.namespace().equals(ident.namespace());
-    Long schemaId =
-        isSchemaChanged
-            ? EntityIdService.getEntityId(
-                NameIdentifier.of(newEntity.namespace().levels()), 
Entity.EntityType.SCHEMA)
-            : oldViewPO.getSchemaId();
-
-    ViewPO newViewPO =
-        ViewPO.builder()
-            .withViewId(oldViewPO.getViewId())
-            .withViewName(newEntity.name())
-            .withMetalakeId(oldViewPO.getMetalakeId())
-            .withCatalogId(oldViewPO.getCatalogId())
-            .withSchemaId(schemaId)
-            .withDeletedAt(oldViewPO.getDeletedAt())
-            .withLastVersion(oldViewPO.getLastVersion())
-            .withCurrentVersion(oldViewPO.getCurrentVersion())
-            .build();
-
-    updateView(oldViewPO, newViewPO);
-
-    return newEntity;
+    try {
+      ViewPO newViewPO = updateViewPO(oldViewPO, newEntity);
+      SessionUtils.doMultipleWithCommit(
+          () ->
+              SessionUtils.doWithoutCommit(
+                  ViewVersionInfoMapper.class,
+                  mapper -> 
mapper.insertViewVersionInfo(newViewPO.getViewVersionInfoPO())),
+          () ->
+              SessionUtils.doWithoutCommit(
+                  ViewMetaMapper.class, mapper -> 
mapper.updateViewMeta(newViewPO, oldViewPO)));
+      return newEntity;
+    } catch (RuntimeException re) {
+      ExceptionUtils.checkSQLException(
+          re, Entity.EntityType.VIEW, newEntity.nameIdentifier().toString());
+      throw re;
+    }
   }
 
-  /**
-   * Delete a view by identifier.
-   *
-   * @param ident The identifier of the view.
-   * @return true if the view was deleted, false otherwise.
-   */
   @Monitored(
       metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
       baseMetricName = "deleteViewByIdentifier")
   public boolean deleteView(NameIdentifier ident) {
     NameIdentifierUtil.checkView(ident);
-
     ViewPO viewPO = viewPOFetcher().apply(ident);
     return deleteView(viewPO.getViewId());
   }
 
-  private ViewPO getViewPOBySchemaIdAndName(Long schemaId, String viewName) {
-    ViewPO viewPO =
-        SessionUtils.getWithoutCommit(
+  @Monitored(
+      metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
+      baseMetricName = "deleteViewMetasByLegacyTimeline")
+  public int deleteViewMetasByLegacyTimeline(Long legacyTimeline, int limit) {
+    int versionDeletedCount =
+        SessionUtils.doWithCommitAndFetchResult(
+            ViewVersionInfoMapper.class,
+            mapper -> 
mapper.deleteViewVersionsByLegacyTimeline(legacyTimeline, limit));
+
+    int metaDeletedCount =
+        SessionUtils.doWithCommitAndFetchResult(
             ViewMetaMapper.class,
-            mapper -> mapper.selectViewMetaBySchemaIdAndName(schemaId, 
viewName));
+            mapper -> mapper.deleteViewMetasByLegacyTimeline(legacyTimeline, 
limit));
 
-    if (viewPO == null) {
-      throw new NoSuchEntityException(
-          NoSuchEntityException.NO_SUCH_ENTITY_MESSAGE,
-          Entity.EntityType.VIEW.name().toLowerCase(),
-          viewName);
-    }
-    return viewPO;
+    return versionDeletedCount + metaDeletedCount;
   }

Review Comment:
   This observation is correct in isolation, but the same delete-budget pattern 
is already used in the other relational meta services as well. I do not want to 
special-case view cleanup in this PR and make it diverge from 
table/fileset/function behavior. If we want a single total budget plus one 
transaction, that should be handled as a broader follow-up across the shared 
pattern.



##########
core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java:
##########
@@ -158,104 +151,81 @@ public GenericEntity getViewByIdentifier(NameIdentifier 
identifier) {
       metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
       baseMetricName = "insertViewFromEntity")
   public void insertView(GenericEntity entity, boolean overwrite) throws 
IOException {
-    Namespace namespace = entity.namespace();
-    NamespaceUtil.checkView(namespace);
-
-    ViewPO.Builder builder = createViewPOBuilder(namespace);
-    ViewPO viewPO =
-        builder
-            .withViewId(entity.id())
-            .withViewName(entity.name())
-            .withCurrentVersion(1L)
-            .withLastVersion(1L)
-            .withDeletedAt(0L)
+    NamespaceUtil.checkView(entity.namespace());
+
+    ViewEntity viewEntity =
+        ViewEntity.builder()
+            .withId(entity.id())
+            .withName(entity.name())
+            .withNamespace(entity.namespace())
+            .withColumns(new Column[0])
+            .withRepresentations(
+                new Representation[] {
+                  
SQLRepresentation.builder().withDialect("unknown").withSql("placeholder").build()
+                })
+            .withAuditInfo(AuditInfo.EMPTY)
             .build();
-
-    insertView(viewPO, overwrite);
+    insertView(viewEntity, overwrite);
   }
 
-  /**
-   * Update a view.
-   *
-   * @param ident The identifier of the view.
-   * @param updater The function to update the view entity.
-   * @return The updated GenericEntity.
-   * @throws IOException If an I/O error occurs.
-   */
   @Monitored(
       metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME,
       baseMetricName = "updateViewByIdentifier")
-  public <E extends HasIdentifier> GenericEntity updateView(
+  public <E extends Entity & HasIdentifier> ViewEntity updateView(
       NameIdentifier ident, Function<E, E> updater) throws IOException {
     NameIdentifierUtil.checkView(ident);
 
     ViewPO oldViewPO = viewPOFetcher().apply(ident);
+    ViewEntity oldViewEntity = fromViewPO(oldViewPO, ident.namespace());
+    ViewEntity newEntity = (ViewEntity) updater.apply((E) oldViewEntity);

Review Comment:
   The type-safety concern is valid, but this updater signature currently 
follows the same pattern used by the other relational meta services too. For 
this PR I fixed the concrete runtime mismatch on the view rename path instead 
of tightening only the view service API and leaving the rest of the pattern 
inconsistent. I prefer to keep that signature change as a broader follow-up if 
we decide to apply it across table/fileset/function/view together.



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

Reply via email to