This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch branch-0.9
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-0.9 by this push:
new 803daf8b75 [#6815] feat(core): Support update comment for model
version (#6949)
803daf8b75 is described below
commit 803daf8b7572ed25d994d9d87c43bce2bb305d46
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Apr 16 14:02:54 2025 +0800
[#6815] feat(core): Support update comment for model version (#6949)
### What changes were proposed in this pull request?
Support update comment for model version
- [x] PR1: Add ModelVersionChange API interface, Implement the update
comment logic in model catalog and JDBC backend logic, update related
event.
- [ ] PR2: Add REST endpoint to support model version change, add Java
client and Python client for model version comment update.
### Why are the changes needed?
Fix: #6815
### Does this PR introduce _any_ user-facing change?
User can update the comment of a model version.
### How was this patch tested?
local test.
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Lord of Abyss
<[email protected]>
Co-authored-by: roryqi <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jerry Shao <[email protected]>
Co-authored-by: yangyang zhong <[email protected]>
Co-authored-by: FANNG <[email protected]>
Co-authored-by: Eric Chang <[email protected]>
Co-authored-by: Mini Yu <[email protected]>
Co-authored-by: mchades <[email protected]>
---
.../org/apache/gravitino/model/ModelCatalog.java | 32 ++++
.../org/apache/gravitino/model/ModelChange.java | 4 +-
.../apache/gravitino/model/ModelVersionChange.java | 104 ++++++++++++
.../gravitino/model/TestModelVersionChange.java | 66 ++++++++
.../catalog/model/ModelCatalogOperations.java | 98 +++++++++++
.../catalog/model/TestModelCatalogOperations.java | 97 +++++++++++
.../gravitino/client/GenericModelCatalog.java | 17 ++
.../catalog/ModelNormalizeDispatcher.java | 17 ++
.../catalog/ModelOperationDispatcher.java | 44 +++++
.../apache/gravitino/hook/ModelHookDispatcher.java | 15 ++
.../gravitino/listener/ModelEventDispatcher.java | 51 ++++++
.../listener/api/event/AlterModelVersionEvent.java | 83 +++++++++
.../api/event/AlterModelVersionFailureEvent.java | 94 +++++++++++
.../api/event/AlterModelVersionPreEvent.java | 93 +++++++++++
.../listener/api/event/OperationType.java | 1 +
.../apache/gravitino/listener/api/info/Either.java | 110 ++++++++++++
.../gravitino/storage/relational/JDBCBackend.java | 2 +
.../relational/mapper/ModelVersionMetaMapper.java | 7 +
.../mapper/ModelVersionMetaSQLProviderFactory.java | 6 +
.../base/ModelVersionMetaBaseSQLProvider.java | 29 ++++
.../service/ModelVersionMetaService.java | 86 ++++++++++
.../storage/relational/utils/POConverters.java | 38 +++++
.../catalog/TestModelOperationDispatcher.java | 32 ++++
.../gravitino/connector/TestCatalogOperations.java | 88 ++++++++++
.../gravitino/listener/api/event/TestEither.java | 76 +++++++++
.../listener/api/event/TestModelEvent.java | 186 +++++++++++++++++++++
.../service/TestModelVersionMetaService.java | 91 ++++++++++
docs/gravitino-server-config.md | 4 +-
28 files changed, 1567 insertions(+), 4 deletions(-)
diff --git a/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
b/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
index 8d24ae7efe..fbcf4e8de2 100644
--- a/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
+++ b/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
@@ -251,4 +251,36 @@ public interface ModelCatalog {
*/
Model alterModel(NameIdentifier ident, ModelChange... changes)
throws NoSuchModelException, IllegalArgumentException;
+
+ /**
+ * Applies the specified {@link ModelVersionChange changes} to a model
version identified by its
+ * version number.
+ *
+ * <p>If any change is rejected by the implementation, no changes will be
applied.
+ *
+ * @param ident the {@link NameIdentifier} of the model to be altered
+ * @param version the version number of the model version to be altered
+ * @param changes one or more {@link ModelVersionChange} instances to apply
+ * @return the updated {@link ModelVersion} instance
+ * @throws NoSuchModelVersionException if the specified model version does
not exist
+ * @throws IllegalArgumentException if any change is rejected by the
implementation
+ */
+ ModelVersion alterModelVersion(NameIdentifier ident, int version,
ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException;
+
+ /**
+ * Applies the specified {@link ModelVersionChange changes} to a model
version identified by its
+ * alias.
+ *
+ * <p>If any change is rejected by the implementation, no changes will be
applied.
+ *
+ * @param ident the {@link NameIdentifier} of the model to be altered
+ * @param alias the alias of the model version to be altered
+ * @param changes one or more {@link ModelVersionChange} instances to apply
+ * @return the updated {@link ModelVersion} instance
+ * @throws NoSuchModelVersionException if the specified model version does
not exist
+ * @throws IllegalArgumentException if any change is rejected by the
implementation
+ */
+ ModelVersion alterModelVersion(NameIdentifier ident, String alias,
ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException;
}
diff --git a/api/src/main/java/org/apache/gravitino/model/ModelChange.java
b/api/src/main/java/org/apache/gravitino/model/ModelChange.java
index 513ad569e3..1534b9369a 100644
--- a/api/src/main/java/org/apache/gravitino/model/ModelChange.java
+++ b/api/src/main/java/org/apache/gravitino/model/ModelChange.java
@@ -105,7 +105,7 @@ public interface ModelChange {
*/
@Override
public int hashCode() {
- return newName.hashCode();
+ return Objects.hash(newName);
}
/**
@@ -239,7 +239,7 @@ public interface ModelChange {
*/
@Override
public int hashCode() {
- return property.hashCode();
+ return Objects.hash(property);
}
/**
diff --git
a/api/src/main/java/org/apache/gravitino/model/ModelVersionChange.java
b/api/src/main/java/org/apache/gravitino/model/ModelVersionChange.java
new file mode 100644
index 0000000000..281d1dcbb7
--- /dev/null
+++ b/api/src/main/java/org/apache/gravitino/model/ModelVersionChange.java
@@ -0,0 +1,104 @@
+/*
+ * 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.model;
+
+import java.util.Objects;
+import org.apache.gravitino.annotation.Evolving;
+
+/**
+ * A model version change is a change to a model version. It can be used to
update uri of a model
+ * version, update the comment of a model, set a property and value pair for a
model version, or
+ * remove a property from a model.
+ */
+@Evolving
+public interface ModelVersionChange {
+
+ /**
+ * Create a ModelVersionChange for updating the comment of a model version.
+ *
+ * @param newComment new comment to be set for the model version
+ * @return a new ModelVersionChange instance for updating the comment of a
model version
+ */
+ static ModelVersionChange updateComment(String newComment) {
+ return new ModelVersionChange.UpdateComment(newComment);
+ }
+
+ /** A ModelVersionChange to update the modelve version comment. */
+ final class UpdateComment implements ModelVersionChange {
+
+ private final String newComment;
+
+ /**
+ * Creates a new {@link UpdateComment} instance with the specified new
comment.
+ *
+ * @param newComment new comment to be set for the model version
+ */
+ public UpdateComment(String newComment) {
+ this.newComment = newComment;
+ }
+
+ /**
+ * Returns the new comment to be set for the model version.
+ *
+ * @return the new comment to be set for the model version
+ */
+ public String newComment() {
+ return newComment;
+ }
+
+ /**
+ * Compares this {@link UpdateComment} instance with another object for
equality. The comparison
+ * is based on the new comment of the model version.
+ *
+ * @param obj The object to compare with this instance.
+ * @return {@code true} if the given object represents the same model
update operation; {@code
+ * false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) return true;
+ if (!(obj instanceof UpdateComment)) return false;
+ UpdateComment other = (UpdateComment) obj;
+ return Objects.equals(newComment, other.newComment);
+ }
+
+ /**
+ * Generates a hash code for this {@link UpdateComment} instance. The hash
code is based on the
+ * new comment of the model.
+ *
+ * @return A hash code value for this model renaming operation.
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(newComment);
+ }
+
+ /**
+ * Returns a string representation of the {@link UpdateComment} instance.
This string format
+ * includes the class name followed by the comment to be updated.
+ *
+ * @return A string summary of the {@link UpdateComment} instance.
+ */
+ @Override
+ public String toString() {
+ return "UpdateComment " + newComment;
+ }
+ }
+}
diff --git
a/api/src/test/java/org/apache/gravitino/model/TestModelVersionChange.java
b/api/src/test/java/org/apache/gravitino/model/TestModelVersionChange.java
new file mode 100644
index 0000000000..bc4e9bb668
--- /dev/null
+++ b/api/src/test/java/org/apache/gravitino/model/TestModelVersionChange.java
@@ -0,0 +1,66 @@
+/*
+ * 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.model;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestModelVersionChange {
+ @Test
+ void testCreateUpdateVersionCommentChangeUseStaticMethod() {
+ String newComment = "new comment";
+ ModelVersionChange modelVersionChange =
ModelVersionChange.updateComment(newComment);
+ Assertions.assertEquals(ModelVersionChange.UpdateComment.class,
modelVersionChange.getClass());
+
+ ModelVersionChange.UpdateComment updateCommentChange =
+ (ModelVersionChange.UpdateComment) modelVersionChange;
+ Assertions.assertEquals(newComment, updateCommentChange.newComment());
+ Assertions.assertEquals("UpdateComment " + newComment,
updateCommentChange.toString());
+ }
+
+ @Test
+ void testCreateUpdateVersionCommentChangeUseConstructor() {
+ String newComment = "new comment";
+ ModelVersionChange modelVersionChange = new
ModelVersionChange.UpdateComment(newComment);
+ Assertions.assertEquals(ModelVersionChange.UpdateComment.class,
modelVersionChange.getClass());
+
+ ModelVersionChange.UpdateComment updateCommentChange =
+ (ModelVersionChange.UpdateComment) modelVersionChange;
+ Assertions.assertEquals(newComment, updateCommentChange.newComment());
+ Assertions.assertEquals("UpdateComment " + newComment,
updateCommentChange.toString());
+ }
+
+ @Test
+ void testUpdateVersionCommentChangeEquals() {
+ String newComment = "new comment";
+ String differentComment = "different comment";
+ ModelVersionChange modelVersionChange1 =
ModelVersionChange.updateComment(newComment);
+ ModelVersionChange modelVersionChange2 =
ModelVersionChange.updateComment(newComment);
+ ModelVersionChange modelVersionChange3 =
ModelVersionChange.updateComment(differentComment);
+
+ Assertions.assertEquals(modelVersionChange1, modelVersionChange2);
+ Assertions.assertNotEquals(modelVersionChange1, modelVersionChange3);
+ Assertions.assertNotEquals(modelVersionChange2, modelVersionChange3);
+
+ Assertions.assertEquals(modelVersionChange1.hashCode(),
modelVersionChange2.hashCode());
+ Assertions.assertNotEquals(modelVersionChange1.hashCode(),
modelVersionChange3.hashCode());
+ Assertions.assertNotEquals(modelVersionChange2.hashCode(),
modelVersionChange3.hashCode());
+ }
+}
diff --git
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogOperations.java
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogOperations.java
index 6ad4acb2b0..21d8612b83 100644
---
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogOperations.java
+++
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogOperations.java
@@ -49,6 +49,7 @@ import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelCatalog;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.apache.gravitino.utils.NamespaceUtil;
import org.apache.gravitino.utils.PrincipalUtils;
@@ -293,6 +294,28 @@ public class ModelCatalogOperations extends
ManagedSchemaOperations
}
}
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ NameIdentifierUtil.checkModel(ident);
+ NameIdentifier modelVersionIdent =
NameIdentifierUtil.toModelVersionIdentifier(ident, version);
+
+ return internalUpdateModelVersion(modelVersionIdent, changes);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ NameIdentifierUtil.checkModel(ident);
+ NameIdentifier modelVersionIdent =
NameIdentifierUtil.toModelVersionIdentifier(ident, alias);
+
+ return internalUpdateModelVersion(modelVersionIdent, changes);
+ }
+
private ModelEntity updateModelEntity(
NameIdentifier ident, ModelEntity modelEntity, ModelChange... changes) {
@@ -340,6 +363,81 @@ public class ModelCatalogOperations extends
ManagedSchemaOperations
.build();
}
+ private ModelVersion internalUpdateModelVersion(
+ NameIdentifier ident, ModelVersionChange... changes) {
+ NameIdentifier modelIdent = NameIdentifierUtil.toModelIdentifier(ident);
+ try {
+ if (!store.exists(modelIdent, Entity.EntityType.MODEL)) {
+ throw new NoSuchModelException("Model %s does not exist", modelIdent);
+ }
+
+ if (!store.exists(ident, Entity.EntityType.MODEL_VERSION)) {
+ throw new NoSuchModelVersionException("Model version %s does not
exist", ident);
+ }
+ } catch (IOException ioe) {
+ throw new RuntimeException("Failed to alter model version " + ident,
ioe);
+ }
+
+ try {
+ ModelVersionEntity updatedModelVersionEntity =
+ store.update(
+ ident,
+ ModelVersionEntity.class,
+ Entity.EntityType.MODEL_VERSION,
+ e -> updateModelVersionEntity(e, changes));
+
+ return toModelVersionImpl(updatedModelVersionEntity);
+
+ } catch (IOException ioe) {
+ throw new RuntimeException("Failed to load model version " + ident, ioe);
+ } catch (NoSuchEntityException nsee) {
+ throw new NoSuchModelVersionException(nsee, "Model Version %s does not
exist", ident);
+ }
+ }
+
+ private ModelVersionEntity updateModelVersionEntity(
+ ModelVersionEntity modelVersionEntity, ModelVersionChange... changes) {
+ NameIdentifier entityModelIdentifier =
modelVersionEntity.modelIdentifier();
+ int entityVersion = modelVersionEntity.version();
+ String entityComment = modelVersionEntity.comment();
+ List<String> entityAliases =
+ modelVersionEntity.aliases() == null
+ ? Lists.newArrayList()
+ : Lists.newArrayList(modelVersionEntity.aliases());
+ String entityUri = modelVersionEntity.uri();
+ Map<String, String> entityProperties =
+ modelVersionEntity.properties() == null
+ ? Maps.newHashMap()
+ : Maps.newHashMap(modelVersionEntity.properties());
+ AuditInfo entityAuditInfo = modelVersionEntity.auditInfo();
+ String modifier = PrincipalUtils.getCurrentPrincipal().getName();
+
+ for (ModelVersionChange change : changes) {
+ if (change instanceof ModelVersionChange.UpdateComment) {
+ entityComment = ((ModelVersionChange.UpdateComment)
change).newComment();
+ } else {
+ throw new IllegalArgumentException(
+ "Unsupported model version change: " +
change.getClass().getSimpleName());
+ }
+ }
+
+ return ModelVersionEntity.builder()
+ .withVersion(entityVersion)
+ .withModelIdentifier(entityModelIdentifier)
+ .withAliases(entityAliases)
+ .withComment(entityComment)
+ .withUri(entityUri)
+ .withProperties(entityProperties)
+ .withAuditInfo(
+ AuditInfo.builder()
+ .withCreator(entityAuditInfo.creator())
+ .withCreateTime(entityAuditInfo.createTime())
+ .withLastModifier(modifier)
+ .withLastModifiedTime(Instant.now())
+ .build())
+ .build();
+ }
+
private ModelImpl toModelImpl(ModelEntity model) {
return ModelImpl.builder()
.withName(model.name())
diff --git
a/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
b/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
index bb6c010456..2bb88497bc 100644
---
a/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
+++
b/catalogs/catalog-model/src/test/java/org/apache/gravtitino/catalog/model/TestModelCatalogOperations.java
@@ -70,6 +70,7 @@ import org.apache.gravitino.meta.SchemaVersion;
import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.storage.IdGenerator;
import org.apache.gravitino.storage.RandomIdGenerator;
import org.apache.gravitino.utils.NameIdentifierUtil;
@@ -798,6 +799,102 @@ public class TestModelCatalogOperations {
Assertions.assertEquals(newProperties, alteredModel.properties());
}
+ @Test
+ void testUpdateVersionCommentViaVersion() {
+ String schemaName = randomSchemaName();
+ createSchema(schemaName);
+
+ String modelName = "model1";
+ String modelComment = "model1 comment";
+
+ String versionComment = "version1 comment";
+ String versionNewComment = "new version1 comment";
+ String versionUri = "model_version_path";
+ String[] versionAliases = new String[] {"alias1", "alias2"};
+
+ NameIdentifier modelIdent =
+ NameIdentifierUtil.ofModel(METALAKE_NAME, CATALOG_NAME, schemaName,
modelName);
+ StringIdentifier stringId = StringIdentifier.fromId(idGenerator.nextId());
+ Map<String, String> properties =
StringIdentifier.newPropertiesWithId(stringId, null);
+
+ ops.registerModel(modelIdent, modelComment, properties);
+ StringIdentifier versionId = StringIdentifier.fromId(idGenerator.nextId());
+ Map<String, String> versionProperties =
StringIdentifier.newPropertiesWithId(versionId, null);
+
+ ops.linkModelVersion(modelIdent, versionUri, versionAliases,
versionComment, versionProperties);
+
+ // validate loaded model
+ Model loadedModel = ops.getModel(modelIdent);
+ Assertions.assertEquals(1, loadedModel.latestVersion());
+
+ // validate loaded version
+ ModelVersion loadedVersion = ops.getModelVersion(modelIdent, 0);
+ Assertions.assertEquals(0, loadedVersion.version());
+ Assertions.assertArrayEquals(versionAliases, loadedVersion.aliases());
+ Assertions.assertEquals(versionComment, loadedVersion.comment());
+ Assertions.assertEquals(versionUri, loadedVersion.uri());
+ Assertions.assertEquals(versionProperties, loadedVersion.properties());
+
+ // update comment via version and validate
+ ModelVersionChange updateCommentChange =
ModelVersionChange.updateComment(versionNewComment);
+ ModelVersion updatedModelVersion = ops.alterModelVersion(modelIdent, 0,
updateCommentChange);
+
+ Assertions.assertEquals(0, updatedModelVersion.version());
+ Assertions.assertEquals(versionNewComment, updatedModelVersion.comment());
+ Assertions.assertEquals(versionUri, updatedModelVersion.uri());
+ Assertions.assertEquals(versionProperties,
updatedModelVersion.properties());
+ }
+
+ @Test
+ void testUpdateVersionCommentViaAlias() {
+ String schemaName = randomSchemaName();
+ createSchema(schemaName);
+
+ String modelName = "model1";
+ String modelComment = "model1 comment";
+
+ String versionComment = "version1 comment";
+ String versionNewComment = "new version1 comment";
+ String versionUri = "model_version_path";
+ String[] versionAliases = new String[] {"alias1", "alias2"};
+ String versionAlias = versionAliases[0];
+
+ NameIdentifier modelIdent =
+ NameIdentifierUtil.ofModel(METALAKE_NAME, CATALOG_NAME, schemaName,
modelName);
+ StringIdentifier stringId = StringIdentifier.fromId(idGenerator.nextId());
+ Map<String, String> properties =
StringIdentifier.newPropertiesWithId(stringId, null);
+
+ ops.registerModel(modelIdent, modelComment, properties);
+ StringIdentifier versionId = StringIdentifier.fromId(idGenerator.nextId());
+ Map<String, String> versionProperties =
StringIdentifier.newPropertiesWithId(versionId, null);
+
+ ops.linkModelVersion(modelIdent, versionUri, versionAliases,
versionComment, versionProperties);
+
+ Model loadedModel = ops.getModel(modelIdent);
+
+ // validate loaded model
+ Assertions.assertEquals(1, loadedModel.latestVersion());
+
+ // validate loaded version via alias
+ ModelVersion loadedVersion = ops.getModelVersion(modelIdent, versionAlias);
+ Assertions.assertEquals(0, loadedVersion.version());
+ Assertions.assertArrayEquals(versionAliases, loadedVersion.aliases());
+ Assertions.assertEquals(versionComment, loadedVersion.comment());
+ Assertions.assertEquals(versionUri, loadedVersion.uri());
+ Assertions.assertEquals(versionProperties, loadedVersion.properties());
+
+ // update comment via alias and validate
+ ModelVersionChange updateCommentChange =
ModelVersionChange.updateComment(versionNewComment);
+ ModelVersion updatedModelVersion =
+ ops.alterModelVersion(modelIdent, versionAlias, updateCommentChange);
+
+ Assertions.assertEquals(0, updatedModelVersion.version());
+ Assertions.assertArrayEquals(versionAliases,
updatedModelVersion.aliases());
+ Assertions.assertEquals(versionNewComment, updatedModelVersion.comment());
+ Assertions.assertEquals(versionUri, updatedModelVersion.uri());
+ Assertions.assertEquals(versionProperties,
updatedModelVersion.properties());
+ }
+
private String randomSchemaName() {
return "schema_" + UUID.randomUUID().toString().replace("-", "");
}
diff --git
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModelCatalog.java
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModelCatalog.java
index 5a58275bd0..64d6a91b00 100644
---
a/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModelCatalog.java
+++
b/clients/client-java/src/main/java/org/apache/gravitino/client/GenericModelCatalog.java
@@ -50,6 +50,7 @@ import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelCatalog;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.rest.RESTUtils;
class GenericModelCatalog extends BaseSchemaCatalog implements ModelCatalog {
@@ -281,6 +282,22 @@ class GenericModelCatalog extends BaseSchemaCatalog
implements ModelCatalog {
return new GenericModel(resp.getModel(), restClient, modelFullNs);
}
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+ // TODO implement
+ return null;
+ }
+
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ // TODO implement
+ return null;
+ }
+
/** @return A new builder instance for {@link GenericModelCatalog}. */
public static Builder builder() {
return new Builder();
diff --git
a/core/src/main/java/org/apache/gravitino/catalog/ModelNormalizeDispatcher.java
b/core/src/main/java/org/apache/gravitino/catalog/ModelNormalizeDispatcher.java
index c73816f9a2..7e1632f544 100644
---
a/core/src/main/java/org/apache/gravitino/catalog/ModelNormalizeDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/catalog/ModelNormalizeDispatcher.java
@@ -35,6 +35,7 @@ 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.model.ModelVersionChange;
public class ModelNormalizeDispatcher implements ModelDispatcher {
private final CatalogManager catalogManager;
@@ -136,6 +137,22 @@ public class ModelNormalizeDispatcher implements
ModelDispatcher {
return dispatcher.alterModel(normalizeCaseSensitive(ident), changes);
}
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+ return dispatcher.alterModelVersion(normalizeCaseSensitive(ident),
version, changes);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ return dispatcher.alterModelVersion(normalizeCaseSensitive(ident), alias,
changes);
+ }
+
private Namespace normalizeCaseSensitive(Namespace namespace) {
Capability capabilities =
getCapability(NameIdentifier.of(namespace.levels()), catalogManager);
return applyCaseSensitive(namespace, Capability.Scope.MODEL, capabilities);
diff --git
a/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
b/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
index 88376ee5fd..ee7eb72014 100644
---
a/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
@@ -36,9 +36,12 @@ import org.apache.gravitino.exceptions.NoSuchSchemaException;
import org.apache.gravitino.lock.LockType;
import org.apache.gravitino.lock.TreeLockUtils;
import org.apache.gravitino.model.Model;
+import org.apache.gravitino.model.ModelCatalog;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.storage.IdGenerator;
+import org.apache.gravitino.utils.ThrowableFunction;
public class ModelOperationDispatcher extends OperationDispatcher implements
ModelDispatcher {
@@ -236,6 +239,47 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
alteredModel.properties()));
}
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelVersionException, IllegalArgumentException {
+ validateAlterProperties(ident,
HasPropertyMetadata::modelPropertiesMetadata, changes);
+ return executeAlterModelVersion(ident, f -> f.alterModelVersion(ident,
version, changes));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ validateAlterProperties(ident,
HasPropertyMetadata::modelPropertiesMetadata, changes);
+ return executeAlterModelVersion(ident, f -> f.alterModelVersion(ident,
alias, changes));
+ }
+
+ private ModelVersion executeAlterModelVersion(
+ NameIdentifier ident, ThrowableFunction<ModelCatalog, ModelVersion> fn) {
+ NameIdentifier catalogIdent = getCatalogIdentifier(ident);
+
+ ModelVersion alteredModelVersion =
+ TreeLockUtils.doWithTreeLock(
+ ident,
+ LockType.WRITE,
+ () ->
+ doWithCatalog(
+ catalogIdent,
+ c -> c.doWithModelOps(fn),
+ NoSuchModelVersionException.class,
+ IllegalArgumentException.class));
+
+ return EntityCombinedModelVersion.of(alteredModelVersion)
+ .withHiddenProperties(
+ getHiddenPropertyNames(
+ catalogIdent,
+ HasPropertyMetadata::modelPropertiesMetadata,
+ alteredModelVersion.properties()));
+ }
+
private ModelVersion internalGetModelVersion(
NameIdentifier ident, Supplier<ModelVersion> supplier) {
NameIdentifier catalogIdent = getCatalogIdentifier(ident);
diff --git
a/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java
b/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java
index af6723e844..e5f6a58612 100644
--- a/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java
+++ b/core/src/main/java/org/apache/gravitino/hook/ModelHookDispatcher.java
@@ -36,6 +36,7 @@ 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.model.ModelVersionChange;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.apache.gravitino.utils.PrincipalUtils;
@@ -173,4 +174,18 @@ public class ModelHookDispatcher implements
ModelDispatcher {
throws NoSuchModelException, IllegalArgumentException {
return dispatcher.alterModel(ident, changes);
}
+
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+ return dispatcher.alterModelVersion(ident, version, changes);
+ }
+
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ return dispatcher.alterModelVersion(ident, alias, changes);
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
b/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
index e5d91928fb..23c9a690e0 100644
--- a/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
+++ b/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
@@ -31,6 +31,9 @@ import org.apache.gravitino.exceptions.NoSuchSchemaException;
import org.apache.gravitino.listener.api.event.AlterModelEvent;
import org.apache.gravitino.listener.api.event.AlterModelFailureEvent;
import org.apache.gravitino.listener.api.event.AlterModelPreEvent;
+import org.apache.gravitino.listener.api.event.AlterModelVersionEvent;
+import org.apache.gravitino.listener.api.event.AlterModelVersionFailureEvent;
+import org.apache.gravitino.listener.api.event.AlterModelVersionPreEvent;
import org.apache.gravitino.listener.api.event.DeleteModelEvent;
import org.apache.gravitino.listener.api.event.DeleteModelFailureEvent;
import org.apache.gravitino.listener.api.event.DeleteModelPreEvent;
@@ -58,11 +61,13 @@ import
org.apache.gravitino.listener.api.event.RegisterAndLinkModelPreEvent;
import org.apache.gravitino.listener.api.event.RegisterModelEvent;
import org.apache.gravitino.listener.api.event.RegisterModelFailureEvent;
import org.apache.gravitino.listener.api.event.RegisterModelPreEvent;
+import org.apache.gravitino.listener.api.info.Either;
import org.apache.gravitino.listener.api.info.ModelInfo;
import org.apache.gravitino.listener.api.info.ModelVersionInfo;
import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.utils.PrincipalUtils;
/**
@@ -298,6 +303,52 @@ public class ModelEventDispatcher implements
ModelDispatcher {
}
}
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(
+ new AlterModelVersionPreEvent(initiator, ident, Either.right(version),
changes));
+ try {
+ ModelVersion modelVersion = dispatcher.alterModelVersion(ident, version,
changes);
+ eventBus.dispatchEvent(
+ new AlterModelVersionEvent(
+ initiator, ident, new ModelVersionInfo(modelVersion), changes));
+
+ return modelVersion;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(
+ new AlterModelVersionFailureEvent(initiator, ident, e,
Either.right(version), changes));
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+ String initiator = PrincipalUtils.getCurrentUserName();
+
+ eventBus.dispatchEvent(
+ new AlterModelVersionPreEvent(initiator, ident, Either.left(alias),
changes));
+ try {
+ ModelVersion modelVersion = dispatcher.alterModelVersion(ident, alias,
changes);
+ eventBus.dispatchEvent(
+ new AlterModelVersionEvent(
+ initiator, ident, new ModelVersionInfo(modelVersion), changes));
+
+ return modelVersion;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(
+ new AlterModelVersionFailureEvent(initiator, ident, e,
Either.left(alias), changes));
+ throw e;
+ }
+ }
+
/** {@inheritDoc} */
@Override
public int[] listModelVersions(NameIdentifier ident) throws
NoSuchModelException {
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionEvent.java
new file mode 100644
index 0000000000..b371995258
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionEvent.java
@@ -0,0 +1,83 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.ModelVersionInfo;
+import org.apache.gravitino.model.ModelVersionChange;
+
+/** Represents an event triggered when a model version is successfully
altered. */
+@DeveloperApi
+public class AlterModelVersionEvent extends ModelEvent {
+ private final ModelVersionInfo alteredModelVersionInfo;
+ private final ModelVersionChange[] modelVersionChanges;
+
+ /**
+ * Constructs a new {@link AlterModelVersionEvent} instance with specified
arguments.
+ *
+ * @param user The user who triggered the event.
+ * @param identifier the identifier of the model.
+ * @param alteredModelVersionInfo The post-alteration state of the model
version.
+ * @param modelVersionChanges An array of {@link ModelVersionChange} objects
representing the
+ * specific changes applied to the model version during the alteration
process.
+ */
+ public AlterModelVersionEvent(
+ String user,
+ NameIdentifier identifier,
+ ModelVersionInfo alteredModelVersionInfo,
+ ModelVersionChange[] modelVersionChanges) {
+ super(user, identifier);
+
+ this.alteredModelVersionInfo = alteredModelVersionInfo;
+ this.modelVersionChanges = modelVersionChanges;
+ }
+
+ /**
+ * Retrieves the updated state of the model version after the successful
alteration.
+ *
+ * @return A {@link ModelVersionInfo} instance encapsulating the details of
the altered model
+ * version.
+ */
+ public ModelVersionInfo alteredModelVersionInfo() {
+ return alteredModelVersionInfo;
+ }
+
+ /**
+ * Retrieves the specific changes that were made to the model version during
the alteration
+ * process.
+ *
+ * @return An array of {@link ModelVersionChange} objects detailing each
modification applied to
+ * the specified model version.
+ */
+ public ModelVersionChange[] modelVersionChanges() {
+ return modelVersionChanges;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionFailureEvent.java
new file mode 100644
index 0000000000..db1d666f4d
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionFailureEvent.java
@@ -0,0 +1,94 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.Either;
+import org.apache.gravitino.model.ModelVersionChange;
+
+/** Represents an event triggered when a model version alteration operation
fails. */
+@DeveloperApi
+public class AlterModelVersionFailureEvent extends ModelFailureEvent {
+ private final Either<String, Integer> aliasOrVersion;
+ private ModelVersionChange[] modelVersionChanges;
+
+ /**
+ * Constructs a new {@code AlterModelVersionFailureEvent} instance. Only one
of {@code alias} or
+ * {@code version} should be specified.
+ *
+ * @param user the user who triggered the event
+ * @param identifier the identifier of the model involved in the event
+ * @param exception the exception that caused the failure
+ * @param aliasOrVersion the alias or version of the model version involved
in the event
+ * @param modelVersionChanges an array of {@code ModelVersionChange}
instances that were attempted
+ * to be applied
+ */
+ public AlterModelVersionFailureEvent(
+ String user,
+ NameIdentifier identifier,
+ Exception exception,
+ Either<String, Integer> aliasOrVersion,
+ ModelVersionChange[] modelVersionChanges) {
+ super(user, identifier, exception);
+
+ this.aliasOrVersion = aliasOrVersion;
+ this.modelVersionChanges = modelVersionChanges;
+ }
+
+ /**
+ * Returns the alias of the model version involved in the event.
+ *
+ * @return if the left value of {@code aliasOrVersion} is not null, returns
the left value,
+ * otherwise throw IllegalStateException.
+ */
+ public String alias() {
+ return aliasOrVersion.getLeft();
+ }
+
+ /**
+ * Returns the version of the model version involved in the event.
+ *
+ * @return if the right value of {@code aliasOrVersion} is not null, returns
the right value,
+ * otherwise throw IllegalStateException.
+ */
+ public Integer version() {
+ return aliasOrVersion.getRight();
+ }
+
+ /**
+ * Returns the model version changes that were attempted.
+ *
+ * @return an array of {@code ModelVersionChange} instances
+ */
+ public ModelVersionChange[] modelVersionChanges() {
+ return modelVersionChanges;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionPreEvent.java
new file mode 100644
index 0000000000..3c2bbc1b65
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterModelVersionPreEvent.java
@@ -0,0 +1,93 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.Either;
+import org.apache.gravitino.model.ModelVersionChange;
+
+/** Represents an event triggered before a model version is successfully
altered. */
+@DeveloperApi
+public class AlterModelVersionPreEvent extends ModelPreEvent {
+
+ private final Either<String, Integer> aliasOrVersion;
+ private ModelVersionChange[] modelVersionChanges;
+
+ /**
+ * Constructs a new {@code AlterModelVersionPreEvent} instance. Only one of
{@code alias} or
+ * {@code version} should be specified.
+ *
+ * @param user the user who triggered the event
+ * @param identifier the identifier of the model involved in the event
+ * @param aliasOrVersion the alias or version of the model version involved
in the event
+ * @param modelVersionChanges an array of {@code ModelVersionChange}
instances representing the
+ * changes to apply
+ */
+ public AlterModelVersionPreEvent(
+ String user,
+ NameIdentifier identifier,
+ Either<String, Integer> aliasOrVersion,
+ ModelVersionChange[] modelVersionChanges) {
+ super(user, identifier);
+
+ this.aliasOrVersion = aliasOrVersion;
+ this.modelVersionChanges = modelVersionChanges;
+ }
+
+ /**
+ * Returns the alias of the model version involved in the event.
+ *
+ * @return if the left value of {@code aliasOrVersion} is not null, returns
the left value,
+ * otherwise throw an IllegalStateException exception.
+ */
+ public String alias() {
+ return aliasOrVersion.getLeft();
+ }
+
+ /**
+ * Returns the version of the model involved in the event.
+ *
+ * @return if the right value of {@code aliasOrVersion} is not null, returns
the right value,
+ * otherwise throw an IllegalStateException exception.
+ */
+ public Integer version() {
+ return aliasOrVersion.getRight();
+ }
+
+ /**
+ * Returns the model version changes to be applied.
+ *
+ * @return an array of {@code ModelVersionChange} instances
+ */
+ public ModelVersionChange[] modelVersionChanges() {
+ return modelVersionChanges;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
index aebf43c3ba..e5b443df51 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
@@ -112,6 +112,7 @@ public enum OperationType {
GET_MODEL_VERSION,
LIST_MODEL_VERSIONS,
REGISTER_AND_LINK_MODEL_VERSION,
+ ALTER_MODEL_VERSION,
// User
ADD_USER,
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/info/Either.java
b/core/src/main/java/org/apache/gravitino/listener/api/info/Either.java
new file mode 100644
index 0000000000..60ebadaef3
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/listener/api/info/Either.java
@@ -0,0 +1,110 @@
+/*
+ * 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.listener.api.info;
+
+import java.util.Optional;
+import org.glassfish.jersey.internal.guava.Preconditions;
+
+/**
+ * Either represents a value of two possible types (a disjoint union).
+ *
+ * @param <L> Left type
+ * @param <R> Right type
+ */
+public final class Either<L, R> {
+ private final Optional<L> left;
+ private final Optional<R> right;
+
+ /**
+ * Create a new {@code Either} instance with a left value.
+ *
+ * @param value Left value
+ * @return Either with left value
+ * @param <L> Left type
+ * @param <R> Right type
+ */
+ public static <L, R> Either<L, R> left(L value) {
+ Preconditions.checkArgument(value != null, "Left value cannot be null");
+ return new Either<>(Optional.of(value), Optional.empty());
+ }
+
+ /**
+ * Create a new {@code Either} instance with a right value.
+ *
+ * @param value Right value
+ * @return Either with right value
+ * @param <L> Left type
+ * @param <R> Right type
+ */
+ public static <L, R> Either<L, R> right(R value) {
+ Preconditions.checkArgument(value != null, "Right value cannot be null");
+ return new Either<>(Optional.empty(), Optional.of(value));
+ }
+
+ /** Private constructor. */
+ private Either(Optional<L> l, Optional<R> r) {
+ left = l;
+ right = r;
+ }
+
+ /**
+ * Returns true if this is a left value.
+ *
+ * @return True if this is a left value
+ */
+ public boolean isLeft() {
+ return left.isPresent();
+ }
+
+ /**
+ * Returns true if this is a right value.
+ *
+ * @return True if this is a right value
+ */
+ public boolean isRight() {
+ return right.isPresent();
+ }
+
+ /**
+ * Returns the left value if this is a left value, otherwise throws an
exception.
+ *
+ * @return Left value
+ * @throws IllegalStateException if this is a right value
+ */
+ public L getLeft() {
+ if (isRight()) {
+ throw new IllegalStateException("Not a left value");
+ }
+ return left.get();
+ }
+
+ /**
+ * Returns the right value if this is a right value, otherwise throws an
exception.
+ *
+ * @return Right value
+ * @throws IllegalStateException if this is a left value
+ */
+ public R getRight() {
+ if (isLeft()) {
+ throw new IllegalStateException("Not a right value");
+ }
+ return right.get();
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
index 3ce1c75f20..07965901dd 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java
@@ -205,6 +205,8 @@ public class JDBCBackend implements RelationalBackend {
return (E) TagMetaService.getInstance().updateTag(ident, updater);
case MODEL:
return (E) ModelMetaService.getInstance().updateModel(ident, updater);
+ case MODEL_VERSION:
+ return (E)
ModelVersionMetaService.getInstance().updateModelVersion(ident, updater);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for update operation", entityType);
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaMapper.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaMapper.java
index 6bd6fa5def..aa7cc7e365 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaMapper.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaMapper.java
@@ -90,4 +90,11 @@ public interface ModelVersionMetaMapper {
method = "deleteModelVersionMetasByLegacyTimeline")
Integer deleteModelVersionMetasByLegacyTimeline(
@Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit);
+
+ @UpdateProvider(
+ type = ModelVersionMetaSQLProviderFactory.class,
+ method = "updateModelVersionMeta")
+ Integer updateModelVersionMeta(
+ @Param("newModelVersionMeta") ModelVersionPO newModelVersionPO,
+ @Param("oldModelVersionMeta") ModelVersionPO oldModelVersionPO);
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaSQLProviderFactory.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaSQLProviderFactory.java
index 1f830f3551..3a5ef7fba1 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaSQLProviderFactory.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/ModelVersionMetaSQLProviderFactory.java
@@ -102,4 +102,10 @@ public class ModelVersionMetaSQLProviderFactory {
@Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit)
{
return
getProvider().deleteModelVersionMetasByLegacyTimeline(legacyTimeline, limit);
}
+
+ public static String updateModelVersionMeta(
+ @Param("newModelVersionMeta") ModelVersionPO newModelVersionPO,
+ @Param("oldModelVersionMeta") ModelVersionPO oldModelVersionPO) {
+ return getProvider().updateModelVersionMeta(newModelVersionPO,
oldModelVersionPO);
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ModelVersionMetaBaseSQLProvider.java
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ModelVersionMetaBaseSQLProvider.java
index a43f114b0b..6fffd7f56b 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ModelVersionMetaBaseSQLProvider.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/ModelVersionMetaBaseSQLProvider.java
@@ -147,4 +147,33 @@ public class ModelVersionMetaBaseSQLProvider {
+ ModelVersionMetaMapper.TABLE_NAME
+ " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT
#{limit}";
}
+
+ public String updateModelVersionMeta(
+ @Param("newModelVersionMeta") ModelVersionPO newModelVersionPO,
+ @Param("oldModelVersionMeta") ModelVersionPO oldModelVersionPO) {
+
+ return "UPDATE "
+ + ModelVersionMetaMapper.TABLE_NAME
+ + " SET "
+ + "metalake_id = #{newModelVersionMeta.metalakeId}, "
+ + "catalog_id = #{newModelVersionMeta.catalogId}, "
+ + "schema_id = #{newModelVersionMeta.schemaId}, "
+ + "model_id = #{newModelVersionMeta.modelId}, "
+ + "version = #{newModelVersionMeta.modelVersion}, "
+ + "model_version_comment = #{newModelVersionMeta.modelVersionComment},
"
+ + "model_version_properties =
#{newModelVersionMeta.modelVersionProperties}, "
+ + "model_version_uri = #{newModelVersionMeta.modelVersionUri}, "
+ + "audit_info = #{newModelVersionMeta.auditInfo}, "
+ + "deleted_at = #{newModelVersionMeta.deletedAt} "
+ + "WHERE model_id = #{oldModelVersionMeta.modelId} "
+ + "AND metalake_id = #{oldModelVersionMeta.metalakeId} "
+ + "AND catalog_id = #{oldModelVersionMeta.catalogId} "
+ + "AND schema_id = #{oldModelVersionMeta.schemaId} "
+ + "AND version = #{oldModelVersionMeta.modelVersion} "
+ + "AND model_version_comment =
#{oldModelVersionMeta.modelVersionComment} "
+ + "AND model_version_properties =
#{oldModelVersionMeta.modelVersionProperties} "
+ + "AND model_version_uri = #{oldModelVersionMeta.modelVersionUri} "
+ + "AND audit_info = #{oldModelVersionMeta.auditInfo} "
+ + "AND deleted_at = 0";
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
index 330a0b66eb..ab440e8c4d 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/ModelVersionMetaService.java
@@ -24,10 +24,13 @@ import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.gravitino.Entity;
+import org.apache.gravitino.HasIdentifier;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.exceptions.NoSuchEntityException;
@@ -44,6 +47,7 @@ import
org.apache.gravitino.storage.relational.utils.SessionUtils;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.apache.gravitino.utils.NamespaceUtil;
import org.glassfish.jersey.internal.guava.Lists;
+import org.glassfish.jersey.internal.guava.Preconditions;
public class ModelVersionMetaService {
@@ -247,4 +251,86 @@ public class ModelVersionMetaService {
return modelVersionDeletedCount[0] + modelVersionAliasRelDeletedCount[0];
}
+
+ /**
+ * Updates the model version entity.
+ *
+ * @param ident the {@link NameIdentifier} instance of the model version to
update
+ * @param updater the function to update the model version entity
+ * @return the updated model version entity
+ * @param <E> the type of the entity to update
+ * @throws IOException if an error occurs while updating the entity
+ */
+ public <E extends Entity & HasIdentifier> ModelVersionEntity
updateModelVersion(
+ NameIdentifier ident, Function<E, E> updater) throws IOException {
+ NameIdentifierUtil.checkModelVersion(ident);
+ NameIdentifier modelIdent = NameIdentifier.of(ident.namespace().levels());
+
+ boolean isVersionNumber = NumberUtils.isCreatable(ident.name());
+ ModelEntity modelEntity =
ModelMetaService.getInstance().getModelByIdentifier(modelIdent);
+
+ ModelVersionPO oldModelVersionPO =
+ SessionUtils.getWithoutCommit(
+ ModelVersionMetaMapper.class,
+ mapper -> {
+ if (isVersionNumber) {
+ return mapper.selectModelVersionMeta(
+ modelEntity.id(), Integer.valueOf(ident.name()));
+ } else {
+ return mapper.selectModelVersionMetaByAlias(modelEntity.id(),
ident.name());
+ }
+ });
+
+ if (oldModelVersionPO == null) {
+ throw new NoSuchEntityException(
+ NoSuchEntityException.NO_SUCH_ENTITY_MESSAGE,
+ Entity.EntityType.MODEL_VERSION.name().toLowerCase(Locale.ROOT),
+ ident.toString());
+ }
+
+ List<ModelVersionAliasRelPO> aliasRelPOs =
+ SessionUtils.getWithoutCommit(
+ ModelVersionAliasRelMapper.class,
+ mapper -> {
+ if (isVersionNumber) {
+ return mapper.selectModelVersionAliasRelsByModelIdAndVersion(
+ modelEntity.id(), Integer.valueOf(ident.name()));
+ } else {
+ return mapper.selectModelVersionAliasRelsByModelIdAndAlias(
+ modelEntity.id(), ident.name());
+ }
+ });
+
+ ModelVersionEntity oldModelVersionEntity =
+ POConverters.fromModelVersionPO(modelIdent, oldModelVersionPO,
aliasRelPOs);
+ ModelVersionEntity newModelVersionEntity =
+ (ModelVersionEntity) updater.apply((E) oldModelVersionEntity);
+
+ Preconditions.checkArgument(
+ Objects.equals(oldModelVersionEntity.version(),
newModelVersionEntity.version()),
+ "The updated model version: %s should be same with the table entity
version before: %s",
+ newModelVersionEntity.version(),
+ oldModelVersionEntity.version());
+
+ Integer updateResult;
+ try {
+ updateResult =
+ SessionUtils.doWithCommitAndFetchResult(
+ ModelVersionMetaMapper.class,
+ mapper ->
+ mapper.updateModelVersionMeta(
+ POConverters.updateModelVersionPO(oldModelVersionPO,
newModelVersionEntity),
+ oldModelVersionPO));
+ } catch (RuntimeException re) {
+ ExceptionUtils.checkSQLException(
+ re, Entity.EntityType.CATALOG,
newModelVersionEntity.nameIdentifier().toString());
+ throw re;
+ }
+
+ if (updateResult > 0) {
+ return newModelVersionEntity;
+ } else {
+ throw new IOException("Failed to update the entity: " + ident);
+ }
+ }
}
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
index 45abfe1ff2..36728458de 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/utils/POConverters.java
@@ -1376,6 +1376,14 @@ public class POConverters {
}
}
+ /**
+ * Updata ModelPO with new ModelEntity object, metalakeID, catalogID,
schemaID will be the same as
+ * the old one. the id, name, comment, properties, latestVersion and
auditInfo will be updated.
+ *
+ * @param oldModelPO the old ModelPO object
+ * @param newModel the new ModelEntity object
+ * @return the updated ModelPO object
+ */
public static ModelPO updateModelPO(ModelPO oldModelPO, ModelEntity
newModel) {
try {
return ModelPO.builder()
@@ -1395,6 +1403,36 @@ public class POConverters {
}
}
+ /**
+ * Update ModelVersionPO with new ModelVersionEntity object, metalakeID,
catalogID, schemaID and
+ * modelID will be the same as the old one. uri, comment, properties,
version and auditInfo will
+ * be updated.
+ *
+ * @param oldModelVersionPO the old ModelVersionPO object
+ * @param newModelVersion the new ModelVersionEntity object
+ * @return the updated ModelVersionPO object
+ */
+ public static ModelVersionPO updateModelVersionPO(
+ ModelVersionPO oldModelVersionPO, ModelVersionEntity newModelVersion) {
+ try {
+ return ModelVersionPO.builder()
+ .withModelId(oldModelVersionPO.getModelId())
+ .withMetalakeId(oldModelVersionPO.getMetalakeId())
+ .withCatalogId(oldModelVersionPO.getCatalogId())
+ .withSchemaId(oldModelVersionPO.getSchemaId())
+ .withModelVersionUri(newModelVersion.uri())
+ .withModelVersion(oldModelVersionPO.getModelVersion())
+ .withModelVersionComment(newModelVersion.comment())
+ .withModelVersionProperties(
+
JsonUtils.anyFieldMapper().writeValueAsString(newModelVersion.properties()))
+
.withAuditInfo(JsonUtils.anyFieldMapper().writeValueAsString(newModelVersion.auditInfo()))
+ .withDeletedAt(DEFAULT_DELETED_AT)
+ .build();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("Failed to serialize json object:", e);
+ }
+ }
+
public static ModelVersionPO initializeModelVersionPO(
ModelVersionEntity modelVersionEntity, ModelVersionPO.Builder builder) {
try {
diff --git
a/core/src/test/java/org/apache/gravitino/catalog/TestModelOperationDispatcher.java
b/core/src/test/java/org/apache/gravitino/catalog/TestModelOperationDispatcher.java
index 24d48c7fed..40c3520bc5 100644
---
a/core/src/test/java/org/apache/gravitino/catalog/TestModelOperationDispatcher.java
+++
b/core/src/test/java/org/apache/gravitino/catalog/TestModelOperationDispatcher.java
@@ -41,6 +41,7 @@ import org.apache.gravitino.lock.LockManager;
import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -363,6 +364,37 @@ public class TestModelOperationDispatcher extends
TestOperationDispatcher {
Assertions.assertEquals(ImmutableMap.of("k2", "v2"),
alteredModel.properties());
}
+ @Test
+ void testUpdateModelComment() {
+ String schemaName = randomSchemaName();
+ String schemaComment = "schema which tests update";
+
+ String modelName = randomModelName();
+ String modelComment = "model which tests update";
+ Map<String, String> props = ImmutableMap.of("k1", "v1", "k2", "v2");
+
+ String versionUri = "s3://test-bucket/test-path/model.json";
+ String[] versionAliases = {"alias1", "alias2"};
+ String versionComment = "version which tests update";
+ String versionNewComment = "new version comment";
+
+ NameIdentifier schemaIdent = NameIdentifier.of(metalake, catalog,
schemaName);
+ schemaOperationDispatcher.createSchema(schemaIdent, schemaComment, props);
+
+ NameIdentifier modelIdent =
+ NameIdentifierUtil.ofModel(metalake, catalog, schemaName, modelName);
+ modelOperationDispatcher.registerModel(modelIdent, modelComment, props);
+
+ modelOperationDispatcher.linkModelVersion(
+ modelIdent, versionUri, versionAliases, versionComment, props);
+ ModelVersionChange changeComment =
ModelVersionChange.updateComment(versionNewComment);
+ ModelVersion modelVersion =
modelOperationDispatcher.getModelVersion(modelIdent, "alias1");
+ ModelVersion alteredModelVersion =
+ modelOperationDispatcher.alterModelVersion(modelIdent, "alias1",
changeComment);
+
+ Assertions.assertEquals(modelVersion.uri(), alteredModelVersion.uri());
+ }
+
private String randomSchemaName() {
return "schema_" + UUID.randomUUID().toString().replace("-", "");
}
diff --git
a/core/src/test/java/org/apache/gravitino/connector/TestCatalogOperations.java
b/core/src/test/java/org/apache/gravitino/connector/TestCatalogOperations.java
index 4e0d710871..cb4b55833a 100644
---
a/core/src/test/java/org/apache/gravitino/connector/TestCatalogOperations.java
+++
b/core/src/test/java/org/apache/gravitino/connector/TestCatalogOperations.java
@@ -81,6 +81,7 @@ import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelCatalog;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.rel.Column;
import org.apache.gravitino.rel.Table;
import org.apache.gravitino.rel.TableCatalog;
@@ -976,6 +977,93 @@ public class TestCatalogOperations
return updatedModel;
}
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+
+ if (!models.containsKey(ident)) {
+ throw new NoSuchModelVersionException("Model %s does not exist", ident);
+ }
+
+ Pair<NameIdentifier, Integer> versionPair = Pair.of(ident, version);
+ if (!modelVersions.containsKey(versionPair)) {
+ throw new NoSuchModelVersionException("Model version %s does not exist",
versionPair);
+ }
+
+ return internalUpdateModelVersion(ident, version, changes);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion alterModelVersion(
+ NameIdentifier ident, String alias, ModelVersionChange... changes)
+ throws NoSuchModelException, IllegalArgumentException {
+
+ if (!models.containsKey(ident)) {
+ throw new NoSuchModelVersionException("Model %s does not exist", ident);
+ }
+
+ Pair<NameIdentifier, String> aliasPair = Pair.of(ident, alias);
+ if (!modelAliasToVersion.containsKey(aliasPair)) {
+ throw new NoSuchModelVersionException("Model version %s does not exist",
alias);
+ }
+
+ int version = modelAliasToVersion.get(aliasPair);
+ Pair<NameIdentifier, Integer> versionPair = Pair.of(ident, version);
+ if (!modelVersions.containsKey(versionPair)) {
+ throw new NoSuchModelVersionException("Model version %s does not exist",
versionPair);
+ }
+
+ return internalUpdateModelVersion(ident, version, changes);
+ }
+
+ private ModelVersion internalUpdateModelVersion(
+ NameIdentifier ident, int version, ModelVersionChange... changes)
+ throws NoSuchModelException, NoSuchModelVersionException,
IllegalArgumentException {
+
+ Pair<NameIdentifier, Integer> versionPair = Pair.of(ident, version);
+ AuditInfo updatedAuditInfo =
+ AuditInfo.builder()
+ .withCreator("test")
+ .withCreateTime(Instant.now())
+ .withLastModifier("test")
+ .withLastModifiedTime(Instant.now())
+ .build();
+
+ TestModelVersion testModelVersion = modelVersions.get(versionPair);
+ Map<String, String> newProps =
+ testModelVersion.properties() != null
+ ? Maps.newHashMap(testModelVersion.properties())
+ : Maps.newHashMap();
+ String newComment = testModelVersion.comment();
+ int newVersion = testModelVersion.version();
+ String[] newAliases = testModelVersion.aliases();
+ String newUri = testModelVersion.uri();
+
+ for (ModelVersionChange change : changes) {
+ if (change instanceof ModelVersionChange.UpdateComment) {
+ newComment = ((ModelVersionChange.UpdateComment) change).newComment();
+ } else {
+ throw new IllegalArgumentException("Unsupported model change: " +
change);
+ }
+ }
+
+ TestModelVersion updatedModelVersion =
+ TestModelVersion.builder()
+ .withVersion(newVersion)
+ .withComment(newComment)
+ .withProperties(newProps)
+ .withAuditInfo(updatedAuditInfo)
+ .withUri(newUri)
+ .withAliases(newAliases)
+ .build();
+
+ modelVersions.put(versionPair, updatedModelVersion);
+ return updatedModelVersion;
+ }
+
private boolean hasCallerContext() {
return CallerContext.CallerContextHolder.get() != null
&& CallerContext.CallerContextHolder.get().context() != null
diff --git
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestEither.java
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestEither.java
new file mode 100644
index 0000000000..de331b013d
--- /dev/null
+++ b/core/src/test/java/org/apache/gravitino/listener/api/event/TestEither.java
@@ -0,0 +1,76 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.listener.api.info.Either;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestEither {
+
+ @Test
+ void testLeftValue() {
+ Either<String, Integer> either = Either.left("alias");
+
+ Assertions.assertTrue(either.isLeft());
+ Assertions.assertFalse(either.isRight());
+ Assertions.assertEquals("alias", either.getLeft());
+ }
+
+ @Test
+ void testRightValue() {
+ Either<String, Integer> either = Either.right(42);
+
+ Assertions.assertTrue(either.isRight());
+ Assertions.assertFalse(either.isLeft());
+ Assertions.assertEquals(42, either.getRight());
+ }
+
+ @Test
+ void testGetLeftThrowsOnRight() {
+ Either<String, Integer> either = Either.right(99);
+
+ IllegalStateException exception =
+ Assertions.assertThrows(IllegalStateException.class, either::getLeft);
+ Assertions.assertEquals("Not a left value", exception.getMessage());
+ }
+
+ @Test
+ void testGetRightThrowsOnLeft() {
+ Either<String, Integer> either = Either.left("lefty");
+
+ IllegalStateException exception =
+ Assertions.assertThrows(IllegalStateException.class, either::getRight);
+ Assertions.assertEquals("Not a right value", exception.getMessage());
+ }
+
+ @Test
+ void testToStringReadable() {
+ Either<String, Integer> left = Either.left("model_v1");
+ Either<String, Integer> right = Either.right(3);
+
+ // Optional checks — not essential but good to verify Optional usage
+ Assertions.assertTrue(left.isLeft());
+ Assertions.assertEquals("model_v1", left.getLeft());
+
+ Assertions.assertTrue(right.isRight());
+ Assertions.assertEquals(3, right.getRight());
+ }
+}
diff --git
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
index c86b83040f..f0d7b391ca 100644
---
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
+++
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
@@ -40,6 +40,7 @@ import
org.apache.gravitino.listener.api.info.ModelVersionInfo;
import org.apache.gravitino.model.Model;
import org.apache.gravitino.model.ModelChange;
import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.model.ModelVersionChange;
import org.apache.gravitino.utils.NameIdentifierUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -54,7 +55,11 @@ public class TestModelEvent {
private Model modelA;
private Model modelB;
private Model alterNameModel;
+ private ModelVersion alterCommentModelVersion;
+ private ModelVersion otherAlterCommentModelVersion;
private ModelChange modelRenameChange;
+ private String newModelVersionComment;
+ private ModelVersionChange modelUpdateCommentChange;
private NameIdentifier existingIdentA;
private NameIdentifier existingIdentB;
private NameIdentifier notExistingIdent;
@@ -64,6 +69,7 @@ public class TestModelEvent {
@BeforeAll
void init() {
+ this.newModelVersionComment = "new comment";
this.namespace = Namespace.of("metalake", "catalog", "schema");
this.existingIdentA = NameIdentifierUtil.ofModel("metalake", "catalog",
"schema", "modelA");
this.existingIdentB = NameIdentifierUtil.ofModel("metalake", "catalog",
"schema", "modelB");
@@ -71,7 +77,22 @@ public class TestModelEvent {
this.modelA = getMockModel("modelA", "commentA");
this.modelB = getMockModel("modelB", "commentB");
this.alterNameModel = getMockModel("modelA_rename", "commentA");
+ this.alterCommentModelVersion =
+ getMockModelVersion(
+ "uriA",
+ 1,
+ new String[] {"aliasProduction"},
+ newModelVersionComment,
+ ImmutableMap.of("color", "#FFFFFF"));
+ this.otherAlterCommentModelVersion =
+ getMockModelVersion(
+ "uriB",
+ 2,
+ new String[] {"aliasTest"},
+ newModelVersionComment,
+ ImmutableMap.of("color", "#FFFFFF"));
this.modelRenameChange = getMockModelChange("modelA_rename");
+ this.modelUpdateCommentChange = getMockModelVersionChange("new comment");
this.firstModelVersion =
mockModelVersion("uriA", new String[] {"aliasProduction"},
"versionInfoA");
@@ -786,6 +807,147 @@ public class TestModelEvent {
});
}
+ @Test
+ void testAlterModelVersionPreEventWithVersion() {
+ dispatcher.alterModelVersion(existingIdentA, 1, modelUpdateCommentChange);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(AlterModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ AlterModelVersionPreEvent alterModelVersionPreEvent =
(AlterModelVersionPreEvent) preEvent;
+ ModelVersionChange[] changes =
alterModelVersionPreEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+
+ // validate alias and version fields
+ Assertions.assertEquals(1, alterModelVersionPreEvent.version());
+ }
+
+ @Test
+ void testAlterModelVersionPreEventWithAlias() {
+ dispatcher.alterModelVersion(existingIdentB, "aliasTest",
modelUpdateCommentChange);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(AlterModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ AlterModelVersionPreEvent alterModelVersionPreEvent =
(AlterModelVersionPreEvent) preEvent;
+ ModelVersionChange[] changes =
alterModelVersionPreEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+
+ // validate alias and version fields
+ Assertions.assertEquals("aliasTest", alterModelVersionPreEvent.alias());
+ }
+
+ @Test
+ void testAlterModelVersionEventWithVersion() {
+ dispatcher.alterModelVersion(existingIdentA, 1, modelUpdateCommentChange);
+
+ // validate post-event
+ Event postEvent = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(AlterModelVersionEvent.class,
postEvent.getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
postEvent.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS,
postEvent.operationStatus());
+
+ AlterModelVersionEvent alterModelVersionEvent = (AlterModelVersionEvent)
postEvent;
+ ModelVersionChange[] changes =
alterModelVersionEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+ ModelVersionInfo modelVersionInfo =
alterModelVersionEvent.alteredModelVersionInfo();
+
+ // validate ModelVersionInfo
+ Assertions.assertEquals("uriA", modelVersionInfo.uri());
+ Assertions.assertTrue(modelVersionInfo.aliases().isPresent());
+ Assertions.assertArrayEquals(
+ new String[] {"aliasProduction"}, modelVersionInfo.aliases().get());
+ Assertions.assertTrue(modelVersionInfo.comment().isPresent());
+ Assertions.assertEquals(newModelVersionComment,
modelVersionInfo.comment().get());
+ Assertions.assertEquals(ImmutableMap.of("color", "#FFFFFF"),
modelVersionInfo.properties());
+ }
+
+ @Test
+ void testAlterModelVersionEventWithAlias() {
+ dispatcher.alterModelVersion(existingIdentB, "aliasTest",
modelUpdateCommentChange);
+
+ // validate post-event
+ Event postEvent = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(AlterModelVersionEvent.class,
postEvent.getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
postEvent.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS,
postEvent.operationStatus());
+
+ AlterModelVersionEvent alterModelVersionEvent = (AlterModelVersionEvent)
postEvent;
+ ModelVersionChange[] changes =
alterModelVersionEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+ ModelVersionInfo modelVersionInfo =
alterModelVersionEvent.alteredModelVersionInfo();
+
+ // validate ModelVersionInfo
+ Assertions.assertEquals("uriB", modelVersionInfo.uri());
+ Assertions.assertTrue(modelVersionInfo.aliases().isPresent());
+ Assertions.assertArrayEquals(new String[] {"aliasTest"},
modelVersionInfo.aliases().get());
+ Assertions.assertTrue(modelVersionInfo.comment().isPresent());
+ Assertions.assertEquals(newModelVersionComment,
modelVersionInfo.comment().get());
+ Assertions.assertEquals(ImmutableMap.of("color", "#FFFFFF"),
modelVersionInfo.properties());
+ }
+
+ @Test
+ void testAlterModelVersionFailureEventWithVersion() {
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class,
+ () -> failureDispatcher.alterModelVersion(existingIdentA, 1,
modelUpdateCommentChange));
+
+ // validate failure event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(AlterModelVersionFailureEvent.class,
event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class,
+ ((AlterModelVersionFailureEvent) event).exception().getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+
+ AlterModelVersionFailureEvent alterModelVersionFailureEvent =
+ (AlterModelVersionFailureEvent) event;
+ ModelVersionChange[] changes =
alterModelVersionFailureEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+
+ // validate alias and version fields
+ Assertions.assertEquals(1, alterModelVersionFailureEvent.version());
+ }
+
+ @Test
+ void testAlterModelVersionFailureEventWithAlias() {
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class,
+ () ->
+ failureDispatcher.alterModelVersion(
+ existingIdentB, "aliasTest", modelUpdateCommentChange));
+
+ // validate failure event
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(AlterModelVersionFailureEvent.class,
event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class,
+ ((AlterModelVersionFailureEvent) event).exception().getClass());
+ Assertions.assertEquals(OperationType.ALTER_MODEL_VERSION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+
+ AlterModelVersionFailureEvent alterModelVersionFailureEvent =
+ (AlterModelVersionFailureEvent) event;
+ ModelVersionChange[] changes =
alterModelVersionFailureEvent.modelVersionChanges();
+ Assertions.assertEquals(1, changes.length);
+ Assertions.assertEquals(modelUpdateCommentChange, changes[0]);
+
+ // validate alias and version fields
+ Assertions.assertEquals("aliasTest",
alterModelVersionFailureEvent.alias());
+ }
+
private ModelDispatcher mockModelDispatcher() {
ModelDispatcher dispatcher = mock(ModelDispatcher.class);
@@ -821,6 +983,11 @@ public class TestModelEvent {
when(dispatcher.alterModel(existingIdentA, new ModelChange[]
{modelRenameChange}))
.thenReturn(alterNameModel);
+ when(dispatcher.alterModelVersion(existingIdentA, 1,
modelUpdateCommentChange))
+ .thenReturn(alterCommentModelVersion);
+ when(dispatcher.alterModelVersion(existingIdentB, "aliasTest",
modelUpdateCommentChange))
+ .thenReturn(otherAlterCommentModelVersion);
+
return dispatcher;
}
@@ -839,6 +1006,18 @@ public class TestModelEvent {
return mockModel;
}
+ private ModelVersion getMockModelVersion(
+ String uri, int version, String[] aliases, String comment, Map<String,
String> properties) {
+ ModelVersion mockModelVersion = mock(ModelVersion.class);
+ when(mockModelVersion.version()).thenReturn(version);
+ when(mockModelVersion.uri()).thenReturn(uri);
+ when(mockModelVersion.aliases()).thenReturn(aliases);
+ when(mockModelVersion.comment()).thenReturn(comment);
+ when(mockModelVersion.properties()).thenReturn(properties);
+
+ return mockModelVersion;
+ }
+
private Model getMockModelWithAudit(String name, String comment) {
Model model = getMockModel(name, comment);
Audit mockAudit = mock(Audit.class);
@@ -940,4 +1119,11 @@ public class TestModelEvent {
return mockObject;
}
+
+ private ModelVersionChange getMockModelVersionChange(String newName) {
+ ModelVersionChange.UpdateComment mockObject =
mock(ModelVersionChange.UpdateComment.class);
+ when(mockObject.newComment()).thenReturn(newName);
+
+ return mockObject;
+ }
}
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestModelVersionMetaService.java
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestModelVersionMetaService.java
index 0797147633..f1206f7959 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestModelVersionMetaService.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestModelVersionMetaService.java
@@ -18,12 +18,15 @@
*/
package org.apache.gravitino.storage.relational.service;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.time.Instant;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
+import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
@@ -35,6 +38,7 @@ import org.apache.gravitino.meta.ModelEntity;
import org.apache.gravitino.meta.ModelVersionEntity;
import org.apache.gravitino.storage.RandomIdGenerator;
import org.apache.gravitino.storage.relational.TestJDBCBackend;
+import org.apache.gravitino.utils.NameIdentifierUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@@ -461,6 +465,89 @@ public class TestModelVersionMetaService extends
TestJDBCBackend {
verifyModelVersionExists(getModelVersionIdent(modelEntity.nameIdentifier(),
"alias2"));
}
+ @Test
+ void testUpdateVersionComment() throws IOException {
+ createParentEntities(METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, auditInfo);
+
+ Map<String, String> properties = ImmutableMap.of("k1", "v1");
+ String modelName = randomModelName();
+ String modelComment = "model1 comment";
+ String modelVersionUri = "S3://test/path/to/model/version";
+ List<String> modelVersionAliases = ImmutableList.of("alias1", "alias2");
+ String modelVersionComment = "test comment";
+ String updatedComment = "new comment";
+ int version = 0;
+
+ ModelEntity modelEntity =
+ createModelEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ MODEL_NS,
+ modelName,
+ modelComment,
+ 0,
+ properties,
+ auditInfo);
+
+ ModelVersionEntity modelVersionEntity =
+ createModelVersionEntity(
+ modelEntity.nameIdentifier(),
+ version,
+ modelVersionUri,
+ modelVersionAliases,
+ modelVersionComment,
+ properties,
+ auditInfo);
+
+ ModelVersionEntity updatedModelVersionEntity =
+ createModelVersionEntity(
+ modelVersionEntity.modelIdentifier(),
+ modelVersionEntity.version(),
+ modelVersionEntity.uri(),
+ modelVersionEntity.aliases(),
+ updatedComment,
+ modelVersionEntity.properties(),
+ modelVersionEntity.auditInfo());
+
+ Assertions.assertDoesNotThrow(
+ () -> ModelMetaService.getInstance().insertModel(modelEntity, false));
+
+ Assertions.assertDoesNotThrow(
+ () ->
ModelVersionMetaService.getInstance().insertModelVersion(modelVersionEntity));
+
+ Function<ModelVersionEntity, ModelVersionEntity> updateCommentUpdater =
+ oldModelVersionEntity -> updatedModelVersionEntity;
+
+ ModelVersionEntity alteredModelVersionEntity =
+ ModelVersionMetaService.getInstance()
+ .updateModelVersion(modelVersionEntity.nameIdentifier(),
updateCommentUpdater);
+
+ Assertions.assertEquals(updatedModelVersionEntity,
alteredModelVersionEntity);
+
+ // Test update a non-exist model
+ Assertions.assertThrows(
+ NoSuchEntityException.class,
+ () ->
+ ModelVersionMetaService.getInstance()
+ .updateModelVersion(
+ NameIdentifierUtil.ofModelVersion(
+ METALAKE_NAME,
+ CATALOG_NAME,
+ SCHEMA_NAME,
+ "non_exist_model",
+ "non_exist_version"),
+ updateCommentUpdater));
+
+ // Test update a non-exist model version
+ Assertions.assertThrows(
+ NoSuchEntityException.class,
+ () ->
+ ModelVersionMetaService.getInstance()
+ .updateModelVersion(
+ NameIdentifierUtil.ofModelVersion(
+ METALAKE_NAME, CATALOG_NAME, SCHEMA_NAME, modelName,
"non_exist_version"),
+ updateCommentUpdater));
+ }
+
private NameIdentifier getModelVersionIdent(NameIdentifier modelIdent, int
version) {
List<String> parts = Lists.newArrayList(modelIdent.namespace().levels());
parts.add(modelIdent.name());
@@ -488,4 +575,8 @@ public class TestModelVersionMetaService extends
TestJDBCBackend {
Assertions.assertFalse(ModelVersionMetaService.getInstance().deleteModelVersion(ident));
}
+
+ private String randomModelName() {
+ return "model_" + UUID.randomUUID().toString().replace("-", "");
+ }
}
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index 5c41b8aa3c..87ff1d56fa 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -128,7 +128,7 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| metalake operation | `CreateMetalakeEvent`,
`AlterMetalakeEvent`, `DropMetalakeEvent`, `LoadMetalakeEvent`,
`ListMetalakeEvent`, `CreateMetalakeFailureEvent`, `AlterMetalakeFailureEvent`,
`DropMetalakeFailureEvent`, `LoadMetalakeFailureEvent`,
`ListMetalakeFailureEvent`
[...]
| Iceberg REST server table operation | `IcebergCreateTableEvent`,
`IcebergUpdateTableEvent`, `IcebergDropTableEvent`, `IcebergLoadTableEvent`,
`IcebergListTableEvent`, `IcebergTableExistsEvent`, `IcebergRenameTableEvent`,
`IcebergCreateTableFailureEvent`, `IcebergUpdateTableFailureEvent`,
`IcebergDropTableFailureEvent`, `IcebergLoadTableFailureEvent`,
`IcebergListTableFailureEvent`, `IcebergRenameTableFailureEvent`,
`IcebergTableExistsFailureEvent` [...]
| tag operation | `ListTagsEvent`, `ListTagsInfoEvent`,
`CreateTagEvent`, `GetTagEvent`, `AlterTagEvent`, `DeleteTagEvent`,
`ListMetadataObjectsForTagEvent`, `ListTagsForMetadataObjectEvent`,
`ListTagsInfoForMetadataObjectEvent`, `AssociateTagsForMetadataObjectEvent`,
`GetTagForMetadataObjectEvent`, `ListTagsFailureEvent`,
`ListTagInfoFailureEvent`, `CreateTagFailureEvent`, `GetTagFailureEvent`,
`AlterTagFailureEvent`, `DeleteTagFailureEvent`, `ListMetadataObjectsFo [...]
-| model operation | `DeleteModelEvent`,
`DeleteModelVersionEvent`, `GetModelEvent`, `GetModelVersionEvent`,
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,
`RegisterAndLinkModelEvent`, `RegisterModelEvent`, `DeleteModelFailureEvent`,
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`,
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`,
`ListModelFailureEvent`, `ListModelVersionFailureEvent`,
`RegisterAndLinkModelFailureEvent`, [...]
+| model operation | `DeleteModelEvent`,
`DeleteModelVersionEvent`, `GetModelEvent`, `GetModelVersionEvent`,
`LinkModelVersionEvent`, `ListModelEvent`, `ListModelVersionsEvent`,
`RegisterAndLinkModelEvent`, `RegisterModelEvent`,
`AlterModelVersionEvent`,`DeleteModelFailureEvent`,
`DeleteModelVersionFailureEvent`, `GetModelFailureEvent`,
`GetModelVersionFailureEvent`, `LinkModelVersionFailureEvent`,
`ListModelFailureEvent`, `ListModelVersionFailureEvent`, `RegisterAn [...]
| user operation | `AddUserEvent`, `GetUserEvent`,
`ListUserNamesEvent`, `ListUsersEvent`, `RemoveUserEvent`,
`GrantUserRolesEvent`, `RevokeUserRolesEvent`, `AddUserFailureEvent`,
`GetUserFailureEvent`, `GrantUserRolesFailureEvent`,
`ListUserNamesFailureEvent`, `ListUsersFailureEvent`, `RemoveUserFailureEvent`,
`RevokeUserRolesFailureEvent`
[...]
| group operation | `AddGroupEvent`, `GetGroupEvent`,
`ListGroupNamesEvent`, `ListGroupsEvent`, `RemoveGroupEvent`,
`GrantGroupRolesEvent`, `RevokeGroupRolesEvent`, `AddGroupFailureEvent`,
`GetGroupFailureEvent`, `GrantGroupRolesFailureEvent`,
`ListGroupNamesFailureEvent`, `ListGroupsFailureEvent`,
`RemoveGroupFailureEvent`, `RevokeGroupRolesFailureEvent`
[...]
| role operation | `CreateRoleEvent`, `DeleteRoleEvent`,
`GetRoleEvent`, `GrantPrivilegesEvent`, `ListRoleNamesEvent`,
`RevokePrivilegesEvent`, `CreateRoleFailureEvent`, `DeleteRoleFailureEvent`,
`GetRoleFailureEvent`, `GrantPrivilegesFailureEvent`,
`ListRoleNamesFailureEvent`, `RevokePrivilegesFailureEvent`
[...]
@@ -146,7 +146,7 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| Gravitino server metalake operation | `CreateMetalakePreEvent`,
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
| 0.8.0-incubating |
| Gravitino server partition operation | `AddPartitionPreEvent`,
`DropPartitionPreEvent`, `GetPartitionPreEvent`,
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`
| 0.8.0-incubating |
| Gravitino server fileset operation | `CreateFilesetPreEvent`,
`AlterFilesetPreEvent`, `DropFilesetPreEvent`,
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`
| 0.8.0-incubating |
-| Gravitino server model operation | `DeleteModelPreEvent`,
`DeleteModelVersionPreEvent`,
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`,
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`
| 0.9.0-incubating |
+| Gravitino server model operation | `DeleteModelPreEvent`,
`DeleteModelVersionPreEvent`,
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`,
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`,
`AlterModelPreEvent`, `AlterModelVersionPreEvent`, `AlterModelVersionPreEvent`
| 0.9.0-incubating |
| Gravitino server tag operation | `ListTagsPreEvent`,
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`,
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`,
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`,
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` |
0.9.0-incubating |
| Gravitino server user operation | `AddUserPreEvent`, `GetUserPreEvent`,
`ListUserNamesPreEvent`, `ListUsersPreEvent`, `RemoveUserPreEvent`,
`GrantUserRolesPreEvent`, `RevokeUserRolesPreEvent`
| 0.9.0-incubating |
| Gravitino server group operation | `AddGroupPreEvent`,
`GetGroupPreEvent`, `ListGroupNamesPreEvent`, `ListGroupsPreEvent`,
`RemoveGroupPreEvent`, `GrantGroupRolesPreEvent`, `RevokeGroupRolesPreEvent`
|
0.9.0-incubating |