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

Caideyipi pushed a commit to branch codex/fix-jdbc-protocol-diagnostic-match
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 54dc422a67461690d7ceb1a7425a4891e3cc0485
Author: Caideyipi <[email protected]>
AuthorDate: Tue Nov 3 12:17:07 2026 +0800

    Preserve JDBC legacy-server diagnostics across locales
---
 .../org/apache/iotdb/jdbc/IoTDBConnection.java     |  7 ++-
 .../org/apache/iotdb/jdbc/IoTDBConnectionTest.java | 68 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 3 deletions(-)

diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
index d81f15acdf6..7eabe4e4add 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
@@ -73,6 +73,9 @@ public class IoTDBConnection implements Connection {
   private static final Logger logger = 
LoggerFactory.getLogger(IoTDBConnection.class);
   private static final TSProtocolVersion protocolVersion =
       TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V3;
+  // Match Thrift's fixed protocol text independently of the localized 
SQLException message.
+  private static final String MISSING_CLIENT_PROTOCOL_DIAGNOSTIC =
+      "Required field 'client_protocol' was not present!";
   private static final String NOT_SUPPORT_PREPARE_CALL =
       JdbcMessages.EXCEPTION_DOES_NOT_SUPPORT_PREPARECALL_2E958060;
   private static final String NOT_SUPPORT_PREPARE_STATEMENT =
@@ -619,9 +622,7 @@ public class IoTDBConnection implements Connection {
       }
     } catch (TException e) {
       transport.close();
-      if (e.getMessage()
-          .contains(
-              
JdbcMessages.EXCEPTION_REQUIRED_FIELD_CLIENT_PROTOCOL_WAS_NOT_PRESENT_2059BC1E))
 {
+      if (e.getMessage().contains(MISSING_CLIENT_PROTOCOL_DIAGNOSTIC)) {
         // the server is an old version (less than 0.10)
         throw new SQLException(
             String.format(
diff --git 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
index be3c7de929e..c31726e605c 100644
--- 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
+++ 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
@@ -20,13 +20,16 @@
 package org.apache.iotdb.jdbc;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.jdbc.i18n.JdbcMessages;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.service.rpc.thrift.IClientRPCService;
 import org.apache.iotdb.service.rpc.thrift.ServerProperties;
 import org.apache.iotdb.service.rpc.thrift.TSGetTimeZoneResp;
+import org.apache.iotdb.service.rpc.thrift.TSOpenSessionReq;
 import org.apache.iotdb.service.rpc.thrift.TSSetTimeZoneReq;
 
 import org.apache.thrift.TException;
+import org.apache.thrift.transport.TTransport;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -34,17 +37,25 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.sql.SQLClientInfoException;
 import java.sql.SQLException;
 import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Properties;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -158,4 +169,61 @@ public class IoTDBConnectionTest {
 
     verify(tableConnection, never()).prepareStatement(anyString());
   }
+
+  @Test
+  public void testOpenSessionRecognizesLegacyProtocolDiagnostic() throws 
Exception {
+    TException cause =
+        new TException(
+            "Required field 'client_protocol' was not present! Struct: 
TSOpenSessionReq(...)");
+
+    SQLException exception = failOpenSession(cause);
+
+    assertEquals(
+        String.format(
+            JdbcMessages
+                
.EXCEPTION_CAN_NOT_ESTABLISH_CONNECTION_ARG_YOU_MAY_TRY_CONNECT_OLD_8FC3703E,
+            connection.getParams().getJdbcUriString(),
+            cause.getMessage()),
+        exception.getMessage());
+  }
+
+  @Test
+  public void testOpenSessionPreservesOtherMissingFieldDiagnostic() throws 
Exception {
+    TException cause =
+        new TException("Required field 'username' was not present! Struct: 
TSOpenSessionReq(...)");
+
+    SQLException exception = failOpenSession(cause);
+
+    assertEquals(
+        String.format(
+            
JdbcMessages.EXCEPTION_CAN_NOT_ESTABLISH_CONNECTION_ARG_ARG_D7246055,
+            connection.getParams().getJdbcUriString(),
+            cause.getMessage()),
+        exception.getMessage());
+  }
+
+  private SQLException failOpenSession(TException cause) throws Exception {
+    IoTDBConnectionParams params =
+        Utils.parseUrl("jdbc:iotdb://127.0.0.1:6667/", new Properties());
+    Field paramsField = IoTDBConnection.class.getDeclaredField("params");
+    paramsField.setAccessible(true);
+    paramsField.set(connection, params);
+    TTransport transport = mock(TTransport.class);
+    Field transportField = IoTDBConnection.class.getDeclaredField("transport");
+    transportField.setAccessible(true);
+    transportField.set(connection, transport);
+    connection.setClient(client);
+    when(client.openSession(any(TSOpenSessionReq.class))).thenThrow(cause);
+    Method openSession = 
IoTDBConnection.class.getDeclaredMethod("openSession");
+    openSession.setAccessible(true);
+
+    InvocationTargetException invocationException =
+        assertThrows(InvocationTargetException.class, () -> 
openSession.invoke(connection));
+
+    assertTrue(invocationException.getCause() instanceof SQLException);
+    SQLException exception = (SQLException) invocationException.getCause();
+    assertSame(cause, exception.getCause());
+    verify(transport).close();
+    return exception;
+  }
 }

Reply via email to