You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ji...@apache.org on 2019/06/25 14:46:36 UTC

[incubator-iotdb] 01/01: add prepared statement

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

jiangtian pushed a commit to branch feature_prepared_statement
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git

commit a8f58b65d4f13840baaf6a3f5c671cc97746a7fb
Author: 江天 <jt...@163.com>
AuthorDate: Tue Jun 25 22:44:27 2019 +0800

    add prepared statement
---
 .../org/apache/iotdb/db/service/TSServiceImpl.java |  20 +++
 .../iotdb/db/integration/IoTDBPreparedStmtIT.java  | 186 +++++++++++++++++++++
 .../org/apache/iotdb/jdbc/IoTDBConnection.java     |   5 +-
 .../jdbc/IoTDBPreparedInsertionStatement.java      |  57 +++++++
 ...eStatement.java => IoTDBPreparedStatement.java} |  11 +-
 .../java/org/apache/iotdb/jdbc/IoTDBStatement.java |   2 +-
 ...ntTest.java => IoTDBPreparedStatementTest.java} |  32 ++--
 service-rpc/src/main/thrift/rpc.thrift             |   9 +
 8 files changed, 301 insertions(+), 21 deletions(-)

diff --git a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 6fe08c8..0458f3a 100644
--- a/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/iotdb/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -52,6 +52,7 @@ import org.apache.iotdb.db.qp.QueryProcessor;
 import org.apache.iotdb.db.qp.executor.OverflowQPExecutor;
 import org.apache.iotdb.db.qp.logical.Operator;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
 import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
@@ -74,6 +75,7 @@ import org.apache.iotdb.service.rpc.thrift.TSFetchResultsResp;
 import org.apache.iotdb.service.rpc.thrift.TSGetTimeZoneResp;
 import org.apache.iotdb.service.rpc.thrift.TSHandleIdentifier;
 import org.apache.iotdb.service.rpc.thrift.TSIService;
+import org.apache.iotdb.service.rpc.thrift.TSInsertionReq;
 import org.apache.iotdb.service.rpc.thrift.TSOpenSessionReq;
 import org.apache.iotdb.service.rpc.thrift.TSOpenSessionResp;
 import org.apache.iotdb.service.rpc.thrift.TSOperationHandle;
@@ -948,5 +950,23 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
     return properties;
   }
 
+  @Override
+  public TSExecuteStatementResp executeInsertion(TSInsertionReq req) {
+    if (!checkLogin()) {
+      LOGGER.info(INFO_NOT_LOGIN, IoTDBConstant.GLOBAL_DB_NAME);
+      return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, ERROR_NOT_LOGIN);
+    }
+    InsertPlan plan = new InsertPlan();
+    plan.setTime(req.getTimestamp());
+    plan.setDeviceId(req.getDeviceId());
+    plan.setMeasurements(req.getMeasurements().toArray(new String[0]));
+    plan.setValues(req.getValues().toArray(new String[0]));
+    try {
+      return executeUpdateStatement(plan);
+    } catch (Exception e) {
+      LOGGER.info("meet error while executing an insertion into {}", req.getDeviceId(), e);
+      return getTSExecuteStatementResp(TS_StatusCode.ERROR_STATUS, e.getMessage());
+    }
+  }
 }
 
