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

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


The following commit(s) were added to refs/heads/master by this push:
     new fb08f7b  [IOTDB-1808] Compatibility of Apache IoTDB with InfluxDB - 
Query Func (#5104)
fb08f7b is described below

commit fb08f7bc277925ca5b8e26978e714556b90e415c
Author: Xieqijun <[email protected]>
AuthorDate: Sun Mar 20 22:45:56 2022 +0800

    [IOTDB-1808] Compatibility of Apache IoTDB with InfluxDB - Query Func 
(#5104)
    
    Co-authored-by: Timcross-WEI <[email protected]>
    Co-authored-by: Steve Yurong Su <[email protected]>
---
 .../apache/iotdb/db/qp/sql/InfluxDBSqlParser.g4    |   2 +
 .../org/apache/iotdb/influxdb/IoTDBInfluxDB.java   |   4 +-
 .../iotdb/influxdb/example/InfluxDBExample.java    |  38 +-
 .../protocol/impl/IoTDBInfluxDBService.java        |  22 +-
 .../iotdb/influxdb/session/InfluxDBSession.java    |  29 +
 .../influxdb/integration/IoTDBInfluxDBIT.java      |  77 +-
 .../{InfluxDBConstant.java => InfluxConstant.java} |   2 +-
 .../influxdb/constant/InfluxSQLConstant.java       |   7 +
 .../protocol/influxdb/function/InfluxFunction.java |  58 ++
 .../influxdb/function/InfluxFunctionFactory.java   |  62 ++
 .../InfluxFunctionValue.java}                      |  28 +-
 .../aggregator/InfluxAggregator.java}              |  17 +-
 .../function/aggregator/InfluxCountFunction.java   |  59 ++
 .../function/aggregator/InfluxMeanFunction.java    |  72 ++
 .../function/aggregator/InfluxMedianFunction.java  |  75 ++
 .../function/aggregator/InfluxModeFunction.java    |  88 ++
 .../function/aggregator/InfluxSpreadFunction.java  |  88 ++
 .../function/aggregator/InfluxStddevFunction.java  |  68 ++
 .../function/aggregator/InfluxSumFunction.java     |  68 ++
 .../function/selector/InfluxFirstFunction.java     |  73 ++
 .../function/selector/InfluxLastFunction.java      |  73 ++
 .../function/selector/InfluxMaxFunction.java       | 102 +++
 .../function/selector/InfluxMinFunction.java       | 102 +++
 .../influxdb/function/selector/InfluxSelector.java |  57 ++
 .../db/protocol/influxdb/handler/QueryHandler.java | 956 +++++++++++++++++++++
 .../influxdb/meta/InfluxDBMetaManager.java         |   8 +-
 .../influxdb/operator/InfluxSelectComponent.java   |   8 +-
 .../CommonUtils.java}                              |  24 +-
 .../InfluxDBConstant.java => util/FieldUtils.java} |  33 +-
 .../db/protocol/influxdb/util/FilterUtils.java     |  83 ++
 .../protocol/influxdb/util/QueryResultUtils.java   | 291 +++++++
 .../db/protocol/influxdb/util/StringUtils.java     |  97 +++
 .../db/query/dataset/AlignByDeviceDataSet.java     |   4 +
 .../service/thrift/impl/InfluxDBServiceImpl.java   |  14 +
 .../java/org/apache/iotdb/db/utils/MathUtils.java  |  51 ++
 thrift-influxdb/src/main/thrift/influxdb.thrift    |  19 +
 36 files changed, 2814 insertions(+), 45 deletions(-)

diff --git 
a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/InfluxDBSqlParser.g4 
b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/InfluxDBSqlParser.g4
index 2df0017..316c4db 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/InfluxDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/InfluxDBSqlParser.g4
@@ -74,6 +74,8 @@ nodeName
     | ID
     | QUTOED_ID
     | QUTOED_ID_IN_NODE_NAME
+    | LAST
+    | COUNT
     ;
 
 // Identifier
diff --git 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/IoTDBInfluxDB.java 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/IoTDBInfluxDB.java
index 8b8e153..54d5065 100644
--- 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/IoTDBInfluxDB.java
+++ 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/IoTDBInfluxDB.java
@@ -187,8 +187,8 @@ public class IoTDBInfluxDB implements InfluxDB {
   }
 
   @Override
