This is an automated email from the ASF dual-hosted git repository. jshao 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 a9e93e256e [#6704] feat(authz): Support model hook dispatcher (#6844) a9e93e256e is described below commit a9e93e256ef7b397af11b45ad858f771d0c6fdb7 Author: roryqi <h...@datastrato.com> AuthorDate: Wed Apr 9 12:30:42 2025 +0800 [#6704] feat(authz): Support model hook dispatcher (#6844) ### What changes were proposed in this pull request? Support model hook dispatcher ### Why are the changes needed? Fix: #6704 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Add IT. --- .../integration/test/authorization/OwnerIT.java | 56 +++++++ .../java/org/apache/gravitino/GravitinoEnv.java | 5 +- .../apache/gravitino/hook/ModelHookDispatcher.java | 176 +++++++++++++++++++++ .../mapper/OwnerMetaSQLProviderFactory.java | 2 +- .../provider/base/OwnerMetaBaseSQLProvider.java | 13 +- .../base/SecurableObjectBaseSQLProvider.java | 11 ++ .../base/TagMetadataObjectRelBaseSQLProvider.java | 11 ++ .../postgresql/OwnerMetaPostgreSQLProvider.java | 13 +- .../SecurableObjectPostgreSQLProvider.java | 11 ++ .../TagMetadataObjectRelPostgreSQLProvider.java | 11 ++ .../relational/service/ModelMetaService.java | 26 ++- .../relational/service/TestOwnerMetaService.java | 79 +++++++-- .../relational/service/TestSecurableObjects.java | 65 ++++++-- .../relational/service/TestTagMetaService.java | 70 +++++++- 14 files changed, 515 insertions(+), 34 deletions(-) diff --git a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/OwnerIT.java b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/OwnerIT.java index daac8002ab..32ca7bd778 100644 --- a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/OwnerIT.java +++ b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/OwnerIT.java @@ -324,6 +324,62 @@ public class OwnerIT extends BaseIT { client.dropMetalake(metalakeNameD, true); } + @Test + public void testCreateModel() { + String metalakeNameF = RandomNameUtils.genRandomName("metalakeF"); + GravitinoMetalake metalake = + client.createMetalake(metalakeNameF, "metalake F comment", Collections.emptyMap()); + String catalogNameF = RandomNameUtils.genRandomName("catalogF"); + Map<String, String> properties = Maps.newHashMap(); + Catalog catalog = + metalake.createCatalog(catalogNameF, Catalog.Type.MODEL, "catalog comment", properties); + + NameIdentifier modelIdent = NameIdentifier.of("schema_owner", "model_owner"); + catalog.asSchemas().createSchema("schema_owner", "comment", Collections.emptyMap()); + catalog.asModelCatalog().registerModel(modelIdent, "comment", Collections.emptyMap()); + + MetadataObject metalakeObject = + MetadataObjects.of(null, metalakeNameF, MetadataObject.Type.METALAKE); + Owner owner = metalake.getOwner(metalakeObject).get(); + Assertions.assertEquals(AuthConstants.ANONYMOUS_USER, owner.name()); + Assertions.assertEquals(Owner.Type.USER, owner.type()); + + MetadataObject catalogObject = + MetadataObjects.of(Lists.newArrayList(catalogNameF), MetadataObject.Type.CATALOG); + owner = metalake.getOwner(catalogObject).get(); + Assertions.assertEquals(AuthConstants.ANONYMOUS_USER, owner.name()); + Assertions.assertEquals(Owner.Type.USER, owner.type()); + + MetadataObject schemaObject = + MetadataObjects.of( + Lists.newArrayList(catalogNameF, "schema_owner"), MetadataObject.Type.SCHEMA); + owner = metalake.getOwner(schemaObject).get(); + Assertions.assertEquals(AuthConstants.ANONYMOUS_USER, owner.name()); + Assertions.assertEquals(Owner.Type.USER, owner.type()); + + MetadataObject modelObject = + MetadataObjects.of( + Lists.newArrayList(catalogNameF, "schema_owner", "model_owner"), + MetadataObject.Type.MODEL); + owner = metalake.getOwner(modelObject).get(); + Assertions.assertEquals(AuthConstants.ANONYMOUS_USER, owner.name()); + Assertions.assertEquals(Owner.Type.USER, owner.type()); + + // Set another owner + String anotherUser = "another"; + metalake.addUser(anotherUser); + metalake.setOwner(modelObject, anotherUser, Owner.Type.USER); + owner = metalake.getOwner(modelObject).get(); + Assertions.assertEquals(anotherUser, owner.name()); + Assertions.assertEquals(Owner.Type.USER, owner.type()); + + // Clean up + catalog.asModelCatalog().deleteModel(modelIdent); + catalog.asSchemas().dropSchema("schema_owner", true); + metalake.dropCatalog(catalogNameF, true); + client.dropMetalake(metalakeNameF, true); + } + @Test public void testOwnerWithException() { String metalakeNameE = RandomNameUtils.genRandomName("metalakeE"); diff --git a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java index 4e9fc02b49..b33f2525a2 100644 --- a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java +++ b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java @@ -51,6 +51,7 @@ import org.apache.gravitino.hook.AccessControlHookDispatcher; import org.apache.gravitino.hook.CatalogHookDispatcher; import org.apache.gravitino.hook.FilesetHookDispatcher; import org.apache.gravitino.hook.MetalakeHookDispatcher; +import org.apache.gravitino.hook.ModelHookDispatcher; import org.apache.gravitino.hook.SchemaHookDispatcher; import org.apache.gravitino.hook.TableHookDispatcher; import org.apache.gravitino.hook.TopicHookDispatcher; @@ -483,11 +484,11 @@ public class GravitinoEnv { new TopicNormalizeDispatcher(topicHookDispatcher, catalogManager); this.topicDispatcher = new TopicEventDispatcher(eventBus, topicNormalizeDispatcher); - // TODO(jerryshao). Add Hook support for Model. ModelOperationDispatcher modelOperationDispatcher = new ModelOperationDispatcher(catalogManager, entityStore, idGenerator); + ModelHookDispatcher modelHookDispatcher = new ModelHookDispatcher(modelOperationDispatcher); ModelNormalizeDispatcher modelNormalizeDispatcher = - new ModelNormalizeDispatcher(modelOperationDispatcher, catalogManager); + new ModelNormalizeDispatcher(modelHookDispatcher, catalogManager); this.modelDispatcher = new ModelEventDispatcher(eventBus, modelNormalizeDispatcher); // Create and initialize access control related modules diff --git a/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java b/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java new file mode 100644 index 0000000000..af6723e844 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java @@ -0,0 +1,176 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.hook; + +import java.util.Map; +import org.apache.gravitino.Entity; +import org.apache.gravitino.GravitinoEnv; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.Namespace; +import org.apache.gravitino.authorization.AuthorizationUtils; +import org.apache.gravitino.authorization.Owner; +import org.apache.gravitino.authorization.OwnerManager; +import org.apache.gravitino.catalog.ModelDispatcher; +import org.apache.gravitino.exceptions.ModelAlreadyExistsException; +import org.apache.gravitino.exceptions.ModelVersionAliasesAlreadyExistException; +import org.apache.gravitino.exceptions.NoSuchModelException; +import org.apache.gravitino.exceptions.NoSuchModelVersionException; +import org.apache.gravitino.exceptions.NoSuchSchemaException; +import org.apache.gravitino.model.Model; +import org.apache.gravitino.model.ModelChange; +import org.apache.gravitino.model.ModelVersion; +import org.apache.gravitino.utils.NameIdentifierUtil; +import org.apache.gravitino.utils.PrincipalUtils; + +/** + * {@code ModelHookDispatcher} is a decorator for {@link ModelDispatcher} that not only delegates + * model operations to the underlying model dispatcher but also executes some hook operations before + * or after the underlying operations. + */ +public class ModelHookDispatcher implements ModelDispatcher { + + private final ModelDispatcher dispatcher; + + public ModelHookDispatcher(ModelDispatcher dispatcher) { + this.dispatcher = dispatcher; + } + + @Override + public NameIdentifier[] listModels(Namespace namespace) throws NoSuchSchemaException { + return dispatcher.listModels(namespace); + } + + @Override + public Model getModel(NameIdentifier ident) throws NoSuchModelException { + return dispatcher.getModel(ident); + } + + @Override + public Model registerModel(NameIdentifier ident, String comment, Map<String, String> properties) + throws NoSuchSchemaException, ModelAlreadyExistsException { + // Check whether the current user exists or not + AuthorizationUtils.checkCurrentUser( + ident.namespace().level(0), PrincipalUtils.getCurrentUserName()); + + Model model = dispatcher.registerModel(ident, comment, properties); + + // Set the creator as owner of the model. + OwnerManager ownerManager = GravitinoEnv.getInstance().ownerManager(); + if (ownerManager != null) { + ownerManager.setOwner( + ident.namespace().level(0), + NameIdentifierUtil.toMetadataObject(ident, Entity.EntityType.MODEL), + PrincipalUtils.getCurrentUserName(), + Owner.Type.USER); + } + return model; + } + + @Override + public boolean deleteModel(NameIdentifier ident) { + return dispatcher.deleteModel(ident); + } + + @Override + public int[] listModelVersions(NameIdentifier ident) throws NoSuchModelException { + return dispatcher.listModelVersions(ident); + } + + @Override + public ModelVersion getModelVersion(NameIdentifier ident, int version) + throws NoSuchModelVersionException { + return dispatcher.getModelVersion(ident, version); + } + + @Override + public ModelVersion getModelVersion(NameIdentifier ident, String alias) + throws NoSuchModelVersionException { + return dispatcher.getModelVersion(ident, alias); + } + + @Override + public void linkModelVersion( + NameIdentifier ident, + String uri, + String[] aliases, + String comment, + Map<String, String> properties) + throws NoSuchModelException, ModelVersionAliasesAlreadyExistException { + dispatcher.linkModelVersion(ident, uri, aliases, comment, properties); + } + + @Override + public boolean deleteModelVersion(NameIdentifier ident, int version) { + return dispatcher.deleteModelVersion(ident, version); + } + + @Override + public boolean deleteModelVersion(NameIdentifier ident, String alias) { + return dispatcher.deleteModelVersion(ident, alias); + } + + @Override + public boolean modelExists(NameIdentifier ident) { + return dispatcher.modelExists(ident); + } + + @Override + public Model registerModel( + NameIdentifier ident, + String uri, + String[] aliases, + String comment, + Map<String, String> properties) + throws NoSuchSchemaException, ModelAlreadyExistsException, + ModelVersionAliasesAlreadyExistException { + // Check whether the current user exists or not + AuthorizationUtils.checkCurrentUser( + ident.namespace().level(0), PrincipalUtils.getCurrentUserName()); + + Model model = dispatcher.registerModel(ident, uri, aliases, comment, properties); + + // Set the creator as owner of the model. + OwnerManager ownerManager = GravitinoEnv.getInstance().ownerManager(); + if (ownerManager != null) { + ownerManager.setOwner( + ident.name(), + NameIdentifierUtil.toMetadataObject(ident, Entity.EntityType.MODEL), + PrincipalUtils.getCurrentUserName(), + Owner.Type.USER); + } + return model; + } + + @Override + public boolean modelVersionExists(NameIdentifier ident, int version) { + return dispatcher.modelVersionExists(ident, version); + } + + @Override + public boolean modelVersionExists(NameIdentifier ident, String alias) { + return dispatcher.modelVersionExists(ident, alias); + } + + @Override + public Model alterModel(NameIdentifier ident, ModelChange... changes) + throws NoSuchModelException, IllegalArgumentException { + return dispatcher.alterModel(ident, changes); + } +} diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/OwnerMetaSQLProviderFactory.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/OwnerMetaSQLProviderFactory.java index 193c3e881a..b7b528a300 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/OwnerMetaSQLProviderFactory.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/OwnerMetaSQLProviderFactory.java @@ -89,7 +89,7 @@ public class OwnerMetaSQLProviderFactory { } public static String softDeleteOwnerRelBySchemaId(@Param("schemaId") Long schemaId) { - return getProvider().sotDeleteOwnerRelBySchemaId(schemaId); + return getProvider().softDeleteOwnerRelBySchemaId(schemaId); } public static String deleteOwnerMetasByLegacyTimeline( 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 ab89ddcd47..6e3f69e4db 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 @@ -23,6 +23,7 @@ import static org.apache.gravitino.storage.relational.mapper.OwnerMetaMapper.OWN import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; import org.apache.gravitino.storage.relational.mapper.GroupMetaMapper; +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; @@ -148,10 +149,15 @@ public class OwnerMetaBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.catalog_id = #{catalogId} AND" + " ft.fileset_id = ot.metadata_object_id AND ot.metadata_object_type = 'FILESET'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type = 'MODEL'" + ")"; } - public String sotDeleteOwnerRelBySchemaId(@Param("schemaId") Long schemaId) { + public String softDeleteOwnerRelBySchemaId(@Param("schemaId") Long schemaId) { return "UPDATE " + OWNER_TABLE_NAME + " ot SET ot.deleted_at = (UNIX_TIMESTAMP() * 1000.0)" @@ -176,6 +182,11 @@ public class OwnerMetaBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.schema_id = #{schemaId} AND " + " ft.fileset_id = ot.metadata_object_id AND ot.metadata_object_type = 'FILESET'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type = 'MODEL'" + ")"; } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/SecurableObjectBaseSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/SecurableObjectBaseSQLProvider.java index 42e9026193..6f6407a81a 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/SecurableObjectBaseSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/SecurableObjectBaseSQLProvider.java @@ -24,6 +24,7 @@ import static org.apache.gravitino.storage.relational.mapper.SecurableObjectMapp import java.util.List; import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; +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; @@ -128,6 +129,11 @@ public class SecurableObjectBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.catalog_id = #{catalogId} AND" + " ft.fileset_id = sect.metadata_object_id AND sect.type = 'FILESET'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = sect.metadata_object_id AND sect.type = 'MODEL'" + ")"; } @@ -156,6 +162,11 @@ public class SecurableObjectBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.schema_id = #{schemaId} AND " + " ft.fileset_id = sect.metadata_object_id AND sect.type = 'FILESET'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + " mt.model_id = sect.metadata_object_id AND sect.type = 'MODEL'" + ")"; } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TagMetadataObjectRelBaseSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TagMetadataObjectRelBaseSQLProvider.java index 6c1c7eb5fc..778a026a20 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TagMetadataObjectRelBaseSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/TagMetadataObjectRelBaseSQLProvider.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; import org.apache.gravitino.storage.relational.mapper.MetalakeMetaMapper; +import org.apache.gravitino.storage.relational.mapper.ModelMetaMapper; import org.apache.gravitino.storage.relational.mapper.SchemaMetaMapper; import org.apache.gravitino.storage.relational.mapper.TableColumnMapper; import org.apache.gravitino.storage.relational.mapper.TableMetaMapper; @@ -198,6 +199,11 @@ public class TagMetadataObjectRelBaseSQLProvider { + TableColumnMapper.COLUMN_TABLE_NAME + " cot WHERE cot.catalog_id = #{catalogId} AND" + " cot.column_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'COLUMN'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'MODEL'" + ")"; } @@ -231,6 +237,11 @@ public class TagMetadataObjectRelBaseSQLProvider { + TableColumnMapper.COLUMN_TABLE_NAME + " cot WHERE cot.schema_id = #{schemaId} AND " + " cot.column_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'COLUMN'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + " mt.model_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'MODEL'" + ")"; } 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 c0f5d73d8e..c88f292ae4 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 @@ -22,6 +22,7 @@ import static org.apache.gravitino.storage.relational.mapper.OwnerMetaMapper.OWN import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; +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; @@ -88,11 +89,16 @@ public class OwnerMetaPostgreSQLProvider extends OwnerMetaBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.catalog_id = #{catalogId} AND" + " ft.fileset_id = ot.metadata_object_id AND ot.metadata_object_type = 'FILESET'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = ot.metadata_object_id AND ot.metadata_object_type = 'MODEL'" + ")"; } @Override - public String sotDeleteOwnerRelBySchemaId(Long schemaId) { + public String softDeleteOwnerRelBySchemaId(Long schemaId) { return "UPDATE " + OWNER_TABLE_NAME + " ot SET deleted_at = floor(extract(epoch from((current_timestamp - timestamp '1970-01-01 00:00:00')*1000))) " @@ -116,6 +122,11 @@ public class OwnerMetaPostgreSQLProvider extends OwnerMetaBaseSQLProvider { + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.schema_id = #{schemaId} AND " + "ft.fileset_id = ot.metadata_object_id AND ot.metadata_object_type = 'FILESET'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + "mt.model_id = ot.metadata_object_id AND ot.metadata_object_type = 'MODEL'" + ")"; } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java index c67324f9a7..027f4fb720 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java @@ -24,6 +24,7 @@ import static org.apache.gravitino.storage.relational.mapper.SecurableObjectMapp import java.util.List; import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; +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; @@ -113,6 +114,11 @@ public class SecurableObjectPostgreSQLProvider extends SecurableObjectBaseSQLPro + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.catalog_id = #{catalogId} AND" + " ft.fileset_id = sect.metadata_object_id AND sect.type = 'FILESET'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = sect.metadata_object_id AND sect.type = 'MODEL'" + ")"; } @@ -142,6 +148,11 @@ public class SecurableObjectPostgreSQLProvider extends SecurableObjectBaseSQLPro + FilesetMetaMapper.META_TABLE_NAME + " ft WHERE ft.schema_id = #{schemaId} AND " + "ft.fileset_id = sect.metadata_object_id AND sect.type = 'FILESET'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + " mt.model_id = sect.metadata_object_id AND sect.type = 'MODEL'" + ")"; } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java index 9045ead8ea..be008deca5 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.gravitino.storage.relational.mapper.CatalogMetaMapper; import org.apache.gravitino.storage.relational.mapper.FilesetMetaMapper; import org.apache.gravitino.storage.relational.mapper.MetalakeMetaMapper; +import org.apache.gravitino.storage.relational.mapper.ModelMetaMapper; import org.apache.gravitino.storage.relational.mapper.SchemaMetaMapper; import org.apache.gravitino.storage.relational.mapper.TableColumnMapper; import org.apache.gravitino.storage.relational.mapper.TableMetaMapper; @@ -109,6 +110,11 @@ public class TagMetadataObjectRelPostgreSQLProvider extends TagMetadataObjectRel + TableColumnMapper.COLUMN_TABLE_NAME + " cot WHERE cot.catalog_id = #{catalogId} AND" + " cot.column_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'COLUMN'" + + " UNION " + + " SELECT mt.catalog_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.catalog_id = #{catalogId} AND" + + " mt.model_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'MODEL'" + ")"; } @@ -143,6 +149,11 @@ public class TagMetadataObjectRelPostgreSQLProvider extends TagMetadataObjectRel + TableColumnMapper.COLUMN_TABLE_NAME + " cot WHERE cot.schema_id = #{schemaId} AND" + " cot.column_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'COLUMN'" + + " UNION " + + " SELECT mt.schema_id FROM " + + ModelMetaMapper.TABLE_NAME + + " mt WHERE mt.schema_id = #{schemaId} AND " + + " mt.model_id = tmt.metadata_object_id AND tmt.metadata_object_type = 'MODEL'" + ")"; } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java index 7e32af2f4b..79ca6fc1b0 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelMetaService.java @@ -29,6 +29,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.gravitino.Entity; import org.apache.gravitino.HasIdentifier; +import org.apache.gravitino.MetadataObject; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; import org.apache.gravitino.exceptions.NoSuchEntityException; @@ -36,6 +37,9 @@ import org.apache.gravitino.meta.ModelEntity; import org.apache.gravitino.storage.relational.mapper.ModelMetaMapper; import org.apache.gravitino.storage.relational.mapper.ModelVersionAliasRelMapper; import org.apache.gravitino.storage.relational.mapper.ModelVersionMetaMapper; +import org.apache.gravitino.storage.relational.mapper.OwnerMetaMapper; +import org.apache.gravitino.storage.relational.mapper.SecurableObjectMapper; +import org.apache.gravitino.storage.relational.mapper.TagMetadataObjectRelMapper; import org.apache.gravitino.storage.relational.po.ModelPO; import org.apache.gravitino.storage.relational.utils.ExceptionUtils; import org.apache.gravitino.storage.relational.utils.POConverters; @@ -102,8 +106,10 @@ public class ModelMetaService { NameIdentifierUtil.checkModel(ident); Long schemaId; + Long modelId; try { schemaId = CommonMetaService.getInstance().getParentEntityIdByNamespace(ident.namespace()); + modelId = getModelIdBySchemaIdAndModelName(schemaId, ident.name()); } catch (NoSuchEntityException e) { LOG.warn("Failed to delete model: {}", ident, e); return false; @@ -132,7 +138,25 @@ public class ModelMetaService { SessionUtils.doWithoutCommitAndFetchResult( ModelMetaMapper.class, mapper -> - mapper.softDeleteModelMetaBySchemaIdAndModelName(schemaId, ident.name())))); + mapper.softDeleteModelMetaBySchemaIdAndModelName(schemaId, ident.name()))), + () -> + SessionUtils.doWithoutCommit( + OwnerMetaMapper.class, + mapper -> + mapper.softDeleteOwnerRelByMetadataObjectIdAndType( + modelId, MetadataObject.Type.MODEL.name())), + () -> + SessionUtils.doWithoutCommit( + SecurableObjectMapper.class, + mapper -> + mapper.softDeleteObjectRelsByMetadataObject( + modelId, MetadataObject.Type.MODEL.name())), + () -> + SessionUtils.doWithoutCommit( + TagMetadataObjectRelMapper.class, + mapper -> + mapper.softDeleteTagMetadataObjectRelsByMetadataObject( + modelId, MetadataObject.Type.MODEL.name()))); return modelDeletedCount.get() > 0; } 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 89dea63a59..908022f667 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 @@ -28,6 +28,7 @@ import org.apache.gravitino.meta.BaseMetalake; import org.apache.gravitino.meta.CatalogEntity; import org.apache.gravitino.meta.FilesetEntity; import org.apache.gravitino.meta.GroupEntity; +import org.apache.gravitino.meta.ModelEntity; import org.apache.gravitino.meta.RoleEntity; import org.apache.gravitino.meta.SchemaEntity; import org.apache.gravitino.meta.TableEntity; @@ -260,6 +261,16 @@ class TestOwnerMetaService extends TestJDBCBackend { "topic", auditInfo); backend.insert(topic, false); + ModelEntity model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); UserEntity user = createUserEntity( @@ -279,33 +290,40 @@ class TestOwnerMetaService extends TestJDBCBackend { .setOwner(fileset.nameIdentifier(), fileset.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() .setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(), user.type()); + OwnerMetaService.getInstance() + .setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(), user.type()); + + Assertions.assertEquals(6, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countActiveOwnerRel(user.id())); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + // Test to delete model + ModelMetaService.getInstance().deleteModel(model.nameIdentifier()); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(5, countActiveOwnerRel(user.id())); // Test to delete table TableMetaService.getInstance().deleteTable(table.nameIdentifier()); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(4, countActiveOwnerRel(user.id())); // Test to delete topic TopicMetaService.getInstance().deleteTopic(topic.nameIdentifier()); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(3, countActiveOwnerRel(user.id())); // Test to delete fileset FilesetMetaService.getInstance().deleteFileset(fileset.nameIdentifier()); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(2, countActiveOwnerRel(user.id())); // Test to delete schema SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), false); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(1, countActiveOwnerRel(user.id())); // Test to delete catalog CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), false); - Assertions.assertEquals(5, countAllOwnerRel(user.id())); + Assertions.assertEquals(6, countAllOwnerRel(user.id())); Assertions.assertEquals(0, countActiveOwnerRel(user.id())); // Test to delete catalog with cascade mode @@ -343,6 +361,16 @@ class TestOwnerMetaService extends TestJDBCBackend { "topic", auditInfo); backend.insert(topic, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); OwnerMetaService.getInstance() .setOwner(catalog.nameIdentifier(), catalog.type(), user.nameIdentifier(), user.type()); @@ -354,9 +382,11 @@ class TestOwnerMetaService extends TestJDBCBackend { .setOwner(fileset.nameIdentifier(), fileset.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() .setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(), user.type()); + OwnerMetaService.getInstance() + .setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(), user.type()); CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), true); - Assertions.assertEquals(10, countAllOwnerRel(user.id())); + Assertions.assertEquals(12, countAllOwnerRel(user.id())); Assertions.assertEquals(0, countActiveOwnerRel(user.id())); // Test to delete schema with cascade mode @@ -380,6 +410,7 @@ class TestOwnerMetaService extends TestJDBCBackend { "fileset", auditInfo); backend.insert(fileset, false); + table = createTableEntity( RandomIdGenerator.INSTANCE.nextId(), @@ -387,6 +418,7 @@ class TestOwnerMetaService extends TestJDBCBackend { "table", auditInfo); backend.insert(table, false); + topic = createTopicEntity( RandomIdGenerator.INSTANCE.nextId(), @@ -395,6 +427,17 @@ class TestOwnerMetaService extends TestJDBCBackend { auditInfo); backend.insert(topic, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + OwnerMetaService.getInstance() .setOwner(schema.nameIdentifier(), schema.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() @@ -405,9 +448,11 @@ class TestOwnerMetaService extends TestJDBCBackend { .setOwner(fileset.nameIdentifier(), fileset.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() .setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(), user.type()); + OwnerMetaService.getInstance() + .setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(), user.type()); SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), true); - Assertions.assertEquals(15, countAllOwnerRel(user.id())); + Assertions.assertEquals(18, countAllOwnerRel(user.id())); Assertions.assertEquals(1, countActiveOwnerRel(user.id())); // Test to delete user @@ -439,8 +484,20 @@ class TestOwnerMetaService extends TestJDBCBackend { Namespace.of("metalake", "catalog", "schema"), "topic", auditInfo); + backend.insert(topic, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + OwnerMetaService.getInstance() .setOwner(schema.nameIdentifier(), schema.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() @@ -451,9 +508,13 @@ class TestOwnerMetaService extends TestJDBCBackend { .setOwner(fileset.nameIdentifier(), fileset.type(), user.nameIdentifier(), user.type()); OwnerMetaService.getInstance() .setOwner(topic.nameIdentifier(), topic.type(), user.nameIdentifier(), user.type()); + OwnerMetaService.getInstance() + .setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(), user.type()); + OwnerMetaService.getInstance() + .setOwner(model.nameIdentifier(), model.type(), user.nameIdentifier(), user.type()); UserMetaService.getInstance().deleteUser(user.nameIdentifier()); - Assertions.assertEquals(20, countAllOwnerRel(user.id())); + Assertions.assertEquals(25, countAllOwnerRel(user.id())); Assertions.assertEquals(0, countActiveOwnerRel(user.id())); } } diff --git a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestSecurableObjects.java b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestSecurableObjects.java index b5cc85112a..950ed6f845 100644 --- a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestSecurableObjects.java +++ b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestSecurableObjects.java @@ -34,6 +34,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.ModelEntity; import org.apache.gravitino.meta.RoleEntity; import org.apache.gravitino.meta.SchemaEntity; import org.apache.gravitino.meta.TableEntity; @@ -192,6 +193,16 @@ public class TestSecurableObjects extends TestJDBCBackend { "topic", auditInfo); backend.insert(topic, false); + ModelEntity model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); SecurableObject catalogObject = SecurableObjects.ofCatalog( @@ -210,6 +221,9 @@ public class TestSecurableObjects extends TestJDBCBackend { SecurableObject topicObject = SecurableObjects.ofTopic( schemaObject, "topic", Lists.newArrayList(Privileges.ConsumeTopic.deny())); + SecurableObject modelObject = + SecurableObjects.ofModel( + schemaObject, "model", Lists.newArrayList(Privileges.UseModel.deny())); RoleEntity role1 = createRoleEntity( @@ -218,37 +232,42 @@ public class TestSecurableObjects extends TestJDBCBackend { "role1", auditInfo, Lists.newArrayList( - catalogObject, schemaObject, tableObject, filesetObject, topicObject), + catalogObject, schemaObject, tableObject, filesetObject, topicObject, modelObject), ImmutableMap.of("k1", "v1")); roleMetaService.insertRole(role1, false); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countActiveObjectRel(role1.id())); + + // Test to delete model + ModelMetaService.getInstance().deleteModel(model.nameIdentifier()); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(5, countActiveObjectRel(role1.id())); // Test to delete table TableMetaService.getInstance().deleteTable(table.nameIdentifier()); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(4, countActiveObjectRel(role1.id())); // Test to delete topic TopicMetaService.getInstance().deleteTopic(topic.nameIdentifier()); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(3, countActiveObjectRel(role1.id())); // Test to delete fileset FilesetMetaService.getInstance().deleteFileset(fileset.nameIdentifier()); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(2, countActiveObjectRel(role1.id())); // Test to delete schema SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), false); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(1, countActiveObjectRel(role1.id())); // Test to delete catalog CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), false); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(0, countActiveObjectRel(role1.id())); roleMetaService.deleteRole(role1.nameIdentifier()); @@ -281,6 +300,7 @@ public class TestSecurableObjects extends TestJDBCBackend { "table", auditInfo); backend.insert(table, false); + topic = createTopicEntity( RandomIdGenerator.INSTANCE.nextId(), @@ -288,6 +308,18 @@ public class TestSecurableObjects extends TestJDBCBackend { "topic", auditInfo); backend.insert(topic, false); + + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + role1 = createRoleEntity( RandomIdGenerator.INSTANCE.nextId(), @@ -295,13 +327,13 @@ public class TestSecurableObjects extends TestJDBCBackend { "role1", auditInfo, Lists.newArrayList( - catalogObject, schemaObject, tableObject, filesetObject, topicObject), + catalogObject, schemaObject, tableObject, filesetObject, topicObject, modelObject), ImmutableMap.of("k1", "v1")); roleMetaService.insertRole(role1, false); CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), true); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(0, countActiveObjectRel(role1.id())); roleMetaService.deleteRole(role1.nameIdentifier()); @@ -341,6 +373,17 @@ public class TestSecurableObjects extends TestJDBCBackend { "topic", auditInfo); backend.insert(topic, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of("metalake", "catalog", "schema"), + "model", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + role1 = createRoleEntity( RandomIdGenerator.INSTANCE.nextId(), @@ -348,13 +391,13 @@ public class TestSecurableObjects extends TestJDBCBackend { "role1", auditInfo, Lists.newArrayList( - catalogObject, schemaObject, tableObject, filesetObject, topicObject), + catalogObject, schemaObject, tableObject, filesetObject, topicObject, modelObject), ImmutableMap.of("k1", "v1")); roleMetaService.insertRole(role1, false); SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), true); - Assertions.assertEquals(5, countAllObjectRel(role1.id())); + Assertions.assertEquals(6, countAllObjectRel(role1.id())); Assertions.assertEquals(1, countActiveObjectRel(role1.id())); } } diff --git a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java index a81f222de9..feb4bdb07c 100644 --- a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java +++ b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestTagMetaService.java @@ -36,6 +36,7 @@ import org.apache.gravitino.meta.BaseMetalake; import org.apache.gravitino.meta.CatalogEntity; import org.apache.gravitino.meta.ColumnEntity; import org.apache.gravitino.meta.FilesetEntity; +import org.apache.gravitino.meta.ModelEntity; import org.apache.gravitino.meta.SchemaEntity; import org.apache.gravitino.meta.TableEntity; import org.apache.gravitino.meta.TagEntity; @@ -731,6 +732,17 @@ public class TestTagMetaService extends TestJDBCBackend { auditInfo); backend.insert(fileset, false); + ModelEntity model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of(metalakeName, catalog.name(), schema.name()), + "model1", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + TagMetaService tagMetaService = TagMetaService.getInstance(); TagEntity tagEntity1 = TagEntity.builder() @@ -774,34 +786,44 @@ public class TestTagMetaService extends TestJDBCBackend { column.type(), new NameIdentifier[] {tagEntity1.nameIdentifier()}, new NameIdentifier[0]); + tagMetaService.associateTagsWithMetadataObject( + model.nameIdentifier(), + model.type(), + new NameIdentifier[] {tagEntity1.nameIdentifier()}, + new NameIdentifier[0]); + + Assertions.assertEquals(7, countActiveTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); + // Test to delete a model + ModelMetaService.getInstance().deleteModel(model.nameIdentifier()); Assertions.assertEquals(6, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a table TableMetaService.getInstance().deleteTable(table.nameIdentifier()); Assertions.assertEquals(4, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a topic TopicMetaService.getInstance().deleteTopic(topic.nameIdentifier()); Assertions.assertEquals(3, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a fileset FilesetMetaService.getInstance().deleteFileset(fileset.nameIdentifier()); Assertions.assertEquals(2, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a schema SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), false); Assertions.assertEquals(1, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a catalog CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), false); Assertions.assertEquals(0, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(6, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(7, countAllTagRel(tagEntity1.id())); // Test to drop a catalog using cascade mode catalog = @@ -858,6 +880,17 @@ public class TestTagMetaService extends TestJDBCBackend { auditInfo); backend.insert(fileset, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of(metalakeName, catalog.name(), schema.name()), + "model1", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + tagMetaService.associateTagsWithMetadataObject( catalog.nameIdentifier(), catalog.type(), @@ -890,10 +923,15 @@ public class TestTagMetaService extends TestJDBCBackend { column.type(), new NameIdentifier[] {tagEntity1.nameIdentifier()}, new NameIdentifier[0]); + tagMetaService.associateTagsWithMetadataObject( + model.nameIdentifier(), + model.type(), + new NameIdentifier[] {tagEntity1.nameIdentifier()}, + new NameIdentifier[0]); CatalogMetaService.getInstance().deleteCatalog(catalog.nameIdentifier(), true); Assertions.assertEquals(0, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(12, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(14, countAllTagRel(tagEntity1.id())); // Test to drop a schema using cascade mode catalog = @@ -950,6 +988,17 @@ public class TestTagMetaService extends TestJDBCBackend { auditInfo); backend.insert(fileset, false); + model = + createModelEntity( + RandomIdGenerator.INSTANCE.nextId(), + Namespace.of(metalakeName, catalog.name(), schema.name()), + "model1", + "comment", + 1, + null, + auditInfo); + backend.insert(model, false); + tagMetaService.associateTagsWithMetadataObject( catalog.nameIdentifier(), catalog.type(), @@ -982,10 +1031,15 @@ public class TestTagMetaService extends TestJDBCBackend { column.type(), new NameIdentifier[] {tagEntity1.nameIdentifier()}, new NameIdentifier[0]); + tagMetaService.associateTagsWithMetadataObject( + model.nameIdentifier(), + model.type(), + new NameIdentifier[] {tagEntity1.nameIdentifier()}, + new NameIdentifier[0]); // Test to drop a schema SchemaMetaService.getInstance().deleteSchema(schema.nameIdentifier(), true); Assertions.assertEquals(1, countActiveTagRel(tagEntity1.id())); - Assertions.assertEquals(18, countAllTagRel(tagEntity1.id())); + Assertions.assertEquals(21, countAllTagRel(tagEntity1.id())); } }