This is an automated email from the ASF dual-hosted git repository.

roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new bc48893849 [#9746][followup]fix(core): Fix view schema_id not updated 
during cross-namespace rename (#10013)
bc48893849 is described below

commit bc488938497d784ecd147944f579fe8254195ebf
Author: Bharath Krishna <[email protected]>
AuthorDate: Tue Feb 17 19:45:32 2026 +0530

    [#9746][followup]fix(core): Fix view schema_id not updated during 
cross-namespace rename (#10013)
    
    ### What changes were proposed in this pull request?
    
    Fix a bug in the view entity backend where `schema_id` was not being
    updated when a view is renamed across namespaces (schemas).
    
    ### Why are the changes needed?
    
    
    When a view is renamed from one schema to another (e.g.,
    `schema1.myview` → `schema2.myview`), the `schema_id` foreign key in the
    `view_meta` table remained unchanged. This caused:
    - Entity lookups by the new `NameIdentifier` to fail (wrong schema_id)
    - Ownership queries to return empty results
    - Can cause authorization checks to fail
    
    
    Fix: #9746
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. This fixes a bug in internal metadata management that would have
    caused errors during cross-namespace view renames.
    
    ### How was this patch tested?
    
    Unit test
---
 .../provider/base/ViewMetaBaseSQLProvider.java     |  1 +
 .../relational/service/ViewMetaService.java        | 12 +++++-
 .../relational/service/TestViewMetaService.java    | 43 ++++++++++++++++++++++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ViewMetaBaseSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ViewMetaBaseSQLProvider.java
index 7f72dba7f3..ca7efd6a79 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ViewMetaBaseSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ViewMetaBaseSQLProvider.java
@@ -147,6 +147,7 @@ public class ViewMetaBaseSQLProvider {
     return "UPDATE "
         + TABLE_NAME
         + " SET view_name = #{newViewMeta.viewName}, "
+        + " schema_id = #{newViewMeta.schemaId}, "
         + " current_version = #{newViewMeta.currentVersion}, "
         + " last_version = #{newViewMeta.lastVersion}, "
         + " deleted_at = #{newViewMeta.deletedAt} "
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java
index a64d85e0d8..9784401aae 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ViewMetaService.java
@@ -195,18 +195,28 @@ public class ViewMetaService {
         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(oldViewPO.getSchemaId())
+            .withSchemaId(schemaId)
             .withDeletedAt(oldViewPO.getDeletedAt())
             .withLastVersion(oldViewPO.getLastVersion())
             .withCurrentVersion(oldViewPO.getCurrentVersion())
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestViewMetaService.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestViewMetaService.java
index 327e5f66af..d221426b46 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestViewMetaService.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestViewMetaService.java
@@ -167,6 +167,49 @@ public class TestViewMetaService extends TestJDBCBackend {
     assertEquals(viewNamespace, retrievedView.namespace());
   }
 
+  @TestTemplate
+  public void testUpdateViewCrossNamespace() throws IOException {
+    // Create a second schema for cross-namespace rename
+    String schemaName2 = "schema_for_view_test_2";
+    createAndInsertSchema(metalakeName, catalogName, schemaName2);
+
+    Namespace viewNamespace1 = NamespaceUtil.ofView(metalakeName, catalogName, 
schemaName);
+    Namespace viewNamespace2 = NamespaceUtil.ofView(metalakeName, catalogName, 
schemaName2);
+
+    GenericEntity view =
+        createViewEntity(
+            RandomIdGenerator.INSTANCE.nextId(), viewNamespace1, 
"view_cross_namespace");
+
+    backend.insert(view, false);
+
+    // Update view to move to different namespace
+    Function<GenericEntity, GenericEntity> updater =
+        oldView ->
+            GenericEntity.builder()
+                .withId(oldView.id())
+                .withName("view_cross_namespace_renamed")
+                .withNamespace(viewNamespace2)
+                .withEntityType(Entity.EntityType.VIEW)
+                .build();
+
+    NameIdentifier viewIdent = NameIdentifier.of(viewNamespace1, 
"view_cross_namespace");
+    GenericEntity updatedView = backend.update(viewIdent, 
Entity.EntityType.VIEW, updater);
+
+    assertNotNull(updatedView);
+    assertEquals("view_cross_namespace_renamed", updatedView.name());
+    assertEquals(view.id(), updatedView.id());
+
+    // Verify old namespace+name no longer exists
+    assertThrows(NoSuchEntityException.class, () -> backend.get(viewIdent, 
Entity.EntityType.VIEW));
+
+    // Verify new namespace+name exists
+    NameIdentifier newViewIdent = NameIdentifier.of(viewNamespace2, 
"view_cross_namespace_renamed");
+    GenericEntity retrievedView = backend.get(newViewIdent, 
Entity.EntityType.VIEW);
+    assertNotNull(retrievedView);
+    assertEquals("view_cross_namespace_renamed", retrievedView.name());
+    assertEquals(viewNamespace2, retrievedView.namespace());
+  }
+
   @TestTemplate
   public void testUpdateAlreadyExistsException() throws IOException {
     Namespace viewNamespace = NamespaceUtil.ofView(metalakeName, catalogName, 
schemaName);

Reply via email to