This is an automated email from the ASF dual-hosted git repository.

yuqi1129 pushed a commit to branch feat/12166-occ-drop-cas
in repository https://gitbox.apache.org/repos/asf/gravitino.git

commit 47525235e25d58021ec5587ef3949472f8d7649d
Author: yuqi <[email protected]>
AuthorDate: Fri Jul 24 17:14:26 2026 +0800

    [#12166] improvement(core): version-checked soft-delete (drop CAS) for 
user, group, role
    
    These soft-deletes returned void and the services returned true 
unconditionally.
    Change softDelete{User,Group,Role}MetaBy{...}Id to return Integer with a
    current_version param + WHERE predicate (base + PostgreSQL), fetch the PO 
for the
    version (getXxxPOByMetalakeIdAndName throws NoSuch, preserving behavior), 
capture the
    row count, and return count > 0 (Option A). Update TestAuthMappers call 
sites.
    
    Part of #12166 (drop CAS).
---
 .../storage/relational/mapper/GroupMetaMapper.java       |  3 ++-
 .../relational/mapper/GroupMetaSQLProviderFactory.java   |  5 +++--
 .../storage/relational/mapper/RoleMetaMapper.java        |  3 ++-
 .../relational/mapper/RoleMetaSQLProviderFactory.java    |  5 +++--
 .../storage/relational/mapper/UserMetaMapper.java        |  3 ++-
 .../relational/mapper/UserMetaSQLProviderFactory.java    |  5 +++--
 .../mapper/provider/base/GroupMetaBaseSQLProvider.java   |  7 +++++--
 .../mapper/provider/base/RoleMetaBaseSQLProvider.java    |  7 +++++--
 .../mapper/provider/base/UserMetaBaseSQLProvider.java    |  7 +++++--
 .../provider/postgresql/GroupMetaPostgreSQLProvider.java |  6 ++++--
 .../provider/postgresql/RoleMetaPostgreSQLProvider.java  |  7 +++++--
 .../provider/postgresql/UserMetaPostgreSQLProvider.java  |  6 ++++--
 .../storage/relational/service/GroupMetaService.java     | 16 ++++++++++++----
 .../storage/relational/service/RoleMetaService.java      | 14 ++++++++++----
 .../storage/relational/service/UserMetaService.java      | 16 ++++++++++++----
 .../relational/mapper/provider/base/TestAuthMappers.java |  6 +++---
 16 files changed, 80 insertions(+), 36 deletions(-)

diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaMapper.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaMapper.java
index c86df5a90e..c6b60f4018 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaMapper.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaMapper.java
@@ -76,7 +76,8 @@ public interface GroupMetaMapper {
   void insertGroupMetaOnDuplicateKeyUpdate(@Param("groupMeta") GroupPO 
groupPO);
 
   @UpdateProvider(type = GroupMetaSQLProviderFactory.class, method = 
"softDeleteGroupMetaByGroupId")
-  void softDeleteGroupMetaByGroupId(@Param("groupId") Long groupId);
+  Integer softDeleteGroupMetaByGroupId(
+      @Param("groupId") Long groupId, @Param("currentVersion") Long 
currentVersion);
 
   @UpdateProvider(
       type = GroupMetaSQLProviderFactory.class,
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaSQLProviderFactory.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaSQLProviderFactory.java
index 21d0d4df8e..ee6119bc23 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaSQLProviderFactory.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/GroupMetaSQLProviderFactory.java
@@ -72,8 +72,9 @@ public class GroupMetaSQLProviderFactory {
     return getProvider().insertGroupMetaOnDuplicateKeyUpdate(groupPO);
   }
 
-  public static String softDeleteGroupMetaByGroupId(@Param("groupId") Long 
groupId) {
-    return getProvider().softDeleteGroupMetaByGroupId(groupId);
+  public static String softDeleteGroupMetaByGroupId(
+      @Param("groupId") Long groupId, @Param("currentVersion") Long 
currentVersion) {
+    return getProvider().softDeleteGroupMetaByGroupId(groupId, currentVersion);
   }
 
   public static String softDeleteGroupMetasByMetalakeId(@Param("metalakeId") 
Long metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
index 78fcc921d2..953e625c0e 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaMapper.java
@@ -82,7 +82,8 @@ public interface RoleMetaMapper {
       @Param("newRoleMeta") RolePO newRolePO, @Param("oldRoleMeta") RolePO 
oldRolePO);
 
   @UpdateProvider(type = RoleMetaSQLProviderFactory.class, method = 
"softDeleteRoleMetaByRoleId")
-  void softDeleteRoleMetaByRoleId(@Param("roleId") Long roleId);
+  Integer softDeleteRoleMetaByRoleId(
+      @Param("roleId") Long roleId, @Param("currentVersion") Long 
currentVersion);
 
   @UpdateProvider(
       type = RoleMetaSQLProviderFactory.class,
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
index 649c897f68..4a3098bac3 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/RoleMetaSQLProviderFactory.java
@@ -90,8 +90,9 @@ public class RoleMetaSQLProviderFactory {
     return getProvider().updateRoleMeta(newRolePO, oldRolePO);
   }
 
-  public static String softDeleteRoleMetaByRoleId(@Param("roleId") Long 
roleId) {
-    return getProvider().softDeleteRoleMetaByRoleId(roleId);
+  public static String softDeleteRoleMetaByRoleId(
+      @Param("roleId") Long roleId, @Param("currentVersion") Long 
currentVersion) {
+    return getProvider().softDeleteRoleMetaByRoleId(roleId, currentVersion);
   }
 
   public static String softDeleteRoleMetasByMetalakeId(@Param("metalakeId") 
Long metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaMapper.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaMapper.java
index 87f8a26b17..3eea1c983c 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaMapper.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaMapper.java
@@ -71,7 +71,8 @@ public interface UserMetaMapper {
   void insertUserMetaOnDuplicateKeyUpdate(@Param("userMeta") UserPO userPO);
 
   @UpdateProvider(type = UserMetaSQLProviderFactory.class, method = 
"softDeleteUserMetaByUserId")
-  void softDeleteUserMetaByUserId(@Param("userId") Long userId);
+  Integer softDeleteUserMetaByUserId(
+      @Param("userId") Long userId, @Param("currentVersion") Long 
currentVersion);
 
   @UpdateProvider(
       type = UserMetaSQLProviderFactory.class,
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaSQLProviderFactory.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaSQLProviderFactory.java
index cc7de6fb28..29d9567ba0 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaSQLProviderFactory.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/UserMetaSQLProviderFactory.java
@@ -69,8 +69,9 @@ public class UserMetaSQLProviderFactory {
     return getProvider().insertUserMetaOnDuplicateKeyUpdate(userPO);
   }
 
-  public static String softDeleteUserMetaByUserId(@Param("userId") Long 
userId) {
-    return getProvider().softDeleteUserMetaByUserId(userId);
+  public static String softDeleteUserMetaByUserId(
+      @Param("userId") Long userId, @Param("currentVersion") Long 
currentVersion) {
+    return getProvider().softDeleteUserMetaByUserId(userId, currentVersion);
   }
 
   public static String softDeleteUserMetasByMetalakeId(@Param("metalakeId") 
Long metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/GroupMetaBaseSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/GroupMetaBaseSQLProvider.java
index 8b04ffc6f6..880907b7ee 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/GroupMetaBaseSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/GroupMetaBaseSQLProvider.java
@@ -184,12 +184,15 @@ public class GroupMetaBaseSQLProvider {
         + " deleted_at = #{groupMeta.deletedAt}";
   }
 
-  public String softDeleteGroupMetaByGroupId(@Param("groupId") Long groupId) {
+  public String softDeleteGroupMetaByGroupId(
+      @Param("groupId") Long groupId, @Param("currentVersion") Long 
currentVersion) {
     return "UPDATE "
         + GROUP_TABLE_NAME
         + " SET deleted_at = (UNIX_TIMESTAMP() * 1000.0)"
         + " + EXTRACT(MICROSECOND FROM CURRENT_TIMESTAMP(3)) / 1000"
-        + " WHERE group_id = #{groupId} AND deleted_at = 0";
+        // OCC: version-checked delete (0 rows = stale version; the service 
returns false).
+        + " WHERE group_id = #{groupId} AND current_version = 
#{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   public String softDeleteGroupMetasByMetalakeId(@Param("metalakeId") Long 
metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
index a0d2a9165f..7b916c61ef 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/RoleMetaBaseSQLProvider.java
@@ -169,12 +169,15 @@ public class RoleMetaBaseSQLProvider {
         + " AND deleted_at = 0";
   }
 
-  public String softDeleteRoleMetaByRoleId(@Param("roleId") Long roleId) {
+  public String softDeleteRoleMetaByRoleId(
+      @Param("roleId") Long roleId, @Param("currentVersion") Long 
currentVersion) {
     return "UPDATE "
         + ROLE_TABLE_NAME
         + " SET deleted_at = (UNIX_TIMESTAMP() * 1000.0)"
         + " + EXTRACT(MICROSECOND FROM CURRENT_TIMESTAMP(3)) / 1000"
-        + " WHERE role_id = #{roleId} AND deleted_at = 0";
+        // OCC: version-checked delete (0 rows = stale version; the service 
returns false).
+        + " WHERE role_id = #{roleId} AND current_version = #{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   public String softDeleteRoleMetasByMetalakeId(@Param("metalakeId") Long 
metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/UserMetaBaseSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/UserMetaBaseSQLProvider.java
index 3b11b056dd..3c0e0fa339 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/UserMetaBaseSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/base/UserMetaBaseSQLProvider.java
@@ -135,12 +135,15 @@ public class UserMetaBaseSQLProvider {
         + " deleted_at = #{userMeta.deletedAt}";
   }
 
-  public String softDeleteUserMetaByUserId(@Param("userId") Long userId) {
+  public String softDeleteUserMetaByUserId(
+      @Param("userId") Long userId, @Param("currentVersion") Long 
currentVersion) {
     return "UPDATE "
         + USER_TABLE_NAME
         + " SET deleted_at = (UNIX_TIMESTAMP() * 1000.0)"
         + " + EXTRACT(MICROSECOND FROM CURRENT_TIMESTAMP(3)) / 1000"
-        + " WHERE user_id = #{userId} AND deleted_at = 0";
+        // OCC: version-checked delete (0 rows = stale version; the service 
returns false).
+        + " WHERE user_id = #{userId} AND current_version = #{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   public String softDeleteUserMetasByMetalakeId(@Param("metalakeId") Long 
metalakeId) {
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java
index 4f617f98b5..8e862027fe 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java
@@ -29,11 +29,13 @@ import org.apache.ibatis.annotations.Param;
 
 public class GroupMetaPostgreSQLProvider extends GroupMetaBaseSQLProvider {
   @Override
-  public String softDeleteGroupMetaByGroupId(Long groupId) {
+  public String softDeleteGroupMetaByGroupId(Long groupId, Long 
currentVersion) {
     return "UPDATE "
         + GROUP_TABLE_NAME
         + " SET deleted_at = CAST(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 
AS BIGINT)"
-        + " WHERE group_id = #{groupId} AND deleted_at = 0";
+        // OCC: version-checked delete (see the base provider for rationale).
+        + " WHERE group_id = #{groupId} AND current_version = 
#{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   @Override
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java
index 44de0a3bab..c483ba3b7a 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java
@@ -26,11 +26,14 @@ import org.apache.ibatis.annotations.Param;
 
 public class RoleMetaPostgreSQLProvider extends RoleMetaBaseSQLProvider {
   @Override
-  public String softDeleteRoleMetaByRoleId(@Param("roleId") Long roleId) {
+  public String softDeleteRoleMetaByRoleId(
+      @Param("roleId") Long roleId, @Param("currentVersion") Long 
currentVersion) {
     return "UPDATE "
         + ROLE_TABLE_NAME
         + " SET deleted_at = CAST(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 
AS BIGINT)"
-        + " WHERE role_id = #{roleId} AND deleted_at = 0";
+        // OCC: version-checked delete (see the base provider for rationale).
+        + " WHERE role_id = #{roleId} AND current_version = #{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   @Override
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java
index 2305535b1d..43d60fabd9 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java
@@ -28,11 +28,13 @@ import org.apache.ibatis.annotations.Param;
 
 public class UserMetaPostgreSQLProvider extends UserMetaBaseSQLProvider {
   @Override
-  public String softDeleteUserMetaByUserId(Long userId) {
+  public String softDeleteUserMetaByUserId(Long userId, Long currentVersion) {
     return "UPDATE "
         + USER_TABLE_NAME
         + " SET deleted_at = CAST(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 
AS BIGINT)"
-        + " WHERE user_id = #{userId} AND deleted_at = 0";
+        // OCC: version-checked delete (see the base provider for rationale).
+        + " WHERE user_id = #{userId} AND current_version = #{currentVersion}"
+        + " AND deleted_at = 0";
   }
 
   @Override
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
index b540f3f9da..9605caf768 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/GroupMetaService.java
@@ -214,12 +214,19 @@ public class GroupMetaService {
   public boolean deleteGroup(NameIdentifier identifier) {
     AuthorizationUtils.checkGroup(identifier);
 
-    Long groupId = EntityIdService.getEntityId(identifier, 
Entity.EntityType.GROUP);
+    Long metalakeId =
+        
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
+    GroupPO groupPO = getGroupPOByMetalakeIdAndName(metalakeId, 
identifier.name());
+    Long groupId = groupPO.getGroupId();
+    Long currentVersion = groupPO.getCurrentVersion();
+    int[] groupDeletedCount = new int[] {0};
 
     SessionUtils.doMultipleWithCommit(
         () ->
-            SessionUtils.doWithoutCommit(
-                GroupMetaMapper.class, mapper -> 
mapper.softDeleteGroupMetaByGroupId(groupId)),
+            groupDeletedCount[0] =
+                SessionUtils.getWithoutCommit(
+                    GroupMetaMapper.class,
+                    mapper -> mapper.softDeleteGroupMetaByGroupId(groupId, 
currentVersion)),
         () ->
             SessionUtils.doWithoutCommit(
                 GroupRoleRelMapper.class,
@@ -230,7 +237,8 @@ public class GroupMetaService {
                 mapper ->
                     mapper.softDeleteOwnerRelByOwnerIdAndType(
                         groupId, Entity.EntityType.GROUP.name())));
-    return true;
+    // OCC: false when the group's version changed between read and delete.
+    return groupDeletedCount[0] > 0;
   }
 
   @Monitored(metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME, 
baseMetricName = "updateGroup")
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index 0298938c08..a19a3d20d1 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -317,12 +317,17 @@ public class RoleMetaService {
 
     Long metalakeId =
         
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
-    Long roleId = getRoleIdByMetalakeIdAndName(metalakeId, identifier.name());
+    RolePO rolePO = getRolePOByMetalakeIdAndName(metalakeId, 
identifier.name());
+    Long roleId = rolePO.getRoleId();
+    Long currentVersion = rolePO.getCurrentVersion();
+    int[] roleDeletedCount = new int[] {0};
 
     SessionUtils.doMultipleWithCommit(
         () ->
-            SessionUtils.doWithoutCommit(
-                RoleMetaMapper.class, mapper -> 
mapper.softDeleteRoleMetaByRoleId(roleId)),
+            roleDeletedCount[0] =
+                SessionUtils.getWithoutCommit(
+                    RoleMetaMapper.class,
+                    mapper -> mapper.softDeleteRoleMetaByRoleId(roleId, 
currentVersion)),
         () ->
             SessionUtils.doWithoutCommit(
                 UserRoleRelMapper.class, mapper -> 
mapper.softDeleteUserRoleRelByRoleId(roleId)),
@@ -339,7 +344,8 @@ public class RoleMetaService {
                 mapper ->
                     mapper.softDeleteOwnerRelByMetadataObjectIdAndType(
                         roleId, MetadataObject.Type.ROLE.name())));
-    return true;
+    // OCC: false when the role's version changed between read and delete.
+    return roleDeletedCount[0] > 0;
   }
 
   @Monitored(
diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
index e63487669c..16467a51a1 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/service/UserMetaService.java
@@ -174,12 +174,19 @@ public class UserMetaService {
   public boolean deleteUser(NameIdentifier identifier) {
     AuthorizationUtils.checkUser(identifier);
 
-    Long userId = EntityIdService.getEntityId(identifier, 
Entity.EntityType.USER);
+    Long metalakeId =
+        
MetalakeMetaService.getInstance().getMetalakeIdByName(identifier.namespace().level(0));
+    UserPO userPO = getUserPOByMetalakeIdAndName(metalakeId, 
identifier.name());
+    Long userId = userPO.getUserId();
+    Long currentVersion = userPO.getCurrentVersion();
+    int[] userDeletedCount = new int[] {0};
 
     SessionUtils.doMultipleWithCommit(
         () ->
-            SessionUtils.doWithoutCommit(
-                UserMetaMapper.class, mapper -> 
mapper.softDeleteUserMetaByUserId(userId)),
+            userDeletedCount[0] =
+                SessionUtils.getWithoutCommit(
+                    UserMetaMapper.class,
+                    mapper -> mapper.softDeleteUserMetaByUserId(userId, 
currentVersion)),
         () ->
             SessionUtils.doWithoutCommit(
                 UserRoleRelMapper.class, mapper -> 
mapper.softDeleteUserRoleRelByUserId(userId)),
@@ -189,7 +196,8 @@ public class UserMetaService {
                 mapper ->
                     mapper.softDeleteOwnerRelByOwnerIdAndType(
                         userId, Entity.EntityType.USER.name())));
-    return true;
+    // OCC: false when the user's version changed between read and delete.
+    return userDeletedCount[0] > 0;
   }
 
   @Monitored(metricsSource = GRAVITINO_RELATIONAL_STORE_METRIC_NAME, 
baseMetricName = "updateUser")
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/base/TestAuthMappers.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/base/TestAuthMappers.java
index e26613c790..6d3d1b695f 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/base/TestAuthMappers.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/base/TestAuthMappers.java
@@ -188,7 +188,7 @@ public class TestAuthMappers {
   void testRoleMetaTouchUpdatedAtSkipsSoftDeleted() {
     insertMetalake(1L, "metalake1");
     insertRole(13L, "role13", 1L);
-    roleMetaMapper.softDeleteRoleMetaByRoleId(13L);
+    roleMetaMapper.softDeleteRoleMetaByRoleId(13L, 1L);
 
     long beforeUpdatedAt = queryUpdatedAt("role_meta", "role_id", 13L);
     roleMetaMapper.touchRoleUpdatedAt(13L);
@@ -219,7 +219,7 @@ public class TestAuthMappers {
   void testUserMetaTouchUpdatedAtSkipsSoftDeleted() {
     insertMetalake(1L, "metalake1");
     insertUser(22L, "user22", 1L);
-    userMetaMapper.softDeleteUserMetaByUserId(22L);
+    userMetaMapper.softDeleteUserMetaByUserId(22L, 1L);
 
     long beforeUpdatedAt = queryUpdatedAt("user_meta", "user_id", 22L);
     userMetaMapper.touchUserUpdatedAt(22L);
@@ -264,7 +264,7 @@ public class TestAuthMappers {
   void testGroupMetaTouchUpdatedAtSkipsSoftDeleted() {
     insertMetalake(1L, "metalake1");
     insertGroup(31L, "group31", 1L);
-    groupMetaMapper.softDeleteGroupMetaByGroupId(31L);
+    groupMetaMapper.softDeleteGroupMetaByGroupId(31L, 1L);
 
     long beforeUpdatedAt = queryUpdatedAt("group_meta", "group_id", 31L);
     groupMetaMapper.touchGroupUpdatedAt(31L);

Reply via email to