Skip to content

Commit

Permalink
[apache#2851] feat(core): Add relational backend for Group Entity (ap…
Browse files Browse the repository at this point in the history
…ache#3031)

### What changes were proposed in this pull request?

add relational backend for Group Entity

[note]: wait for apache#2850 merged first

### Why are the changes needed?

Fix: apache#2851 

### Does this PR introduce _any_ user-facing change?

N/A

### How was this patch tested?

ut

---------

Co-authored-by: yangliwei <[email protected]>
  • Loading branch information
lw-yang and lw-yang authored Apr 22, 2024
1 parent 720ec29 commit dfdd553
Show file tree
Hide file tree
Showing 19 changed files with 1,750 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.datastrato.gravitino.meta.BaseMetalake;
import com.datastrato.gravitino.meta.CatalogEntity;
import com.datastrato.gravitino.meta.FilesetEntity;
import com.datastrato.gravitino.meta.GroupEntity;
import com.datastrato.gravitino.meta.RoleEntity;
import com.datastrato.gravitino.meta.SchemaEntity;
import com.datastrato.gravitino.meta.TableEntity;
Expand All @@ -28,6 +29,7 @@
import com.datastrato.gravitino.storage.relational.converters.SQLExceptionConverterFactory;
import com.datastrato.gravitino.storage.relational.service.CatalogMetaService;
import com.datastrato.gravitino.storage.relational.service.FilesetMetaService;
import com.datastrato.gravitino.storage.relational.service.GroupMetaService;
import com.datastrato.gravitino.storage.relational.service.MetalakeMetaService;
import com.datastrato.gravitino.storage.relational.service.RoleMetaService;
import com.datastrato.gravitino.storage.relational.service.SchemaMetaService;
Expand Down Expand Up @@ -109,6 +111,8 @@ public <E extends Entity & HasIdentifier> void insert(E e, boolean overwritten)
UserMetaService.getInstance().insertUser((UserEntity) e, overwritten);
} else if (e instanceof RoleEntity) {
RoleMetaService.getInstance().insertRole((RoleEntity) e, overwritten);
} else if (e instanceof GroupEntity) {
GroupMetaService.getInstance().insertGroup((GroupEntity) e, overwritten);
} else {
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for insert operation", e.getClass());
Expand All @@ -134,6 +138,8 @@ public <E extends Entity & HasIdentifier> E update(
return (E) TopicMetaService.getInstance().updateTopic(ident, updater);
case USER:
return (E) UserMetaService.getInstance().updateUser(ident, updater);
case GROUP:
return (E) GroupMetaService.getInstance().updateGroup(ident, updater);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for update operation", entityType);
Expand All @@ -158,6 +164,8 @@ public <E extends Entity & HasIdentifier> E get(
return (E) TopicMetaService.getInstance().getTopicByIdentifier(ident);
case USER:
return (E) UserMetaService.getInstance().getUserByIdentifier(ident);
case GROUP:
return (E) GroupMetaService.getInstance().getGroupByIdentifier(ident);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for get operation", entityType);
Expand All @@ -181,6 +189,8 @@ public boolean delete(NameIdentifier ident, Entity.EntityType entityType, boolea
return TopicMetaService.getInstance().deleteTopic(ident);
case USER:
return UserMetaService.getInstance().deleteUser(ident);
case GROUP:
return GroupMetaService.getInstance().deleteGroup(ident);
default:
throw new UnsupportedEntityTypeException(
"Unsupported entity type: %s for delete operation", entityType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

package com.datastrato.gravitino.storage.relational.mapper;

import com.datastrato.gravitino.storage.relational.po.GroupPO;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

/**
* A MyBatis Mapper for table meta operation SQLs.
*
* <p>This interface class is a specification defined by MyBatis. It requires this interface class
* to identify the corresponding SQLs for execution. We can write SQLs in an additional XML file, or
* write SQLs with annotations in this interface Mapper. See: <a
* href="https://mybatis.org/mybatis-3/getting-started.html"></a>
*/
public interface GroupMetaMapper {
String TABLE_NAME = "group_meta";

@Select(
"SELECT group_id as groupId FROM "
+ TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND group_name = #{groupName}"
+ " AND deleted_at = 0")
Long selectGroupIdBySchemaIdAndName(
@Param("metalakeId") Long metalakeId, @Param("groupName") String name);

@Select(
"SELECT group_id as groupId, group_name as groupName,"
+ " metalake_id as metalakeId,"
+ " audit_info as auditInfo,"
+ " current_version as currentVersion, last_version as lastVersion,"
+ " deleted_at as deletedAt"
+ " FROM "
+ TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND group_name = #{groupName}"
+ " AND deleted_at = 0")
GroupPO selectGroupMetaByMetalakeIdAndName(
@Param("metalakeId") Long metalakeId, @Param("groupName") String name);

@Insert(
"INSERT INTO "
+ TABLE_NAME
+ "(group_id, group_name,"
+ " metalake_id, audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{groupMeta.groupId},"
+ " #{groupMeta.groupName},"
+ " #{groupMeta.metalakeId},"
+ " #{groupMeta.auditInfo},"
+ " #{groupMeta.currentVersion},"
+ " #{groupMeta.lastVersion},"
+ " #{groupMeta.deletedAt}"
+ " )")
void insertGroupMeta(@Param("groupMeta") GroupPO groupPO);

@Insert(
"INSERT INTO "
+ TABLE_NAME
+ "(group_id, group_name,"
+ "metalake_id, audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES("
+ " #{groupMeta.groupId},"
+ " #{groupMeta.groupName},"
+ " #{groupMeta.metalakeId},"
+ " #{groupMeta.auditInfo},"
+ " #{groupMeta.currentVersion},"
+ " #{groupMeta.lastVersion},"
+ " #{groupMeta.deletedAt}"
+ " )"
+ " ON DUPLICATE KEY UPDATE"
+ " group_name = #{groupMeta.groupName},"
+ " metalake_id = #{groupMeta.metalakeId},"
+ " audit_info = #{groupMeta.auditInfo},"
+ " current_version = #{groupMeta.currentVersion},"
+ " last_version = #{groupMeta.lastVersion},"
+ " deleted_at = #{groupMeta.deletedAt}")
void insertGroupMetaOnDuplicateKeyUpdate(@Param("groupMeta") GroupPO groupPO);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE group_id = #{groupId} AND deleted_at = 0")
void softDeleteGroupMetaByGroupId(@Param("groupId") Long groupId);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE metalake_id = #{metalakeId} AND deleted_at = 0")
void softDeleteGroupMetasByMetalakeId(@Param("metalakeId") Long metalakeId);

@Update(
"UPDATE "
+ TABLE_NAME
+ " SET group_name = #{newGroupMeta.groupName},"
+ " metalake_id = #{newGroupMeta.metalakeId},"
+ " audit_info = #{newGroupMeta.auditInfo},"
+ " current_version = #{newGroupMeta.currentVersion},"
+ " last_version = #{newGroupMeta.lastVersion},"
+ " deleted_at = #{newGroupMeta.deletedAt}"
+ " WHERE group_id = #{oldGroupMeta.groupId}"
+ " AND group_name = #{oldGroupMeta.groupName}"
+ " AND metalake_id = #{oldGroupMeta.metalakeId}"
+ " AND audit_info = #{oldGroupMeta.auditInfo}"
+ " AND current_version = #{oldGroupMeta.currentVersion}"
+ " AND last_version = #{oldGroupMeta.lastVersion}"
+ " AND deleted_at = 0")
Integer updateGroupMeta(
@Param("newGroupMeta") GroupPO newGroupPO, @Param("oldGroupMeta") GroupPO oldGroupPO);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Copyright 2024 Datastrato Pvt Ltd.
* This software is licensed under the Apache License version 2.
*/

package com.datastrato.gravitino.storage.relational.mapper;

import com.datastrato.gravitino.storage.relational.po.GroupRoleRelPO;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

/**
* A MyBatis Mapper for table meta operation SQLs.
*
* <p>This interface class is a specification defined by MyBatis. It requires this interface class
* to identify the corresponding SQLs for execution. We can write SQLs in an additional XML file, or
* write SQLs with annotations in this interface Mapper. See: <a
* href="https://mybatis.org/mybatis-3/getting-started.html"></a>
*/
public interface GroupRoleRelMapper {
String RELATION_TABLE_NAME = "group_role_rel";
String GROUP_TABLE_NAME = "group_meta";

@Insert({
"<script>",
"INSERT INTO "
+ RELATION_TABLE_NAME
+ "(group_id, role_id,"
+ " audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES ",
"<foreach collection='groupRoleRels' item='item' separator=','>",
"(#{item.groupId},"
+ " #{item.roleId},"
+ " #{item.auditInfo},"
+ " #{item.currentVersion},"
+ " #{item.lastVersion},"
+ " #{item.deletedAt})",
"</foreach>",
"</script>"
})
void batchInsertGroupRoleRel(@Param("groupRoleRels") List<GroupRoleRelPO> groupRoleRelPOS);

@Insert({
"<script>",
"INSERT INTO "
+ RELATION_TABLE_NAME
+ "(group_id, role_id,"
+ " audit_info,"
+ " current_version, last_version, deleted_at)"
+ " VALUES ",
"<foreach collection='groupRoleRels' item='item' separator=','>",
"(#{item.groupId},"
+ " #{item.roleId},"
+ " #{item.auditInfo},"
+ " #{item.currentVersion},"
+ " #{item.lastVersion},"
+ " #{item.deletedAt})",
"</foreach>",
" ON DUPLICATE KEY UPDATE"
+ " group_id = VALUES(group_id),"
+ " role_id = VALUES(role_id),"
+ " audit_info = VALUES(audit_info),"
+ " current_version = VALUES(current_version),"
+ " last_version = VALUES(last_version),"
+ " deleted_at = VALUES(deleted_at)",
"</script>"
})
void batchInsertGroupRoleRelOnDuplicateKeyUpdate(
@Param("groupRoleRels") List<GroupRoleRelPO> groupRoleRelPOS);

@Update(
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE group_id = #{groupId} AND deleted_at = 0")
void softDeleteGroupRoleRelByGroupId(@Param("groupId") Long groupId);

@Update({
"<script>",
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE group_id = #{groupId} AND role_id in (",
"<foreach collection='roleIds' item='roleId' separator=','>",
"#{roleId}",
"</foreach>",
") " + "AND deleted_at = 0",
"</script>"
})
void softDeleteGroupRoleRelByGroupAndRoles(
@Param("groupId") Long groupId, @Param("roleIds") List<Long> roleIds);

@Update(
"UPDATE "
+ RELATION_TABLE_NAME
+ " SET deleted_at = UNIX_TIMESTAMP(CURRENT_TIMESTAMP(3)) * 1000.0"
+ " WHERE group_id IN (SELECT group_id FROM "
+ GROUP_TABLE_NAME
+ " WHERE metalake_id = #{metalakeId} AND deleted_at = 0)"
+ " AND deleted_at = 0")
void softDeleteGroupRoleRelByMetalakeId(Long metalakeId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
*/
public interface RoleMetaMapper {
String ROLE_TABLE_NAME = "role_meta";
String RELATION_TABLE_NAME = "user_role_rel";
String USER_RELATION_TABLE_NAME = "user_role_rel";
String GROUP_RELATION_TABLE_NAME = "group_role_rel";

@Select(
"SELECT role_id as roleId FROM "
Expand All @@ -40,12 +41,27 @@ Long selectRoleIdByMetalakeIdAndName(
+ " FROM "
+ ROLE_TABLE_NAME
+ " ro JOIN "
+ RELATION_TABLE_NAME
+ USER_RELATION_TABLE_NAME
+ " re ON ro.role_id = re.role_id"
+ " WHERE re.user_id = #{userId}"
+ " AND ro.deleted_at = 0 AND re.deleted_at = 0")
List<RolePO> listRolesByUserId(@Param("userId") Long userId);

@Select(
"SELECT ro.role_id as roleId, ro.role_name as roleName,"
+ " ro.metalake_id as metalakeId, ro.properties as properties,"
+ " ro.securable_object as securableObject, ro.privileges as privileges,"
+ " ro.audit_info as auditInfo, ro.current_version as currentVersion,"
+ " ro.last_version as lastVersion, ro.deleted_at as deletedAt"
+ " FROM "
+ ROLE_TABLE_NAME
+ " ro JOIN "
+ GROUP_RELATION_TABLE_NAME
+ " ge ON ro.role_id = ge.role_id"
+ " WHERE ge.group_id = #{groupId}"
+ " AND ro.deleted_at = 0 AND ge.deleted_at = 0")
List<RolePO> listRolesByGroupId(Long groupId);

@Insert(
"INSERT INTO "
+ ROLE_TABLE_NAME
Expand Down
Loading

0 comments on commit dfdd553

Please sign in to comment.