diff --git a/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBPreparedStmtIT.java b/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBPreparedStmtIT.java
new file mode 100644
index 0000000..47c15ec
--- /dev/null
+++ b/iotdb/src/test/java/org/apache/iotdb/db/integration/IoTDBPreparedStmtIT.java
@@ -0,0 +1,186 @@
+/**
+ * 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.db.integration;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.utils.EnvironmentUtils;
+import org.apache.iotdb.jdbc.Config;
+import org.apache.iotdb.jdbc.IoTDBPreparedInsertionStatement;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class IoTDBPreparedStmtIT {
+
+  private static IoTDB daemon;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    EnvironmentUtils.closeStatMonitor();
+    EnvironmentUtils.closeMemControl();
+    daemon = IoTDB.getInstance();
+    daemon.active();
+    EnvironmentUtils.envSetUp();
+    Class.forName(Config.JDBC_DRIVER_NAME);
+    prepareSeries();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    daemon.stop();
+    EnvironmentUtils.cleanEnv();
+  }
+
+  private static void prepareSeries() throws SQLException {
+    Connection connection;
+    connection = DriverManager
+        .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+    try {
+      Statement statement = connection.createStatement();
+
+      statement.execute("SET STORAGE GROUP TO root.device1");
+      statement.execute("SET STORAGE GROUP TO root.device2");
+
+      for (int i = 0; i < 5; i++) {
+        statement.execute(String.format("CREATE TIMESERIES root.device1.sensor%d WITH "
+            + "DATATYPE=DOUBLE,ENCODING=PLAIN", i));
+        statement.execute(String.format("CREATE TIMESERIES root.device2.sensor%d WITH "
+            + "DATATYPE=DOUBLE,ENCODING=PLAIN", i));
+      }
+      // to create processors
+      statement.execute("INSERT INTO root.device1(timestamp,sensor0,sensor1,sensor2,sensor3,"
+          + "sensor4) VALUES (1,1,1,1,1,1)");
+      statement.execute("INSERT INTO root.device2(timestamp,sensor0,sensor1,sensor2,sensor3,"
+          + "sensor4) VALUES (1,1,1,1,1,1)");
+      statement.close();
+    } finally {
+      connection.close();
+    }
+  }
+
+  @Test
+  public void testPreparedInsertion() throws SQLException {
+    Connection connection;
+    connection = DriverManager
+        .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+    IoTDBPreparedInsertionStatement statement = (IoTDBPreparedInsertionStatement) connection.prepareStatement("INSERT");
+
+    try {
+      statement.setDeviceId("root.device1");
+      String[] measurements = new String[5];
+      for (int i = 0; i < 5; i++) {
+        measurements[i] = "sensor" + i;
+      }
+      statement.setMeasurements(Arrays.asList(measurements));
+      String[] values = new String[5];
+      for (int i = 1; i <= 100; i++) {
+        statement.setTimestamp(i);
+        for (int j = 0; j < 5; j ++) {
+          values[j] = String.valueOf(j);
+        }
+        statement.setValues(Arrays.asList(values));
+        statement.execute();
+      }
+      statement.close();
+
+      Statement queryStmt = connection.createStatement();
+      ResultSet resultSet = queryStmt.executeQuery("SELECT * FROM root.device1");
+      int cnt = 0;
+      while (resultSet.next()) {
+        cnt++;
+        assertEquals(cnt, resultSet.getLong(1));
+        for (int i = 0; i < 5; i++) {
+          assertEquals((double) i, resultSet.getDouble(i+2), 0.0001);
+        }
+      }
+      assertEquals(100, cnt);
+      resultSet.close();
+      queryStmt.close();
+    } finally {
+      connection.close();
+    }
+  }
+
+  @Test
+  public void testPreparedInsertionPerf() throws SQLException {
+    Connection connection;
+    connection = DriverManager
+        .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+    long preparedConsumption;
+    long normalConsumption;
+
+    try {
+      IoTDBPreparedInsertionStatement statement = (IoTDBPreparedInsertionStatement) connection.prepareStatement("INSERT");
+      long startTime = System.currentTimeMillis();
+      statement.setDeviceId("root.device1");
+      String[] measurements = new String[5];
+      for (int i = 0; i < 5; i++) {
+        measurements[i] = "sensor" + i;
+      }
+      statement.setMeasurements(Arrays.asList(measurements));
+      String[] values = new String[5];
+      for (int i = 1000000; i <= 2000000; i++) {
+        statement.setTimestamp(i);
+        for (int j = 0; j < 5; j ++) {
+          values[j] = String.valueOf(j);
+        }
+        statement.setValues(Arrays.asList(values));
+        statement.execute();
+      }
+      statement.close();
+      preparedConsumption = System.currentTimeMillis() - startTime;
+
+    } finally {
+      connection.close();
+    }
+
+    connection = DriverManager
+        .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+    try {
+      Statement statement = connection.createStatement();
+      long startTime = System.currentTimeMillis();
+      String insertionTemplate = "INSERT INTO root.device2(timestamp,sensor0,sensor1,sensor2,"
+          + "sensor3,sensor4) VALUES (%d,%d,%d,%d,%d,%d)";
+      Object[] args = new Object[6];
+
+      for (int i = 1000000; i <= 2000000; i++) {
+        args[0] = i;
+        for (int j = 0; j < 5; j ++) {
+          args[j+1] = j;
+        }
+        statement.execute(String.format(insertionTemplate, args));
+      }
+      statement.close();
+      normalConsumption = System.currentTimeMillis() - startTime;
+    } finally {
+      connection.close();
+    }
+    System.out.printf("Prepared statement costs %d, normal statement costs %d \n",
+        preparedConsumption, normalConsumption);
+  }
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
index e94b926..e380f5c 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
@@ -340,7 +340,10 @@ public class IoTDBConnection implements Connection {
 
   @Override
   public PreparedStatement prepareStatement(String sql) throws SQLException {
-    return new IoTDBPrepareStatement(this, client, sessionHandle, sql, zoneId);
+    if (sql.equalsIgnoreCase("INSERT")) {
+      return new IoTDBPreparedInsertionStatement(this, client, sessionHandle, zoneId);
+    }
+    return new IoTDBPreparedStatement(this, client, sessionHandle, sql, zoneId);
   }
 
   @Override
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedInsertionStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedInsertionStatement.java
new file mode 100644
index 0000000..7c7edf8
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedInsertionStatement.java
@@ -0,0 +1,57 @@
+package org.apache.iotdb.jdbc;
+
+import java.sql.SQLException;
+import java.time.ZoneId;
+import java.util.List;
+import org.apache.iotdb.service.rpc.thrift.TSExecuteStatementResp;
+import org.apache.iotdb.service.rpc.thrift.TSIService.Iface;
+import org.apache.iotdb.service.rpc.thrift.TSInsertionReq;
+import org.apache.iotdb.service.rpc.thrift.TS_SessionHandle;
+import org.apache.iotdb.service.rpc.thrift.TS_StatusCode;
+import org.apache.thrift.TException;
+
+public class IoTDBPreparedInsertionStatement extends IoTDBPreparedStatement {
+
+  private long timestamp;
+  private String deviceId;
+  private List<String> measurements;
+  private List<String> values;
+  private TSInsertionReq req = new TSInsertionReq();
+
+  public IoTDBPreparedInsertionStatement(IoTDBConnection connection,
+      Iface client,
+      TS_SessionHandle sessionHandle, ZoneId zoneId) {
+    super(connection, client, sessionHandle, zoneId);
+  }
+
+  @Override
+  public boolean execute() throws SQLException {
+    req.setDeviceId(deviceId);
+    req.setMeasurements(measurements);
+    req.setValues(values);
+    req.setTimestamp(timestamp);
+    try {
+      TSExecuteStatementResp resp = client.executeInsertion(req);
+      return resp.getStatus().getStatusCode() == TS_StatusCode.SUCCESS_STATUS;
+    } catch (TException e) {
+      throw new SQLException(e);
+    }
+  }
+
+  public void setTimestamp(long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public void setDeviceId(String deviceId) {
+    this.deviceId = deviceId;
+  }
+
+  public void setMeasurements(List<String> measurements) {
+    this.measurements = measurements;
+  }
+
+  public void setValues(List<String> values) {
+    this.values = values;
+  }
+
+}
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPrepareStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
similarity index 97%
rename from jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPrepareStatement.java
rename to jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
index dcbf1b9..6d18fd7 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPrepareStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
@@ -49,9 +49,9 @@ import java.util.Map;
 import org.apache.iotdb.service.rpc.thrift.TSIService.Iface;
 import org.apache.iotdb.service.rpc.thrift.TS_SessionHandle;
 
-public class IoTDBPrepareStatement extends IoTDBStatement implements PreparedStatement {
+public class IoTDBPreparedStatement extends IoTDBStatement implements PreparedStatement {
 
-  private final String sql;
+  private String sql;
   private static final String METHOD_NOT_SUPPORTED_STRING = "Method not supported";
 
   /**
@@ -59,7 +59,12 @@ public class IoTDBPrepareStatement extends IoTDBStatement implements PreparedSta
    */
   private final Map<Integer, String> parameters = new HashMap<>();
 