-  public QueryResult query(final Query query) {
-    throw new 
UnsupportedOperationException(InfluxDBConstant.METHOD_NOT_SUPPORTED);
+  public QueryResult query(final Query queryReq) {
+    return influxDBService.query(queryReq);
   }
 
   @Override
diff --git 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/example/InfluxDBExample.java
 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/example/InfluxDBExample.java
index 734bf07..995948a 100644
--- 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/example/InfluxDBExample.java
+++ 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/example/InfluxDBExample.java
@@ -23,6 +23,8 @@ import org.apache.iotdb.influxdb.IoTDBInfluxDBFactory;
 
 import org.influxdb.InfluxDB;
 import org.influxdb.dto.Point;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -37,6 +39,7 @@ public class InfluxDBExample {
     influxDB.createDatabase("database");
     influxDB.setDatabase("database");
     insertData();
+    queryData();
     influxDB.close();
   }
 
@@ -61,7 +64,7 @@ public class InfluxDBExample {
     tags.put("name", "xie");
     tags.put("sex", "m");
     tags.put("province", "anhui");
-    fields.put("score", 99);
+    fields.put("score", 99.0);
     fields.put("country", "china");
     builder.tag(tags);
     builder.fields(fields);
@@ -69,4 +72,37 @@ public class InfluxDBExample {
     point = builder.build();
     influxDB.write(point);
   }
+
+  private static void queryData() {
+    Query query;
+    QueryResult result;
+
+    //     the selector query is parallel to the field value
+    query =
+        new Query(
+            "select * from student where (name=\"xie\" and sex=\"m\")or 
time<now()-7d", "database");
+    result = influxDB.query(query);
+    System.out.println("query1 result:" + 
result.getResults().get(0).getSeries().get(0).toString());
+
+    //     the selector query is parallel to the field value
+    query = new Query("select * from student ", "database");
+    result = influxDB.query(query);
+    System.out.println("query2 result:" + 
result.getResults().get(0).getSeries().get(0).toString());
+
+    // use iotdb built-in func
+    query =
+        new Query(
+            "select 
max(score),min(score),sum(score),count(score),first(score),last(score) from 
student ",
+            "database");
+    result = influxDB.query(query);
+    System.out.println("query3 result:" + 
result.getResults().get(0).getSeries().get(0).toString());
+
+    // aggregate query and selector query are parallel
+    query =
+        new Query(
+            "select 
count(score),first(score),last(country),max(score),mean(score),median(score),min(score),mode(score),spread(score),stddev(score),sum(score)
 from student where (name=\"xie\" and sex=\"m\")or score<99",
+            "database");
+    result = influxDB.query(query);
+    System.out.println("query4 result:" + 
result.getResults().get(0).getSeries().get(0).toString());
+  }
 }
diff --git 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/protocol/impl/IoTDBInfluxDBService.java
 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/protocol/impl/IoTDBInfluxDBService.java
index a701f4a..73944fc 100644
--- 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/protocol/impl/IoTDBInfluxDBService.java
+++ 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/protocol/impl/IoTDBInfluxDBService.java
@@ -21,11 +21,14 @@ package org.apache.iotdb.influxdb.protocol.impl;
 
 import org.apache.iotdb.influxdb.session.InfluxDBSession;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSCreateDatabaseReq;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSWritePointsReq;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 
 import org.influxdb.InfluxDBException;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
 
 public class IoTDBInfluxDBService {
 
@@ -54,10 +57,11 @@ public class IoTDBInfluxDBService {
     } else {
       tsWritePointsReq.setDatabase(database);
     }
-    tsWritePointsReq.setRetentionPolicy(retentionPolicy);
-    tsWritePointsReq.setPrecision(precision);
-    tsWritePointsReq.setConsistency(consistency);
-    tsWritePointsReq.setLineProtocol(lineProtocol);
+    tsWritePointsReq
+        .setRetentionPolicy(retentionPolicy)
+        .setPrecision(precision)
+        .setConsistency(consistency)
+        .setLineProtocol(lineProtocol);
     try {
       influxDBSession.writePoints(tsWritePointsReq);
     } catch (StatementExecutionException | IoTDBConnectionException e) {
@@ -79,6 +83,16 @@ public class IoTDBInfluxDBService {
     }
   }
 
+  public QueryResult query(Query queryReq) {
+    TSQueryReq tsQueryReq = new TSQueryReq();
+    
tsQueryReq.setDatabase(queryReq.getDatabase()).setCommand(queryReq.getCommand());
+    try {
+      return influxDBSession.query(tsQueryReq);
+    } catch (StatementExecutionException | IoTDBConnectionException e) {
+      throw new InfluxDBException(e.getMessage());
+    }
+  }
+
   public void close() {
     influxDBSession.close();
   }
diff --git 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/session/InfluxDBSession.java
 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/session/InfluxDBSession.java
index 348ccb9..ba7a59c 100644
--- 
a/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/session/InfluxDBSession.java
+++ 
b/influxdb-protocol/src/main/java/org/apache/iotdb/influxdb/session/InfluxDBSession.java
@@ -26,6 +26,8 @@ import 
org.apache.iotdb.protocol.influxdb.rpc.thrift.TSCloseSessionReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSCreateDatabaseReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSOpenSessionReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSOpenSessionResp;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryReq;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryResultRsp;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSWritePointsReq;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.RpcTransportFactory;
@@ -33,12 +35,14 @@ import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.StatementExecutionException;
 import org.apache.iotdb.session.Config;
 
+import com.google.gson.Gson;
 import org.apache.thrift.TException;
 import org.apache.thrift.protocol.TBinaryProtocol;
 import org.apache.thrift.protocol.TCompactProtocol;
 import org.apache.thrift.transport.TTransport;
 import org.apache.thrift.transport.TTransportException;
 import org.influxdb.InfluxDBException;
+import org.influxdb.dto.QueryResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -172,6 +176,31 @@ public class InfluxDBSession {
     }
   }
 
+  public QueryResult query(TSQueryReq request)
+      throws StatementExecutionException, IoTDBConnectionException {
+    request.setSessionId(sessionId);
+    try {
+      TSQueryResultRsp tsQueryResultRsp = client.query(request);
+      RpcUtils.verifySuccess(tsQueryResultRsp.status);
+      return new Gson().fromJson(tsQueryResultRsp.ResultJsonString, 
QueryResult.class);
+    } catch (TException e) {
+      e.printStackTrace();
+      logger.error(e.getMessage());
+      if (reconnect()) {
+        try {
+          request.setSessionId(sessionId);
+          TSQueryResultRsp tsQueryResultRsp = client.query(request);
+          RpcUtils.verifySuccess(tsQueryResultRsp.status);
+          return new Gson().fromJson(tsQueryResultRsp.ResultJsonString, 
QueryResult.class);
+        } catch (TException e1) {
+          throw new IoTDBConnectionException(e1);
+        }
+      } else {
+        throw new IoTDBConnectionException(MSG_RECONNECTION_FAIL);
+      }
+    }
+  }
+
   public void createDatabase(TSCreateDatabaseReq request)
       throws StatementExecutionException, IoTDBConnectionException {
     request.setSessionId(sessionId);
diff --git 
a/influxdb-protocol/src/test/java/org/apache/iotdb/influxdb/integration/IoTDBInfluxDBIT.java
 
b/influxdb-protocol/src/test/java/org/apache/iotdb/influxdb/integration/IoTDBInfluxDBIT.java
index 767962d..acf7d6e 100644
--- 
a/influxdb-protocol/src/test/java/org/apache/iotdb/influxdb/integration/IoTDBInfluxDBIT.java
+++ 
b/influxdb-protocol/src/test/java/org/apache/iotdb/influxdb/integration/IoTDBInfluxDBIT.java
@@ -24,6 +24,8 @@ import org.apache.iotdb.session.Session;
 import org.influxdb.InfluxDB;
 import org.influxdb.InfluxDBException;
 import org.influxdb.dto.Point;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
@@ -64,40 +66,30 @@ public class IoTDBInfluxDBIT {
   }
 
   private void insertData() {
+    // insert the build parameter to construct the influxdb
     Point.Builder builder = Point.measurement("student");
     Map<String, String> tags = new HashMap<>();
     Map<String, Object> fields = new HashMap<>();
-    tags.put("name", "A");
-    tags.put("phone", "B");
-    tags.put("sex", "C");
-    fields.put("score", 99);
+    tags.put("name", "xie");
+    tags.put("sex", "m");
+    fields.put("score", 87);
     fields.put("tel", "110");
     fields.put("country", "china");
     builder.tag(tags);
     builder.fields(fields);
     builder.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
     Point point = builder.build();
+    // after the build construction is completed, start writing
     influxDB.write(point);
 
     builder = Point.measurement("student");
     tags = new HashMap<>();
     fields = new HashMap<>();
-    tags.put("address", "D");
-    fields.put("score", 98);
-    builder.tag(tags);
-    builder.fields(fields);
-    builder.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
-    point = builder.build();
-    influxDB.write(point);
-
-    builder = Point.measurement("student");
-    tags = new HashMap<>();
-    fields = new HashMap<>();
-    tags.put("address", "D");
-    tags.put("name", "A");
-    tags.put("phone", "B");
-    tags.put("sex", "C");
-    fields.put("score", 97);
+    tags.put("name", "xie");
+    tags.put("sex", "m");
+    tags.put("province", "anhui");
+    fields.put("score", 99);
+    fields.put("country", "china");
     builder.tag(tags);
     builder.fields(fields);
     builder.time(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
@@ -162,4 +154,49 @@ public class IoTDBInfluxDBIT {
   public void testConnectAuthFailed() {
     InfluxDB influxDB = IoTDBInfluxDBFactory.connect(host, port, "error", 
"error");
   }
+
+  @Test
+  public void testCommonQueryColumn() {
+    Query query =
+        new Query(
+            "select * from student where (name=\"xie\" and sex=\"m\")or 
time<now()-7d", "database");
+    QueryResult result = influxDB.query(query);
+    QueryResult.Series series = result.getResults().get(0).getSeries().get(0);
+
+    String[] retArray = new String[] {"time", "name", "sex", "province", 
"country", "score", "tel"};
+    for (int i = 0; i < series.getColumns().size(); i++) {
+      assertEquals(retArray[i], series.getColumns().get(i));
+    }
+  }
+
+  @Test
+  public void testFuncWithoutFilter() {
+    Query query =
+        new Query(
+            "select 
max(score),min(score),sum(score),count(score),spread(score),mean(score),first(score),last(score)
 from student ",
+            "database");
+    QueryResult result = influxDB.query(query);
+    QueryResult.Series series = result.getResults().get(0).getSeries().get(0);
+
+    Object[] retArray = new Object[] {0, 99.0, 87.0, 186, 2, 12.0, 93, 87, 99};
+    for (int i = 0; i < series.getColumns().size(); i++) {
+      assertEquals(retArray[i], series.getValues().get(0).get(i));
+    }
+  }
+
+  @Test
+  public void testFunc() {
+    Query query =
+        new Query(
+            "select 
count(score),first(score),last(country),max(score),mean(score),median(score),min(score),mode(score),spread(score),stddev(score),sum(score)
 from student where (name=\"xie\" and sex=\"m\")or score<99",
+            "database");
+    QueryResult result = influxDB.query(query);
+    QueryResult.Series series = result.getResults().get(0).getSeries().get(0);
+
+    Object[] retArray =
+        new Object[] {0, 2, 87, "china", 99.0, 93.0, 93.0, 87.0, 87, 12.0, 
6.0, 186.0};
+    for (int i = 0; i < series.getColumns().size(); i++) {
+      assertEquals(retArray[i], series.getValues().get(0).get(i));
+    }
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxConstant.java
similarity index 96%
copy from 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
copy to 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxConstant.java
index 6b59698..3850201 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxConstant.java
@@ -18,7 +18,7 @@
  */
 package org.apache.iotdb.db.protocol.influxdb.constant;
 
-public class InfluxDBConstant {
+public class InfluxConstant {
 
   public static final String PLACE_HOLDER = "PH";
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxSQLConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxSQLConstant.java
index cbc77b7..3232778 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxSQLConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxSQLConstant.java
@@ -27,6 +27,7 @@ import java.util.Set;
 
 /** this class contains several constants used in SQL. */
 public class InfluxSQLConstant extends SQLConstant {
+  public static final String STAR = "*";
 
   public static final String MAX = "max";
   public static final String MIN = "min";
@@ -41,6 +42,8 @@ public class InfluxSQLConstant extends SQLConstant {
           Arrays.asList(MIN, MAX, FIRST, LAST, MEAN, COUNT, MEDIAN, MODE, 
SPREAD, STDDEV, SUM));
   private static final Set<String> NATIVE_SELECTOR_FUNCTION_NAMES =
       new HashSet<>(Arrays.asList(MIN, MAX, FIRST, LAST));
+  private static final Set<String> ONLY_TRAVERSE_FUNCTION_NAMES =
+      new HashSet<>(Arrays.asList(MEDIAN, MODE, SPREAD, STDDEV));
 
   public InfluxSQLConstant() throws InstantiationException {
     // forbidding instantiation
@@ -54,4 +57,8 @@ public class InfluxSQLConstant extends SQLConstant {
   public static Set<String> getNativeSelectorFunctionNames() {
     return NATIVE_SELECTOR_FUNCTION_NAMES;
   }
+
+  public static Set<String> getOnlyTraverseFunctionNames() {
+    return ONLY_TRAVERSE_FUNCTION_NAMES;
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunction.java
new file mode 100644
index 0000000..f687378
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunction.java
@@ -0,0 +1,58 @@
+/*
+ * 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.protocol.influxdb.function;
+
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.db.query.expression.unary.TimeSeriesOperand;
+
+import java.util.List;
+
+public abstract class InfluxFunction {
+
+  // contain possible parameters
+  private List<Expression> expressionList;
+
+  public InfluxFunction(List<Expression> expressionList) {
+    this.expressionList = expressionList;
+  }
+
+  public InfluxFunction() {}
+
+  public List<Expression> getExpressions() {
+    return this.expressionList;
+  }
+
+  public String getParmaName() {
+    if (expressionList == null) {
+      throw new IllegalArgumentException("not support param");
+    }
+    TimeSeriesOperand parmaExpression = (TimeSeriesOperand) 
expressionList.get(0);
+    return parmaExpression.getPath().getFullPath();
+  }
+
+  public abstract String getFunctionName();
+
+  // calculate result by brute force
+  public abstract InfluxFunctionValue calculateBruteForce();
+
+  // calculate result by iotdb func
+  public abstract InfluxFunctionValue calculateByIoTDBFunc();
+
+  public abstract void updateValueIoTDBFunc(InfluxFunctionValue... 
functionValues);
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionFactory.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionFactory.java
new file mode 100644
index 0000000..505a0b4
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.protocol.influxdb.function;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.aggregator.*;
+import 
org.apache.iotdb.db.protocol.influxdb.function.selector.InfluxFirstFunction;
+import 
org.apache.iotdb.db.protocol.influxdb.function.selector.InfluxLastFunction;
+import 
org.apache.iotdb.db.protocol.influxdb.function.selector.InfluxMaxFunction;
+import 
org.apache.iotdb.db.protocol.influxdb.function.selector.InfluxMinFunction;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxFunctionFactory {
+
+  public static InfluxFunction generateFunction(
+      String functionName, List<Expression> expressionList) {
+    switch (functionName) {
+      case InfluxSQLConstant.MAX:
+        return new InfluxMaxFunction(expressionList);
+      case InfluxSQLConstant.MIN:
+        return new InfluxMinFunction(expressionList);
+      case InfluxSQLConstant.LAST:
+        return new InfluxLastFunction(expressionList);
+      case InfluxSQLConstant.FIRST:
+        return new InfluxFirstFunction(expressionList);
+      case InfluxSQLConstant.COUNT:
+        return new InfluxCountFunction(expressionList);
+      case InfluxSQLConstant.MEAN:
+        return new InfluxMeanFunction(expressionList);
+      case InfluxSQLConstant.MEDIAN:
+        return new InfluxMedianFunction(expressionList);
+      case InfluxSQLConstant.MODE:
+        return new InfluxModeFunction(expressionList);
+      case InfluxSQLConstant.SPREAD:
+        return new InfluxSpreadFunction(expressionList);
+      case InfluxSQLConstant.STDDEV:
+        return new InfluxStddevFunction(expressionList);
+      case InfluxSQLConstant.SUM:
+        return new InfluxSumFunction(expressionList);
+      default:
+        throw new IllegalArgumentException("not support aggregation name:" + 
functionName);
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionValue.java
similarity index 60%
copy from 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
copy to 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionValue.java
index 6b59698..104988b 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/InfluxFunctionValue.java
@@ -16,9 +16,31 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.protocol.influxdb.constant;
+package org.apache.iotdb.db.protocol.influxdb.function;
 
-public class InfluxDBConstant {
+public class InfluxFunctionValue {
 
-  public static final String PLACE_HOLDER = "PH";
+  private Object value;
+  private Long timestamp;
+
+  public InfluxFunctionValue(Object value, Long timestamp) {
+    this.value = value;
+    this.timestamp = timestamp;
+  }
+
+  public Object getValue() {
+    return value;
+  }
+
+  public void setValue(Object value) {
+    this.value = value;
+  }
+
+  public Long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(Long timestamp) {
+    this.timestamp = timestamp;
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxAggregator.java
similarity index 60%
copy from 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
copy to 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxAggregator.java
index 6b59698..5d82ad9 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxAggregator.java
@@ -16,9 +16,20 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.protocol.influxdb.constant;
 
-public class InfluxDBConstant {
+package org.apache.iotdb.db.protocol.influxdb.function.aggregator;
 
-  public static final String PLACE_HOLDER = "PH";
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunction;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public abstract class InfluxAggregator extends InfluxFunction {
+
+  public InfluxAggregator(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  public abstract void updateValueBruteForce(InfluxFunctionValue 
functionValue);
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxCountFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxCountFunction.java
new file mode 100644
index 0000000..f6acb42
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxCountFunction.java
@@ -0,0 +1,59 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxCountFunction extends InfluxAggregator {
+  private int countNum = 0;
+
+  public InfluxCountFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(this.countNum, 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return calculateBruteForce();
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.COUNT;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    this.countNum++;
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    this.countNum += (long) functionValues[0].getValue();
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMeanFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMeanFunction.java
new file mode 100644
index 0000000..8a5a0c6
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMeanFunction.java
@@ -0,0 +1,72 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.db.utils.MathUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InfluxMeanFunction extends InfluxAggregator {
+  private final List<Double> numbers = new ArrayList<>();
+  long sum = 0;
+  long count = 0;
+
+  public InfluxMeanFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(numbers.size() == 0 ? numbers : 
MathUtils.mean(numbers), 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return new InfluxFunctionValue(count != 0 ? sum / count : null, count != 0 
? 0L : null);
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.MEAN;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    if (value instanceof Number) {
+      numbers.add(((Number) value).doubleValue());
+    } else {
+      throw new IllegalArgumentException("mean is not a valid type");
+    }
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (functionValues.length == 1) {
+      count += (long) functionValues[0].getValue();
+    } else if (functionValues.length == 2) {
+      sum += (long) functionValues[1].getValue();
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMedianFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMedianFunction.java
new file mode 100644
index 0000000..33d919a
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxMedianFunction.java
@@ -0,0 +1,75 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class InfluxMedianFunction extends InfluxAggregator {
+  private final List<Double> numbers = new ArrayList<>();
+
+  public InfluxMedianFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    Collections.sort(numbers);
+    int len = numbers.size();
+    if (len > 0) {
+      if (len % 2 == 0) {
+        return new InfluxFunctionValue((numbers.get(len / 2) + numbers.get(len 
/ 2 - 1)) / 2, 0L);
+      } else {
+        return new InfluxFunctionValue(numbers.get(len / 2), 0L);
+      }
+    }
+    return new InfluxFunctionValue(null, null);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.MEDIAN;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    if (value instanceof Number) {
+      numbers.add(((Number) value).doubleValue());
+    } else {
+      throw new IllegalArgumentException("not support this type");
+    }
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxModeFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxModeFunction.java
new file mode 100644
index 0000000..4850104
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxModeFunction.java
@@ -0,0 +1,88 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class InfluxModeFunction extends InfluxAggregator {
+  private final Map<Object, Integer> valueOrders = new HashMap<>();
+  private final Map<Object, Long> valueLastTimestamp = new HashMap<>();
+  private int maxNumber = 0;
+  private Object maxObject = null;
+
+  public InfluxModeFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(maxObject, 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.MODE;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    Long timestamp = functionValue.getTimestamp();
+    // update new data
+    if (!valueOrders.containsKey(value)) {
+      valueOrders.put(value, 1);
+      valueLastTimestamp.put(value, timestamp);
+    } else {
+      valueOrders.put(value, valueOrders.get(value) + 1);
+      if (timestamp < valueLastTimestamp.get(value)) {
+        valueLastTimestamp.put(value, timestamp);
+      }
+    }
+    // Judge whether the new data meets the conditions
+    if (maxObject == null) {
+      maxObject = value;
+      maxNumber = 1;
+    } else {
+      if (valueOrders.get(value) > maxNumber) {
+        maxNumber = valueOrders.get(value);
+        maxObject = value;
+      } else if (valueOrders.get(value) == maxNumber
+          && timestamp < valueLastTimestamp.get(maxObject)) {
+        maxObject = value;
+      }
+    }
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSpreadFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSpreadFunction.java
new file mode 100644
index 0000000..b76ac49
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSpreadFunction.java
@@ -0,0 +1,88 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxSpreadFunction extends InfluxAggregator {
+  private Double maxNum = null;
+  private Double minNum = null;
+
+  public InfluxSpreadFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(maxNum - minNum, 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    if (maxNum == null || minNum == null) {
+      return new InfluxFunctionValue(null, null);
+    }
+    return new InfluxFunctionValue(maxNum - minNum, 0L);
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.SPREAD;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    if (!(value instanceof Number)) {
+      throw new IllegalArgumentException("not support this type");
+    }
+
+    double tmpValue = ((Number) value).doubleValue();
+    if (maxNum == null || tmpValue > maxNum) {
+      maxNum = tmpValue;
+    }
+    if (minNum == null || tmpValue < minNum) {
+      minNum = tmpValue;
+    }
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (functionValues.length == 1) {
+      double tmpValue = ((Number) functionValues[0].getValue()).doubleValue();
+      if (maxNum == null) {
+        maxNum = tmpValue;
+      } else if (tmpValue > maxNum) {
+        maxNum = tmpValue;
+      }
+    } else if (functionValues.length == 2) {
+      double tmpValue = ((Number) functionValues[1].getValue()).doubleValue();
+      if (minNum == null) {
+        minNum = tmpValue;
+      } else if (tmpValue < minNum) {
+        minNum = tmpValue;
+      }
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxStddevFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxStddevFunction.java
new file mode 100644
index 0000000..614f402
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxStddevFunction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.db.utils.MathUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InfluxStddevFunction extends InfluxAggregator {
+  private final List<Double> numbers = new ArrayList<>();
+
+  public InfluxStddevFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(
+        numbers.size() == 0 ? numbers : MathUtils.popStdDev(numbers), 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.STDDEV;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    if (!(value instanceof Number)) {
+      throw new IllegalArgumentException("not support this type");
+    }
+
+    double tmpValue = ((Number) value).doubleValue();
+    numbers.add(tmpValue);
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSumFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSumFunction.java
new file mode 100644
index 0000000..f175a1a
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/aggregator/InfluxSumFunction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.protocol.influxdb.function.aggregator;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.db.utils.MathUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class InfluxSumFunction extends InfluxAggregator {
+  private final List<Double> numbers = new ArrayList<>();
+  private long sum = 0;
+
+  public InfluxSumFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(numbers.size() == 0 ? numbers : 
MathUtils.sum(numbers), 0L);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return new InfluxFunctionValue(sum, 0L);
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.SUM;
+  }
+
+  @Override
+  public void updateValueBruteForce(InfluxFunctionValue functionValue) {
+    Object value = functionValue.getValue();
+    if (!(value instanceof Number)) {
+      throw new IllegalArgumentException("not support this type");
+    }
+
+    double tmpValue = ((Number) value).doubleValue();
+    numbers.add(tmpValue);
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    sum += (double) functionValues[0].getValue();
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxFirstFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxFirstFunction.java
new file mode 100644
index 0000000..bba41c0
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxFirstFunction.java
@@ -0,0 +1,73 @@
+/*
+ * 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.protocol.influxdb.function.selector;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxFirstFunction extends InfluxSelector {
+  private Object value;
+
+  public InfluxFirstFunction(List<Expression> expressionList) {
+    super(expressionList);
+    this.setTimestamp(Long.MAX_VALUE);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(value, this.getTimestamp());
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return calculateBruteForce();
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (value == null && getTimestamp() == null) {
+      value = functionValues[0].getValue();
+      setTimestamp(functionValues[0].getTimestamp());
+    } else if (getTimestamp() < functionValues[0].getTimestamp()) {
+      value = functionValues[0].getValue();
+      setTimestamp(functionValues[0].getTimestamp());
+    }
+  }
+
+  @Override
+  public void updateValueAndRelateValues(
+      InfluxFunctionValue functionValue, List<Object> relatedValues) {
+    Object value = functionValue.getValue();
+    Long timestamp = functionValue.getTimestamp();
+    if (timestamp <= this.getTimestamp()) {
+      this.value = value;
+      this.setTimestamp(timestamp);
+      this.setRelatedValues(relatedValues);
+    }
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.FIRST;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxLastFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxLastFunction.java
new file mode 100644
index 0000000..2674e0e
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxLastFunction.java
@@ -0,0 +1,73 @@
+/*
+ * 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.protocol.influxdb.function.selector;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxLastFunction extends InfluxSelector {
+  private Object value;
+
+  public InfluxLastFunction(List<Expression> expressionList) {
+    super(expressionList);
+    this.setTimestamp(Long.MIN_VALUE);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    return new InfluxFunctionValue(value, this.getTimestamp());
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return calculateBruteForce();
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (value == null && getTimestamp() == null) {
+      value = functionValues[0].getValue();
+      setTimestamp(functionValues[0].getTimestamp());
+    } else if (getTimestamp() > functionValues[0].getTimestamp()) {
+      value = functionValues[0].getValue();
+      setTimestamp(functionValues[0].getTimestamp());
+    }
+  }
+
+  @Override
+  public void updateValueAndRelateValues(
+      InfluxFunctionValue functionValue, List<Object> relatedValues) {
+    Object value = functionValue.getValue();
+    Long timestamp = functionValue.getTimestamp();
+    if (timestamp >= this.getTimestamp()) {
+      this.value = value;
+      this.setTimestamp(timestamp);
+      this.setRelatedValues(relatedValues);
+    }
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.LAST;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMaxFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMaxFunction.java
new file mode 100644
index 0000000..448955f
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMaxFunction.java
@@ -0,0 +1,102 @@
+/*
+ * 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.protocol.influxdb.function.selector;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxMaxFunction extends InfluxSelector {
+  private Double doubleValue = Double.MIN_VALUE;
+  private String stringValue = null;
+  private boolean isNumber = false;
+  private boolean isString = false;
+
+  private Double maxValue = null;
+
+  public InfluxMaxFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    if (!isString && !isNumber) {
+      return new InfluxFunctionValue(null, null);
+    } else if (isString) {
+      return new InfluxFunctionValue(stringValue, this.getTimestamp());
+    } else {
+      return new InfluxFunctionValue(doubleValue, this.getTimestamp());
+    }
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return new InfluxFunctionValue(maxValue, maxValue == null ? null : 0L);
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (functionValues[0].getValue() instanceof Number) {
+      double tmpValue = ((Number) functionValues[0].getValue()).doubleValue();
+      if (maxValue == null) {
+        maxValue = tmpValue;
+      } else if (tmpValue > maxValue) {
+        maxValue = tmpValue;
+      }
+    }
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.MAX;
+  }
+
+  @Override
+  public void updateValueAndRelateValues(
+      InfluxFunctionValue functionValue, List<Object> relatedValues) {
+    Object value = functionValue.getValue();
+    Long timestamp = functionValue.getTimestamp();
+    if (value instanceof Number) {
+      if (!isNumber) {
+        isNumber = true;
+      }
+      double tmpValue = ((Number) value).doubleValue();
+      if (tmpValue >= this.doubleValue) {
+        doubleValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      }
+    } else if (value instanceof String) {
+      String tmpValue = (String) value;
+      if (!isString) {
+        isString = true;
+        stringValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      } else if (tmpValue.compareTo(this.stringValue) >= 0) {
+        stringValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      }
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMinFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMinFunction.java
new file mode 100644
index 0000000..073a640
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxMinFunction.java
@@ -0,0 +1,102 @@
+/*
+ * 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.protocol.influxdb.function.selector;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public class InfluxMinFunction extends InfluxSelector {
+  private Double doubleValue = Double.MAX_VALUE;
+  private String stringValue = null;
+  private boolean isNumber = false;
+  private boolean isString = false;
+
+  private Double minValue = null;
+
+  public InfluxMinFunction(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  @Override
+  public InfluxFunctionValue calculateBruteForce() {
+    if (!isString && !isNumber) {
+      return new InfluxFunctionValue(null, null);
+    } else if (isString) {
+      return new InfluxFunctionValue(stringValue, this.getTimestamp());
+    } else {
+      return new InfluxFunctionValue(doubleValue, this.getTimestamp());
+    }
+  }
+
+  @Override
+  public InfluxFunctionValue calculateByIoTDBFunc() {
+    return new InfluxFunctionValue(minValue, minValue == null ? null : 0L);
+  }
+
+  @Override
+  public void updateValueIoTDBFunc(InfluxFunctionValue... functionValues) {
+    if (functionValues[0].getValue() instanceof Number) {
+      double tmpValue = ((Number) functionValues[0].getValue()).doubleValue();
+      if (minValue == null) {
+        minValue = tmpValue;
+      } else if (tmpValue < minValue) {
+        minValue = tmpValue;
+      }
+    }
+  }
+
+  @Override
+  public String getFunctionName() {
+    return InfluxSQLConstant.MIN;
+  }
+
+  @Override
+  public void updateValueAndRelateValues(
+      InfluxFunctionValue functionValue, List<Object> relatedValues) {
+    Object value = functionValue.getValue();
+    Long timestamp = functionValue.getTimestamp();
+    if (value instanceof Number) {
+      if (!isNumber) {
+        isNumber = true;
+      }
+      double tmpValue = ((Number) value).doubleValue();
+      if (tmpValue <= this.doubleValue) {
+        doubleValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      }
+    } else if (value instanceof String) {
+      String tmpValue = (String) value;
+      if (!isString) {
+        isString = true;
+        stringValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      } else if (tmpValue.compareTo(this.stringValue) <= 0) {
+        stringValue = tmpValue;
+        this.setTimestamp(timestamp);
+        this.setRelatedValues(relatedValues);
+      }
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxSelector.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxSelector.java
new file mode 100644
index 0000000..c4c9e33
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/function/selector/InfluxSelector.java
@@ -0,0 +1,57 @@
+/*
+ * 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.protocol.influxdb.function.selector;
+
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunction;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import org.apache.iotdb.db.query.expression.Expression;
+
+import java.util.List;
+
+public abstract class InfluxSelector extends InfluxFunction {
+
+  // The timestamp corresponding to the value
+  private Long timestamp = null;
+
+  private List<Object> relatedValues;
+
+  public InfluxSelector(List<Expression> expressionList) {
+    super(expressionList);
+  }
+
+  public List<Object> getRelatedValues() {
+    return this.relatedValues;
+  }
+
+  public void setRelatedValues(List<Object> relatedValues) {
+    this.relatedValues = relatedValues;
+  }
+
+  public Long getTimestamp() {
+    return timestamp;
+  }
+
+  public void setTimestamp(Long timestamp) {
+    this.timestamp = timestamp;
+  }
+
+  public abstract void updateValueAndRelateValues(
+      InfluxFunctionValue functionValue, List<Object> relatedValues);
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/handler/QueryHandler.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/handler/QueryHandler.java
new file mode 100644
index 0000000..e2c5317
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/handler/QueryHandler.java
@@ -0,0 +1,956 @@
+/*
+ * 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.protocol.influxdb.handler;
+
+import org.apache.iotdb.db.auth.AuthException;
+import org.apache.iotdb.db.conf.IoTDBConstant;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxSQLConstant;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunction;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionFactory;
+import org.apache.iotdb.db.protocol.influxdb.function.InfluxFunctionValue;
+import 
org.apache.iotdb.db.protocol.influxdb.function.aggregator.InfluxAggregator;
+import org.apache.iotdb.db.protocol.influxdb.function.selector.InfluxSelector;
+import org.apache.iotdb.db.protocol.influxdb.meta.InfluxDBMetaManager;
+import org.apache.iotdb.db.protocol.influxdb.operator.InfluxQueryOperator;
+import org.apache.iotdb.db.protocol.influxdb.operator.InfluxSelectComponent;
+import org.apache.iotdb.db.protocol.influxdb.util.FieldUtils;
+import org.apache.iotdb.db.protocol.influxdb.util.FilterUtils;
+import org.apache.iotdb.db.protocol.influxdb.util.QueryResultUtils;
+import org.apache.iotdb.db.protocol.influxdb.util.StringUtils;
+import org.apache.iotdb.db.qp.constant.FilterConstant;
+import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
+import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
+import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
+import org.apache.iotdb.db.query.context.QueryContext;
+import org.apache.iotdb.db.query.expression.Expression;
+import org.apache.iotdb.db.query.expression.ResultColumn;
+import org.apache.iotdb.db.query.expression.unary.FunctionExpression;
+import org.apache.iotdb.db.query.expression.unary.TimeSeriesOperand;
+import org.apache.iotdb.db.service.basic.ServiceProvider;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryResultRsp;
+import org.apache.iotdb.rpc.RpcUtils;
+import org.apache.iotdb.rpc.TSStatusCode;
+import org.apache.iotdb.service.rpc.thrift.TSStatus;
+import 
org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
+import org.apache.iotdb.tsfile.read.common.Field;
+import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.expression.IExpression;
+import org.apache.iotdb.tsfile.read.expression.impl.SingleSeriesExpression;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+
+import com.google.gson.Gson;
+import org.apache.thrift.TException;
+import org.influxdb.InfluxDBException;
+import org.influxdb.dto.QueryResult;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class QueryHandler {
+
+  public static TSQueryResultRsp queryInfluxDB(
+      String database,
+      InfluxQueryOperator queryOperator,
+      long sessionId,
+      ServiceProvider serviceProvider) {
+    String measurement = 
queryOperator.getFromComponent().getPrefixPaths().get(0).getFullPath();
+    // The list of fields under the current measurement and the order of the 
specified rules
+    Map<String, Integer> fieldOrders = getFieldOrders(database, measurement, 
serviceProvider);
+    QueryResult queryResult;
+    TSQueryResultRsp tsQueryResultRsp = new TSQueryResultRsp();
+    try {
+      // contain filter condition or have common query the result of by 
traversal.
+      if (queryOperator.getWhereComponent() != null
+          || queryOperator.getSelectComponent().isHasCommonQuery()
+          || queryOperator.getSelectComponent().isHasOnlyTraverseFunction()) {
+        // step1 : generate query results
+        queryResult =
+            queryExpr(
+                queryOperator.getWhereComponent() != null
+                    ? queryOperator.getWhereComponent().getFilterOperator()
+                    : null,
+                database,
+                measurement,
+                serviceProvider,
+                fieldOrders,
+                sessionId);
+        // step2 : select filter
+        ProcessSelectComponent(queryResult, 
queryOperator.getSelectComponent());
+      }
+      // don't contain filter condition and only have function use iotdb 
function.
+      else {
+        queryResult =
+            queryFuncWithoutFilter(
+                queryOperator.getSelectComponent(), database, measurement, 
serviceProvider);
+      }
+      return tsQueryResultRsp
+          .setResultJsonString(new Gson().toJson(queryResult))
+          .setStatus(RpcUtils.getInfluxDBStatus(TSStatusCode.SUCCESS_STATUS));
+    } catch (AuthException e) {
+      return tsQueryResultRsp.setStatus(
+          RpcUtils.getInfluxDBStatus(
+              TSStatusCode.UNINITIALIZED_AUTH_ERROR.getStatusCode(), 
e.getMessage()));
+    }
+  }
+
+  /**
+   * conditions are generated from subtrees of unique conditions
+   *
+   * @param basicFunctionOperator subtree to generate condition
+   * @return corresponding conditions
+   */
+  public static IExpression getIExpressionForBasicFunctionOperator(
+      BasicFunctionOperator basicFunctionOperator) {
+    return new SingleSeriesExpression(
+        basicFunctionOperator.getSinglePath(),
+        FilterUtils.filterTypeToFilter(
+            basicFunctionOperator.getFilterType(), 
basicFunctionOperator.getValue()));
+  }
+
+  /**
+   * further process the obtained query result through the query criteria of 
select
+   *
+   * @param queryResult query results to be processed
+   * @param selectComponent select conditions to be filtered
+   */
+  public static void ProcessSelectComponent(
+      QueryResult queryResult, InfluxSelectComponent selectComponent) {
+
+    // get the row order map of the current data result first
+    List<String> columns = 
queryResult.getResults().get(0).getSeries().get(0).getColumns();
+    Map<String, Integer> columnOrders = new HashMap<>();
+    for (int i = 0; i < columns.size(); i++) {
+      columnOrders.put(columns.get(i), i);
+    }
+    // get current values
+    List<List<Object>> values = 
queryResult.getResults().get(0).getSeries().get(0).getValues();
+    // new columns
+    List<String> newColumns = new ArrayList<>();
+    newColumns.add(InfluxSQLConstant.RESERVED_TIME);
+
+    // when have function
+    if (selectComponent.isHasFunction()) {
+      List<InfluxFunction> functions = new ArrayList<>();
+      for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
+        Expression expression = resultColumn.getExpression();
+        if (expression instanceof FunctionExpression) {
+          String functionName = ((FunctionExpression) 
expression).getFunctionName();
+          functions.add(
+              InfluxFunctionFactory.generateFunction(functionName, 
expression.getExpressions()));
+          newColumns.add(functionName);
+        } else if (expression instanceof TimeSeriesOperand) {
+          String columnName = ((TimeSeriesOperand) 
expression).getPath().getFullPath();
+          if (!columnName.equals(InfluxSQLConstant.STAR)) {
+            newColumns.add(columnName);
+          } else {
+            newColumns.addAll(columns.subList(1, columns.size()));
+          }
+        }
+      }
+      for (List<Object> value : values) {
+        for (InfluxFunction function : functions) {
+          List<Expression> expressions = function.getExpressions();
+          if (expressions == null) {
+            throw new IllegalArgumentException("not support param");
+          }
+          TimeSeriesOperand parmaExpression = (TimeSeriesOperand) 
expressions.get(0);
+          String parmaName = parmaExpression.getPath().getFullPath();
+          if (columnOrders.containsKey(parmaName)) {
+            Object selectedValue = value.get(columnOrders.get(parmaName));
+            Long selectedTimestamp = (Long) value.get(0);
+            if (selectedValue != null) {
+              // selector function
+              if (function instanceof InfluxSelector) {
+                ((InfluxSelector) function)
+                    .updateValueAndRelateValues(
+                        new InfluxFunctionValue(selectedValue, 
selectedTimestamp), value);
+              } else {
+                // aggregate function
+                ((InfluxAggregator) function)
+                    .updateValueBruteForce(
+                        new InfluxFunctionValue(selectedValue, 
selectedTimestamp));
+              }
+            }
+          }
+        }
+      }
+      List<Object> value = new ArrayList<>();
+      values = new ArrayList<>();
+      // after the data is constructed, the final results are generated
+      // First, judge whether there are common queries. If there are, a 
selector function is allowed
+      // without aggregate functions
+      if (selectComponent.isHasCommonQuery()) {
+        InfluxSelector selector = (InfluxSelector) functions.get(0);
+        List<Object> relatedValue = selector.getRelatedValues();
+        for (String column : newColumns) {
+          if 
(InfluxSQLConstant.getNativeSelectorFunctionNames().contains(column)) {
+            value.add(selector.calculateBruteForce().getValue());
+          } else {
+            if (relatedValue != null) {
+              value.add(relatedValue.get(columnOrders.get(column)));
+            }
+          }
+        }
+      } else {
+        // If there are no common queries, they are all function queries
+        for (InfluxFunction function : functions) {
+          if (value.size() == 0) {
+            value.add(function.calculateBruteForce().getTimestamp());
+          } else {
+            value.set(0, function.calculateBruteForce().getTimestamp());
+          }
+          value.add(function.calculateBruteForce().getValue());
+        }
+        if (selectComponent.isHasAggregationFunction() || 
selectComponent.isHasMoreFunction()) {
+          value.set(0, 0);
+        }
+      }
+      values.add(value);
+    }
+    // if it is not a function query, it is only a common query
+    else if (selectComponent.isHasCommonQuery()) {
+      // start traversing the scope of the select
+      for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
+        Expression expression = resultColumn.getExpression();
+        if (expression instanceof TimeSeriesOperand) {
+          // not star case
+          if (!((TimeSeriesOperand) expression)
+              .getPath()
+              .getFullPath()
+              .equals(InfluxSQLConstant.STAR)) {
+            newColumns.add(((TimeSeriesOperand) 
expression).getPath().getFullPath());
+          } else {
+            newColumns.addAll(columns.subList(1, columns.size()));
+          }
+        }
+      }
+      List<List<Object>> newValues = new ArrayList<>();
+      for (List<Object> value : values) {
+        List<Object> tmpValue = new ArrayList<>();
+        for (String newColumn : newColumns) {
+          tmpValue.add(value.get(columnOrders.get(newColumn)));
+        }
+        newValues.add(tmpValue);
+      }
+      values = newValues;
+    }
+    QueryResultUtils.updateQueryResultColumnValue(
+        queryResult, StringUtils.removeDuplicate(newColumns), values);
+  }
+
+  public static Map<String, Integer> getFieldOrders(
+      String database, String measurement, ServiceProvider serviceProvider) {
+    Map<String, Integer> fieldOrders = new HashMap<>();
+    long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+    try {
+      String showTimeseriesSql = "show timeseries root." + database + '.' + 
measurement + ".**";
+      PhysicalPlan physicalPlan =
+          
serviceProvider.getPlanner().parseSQLToPhysicalPlan(showTimeseriesSql);
+      QueryContext queryContext =
+          serviceProvider.genQueryContext(
+              queryId,
+              true,
+              System.currentTimeMillis(),
+              showTimeseriesSql,
+              IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+      QueryDataSet queryDataSet =
+          serviceProvider.createQueryDataSet(
+              queryContext, physicalPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+      int fieldNums = 0;
+      Map<String, Integer> tagOrders =
+          
InfluxDBMetaManager.getDatabase2Measurement2TagOrders().get(database).get(measurement);
+      int tagOrderNums = tagOrders.size();
+      while (queryDataSet.hasNext()) {
+        List<Field> fields = queryDataSet.next().getFields();
+        String filed = 
StringUtils.getFieldByPath(fields.get(0).getStringValue());
+        if (!fieldOrders.containsKey(filed)) {
+          // The corresponding order of fields is 1 + tagNum (the first is 
timestamp, then all tags,
+          // and finally all fields)
+          fieldOrders.put(filed, tagOrderNums + fieldNums + 1);
+          fieldNums++;
+        }
+      }
+    } catch (QueryProcessException
+        | TException
+        | StorageEngineException
+        | SQLException
+        | IOException
+        | InterruptedException
+        | QueryFilterOptimizationException
+        | MetadataException e) {
+      throw new InfluxDBException(e.getMessage());
+    } finally {
+      
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+    }
+    return fieldOrders;
+  }
+
+  /**
+   * Query the select result. By default, there are no filter conditions. The 
functions to be
+   * queried use the built-in iotdb functions
+   *
+   * @param selectComponent select data to query
+   * @return select query result
+   */
+  public static QueryResult queryFuncWithoutFilter(
+      InfluxSelectComponent selectComponent,
+      String database,
+      String measurement,
+      ServiceProvider serviceProvider) {
+    // columns
+    List<String> columns = new ArrayList<>();
+    columns.add(InfluxSQLConstant.RESERVED_TIME);
+
+    List<InfluxFunction> functions = new ArrayList<>();
+    String path = "root." + database + "." + measurement;
+    for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
+      Expression expression = resultColumn.getExpression();
+      if (expression instanceof FunctionExpression) {
+        String functionName = ((FunctionExpression) 
expression).getFunctionName();
+        functions.add(
+            InfluxFunctionFactory.generateFunction(functionName, 
expression.getExpressions()));
+        columns.add(functionName);
+      }
+    }
+
+    List<Object> value = new ArrayList<>();
+    List<List<Object>> values = new ArrayList<>();
+    for (InfluxFunction function : functions) {
+      InfluxFunctionValue functionValue = updateByIoTDBFunc(function, 
serviceProvider, path);
+      //      InfluxFunctionValue functionValue = 
function.calculateByIoTDBFunc();
+      if (value.size() == 0) {
+        value.add(functionValue.getTimestamp());
+      } else {
+        value.set(0, functionValue.getTimestamp());
+      }
+      value.add(functionValue.getValue());
+    }
+    if (selectComponent.isHasAggregationFunction() || 
selectComponent.isHasMoreFunction()) {
+      value.set(0, 0);
+    }
+    values.add(value);
+
+    // generate series
+    QueryResult queryResult = new QueryResult();
+    QueryResult.Series series = new QueryResult.Series();
+    series.setColumns(columns);
+    series.setValues(values);
+    series.setName(measurement);
+    QueryResult.Result result = new QueryResult.Result();
+    result.setSeries(new ArrayList<>(Arrays.asList(series)));
+    queryResult.setResults(new ArrayList<>(Arrays.asList(result)));
+    return queryResult;
+  }
+
+  private static InfluxFunctionValue updateByIoTDBFunc(
+      InfluxFunction function, ServiceProvider serviceProvider, String path) {
+    switch (function.getFunctionName()) {
+      case InfluxSQLConstant.COUNT:
+        {
+          long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          String functionSql =
+              StringUtils.generateFunctionSql(
+                  function.getFunctionName(), function.getParmaName(), path);
+          try {
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSql);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSql,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Field> fields = queryDataSet.next().getFields();
+              for (Field field : fields) {
+                function.updateValueIoTDBFunc(new 
InfluxFunctionValue(field.getLongV(), null));
+              }
+            }
+          } catch (QueryProcessException
+              | QueryFilterOptimizationException
+              | StorageEngineException
+              | IOException
+              | MetadataException
+              | SQLException
+              | TException
+              | InterruptedException e) {
+            e.printStackTrace();
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+          }
+          break;
+        }
+      case InfluxSQLConstant.MEAN:
+        {
+          long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            String functionSqlCount =
+                StringUtils.generateFunctionSql("count", 
function.getParmaName(), path);
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSqlCount);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSqlCount,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Field> fields = queryDataSet.next().getFields();
+              for (Field field : fields) {
+                function.updateValueIoTDBFunc(new 
InfluxFunctionValue(field.getLongV(), null));
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+          }
+          long queryId1 = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            String functionSqlSum =
+                StringUtils.generateFunctionSql("sum", 
function.getParmaName(), path);
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSqlSum);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSqlSum,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Field> fields = queryDataSet.next().getFields();
+              for (Field field : fields) {
+                function.updateValueIoTDBFunc(
+                    null, new InfluxFunctionValue(field.getDoubleV(), null));
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            e.printStackTrace();
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId1);
+          }
+          break;
+        }
+      case InfluxSQLConstant.SPREAD:
+        {
+          long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            String functionSqlMaxValue =
+                StringUtils.generateFunctionSql("max_value", 
function.getParmaName(), path);
+            QueryPlan queryPlan =
+                (QueryPlan)
+                    
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSqlMaxValue);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSqlMaxValue,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Path> paths = queryDataSet.getPaths();
+              List<Field> fields = queryDataSet.next().getFields();
+              for (int i = 0; i < paths.size(); i++) {
+                Object o = FieldUtils.iotdbFieldConvert(fields.get(i));
+                if (o instanceof Number) {
+                  function.updateValueIoTDBFunc(
+                      new InfluxFunctionValue(((Number) o).doubleValue(), 
null));
+                }
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+          }
+          long queryId1 = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            String functionSqlMinValue =
+                StringUtils.generateFunctionSql("min_value", 
function.getParmaName(), path);
+            QueryPlan queryPlan =
+                (QueryPlan)
+                    
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSqlMinValue);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSqlMinValue,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Path> paths = queryDataSet.getPaths();
+              List<Field> fields = queryDataSet.next().getFields();
+              for (int i = 0; i < paths.size(); i++) {
+                Object o = FieldUtils.iotdbFieldConvert(fields.get(i));
+                if (o instanceof Number) {
+                  function.updateValueIoTDBFunc(
+                      null, new InfluxFunctionValue(((Number) 
o).doubleValue(), null));
+                }
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId1);
+          }
+          break;
+        }
+      case InfluxSQLConstant.SUM:
+        {
+          long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            String functionSql =
+                StringUtils.generateFunctionSql("sum", 
function.getParmaName(), path);
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSql);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSql,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Field> fields = queryDataSet.next().getFields();
+              if (fields.get(1).getDataType() != null) {
+                function.updateValueIoTDBFunc(
+                    new InfluxFunctionValue(fields.get(1).getDoubleV(), null));
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+          }
+          break;
+        }
+      case InfluxSQLConstant.FIRST:
+      case InfluxSQLConstant.LAST:
+        {
+          String functionSql;
+          if (function.getFunctionName().equals(InfluxSQLConstant.FIRST)) {
+            functionSql =
+                StringUtils.generateFunctionSql("first_value", 
function.getParmaName(), path);
+          } else {
+            functionSql =
+                StringUtils.generateFunctionSql("last_value", 
function.getParmaName(), path);
+          }
+          List<Long> queryIds = new ArrayList<>();
+          queryIds.add(ServiceProvider.SESSION_MANAGER.requestQueryId(true));
+          try {
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSql);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryIds.get(0),
+                    true,
+                    System.currentTimeMillis(),
+                    functionSql,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Path> paths = queryDataSet.getPaths();
+              List<Field> fields = queryDataSet.next().getFields();
+              for (int i = 0; i < paths.size(); i++) {
+                Object o = FieldUtils.iotdbFieldConvert(fields.get(i));
+                long queryId = 
ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+                queryIds.add(queryId);
+                if (o != null) {
+                  String specificSql =
+                      String.format(
+                          "select %s from %s where %s=%s",
+                          function.getParmaName(),
+                          paths.get(i).getDevice(),
+                          paths.get(i).getFullPath(),
+                          o);
+                  QueryPlan queryPlanNew =
+                      (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(specificSql);
+                  QueryContext queryContextNew =
+                      serviceProvider.genQueryContext(
+                          queryId,
+                          true,
+                          System.currentTimeMillis(),
+                          specificSql,
+                          IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+                  QueryDataSet queryDataSetNew =
+                      serviceProvider.createQueryDataSet(
+                          queryContextNew, queryPlanNew, 
IoTDBConstant.DEFAULT_FETCH_SIZE);
+                  while (queryDataSetNew.hasNext()) {
+                    RowRecord recordNew = queryDataSetNew.next();
+                    List<Field> newFields = recordNew.getFields();
+                    long time = recordNew.getTimestamp();
+                    function.updateValueIoTDBFunc(new 
InfluxFunctionValue(newFields.get(0), time));
+                  }
+                }
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            for (long queryId : queryIds) {
+              
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+            }
+          }
+          break;
+        }
+      case InfluxSQLConstant.MAX:
+      case InfluxSQLConstant.MIN:
+        {
+          String functionSql;
+          if (function.getFunctionName().equals(InfluxSQLConstant.MAX)) {
+            functionSql =
+                StringUtils.generateFunctionSql("max_value", 
function.getParmaName(), path);
+          } else {
+            functionSql =
+                StringUtils.generateFunctionSql("min_value", 
function.getParmaName(), path);
+          }
+          long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+          try {
+            QueryPlan queryPlan =
+                (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(functionSql);
+            QueryContext queryContext =
+                serviceProvider.genQueryContext(
+                    queryId,
+                    true,
+                    System.currentTimeMillis(),
+                    functionSql,
+                    IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+            QueryDataSet queryDataSet =
+                serviceProvider.createQueryDataSet(
+                    queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+            while (queryDataSet.hasNext()) {
+              List<Path> paths = queryDataSet.getPaths();
+              List<Field> fields = queryDataSet.next().getFields();
+              for (int i = 0; i < paths.size(); i++) {
+                Object o = FieldUtils.iotdbFieldConvert(fields.get(i));
+                function.updateValueIoTDBFunc(new InfluxFunctionValue(o, 
null));
+              }
+            }
+          } catch (QueryProcessException
+              | TException
+              | StorageEngineException
+              | SQLException
+              | IOException
+              | InterruptedException
+              | QueryFilterOptimizationException
+              | MetadataException e) {
+            throw new InfluxDBException(e.getMessage());
+          } finally {
+            
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+          }
+          break;
+        }
+      default:
+        throw new IllegalStateException("Unexpected value: " + 
function.getFunctionName());
+    }
+    return function.calculateByIoTDBFunc();
+  }
+
+  public static void checkInfluxDBQueryOperator(Operator operator) {
+    if (!(operator instanceof InfluxQueryOperator)) {
+      throw new IllegalArgumentException("not query sql");
+    }
+    InfluxSelectComponent selectComponent = ((InfluxQueryOperator) 
operator).getSelectComponent();
+    if (selectComponent.isHasMoreSelectorFunction() && 
selectComponent.isHasCommonQuery()) {
+      throw new IllegalArgumentException(
+          "ERR: mixing multiple selector functions with tags or fields is not 
supported");
+    }
+    if (selectComponent.isHasAggregationFunction() && 
selectComponent.isHasCommonQuery()) {
+      throw new IllegalArgumentException(
+          "ERR: mixing aggregate and non-aggregate queries is not supported");
+    }
+  }
+
+  public static QueryResult queryExpr(
+      FilterOperator operator,
+      String database,
+      String measurement,
+      ServiceProvider serviceProvider,
+      Map<String, Integer> fieldOrders,
+      Long sessionId)
+      throws AuthException {
+    if (operator == null) {
+      List<IExpression> expressions = new ArrayList<>();
+      return queryByConditions(
+          expressions, database, measurement, serviceProvider, fieldOrders, 
sessionId);
+    } else if (operator instanceof BasicFunctionOperator) {
+      List<IExpression> iExpressions = new ArrayList<>();
+      
iExpressions.add(getIExpressionForBasicFunctionOperator((BasicFunctionOperator) 
operator));
+      return queryByConditions(
+          iExpressions, database, measurement, serviceProvider, fieldOrders, 
sessionId);
+    } else {
+      FilterOperator leftOperator = operator.getChildren().get(0);
+      FilterOperator rightOperator = operator.getChildren().get(1);
+      if (operator.getFilterType() == FilterConstant.FilterType.KW_OR) {
+        return QueryResultUtils.orQueryResultProcess(
+            queryExpr(leftOperator, database, measurement, serviceProvider, 
fieldOrders, sessionId),
+            queryExpr(
+                rightOperator, database, measurement, serviceProvider, 
fieldOrders, sessionId));
+      } else if (operator.getFilterType() == FilterConstant.FilterType.KW_AND) 
{
+        if (canMergeOperator(leftOperator) && canMergeOperator(rightOperator)) 
{
+          List<IExpression> iExpressions1 = 
getIExpressionByFilterOperatorOperator(leftOperator);
+          List<IExpression> iExpressions2 = 
getIExpressionByFilterOperatorOperator(rightOperator);
+          iExpressions1.addAll(iExpressions2);
+          return queryByConditions(
+              iExpressions1, database, measurement, serviceProvider, 
fieldOrders, sessionId);
+        } else {
+          return QueryResultUtils.andQueryResultProcess(
+              queryExpr(
+                  leftOperator, database, measurement, serviceProvider, 
fieldOrders, sessionId),
+              queryExpr(
+                  rightOperator, database, measurement, serviceProvider, 
fieldOrders, sessionId));
+        }
+      }
+    }
+    throw new IllegalArgumentException("unknown operator " + operator);
+  }
+
+  /**
+   * get query results in the format of influxdb through conditions
+   *
+   * @param expressions list of conditions, including tag and field condition
+   * @return returns the results of the influxdb query
+   */
+  private static QueryResult queryByConditions(
+      List<IExpression> expressions,
+      String database,
+      String measurement,
+      ServiceProvider serviceProvider,
+      Map<String, Integer> fieldOrders,
+      Long sessionId)
+      throws AuthException {
+    // used to store the actual order according to the tag
+    Map<Integer, SingleSeriesExpression> realTagOrders = new HashMap<>();
+    // stores a list of conditions belonging to the field
+    List<SingleSeriesExpression> fieldExpressions = new ArrayList<>();
+    // maximum number of tags in the current query criteria
+    int currentQueryMaxTagNum = 0;
+    Map<String, Integer> tagOrders =
+        
InfluxDBMetaManager.getDatabase2Measurement2TagOrders().get(database).get(measurement);
+    for (IExpression expression : expressions) {
+      SingleSeriesExpression singleSeriesExpression = 
((SingleSeriesExpression) expression);
+      // the current condition is in tag
+      if 
(tagOrders.containsKey(singleSeriesExpression.getSeriesPath().getFullPath())) {
+        int curOrder = 
tagOrders.get(singleSeriesExpression.getSeriesPath().getFullPath());
+        // put it into the map according to the tag
+        realTagOrders.put(curOrder, singleSeriesExpression);
+        // update the maximum tag order of the current query criteria
+        currentQueryMaxTagNum = Math.max(currentQueryMaxTagNum, curOrder);
+      } else {
+        fieldExpressions.add(singleSeriesExpression);
+      }
+    }
+    // construct the actual query path
+    StringBuilder curQueryPath = new StringBuilder("root." + database + "." + 
measurement);
+    // the maximum number of traversals from 1 to the current query condition
+    for (int i = 1; i <= currentQueryMaxTagNum; i++) {
+      if (realTagOrders.containsKey(i)) {
+        // since it is the value in the path, you need to remove the quotation 
marks at the
+        // beginning and end
+        curQueryPath
+            .append(".")
+            .append(
+                StringUtils.removeQuotation(
+                    
FilterUtils.getFilterStringValue(realTagOrders.get(i).getFilter())));
+      } else {
+        curQueryPath.append(".").append("*");
+      }
+    }
+    curQueryPath.append(".**");
+    // construct actual query condition
+    StringBuilder realIotDBCondition = new StringBuilder();
+    for (int i = 0; i < fieldExpressions.size(); i++) {
+      SingleSeriesExpression singleSeriesExpression = fieldExpressions.get(i);
+      if (i != 0) {
+        realIotDBCondition.append(" and ");
+      }
+      realIotDBCondition
+          .append(singleSeriesExpression.getSeriesPath().getFullPath())
+          .append(" ")
+          
.append((FilterUtils.getFilerSymbol(singleSeriesExpression.getFilter())))
+          .append(" ")
+          
.append(FilterUtils.getFilterStringValue(singleSeriesExpression.getFilter()));
+    }
+    // actual query SQL statement
+    String realQuerySql;
+
+    realQuerySql = "select * from " + curQueryPath;
+    if (!(realIotDBCondition.length() == 0)) {
+      realQuerySql += " where " + realIotDBCondition;
+    }
+    realQuerySql += " align by device";
+
+    long queryId = ServiceProvider.SESSION_MANAGER.requestQueryId(true);
+    try {
+      QueryPlan queryPlan =
+          (QueryPlan) 
serviceProvider.getPlanner().parseSQLToPhysicalPlan(realQuerySql);
+      TSStatus tsStatus = serviceProvider.checkAuthority(queryPlan, sessionId);
+      if (tsStatus != null) {
+        throw new AuthException(tsStatus.getMessage());
+      }
+      QueryContext queryContext =
+          serviceProvider.genQueryContext(
+              queryId,
+              true,
+              System.currentTimeMillis(),
+              realQuerySql,
+              IoTDBConstant.DEFAULT_CONNECTION_TIMEOUT_MS);
+      QueryDataSet queryDataSet =
+          serviceProvider.createQueryDataSet(
+              queryContext, queryPlan, IoTDBConstant.DEFAULT_FETCH_SIZE);
+      return QueryResultUtils.iotdbResultConvertInfluxResult(
+          queryDataSet, database, measurement, fieldOrders);
+    } catch (QueryProcessException
+        | TException
+        | StorageEngineException
+        | SQLException
+        | IOException
+        | InterruptedException
+        | QueryFilterOptimizationException
+        | MetadataException e) {
+      throw new InfluxDBException(e.getMessage());
+    } finally {
+      
ServiceProvider.SESSION_MANAGER.releaseQueryResourceNoExceptions(queryId);
+    }
+  }
+
+  /**
+   * generate query conditions through the syntax tree (if you enter this 
function, it means that it
+   * must be a syntax tree that can be merged, and there is no or)
+   *
+   * @param filterOperator the syntax tree of query criteria needs to be 
generated
+   * @return condition list
+   */
+  public static List<IExpression> getIExpressionByFilterOperatorOperator(
+      FilterOperator filterOperator) {
+    if (filterOperator instanceof BasicFunctionOperator) {
+      // It must be a non-or situation
+      List<IExpression> expressions = new ArrayList<>();
+      expressions.add(
+          getIExpressionForBasicFunctionOperator((BasicFunctionOperator) 
filterOperator));
+      return expressions;
+    } else {
+      FilterOperator leftOperator = filterOperator.getChildren().get(0);
+      FilterOperator rightOperator = filterOperator.getChildren().get(1);
+      List<IExpression> expressions1 = 
getIExpressionByFilterOperatorOperator(leftOperator);
+      List<IExpression> expressions2 = 
getIExpressionByFilterOperatorOperator(rightOperator);
+      expressions1.addAll(expressions2);
+      return expressions1;
+    }
+  }
+
+  /**
+   * judge whether the subtrees of the syntax tree have or operations. If not, 
the query can be
+   * merged
+   *
+   * @param operator subtree to judge
+   * @return can merge queries
+   */
+  public static boolean canMergeOperator(FilterOperator operator) {
+    if (operator instanceof BasicFunctionOperator) {
+      return true;
+    } else {
+      if (operator.getFilterType() == FilterConstant.FilterType.KW_OR) {
+        return false;
+      } else {
+        FilterOperator leftOperator = operator.getChildren().get(0);
+        FilterOperator rightOperator = operator.getChildren().get(1);
+        return canMergeOperator(leftOperator) && 
canMergeOperator(rightOperator);
+      }
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/meta/InfluxDBMetaManager.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/meta/InfluxDBMetaManager.java
index ff20c64..261a0e9 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/meta/InfluxDBMetaManager.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/meta/InfluxDBMetaManager.java
@@ -25,7 +25,7 @@ import 
org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.path.PartialPath;
-import org.apache.iotdb.db.protocol.influxdb.constant.InfluxDBConstant;
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxConstant;
 import org.apache.iotdb.db.qp.Planner;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.crud.QueryPlan;
@@ -188,7 +188,7 @@ public class InfluxDBMetaManager {
           .append(
               layerOrderToTagKeysInPath.containsKey(i)
                   ? tags.get(layerOrderToTagKeysInPath.get(i))
-                  : InfluxDBConstant.PLACE_HOLDER);
+                  : InfluxConstant.PLACE_HOLDER);
     }
     return path.toString();
   }
@@ -204,6 +204,10 @@ public class InfluxDBMetaManager {
     }
   }
 
+  public static Map<String, Map<String, Map<String, Integer>>> 
getDatabase2Measurement2TagOrders() {
+    return database2Measurement2TagOrders;
+  }
+
   private static class InfluxDBMetaManagerHolder {
     private static final InfluxDBMetaManager INSTANCE = new 
InfluxDBMetaManager();
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/operator/InfluxSelectComponent.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/operator/InfluxSelectComponent.java
index 4e98caa..b5b9113 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/operator/InfluxSelectComponent.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/operator/InfluxSelectComponent.java
@@ -36,6 +36,7 @@ public final class InfluxSelectComponent
   private boolean hasMoreFunction = false;
   private boolean hasFunction = false;
   private boolean hasCommonQuery = false;
+  private boolean hasOnlyTraverseFunction = false;
 
   public InfluxSelectComponent() {
     super((ZoneId) null);
@@ -61,6 +62,9 @@ public final class InfluxSelectComponent
       } else {
         hasAggregationFunction = true;
       }
+      if 
(InfluxSQLConstant.getOnlyTraverseFunctionNames().contains(functionName.toLowerCase()))
 {
+        hasOnlyTraverseFunction = true;
+      }
     }
     if (expression instanceof TimeSeriesOperand) {
       hasCommonQuery = true;
@@ -80,8 +84,8 @@ public final class InfluxSelectComponent
     return hasCommonQuery;
   }
 
-  public boolean isHasSelectorFunction() {
-    return hasSelectorFunction;
+  public boolean isHasOnlyTraverseFunction() {
+    return hasOnlyTraverseFunction;
   }
 
   public boolean isHasMoreSelectorFunction() {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/CommonUtils.java
similarity index 61%
copy from 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
copy to 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/CommonUtils.java
index 6b59698..fcdc7cd 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/CommonUtils.java
@@ -16,9 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.protocol.influxdb.constant;
+package org.apache.iotdb.db.protocol.influxdb.util;
 
-public class InfluxDBConstant {
-
-  public static final String PLACE_HOLDER = "PH";
+public class CommonUtils {
+  /**
+   * judge whether two instances are equal, and allow null check
+   *
+   * @param o1 object1
+   * @param o2 object2
+   * @return are they equal
+   */
+  public static boolean checkEqualsContainNull(Object o1, Object o2) {
+    if (o1 == null && o2 == null) {
+      return true;
+    } else if (o1 == null) {
+      return false;
+    } else if (o2 == null) {
+      return false;
+    } else {
+      return o1.equals(o2);
+    }
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FieldUtils.java
similarity index 50%
rename from 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
rename to 
server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FieldUtils.java
index 6b59698..9b49e87 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/constant/InfluxDBConstant.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FieldUtils.java
@@ -16,9 +16,36 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.protocol.influxdb.constant;
+package org.apache.iotdb.db.protocol.influxdb.util;
 
-public class InfluxDBConstant {
+import org.apache.iotdb.tsfile.read.common.Field;
 
-  public static final String PLACE_HOLDER = "PH";
+public class FieldUtils {
+  /**
+   * convert the value of field in iotdb to object
+   *
+   * @param field filed to be converted
+   * @return value stored in field
+   */
+  public static Object iotdbFieldConvert(Field field) {
+    if (field.getDataType() == null) {
+      return null;
+    }
+    switch (field.getDataType()) {
+      case TEXT:
+        return field.getStringValue();
+      case INT64:
+        return field.getLongV();
+      case INT32:
+        return field.getIntV();
+      case DOUBLE:
+        return field.getDoubleV();
+      case FLOAT:
+        return field.getFloatV();
+      case BOOLEAN:
+        return field.getBoolV();
+      default:
+        return null;
+    }
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FilterUtils.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FilterUtils.java
new file mode 100644
index 0000000..8bad260
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/FilterUtils.java
@@ -0,0 +1,83 @@
+/*
+ * 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.protocol.influxdb.util;
+
+import org.apache.iotdb.db.qp.constant.FilterConstant;
+import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
+import org.apache.iotdb.tsfile.read.filter.ValueFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+
+public class FilterUtils {
+
+  public static String getFilterStringValue(Filter filter) {
+    String filterString = filter.toString();
+    if (filter instanceof ValueFilter.ValueEq) {
+      return filterString.split("== ")[1];
+    } else if (filter instanceof ValueFilter.ValueNotEq) {
+      return filterString.split("!= ")[1];
+    } else if (filter instanceof ValueFilter.ValueLtEq) {
+      return filterString.split("<= ")[1];
+    } else if (filter instanceof ValueFilter.ValueLt) {
+      return filterString.split("< ")[1];
+    } else if (filter instanceof ValueFilter.ValueGtEq) {
+      return filterString.split(">= ")[1];
+    } else if (filter instanceof ValueFilter.ValueGt) {
+      return filterString.split("> ")[1];
+    } else {
+      throw new UnSupportedDataTypeException("Unsupported filter :" + filter);
+    }
+  }
+
+  public static String getFilerSymbol(Filter filter) {
+    if (filter instanceof ValueFilter.ValueEq) {
+      return "=";
+    } else if (filter instanceof ValueFilter.ValueNotEq) {
+      return "!=";
+    } else if (filter instanceof ValueFilter.ValueLtEq) {
+      return "<=";
+    } else if (filter instanceof ValueFilter.ValueLt) {
+      return "<";
+    } else if (filter instanceof ValueFilter.ValueGtEq) {
+      return ">=";
+    } else if (filter instanceof ValueFilter.ValueGt) {
+      return ">";
+    } else {
+      throw new UnSupportedDataTypeException("Unsupported filter :" + filter);
+    }
+  }
+
+  public static Filter filterTypeToFilter(FilterConstant.FilterType 
filterType, String value) {
+    switch (filterType) {
+      case EQUAL:
+        return ValueFilter.eq(value);
+      case NOTEQUAL:
+        return ValueFilter.notEq(value);
+      case LESSTHANOREQUALTO:
+        return ValueFilter.ltEq(value);
+      case LESSTHAN:
+        return ValueFilter.lt(value);
+      case GREATERTHANOREQUALTO:
+        return ValueFilter.gtEq(value);
+      case GREATERTHAN:
+        return ValueFilter.gt(value);
+      default:
+        throw new UnSupportedDataTypeException("Unsupported data type:" + 
filterType);
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/QueryResultUtils.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/QueryResultUtils.java
new file mode 100644
index 0000000..df4c431
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/QueryResultUtils.java
@@ -0,0 +1,291 @@
+/*
+ * 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.protocol.influxdb.util;
+
+import org.apache.iotdb.db.protocol.influxdb.constant.InfluxConstant;
+import org.apache.iotdb.db.protocol.influxdb.meta.InfluxDBMetaManager;
+import org.apache.iotdb.db.query.dataset.AlignByDeviceDataSet;
+import org.apache.iotdb.tsfile.read.common.Field;
+import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
+
+import org.influxdb.dto.QueryResult;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class QueryResultUtils {
+  /**
+   * update the new values to the query results of influxdb
+   *
+   * @param queryResult influxdb query results to be updated
+   * @param columns columns to be updated
+   * @param updateValues values to be updated
+   */
+  public static void updateQueryResultColumnValue(
+      QueryResult queryResult, List<String> columns, List<List<Object>> 
updateValues) {
+    List<QueryResult.Result> results = queryResult.getResults();
+    QueryResult.Result result = results.get(0);
+    List<QueryResult.Series> series = results.get(0).getSeries();
+    QueryResult.Series serie = series.get(0);
+
+    serie.setValues(updateValues);
+    serie.setColumns(columns);
+    series.set(0, serie);
+    result.setSeries(series);
+    results.set(0, result);
+  }
+
+  /**
+   * Convert align by device query result of iotdb to the query result of 
influxdb
+   *
+   * @param queryDataSet iotdb query results to be converted
+   * @return query results in influxdb format
+   */
+  public static QueryResult iotdbResultConvertInfluxResult(
+      QueryDataSet queryDataSet,
+      String database,
+      String measurement,
+      Map<String, Integer> fieldOrders)
+      throws IOException {
+
+    if (queryDataSet == null) {
+      return getNullQueryResult();
+    }
+    // generate series
+    QueryResult.Series series = new QueryResult.Series();
+    series.setName(measurement);
+    // gets the reverse map of the tag
+    Map<String, Integer> tagOrders =
+        
InfluxDBMetaManager.getDatabase2Measurement2TagOrders().get(database).get(measurement);
+    Map<Integer, String> tagOrderReversed =
+        tagOrders.entrySet().stream()
+            .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
+    Map<Integer, String> fieldOrdersReversed =
+        fieldOrders.entrySet().stream()
+            .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
+    int tagSize = tagOrderReversed.size();
+    ArrayList<String> tagList = new ArrayList<>();
+    for (int i = 1; i <= tagSize; i++) {
+      tagList.add(tagOrderReversed.get(i));
+    }
+
+    ArrayList<String> fieldList = new ArrayList<>();
+    for (int i = 1 + tagSize; i < 1 + tagSize + fieldOrders.size(); i++) {
+      fieldList.add(fieldOrdersReversed.get(i));
+    }
+    ArrayList<String> columns = new ArrayList<>();
+    columns.add("time");
+    columns.addAll(tagList);
+    columns.addAll(fieldList);
+    // insert columns into series
+    series.setColumns(columns);
+
+    List<List<Object>> values = new ArrayList<>();
+
+    while (queryDataSet.hasNext()) {
+      Object[] value = new Object[columns.size()];
+
+      RowRecord record = queryDataSet.next();
+      List<Field> fields = record.getFields();
+
+      value[0] = record.getTimestamp();
+
+      String deviceName = fields.get(0).getStringValue();
+      String[] deviceNameList = deviceName.split("\\.");
+      for (int i = 3; i < deviceNameList.length; i++) {
+        if (!deviceNameList[i].equals(InfluxConstant.PLACE_HOLDER)) {
+          value[i - 2] = deviceNameList[i];
+        }
+      }
+      for (int i = 1; i < fields.size(); i++) {
+        Object o = FieldUtils.iotdbFieldConvert(fields.get(i));
+        if (o != null) {
+          // insert the value of filed into it
+          value[
+                  fieldOrders.get(
+                      ((AlignByDeviceDataSet) 
queryDataSet).getMeasurements().get(i - 1))] =
+              o;
+        }
+      }
+      // insert actual value
+      values.add(Arrays.asList(value));
+    }
+    series.setValues(values);
+
+    QueryResult queryResult = new QueryResult();
+    QueryResult.Result result = new QueryResult.Result();
+    result.setSeries(new ArrayList<>(Arrays.asList(series)));
+    queryResult.setResults(new ArrayList<>(Arrays.asList(result)));
+
+    return queryResult;
+  }
+
+  /**
+   * get a null query result
+   *
+   * @return null queryResult
+   */
+  public static QueryResult getNullQueryResult() {
+    QueryResult queryResult = new QueryResult();
+    QueryResult.Result result = new QueryResult.Result();
+    queryResult.setResults(Arrays.asList(result));
+    return queryResult;
+  }
+
+  /**
+   * update the new values to the query results of influxdb
+   *
+   * @param queryResult influxdb query results to be updated
+   * @param updateValues values to be updated
+   */
+  private static void updateQueryResultValue(
+      QueryResult queryResult, List<List<Object>> updateValues) {
+    List<QueryResult.Result> results = queryResult.getResults();
+    QueryResult.Result result = results.get(0);
+    List<QueryResult.Series> series = results.get(0).getSeries();
+    QueryResult.Series serie = series.get(0);
+
+    serie.setValues(updateValues);
+    series.set(0, serie);
+    result.setSeries(series);
+    results.set(0, result);
+  }
+
+  /**
+   * check whether the query results of two influxdb belong to the same query, 
that is, whether the
+   * measurement and columns are consistent
+   *
+   * @param queryResult1 query result1
+   * @param queryResult2 query result2
+   * @return belong to the same query
+   */
+  private static boolean checkSameQueryResult(QueryResult queryResult1, 
QueryResult queryResult2) {
+    return queryResult1
+            .getResults()
+            .get(0)
+            .getSeries()
+            .get(0)
+            .getName()
+            
.equals(queryResult2.getResults().get(0).getSeries().get(0).getName())
+        && StringUtils.checkSameStringList(
+            queryResult1.getResults().get(0).getSeries().get(0).getColumns(),
+            queryResult2.getResults().get(0).getSeries().get(0).getColumns());
+  }
+
+  /**
+   * union the query results of two influxdb
+   *
+   * @param queryResult1 query result 1
+   * @param queryResult2 query result 2
+   * @return union of two query results
+   */
+  public static QueryResult orQueryResultProcess(
+      QueryResult queryResult1, QueryResult queryResult2) {
+    if (checkQueryResultNull(queryResult1)) {
+      return queryResult2;
+    } else if (checkQueryResultNull(queryResult2)) {
+      return queryResult1;
+    }
+    if (!checkSameQueryResult(queryResult1, queryResult2)) {
+      System.out.println("QueryResult1 and QueryResult2 is not same 
attribute");
+      return queryResult1;
+    }
+    List<List<Object>> values1 = 
queryResult1.getResults().get(0).getSeries().get(0).getValues();
+    List<List<Object>> values2 = 
queryResult2.getResults().get(0).getSeries().get(0).getValues();
+    List<List<Object>> notSameValuesInValues1 = new ArrayList<>();
+    for (List<Object> value1 : values1) {
+      boolean allNotEqual = true;
+      for (List<Object> value2 : values2) {
+        boolean notEqual = false;
+        for (int t = 0; t < value1.size(); t++) {
+          // if there is any inequality, skip the current J
+          if (!CommonUtils.checkEqualsContainNull(value1.get(t), 
value2.get(t))) {
+            notEqual = true;
+            break;
+          }
+        }
+        if (!notEqual) {
+          allNotEqual = false;
+          break;
+        }
+      }
+      if (allNotEqual) {
+        notSameValuesInValues1.add(value1);
+      }
+    }
+    // values2 plus a different valueList
+    values2.addAll(notSameValuesInValues1);
+    updateQueryResultValue(queryResult1, values2);
+    return queryResult1;
+  }
+
+  /**
+   * take the intersection of the query results of two influxdb
+   *
+   * @param queryResult1 query result 1
+   * @param queryResult2 query result 2
+   * @return intersection of two query results
+   */
+  public static QueryResult andQueryResultProcess(
+      QueryResult queryResult1, QueryResult queryResult2) {
+    if (checkQueryResultNull(queryResult1) || 
checkQueryResultNull(queryResult2)) {
+      return getNullQueryResult();
+    }
+    if (!checkSameQueryResult(queryResult1, queryResult2)) {
+      System.out.println("QueryResult1 and QueryResult2 is not same 
attribute");
+      return queryResult1;
+    }
+    List<List<Object>> values1 = 
queryResult1.getResults().get(0).getSeries().get(0).getValues();
+    List<List<Object>> values2 = 
queryResult2.getResults().get(0).getSeries().get(0).getValues();
+    List<List<Object>> sameValues = new ArrayList<>();
+    for (List<Object> value1 : values1) {
+      for (List<Object> value2 : values2) {
+        boolean allEqual = true;
+        for (int t = 0; t < value1.size(); t++) {
+          // if there is any inequality, skip the current J
+          if (!CommonUtils.checkEqualsContainNull(value1.get(t), 
value2.get(t))) {
+            allEqual = false;
+            break;
+          }
+        }
+        // at this time, the matching is completed. If it is completely equal
+        if (allEqual) {
+          sameValues.add(value1);
+        }
+      }
+    }
+    updateQueryResultValue(queryResult1, sameValues);
+    return queryResult1;
+  }
+
+  /**
+   * checks whether query result is null in the specified way
+   *
+   * @param queryResult query result to be checked
+   * @return is null
+   */
+  public static boolean checkQueryResultNull(QueryResult queryResult) {
+    return queryResult.getResults().get(0).getSeries() == null;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/StringUtils.java
 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/StringUtils.java
new file mode 100644
index 0000000..39449b6
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/protocol/influxdb/util/StringUtils.java
@@ -0,0 +1,97 @@
+/*
+ * 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.protocol.influxdb.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class StringUtils {
+
+  /**
+   * if the first and last of the current string are quotation marks, they are 
removed
+   *
+   * @param str string to process
+   * @return string after processing
+   */
+  public static String removeQuotation(String str) {
+    if (str.charAt(0) == '"' && str.charAt(str.length() - 1) == '"') {
+      return str.substring(1, str.length() - 1);
+    }
+    return str;
+  }
+
+  /**
+   * remove string list duplicate names
+   *
+   * @param strings the list of strings with duplicate names needs to be 
removed
+   * @return list of de duplicated strings
+   */
+  public static List<String> removeDuplicate(List<String> strings) {
+    Map<String, Integer> nameNums = new HashMap<>();
+    List<String> result = new ArrayList<>();
+    for (String tmpString : strings) {
+      if (!nameNums.containsKey(tmpString)) {
+        nameNums.put(tmpString, 1);
+        result.add(tmpString);
+      } else {
+        int nums = nameNums.get(tmpString);
+        result.add(tmpString + "_" + nums);
+        nameNums.put(tmpString, nums + 1);
+      }
+    }
+    return result;
+  }
+
+  /**
+   * get the last node through the path in iotdb
+   *
+   * @param path path to process
+   * @return last node
+   */
+  public static String getFieldByPath(String path) {
+    String[] tmpList = path.split("\\.");
+    return tmpList[tmpList.length - 1];
+  }
+
+  /**
+   * determine whether the two string lists are the same
+   *
+   * @param list1 first list to compare
+   * @param list2 second list to compare
+   * @return Is it the same
+   */
+  public static boolean checkSameStringList(List<String> list1, List<String> 
list2) {
+    if (list1.size() != list2.size()) {
+      return false;
+    } else {
+      for (int i = 0; i < list1.size(); i++) {
+        if (!list1.get(i).equals(list2.get(i))) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  public static String generateFunctionSql(String functionName, String 
parameter, String path) {
+    return String.format("select %s(%s) from %s.**", functionName, parameter, 
path);
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/AlignByDeviceDataSet.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/AlignByDeviceDataSet.java
index a2ab715..cd38f79 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/AlignByDeviceDataSet.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/AlignByDeviceDataSet.java
@@ -134,6 +134,10 @@ public class AlignByDeviceDataSet extends QueryDataSet {
     return pathsNum;
   }
 
+  public List<String> getMeasurements() {
+    return measurements;
+  }
+
   @Override
   @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity 
warning
   public boolean hasNextWithoutConstraint() throws IOException {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/InfluxDBServiceImpl.java
 
b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/InfluxDBServiceImpl.java
index 9b97cf6..8789142 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/InfluxDBServiceImpl.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/InfluxDBServiceImpl.java
@@ -25,8 +25,12 @@ import 
org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.path.PartialPath;
 import org.apache.iotdb.db.protocol.influxdb.dto.IoTDBPoint;
+import org.apache.iotdb.db.protocol.influxdb.handler.QueryHandler;
 import org.apache.iotdb.db.protocol.influxdb.input.InfluxLineParser;
 import org.apache.iotdb.db.protocol.influxdb.meta.InfluxDBMetaManager;
+import org.apache.iotdb.db.protocol.influxdb.operator.InfluxQueryOperator;
+import org.apache.iotdb.db.protocol.influxdb.sql.InfluxDBLogicalGenerator;
+import org.apache.iotdb.db.qp.logical.Operator;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
@@ -39,6 +43,8 @@ import 
org.apache.iotdb.protocol.influxdb.rpc.thrift.TSCloseSessionReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSCreateDatabaseReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSOpenSessionReq;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSOpenSessionResp;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryReq;
+import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSQueryResultRsp;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSStatus;
 import org.apache.iotdb.protocol.influxdb.rpc.thrift.TSWritePointsReq;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
@@ -135,6 +141,14 @@ public class InfluxDBServiceImpl implements 
InfluxDBService.Iface {
     }
   }
 
+  @Override
+  public TSQueryResultRsp query(TSQueryReq req) throws TException {
+    Operator operator = InfluxDBLogicalGenerator.generate(req.command);
+    QueryHandler.checkInfluxDBQueryOperator(operator);
+    return QueryHandler.queryInfluxDB(
+        req.database, (InfluxQueryOperator) operator, req.sessionId, 
serviceProvider);
+  }
+
   public void handleClientExit() {
     Long sessionId = ServiceProvider.SESSION_MANAGER.getCurrSessionId();
     if (sessionId != null) {
diff --git a/server/src/main/java/org/apache/iotdb/db/utils/MathUtils.java 
b/server/src/main/java/org/apache/iotdb/db/utils/MathUtils.java
index e5809d5..aceec18 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/MathUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/MathUtils.java
@@ -21,6 +21,8 @@ package org.apache.iotdb.db.utils;
 
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 
+import java.util.List;
+
 public class MathUtils {
 
   private MathUtils() {
@@ -77,4 +79,53 @@ public class MathUtils {
                     * Math.pow(10, 
TSFileDescriptor.getInstance().getConfig().getFloatPrecision())))
             / Math.pow(10, 
TSFileDescriptor.getInstance().getConfig().getFloatPrecision());
   }
+
+  /**
+   * calculate sum of list
+   *
+   * @param data need to calculate list
+   * @return sum of list
+   */
+  public static double sum(List<Double> data) {
+    double sum = 0;
+    for (Double datum : data) {
+      sum = sum + datum;
+    }
+    return sum;
+  }
+
+  /**
+   * calculate mean of list
+   *
+   * @param data need to calculate list
+   * @return mean of list
+   */
+  public static double mean(List<Double> data) {
+    return sum(data) / data.size();
+  }
+
+  /**
+   * calculate pop variance of list
+   *
+   * @param data need to calculate list
+   * @return pop variance of list
+   */
+  public static double popVariance(List<Double> data) {
+    double variance = 0;
+    for (int i = 0; i < data.size(); i++) {
+      variance = variance + (Math.pow((data.get(i) - mean(data)), 2));
+    }
+    variance = variance / data.size();
+    return variance;
+  }
+
+  /**
+   * calculate pop std dev of list
+   *
+   * @param data need to calculate list
+   * @return pop std dev of list
+   */
+  public static double popStdDev(List<Double> data) {
+    return Math.sqrt(popVariance(data));
+  }
 }
diff --git a/thrift-influxdb/src/main/thrift/influxdb.thrift 
b/thrift-influxdb/src/main/thrift/influxdb.thrift
index 4ab0a19..a62cd91 100644
--- a/thrift-influxdb/src/main/thrift/influxdb.thrift
+++ b/thrift-influxdb/src/main/thrift/influxdb.thrift
@@ -81,6 +81,23 @@ struct TSCreateDatabaseReq{
   2: required string database
 }
 
+// query()
+// query in influxdb
+struct TSQueryReq{
+  // The session to execute the statement against
+  1: required i64 sessionId
+
+  2: required string command
+  3: required string database
+}
+
+struct TSQueryResultRsp{
+  1: required TSStatus status
+
+  2: optional string resultJsonString
+
+}
+
 service InfluxDBService {
   TSOpenSessionResp openSession(1:TSOpenSessionReq req);
 
@@ -89,4 +106,6 @@ service InfluxDBService {
   TSStatus writePoints(1:TSWritePointsReq req);
 
   TSStatus createDatabase(1:TSCreateDatabaseReq req);
+
+  TSQueryResultRsp query(1:TSQueryReq req);
 }

Reply via email to