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

yuqi1129 pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/branch-1.3 by this push:
     new 59e64ba914 [Cherry-pick to branch-1.3] [#13035] fix(core): Add 
PostgreSQL group-role batch upsert (#13037) (#13061)
59e64ba914 is described below

commit 59e64ba914396054b552455c85c624b53bd5097a
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 10 20:13:07 2026 +0800

    [Cherry-pick to branch-1.3] [#13035] fix(core): Add PostgreSQL group-role 
batch upsert (#13037) (#13061)
    
    **Cherry-pick Information:**
    - Original commit: 56aedb27f1f46089951a36be136ee18263e46b35
    - Target branch: `branch-1.3`
    - Status: ✅ Clean cherry-pick (no conflicts)
    
    Co-authored-by: Qi Yu <[email protected]>
    Co-authored-by: Jerry Shao <[email protected]>
---
 .../postgresql/GroupRoleRelPostgreSQLProvider.java | 34 +++++++++++++
 .../TestGroupRoleRelPostgreSQLProvider.java        | 58 ++++++++++++++++++++++
 2 files changed, 92 insertions(+)

diff --git 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java
 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java
index 2ab7d9f5c0..29058dbd8d 100644
--- 
a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java
+++ 
b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java
@@ -23,6 +23,7 @@ import static 
org.apache.gravitino.storage.relational.mapper.GroupRoleRelMapper.
 
 import java.util.List;
 import 
org.apache.gravitino.storage.relational.mapper.provider.base.GroupRoleRelBaseSQLProvider;
+import org.apache.gravitino.storage.relational.po.GroupRoleRelPO;
 import org.apache.ibatis.annotations.Param;
 
 public class GroupRoleRelPostgreSQLProvider extends 
GroupRoleRelBaseSQLProvider {
@@ -76,6 +77,39 @@ public class GroupRoleRelPostgreSQLProvider extends 
GroupRoleRelBaseSQLProvider
         + " WHERE role_id = #{roleId} AND deleted_at = 0";
   }
 
+  /**
+   * Builds a PostgreSQL batch upsert for group-role relations.
+   *
+   * @param groupRoleRelPOs the group-role relations to insert or update
+   * @return the MyBatis SQL script
+   */
+  @Override
+  public String 
batchInsertGroupRoleRelOnDuplicateKeyUpdate(List<GroupRoleRelPO> 
groupRoleRelPOs) {
+    return "<script>"
+        + "INSERT INTO "
+        + GROUP_ROLE_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 CONFLICT (group_id, role_id, deleted_at) DO UPDATE SET"
+        + " group_id = EXCLUDED.group_id,"
+        + " role_id = EXCLUDED.role_id,"
+        + " audit_info = EXCLUDED.audit_info,"
+        + " current_version = EXCLUDED.current_version,"
+        + " last_version = EXCLUDED.last_version,"
+        + " deleted_at = EXCLUDED.deleted_at"
+        + "</script>";
+  }
+
   @Override
   public String deleteGroupRoleRelMetasByLegacyTimeline(
       @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) 
{
diff --git 
a/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TestGroupRoleRelPostgreSQLProvider.java
 
b/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TestGroupRoleRelPostgreSQLProvider.java
index 8fcd67d1a5..b0435202eb 100644
--- 
a/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TestGroupRoleRelPostgreSQLProvider.java
+++ 
b/core/src/test/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TestGroupRoleRelPostgreSQLProvider.java
@@ -18,19 +18,77 @@
  */
 package org.apache.gravitino.storage.relational.mapper.provider.postgresql;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import org.apache.gravitino.storage.relational.po.GroupRoleRelPO;
 import org.apache.ibatis.mapping.BoundSql;
 import org.apache.ibatis.mapping.SqlSource;
 import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
 import org.apache.ibatis.session.Configuration;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 public class TestGroupRoleRelPostgreSQLProvider {
 
+  @ParameterizedTest
+  @ValueSource(ints = {1, 2})
+  void testBatchInsertGroupRoleRelOnDuplicateKeyUpdate(int batchSize) {
+    List<GroupRoleRelPO> relations = new ArrayList<>();
+    List<Object> expectedParameters = new ArrayList<>();
+    for (int i = 0; i < batchSize; i++) {
+      GroupRoleRelPO relation =
+          GroupRoleRelPO.builder()
+              .withGroupId(10L + i)
+              .withRoleId(20L + i)
+              .withAuditInfo("audit-" + i)
+              .withCurrentVersion(30L + i)
+              .withLastVersion(40L + i)
+              .withDeletedAt(50L + i)
+              .build();
+      relations.add(relation);
+      expectedParameters.addAll(
+          Arrays.asList(
+              relation.getGroupId(),
+              relation.getRoleId(),
+              relation.getAuditInfo(),
+              relation.getCurrentVersion(),
+              relation.getLastVersion(),
+              relation.getDeletedAt()));
+    }
+
+    String script =
+        new 
GroupRoleRelPostgreSQLProvider().batchInsertGroupRoleRelOnDuplicateKeyUpdate(relations);
+    SqlSource sqlSource =
+        new XMLLanguageDriver().createSqlSource(new Configuration(), script, 
Map.class);
+    BoundSql boundSql = sqlSource.getBoundSql(Map.of("groupRoleRels", 
relations));
+    String sql = boundSql.getSql().replaceAll("\\s+", " ").trim();
+
+    Assertions.assertTrue(sql.startsWith("INSERT INTO group_role_rel "));
+    Assertions.assertTrue(
+        sql.contains("ON CONFLICT (group_id, role_id, deleted_at) DO UPDATE 
SET"));
+    Assertions.assertFalse(sql.contains("ON DUPLICATE KEY UPDATE"));
+    Assertions.assertFalse(sql.contains("VALUES("));
+    for (String column :
+        Arrays.asList(
+            "group_id", "role_id", "audit_info", "current_version", 
"last_version", "deleted_at")) {
+      Assertions.assertTrue(sql.contains(column + " = EXCLUDED." + column));
+    }
+
+    List<Object> actualParameters = new ArrayList<>();
+    boundSql
+        .getParameterMappings()
+        .forEach(
+            mapping ->
+                
actualParameters.add(boundSql.getAdditionalParameter(mapping.getProperty())));
+    Assertions.assertEquals(expectedParameters, actualParameters);
+  }
+
   @Test
   void testSoftDeleteGroupRoleRelByGroupAndRolesWithEmptyRoles() {
     GroupRoleRelPostgreSQLProvider provider = new 
GroupRoleRelPostgreSQLProvider();

Reply via email to