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

JNSimba pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 87d6090a758 [fix](jdbc) order composite primary key columns by KEY_SEQ 
(#64740)
87d6090a758 is described below

commit 87d6090a7584088440ed82f4bd2849ad10fb1e66
Author: wudi <[email protected]>
AuthorDate: Thu Jun 25 15:49:43 2026 +0800

    [fix](jdbc) order composite primary key columns by KEY_SEQ (#64740)
    
    ## Proposed changes
    
    `JdbcClient` / `JdbcMySQLClient.getPrimaryKeys` returned primary-key
    columns in whatever order the JDBC driver yielded them.
    `DatabaseMetaData.getPrimaryKeys` orders its rows by `COLUMN_NAME`, not
    `KEY_SEQ`, so for a composite primary key whose definition order differs
    from alphabetical order (e.g. `PRIMARY KEY (tenant_id, order_id)`), the
    columns came back reordered. This affected the resulting Doris key
    columns and the bucket hash distribution.
    
    This reorders the columns by their 1-based `KEY_SEQ`. Single-column keys
    are unaffected; PostgreSQL is unaffected (its driver already returns
    KEY_SEQ order); only MySQL (whose driver sorts by column name) is
    corrected.
---
 .../apache/doris/datasource/jdbc/client/JdbcMySQLClient.java   | 10 ++++++----
 .../cdc/test_streaming_mysql_job_composite_pk.out              |  2 +-
 .../cdc/test_streaming_mysql_job_composite_pk.groovy           |  4 ++--
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
index aa85fd23f80..bcdc9ccc03b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClient.java
@@ -40,6 +40,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.function.Consumer;
 
 public class JdbcMySQLClient extends JdbcClient {
@@ -202,13 +203,14 @@ public class JdbcMySQLClient extends JdbcClient {
     public List<String> getPrimaryKeys(String remoteDbName, String 
remoteTableName) {
         Connection conn = getConnection();
         ResultSet rs = null;
-        List<String> primaryKeys = Lists.newArrayList();
+        // getPrimaryKeys orders rows by COLUMN_NAME, not KEY_SEQ; reorder by 
the 1-based KEY_SEQ
+        // to keep the real composite-PK column order.
+        TreeMap<Short, String> primaryKeys = new TreeMap<>();
         try {
             DatabaseMetaData databaseMetaData = conn.getMetaData();
             rs = databaseMetaData.getPrimaryKeys(remoteDbName, null, 
remoteTableName);
             while (rs.next()) {
-                String fieldName = rs.getString("COLUMN_NAME");
-                primaryKeys.add(fieldName);
+                primaryKeys.put(rs.getShort("KEY_SEQ"), 
rs.getString("COLUMN_NAME"));
             }
         } catch (SQLException e) {
             throw new JdbcClientException("failed to get jdbc primary key info 
for remote table `%s.%s`: %s",
@@ -216,7 +218,7 @@ public class JdbcMySQLClient extends JdbcClient {
         } finally {
             close(rs, conn);
         }
-        return primaryKeys;
+        return Lists.newArrayList(primaryKeys.values());
     }
 
     protected String getCatalogName(Connection conn) throws SQLException {
diff --git 
a/regression-test/data/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.out
 
b/regression-test/data/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.out
index 5558c43e9ea..27c1b7a6357 100644
--- 
a/regression-test/data/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.out
+++ 
b/regression-test/data/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.out
@@ -1,7 +1,7 @@
 -- This file is automatically generated. You should know what you did if you 
want to edit this
 -- !desc_composite_pk --
-order_id       bigint  No      true    \N      
 tenant_id      int     No      true    \N      
+order_id       bigint  No      true    \N      
 order_no       varchar(192)    Yes     false   \N      NONE
 amount decimal(10,2)   Yes     false   \N      NONE
 
diff --git 
a/regression-test/suites/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.groovy
 
b/regression-test/suites/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.groovy
index 188d459be5f..9cdd43adfa2 100644
--- 
a/regression-test/suites/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.groovy
+++ 
b/regression-test/suites/job_p0/streaming_job/cdc/test_streaming_mysql_job_composite_pk.groovy
@@ -121,12 +121,12 @@ suite("test_streaming_mysql_job_composite_pk", 
"p0,external,mysql,external_docke
         def showTbl = sql """show create table ${currentDb}.${table1}"""
         def createInfo = showTbl[0][1]
         log.info("create table: " + createInfo)
-        assert createInfo.contains("UNIQUE KEY(`order_id`, `tenant_id`)")
+        assert createInfo.contains("UNIQUE KEY(`tenant_id`, `order_id`)")
 
         def showTbl2 = sql """show create table ${currentDb}.${table2}"""
         def createInfo2 = showTbl2[0][1]
         log.info("create table2: " + createInfo2)
-        assert createInfo2.contains("UNIQUE KEY(`role_id`, `user_id`)")
+        assert createInfo2.contains("UNIQUE KEY(`user_id`, `role_id`)")
 
         qt_desc_composite_pk """desc ${currentDb}.${table1};"""
         qt_select_snapshot """select tenant_id, order_id, order_no, amount 
from ${currentDb}.${table1} order by tenant_id, order_id;"""


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to