Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#3914] feat(server): Add REST server interface for Tag System #3943

Merged
merged 30 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3ef459f
Support relational storage for tag system
jerryshao Jul 1, 2024
2164305
Continue to add more UTs
jerryshao Jul 2, 2024
7dfeb15
Change to use ASF header and fix comment
jerryshao Jul 3, 2024
c33eb20
Fix query problem
jerryshao Jul 3, 2024
d3e1ca1
Revert disabled tests
jerryshao Jul 8, 2024
382a9b6
Support relational storage for tag system
jerryshao Jul 1, 2024
687cf5d
Add core logic for tag management (part-2)
jerryshao Jul 8, 2024
bbb7ab3
Fix the style issue
jerryshao Jul 9, 2024
67a4ac0
Fix some issues
jerryshao Jul 10, 2024
eaa2081
Address the comments
jerryshao Jul 12, 2024
bba5b79
Fix issue and add ut
jerryshao Jul 12, 2024
8abab54
Fix style issue
jerryshao Jul 12, 2024
61276ba
[#4112] feat(API, client): Add fileset comment removal operations (#4…
bknbkn Jul 12, 2024
317875d
[#4135] fix(trino-connector): Fix typo about Gravitino in trino-conn…
Dev79844 Jul 12, 2024
bd604fc
[#4105] improvement(core): Remove the logic of getValidRoles (#4121)
jerqi Jul 12, 2024
c8d00bb
[#4155]fix(doc): Fixed an unreachable link (#4156)
JinsYin Jul 12, 2024
41431c2
Add server side rest interface for tag system
jerryshao Jun 20, 2024
f055105
Continue the work
jerryshao Jun 21, 2024
5e89f9c
Rebase and fix the issues
jerryshao Jul 12, 2024
5918f62
Rebase and fix the issues
jerryshao Jul 15, 2024
0f2eaf2
Add core logic for tag management (part-2)
jerryshao Jul 16, 2024
971b9c9
Fix style issues
jerryshao Jul 16, 2024
f1d9cca
Address the comments
jerryshao Jul 16, 2024
75849ca
Merge branch 'issue-4020' into issue-3914
jerryshao Jul 16, 2024
1a8bbdb
Fix style issues
jerryshao Jul 16, 2024
cb4ebe7
Improve the code
jerryshao Jul 16, 2024
aa6586e
Merge branch 'issue-4020' into issue-3914
jerryshao Jul 16, 2024
3c451d4
Merge remote-tracking branch 'origin/main' into issue-3914
jerryshao Jul 17, 2024
3efd7f4
Address the comments
jerryshao Jul 18, 2024
b31490a
Address the comments
jerryshao Jul 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions api/src/main/java/org/apache/gravitino/MetadataObjects.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import java.util.List;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;

/** The helper class for {@link MetadataObject}. */
Expand Down Expand Up @@ -98,6 +99,46 @@ public static MetadataObject of(List<String> names, MetadataObject.Type type) {
return new MetadataObjectImpl(getParentFullName(names), getLastName(names), type);
}

/**
* Get the parent metadata object of the given metadata object.
*
* @param object The metadata object
* @return The parent metadata object if it exists, otherwise null
*/
@Nullable
public static MetadataObject parent(MetadataObject object) {
if (object == null) {
return null;
}

// Return null if the object is the root object
if (object.type() == MetadataObject.Type.METALAKE
|| object.type() == MetadataObject.Type.CATALOG) {
return null;
}

MetadataObject.Type parentType;
switch (object.type()) {
case COLUMN:
parentType = MetadataObject.Type.TABLE;
break;
case TABLE:
case FILESET:
case TOPIC:
parentType = MetadataObject.Type.SCHEMA;
break;
case SCHEMA:
parentType = MetadataObject.Type.CATALOG;
break;

default:
throw new IllegalArgumentException(
"Unexpected to reach here for metadata object type: " + object.type());
}

return parse(object.parent(), parentType);
}

/**
* Parse the metadata object with the given full name and type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.cfg.EnumFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

/**
Expand All @@ -39,7 +40,8 @@ private static class ObjectMapperHolder {
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.build()
.registerModule(new JavaTimeModule());
.registerModule(new JavaTimeModule())
.registerModule(new Jdk8Module());
yuqi1129 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -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.dto.requests;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import java.util.Map;
import javax.annotation.Nullable;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.apache.gravitino.rest.RESTRequest;

/** Represents a request to create a tag. */
@Getter
@EqualsAndHashCode
@ToString
public class TagCreateRequest implements RESTRequest {

@JsonProperty("name")
private final String name;

@JsonProperty("comment")
@Nullable
private final String comment;

@JsonProperty("properties")
@Nullable
private Map<String, String> properties;

/**
* Creates a new TagCreateRequest.
*
* @param name The name of the tag.
* @param comment The comment of the tag.
* @param properties The properties of the tag.
*/
public TagCreateRequest(String name, String comment, Map<String, String> properties) {
this.name = name;
this.comment = comment;
this.properties = properties;
}

/** This is the constructor that is used by Jackson deserializer */
public TagCreateRequest() {
this(null, null, null);
}

/**
* Validates the request.
*
* @throws IllegalArgumentException If the request is invalid, this exception is thrown.
*/
@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(
StringUtils.isNotBlank(name), "\"name\" is required and cannot be empty");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* 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.dto.requests;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.google.common.base.Preconditions;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.apache.gravitino.rest.RESTRequest;
import org.apache.gravitino.tag.TagChange;

/** Represents a request to update a tag. */
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY)
@JsonSubTypes({
@JsonSubTypes.Type(value = TagUpdateRequest.RenameTagRequest.class, name = "rename"),
@JsonSubTypes.Type(
value = TagUpdateRequest.UpdateTagCommentRequest.class,
name = "updateComment"),
@JsonSubTypes.Type(value = TagUpdateRequest.SetTagPropertyRequest.class, name = "setProperty"),
@JsonSubTypes.Type(
value = TagUpdateRequest.RemoveTagPropertyRequest.class,
name = "removeProperty")
})
public interface TagUpdateRequest extends RESTRequest {

/**
* Returns the tag change.
*
* @return the tag change.
*/
TagChange tagChange();

/** The tag update request for renaming a tag. */
@EqualsAndHashCode
@ToString
class RenameTagRequest implements TagUpdateRequest {

@Getter
@JsonProperty("newName")
private final String newName;

/**
* Creates a new RenameTagRequest.
*
* @param newName The new name of the tag.
*/
public RenameTagRequest(String newName) {
this.newName = newName;
}

/** This is the constructor that is used by Jackson deserializer */
public RenameTagRequest() {
this.newName = null;
}

@Override
public TagChange tagChange() {
return TagChange.rename(newName);
}

@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(StringUtils.isNotBlank(newName), "\"newName\" must not be blank");
}
}

/** The tag update request for updating a tag comment. */
@EqualsAndHashCode
@ToString
class UpdateTagCommentRequest implements TagUpdateRequest {

@Getter
@JsonProperty("newComment")
private final String newComment;

/**
* Creates a new UpdateTagCommentRequest.
*
* @param newComment The new comment of the tag.
*/
public UpdateTagCommentRequest(String newComment) {
this.newComment = newComment;
}

/** This is the constructor that is used by Jackson deserializer */
public UpdateTagCommentRequest() {
this.newComment = null;
}

@Override
public TagChange tagChange() {
return TagChange.updateComment(newComment);
}

@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(
StringUtils.isNotBlank(newComment), "\"newComment\" must not be blank");
}
}

/** The tag update request for setting a tag property. */
@EqualsAndHashCode
@ToString
class SetTagPropertyRequest implements TagUpdateRequest {

@Getter
@JsonProperty("property")
private final String property;

@Getter
@JsonProperty("value")
private final String value;

/**
* Creates a new SetTagPropertyRequest.
*
* @param property The property to set.
* @param value The value of the property.
*/
public SetTagPropertyRequest(String property, String value) {
this.property = property;
this.value = value;
}

/** This is the constructor that is used by Jackson deserializer */
public SetTagPropertyRequest() {
this.property = null;
this.value = null;
}

@Override
public TagChange tagChange() {
return TagChange.setProperty(property, value);
}

@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(
StringUtils.isNotBlank(property), "\"property\" must not be blank");
Preconditions.checkArgument(StringUtils.isNotBlank(value), "\"value\" must not be blank");
}
}

/** The tag update request for removing a tag property. */
@EqualsAndHashCode
@ToString
class RemoveTagPropertyRequest implements TagUpdateRequest {

@Getter
@JsonProperty("property")
private final String property;

/**
* Creates a new RemoveTagPropertyRequest.
*
* @param property The property to remove.
*/
public RemoveTagPropertyRequest(String property) {
this.property = property;
}

/** This is the constructor that is used by Jackson deserializer */
public RemoveTagPropertyRequest() {
this.property = null;
}

@Override
public TagChange tagChange() {
return TagChange.removeProperty(property);
}

@Override
public void validate() throws IllegalArgumentException {
Preconditions.checkArgument(
StringUtils.isNotBlank(property), "\"property\" must not be blank");
}
}
}
Loading
Loading