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 04f5dda158 [#10458] fix(core): Include VIEW in cascade owner relation
cleanup for schema and catalog deletion (#10678)
04f5dda158 is described below
commit 04f5dda1585e6401810688bc2116ea3877ef4851
Author: Sachin Ranjalkar <[email protected]>
AuthorDate: Sun Apr 5 22:21:53 2026 +0530
[#10458] fix(core): Include VIEW in cascade owner relation cleanup for
schema and catalog deletion (#10678)
### What changes were proposed in this pull request?
Added VIEW to the UNION queries in `softDeleteOwnerRelByCatalogId` and
`softDeleteOwnerRelBySchemaId` in both the base and PostgreSQL SQL
providers, so that view owner relations are cleaned up during cascade
schema/catalog deletion.
### Why are the changes needed?
When a schema or catalog is deleted in cascade mode, the bulk SQL
queries that soft-delete child owner relations include TABLE, TOPIC,
FILESET, and MODEL but miss VIEW. This leaves orphaned ("zombie") view
owner relation rows in the database.
Note: individual view deletion via `ViewMetaService.deleteView()`
already cleans up owner relations correctly — the bug only affects the
cascade path from schema/catalog deletion.
Fix: #10458
### Does this PR introduce _any_ user-facing change?
No.
### How was this patch tested?
Updated `TestOwnerMetaService.testDeleteMetadataObject()` to include
view entities in all test blocks (individual delete, cascade catalog
delete, cascade schema delete, delete user). The cascade tests verify
that `countActiveOwnerRel` drops to 0 after cascade catalog deletion and
to 1 (only catalog survives) after cascade schema deletion — these
assertions would fail without the SQL fix.
`./gradlew :core:test --tests "*TestOwnerMetaService*" -PskipITs`
passes.
---
.../provider/base/OwnerMetaBaseSQLProvider.java | 11 ++++
.../postgresql/OwnerMetaPostgreSQLProvider.java | 11 ++++
.../relational/service/TestOwnerMetaService.java | 61 ++++++++++++++++++----
3 files changed, 72 insertions(+), 11 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/OwnerMetaBaseSQLProvider.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/OwnerMetaBaseSQLProvider.java
index ece7bfc22a..a7ce2b8247 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/OwnerMetaBaseSQLProvider.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/OwnerMetaBaseSQLProvider.java
@@ -29,6 +29,7 @@ import
org.apache.gravitino.storage.relational.mapper.SchemaMetaMapper;
import org.apache.gravitino.storage.relational.mapper.TableMetaMapper;
import org.apache.gravitino.storage.relational.mapper.TopicMetaMapper;
import org.apache.gravitino.storage.relational.mapper.UserMetaMapper;
+import org.apache.gravitino.storage.relational.mapper.ViewMetaMapper;
import org.apache.gravitino.storage.relational.po.OwnerRelPO;
import org.apache.ibatis.annotations.Param;
@@ -183,6 +184,11 @@ public class OwnerMetaBaseSQLProvider {
+ ModelMetaMapper.TABLE_NAME
+ " mt WHERE mt.catalog_id = #{catalogId} AND"
+ " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type =
'MODEL'"
+ + " UNION"
+ + " SELECT vt.catalog_id FROM "
+ + ViewMetaMapper.TABLE_NAME
+ + " vt WHERE vt.catalog_id = #{catalogId} AND"
+ + " vt.view_id = ot.metadata_object_id AND ot.metadata_object_type =
'VIEW'"
+ ")";
}
@@ -216,6 +222,11 @@ public class OwnerMetaBaseSQLProvider {
+ ModelMetaMapper.TABLE_NAME
+ " mt WHERE mt.schema_id = #{schemaId} AND"
+ " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type =
'MODEL'"
+ + " UNION"
+ + " SELECT vt.schema_id FROM "
+ + ViewMetaMapper.TABLE_NAME
+ + " vt WHERE vt.schema_id = #{schemaId} AND"
+ + " vt.view_id = ot.metadata_object_id AND ot.metadata_object_type =
'VIEW'"
+ ")";
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java
index ec50c68fb1..4012bf52d5 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java
@@ -26,6 +26,7 @@ import
org.apache.gravitino.storage.relational.mapper.ModelMetaMapper;
import org.apache.gravitino.storage.relational.mapper.SchemaMetaMapper;
import org.apache.gravitino.storage.relational.mapper.TableMetaMapper;
import org.apache.gravitino.storage.relational.mapper.TopicMetaMapper;
+import org.apache.gravitino.storage.relational.mapper.ViewMetaMapper;
import
org.apache.gravitino.storage.relational.mapper.provider.base.OwnerMetaBaseSQLProvider;
import org.apache.ibatis.annotations.Param;
@@ -90,6 +91,11 @@ public class OwnerMetaPostgreSQLProvider extends
OwnerMetaBaseSQLProvider {
+ ModelMetaMapper.TABLE_NAME
+ " mt WHERE mt.catalog_id = #{catalogId} AND"
+ " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type =
'MODEL'"
+ + " UNION"
+ + " SELECT vt.catalog_id FROM "
+ + ViewMetaMapper.TABLE_NAME
+ + " vt WHERE vt.catalog_id = #{catalogId} AND"
+ + " vt.view_id = ot.metadata_object_id AND ot.metadata_object_type =
'VIEW'"
+ ")";
}
@@ -123,6 +129,11 @@ public class OwnerMetaPostgreSQLProvider extends
OwnerMetaBaseSQLProvider {
+ ModelMetaMapper.TABLE_NAME
+ " mt WHERE mt.schema_id = #{schemaId} AND"
+ " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type =
'MODEL'"
+ + " UNION"
+ + " SELECT vt.schema_id FROM "
+ + ViewMetaMapper.TABLE_NAME
+ + " vt WHERE vt.schema_id = #{schemaId} AND"
+ + " vt.view_id = ot.metadata_object_id AND ot.metadata_object_type =
'VIEW'"
+ ")";
}
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestOwnerMetaService.java
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestOwnerMetaService.java
index 8d1ad4ca93..541095f782 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestOwnerMetaService.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestOwnerMetaService.java
@@ -37,6 +37,7 @@ import org.apache.gravitino.meta.AuditInfo;
import org.apache.gravitino.meta.BaseMetalake;
import org.apache.gravitino.meta.CatalogEntity;
import org.apache.gravitino.meta.FilesetEntity;
+import org.apache.gravitino.meta.GenericEntity;
import org.apache.gravitino.meta.GroupEntity;
import org.apache.gravitino.meta.ModelEntity;
import org.apache.gravitino.meta.RoleEntity;
@@ -247,6 +248,12 @@ class TestOwnerMetaService extends TestJDBCBackend {
null,
AUDIT_INFO);
backend.insert(model, false);
+ GenericEntity view =
+ createViewEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ Namespace.of(TestOwnerMetaService.METALAKE_NAME, CATALOG_NAME,
SCHEMA_NAME),
+ "view");
+ backend.insert(view, false);
UserEntity user =
createUserEntity(
@@ -268,38 +275,45 @@ class TestOwnerMetaService extends TestJDBCBackend {
.setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(),
user.type());
OwnerMetaService.getInstance()
.setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(),
user.type());
+ OwnerMetaService.getInstance()
+ .setOwner(view.nameIdentifier(), view.type(), user.nameIdentifier(),
user.type());
+
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countActiveOwnerRel(user.id()));
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ // Test to delete view
+ ViewMetaService.getInstance().deleteView(view.nameIdentifier());
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(6, countActiveOwnerRel(user.id()));
// Test to delete model
ModelMetaService.getInstance().deleteModel(model.nameIdentifier());
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(5, countActiveOwnerRel(user.id()));
// Test to delete table
TableMetaService.getInstance().deleteTable(table.nameIdentifier());
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(4, countActiveOwnerRel(user.id()));
// Test to delete topic
TopicMetaService.getInstance().deleteTopic(topic.nameIdentifier());
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(3, countActiveOwnerRel(user.id()));
// Test to delete fileset
FilesetMetaService.getInstance().deleteFileset(fileset.nameIdentifier());
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(2, countActiveOwnerRel(user.id()));
// Test to delete schema
SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(),
false);
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(1, countActiveOwnerRel(user.id()));
// Test to delete catalog
CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(),
false);
- Assertions.assertEquals(6, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(7, countAllOwnerRel(user.id()));
Assertions.assertEquals(0, countActiveOwnerRel(user.id()));
// Test to delete catalog with cascade mode
@@ -350,6 +364,12 @@ class TestOwnerMetaService extends TestJDBCBackend {
null,
AUDIT_INFO);
backend.insert(model, false);
+ view =
+ createViewEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ Namespace.of(TestOwnerMetaService.METALAKE_NAME, CATALOG_NAME,
SCHEMA_NAME),
+ "view");
+ backend.insert(view, false);
OwnerMetaService.getInstance()
.setOwner(catalog.nameIdentifier(), catalog.type(),
user.nameIdentifier(), user.type());
@@ -363,9 +383,11 @@ class TestOwnerMetaService extends TestJDBCBackend {
.setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(),
user.type());
OwnerMetaService.getInstance()
.setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(),
user.type());
+ OwnerMetaService.getInstance()
+ .setOwner(view.nameIdentifier(), view.type(), user.nameIdentifier(),
user.type());
CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(),
true);
- Assertions.assertEquals(12, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(14, countAllOwnerRel(user.id()));
Assertions.assertEquals(0, countActiveOwnerRel(user.id()));
// Test to delete schema with cascade mode
@@ -420,6 +442,13 @@ class TestOwnerMetaService extends TestJDBCBackend {
AUDIT_INFO);
backend.insert(model, false);
+ view =
+ createViewEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ Namespace.of(TestOwnerMetaService.METALAKE_NAME, CATALOG_NAME,
SCHEMA_NAME),
+ "view");
+ backend.insert(view, false);
+
OwnerMetaService.getInstance()
.setOwner(schema.nameIdentifier(), schema.type(),
user.nameIdentifier(), user.type());
OwnerMetaService.getInstance()
@@ -432,9 +461,11 @@ class TestOwnerMetaService extends TestJDBCBackend {
.setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(),
user.type());
OwnerMetaService.getInstance()
.setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(),
user.type());
+ OwnerMetaService.getInstance()
+ .setOwner(view.nameIdentifier(), view.type(), user.nameIdentifier(),
user.type());
SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(),
true);
- Assertions.assertEquals(18, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(21, countAllOwnerRel(user.id()));
Assertions.assertEquals(1, countActiveOwnerRel(user.id()));
// Test to delete user
@@ -466,7 +497,6 @@ class TestOwnerMetaService extends TestJDBCBackend {
Namespace.of(TestOwnerMetaService.METALAKE_NAME, CATALOG_NAME,
SCHEMA_NAME),
"topic",
AUDIT_INFO);
-
backend.insert(topic, false);
model =
@@ -480,6 +510,13 @@ class TestOwnerMetaService extends TestJDBCBackend {
AUDIT_INFO);
backend.insert(model, false);
+ view =
+ createViewEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ Namespace.of(TestOwnerMetaService.METALAKE_NAME, CATALOG_NAME,
SCHEMA_NAME),
+ "view");
+ backend.insert(view, false);
+
OwnerMetaService.getInstance()
.setOwner(schema.nameIdentifier(), schema.type(),
user.nameIdentifier(), user.type());
OwnerMetaService.getInstance()
@@ -492,9 +529,11 @@ class TestOwnerMetaService extends TestJDBCBackend {
.setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(),
user.type());
OwnerMetaService.getInstance()
.setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(),
user.type());
+ OwnerMetaService.getInstance()
+ .setOwner(view.nameIdentifier(), view.type(), user.nameIdentifier(),
user.type());
UserMetaService.getInstance().deleteUser(user.nameIdentifier());
- Assertions.assertEquals(24, countAllOwnerRel(user.id()));
+ Assertions.assertEquals(28, countAllOwnerRel(user.id()));
Assertions.assertEquals(0, countActiveOwnerRel(user.id()));
}