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

rong pushed a commit to branch jdbc-charset
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 2bc39499c8bd3104a192e6cd0e1691fb58e5273d
Author: Steve Yurong Su <[email protected]>
AuthorDate: Fri May 31 18:00:45 2024 +0800

    JDBC: SUPPORT DIFFERENT CHARSETS
---
 .../main/java/org/apache/iotdb/jdbc/Config.java    |  3 +
 .../org/apache/iotdb/jdbc/IoTDBConnection.java     | 10 ++-
 .../apache/iotdb/jdbc/IoTDBConnectionParams.java   | 10 +++
 .../org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java  | 54 +++++++++++++-
 .../apache/iotdb/jdbc/IoTDBPreparedStatement.java  | 16 ++++-
 .../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 83 +++++++++++++++++-----
 .../src/main/java/org/apache/iotdb/jdbc/Utils.java | 16 +++--
 .../apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java  | 36 +++++-----
 .../org/apache/iotdb/jdbc/IoTDBStatementTest.java  |  8 ++-
 9 files changed, 188 insertions(+), 48 deletions(-)

diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
index 407f07ef30d..4e2e0f38300 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Config.java
@@ -73,6 +73,9 @@ public class Config {
   /** Key of connection's time zone. */
   public static final String TIME_ZONE = "time_zone";
 
+  /** Key of connection's charset. */
+  public static final String CHARSET = "charset";
+
   public static final String USE_SSL = "use_ssl";
 
   public static final String TRUST_STORE = "trust_store";
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 8b3bef19cb9..06e92215155 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
@@ -39,6 +39,7 @@ import org.apache.thrift.transport.TTransportException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.nio.charset.Charset;
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.CallableStatement;
@@ -89,6 +90,8 @@ public class IoTDBConnection implements Connection {
   private int networkTimeout = Config.DEFAULT_CONNECTION_TIMEOUT_MS;
 
   private ZoneId zoneId;
+  private Charset charset;
+
   private boolean autoCommit;
   private String url;
 
@@ -111,6 +114,7 @@ public class IoTDBConnection implements Connection {
     this.userName = info.get("user").toString();
     this.networkTimeout = params.getNetworkTimeout();
     this.zoneId = ZoneId.of(params.getTimeZone());
+    this.charset = params.getCharset();
     openTransport();
     if (Config.rpcThriftCompressionEnable) {
       setClient(new IClientRPCService.Client(new TCompactProtocol(transport)));
@@ -200,7 +204,7 @@ public class IoTDBConnection implements Connection {
     if (isClosed) {
       throw new SQLException("Cannot create statement because connection is 
closed");
     }
-    return new IoTDBStatement(this, getClient(), sessionId, zoneId, 
queryTimeout);
+    return new IoTDBStatement(this, getClient(), sessionId, zoneId, charset, 
queryTimeout);
   }
 
   @Override
@@ -215,7 +219,7 @@ public class IoTDBConnection implements Connection {
       throw new SQLException(
           String.format("Statements with ResultSet type %d are not supported", 
resultSetType));
     }
-    return new IoTDBStatement(this, getClient(), sessionId, zoneId, 
queryTimeout);
+    return new IoTDBStatement(this, getClient(), sessionId, zoneId, charset, 
queryTimeout);
   }
 
   @Override
@@ -366,7 +370,7 @@ public class IoTDBConnection implements Connection {
 
   @Override
   public PreparedStatement prepareStatement(String sql) throws SQLException {
-    return new IoTDBPreparedStatement(this, getClient(), sessionId, sql, 
zoneId);
+    return new IoTDBPreparedStatement(this, getClient(), sessionId, sql, 
zoneId, charset);
   }
 
   @Override
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
index d1523691f79..be51a8fcf07 100644
--- 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
+++ 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnectionParams.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.jdbc;
 
 import org.apache.iotdb.rpc.RpcUtils;
 
+import java.nio.charset.Charset;
 import java.time.ZoneId;
 
 public class IoTDBConnectionParams {
@@ -40,6 +41,7 @@ public class IoTDBConnectionParams {
   private int networkTimeout = Config.DEFAULT_CONNECTION_TIMEOUT_MS;
 
   private String timeZone = ZoneId.systemDefault().toString();
+  private Charset charset = Charset.defaultCharset();
 
   private boolean useSSL = false;
   private String trustStore;
@@ -141,6 +143,14 @@ public class IoTDBConnectionParams {
     return this.timeZone;
   }
 
+  public void setCharset(String charsetName) {
+    this.charset = Charset.forName(charsetName);
+  }
+
+  public Charset getCharset() {
+    return charset;
+  }
+
   public boolean isUseSSL() {
     return useSSL;
   }
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
index df558b18809..17288335015 100644
--- 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
+++ 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
@@ -37,6 +37,7 @@ import java.math.BigDecimal;
 import java.math.MathContext;
 import java.net.URL;
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.Clob;
@@ -70,6 +71,7 @@ public class IoTDBJDBCResultSet implements ResultSet {
   private String operationType = "";
   private List<String> columns = null;
   private List<String> sgColumns = null;
+  private Charset charset = Charset.defaultCharset();
   private String timeFormat = RpcUtils.DEFAULT_TIME_FORMAT;
 
   @SuppressWarnings("squid:S107") // ignore Methods should not have too many 
parameters
@@ -91,7 +93,8 @@ public class IoTDBJDBCResultSet implements ResultSet {
       List<String> sgColumns,
       BitSet aliasColumnMap,
       boolean moreData,
-      ZoneId zoneId)
+      ZoneId zoneId,
+      Charset charset)
       throws SQLException {
     this.ioTDBRpcDataSet =
         new IoTDBRpcDataSet(
@@ -121,6 +124,51 @@ public class IoTDBJDBCResultSet implements ResultSet {
     this.operationType = operationType;
     this.columns = columns;
     this.sgColumns = sgColumns;
+    this.charset = charset;
+  }
+
+  @SuppressWarnings("squid:S107") // ignore Methods should not have too many 
parameters
+  public IoTDBJDBCResultSet(
+      Statement statement,
+      List<String> columnNameList,
+      List<String> columnTypeList,
+      Map<String, Integer> columnNameIndex,
+      boolean ignoreTimeStamp,
+      IClientRPCService.Iface client,
+      String sql,
+      long queryId,
+      long sessionId,
+      List<ByteBuffer> dataSet,
+      TSTracingInfo tracingInfo,
+      long timeout,
+      boolean moreData,
+      ZoneId zoneId,
+      Charset charset)
+      throws SQLException {
+    this.ioTDBRpcDataSet =
+        new IoTDBRpcDataSet(
+            sql,
+            columnNameList,
+            columnTypeList,
+            columnNameIndex,
+            ignoreTimeStamp,
+            moreData,
+            queryId,
+            ((IoTDBStatement) statement).getStmtId(),
+            client,
+            sessionId,
+            dataSet,
+            statement.getFetchSize(),
+            timeout,
+            zoneId,
+            timeFormat);
+    this.statement = statement;
+    this.columnTypeList = columnTypeList;
+    if (tracingInfo != null) {
+      ioTDBRpcTracingInfo = new IoTDBTracingInfo();
+      ioTDBRpcTracingInfo.setTsTracingInfo(tracingInfo);
+    }
+    this.charset = charset;
   }
 
   @SuppressWarnings("squid:S107") // ignore Methods should not have too many 
parameters
@@ -327,7 +375,7 @@ public class IoTDBJDBCResultSet implements ResultSet {
   @Override
   public byte[] getBytes(int columnIndex) throws SQLException {
     try {
-      return ioTDBRpcDataSet.getBinary(columnIndex).getValues();
+      return ioTDBRpcDataSet.getString(columnIndex).getBytes(charset);
     } catch (StatementExecutionException e) {
       throw new SQLException(e.getMessage());
     }
@@ -336,7 +384,7 @@ public class IoTDBJDBCResultSet implements ResultSet {
   @Override
   public byte[] getBytes(String columnName) throws SQLException {
     try {
-      return ioTDBRpcDataSet.getBinary(columnName).getValues();
+      return ioTDBRpcDataSet.getString(columnName).getBytes(charset);
     } catch (StatementExecutionException e) {
       throw new SQLException(e.getMessage());
     }
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
index 6cc0db318de..708450b05cb 100644
--- 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
+++ 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
@@ -32,6 +32,7 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.nio.charset.Charset;
 import java.sql.Array;
 import java.sql.Blob;
 import java.sql.Clob;
@@ -71,10 +72,23 @@ public class IoTDBPreparedStatement extends IoTDBStatement 
implements PreparedSt
   /** save the SQL parameters as (paramLoc,paramValue) pairs. */
   private final Map<Integer, String> parameters = new HashMap<>();
 
+  IoTDBPreparedStatement(
+      IoTDBConnection connection,
+      Iface client,
+      Long sessionId,
+      String sql,
+      ZoneId zoneId,
+      Charset charset)
+      throws SQLException {
+    super(connection, client, sessionId, zoneId, charset);
+    this.sql = sql;
+  }
+
+  // Only for tests
   IoTDBPreparedStatement(
       IoTDBConnection connection, Iface client, Long sessionId, String sql, 
ZoneId zoneId)
       throws SQLException {
-    super(connection, client, sessionId, zoneId);
+    super(connection, client, sessionId, zoneId, Charset.defaultCharset());
     this.sql = sql;
   }
 
diff --git 
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index 6d93c932d0d..f321bd9d800 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -32,6 +32,7 @@ import 
org.apache.iotdb.service.rpc.thrift.TSExecuteStatementResp;
 
 import org.apache.thrift.TException;
 
+import java.nio.charset.Charset;
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -45,12 +46,15 @@ import java.util.List;
 
 public class IoTDBStatement implements Statement {
 
-  ZoneId zoneId;
+  private final IoTDBConnection connection;
+
   private ResultSet resultSet = null;
-  private IoTDBConnection connection;
   private int fetchSize;
   private int maxRows = 0;
 
+  protected final ZoneId zoneId;
+  protected final Charset charset;
+
   /**
    * Timeout of query can be set by users. Unit: s. A negative number means 
using the default
    * configuration of server. And value 0 will disable the function of query 
timeout.
@@ -82,6 +86,7 @@ public class IoTDBStatement implements Statement {
       long sessionId,
       int fetchSize,
       ZoneId zoneId,
+      Charset charset,
       int seconds)
       throws SQLException {
     this.connection = connection;
@@ -90,11 +95,44 @@ public class IoTDBStatement implements Statement {
     this.fetchSize = fetchSize;
     this.batchSQLList = new ArrayList<>();
     this.zoneId = zoneId;
+    this.charset = charset;
     this.queryTimeout = seconds;
     requestStmtId();
   }
 
-  // only for test
+  IoTDBStatement(
+      IoTDBConnection connection,
+      IClientRPCService.Iface client,
+      long sessionId,
+      ZoneId zoneId,
+      Charset charset,
+      int seconds)
+      throws SQLException {
+    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, 
charset, seconds);
+  }
+
+  IoTDBStatement(
+      IoTDBConnection connection,
+      IClientRPCService.Iface client,
+      long sessionId,
+      ZoneId zoneId,
+      Charset charset)
+      throws SQLException {
+    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, 
charset, 0);
+  }
+
+  // Only for tests
+  IoTDBStatement(
+      IoTDBConnection connection,
+      IClientRPCService.Iface client,
+      long sessionId,
+      ZoneId zoneId,
+      int seconds)
+      throws SQLException {
+    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, 
Charset.defaultCharset(), seconds);
+  }
+
+  // Only for tests
   IoTDBStatement(
       IoTDBConnection connection,
       IClientRPCService.Iface client,
@@ -108,24 +146,23 @@ public class IoTDBStatement implements Statement {
     this.fetchSize = Config.DEFAULT_FETCH_SIZE;
     this.batchSQLList = new ArrayList<>();
     this.zoneId = zoneId;
+    this.charset = Charset.defaultCharset();
     this.queryTimeout = seconds;
     this.stmtId = statementId;
   }
 
+  // Only for tests
   IoTDBStatement(
       IoTDBConnection connection, IClientRPCService.Iface client, long 
sessionId, ZoneId zoneId)
       throws SQLException {
-    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, 0);
-  }
-
-  IoTDBStatement(
-      IoTDBConnection connection,
-      IClientRPCService.Iface client,
-      long sessionId,
-      ZoneId zoneId,
-      int seconds)
-      throws SQLException {
-    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, 
seconds);
+    this(
+        connection,
+        client,
+        sessionId,
+        Config.DEFAULT_FETCH_SIZE,
+        zoneId,
+        Charset.defaultCharset(),
+        0);
   }
 
   @Override
@@ -206,6 +243,18 @@ public class IoTDBStatement implements Statement {
     throw new SQLException("Not support closeOnCompletion");
   }
 
+  /**
+   * Execute a SQL encoded in bytes with {@link IoTDBStatement#charset}.
+   *
+   * @param sql raw sql in bytes encoded with {@link IoTDBStatement#charset}
+   * @return true if the first result is a {@link ResultSet} object; false if 
the first result is an
+   *     update count or there is no result
+   * @throws SQLException if a database access error occurs
+   */
+  public boolean execute(byte[] sql) throws SQLException {
+    return execute(new String(sql, charset));
+  }
+
   @Override
   public boolean execute(String sql) throws SQLException {
     checkConnection("execute");
@@ -302,7 +351,8 @@ public class IoTDBStatement implements Statement {
                 execResp.tracingInfo,
                 execReq.timeout,
                 execResp.moreData,
-                zoneId);
+                zoneId,
+                charset);
       }
       return true;
     }
@@ -457,7 +507,8 @@ public class IoTDBStatement implements Statement {
               execResp.sgColumns,
               aliasColumn,
               execResp.moreData,
-              zoneId);
+              zoneId,
+              charset);
     }
     return resultSet;
   }
diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java 
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
index af884d3e781..dcda9e3071e 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.jdbc;
 
+import java.nio.charset.Charset;
 import java.time.DateTimeException;
 import java.time.ZoneId;
 import java.util.Properties;
@@ -104,19 +105,18 @@ public class Utils {
     if (info.containsKey(Config.TIME_ZONE)) {
       params.setTimeZone(info.getProperty(Config.TIME_ZONE));
     }
-
+    if (info.containsKey(Config.CHARSET)) {
+      params.setCharset(info.getProperty(Config.CHARSET));
+    }
     if (info.containsKey(Config.USE_SSL)) {
       params.setUseSSL(Boolean.parseBoolean(info.getProperty(Config.USE_SSL)));
     }
-
     if (info.containsKey(Config.TRUST_STORE)) {
       params.setTrustStore(info.getProperty(Config.TRUST_STORE));
     }
-
     if (info.containsKey(Config.TRUST_STORE_PWD)) {
       params.setTrustStorePwd(info.getProperty(Config.TRUST_STORE_PWD));
     }
-
     return params;
   }
 
@@ -165,6 +165,14 @@ public class Utils {
           }
           info.put(key, value);
           break;
+        case Config.CHARSET:
+          try {
+            Charset.forName(value);
+          } catch (Exception e) {
+            return false;
+          }
+          info.put(key, value);
+          break;
         default:
           return false;
       }
diff --git 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
index e69c7673d66..46595d3d79c 100644
--- 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
+++ 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
@@ -19,6 +19,23 @@
 
 package org.apache.iotdb.jdbc;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.sql.Types;
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.service.rpc.thrift.IClientRPCService;
@@ -29,7 +46,6 @@ import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataReq;
 import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataResp;
 import org.apache.iotdb.service.rpc.thrift.TSFetchResultsReq;
 import org.apache.iotdb.service.rpc.thrift.TSFetchResultsResp;
-
 import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.read.common.block.TsBlockBuilder;
 import org.apache.tsfile.read.common.block.column.TsBlockSerde;
@@ -39,24 +55,6 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.Statement;
-import java.sql.Types;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 /*
    This class is designed to test the function of TsfileQueryResultSet.
    This class also sheds light on the complete execution process of a query 
sql from the jdbc perspective.
diff --git 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
index 2699c442d39..b18a7068b5b 100644
--- 
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
+++ 
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
@@ -31,6 +31,7 @@ import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.nio.charset.Charset;
 import java.sql.SQLException;
 import java.time.ZoneId;
 
@@ -84,7 +85,9 @@ public class IoTDBStatementTest {
   @Test
   public void testSetFetchSize3() throws SQLException {
     final int fetchSize = 10000;
-    IoTDBStatement stmt = new IoTDBStatement(connection, client, sessionId, 
fetchSize, zoneID, 0);
+    IoTDBStatement stmt =
+        new IoTDBStatement(
+            connection, client, sessionId, fetchSize, zoneID, 
Charset.defaultCharset(), 0);
     assertEquals(fetchSize, stmt.getFetchSize());
   }
 
@@ -97,7 +100,8 @@ public class IoTDBStatementTest {
 
   @Test
   public void setTimeoutTest() throws SQLException {
-    IoTDBStatement statement = new IoTDBStatement(connection, client, 
sessionId, zoneID, 60);
+    IoTDBStatement statement =
+        new IoTDBStatement(connection, client, sessionId, zoneID, 
Charset.defaultCharset(), 60);
     Assert.assertEquals(60, statement.getQueryTimeout());
     statement.setQueryTimeout(100);
     Assert.assertEquals(100, statement.getQueryTimeout());

Reply via email to