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