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

suxiaogang223 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 fd4f4b57fc3 [fix](fe) Detect Doris JDBC targets with stable server 
identity (#68321)
fd4f4b57fc3 is described below

commit fd4f4b57fc3a9ee6a1693788b57a9c1711d000ed
Author: Socrates <[email protected]>
AuthorDate: Thu Sep 24 15:32:51 2026 +0800

    [fix](fe) Detect Doris JDBC targets with stable server identity (#68321)
    
    ### What problem does this PR solve?
    
    JDBC Catalog currently decides whether a MySQL-compatible endpoint is
    Doris by parsing `version_comment`. That value is display text and may
    change with product branding or packaging. When the expected marker is
    absent, the endpoint is treated as MySQL and Doris-specific types can be
    mapped incorrectly.
    
    This change exposes a stable, read-only `doris_server_identity` session
    variable with the value `apache_doris`. Both JDBC client implementations
    probe this variable first and use exact identity matching. If the remote
    endpoint does not expose the variable, they fall back to the existing
    `version_comment` detection so older endpoints remain compatible.
    
    The compatibility adjustment for existing enterprise version comments
    remains a separate commit, allowing it to be reviewed or applied
    independently.
    
    ### Release note
    
    Use a stable server identity when detecting Doris JDBC endpoints, with
    backward-compatible fallback for older endpoints.
    
    ### Check List (For Author)
    
    - Test: Unit Test
    - `./run-fe-ut.sh --run
    
org.apache.doris.datasource.jdbc.client.JdbcMySQLClientTest,org.apache.doris.connector.jdbc.client.JdbcMySQLConnectorClientTest`
    - Both test classes passed: 4 tests total, 0 failures, 0 errors, 0
    skipped
    - FE build, checkstyle, and metadata funnel checks passed as part of the
    test command
    - Behavior changed: Yes. JDBC Catalog prefers the stable server identity
    and falls back to the existing version comment probe when the identity
    variable is unavailable.
    - Does this need documentation: No
---
 .../jdbc/client/JdbcMySQLConnectorClient.java         | 18 +++++++++++++++---
 .../jdbc/client/JdbcMySQLConnectorClientTest.java     | 10 ++++++++++
 .../doris/datasource/jdbc/client/JdbcMySQLClient.java | 19 ++++++++++++++++---
 .../java/org/apache/doris/qe/SessionVariable.java     |  5 +++++
 .../datasource/jdbc/client/JdbcMySQLClientTest.java   | 10 ++++++++++
 5 files changed, 56 insertions(+), 6 deletions(-)

diff --git 
a/fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClient.java
 
b/fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClient.java
index 9874d1b2460..992bf5b2b44 100644
--- 
a/fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClient.java
+++ 
b/fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClient.java
@@ -47,6 +47,7 @@ import java.util.function.Consumer;
 public class JdbcMySQLConnectorClient extends JdbcConnectorClient {
 
     private static final Logger LOG = 
LogManager.getLogger(JdbcMySQLConnectorClient.class);
+    private static final String APACHE_DORIS_SERVER_IDENTITY = "apache_doris";
 
     private final boolean convertDateToNull;
     private boolean isDoris = false;
@@ -76,10 +77,15 @@ public class JdbcMySQLConnectorClient extends 
JdbcConnectorClient {
         try {
             conn = getConnection();
             stmt = conn.createStatement();
-            rs = stmt.executeQuery("SHOW VARIABLES LIKE 'version_comment'");
+            rs = stmt.executeQuery("SHOW VARIABLES LIKE 'server_identity'");
             if (rs.next()) {
-                String versionComment = rs.getString("Value");
-                isDoris = isDorisCompatibleVersionComment(versionComment);
+                isDoris = isDorisServerIdentity(rs.getString("Value"));
+            } else {
+                closeResources(rs);
+                rs = stmt.executeQuery("SHOW VARIABLES LIKE 
'version_comment'");
+                if (rs.next()) {
+                    isDoris = 
isDorisCompatibleVersionComment(rs.getString("Value"));
+                }
             }
         } catch (Exception e) {
             LOG.warn("Failed to detect if remote MySQL is Doris: {}", 
e.getMessage());
@@ -88,14 +94,20 @@ public class JdbcMySQLConnectorClient extends 
JdbcConnectorClient {
         }
     }
 
+    static boolean isDorisServerIdentity(String serverIdentity) {
+        return APACHE_DORIS_SERVER_IDENTITY.equalsIgnoreCase(serverIdentity);
+    }
+
     static boolean isDorisCompatibleVersionComment(String versionComment) {
         if (versionComment == null || versionComment.isEmpty()) {
             return false;
         }
         String lowerVersionComment = versionComment.toLowerCase(Locale.ROOT);
+        // Enterprise releases can omit the optional "(Cloud Mode)" suffix.
         return lowerVersionComment.contains("doris")
                 || lowerVersionComment.contains("selectdb")
                 || lowerVersionComment.contains("velodb")
+                || lowerVersionComment.contains("enterprise version 
enterprise-")
                 || (lowerVersionComment.contains("enterprise version")
                     && lowerVersionComment.contains("cloud mode"));
     }
diff --git 
a/fe/fe-connector/fe-connector-jdbc/src/test/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClientTest.java
 
b/fe/fe-connector/fe-connector-jdbc/src/test/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClientTest.java
index 5cb178a9268..772108a5b72 100644
--- 
a/fe/fe-connector/fe-connector-jdbc/src/test/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClientTest.java
+++ 
b/fe/fe-connector/fe-connector-jdbc/src/test/java/org/apache/doris/connector/jdbc/client/JdbcMySQLConnectorClientTest.java
@@ -22,6 +22,14 @@ import org.junit.jupiter.api.Test;
 
 public class JdbcMySQLConnectorClientTest {
 
+    @Test
+    void testIsDorisServerIdentity() {
+        
Assertions.assertTrue(JdbcMySQLConnectorClient.isDorisServerIdentity("apache_doris"));
+        
Assertions.assertTrue(JdbcMySQLConnectorClient.isDorisServerIdentity("APACHE_DORIS"));
+        
Assertions.assertFalse(JdbcMySQLConnectorClient.isDorisServerIdentity("mysql"));
+        
Assertions.assertFalse(JdbcMySQLConnectorClient.isDorisServerIdentity(null));
+    }
+
     @Test
     void testIsDorisCompatibleVersionComment() {
         
Assertions.assertTrue(JdbcMySQLConnectorClient.isDorisCompatibleVersionComment(
@@ -32,6 +40,8 @@ public class JdbcMySQLConnectorClientTest {
                 "VeloDB version 2.1.0"));
         
Assertions.assertTrue(JdbcMySQLConnectorClient.isDorisCompatibleVersionComment(
                 "enterprise version enterprise-4.0.5-rc01-0724569463d (Cloud 
Mode)"));
+        
Assertions.assertTrue(JdbcMySQLConnectorClient.isDorisCompatibleVersionComment(
+                "enterprise version enterprise-current"));
 
         
Assertions.assertFalse(JdbcMySQLConnectorClient.isDorisCompatibleVersionComment(
                 "MySQL Community Server - GPL"));
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 bcdc9ccc03b..c3233c859a3 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
@@ -45,6 +45,8 @@ import java.util.function.Consumer;
 
 public class JdbcMySQLClient extends JdbcClient {
 
+    private static final String APACHE_DORIS_SERVER_IDENTITY = "apache_doris";
+
     private boolean convertDateToNull = false;
     private boolean isDoris = false;
 
@@ -57,10 +59,15 @@ public class JdbcMySQLClient extends JdbcClient {
         try {
             conn = super.getConnection();
             stmt = conn.createStatement();
-            rs = stmt.executeQuery("SHOW VARIABLES LIKE 'version_comment'");
+            rs = stmt.executeQuery("SHOW VARIABLES LIKE 'server_identity'");
             if (rs.next()) {
-                String versionComment = rs.getString("Value");
-                isDoris = isDorisCompatibleVersionComment(versionComment);
+                isDoris = isDorisServerIdentity(rs.getString("Value"));
+            } else {
+                close(rs);
+                rs = stmt.executeQuery("SHOW VARIABLES LIKE 
'version_comment'");
+                if (rs.next()) {
+                    isDoris = 
isDorisCompatibleVersionComment(rs.getString("Value"));
+                }
             }
         } catch (SQLException | JdbcClientException e) {
             closeClient();
@@ -76,14 +83,20 @@ public class JdbcMySQLClient extends JdbcClient {
         this.dbType = dbType;
     }
 
+    static boolean isDorisServerIdentity(String serverIdentity) {
+        return APACHE_DORIS_SERVER_IDENTITY.equalsIgnoreCase(serverIdentity);
+    }
+
     static boolean isDorisCompatibleVersionComment(String versionComment) {
         if (Strings.isNullOrEmpty(versionComment)) {
             return false;
         }
         String lowerVersionComment = versionComment.toLowerCase(Locale.ROOT);
+        // Enterprise releases can omit the optional "(Cloud Mode)" suffix.
         return lowerVersionComment.contains("doris")
                 || lowerVersionComment.contains("selectdb")
                 || lowerVersionComment.contains("velodb")
+                || lowerVersionComment.contains("enterprise version 
enterprise-")
                 || (lowerVersionComment.contains("enterprise version")
                     && lowerVersionComment.contains("cloud mode"));
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index c0c995e4817..e6ee9525c24 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -164,6 +164,8 @@ public class SessionVariable implements Serializable, 
Writable {
     public static final String SQL_SAFE_UPDATES = "sql_safe_updates";
     public static final String NET_BUFFER_LENGTH = "net_buffer_length";
     public static final String HAVE_QUERY_CACHE =  "have_query_cache";
+    public static final String SERVER_IDENTITY = "server_identity";
+    public static final String APACHE_DORIS_SERVER_IDENTITY = "apache_doris";
     // mem limit can't smaller than bufferpool's default page size
     public static final int MIN_EXEC_MEM_LIMIT = 2097152;
     public static final String BATCH_SIZE = "batch_size";
@@ -1385,6 +1387,9 @@ public class SessionVariable implements Serializable, 
Writable {
     @VarAttrDef.VarAttr(name = HAVE_QUERY_CACHE, flag = VarAttrDef.READ_ONLY)
     public boolean haveQueryCache = false;
 
+    @VarAttrDef.VarAttr(name = SERVER_IDENTITY, flag = VarAttrDef.READ_ONLY)
+    public String serverIdentity = APACHE_DORIS_SERVER_IDENTITY;
+
     // 8192 minus 16 + 16 bytes padding that in padding pod array.
     // This remains the row cap for output blocks even when adaptive byte 
budgeting is enabled.
     @VarAttrDef.VarAttr(name = BATCH_SIZE, fuzzy = true, checker = 
"checkBatchSize", needForward = true)
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClientTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClientTest.java
index 6379c0db52a..375bb4f2e03 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClientTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/jdbc/client/JdbcMySQLClientTest.java
@@ -22,6 +22,14 @@ import org.junit.jupiter.api.Test;
 
 public class JdbcMySQLClientTest {
 
+    @Test
+    public void testIsDorisServerIdentity() {
+        
Assertions.assertTrue(JdbcMySQLClient.isDorisServerIdentity("apache_doris"));
+        
Assertions.assertTrue(JdbcMySQLClient.isDorisServerIdentity("APACHE_DORIS"));
+        Assertions.assertFalse(JdbcMySQLClient.isDorisServerIdentity("mysql"));
+        Assertions.assertFalse(JdbcMySQLClient.isDorisServerIdentity(null));
+    }
+
     @Test
     public void testIsDorisCompatibleVersionComment() {
         
Assertions.assertTrue(JdbcMySQLClient.isDorisCompatibleVersionComment("Apache 
Doris version 3.1.0"));
@@ -29,6 +37,8 @@ public class JdbcMySQLClientTest {
         
Assertions.assertTrue(JdbcMySQLClient.isDorisCompatibleVersionComment("VeloDB 
version 2.1.0"));
         Assertions.assertTrue(JdbcMySQLClient.isDorisCompatibleVersionComment(
                 "enterprise version enterprise-4.0.5-rc01-0724569463d (Cloud 
Mode)"));
+        Assertions.assertTrue(JdbcMySQLClient.isDorisCompatibleVersionComment(
+                "enterprise version enterprise-current"));
 
         
Assertions.assertFalse(JdbcMySQLClient.isDorisCompatibleVersionComment("MySQL 
Community Server - GPL"));
         
Assertions.assertFalse(JdbcMySQLClient.isDorisCompatibleVersionComment(""));


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

Reply via email to