-  public IoTDBPrepareStatement(IoTDBConnection connection, Iface client,
+  public IoTDBPreparedStatement(IoTDBConnection connection, Iface client,
+      TS_SessionHandle sessionHandle, ZoneId zoneId) {
+    super(connection, client, sessionHandle, zoneId);
+  }
+
+  public IoTDBPreparedStatement(IoTDBConnection connection, Iface client,
       TS_SessionHandle sessionHandle, String sql,
       ZoneId zoneId) {
     super(connection, client, sessionHandle, zoneId);
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index 3c4e298..edb2bce 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -61,7 +61,7 @@ public class IoTDBStatement implements Statement {
   private IoTDBConnection connection;
   private int fetchSize = Config.fetchSize;
   private int queryTimeout = 10;
-  private TSIService.Iface client = null;
+  protected TSIService.Iface client = null;
   private TS_SessionHandle sessionHandle = null;
   private TSOperationHandle operationHandle = null;
   private List<String> batchSQLList;
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPrepareStatementTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
similarity index 88%
rename from jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPrepareStatementTest.java
rename to jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
index 1b60ec8..ca9928e 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPrepareStatementTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
@@ -40,7 +40,7 @@ import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-public class IoTDBPrepareStatementTest {
+public class IoTDBPreparedStatementTest {
 
   @Mock
   TSExecuteStatementResp execStatementResp;
@@ -72,7 +72,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void testNonParameterized() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < 24 and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.execute();
 
@@ -88,7 +88,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void unusedArgument() throws SQLException {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < 24 and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setString(1, "123");
     ps.execute();
@@ -98,7 +98,7 @@ public class IoTDBPrepareStatementTest {
   @Test(expected = SQLException.class)
   public void unsetArgument() throws SQLException {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < 24 and time > ?";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.execute();
   }
@@ -107,7 +107,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneIntArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setInt(1, 123);
     ps.execute();
@@ -123,7 +123,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneLongArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setLong(1, 123);
     ps.execute();
@@ -139,7 +139,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneFloatArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setFloat(1, 123.133f);
     ps.execute();
@@ -155,7 +155,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneDoubleArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setDouble(1, 123.456);
     ps.execute();
@@ -171,7 +171,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneBooleanArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setBoolean(1, false);
     ps.execute();
@@ -187,7 +187,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneStringArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE temperature < ? and time > 2017-11-1 0:13:00";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setString(1, "abcde");
     ps.execute();
@@ -203,7 +203,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneTimeLongArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE time > ?";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setLong(1, 1233);
     ps.execute();
@@ -218,7 +218,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void oneTimeTimestampArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE time > ?";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setTimestamp(1, Timestamp.valueOf("2017-11-01 00:13:00"));
     ps.execute();
@@ -234,7 +234,7 @@ public class IoTDBPrepareStatementTest {
   @Test
   public void escapingOfStringArgument() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE status = '134' and temperature = ?";
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setLong(1, 1333);
     ps.execute();
@@ -252,7 +252,7 @@ public class IoTDBPrepareStatementTest {
   public void pastingIntoEscapedQuery() throws Exception {
     String sql = "SELECT status, temperature FROM root.ln.wf01.wt01 WHERE status = '\\044e' || temperature = ?";
 
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setDouble(1, -1323.0);
     ps.execute();
@@ -270,7 +270,7 @@ public class IoTDBPrepareStatementTest {
   public void testInsertStatement1() throws Exception {
     String sql = "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
 
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setLong(1, 12324);
     ps.setBoolean(2, false);
@@ -294,7 +294,7 @@ public class IoTDBPrepareStatementTest {
   public void testInsertStatement2() throws Exception {
     String sql = "INSERT INTO root.ln.wf01.wt01(timestamp,a,b,c,d,e,f) VALUES(?,?,?,?,?,?,?)";
 
-    IoTDBPrepareStatement ps = new IoTDBPrepareStatement(connection, client, sessHandle, sql,
+    IoTDBPreparedStatement ps = new IoTDBPreparedStatement(connection, client, sessHandle, sql,
         zoneId);
     ps.setTimestamp(1, Timestamp.valueOf("2017-11-01 00:13:00"));
     ps.setBoolean(2, false);
diff --git a/service-rpc/src/main/thrift/rpc.thrift b/service-rpc/src/main/thrift/rpc.thrift
index 6e857e8..c4ed4e2 100644
--- a/service-rpc/src/main/thrift/rpc.thrift
+++ b/service-rpc/src/main/thrift/rpc.thrift
@@ -248,6 +248,13 @@ struct TSSetTimeZoneResp {
     1: required TS_Status status
 }
 
+struct TSInsertionReq {
+    1: required string deviceId
+    2: required list<string> measurements
+    3: required list<string> values
+    4: required i64 timestamp
+}
+
 struct ServerProperties {
 	1: required string version;
 	2: required list<string> supportedTimeAggregationOperations;
@@ -279,4 +286,6 @@ service TSIService {
 	TSSetTimeZoneResp setTimeZone(1:TSSetTimeZoneReq req);
 	
 	ServerProperties getProperties();
+
+	TSExecuteStatementResp executeInsertion(1:TSInsertionReq req);
 	}