You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2024/05/31 10:14:42 UTC

(iotdb) branch jdbc-charset created (now d09621bf4ed)

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

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


      at d09621bf4ed Add example

This branch includes the following new commits:

     new 2bc39499c8b JDBC: SUPPORT DIFFERENT CHARSETS
     new d09621bf4ed Add example

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(iotdb) 02/02: Add example

Posted by ro...@apache.org.
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 d09621bf4ede5423da853835e328aa9fac4d4ecf
Author: Steve Yurong Su <ro...@apache.org>
AuthorDate: Fri May 31 18:14:29 2024 +0800

    Add example
---
 .../java/org/apache/iotdb/JDBCCharsetExample.java  | 86 ++++++++++++++++++++++
 .../java/org/apache/iotdb/jdbc/IoTDBStatement.java |  9 ++-
 .../apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java  | 36 ++++-----
 3 files changed, 113 insertions(+), 18 deletions(-)

diff --git a/example/jdbc/src/main/java/org/apache/iotdb/JDBCCharsetExample.java b/example/jdbc/src/main/java/org/apache/iotdb/JDBCCharsetExample.java
new file mode 100644
index 00000000000..143983d38c5
--- /dev/null
+++ b/example/jdbc/src/main/java/org/apache/iotdb/JDBCCharsetExample.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb;
+
+import org.apache.iotdb.jdbc.IoTDBSQLException;
+import org.apache.iotdb.jdbc.IoTDBStatement;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.UnsupportedEncodingException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+public class JDBCCharsetExample {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(JDBCCharsetExample.class);
+
+  public static void main(String[] args) throws Exception {
+    Class.forName("org.apache.iotdb.jdbc.IoTDBDriver");
+
+    try (final Connection connection =
+            DriverManager.getConnection(
+                "jdbc:iotdb://127.0.0.1:6667?charset=GB18030", "root", "root");
+        final IoTDBStatement statement = (IoTDBStatement) connection.createStatement()) {
+
+      final String insertSQLWithGB18030 =
+          "insert into root.测试(timestamp, 维语, 彝语, 繁体, 蒙文, 简体, 标点符号, 藏语) values(1, 'ئۇيغۇر تىلى', 'ꆈꌠꉙ', \"繁體\", 'ᠮᠣᠩᠭᠣᠯ ᠬᠡᠯᠡ', '简体', '——?!', \"བོད་སྐད།\");";
+      final byte[] insertSQLWithGB18030Bytes = insertSQLWithGB18030.getBytes("GB18030");
+      statement.execute(insertSQLWithGB18030Bytes);
+
+      ResultSet resultSet = statement.executeQuery("select ** from root");
+      outputResult(resultSet);
+    } catch (IoTDBSQLException e) {
+      LOGGER.error("IoTDB Jdbc example error", e);
+    }
+  }
+
+  @SuppressWarnings({"squid:S106"})
+  private static void outputResult(ResultSet resultSet)
+      throws SQLException, UnsupportedEncodingException {
+    if (resultSet != null) {
+      System.out.println("--------------------------");
+      final ResultSetMetaData metaData = resultSet.getMetaData();
+      final int columnCount = metaData.getColumnCount();
+      for (int i = 0; i < columnCount; i++) {
+        System.out.print(metaData.getColumnLabel(i + 1) + " ");
+      }
+      System.out.println();
+
+      while (resultSet.next()) {
+        for (int i = 1; ; i++) {
+          System.out.print(
+              resultSet.getString(i) + " (" + new String(resultSet.getBytes(i), "GB18030") + ")");
+          if (i < columnCount) {
+            System.out.print(", ");
+          } else {
+            System.out.println();
+            break;
+          }
+        }
+      }
+      System.out.println("--------------------------\n");
+    }
+  }
+}
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 f321bd9d800..ffc79a41a72 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
@@ -129,7 +129,14 @@ public class IoTDBStatement implements Statement {
       ZoneId zoneId,
       int seconds)
       throws SQLException {
-    this(connection, client, sessionId, Config.DEFAULT_FETCH_SIZE, zoneId, Charset.defaultCharset(), seconds);
+    this(
+        connection,
+        client,
+        sessionId,
+        Config.DEFAULT_FETCH_SIZE,
+        zoneId,
+        Charset.defaultCharset(),
+        seconds);
   }
 
   // Only for tests
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 46595d3d79c..e69c7673d66 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,23 +19,6 @@
 
 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;
@@ -46,6 +29,7 @@ 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;
@@ -55,6 +39,24 @@ 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.


(iotdb) 01/02: JDBC: SUPPORT DIFFERENT CHARSETS

Posted by ro...@apache.org.
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 <ro...@apache.org>
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());