You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2020/11/24 07:55:37 UTC

[iotdb] branch master updated: Change listener to visitor in antlr in order to improve prase speed. (#2034)

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

qiaojialin 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 891d8b6  Change listener to visitor in antlr in order to improve prase speed. (#2034)
891d8b6 is described below

commit 891d8b6ac1e70e1a0eb8d7fa892c4fb3ba9c4cd4
Author: Boris <ge...@apache.org>
AuthorDate: Tue Nov 24 15:55:19 2020 +0800

    Change listener to visitor in antlr in order to improve prase speed. (#2034)
---
 antlr/pom.xml                                      |    4 +
 .../iotdb/db/qp/{strategy => sql}/SqlBase.g4       |   45 +-
 .../org/apache/iotdb/db/metadata/MManager.java     |    5 +-
 .../main/java/org/apache/iotdb/db/qp/Planner.java  |    8 +-
 .../apache/iotdb/db/qp/constant/SQLConstant.java   |    2 +-
 .../db/qp/logical/crud/QueryIndexOperator.java     |   53 -
 .../iotdb/db/qp/logical/crud/QueryOperator.java    |   21 +
 .../IoTDBSqlVisitor.java}                          | 2629 ++++++++++----------
 .../iotdb/db/qp/strategy/LogicalGenerator.java     | 1950 +--------------
 .../apache/iotdb/db/qp/strategy/ParseDriver.java   |   69 -
 .../iotdb/db/qp/strategy/PhysicalGenerator.java    |   14 +-
 ...gicalGeneratorError.java => SQLParseError.java} |    4 +-
 .../qp/strategy/optimizer/ConcatPathOptimizer.java |    3 +-
 .../iotdb/db/qp/plan/IndexLogicalPlanTest.java     |   32 +-
 .../iotdb/db/qp/plan/LogicalPlanSmallTest.java     |  110 +-
 .../sql/DatetimeQueryDataSetUtilsTest.java         |    2 +-
 .../iotdb/db/qp/strategy/LogicalGeneratorTest.java |   26 +-
 17 files changed, 1491 insertions(+), 3486 deletions(-)

diff --git a/antlr/pom.xml b/antlr/pom.xml
index 3d9da5f..955bd75 100644
--- a/antlr/pom.xml
+++ b/antlr/pom.xml
@@ -44,6 +44,10 @@
                 <version>${antlr4.version}</version>
                 <executions>
                     <execution>
+                        <configuration>
+                            <listener>false</listener>
+                            <visitor>true</visitor>
+                        </configuration>
                         <goals>
                             <goal>antlr4</goal>
                         </goals>
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
similarity index 94%
rename from antlr/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
rename to antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
index 5a1aa67..9a83276 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4
@@ -33,7 +33,7 @@ statement
     : CREATE TIMESERIES fullPath alias? WITH attributeClauses #createTimeseries
     | DELETE TIMESERIES prefixPath (COMMA prefixPath)* #deleteTimeseries
     | ALTER TIMESERIES fullPath alterClause #alterTimeseries
-    | INSERT INTO prefixPath insertColumnSpec VALUES insertValuesSpec #insertStatement
+    | INSERT INTO prefixPath insertColumnsSpec VALUES insertValuesSpec #insertStatement
     | UPDATE prefixPath setClause whereClause? #updateStatement
     | DELETE FROM prefixPath (COMMA prefixPath)* (whereClause)? #deleteStatement
     | SET STORAGE GROUP TO prefixPath #setStorageGroup
@@ -42,7 +42,6 @@ statement
     | DESCRIBE prefixPath #describePath // not support yet
     | CREATE INDEX ON prefixPath whereClause? indexWithClause #createIndex //not support yet
     | DROP INDEX indexName=ID ON prefixPath #dropIndex //not support yet
-
     | MERGE #merge
     | FLUSH prefixPath? (COMMA prefixPath)* (booleanClause)?#flush
     | FULL MERGE #fullMerge
@@ -150,19 +149,19 @@ alterClause
     | DROP ID (COMMA ID)*
     | ADD TAGS property (COMMA property)*
     | ADD ATTRIBUTES property (COMMA property)*
-    | UPSERT aliasClause tagClause attributeClause
+    | UPSERT aliasClause? tagClause? attributeClause?
     ;
 
 aliasClause
-    : (ALIAS OPERATOR_EQ ID)?
+    : ALIAS OPERATOR_EQ ID
     ;
 
 attributeClauses
     : DATATYPE OPERATOR_EQ dataType (COMMA ENCODING OPERATOR_EQ encoding)?
     (COMMA (COMPRESSOR | COMPRESSION) OPERATOR_EQ compressor)?
     (COMMA property)*
-    tagClause
-    attributeClause
+    tagClause?
+    attributeClause?
     ;
 
 compressor
@@ -177,11 +176,11 @@ compressor
     ;
 
 attributeClause
-    : (ATTRIBUTES LR_BRACKET property (COMMA property)* RR_BRACKET)?
+    : ATTRIBUTES LR_BRACKET property (COMMA property)* RR_BRACKET
     ;
 
 tagClause
-    : (TAGS LR_BRACKET property (COMMA property)* RR_BRACKET)?
+    : TAGS LR_BRACKET property (COMMA property)* RR_BRACKET
     ;
 
 setClause
@@ -189,7 +188,7 @@ setClause
     ;
 
 whereClause
-    : WHERE orExpression
+    : WHERE (orExpression | indexPredicateClause)
     ;
 
 showWhereClause
@@ -210,7 +209,6 @@ andExpression
 predicate
     : (TIME | TIMESTAMP | suffixPath | fullPath) comparisonOperator constant
     | (TIME | TIMESTAMP | suffixPath | fullPath) inClause
-    | (suffixPath | fullPath) indexPredicateClause
     | OPERATOR_NOT? LR_BRACKET orExpression RR_BRACKET
     ;
 
@@ -223,19 +221,19 @@ fromClause
     ;
 
 specialClause
-    : specialLimit
-    | orderByTimeClause specialLimit?
-    | groupByTimeClause orderByTimeClause? specialLimit?
-    | groupByFillClause orderByTimeClause? specialLimit?
-    | fillClause slimitClause? alignByDeviceClauseOrDisableAlign?
-    | alignByDeviceClauseOrDisableAlign
-    | groupByLevelClause orderByTimeClause? specialLimit?
+    : specialLimit #specialLimitStatement
+    | orderByTimeClause specialLimit? #orderByTimeStatement
+    | groupByTimeClause orderByTimeClause? specialLimit? #groupByTimeStatement
+    | groupByFillClause orderByTimeClause? specialLimit? #groupByFillStatement
+    | fillClause slimitClause? alignByDeviceClauseOrDisableAlign? #fillStatement
+    | alignByDeviceClauseOrDisableAlign #alignByDeviceStatementOrDisableAlignInSpecialClause
+    | groupByLevelClause orderByTimeClause? specialLimit? #groupByLevelStatement
     ;
 
 specialLimit
-    : limitClause slimitClause? alignByDeviceClauseOrDisableAlign?
-    | slimitClause limitClause? alignByDeviceClauseOrDisableAlign?
-    | alignByDeviceClauseOrDisableAlign
+    : limitClause slimitClause? alignByDeviceClauseOrDisableAlign? #limitStatement
+    | slimitClause limitClause? alignByDeviceClauseOrDisableAlign? #slimitStatement
+    | alignByDeviceClauseOrDisableAlign #alignByDeviceClauseOrDisableAlignInSpecialLimit
     ;
 
 orderByTimeClause
@@ -332,9 +330,8 @@ topClause
     ;
 
 indexPredicateClause
-    : LIKE sequenceClause
-    | CONTAIN sequenceClause WITH TOLERANCE constant
-    (CONCAT sequenceClause WITH TOLERANCE constant)*
+    : (suffixPath | fullPath) LIKE sequenceClause
+    | (suffixPath | fullPath) CONTAIN sequenceClause WITH TOLERANCE constant (CONCAT sequenceClause WITH TOLERANCE constant)*
     ;
 
 
@@ -351,7 +348,7 @@ comparisonOperator
     | type = OPERATOR_NEQ
     ;
 
-insertColumnSpec
+insertColumnsSpec
     : LR_BRACKET (TIMESTAMP|TIME) (COMMA nodeNameWithoutStar)+ RR_BRACKET
     ;
 
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index d349f21..02eb4df 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -1253,7 +1253,10 @@ public class MManager {
       }
     }
 
-    pair.right.putAll(attributesMap);
+    if (attributesMap != null) {
+      pair.right.putAll(attributesMap);
+    }
+
 
     // persist the change to disk
     tagLogFile.write(pair.left, pair.right, leafMNode.getOffset());
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
index 39dfc43..e6db9c0 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
@@ -41,7 +41,7 @@ import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.crud.SFWOperator;
 import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
-import org.apache.iotdb.db.qp.strategy.ParseDriver;
+import org.apache.iotdb.db.qp.strategy.LogicalGenerator;
 import org.apache.iotdb.db.qp.strategy.PhysicalGenerator;
 import org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer;
 import org.apache.iotdb.db.qp.strategy.optimizer.DnfFilterOptimizer;
@@ -56,10 +56,10 @@ import org.apache.iotdb.service.rpc.thrift.TSRawDataQueryReq;
  */
 public class Planner {
 
-  protected ParseDriver parseDriver;
+  protected LogicalGenerator logicalGenerator;
 
   public Planner() {
-    this.parseDriver = new ParseDriver();
+    this.logicalGenerator = new LogicalGenerator();
   }
 
   @TestOnly
@@ -73,7 +73,7 @@ public class Planner {
    */
   public PhysicalPlan parseSQLToPhysicalPlan(String sqlStr, ZoneId zoneId, int fetchSize)
       throws QueryProcessException {
-    Operator operator = parseDriver.parse(sqlStr, zoneId);
+    Operator operator = logicalGenerator.generate(sqlStr, zoneId);
     int maxDeduplicatedPathNum = QueryResourceManager.getInstance()
         .getMaxDeduplicatedPathNum(fetchSize);
     if (operator instanceof SFWOperator && ((SFWOperator) operator).isLastQuery()) {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
index 379c00d..f1003b8 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/constant/SQLConstant.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.db.qp.constant;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.iotdb.db.metadata.PartialPath;
-import org.apache.iotdb.db.qp.strategy.SqlBaseLexer;
+import org.apache.iotdb.db.qp.sql.SqlBaseLexer;
 
 /**
  * this class contains several constants used in SQL.
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryIndexOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryIndexOperator.java
deleted file mode 100644
index e4e516e..0000000
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryIndexOperator.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.qp.logical.crud;
-
-import java.util.Map;
-import org.apache.iotdb.db.index.common.IndexType;
-
-/**
- * this operator is to conduct similarity search based on a certain index.
- */
-public class QueryIndexOperator extends QueryOperator {
-
-  private Map<String, Object> props;
-
-  private IndexType indexType;
-
-  public QueryIndexOperator(int tokenIntType) {
-    super(tokenIntType);
-    operatorType = OperatorType.QUERY_INDEX;
-  }
-
-  public Map<String, Object> getProps() {
-    return props;
-  }
-
-  public void setProps(Map<String, Object> props) {
-    this.props = props;
-  }
-
-  public IndexType getIndexType() {
-    return indexType;
-  }
-
-  public void setIndexType(IndexType indexType) {
-    this.indexType = indexType;
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryOperator.java
index 4b36f62..249477f 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/QueryOperator.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.db.qp.logical.crud;
 
 import java.util.Map;
+import org.apache.iotdb.db.index.common.IndexType;
 import org.apache.iotdb.db.qp.logical.Operator;
 import org.apache.iotdb.db.query.executor.fill.IFill;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -56,11 +57,31 @@ public class QueryOperator extends SFWOperator {
 
   private boolean ascending = true;
 
+  private Map<String, Object> props;
+
+  private IndexType indexType;
+
   public QueryOperator(int tokenIntType) {
     super(tokenIntType);
     operatorType = Operator.OperatorType.QUERY;
   }
 
+  public Map<String, Object> getProps() {
+    return props;
+  }
+
+  public void setProps(Map<String, Object> props) {
+    this.props = props;
+  }
+
+  public IndexType getIndexType() {
+    return indexType;
+  }
+
+  public void setIndexType(IndexType indexType) {
+    this.indexType = indexType;
+  }
+
   public boolean isFill() {
     return isFill;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
similarity index 61%
copy from server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
copy to server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 57d632b..2cdd2d2 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -16,13 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.qp.strategy;
+package org.apache.iotdb.db.qp.sql;
 
-import static org.apache.iotdb.db.index.common.IndexConstant.NON_SET_TOP_K;
 import static org.apache.iotdb.db.index.common.IndexConstant.PATTERN;
 import static org.apache.iotdb.db.index.common.IndexConstant.THRESHOLD;
 import static org.apache.iotdb.db.index.common.IndexConstant.TOP_K;
-import static org.apache.iotdb.db.qp.constant.SQLConstant.RESERVED_TIME;
 import static org.apache.iotdb.db.qp.constant.SQLConstant.TIME_PATH;
 
 import java.io.File;
@@ -40,18 +38,18 @@ import org.antlr.v4.runtime.tree.TerminalNode;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.index.UnsupportedIndexTypeException;
 import org.apache.iotdb.db.exception.runtime.SQLParserException;
+import org.apache.iotdb.db.index.common.IndexType;
 import org.apache.iotdb.db.index.common.IndexUtils;
 import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.db.qp.constant.DatetimeUtils;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
-import org.apache.iotdb.db.qp.logical.RootOperator;
+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.DeleteDataOperator;
 import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
 import org.apache.iotdb.db.qp.logical.crud.FromOperator;
 import org.apache.iotdb.db.qp.logical.crud.InOperator;
 import org.apache.iotdb.db.qp.logical.crud.InsertOperator;
-import org.apache.iotdb.db.qp.logical.crud.QueryIndexOperator;
 import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
 import org.apache.iotdb.db.qp.logical.crud.UpdateOperator;
@@ -87,108 +85,127 @@ import org.apache.iotdb.db.qp.logical.sys.ShowStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTTLOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.TracingOperator;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AliasContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlignByDeviceClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlterUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AndExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AsClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AsElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AttributeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AttributeClausesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ConstantContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountDevicesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountNodesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateSnapshotContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DateExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeletePartitionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DropRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DropUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FillClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FlushContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FromClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FullMergeContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FullPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionAsClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionAsElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionCallContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantRoleToUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantWatermarkEmbeddingContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GroupByTimeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.IndexPredicateClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertColumnSpecContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertValuesSpecContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LastClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LimitClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllRoleOfUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllUserOfRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListPrivilegesRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListPrivilegesUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListRolePrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListUserPrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadConfigurationStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadFilesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.MergeContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.MoveFileContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.NodeNameContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.NodeNameWithoutStarContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OffsetClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OrExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OrderByTimeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PredicateContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PrefixPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PropertyContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PropertyValueContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RemoveFileContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeRoleFromUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeWatermarkEmbeddingContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RootOrIdContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SelectElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SelectStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SequenceClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetColContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowAllTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowChildPathsContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowDevicesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowMergeStatusContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowVersionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowWhereClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SlimitClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SoffsetClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.StringLiteralContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SuffixPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TagClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TimeIntervalContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TopClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TracingOffContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TracingOnContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TypeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UnsetTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UpdateStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.WhereClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AliasClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlignByDeviceClauseOrDisableAlignInSpecialLimitContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlignByDeviceStatementOrDisableAlignInSpecialClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlterClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlterTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlterUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AndExpressionContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AsClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AsElementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AttributeClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.AttributeClausesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ClearcacheContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ConstantContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CountDevicesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CountNodesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CountStorageGroupContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CountTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateIndexContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateSnapshotContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.CreateUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DateExpressionContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeletePartitionContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeleteStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeleteStorageGroupContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DeleteTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropIndexContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.DropUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FillClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FillStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FlushContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FromClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FullMergeContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FullPathContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FunctionAsClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FunctionAsElementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FunctionCallContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.FunctionElementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GrantRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GrantRoleToUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GrantUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GrantWatermarkEmbeddingContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByFillClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByFillStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByLevelClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByLevelStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByTimeClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.GroupByTimeStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.InClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.IndexPredicateClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.IndexWithClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.InsertColumnsSpecContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.InsertStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.InsertValuesSpecContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LastClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LastElementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LimitClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LimitStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListAllRoleOfUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListAllUserOfRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListPrivilegesRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListPrivilegesUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListRolePrivilegesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ListUserPrivilegesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LoadConfigurationStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LoadFilesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.LoadStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.MergeContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.MoveFileContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.NodeNameContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.NodeNameWithoutStarContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.OffsetClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.OrExpressionContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.OrderByTimeClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.OrderByTimeStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.PredicateContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.PrefixPathContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.PrivilegesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.PropertyContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.PropertyValueContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RemoveFileContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RevokeRoleContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RevokeRoleFromUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RevokeUserContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RevokeWatermarkEmbeddingContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.RootOrIdContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SelectElementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SelectStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SequenceClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SetColContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SetStorageGroupContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SetTTLStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowAllTTLStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowChildPathsContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowDevicesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowFlushTaskInfoContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowMergeStatusContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowStorageGroupContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowTTLStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowTimeseriesContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowVersionContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowWhereClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SingleStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SlimitClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SlimitStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SoffsetClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SpecialLimitStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.StringLiteralContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.SuffixPathContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TagClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TimeIntervalContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TracingOffContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TracingOnContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.TypeClauseContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.UnsetTTLStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.UpdateStatementContext;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser.WhereClauseContext;
 import org.apache.iotdb.db.query.executor.fill.IFill;
 import org.apache.iotdb.db.query.executor.fill.LinearFill;
 import org.apache.iotdb.db.query.executor.fill.PreviousFill;
@@ -199,332 +216,250 @@ import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.utils.StringContainer;
-import org.apache.iotdb.db.index.common.IndexType;
 
-/**
- * This class is a listener and you can get an operator which is a logical plan.
- */
-public class LogicalGenerator extends SqlBaseBaseListener {
+public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
 
-  private RootOperator initializedOperator = null;
-  private ZoneId zoneId;
-  private int operatorType;
-  private CreateTimeSeriesOperator createTimeSeriesOperator;
-  private AlterTimeSeriesOperator alterTimeSeriesOperator;
-  private InsertOperator insertOp;
-  private SelectOperator selectOp;
-  private UpdateOperator updateOp;
-  private QueryOperator queryOp;
-  private DeleteDataOperator deleteDataOp;
-  private CreateIndexOperator createIndexOp;
-  private QueryIndexOperator queryIndexOp;
-  private int indexTopK = NON_SET_TOP_K;
   private static final String DELETE_RANGE_ERROR_MSG =
-    "For delete statement, where clause can only contain atomic expressions like : " +
-      "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'";
-
+      "For delete statement, where clause can only contain atomic expressions like : " +
+          "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'";
+  private ZoneId zoneId;
+  QueryOperator queryOp;
 
-  LogicalGenerator(ZoneId zoneId) {
+  public void setZoneId(ZoneId zoneId) {
     this.zoneId = zoneId;
   }
 
-  RootOperator getLogicalPlan() {
-    return initializedOperator;
-  }
-
-  @Override
-  public void enterCountTimeseries(CountTimeseriesContext ctx) {
-    super.enterCountTimeseries(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    if (ctx.INT() != null) {
-      initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_NODE_TIMESERIES,
-          path, Integer.parseInt(ctx.INT().getText()));
-    } else {
-      initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_TIMESERIES,
-          path);
-    }
-  }
-
-  @Override
-  public void enterCountDevices(CountDevicesContext ctx) {
-    super.enterCountDevices(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_DEVICES, path);
-  }
-
   @Override
-  public void enterCountStorageGroup(CountStorageGroupContext ctx) {
-    super.enterCountStorageGroup(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_STORAGE_GROUP, path);
+  public Operator visitSingleStatement(SingleStatementContext ctx) {
+    return visit(ctx.statement());
   }
 
   @Override
-  public void enterFlush(FlushContext ctx) {
-    super.enterFlush(ctx);
-    FlushOperator flushOperator = new FlushOperator(SQLConstant.TOK_FLUSH);
-    if (ctx.booleanClause() != null) {
-      flushOperator.setSeq(Boolean.parseBoolean(ctx.booleanClause().getText()));
+  public Operator visitCreateTimeseries(CreateTimeseriesContext ctx) {
+    CreateTimeSeriesOperator createTimeSeriesOperator = new CreateTimeSeriesOperator(
+        SQLConstant.TOK_METADATA_CREATE);
+    createTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
+    if (ctx.alias() != null) {
+      createTimeSeriesOperator.setAlias(ctx.alias().ID().getText());
     }
-    if (ctx.prefixPath(0) != null) {
-      List<PartialPath> storageGroups = new ArrayList<>();
-      for (PrefixPathContext prefixPathContext : ctx.prefixPath()) {
-        storageGroups.add(parsePrefixPath(prefixPathContext));
-      }
-      flushOperator.setStorageGroupList(storageGroups);
+    if (ctx.attributeClauses() != null) {
+      parseAttributeClauses(ctx.attributeClauses(), createTimeSeriesOperator);
     }
-
-    initializedOperator = flushOperator;
+    return createTimeSeriesOperator;
   }
 
   @Override
-  public void enterTracingOn(TracingOnContext ctx) {
-    super.enterTracingOn(ctx);
-    initializedOperator = new TracingOperator(SQLConstant.TOK_TRACING, true);
+  public Operator visitDeleteTimeseries(DeleteTimeseriesContext ctx) {
+    List<PartialPath> deletePaths = new ArrayList<>();
+    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
+    for (PrefixPathContext prefixPath : prefixPaths) {
+      deletePaths.add(parsePrefixPath(prefixPath));
+    }
+    DeleteTimeSeriesOperator deleteTimeSeriesOperator = new DeleteTimeSeriesOperator(
+        SQLConstant.TOK_METADATA_DELETE);
+    deleteTimeSeriesOperator.setDeletePathList(deletePaths);
+    return deleteTimeSeriesOperator;
   }
 
   @Override
-  public void enterTracingOff(TracingOffContext ctx) {
-    super.enterTracingOff(ctx);
-    initializedOperator = new TracingOperator(SQLConstant.TOK_TRACING, false);
+  public Operator visitAlterTimeseries(AlterTimeseriesContext ctx) {
+    AlterTimeSeriesOperator alterTimeSeriesOperator = new AlterTimeSeriesOperator(
+        SQLConstant.TOK_METADATA_ALTER);
+    alterTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
+    parseAlterClause(ctx.alterClause(), alterTimeSeriesOperator);
+    return alterTimeSeriesOperator;
   }
 
   @Override
-  public void enterMerge(MergeContext ctx) {
-    super.enterMerge(ctx);
-    initializedOperator = new MergeOperator(SQLConstant.TOK_MERGE);
+  public Operator visitInsertStatement(InsertStatementContext ctx) {
+    InsertOperator insertOp = new InsertOperator(SQLConstant.TOK_INSERT);
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    selectOp.addSelectPath(parsePrefixPath(ctx.prefixPath()));
+    insertOp.setSelectOperator(selectOp);
+    parseInsertColumnSpec(ctx.insertColumnsSpec(), insertOp);
+    parseInsertValuesSpec(ctx.insertValuesSpec(), insertOp);
+    return insertOp;
   }
 
   @Override
-  public void enterFullMerge(FullMergeContext ctx) {
-    super.enterFullMerge(ctx);
-    initializedOperator = new MergeOperator(SQLConstant.TOK_FULL_MERGE);
+  public Operator visitUpdateStatement(UpdateStatementContext ctx) {
+    UpdateOperator updateOp = new UpdateOperator(SQLConstant.TOK_UPDATE);
+    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
+    fromOp.addPrefixTablePath(parsePrefixPath(ctx.prefixPath()));
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_QUERY);
+    for (SetColContext colContext : ctx.setClause().setCol()) {
+      parseSetCol(colContext, selectOp, updateOp);
+    }
+    FilterOperator whereOp = (FilterOperator) visit(ctx.whereClause());
+    updateOp.setFilterOperator(whereOp.getChildren().get(0));
+    updateOp.setSelectOperator(selectOp);
+    return updateOp;
   }
 
   @Override
-  public void enterClearcache(SqlBaseParser.ClearcacheContext ctx) {
-    super.enterClearcache(ctx);
-    initializedOperator = new ClearCacheOperator(SQLConstant.TOK_CLEAR_CACHE);
+  public Operator visitDeleteStatement(DeleteStatementContext ctx) {
+    DeleteDataOperator deleteDataOp = new DeleteDataOperator(SQLConstant.TOK_DELETE);
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
+    for (PrefixPathContext prefixPath : prefixPaths) {
+      PartialPath path = parsePrefixPath(prefixPath);
+      selectOp.addSelectPath(path);
+    }
+    deleteDataOp.setSelectOperator(selectOp);
+    if (ctx.whereClause() != null) {
+      FilterOperator whereOp = (FilterOperator) visit(ctx.whereClause());
+      deleteDataOp.setFilterOperator(whereOp.getChildren().get(0));
+      Pair<Long, Long> timeInterval = parseDeleteTimeInterval(deleteDataOp);
+      deleteDataOp.setStartTime(timeInterval.left);
+      deleteDataOp.setEndTime(timeInterval.right);
+    }
+    return deleteDataOp;
   }
 
   @Override
-  public void enterCountNodes(CountNodesContext ctx) {
-    super.enterCountNodes(ctx);
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_NODES,
-        parsePrefixPath(ctx.prefixPath()), Integer.parseInt(ctx.INT().getText()));
+  public Operator visitSetStorageGroup(SetStorageGroupContext ctx) {
+    SetStorageGroupOperator setStorageGroupOperator = new SetStorageGroupOperator(
+        SQLConstant.TOK_METADATA_SET_FILE_LEVEL);
+    PartialPath path = parsePrefixPath(ctx.prefixPath());
+    setStorageGroupOperator.setPath(path);
+    return setStorageGroupOperator;
   }
 
   @Override
-  public void enterShowDevices(ShowDevicesContext ctx) {
-    super.enterShowDevices(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
-          new PartialPath(SQLConstant.getSingleRootArray()));
+  public Operator visitDeleteStorageGroup(DeleteStorageGroupContext ctx) {
+    List<PartialPath> deletePaths = new ArrayList<>();
+    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
+    for (PrefixPathContext prefixPath : prefixPaths) {
+      deletePaths.add(parsePrefixPath(prefixPath));
     }
+    DeleteStorageGroupOperator deleteStorageGroupOperator = new DeleteStorageGroupOperator(
+        SQLConstant.TOK_METADATA_DELETE_FILE_LEVEL);
+    deleteStorageGroupOperator.setDeletePathList(deletePaths);
+    return deleteStorageGroupOperator;
   }
 
   @Override
-  public void enterShowChildPaths(ShowChildPathsContext ctx) {
-    super.enterShowChildPaths(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
-          new PartialPath(SQLConstant.getSingleRootArray()));
+  public Operator visitCreateIndex(CreateIndexContext ctx) {
+    CreateIndexOperator createIndexOp = new CreateIndexOperator(SQLConstant.TOK_CREATE_INDEX);
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
+    for (PrefixPathContext prefixPath : prefixPaths) {
+      PartialPath path = parsePrefixPath(prefixPath);
+      selectOp.addSelectPath(path);
     }
-  }
-
-  @Override
-  public void enterShowStorageGroup(ShowStorageGroupContext ctx) {
-    super.enterShowStorageGroup(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
-          new PartialPath(SQLConstant.getSingleRootArray()));
+    createIndexOp.setSelectOperator(selectOp);
+    parseIndexWithClause(ctx.indexWithClause(), createIndexOp);
+    FilterOperator whereOp;
+    if (ctx.whereClause() != null) {
+      whereOp = (FilterOperator) visit(ctx.whereClause());
+      createIndexOp.setFilterOperator(whereOp.getChildren().get(0));
+      long indexTime = parseCreateIndexFilter(createIndexOp);
+      createIndexOp.setTime(indexTime);
     }
+    return createIndexOp;
   }
 
-  @Override
-  public void enterLoadFiles(LoadFilesContext ctx) {
-    super.enterLoadFiles(ctx);
-    if (ctx.autoCreateSchema() != null) {
-      if (ctx.autoCreateSchema().INT() != null) {
-        initializedOperator = new LoadFilesOperator(
-            new File(removeStringQuote(ctx.stringLiteral().getText())),
-            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
-            Integer.parseInt(ctx.autoCreateSchema().INT().getText())
-        );
-      } else {
-        initializedOperator = new LoadFilesOperator(
-            new File(removeStringQuote(ctx.stringLiteral().getText())),
-            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
-            IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
-        );
-      }
-    } else {
-      initializedOperator = new LoadFilesOperator(
-          new File(removeStringQuote(ctx.stringLiteral().getText())),
-          true,
-          IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
-      );
+  /**
+   * for create index command, time should only have an end time.
+   *
+   * @param operator create index plan
+   */
+  private long parseCreateIndexFilter(CreateIndexOperator operator) {
+    FilterOperator filterOperator = operator.getFilterOperator();
+    if (filterOperator.getTokenIntType() != SQLConstant.GREATERTHAN
+        && filterOperator.getTokenIntType() != SQLConstant.GREATERTHANOREQUALTO) {
+      throw new SQLParserException(
+          "For create index command, where clause must be like : time > XXX or time >= XXX");
     }
-  }
-
-  @Override
-  public void enterMoveFile(MoveFileContext ctx) {
-    super.enterMoveFile(ctx);
-    initializedOperator = new MoveFileOperator(
-        new File(removeStringQuote(ctx.stringLiteral(0).getText())),
-        new File(removeStringQuote(ctx.stringLiteral(1).getText())));
-  }
-
-  @Override
-  public void enterRemoveFile(RemoveFileContext ctx) {
-    super.enterRemoveFile(ctx);
-    initializedOperator = new RemoveFileOperator(
-        new File(removeStringQuote(ctx.stringLiteral().getText())));
-  }
-
-  @Override
-  public void enterLoadConfigurationStatement(LoadConfigurationStatementContext ctx) {
-    super.enterLoadConfigurationStatement(ctx);
-    if (ctx.GLOBAL() != null) {
-      initializedOperator = new LoadConfigurationOperator(LoadConfigurationOperatorType.GLOBAL);
-    } else {
-      initializedOperator = new LoadConfigurationOperator(LoadConfigurationOperatorType.LOCAL);
+    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
+    if (filterOperator.getTokenIntType() == SQLConstant.LESSTHAN) {
+      time = time - 1;
     }
-
-  }
-
-  @Override
-  public void enterShowVersion(ShowVersionContext ctx) {
-    super.enterShowVersion(ctx);
-    initializedOperator = new ShowOperator(SQLConstant.TOK_VERSION);
+    return time;
   }
 
-  @Override
-  public void enterShowFlushTaskInfo(SqlBaseParser.ShowFlushTaskInfoContext ctx) {
-    super.enterShowFlushTaskInfo(ctx);
-    initializedOperator = new ShowOperator(SQLConstant.TOK_FLUSH_TASK_INFO);
-  }
+  public void parseIndexWithClause(IndexWithClauseContext ctx, CreateIndexOperator createIndexOp) {
+    IndexType indexType;
+    try {
+      indexType = IndexType.getIndexType(ctx.indexName.getText());
+    } catch (UnsupportedIndexTypeException e) {
+      throw new SQLParserException(ctx.indexName.getText());
+    }
 
-  @Override
-  public void enterShowTimeseries(ShowTimeseriesContext ctx) {
-    super.enterShowTimeseries(ctx);
-    boolean orderByHeat = ctx.LATEST() != null;
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
-          parsePrefixPath(ctx.prefixPath()), orderByHeat);
-    } else {
-      initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES, new PartialPath(SQLConstant.getSingleRootArray()),
-          orderByHeat);
+    List<PropertyContext> properties = ctx.property();
+    Map<String, String> props = new HashMap<>(properties.size(), 1);
+    if (ctx.property(0) != null) {
+      for (PropertyContext property : properties) {
+        String k = property.ID().getText().toUpperCase();
+        String v = property.propertyValue().getText().toUpperCase();
+        v = IndexUtils.removeQuotation(v);
+        props.put(k, v);
+      }
     }
+    createIndexOp.setIndexType(indexType);
+    createIndexOp.setProps(props);
   }
 
   @Override
-  public void enterCreateTimeseries(CreateTimeseriesContext ctx) {
-    super.enterCreateTimeseries(ctx);
-    createTimeSeriesOperator = new CreateTimeSeriesOperator(SQLConstant.TOK_METADATA_CREATE);
-    operatorType = SQLConstant.TOK_METADATA_CREATE;
-    createTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
+  public Operator visitDropIndex(DropIndexContext ctx) {
+    DropIndexOperator dropIndexOperator = new DropIndexOperator(SQLConstant.TOK_DROP_INDEX);
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
+    for (PrefixPathContext prefixPath : prefixPaths) {
+      PartialPath path = parsePrefixPath(prefixPath);
+      selectOp.addSelectPath(path);
+    }
+    dropIndexOperator.setSelectOperator(selectOp);
+    try {
+      dropIndexOperator.setIndexType(IndexType.getIndexType(ctx.indexName.getText()));
+    } catch (UnsupportedIndexTypeException e) {
+      throw new SQLParserException(ctx.indexName.getText());
+    }
+    return dropIndexOperator;
   }
 
   @Override
-  public void enterAlterTimeseries(SqlBaseParser.AlterTimeseriesContext ctx) {
-    super.enterAlterTimeseries(ctx);
-    alterTimeSeriesOperator = new AlterTimeSeriesOperator(SQLConstant.TOK_METADATA_ALTER);
-    operatorType = SQLConstant.TOK_METADATA_ALTER;
-    alterTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
+  public Operator visitMerge(MergeContext ctx) {
+    return new MergeOperator(SQLConstant.TOK_MERGE);
   }
 
   @Override
-  public void enterAlterClause(SqlBaseParser.AlterClauseContext ctx) {
-    super.enterAlterClause(ctx);
-    Map<String, String> alterMap = new HashMap<>();
-    // rename
-    if (ctx.RENAME() != null) {
-      alterTimeSeriesOperator.setAlterType(AlterType.RENAME);
-      alterMap.put(ctx.beforeName.getText(), ctx.currentName.getText());
-    } else if (ctx.SET() != null) {
-      // set
-      alterTimeSeriesOperator.setAlterType(AlterType.SET);
-      setMap(ctx, alterMap);
-    } else if (ctx.DROP() != null) {
-      // drop
-      alterTimeSeriesOperator.setAlterType(AlterType.DROP);
-      for (TerminalNode dropId : ctx.ID()) {
-        alterMap.put(dropId.getText(), null);
+  public Operator visitFlush(FlushContext ctx) {
+    FlushOperator flushOperator = new FlushOperator(SQLConstant.TOK_FLUSH);
+    if (ctx.booleanClause() != null) {
+      flushOperator.setSeq(Boolean.parseBoolean(ctx.booleanClause().getText()));
+    }
+    if (ctx.prefixPath(0) != null) {
+      List<PartialPath> storageGroups = new ArrayList<>();
+      for (PrefixPathContext prefixPathContext : ctx.prefixPath()) {
+        storageGroups.add(parsePrefixPath(prefixPathContext));
       }
-    } else if (ctx.TAGS() != null) {
-      // add tag
-      alterTimeSeriesOperator.setAlterType(AlterType.ADD_TAGS);
-      setMap(ctx, alterMap);
-    } else if (ctx.ATTRIBUTES() != null) {
-      // add attribute
-      alterTimeSeriesOperator.setAlterType(AlterType.ADD_ATTRIBUTES);
-      setMap(ctx, alterMap);
-    } else {
-      // upsert
-      alterTimeSeriesOperator.setAlterType(AlterType.UPSERT);
+      flushOperator.setStorageGroupList(storageGroups);
     }
-    alterTimeSeriesOperator.setAlterMap(alterMap);
-    initializedOperator = alterTimeSeriesOperator;
+    return flushOperator;
   }
 
-  private void setMap(SqlBaseParser.AlterClauseContext ctx, Map<String, String> alterMap) {
-    List<PropertyContext> tagsList = ctx.property();
-    if (ctx.property(0) != null) {
-      for (PropertyContext property : tagsList) {
-        String value;
-        if (property.propertyValue().stringLiteral() != null) {
-          value = removeStringQuote(property.propertyValue().getText());
-        } else {
-          value = property.propertyValue().getText();
-        }
-        alterMap.put(property.ID().getText(), value);
-      }
-    }
+  @Override
+  public Operator visitFullMerge(FullMergeContext ctx) {
+    return new MergeOperator(SQLConstant.TOK_FULL_MERGE);
   }
 
   @Override
-  public void enterAlias(AliasContext ctx) {
-    super.enterAlias(ctx);
-    createTimeSeriesOperator.setAlias(ctx.ID().getText());
+  public Operator visitClearcache(ClearcacheContext ctx) {
+    return new ClearCacheOperator(SQLConstant.TOK_CLEAR_CACHE);
   }
 
   @Override
-  public void enterCreateUser(CreateUserContext ctx) {
-    super.enterCreateUser(ctx);
+  public Operator visitCreateUser(CreateUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
         AuthorOperator.AuthorType.CREATE_USER);
     authorOperator.setUserName(ctx.ID().getText());
     authorOperator.setPassWord(removeStringQuote(ctx.password.getText()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_CREATE;
-  }
-
-  @Override
-  public void enterCreateRole(CreateRoleContext ctx) {
-    super.enterCreateRole(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
-        AuthorOperator.AuthorType.CREATE_ROLE);
-    authorOperator.setRoleName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_CREATE;
+    return authorOperator;
   }
 
   @Override
-  public void enterAlterUser(AlterUserContext ctx) {
-    super.enterAlterUser(ctx);
+  public Operator visitAlterUser(AlterUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_UPDATE_USER,
         AuthorOperator.AuthorType.UPDATE_USER);
     if (ctx.ID() != null) {
@@ -533,103 +468,93 @@ public class LogicalGenerator extends SqlBaseBaseListener {
       authorOperator.setUserName(ctx.ROOT().getText());
     }
     authorOperator.setNewPassword(removeStringQuote(ctx.password.getText()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_UPDATE_USER;
+    return authorOperator;
   }
 
   @Override
-  public void enterDropUser(DropUserContext ctx) {
-    super.enterDropUser(ctx);
+  public Operator visitDropUser(DropUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_DROP,
         AuthorOperator.AuthorType.DROP_USER);
     authorOperator.setUserName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_DROP;
+    return authorOperator;
+  }
+
+  @Override
+  public Operator visitCreateRole(CreateRoleContext ctx) {
+    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
+        AuthorOperator.AuthorType.CREATE_ROLE);
+    authorOperator.setRoleName(ctx.ID().getText());
+    return authorOperator;
   }
 
   @Override
-  public void enterDropRole(DropRoleContext ctx) {
-    super.enterDropRole(ctx);
+  public Operator visitDropRole(DropRoleContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_DROP,
         AuthorOperator.AuthorType.DROP_ROLE);
     authorOperator.setRoleName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_DROP;
+    return authorOperator;
   }
 
   @Override
-  public void enterGrantUser(GrantUserContext ctx) {
-    super.enterGrantUser(ctx);
+  public Operator visitGrantUser(GrantUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorOperator.AuthorType.GRANT_USER);
     authorOperator.setUserName(ctx.ID().getText());
     authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
     authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterGrantRole(GrantRoleContext ctx) {
-    super.enterGrantRole(ctx);
+  public Operator visitGrantRole(GrantRoleContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorType.GRANT_ROLE);
     authorOperator.setRoleName(ctx.ID().getText());
     authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
     authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterRevokeUser(RevokeUserContext ctx) {
-    super.enterRevokeUser(ctx);
+  public Operator visitRevokeUser(RevokeUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorType.REVOKE_USER);
     authorOperator.setUserName(ctx.ID().getText());
     authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
     authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterRevokeRole(RevokeRoleContext ctx) {
-    super.enterRevokeRole(ctx);
+  public Operator visitRevokeRole(RevokeRoleContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorType.REVOKE_ROLE);
     authorOperator.setRoleName(ctx.ID().getText());
     authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
     authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterGrantRoleToUser(GrantRoleToUserContext ctx) {
-    super.enterGrantRoleToUser(ctx);
+  public Operator visitGrantRoleToUser(GrantRoleToUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorOperator.AuthorType.GRANT_ROLE_TO_USER);
     authorOperator.setRoleName(ctx.roleName.getText());
     authorOperator.setUserName(ctx.userName.getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterRevokeRoleFromUser(RevokeRoleFromUserContext ctx) {
-    super.enterRevokeRoleFromUser(ctx);
+  public Operator visitRevokeRoleFromUser(RevokeRoleFromUserContext ctx) {
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
         AuthorType.REVOKE_ROLE_FROM_USER);
     authorOperator.setRoleName(ctx.roleName.getText());
     authorOperator.setUserName(ctx.userName.getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
+    return authorOperator;
   }
 
   @Override
-  public void enterLoadStatement(LoadStatementContext ctx) {
-    super.enterLoadStatement(ctx);
+  public Operator visitLoadStatement(LoadStatementContext ctx) {
     if (ctx.prefixPath().nodeName().size() < 3) {
       throw new SQLParserException("data load command: child count < 3\n");
     }
@@ -641,898 +566,950 @@ public class LogicalGenerator extends SqlBaseBaseListener {
     for (NodeNameContext nodeName : nodeNames) {
       sc.addTail(nodeName.getText());
     }
-    initializedOperator = new LoadDataOperator(SQLConstant.TOK_DATALOAD,
+    return new LoadDataOperator(SQLConstant.TOK_DATALOAD,
         removeStringQuote(csvPath),
         sc.toString());
-    operatorType = SQLConstant.TOK_DATALOAD;
   }
 
   @Override
-  public void enterGrantWatermarkEmbedding(GrantWatermarkEmbeddingContext ctx) {
-    super.enterGrantWatermarkEmbedding(ctx);
+  public Operator visitGrantWatermarkEmbedding(GrantWatermarkEmbeddingContext ctx) {
     List<RootOrIdContext> rootOrIdList = ctx.rootOrId();
     List<String> users = new ArrayList<>();
     for (RootOrIdContext rootOrId : rootOrIdList) {
       users.add(rootOrId.getText());
     }
-    initializedOperator = new DataAuthOperator(SQLConstant.TOK_GRANT_WATERMARK_EMBEDDING, users);
+    return new DataAuthOperator(SQLConstant.TOK_GRANT_WATERMARK_EMBEDDING, users);
   }
 
   @Override
-  public void enterRevokeWatermarkEmbedding(RevokeWatermarkEmbeddingContext ctx) {
-    super.enterRevokeWatermarkEmbedding(ctx);
+  public Operator visitRevokeWatermarkEmbedding(RevokeWatermarkEmbeddingContext ctx) {
     List<RootOrIdContext> rootOrIdList = ctx.rootOrId();
     List<String> users = new ArrayList<>();
     for (RootOrIdContext rootOrId : rootOrIdList) {
       users.add(rootOrId.getText());
     }
-    initializedOperator = new DataAuthOperator(SQLConstant.TOK_REVOKE_WATERMARK_EMBEDDING, users);
-    operatorType = SQLConstant.TOK_REVOKE_WATERMARK_EMBEDDING;
+    return new DataAuthOperator(SQLConstant.TOK_REVOKE_WATERMARK_EMBEDDING, users);
   }
 
   @Override
-  public void enterListUser(ListUserContext ctx) {
-    super.enterListUser(ctx);
-    initializedOperator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_USER);
-    operatorType = SQLConstant.TOK_LIST;
+  public Operator visitListUser(ListUserContext ctx) {
+    return new AuthorOperator(SQLConstant.TOK_LIST, AuthorOperator.AuthorType.LIST_USER);
   }
 
   @Override
-  public void enterListRole(ListRoleContext ctx) {
-    super.enterListRole(ctx);
-    initializedOperator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_ROLE);
-    operatorType = SQLConstant.TOK_LIST;
+  public Operator visitListRole(ListRoleContext ctx) {
+    return new AuthorOperator(SQLConstant.TOK_LIST, AuthorOperator.AuthorType.LIST_ROLE);
   }
 
   @Override
-  public void enterListPrivilegesUser(ListPrivilegesUserContext ctx) {
-    super.enterListPrivilegesUser(ctx);
+  public Operator visitListPrivilegesUser(ListPrivilegesUserContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
     operator.setUserName(ctx.rootOrId().getText());
     operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterListPrivilegesRole(ListPrivilegesRoleContext ctx) {
-    super.enterListPrivilegesRole(ctx);
+  public Operator visitListPrivilegesRole(ListPrivilegesRoleContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
     operator.setRoleName((ctx.ID().getText()));
     operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterListUserPrivileges(ListUserPrivilegesContext ctx) {
-    super.enterListUserPrivileges(ctx);
+  public Operator visitListUserPrivileges(ListUserPrivilegesContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
     operator.setUserName(ctx.rootOrId().getText());
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterListRolePrivileges(ListRolePrivilegesContext ctx) {
-    super.enterListRolePrivileges(ctx);
+  public Operator visitListRolePrivileges(ListRolePrivilegesContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
     operator.setRoleName(ctx.ID().getText());
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterListAllRoleOfUser(ListAllRoleOfUserContext ctx) {
-    super.enterListAllRoleOfUser(ctx);
+  public Operator visitListAllRoleOfUser(ListAllRoleOfUserContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_USER_ROLES);
-    initializedOperator = operator;
     operator.setUserName(ctx.rootOrId().getText());
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterListAllUserOfRole(ListAllUserOfRoleContext ctx) {
-    super.enterListAllUserOfRole(ctx);
+  public Operator visitListAllUserOfRole(ListAllUserOfRoleContext ctx) {
     AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
         AuthorOperator.AuthorType.LIST_ROLE_USERS);
-    initializedOperator = operator;
     operator.setRoleName((ctx.ID().getText()));
-    operatorType = SQLConstant.TOK_LIST;
+    return operator;
   }
 
   @Override
-  public void enterSetTTLStatement(SetTTLStatementContext ctx) {
-    super.enterSetTTLStatement(ctx);
+  public Operator visitSetTTLStatement(SetTTLStatementContext ctx) {
     SetTTLOperator operator = new SetTTLOperator(SQLConstant.TOK_SET);
     operator.setStorageGroup(parsePrefixPath(ctx.prefixPath()));
     operator.setDataTTL(Long.parseLong(ctx.INT().getText()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_SET;
+    return operator;
   }
 
   @Override
-  public void enterUnsetTTLStatement(UnsetTTLStatementContext ctx) {
-    super.enterUnsetTTLStatement(ctx);
+  public Operator visitUnsetTTLStatement(UnsetTTLStatementContext ctx) {
     SetTTLOperator operator = new SetTTLOperator(SQLConstant.TOK_UNSET);
     operator.setStorageGroup(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_UNSET;
+    return operator;
   }
 
   @Override
-  public void enterShowTTLStatement(ShowTTLStatementContext ctx) {
-    super.enterShowTTLStatement(ctx);
+  public Operator visitShowTTLStatement(ShowTTLStatementContext ctx) {
     List<PartialPath> storageGroups = new ArrayList<>();
     List<PrefixPathContext> prefixPathList = ctx.prefixPath();
     for (PrefixPathContext prefixPath : prefixPathList) {
       storageGroups.add(parsePrefixPath(prefixPath));
     }
-    initializedOperator = new ShowTTLOperator(storageGroups);
+    return new ShowTTLOperator(storageGroups);
   }
 
   @Override
-  public void enterShowAllTTLStatement(ShowAllTTLStatementContext ctx) {
-    super.enterShowAllTTLStatement(ctx);
+  public Operator visitShowAllTTLStatement(ShowAllTTLStatementContext ctx) {
     List<PartialPath> storageGroups = new ArrayList<>();
-    initializedOperator = new ShowTTLOperator(storageGroups);
+    return new ShowTTLOperator(storageGroups);
   }
 
-  private String[] parsePrivilege(PrivilegesContext ctx) {
-    List<StringLiteralContext> privilegeList = ctx.stringLiteral();
-    List<String> privileges = new ArrayList<>();
-    for (StringLiteralContext privilege : privilegeList) {
-      privileges.add(removeStringQuote(privilege.getText()));
-    }
-    return privileges.toArray(new String[0]);
+  @Override
+  public Operator visitShowFlushTaskInfo(ShowFlushTaskInfoContext ctx) {
+    return new ShowOperator(SQLConstant.TOK_FLUSH_TASK_INFO);
   }
 
-  private String removeStringQuote(String src) {
-    if (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'') {
-      return src.substring(1, src.length() - 1);
-    } else if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
-      return src.substring(1, src.length() - 1);
-    } else {
-      throw new SQLParserException("error format for string with quote:" + src);
-    }
+  @Override
+  public Operator visitShowVersion(ShowVersionContext ctx) {
+    return new ShowOperator(SQLConstant.TOK_VERSION);
   }
 
   @Override
-  public void enterDeleteTimeseries(DeleteTimeseriesContext ctx) {
-    super.enterDeleteTimeseries(ctx);
-    List<PartialPath> deletePaths = new ArrayList<>();
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      deletePaths.add(parsePrefixPath(prefixPath));
-    }
-    DeleteTimeSeriesOperator deleteTimeSeriesOperator = new DeleteTimeSeriesOperator(
-        SQLConstant.TOK_METADATA_DELETE);
-    deleteTimeSeriesOperator.setDeletePathList(deletePaths);
-    initializedOperator = deleteTimeSeriesOperator;
-    operatorType = SQLConstant.TOK_METADATA_DELETE;
+  public Operator visitShowTimeseries(ShowTimeseriesContext ctx) {
+    boolean orderByHeat = ctx.LATEST() != null;
+    ShowTimeSeriesOperator showTimeSeriesOperator;
+    if (ctx.prefixPath() != null) {
+      showTimeSeriesOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
+          parsePrefixPath(ctx.prefixPath()), orderByHeat);
+    } else {
+      showTimeSeriesOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
+          new PartialPath(SQLConstant.getSingleRootArray()),
+          orderByHeat);
+    }
+    if (ctx.showWhereClause() != null) {
+      parseShowWhereClause(ctx.showWhereClause(), showTimeSeriesOperator);
+    }
+    if (ctx.limitClause() != null) {
+      parseLimitClause(ctx.limitClause(), showTimeSeriesOperator);
+    }
+    return showTimeSeriesOperator;
   }
 
   @Override
-  public void enterSetStorageGroup(SetStorageGroupContext ctx) {
-    super.enterSetStorageGroup(ctx);
-    SetStorageGroupOperator setStorageGroupOperator = new SetStorageGroupOperator(
-        SQLConstant.TOK_METADATA_SET_FILE_LEVEL);
-    PartialPath path = parsePrefixPath(ctx.prefixPath());
-    setStorageGroupOperator.setPath(path);
-    initializedOperator = setStorageGroupOperator;
-    operatorType = SQLConstant.TOK_METADATA_SET_FILE_LEVEL;
+  public Operator visitShowStorageGroup(ShowStorageGroupContext ctx) {
+    if (ctx.prefixPath() != null) {
+      return new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
+          parsePrefixPath(ctx.prefixPath()));
+    } else {
+      return new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
+          new PartialPath(SQLConstant.getSingleRootArray()));
+    }
   }
 
   @Override
-  public void enterDeleteStorageGroup(DeleteStorageGroupContext ctx) {
-    super.enterDeleteStorageGroup(ctx);
-    List<PartialPath> deletePaths = new ArrayList<>();
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      deletePaths.add(parsePrefixPath(prefixPath));
+  public Operator visitShowChildPaths(ShowChildPathsContext ctx) {
+    if (ctx.prefixPath() != null) {
+      return new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
+          parsePrefixPath(ctx.prefixPath()));
+    } else {
+      return new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
+          new PartialPath(SQLConstant.getSingleRootArray()));
     }
-    DeleteStorageGroupOperator deleteStorageGroupOperator = new DeleteStorageGroupOperator(
-        SQLConstant.TOK_METADATA_DELETE_FILE_LEVEL);
-    deleteStorageGroupOperator.setDeletePathList(deletePaths);
-    initializedOperator = deleteStorageGroupOperator;
-    operatorType = SQLConstant.TOK_METADATA_DELETE_FILE_LEVEL;
   }
 
   @Override
-  public void enterDeleteStatement(DeleteStatementContext ctx) {
-    super.enterDeleteStatement(ctx);
-    operatorType = SQLConstant.TOK_DELETE;
-    deleteDataOp = new DeleteDataOperator(SQLConstant.TOK_DELETE);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
+  public Operator visitShowDevices(ShowDevicesContext ctx) {
+    if (ctx.prefixPath() != null) {
+      return new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
+          parsePrefixPath(ctx.prefixPath()));
+    } else {
+      return new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
+          new PartialPath(SQLConstant.getSingleRootArray()));
     }
-    deleteDataOp.setSelectOperator(selectOp);
-    initializedOperator = deleteDataOp;
   }
 
   @Override
-  public void enterDisableAlign(SqlBaseParser.DisableAlignContext ctx) {
-    super.enterDisableAlign(ctx);
-    queryOp.setAlignByTime(false);
+  public Operator visitShowMergeStatus(ShowMergeStatusContext ctx) {
+    return new ShowMergeStatusOperator(SQLConstant.TOK_SHOW_MERGE_STATUS);
   }
 
-  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
   @Override
-  public void enterGroupByFillClause(SqlBaseParser.GroupByFillClauseContext ctx) {
-    super.enterGroupByFillClause(ctx);
-    queryOp.setGroupByTime(true);
-    queryOp.setFill(true);
-    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
-
-    // parse timeUnit
-    queryOp.setUnit(parseDuration(ctx.DURATION().getText()));
-    queryOp.setSlidingStep(queryOp.getUnit());
-
-    parseTimeInterval(ctx.timeInterval());
-
-    List<TypeClauseContext> list = ctx.typeClause();
-    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
-    for (TypeClauseContext typeClause : list) {
-      // group by fill doesn't support linear fill
-      if (typeClause.linearClause() != null) {
-        throw new SQLParserException("group by fill doesn't support linear fill");
-      }
-      // all type use the same fill way
-      if (SQLConstant.ALL.equalsIgnoreCase(typeClause.dataType().getText())) {
-        IFill fill;
-        if (typeClause.previousUntilLastClause() != null) {
-          long preRange;
-          if (typeClause.previousUntilLastClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousUntilLastClause().DURATION().getText());
-          } else {
-            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-          }
-          fill = new PreviousFill(preRange, true);
-        } else {
-          long preRange;
-          if (typeClause.previousClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousClause().DURATION().getText());
-          } else {
-            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-          }
-          fill = new PreviousFill(preRange);
-        }
-        for (TSDataType tsDataType : TSDataType.values()) {
-          fillTypes.put(tsDataType, fill.copy());
-        }
-        break;
-      } else {
-        parseTypeClause(typeClause, fillTypes);
-      }
-    }
-    queryOp.setFill(true);
-    queryOp.setFillTypes(fillTypes);
+  public Operator visitTracingOn(TracingOnContext ctx) {
+    return new TracingOperator(SQLConstant.TOK_TRACING, true);
   }
 
-  private void parseTimeInterval(TimeIntervalContext timeInterval) {
-    long startTime;
-    long endTime;
-    if (timeInterval.timeValue(0).INT() != null) {
-      startTime = Long.parseLong(timeInterval.timeValue(0).INT().getText());
-    } else if (timeInterval.timeValue(0).dateExpression() != null) {
-      startTime = parseDateExpression(timeInterval.timeValue(0).dateExpression());
-    } else {
-      startTime = parseTimeFormat(timeInterval.timeValue(0).dateFormat().getText());
-    }
-    if (timeInterval.timeValue(1).INT() != null) {
-      endTime = Long.parseLong(timeInterval.timeValue(1).INT().getText());
-    } else if (timeInterval.timeValue(1).dateExpression() != null) {
-      endTime = parseDateExpression(timeInterval.timeValue(1).dateExpression());
-    } else {
-      endTime = parseTimeFormat(timeInterval.timeValue(1).dateFormat().getText());
-    }
-
-    queryOp.setStartTime(startTime);
-    queryOp.setEndTime(endTime);
-    if (startTime >= endTime) {
-      throw new SQLParserException("start time should be smaller than endTime in GroupBy");
-    }
+  @Override
+  public Operator visitTracingOff(TracingOffContext ctx) {
+    return new TracingOperator(SQLConstant.TOK_TRACING, false);
   }
 
   @Override
-  public void enterGroupByTimeClause(GroupByTimeClauseContext ctx) {
-    super.enterGroupByTimeClause(ctx);
-
-    queryOp.setGroupByTime(true);
-    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
-    // parse timeUnit
-    queryOp.setUnit(parseDuration(ctx.DURATION(0).getText()));
-    queryOp.setSlidingStep(queryOp.getUnit());
-    // parse sliding step
-    if (ctx.DURATION().size() == 2) {
-      queryOp.setSlidingStep(parseDuration(ctx.DURATION(1).getText()));
-      if (queryOp.getSlidingStep() < queryOp.getUnit()) {
-        throw new SQLParserException(
-            "The third parameter sliding step shouldn't be smaller than the second parameter time interval.");
-      }
-    }
-
-    parseTimeInterval(ctx.timeInterval());
-
+  public Operator visitCountTimeseries(CountTimeseriesContext ctx) {
+    PrefixPathContext pathContext = ctx.prefixPath();
+    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext)
+        : new PartialPath(SQLConstant.getSingleRootArray()));
     if (ctx.INT() != null) {
-      queryOp.setGroupByLevel(true);
-      queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
+      return new CountOperator(SQLConstant.TOK_COUNT_NODE_TIMESERIES,
+          path, Integer.parseInt(ctx.INT().getText()));
+    } else {
+      return new CountOperator(SQLConstant.TOK_COUNT_TIMESERIES,
+          path);
     }
   }
 
   @Override
-  public void enterGroupByLevelClause(SqlBaseParser.GroupByLevelClauseContext ctx) {
-    super.enterGroupByLevelClause(ctx);
-    queryOp.setGroupByLevel(true);
+  public Operator visitCountDevices(CountDevicesContext ctx) {
+    PrefixPathContext pathContext = ctx.prefixPath();
+    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext)
+        : new PartialPath(SQLConstant.getSingleRootArray()));
+    return new CountOperator(SQLConstant.TOK_COUNT_DEVICES, path);
+  }
 
-    queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
+  @Override
+  public Operator visitCountStorageGroup(CountStorageGroupContext ctx) {
+    PrefixPathContext pathContext = ctx.prefixPath();
+    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext)
+        : new PartialPath(SQLConstant.getSingleRootArray()));
+    return new CountOperator(SQLConstant.TOK_COUNT_STORAGE_GROUP, path);
   }
 
   @Override
-  public void enterFillClause(FillClauseContext ctx) {
-    super.enterFillClause(ctx);
-    FilterOperator filterOperator = queryOp.getFilterOperator();
-    if (!filterOperator.isLeaf() || filterOperator.getTokenIntType() != SQLConstant.EQUAL) {
-      throw new SQLParserException("Only \"=\" can be used in fill function");
-    }
-    List<TypeClauseContext> list = ctx.typeClause();
-    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
-    for (TypeClauseContext typeClause : list) {
-      parseTypeClause(typeClause, fillTypes);
-    }
-    queryOp.setFill(true);
-    queryOp.setFillTypes(fillTypes);
+  public Operator visitCountNodes(CountNodesContext ctx) {
+    return new CountOperator(SQLConstant.TOK_COUNT_NODES,
+        parsePrefixPath(ctx.prefixPath()), Integer.parseInt(ctx.INT().getText()));
   }
 
-  private void parseTypeClause(TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) {
-    TSDataType dataType = parseType(ctx.dataType().getText());
-    if (ctx.linearClause() != null && dataType == TSDataType.TEXT) {
-      throw new SQLParserException(String.format("type %s cannot use %s fill function"
-          , dataType, ctx.linearClause().LINEAR().getText()));
+  @Override
+  public Operator visitLoadConfigurationStatement(LoadConfigurationStatementContext ctx) {
+    if (ctx.GLOBAL() != null) {
+      return new LoadConfigurationOperator(LoadConfigurationOperatorType.GLOBAL);
+    } else {
+      return new LoadConfigurationOperator(LoadConfigurationOperatorType.LOCAL);
     }
+  }
 
-    int defaultFillInterval = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-
-    if (ctx.linearClause() != null) {  // linear
-      if (ctx.linearClause().DURATION(0) != null) {
-        long beforeRange = parseDuration(ctx.linearClause().DURATION(0).getText());
-        long afterRange = parseDuration(ctx.linearClause().DURATION(1).getText());
-        fillTypes.put(dataType, new LinearFill(beforeRange, afterRange));
-      } else {
-        fillTypes.put(dataType, new LinearFill(defaultFillInterval, defaultFillInterval));
-      }
-    } else if (ctx.previousClause() != null) { // previous
-      if (ctx.previousClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousClause().DURATION().getText());
-        fillTypes.put(dataType, new PreviousFill(preRange));
-      } else {
-        fillTypes.put(dataType, new PreviousFill(defaultFillInterval));
-      }
-    } else { // previous until last
-      if (ctx.previousUntilLastClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousUntilLastClause().DURATION().getText());
-        fillTypes.put(dataType, new PreviousFill(preRange, true));
+  @Override
+  public Operator visitLoadFiles(LoadFilesContext ctx) {
+    if (ctx.autoCreateSchema() != null) {
+      if (ctx.autoCreateSchema().INT() != null) {
+        return new LoadFilesOperator(
+            new File(removeStringQuote(ctx.stringLiteral().getText())),
+            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
+            Integer.parseInt(ctx.autoCreateSchema().INT().getText())
+        );
       } else {
-        fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true));
+        return new LoadFilesOperator(
+            new File(removeStringQuote(ctx.stringLiteral().getText())),
+            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
+            IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
+        );
       }
+    } else {
+      return new LoadFilesOperator(
+          new File(removeStringQuote(ctx.stringLiteral().getText())),
+          true,
+          IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
+      );
     }
   }
 
   @Override
-  public void enterAlignByDeviceClause(AlignByDeviceClauseContext ctx) {
-    super.enterAlignByDeviceClause(ctx);
-    queryOp.setAlignByDevice(true);
+  public Operator visitRemoveFile(RemoveFileContext ctx) {
+    return new RemoveFileOperator(new File(removeStringQuote(ctx.stringLiteral().getText())));
   }
 
-  /**
-   * parse datatype node.
-   */
-  private TSDataType parseType(String datatype) {
-    String type = datatype.toLowerCase();
-    switch (type) {
-      case "int32":
-        return TSDataType.INT32;
-      case "int64":
-        return TSDataType.INT64;
-      case "float":
-        return TSDataType.FLOAT;
-      case "double":
-        return TSDataType.DOUBLE;
-      case "boolean":
-        return TSDataType.BOOLEAN;
-      case "text":
-        return TSDataType.TEXT;
-      default:
-        throw new SQLParserException("not a valid fill type : " + type);
-    }
+  @Override
+  public Operator visitMoveFile(MoveFileContext ctx) {
+    return new MoveFileOperator(
+        new File(removeStringQuote(ctx.stringLiteral(0).getText())),
+        new File(removeStringQuote(ctx.stringLiteral(1).getText())));
   }
 
   @Override
-  public void enterLimitClause(LimitClauseContext ctx) {
-    super.enterLimitClause(ctx);
-    int limit;
-    try {
-      limit = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException("Out of range. LIMIT <N>: N should be Int32.");
-    }
-    if (limit <= 0) {
-      throw new SQLParserException("LIMIT <N>: N should be greater than 0.");
-    }
-    if (initializedOperator instanceof ShowTimeSeriesOperator) {
-      ((ShowTimeSeriesOperator) initializedOperator).setLimit(limit);
-    } else {
-      queryOp.setRowLimit(limit);
+  public Operator visitDeletePartition(DeletePartitionContext ctx) {
+    DeletePartitionOperator deletePartitionOperator = new DeletePartitionOperator(
+        SQLConstant.TOK_DELETE_PARTITION);
+    deletePartitionOperator.setStorageGroupName(parsePrefixPath(ctx.prefixPath()));
+    Set<Long> idSet = new HashSet<>();
+    for (TerminalNode terminalNode : ctx.INT()) {
+      idSet.add(Long.parseLong(terminalNode.getText()));
     }
+    deletePartitionOperator.setPartitionIds(idSet);
+    return deletePartitionOperator;
   }
 
   @Override
-  public void enterOffsetClause(OffsetClauseContext ctx) {
-    super.enterOffsetClause(ctx);
-    int offset;
-    try {
-      offset = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32.");
+  public Operator visitCreateSnapshot(CreateSnapshotContext ctx) {
+    return new CreateSnapshotOperator(SQLConstant.TOK_CREATE_SCHEMA_SNAPSHOT);
+  }
+
+  @Override
+  public Operator visitSelectStatement(SelectStatementContext ctx) {
+    queryOp = new QueryOperator(SQLConstant.TOK_QUERY);
+    SelectOperator selectOp = (SelectOperator) visit(ctx.selectElements());
+    queryOp.setSelectOperator(selectOp);
+    FromOperator fromOp = (FromOperator) visit(ctx.fromClause());
+    queryOp.setFromOperator(fromOp);
+    if (ctx.topClause() != null) {
+      Map<String, Object> props = new HashMap<>();
+      int top = Integer.parseInt(ctx.topClause().INT().getText());
+      if (top < 0) {
+        throw new SQLParserException("TOP <N>: N should be greater than 0.");
+      }
+      props.put(TOP_K, top);
+      queryOp.setProps(props);
     }
-    if (offset < 0) {
-      throw new SQLParserException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
+    if (ctx.whereClause() != null) {
+      Operator operator = visit(ctx.whereClause());
+      if (operator instanceof FilterOperator) {
+        FilterOperator whereOp = (FilterOperator) operator;
+        queryOp.setFilterOperator(whereOp.getChildren().get(0));
+      }
     }
-    if (initializedOperator instanceof ShowTimeSeriesOperator) {
-      ((ShowTimeSeriesOperator) initializedOperator).setOffset(offset);
-    } else {
-      queryOp.setRowOffset(offset);
+    if (ctx.specialClause() != null) {
+      visit(ctx.specialClause());
     }
+    return queryOp;
   }
 
   @Override
-  public void enterOrderByTimeClause(OrderByTimeClauseContext ctx) {
-    super.enterOrderByTimeClause(ctx);
-    queryOp.setColumn(ctx.TIME().getText());
-    if (ctx.DESC() != null) {
-      queryOp.setAscending(false);
+  public Operator visitFunctionElement(FunctionElementContext ctx) {
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<FunctionCallContext> functionCallContextList = ctx.functionCall();
+    for (FunctionCallContext functionCallContext : functionCallContextList) {
+      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
+      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
     }
+    return selectOp;
   }
 
   @Override
-  public void enterSlimitClause(SlimitClauseContext ctx) {
-    super.enterSlimitClause(ctx);
-    int slimit;
-    try {
-      slimit = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. SLIMIT <SN>: SN should be Int32.");
-    }
-    if (slimit <= 0) {
-      throw new SQLParserException("SLIMIT <SN>: SN should be greater than 0.");
+  public Operator visitLastElement(LastElementContext ctx) {
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    selectOp.setLastQuery();
+    LastClauseContext lastClauseContext = ctx.lastClause();
+    if (lastClauseContext.asClause().size() != 0) {
+      parseAsClause(lastClauseContext.asClause(), selectOp);
+    } else {
+      List<SuffixPathContext> suffixPaths = lastClauseContext.suffixPath();
+      for (SuffixPathContext suffixPath : suffixPaths) {
+        PartialPath path = parseSuffixPath(suffixPath);
+        selectOp.addSelectPath(path);
+      }
     }
-    queryOp.setSeriesLimit(slimit);
+    return selectOp;
   }
 
   @Override
-  public void enterSoffsetClause(SoffsetClauseContext ctx) {
-    super.enterSoffsetClause(ctx);
-    int soffset;
-    try {
-      soffset = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
-    }
-    if (soffset < 0) {
-      throw new SQLParserException(
-          "SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
-    }
-    queryOp.setSeriesOffset(soffset);
+  public Operator visitAsElement(AsElementContext ctx) {
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    parseAsClause(ctx.asClause(), selectOp);
+    return selectOp;
   }
 
   @Override
-  public void enterInsertColumnSpec(InsertColumnSpecContext ctx) {
-    super.enterInsertColumnSpec(ctx);
-    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
-    List<String> measurementList = new ArrayList<>();
-    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
-      String measurement = nodeNameWithoutStar.getText();
-      measurementList.add(measurement);
+  public Operator visitFunctionAsElement(FunctionAsElementContext ctx) {
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<FunctionAsClauseContext> functionAsClauseContexts = ctx.functionAsClause();
+    for (FunctionAsClauseContext functionAsClauseContext : functionAsClauseContexts) {
+      FunctionCallContext functionCallContext = functionAsClauseContext.functionCall();
+      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
+      if (functionAsClauseContext.ID() != null) {
+        path.setTsAlias(functionAsClauseContext.ID().toString());
+      }
+      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
     }
-    insertOp.setMeasurementList(measurementList.toArray(new String[0]));
+    return selectOp;
   }
 
-  @Override
-  public void enterInsertValuesSpec(InsertValuesSpecContext ctx) {
-    super.enterInsertValuesSpec(ctx);
-    long timestamp;
-    if (ctx.dateFormat() != null) {
-      timestamp = parseTimeFormat(ctx.dateFormat().getText());
-    } else {
-      timestamp = Long.parseLong(ctx.INT().getText());
-    }
-    insertOp.setTime(timestamp);
-    List<String> valueList = new ArrayList<>();
-    List<ConstantContext> values = ctx.constant();
-    for (ConstantContext value : values) {
-      valueList.add(value.getText());
+  public void parseAsClause(List<AsClauseContext> asClauseContexts, SelectOperator selectOp) {
+    for (AsClauseContext asClauseContext : asClauseContexts) {
+      PartialPath path = parseSuffixPath(asClauseContext.suffixPath());
+      if (asClauseContext.ID() != null) {
+        path.setTsAlias(asClauseContext.ID().toString());
+      }
+      selectOp.addSelectPath(path);
     }
-    insertOp.setValueList(valueList.toArray(new String[0]));
-    initializedOperator = insertOp;
   }
 
-  private PartialPath parseFullPath(FullPathContext ctx) {
-    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
-    String[] path = new String[nodeNamesWithoutStar.size() + 1];
-    int i = 0;
-    if (ctx.ROOT() != null) {
-      path[0] = ctx.ROOT().getText();
-    }
-    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
-      i++;
-      path[i] = nodeNameWithoutStar.getText();
-    }
-    return new PartialPath(path);
+  @Override
+  public Operator visitSpecialLimitStatement(SpecialLimitStatementContext ctx) {
+    return visit(ctx.specialLimit());
   }
 
   @Override
-  public void enterAttributeClauses(AttributeClausesContext ctx) {
-    super.enterAttributeClauses(ctx);
-    final String dataType = ctx.dataType().getChild(0).getText().toUpperCase();
-    final TSDataType tsDataType = TSDataType.valueOf(dataType);
-    createTimeSeriesOperator.setDataType(tsDataType);
-
-    final IoTDBDescriptor ioTDBDescriptor = IoTDBDescriptor.getInstance();
-    TSEncoding encoding = ioTDBDescriptor.getDefualtEncodingByType(tsDataType);
-    if (Objects.nonNull(ctx.encoding())) {
-      String encodingString = ctx.encoding().getChild(0).getText().toUpperCase();
-      encoding = TSEncoding.valueOf(encodingString);
-    }
-    createTimeSeriesOperator.setEncoding(encoding);
-
-    CompressionType compressor;
-    List<PropertyContext> properties = ctx.property();
-    if (ctx.compressor() != null) {
-      compressor = CompressionType.valueOf(ctx.compressor().getText().toUpperCase());
-    } else {
-      compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
+  public Operator visitLimitStatement(LimitStatementContext ctx) {
+    parseLimitClause(ctx.limitClause(), queryOp);
+    if (ctx.slimitClause() != null) {
+      parseSlimitClause(ctx.slimitClause(), queryOp);
     }
-    Map<String, String> props = null;
-    if (ctx.property(0) != null) {
-      props = new HashMap<>(properties.size());
-      for (PropertyContext property : properties) {
-        props.put(property.ID().getText().toLowerCase(),
-            property.propertyValue().getText().toLowerCase());
+    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
+      if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) {
+        parseAlignByDeviceClause(queryOp);
+      } else {
+        parseDisableAlign(queryOp);
       }
     }
-    createTimeSeriesOperator.setCompressor(compressor);
-    createTimeSeriesOperator.setProps(props);
-    initializedOperator = createTimeSeriesOperator;
+    return queryOp;
   }
 
   @Override
-  public void enterIndexWithClause(SqlBaseParser.IndexWithClauseContext ctx) {
-    super.enterIndexWithClause(ctx);
-    IndexType indexType;
-    try {
-      indexType = IndexType.getIndexType(ctx.indexName.getText());
-    } catch (UnsupportedIndexTypeException e) {
-      throw new SQLParserException(
-          String.format(ctx.indexName.getText()));
+  public Operator visitSlimitStatement(SlimitStatementContext ctx) {
+    parseSlimitClause(ctx.slimitClause(), queryOp);
+    if (ctx.limitClause() != null) {
+      parseLimitClause(ctx.limitClause(), queryOp);
     }
-
-    List<PropertyContext> properties = ctx.property();
-    Map<String, String> props = new HashMap<>(properties.size(), 1);
-    if (ctx.property(0) != null) {
-      for (PropertyContext property : properties) {
-        String k = property.ID().getText().toUpperCase();
-        String v = property.propertyValue().getText().toUpperCase();
-        v = IndexUtils.removeQuotation(v);
-        props.put(k, v);
+    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
+      if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) {
+        parseAlignByDeviceClause(queryOp);
+      } else {
+        parseDisableAlign(queryOp);
       }
     }
-
-    if (operatorType == SQLConstant.TOK_CREATE_INDEX) {
-      createIndexOp.setIndexType(indexType);
-      createIndexOp.setProps(props);
-    } else {
-      throw new SQLParserException("WITH clause only supports CREATE INDEX");
-    }
+    return queryOp;
   }
 
   @Override
-  public void enterAliasClause(SqlBaseParser.AliasClauseContext ctx) {
-    super.enterAliasClause(ctx);
-    if (alterTimeSeriesOperator != null && ctx.ID() != null) {
-      alterTimeSeriesOperator.setAlias(ctx.ID().getText());
+  public Operator visitAlignByDeviceClauseOrDisableAlignInSpecialLimit(
+      AlignByDeviceClauseOrDisableAlignInSpecialLimitContext ctx) {
+    if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) {
+      parseAlignByDeviceClause(queryOp);
+    } else {
+      parseDisableAlign(queryOp);
     }
+    return queryOp;
   }
 
-
   @Override
-  public void enterAttributeClause(AttributeClauseContext ctx) {
-    super.enterAttributeClause(ctx);
-    Map<String, String> attributes = extractMap(ctx.property(), ctx.property(0));
-    if (createTimeSeriesOperator != null) {
-      createTimeSeriesOperator.setAttributes(attributes);
-    } else if (alterTimeSeriesOperator != null) {
-      alterTimeSeriesOperator.setAttributesMap(attributes);
+  public Operator visitOrderByTimeStatement(OrderByTimeStatementContext ctx) {
+    parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp);
+    if (ctx.specialLimit() != null) {
+      return visit(ctx.specialLimit());
     }
+    return queryOp;
   }
 
   @Override
-  public void enterTagClause(TagClauseContext ctx) {
-    super.enterTagClause(ctx);
-    Map<String, String> tags = extractMap(ctx.property(), ctx.property(0));
-    if (createTimeSeriesOperator != null) {
-      createTimeSeriesOperator.setTags(tags);
-    } else if (alterTimeSeriesOperator != null) {
-      alterTimeSeriesOperator.setTagsMap(tags);
+  public Operator visitGroupByTimeStatement(GroupByTimeStatementContext ctx) {
+    parseGroupByTimeClause(ctx.groupByTimeClause(), queryOp);
+    if (ctx.orderByTimeClause() != null) {
+      parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp);
     }
-  }
-
-  private Map<String, String> extractMap(List<PropertyContext> property2,
-      PropertyContext property3) {
-    String value;
-    Map<String, String> tags = new HashMap<>(property2.size());
-    if (property3 != null) {
-      for (PropertyContext property : property2) {
-        if (property.propertyValue().stringLiteral() != null) {
-          value = removeStringQuote(property.propertyValue().getText());
-        } else {
-          value = property.propertyValue().getText();
-        }
-        tags.put(property.ID().getText(), value);
-      }
+    if (ctx.specialLimit() != null) {
+      return visit(ctx.specialLimit());
     }
-    return tags;
-  }
-
-  @Override
-  public void enterInsertStatement(InsertStatementContext ctx) {
-    super.enterInsertStatement(ctx);
-    insertOp = new InsertOperator(SQLConstant.TOK_INSERT);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    operatorType = SQLConstant.TOK_INSERT;
-    selectOp.addSelectPath(parsePrefixPath(ctx.prefixPath()));
-    insertOp.setSelectOperator(selectOp);
+    return queryOp;
   }
 
   @Override
-  public void enterUpdateStatement(UpdateStatementContext ctx) {
-    super.enterUpdateStatement(ctx);
-    updateOp = new UpdateOperator(SQLConstant.TOK_UPDATE);
-    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
-    fromOp.addPrefixTablePath(parsePrefixPath(ctx.prefixPath()));
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    operatorType = SQLConstant.TOK_UPDATE;
-    initializedOperator = updateOp;
+  public Operator visitGroupByFillStatement(GroupByFillStatementContext ctx) {
+    parseGroupByFillClause(ctx.groupByFillClause(), queryOp);
+    if (ctx.orderByTimeClause() != null) {
+      parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp);
+    }
+    if (ctx.specialLimit() != null) {
+      return visit(ctx.specialLimit());
+    }
+    return queryOp;
   }
 
   @Override
-  public void enterSelectStatement(SelectStatementContext ctx) {
-    super.enterSelectStatement(ctx);
-    operatorType = SQLConstant.TOK_QUERY;
-    queryOp = new QueryOperator(SQLConstant.TOK_QUERY);
-    initializedOperator = queryOp;
+  public Operator visitFillStatement(FillStatementContext ctx) {
+    parseFillClause(ctx.fillClause(), queryOp);
+    if (ctx.slimitClause() != null) {
+      queryOp = (QueryOperator) visit(ctx.slimitClause());
+    }
+    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
+      if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) {
+        parseAlignByDeviceClause(queryOp);
+      } else {
+        parseDisableAlign(queryOp);
+      }
+    }
+    return queryOp;
   }
 
   @Override
-  public void enterFromClause(FromClauseContext ctx) {
-    super.enterFromClause(ctx);
-    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
-    List<PrefixPathContext> prefixFromPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixFromPath : prefixFromPaths) {
-      PartialPath path = parsePrefixPath(prefixFromPath);
-      fromOp.addPrefixTablePath(path);
-    }
-    switch (operatorType) {
-      case SQLConstant.TOK_QUERY:
-        queryOp.setFromOperator(fromOp);
-        break;
-      case SQLConstant.TOK_QUERY_INDEX:
-        queryIndexOp.setFromOperator(fromOp);
-        break;
-      default:
-        throw new SQLParserException("From clause only support query and index query.");
+  public Operator visitAlignByDeviceStatementOrDisableAlignInSpecialClause(
+      AlignByDeviceStatementOrDisableAlignInSpecialClauseContext ctx) {
+    if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) {
+      parseAlignByDeviceClause(queryOp);
+    } else {
+      parseDisableAlign(queryOp);
     }
+    return queryOp;
   }
 
   @Override
-  public void enterFunctionElement(FunctionElementContext ctx) {
-    super.enterFunctionElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<FunctionCallContext> functionCallContextList = ctx.functionCall();
-    for (FunctionCallContext functionCallContext : functionCallContextList) {
-      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
-      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
+  public Operator visitGroupByLevelStatement(GroupByLevelStatementContext ctx) {
+    parseGroupByLevelClause(ctx.groupByLevelClause(), queryOp);
+    if (ctx.orderByTimeClause() != null) {
+      parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp);
     }
-    queryOp.setSelectOperator(selectOp);
+    if (ctx.specialLimit() != null) {
+      return visit(ctx.specialLimit());
+    }
+    return queryOp;
   }
 
   @Override
-  public void enterSelectElement(SelectElementContext ctx) {
-    super.enterSelectElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<SqlBaseParser.SuffixPathOrConstantContext> suffixPathOrConstants = ctx.suffixPathOrConstant();
+  public Operator visitSelectElement(SelectElementContext ctx) {
+    SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
+    List<SqlBaseParser.SuffixPathOrConstantContext> suffixPathOrConstants = ctx
+        .suffixPathOrConstant();
     for (SqlBaseParser.SuffixPathOrConstantContext suffixPathOrConstant : suffixPathOrConstants) {
       if (suffixPathOrConstant.suffixPath() != null) {
         PartialPath path = parseSuffixPath(suffixPathOrConstant.suffixPath());
         selectOp.addSelectPath(path);
       } else {
-        PartialPath path = new PartialPath(new String[]{suffixPathOrConstant.SINGLE_QUOTE_STRING_LITERAL().getText()});
+        PartialPath path = new PartialPath(
+            new String[]{suffixPathOrConstant.SINGLE_QUOTE_STRING_LITERAL().getText()});
         selectOp.addSelectPath(path);
       }
     }
-    queryOp.setSelectOperator(selectOp);
+    return selectOp;
   }
 
   @Override
-  public void enterLastElement(SqlBaseParser.LastElementContext ctx) {
-    super.enterLastElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    selectOp.setLastQuery();
-    LastClauseContext lastClauseContext = ctx.lastClause();
-    if (lastClauseContext.asClause().size() != 0) {
-      parseAsClause(lastClauseContext.asClause());
-    } else {
-      List<SuffixPathContext> suffixPaths = lastClauseContext.suffixPath();
-      for (SuffixPathContext suffixPath : suffixPaths) {
-        PartialPath path = parseSuffixPath(suffixPath);
-        selectOp.addSelectPath(path);
-      }
+  public Operator visitFromClause(FromClauseContext ctx) {
+    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
+    List<PrefixPathContext> prefixFromPaths = ctx.prefixPath();
+    for (PrefixPathContext prefixFromPath : prefixFromPaths) {
+      PartialPath path = parsePrefixPath(prefixFromPath);
+      fromOp.addPrefixTablePath(path);
     }
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterAsElement(AsElementContext ctx) {
-    super.enterAsElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    parseAsClause(ctx.asClause());
-    queryOp.setSelectOperator(selectOp);
+    return fromOp;
   }
 
-  public void parseAsClause(List<AsClauseContext> asClauseContexts) {
-    for (AsClauseContext asClauseContext : asClauseContexts) {
-      PartialPath path = parseSuffixPath(asClauseContext.suffixPath());
-      if (asClauseContext.ID() != null) {
-        path.setTsAlias(asClauseContext.ID().toString());
+  private void parseIndexPredicate(IndexPredicateClauseContext ctx) {
+    Map<String, Object> props;
+    PartialPath path;
+    if (ctx.suffixPath() != null) {
+      path = parseSuffixPath(ctx.suffixPath());
+    } else {
+      path = parseFullPath(ctx.fullPath());
+    }
+    if (ctx.LIKE() != null) {
+      // whole matching case
+      if (queryOp.getSelectedPaths().size() != 1) {
+        throw new SQLParserException("Index query statement allows only one select path");
       }
-      selectOp.addSelectPath(path);
+      if (!path.equals(queryOp.getSelectedPaths().get(0))) {
+        throw new SQLParserException("In the index query statement, "
+            + "the path in select element and the index predicate should be same");
+      }
+      if (queryOp.getProps() != null) {
+        props = queryOp.getProps();
+      } else {
+        props = new HashMap<>();
+      }
+      props.put(PATTERN, parseSequence(ctx.sequenceClause(0)));
+      queryOp.setIndexType(IndexType.RTREE_PAA);
+    } else if (ctx.CONTAIN() != null) {
+      // subsequence matching case
+      List<double[]> compositePattern = new ArrayList<>();
+      List<Double> thresholds = new ArrayList<>();
+      for (int i = 0; i < ctx.sequenceClause().size(); i++) {
+        compositePattern.add(parseSequence(ctx.sequenceClause(i)));
+        thresholds.add(Double.parseDouble(ctx.constant(i).getText()));
+      }
+      if (queryOp.getProps() != null) {
+        props = queryOp.getProps();
+      } else {
+        props = new HashMap<>();
+      }
+      List<PartialPath> suffixPaths = new ArrayList<>();
+      suffixPaths.add(path);
+      queryOp.getSelectOperator().setSuffixPathList(suffixPaths);
+      props.put(PATTERN, compositePattern);
+      props.put(THRESHOLD, thresholds);
+      queryOp.setIndexType(IndexType.ELB_INDEX);
+    } else {
+      throw new SQLParserException("Unknown index predicate: " + ctx);
     }
+    queryOp.setProps(props);
   }
 
-  @Override
-  public void enterFunctionAsElement(FunctionAsElementContext ctx) {
-    super.enterFunctionAsElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<FunctionAsClauseContext> functionAsClauseContexts = ctx.functionAsClause();
-    for (FunctionAsClauseContext functionAsClauseContext : functionAsClauseContexts) {
-      FunctionCallContext functionCallContext = functionAsClauseContext.functionCall();
-      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
-      if (functionAsClauseContext.ID() != null) {
-        path.setTsAlias(functionAsClauseContext.ID().toString());
-      }
-      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
+  private double[] parseSequence(SequenceClauseContext ctx) {
+    int seqLen = ctx.constant().size();
+    double[] sequence = new double[seqLen];
+    for (int i = 0; i < seqLen; i++) {
+      sequence[i] = Double.parseDouble(ctx.constant(i).getText());
     }
-    queryOp.setSelectOperator(selectOp);
+    return sequence;
   }
 
-  @Override
-  public void enterSetCol(SetColContext ctx) {
-    super.enterSetCol(ctx);
-    selectOp.addSelectPath(parseSuffixPath(ctx.suffixPath()));
-    updateOp.setSelectOperator(selectOp);
-    updateOp.setValue(ctx.constant().getText());
+  public void parseGroupByLevelClause(GroupByLevelClauseContext ctx, QueryOperator queryOp) {
+    queryOp.setGroupByLevel(true);
+    queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
   }
 
-
-  private PartialPath parsePrefixPath(PrefixPathContext ctx) {
-    List<NodeNameContext> nodeNames = ctx.nodeName();
-    String[] path = new String[nodeNames.size() + 1];
-    path[0] = ctx.ROOT().getText();
-    for (int i = 0; i < nodeNames.size(); i++) {
-      path[i + 1] = nodeNames.get(i).getText();
+  public void parseFillClause(FillClauseContext ctx, QueryOperator queryOp) {
+    FilterOperator filterOperator = queryOp.getFilterOperator();
+    if (!filterOperator.isLeaf() || filterOperator.getTokenIntType() != SQLConstant.EQUAL) {
+      throw new SQLParserException("Only \"=\" can be used in fill function");
     }
-    return new PartialPath(path);
+    List<TypeClauseContext> list = ctx.typeClause();
+    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
+    for (TypeClauseContext typeClause : list) {
+      parseTypeClause(typeClause, fillTypes);
+    }
+    queryOp.setFill(true);
+    queryOp.setFillTypes(fillTypes);
   }
 
-  /**
-   * parse duration to time value.
-   *
-   * @param durationStr represent duration string like: 12d8m9ns, 1y1mo, etc.
-   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
-   */
-  private Long parseDuration(String durationStr) {
-    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
+  private void parseLimitClause(LimitClauseContext ctx, Operator operator) {
+    int limit;
+    try {
+      limit = Integer.parseInt(ctx.INT().getText());
+    } catch (NumberFormatException e) {
+      throw new SQLParserException("Out of range. LIMIT <N>: N should be Int32.");
+    }
+    if (limit <= 0) {
+      throw new SQLParserException("LIMIT <N>: N should be greater than 0.");
+    }
+    if (operator instanceof ShowTimeSeriesOperator) {
+      ((ShowTimeSeriesOperator) operator).setLimit(limit);
+    } else {
+      ((QueryOperator) operator).setRowLimit(limit);
+    }
+    if (ctx.offsetClause() != null) {
+      parseOffsetClause(ctx.offsetClause(), operator);
+    }
+  }
 
-    long total = 0;
-    long tmp = 0;
-    for (int i = 0; i < durationStr.length(); i++) {
-      char ch = durationStr.charAt(i);
-      if (Character.isDigit(ch)) {
-        tmp *= 10;
-        tmp += (ch - '0');
-      } else {
-        String unit = durationStr.charAt(i) + "";
-        // This is to identify units with two letters.
-        if (i + 1 < durationStr.length() && !Character.isDigit(durationStr.charAt(i + 1))) {
-          i++;
-          unit += durationStr.charAt(i);
-        }
-        total += DatetimeUtils
-            .convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision);
-        tmp = 0;
+  private void parseOffsetClause(OffsetClauseContext ctx, Operator operator) {
+    int offset;
+    try {
+      offset = Integer.parseInt(ctx.INT().getText());
+    } catch (NumberFormatException e) {
+      throw new SQLParserException(
+          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32.");
+    }
+    if (offset < 0) {
+      throw new SQLParserException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
+    }
+    if (operator instanceof ShowTimeSeriesOperator) {
+      ((ShowTimeSeriesOperator) operator).setOffset(offset);
+    } else {
+      ((QueryOperator) operator).setRowOffset(offset);
+    }
+  }
+
+  private void parseSlimitClause(SlimitClauseContext ctx, QueryOperator queryOp) {
+    int slimit;
+    try {
+      slimit = Integer.parseInt(ctx.INT().getText());
+    } catch (NumberFormatException e) {
+      throw new SQLParserException(
+          "Out of range. SLIMIT <SN>: SN should be Int32.");
+    }
+    if (slimit <= 0) {
+      throw new SQLParserException("SLIMIT <SN>: SN should be greater than 0.");
+    }
+    queryOp.setSeriesLimit(slimit);
+    if (ctx.soffsetClause() != null) {
+      parseSoffsetClause(ctx.soffsetClause(), queryOp);
+    }
+  }
+
+  public void parseSoffsetClause(SoffsetClauseContext ctx, QueryOperator queryOp) {
+    int soffset;
+    try {
+      soffset = Integer.parseInt(ctx.INT().getText());
+    } catch (NumberFormatException e) {
+      throw new SQLParserException(
+          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
+    }
+    if (soffset < 0) {
+      throw new SQLParserException(
+          "SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
+    }
+    queryOp.setSeriesOffset(soffset);
+  }
+
+  private void parseGroupByTimeClause(GroupByTimeClauseContext ctx, QueryOperator queryOp) {
+    queryOp.setGroupByTime(true);
+    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
+    // parse timeUnit
+    queryOp.setUnit(parseDuration(ctx.DURATION(0).getText()));
+    queryOp.setSlidingStep(queryOp.getUnit());
+    // parse sliding step
+    if (ctx.DURATION().size() == 2) {
+      queryOp.setSlidingStep(parseDuration(ctx.DURATION(1).getText()));
+      if (queryOp.getSlidingStep() < queryOp.getUnit()) {
+        throw new SQLParserException(
+            "The third parameter sliding step shouldn't be smaller than the second parameter time interval.");
       }
     }
-    if (total <= 0) {
-      throw new SQLParserException("Interval must more than 0.");
+
+    parseTimeInterval(ctx.timeInterval(), queryOp);
+
+    if (ctx.INT() != null) {
+      queryOp.setGroupByLevel(true);
+      queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
     }
-    return total;
   }
 
-  @Override
-  public void enterWhereClause(WhereClauseContext ctx) {
-    super.enterWhereClause(ctx);
-    FilterOperator whereOp = new FilterOperator(SQLConstant.TOK_WHERE);
-    whereOp.addChildOperator(parseOrExpression(ctx.orExpression()));
-    switch (operatorType) {
-      case SQLConstant.TOK_DELETE:
-        deleteDataOp.setFilterOperator(whereOp.getChildren().get(0));
-        Pair<Long, Long> timeInterval = parseDeleteTimeInterval(deleteDataOp);
-        deleteDataOp.setStartTime(timeInterval.left);
-        deleteDataOp.setEndTime(timeInterval.right);
-        break;
-      case SQLConstant.TOK_QUERY:
-        queryOp.setFilterOperator(whereOp.getChildren().get(0));
-        break;
-      case SQLConstant.TOK_UPDATE:
-        updateOp.setFilterOperator(whereOp.getChildren().get(0));
-        break;
-      case SQLConstant.TOK_CREATE_INDEX:
-        createIndexOp.setFilterOperator(whereOp.getChildren().get(0));
-        long indexTime = parseCreateIndexFilter(createIndexOp);
-        createIndexOp.setTime(indexTime);
-        break;
-      case SQLConstant.TOK_QUERY_INDEX:
-        checkQueryIndex(ctx);
+  private void parseGroupByFillClause(GroupByFillClauseContext ctx, QueryOperator queryOp) {
+    queryOp.setGroupByTime(true);
+    queryOp.setFill(true);
+    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
+
+    // parse timeUnit
+    queryOp.setUnit(parseDuration(ctx.DURATION().getText()));
+    queryOp.setSlidingStep(queryOp.getUnit());
+
+    parseTimeInterval(ctx.timeInterval(), queryOp);
+
+    List<TypeClauseContext> list = ctx.typeClause();
+    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
+    for (TypeClauseContext typeClause : list) {
+      // group by fill doesn't support linear fill
+      if (typeClause.linearClause() != null) {
+        throw new SQLParserException("group by fill doesn't support linear fill");
+      }
+      // all type use the same fill way
+      if (SQLConstant.ALL.equalsIgnoreCase(typeClause.dataType().getText())) {
+        IFill fill;
+        if (typeClause.previousUntilLastClause() != null) {
+          long preRange;
+          if (typeClause.previousUntilLastClause().DURATION() != null) {
+            preRange = parseDuration(typeClause.previousUntilLastClause().DURATION().getText());
+          } else {
+            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+          }
+          fill = new PreviousFill(preRange, true);
+        } else {
+          long preRange;
+          if (typeClause.previousClause().DURATION() != null) {
+            preRange = parseDuration(typeClause.previousClause().DURATION().getText());
+          } else {
+            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+          }
+          fill = new PreviousFill(preRange);
+        }
+        for (TSDataType tsDataType : TSDataType.values()) {
+          fillTypes.put(tsDataType, fill.copy());
+        }
         break;
+      } else {
+        parseTypeClause(typeClause, fillTypes);
+      }
+    }
+    queryOp.setFill(true);
+    queryOp.setFillTypes(fillTypes);
+  }
+
+  private void parseTypeClause(TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) {
+    TSDataType dataType = parseType(ctx.dataType().getText());
+    if (ctx.linearClause() != null && dataType == TSDataType.TEXT) {
+      throw new SQLParserException(String.format("type %s cannot use %s fill function"
+          , dataType, ctx.linearClause().LINEAR().getText()));
+    }
+
+    int defaultFillInterval = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
+
+    if (ctx.linearClause() != null) {  // linear
+      if (ctx.linearClause().DURATION(0) != null) {
+        long beforeRange = parseDuration(ctx.linearClause().DURATION(0).getText());
+        long afterRange = parseDuration(ctx.linearClause().DURATION(1).getText());
+        fillTypes.put(dataType, new LinearFill(beforeRange, afterRange));
+      } else {
+        fillTypes.put(dataType, new LinearFill(defaultFillInterval, defaultFillInterval));
+      }
+    } else if (ctx.previousClause() != null) { // previous
+      if (ctx.previousClause().DURATION() != null) {
+        long preRange = parseDuration(ctx.previousClause().DURATION().getText());
+        fillTypes.put(dataType, new PreviousFill(preRange));
+      } else {
+        fillTypes.put(dataType, new PreviousFill(defaultFillInterval));
+      }
+    } else { // previous until last
+      if (ctx.previousUntilLastClause().DURATION() != null) {
+        long preRange = parseDuration(ctx.previousUntilLastClause().DURATION().getText());
+        fillTypes.put(dataType, new PreviousFill(preRange, true));
+      } else {
+        fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true));
+      }
+    }
+  }
+
+  /**
+   * parse datatype node.
+   */
+  private TSDataType parseType(String datatype) {
+    String type = datatype.toLowerCase();
+    switch (type) {
+      case "int32":
+        return TSDataType.INT32;
+      case "int64":
+        return TSDataType.INT64;
+      case "float":
+        return TSDataType.FLOAT;
+      case "double":
+        return TSDataType.DOUBLE;
+      case "boolean":
+        return TSDataType.BOOLEAN;
+      case "text":
+        return TSDataType.TEXT;
+      default:
+        throw new SQLParserException("not a valid fill type : " + type);
+    }
+  }
+
+  private void parseOrderByTimeClause(OrderByTimeClauseContext ctx, QueryOperator queryOp) {
+    queryOp.setColumn(ctx.TIME().getText());
+    if (ctx.DESC() != null) {
+      queryOp.setAscending(false);
+    }
+  }
+
+  private void parseAlignByDeviceClause(QueryOperator queryOp) {
+    queryOp.setAlignByDevice(true);
+  }
+
+  private void parseDisableAlign(QueryOperator queryOp) {
+    queryOp.setAlignByTime(false);
+  }
+
+  private void parseTimeInterval(TimeIntervalContext timeInterval, QueryOperator queryOp) {
+    long startTime;
+    long endTime;
+    if (timeInterval.timeValue(0).INT() != null) {
+      startTime = Long.parseLong(timeInterval.timeValue(0).INT().getText());
+    } else if (timeInterval.timeValue(0).dateExpression() != null) {
+      startTime = parseDateExpression(timeInterval.timeValue(0).dateExpression());
+    } else {
+      startTime = parseTimeFormat(timeInterval.timeValue(0).dateFormat().getText());
+    }
+    if (timeInterval.timeValue(1).INT() != null) {
+      endTime = Long.parseLong(timeInterval.timeValue(1).INT().getText());
+    } else if (timeInterval.timeValue(1).dateExpression() != null) {
+      endTime = parseDateExpression(timeInterval.timeValue(1).dateExpression());
+    } else {
+      endTime = parseTimeFormat(timeInterval.timeValue(1).dateFormat().getText());
+    }
+
+    queryOp.setStartTime(startTime);
+    queryOp.setEndTime(endTime);
+    if (startTime >= endTime) {
+      throw new SQLParserException("start time should be smaller than endTime in GroupBy");
+    }
+  }
+
+  private void parseShowWhereClause(ShowWhereClauseContext ctx, ShowTimeSeriesOperator operator) {
+    PropertyValueContext propertyValueContext;
+    if (ctx.containsExpression() != null) {
+      operator.setContains(true);
+      propertyValueContext = ctx.containsExpression().propertyValue();
+      operator.setKey(ctx.containsExpression().ID().getText());
+    } else {
+      operator.setContains(false);
+      propertyValueContext = ctx.property().propertyValue();
+      operator.setKey(ctx.property().ID().getText());
+    }
+    String value;
+    if (propertyValueContext.stringLiteral() != null) {
+      value = removeStringQuote(propertyValueContext.getText());
+    } else {
+      value = propertyValueContext.getText();
+    }
+    operator.setValue(value);
+  }
+
+  private String[] parsePrivilege(PrivilegesContext ctx) {
+    List<StringLiteralContext> privilegeList = ctx.stringLiteral();
+    List<String> privileges = new ArrayList<>();
+    for (StringLiteralContext privilege : privilegeList) {
+      privileges.add(removeStringQuote(privilege.getText()));
+    }
+    return privileges.toArray(new String[0]);
+  }
+
+  /**
+   * for delete command, time should only have an end time.
+   *
+   * @param operator delete logical plan
+   */
+  private Pair<Long, Long> parseDeleteTimeInterval(DeleteDataOperator operator) {
+    FilterOperator filterOperator = operator.getFilterOperator();
+    if (!filterOperator.isLeaf() && filterOperator.getTokenIntType() != SQLConstant.KW_AND) {
+      throw new SQLParserException(
+          DELETE_RANGE_ERROR_MSG);
+    }
+
+    if (filterOperator.isLeaf()) {
+      return calcOperatorInterval(filterOperator);
+    }
+
+    List<FilterOperator> children = filterOperator.getChildren();
+    FilterOperator lOperator = children.get(0);
+    FilterOperator rOperator = children.get(1);
+    if (!lOperator.isLeaf() || !rOperator.isLeaf()) {
+      throw new SQLParserException(
+          DELETE_RANGE_ERROR_MSG);
+    }
+
+    Pair<Long, Long> leftOpInterval = calcOperatorInterval(lOperator);
+    Pair<Long, Long> rightOpInterval = calcOperatorInterval(rOperator);
+    Pair<Long, Long> parsedInterval = new Pair<>(
+        Math.max(leftOpInterval.left, rightOpInterval.left),
+        Math.min(leftOpInterval.right, rightOpInterval.right));
+    if (parsedInterval.left > parsedInterval.right) {
+      throw new SQLParserException(
+          "Invalid delete range: [" + parsedInterval.left + ", " + parsedInterval.right + "]");
+    }
+    return parsedInterval;
+  }
+
+  private Pair<Long, Long> calcOperatorInterval(FilterOperator filterOperator) {
+    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
+    switch (filterOperator.getTokenIntType()) {
+      case SQLConstant.LESSTHAN:
+        return new Pair<>(Long.MIN_VALUE, time - 1);
+      case SQLConstant.LESSTHANOREQUALTO:
+        return new Pair<>(Long.MIN_VALUE, time);
+      case SQLConstant.GREATERTHAN:
+        return new Pair<>(time + 1, Long.MAX_VALUE);
+      case SQLConstant.GREATERTHANOREQUALTO:
+        return new Pair<>(time, Long.MAX_VALUE);
+      case SQLConstant.EQUAL:
+        return new Pair<>(time, time);
       default:
-        throw new SQLParserException("Where only support select, delete, update, create index.");
+        throw new SQLParserException(
+            DELETE_RANGE_ERROR_MSG);
     }
   }
 
-  @Override
-  public void enterShowWhereClause(ShowWhereClauseContext ctx) {
-    super.enterShowWhereClause(ctx);
 
-    ShowTimeSeriesOperator operator = (ShowTimeSeriesOperator) initializedOperator;
-    PropertyValueContext propertyValueContext;
-    if (ctx.containsExpression() != null) {
-      operator.setContains(true);
-      propertyValueContext = ctx.containsExpression().propertyValue();
-      operator.setKey(ctx.containsExpression().ID().getText());
-    } else {
-      operator.setContains(false);
-      propertyValueContext = ctx.property().propertyValue();
-      operator.setKey(ctx.property().ID().getText());
-    }
-    String value;
-    if (propertyValueContext.stringLiteral() != null) {
-      value = removeStringQuote(propertyValueContext.getText());
-    } else {
-      value = propertyValueContext.getText();
+  @Override
+  public Operator visitWhereClause(WhereClauseContext ctx) {
+    if (ctx.indexPredicateClause() != null) {
+      parseIndexPredicate(ctx.indexPredicateClause());
+      return queryOp;
     }
-    operator.setValue(value);
+    FilterOperator whereOp = new FilterOperator(SQLConstant.TOK_WHERE);
+    whereOp.addChildOperator(parseOrExpression(ctx.orExpression()));
+    return whereOp;
   }
 
   private FilterOperator parseOrExpression(OrExpressionContext ctx) {
@@ -1604,74 +1581,311 @@ public class LogicalGenerator extends SqlBaseBaseListener {
       }
       if (ctx.inClause() != null) {
         return parseInOperator(ctx.inClause(), path);
-      } else if (ctx.indexPredicateClause() != null) {
-        return parseIndexPredicate(ctx.indexPredicateClause(), path);
       } else {
         return parseBasicFunctionOperator(ctx, path);
       }
     }
   }
 
-  private FilterOperator parseInOperator(InClauseContext ctx, PartialPath path) {
-    Set<String> values = new HashSet<>();
-    boolean not = ctx.OPERATOR_NOT() != null;
-    for (ConstantContext constant : ctx.constant()) {
-      if (constant.dateExpression() != null) {
-        if (!path.equals(TIME_PATH)) {
-          throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
-        }
-        values.add(Long.toString(parseDateExpression(constant.dateExpression())));
-      } else {
-        values.add(constant.getText());
-      }
+  private FilterOperator parseInOperator(InClauseContext ctx, PartialPath path) {
+    Set<String> values = new HashSet<>();
+    boolean not = ctx.OPERATOR_NOT() != null;
+    for (ConstantContext constant : ctx.constant()) {
+      if (constant.dateExpression() != null) {
+        if (!path.equals(TIME_PATH)) {
+          throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
+        }
+        values.add(Long.toString(parseDateExpression(constant.dateExpression())));
+      } else {
+        values.add(constant.getText());
+      }
+    }
+    return new InOperator(ctx.OPERATOR_IN().getSymbol().getType(), path, not, values);
+  }
+
+  private FilterOperator parseBasicFunctionOperator(PredicateContext ctx, PartialPath path) {
+    BasicFunctionOperator basic;
+    if (ctx.constant().dateExpression() != null) {
+      if (!path.equals(TIME_PATH)) {
+        throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
+      }
+      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
+          Long.toString(parseDateExpression(ctx.constant().dateExpression())));
+    } else {
+      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
+          ctx.constant().getText());
+    }
+    return basic;
+  }
+
+  /**
+   * parse time expression, which is addition and subtraction expression of duration time, now() or
+   * DataTimeFormat time. <p> eg. now() + 1d - 2h </p>
+   */
+  private Long parseDateExpression(DateExpressionContext ctx) {
+    long time;
+    time = parseTimeFormat(ctx.getChild(0).getText());
+    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
+      if (ctx.getChild(i).getText().equals("+")) {
+        time += parseDuration(ctx.getChild(i + 1).getText());
+      } else {
+        time -= parseDuration(ctx.getChild(i + 1).getText());
+      }
+    }
+    return time;
+  }
+
+
+  /**
+   * parse duration to time value.
+   *
+   * @param durationStr represent duration string like: 12d8m9ns, 1y1mo, etc.
+   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
+   */
+  private Long parseDuration(String durationStr) {
+    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
+
+    long total = 0;
+    long tmp = 0;
+    for (int i = 0; i < durationStr.length(); i++) {
+      char ch = durationStr.charAt(i);
+      if (Character.isDigit(ch)) {
+        tmp *= 10;
+        tmp += (ch - '0');
+      } else {
+        String unit = durationStr.charAt(i) + "";
+        // This is to identify units with two letters.
+        if (i + 1 < durationStr.length() && !Character.isDigit(durationStr.charAt(i + 1))) {
+          i++;
+          unit += durationStr.charAt(i);
+        }
+        total += DatetimeUtils
+            .convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision);
+        tmp = 0;
+      }
+    }
+    if (total <= 0) {
+      throw new SQLParserException("Interval must more than 0.");
+    }
+    return total;
+  }
+
+  private void parseSetCol(SetColContext ctx, SelectOperator selectOp, UpdateOperator updateOp) {
+    selectOp.addSelectPath(parseSuffixPath(ctx.suffixPath()));
+    updateOp.setValue(ctx.constant().getText());
+  }
+
+  private PartialPath parseSuffixPath(SuffixPathContext ctx) {
+    List<NodeNameContext> nodeNames = ctx.nodeName();
+    String[] path = new String[nodeNames.size()];
+    for (int i = 0; i < nodeNames.size(); i++) {
+      path[i] = nodeNames.get(i).getText();
+    }
+    return new PartialPath(path);
+  }
+
+  private void parseInsertColumnSpec(InsertColumnsSpecContext ctx, InsertOperator insertOp) {
+    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
+    List<String> measurementList = new ArrayList<>();
+    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
+      String measurement = nodeNameWithoutStar.getText();
+      measurementList.add(measurement);
+    }
+    insertOp.setMeasurementList(measurementList.toArray(new String[0]));
+  }
+
+  private void parseInsertValuesSpec(InsertValuesSpecContext ctx, InsertOperator insertOp) {
+    long timestamp;
+    if (ctx.dateFormat() != null) {
+      timestamp = parseTimeFormat(ctx.dateFormat().getText());
+    } else {
+      timestamp = Long.parseLong(ctx.INT().getText());
+    }
+    insertOp.setTime(timestamp);
+    List<String> valueList = new ArrayList<>();
+    List<ConstantContext> values = ctx.constant();
+    for (ConstantContext value : values) {
+      valueList.add(value.getText());
+    }
+    insertOp.setValueList(valueList.toArray(new String[0]));
+  }
+
+
+  private void parseAlterClause(AlterClauseContext ctx,
+      AlterTimeSeriesOperator alterTimeSeriesOperator) {
+    Map<String, String> alterMap = new HashMap<>();
+    // rename
+    if (ctx.RENAME() != null) {
+      alterTimeSeriesOperator.setAlterType(AlterType.RENAME);
+      alterMap.put(ctx.beforeName.getText(), ctx.currentName.getText());
+    } else if (ctx.SET() != null) {
+      // set
+      alterTimeSeriesOperator.setAlterType(AlterType.SET);
+      setMap(ctx, alterMap);
+    } else if (ctx.DROP() != null) {
+      // drop
+      alterTimeSeriesOperator.setAlterType(AlterType.DROP);
+      for (TerminalNode dropId : ctx.ID()) {
+        alterMap.put(dropId.getText(), null);
+      }
+    } else if (ctx.TAGS() != null) {
+      // add tag
+      alterTimeSeriesOperator.setAlterType(AlterType.ADD_TAGS);
+      setMap(ctx, alterMap);
+    } else if (ctx.ATTRIBUTES() != null) {
+      // add attribute
+      alterTimeSeriesOperator.setAlterType(AlterType.ADD_ATTRIBUTES);
+      setMap(ctx, alterMap);
+    } else {
+      // upsert
+      alterTimeSeriesOperator.setAlterType(AlterType.UPSERT);
+      if (ctx.aliasClause() != null) {
+        parseAliasClause(ctx.aliasClause(), alterTimeSeriesOperator);
+      }
+      if (ctx.tagClause() != null) {
+        parseTagClause(ctx.tagClause(), alterTimeSeriesOperator);
+      }
+      if (ctx.attributeClause() != null) {
+        parseAttributeClause(ctx.attributeClause(), alterTimeSeriesOperator);
+      }
+    }
+    alterTimeSeriesOperator.setAlterMap(alterMap);
+  }
+
+  public void parseAliasClause(AliasClauseContext ctx,
+      AlterTimeSeriesOperator alterTimeSeriesOperator) {
+    if (alterTimeSeriesOperator != null && ctx.ID() != null) {
+      alterTimeSeriesOperator.setAlias(ctx.ID().getText());
+    }
+  }
+
+  private void setMap(SqlBaseParser.AlterClauseContext ctx, Map<String, String> alterMap) {
+    List<PropertyContext> tagsList = ctx.property();
+    if (ctx.property(0) != null) {
+      for (PropertyContext property : tagsList) {
+        String value;
+        if (property.propertyValue().stringLiteral() != null) {
+          value = removeStringQuote(property.propertyValue().getText());
+        } else {
+          value = property.propertyValue().getText();
+        }
+        alterMap.put(property.ID().getText(), value);
+      }
+    }
+  }
+
+  private String removeStringQuote(String src) {
+    if (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'') {
+      return src.substring(1, src.length() - 1);
+    } else if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
+      return src.substring(1, src.length() - 1);
+    } else {
+      throw new SQLParserException("error format for string with quote:" + src);
+    }
+  }
+
+  private PartialPath parsePrefixPath(PrefixPathContext ctx) {
+    List<NodeNameContext> nodeNames = ctx.nodeName();
+    String[] path = new String[nodeNames.size() + 1];
+    path[0] = ctx.ROOT().getText();
+    for (int i = 0; i < nodeNames.size(); i++) {
+      path[i + 1] = nodeNames.get(i).getText();
+    }
+    return new PartialPath(path);
+  }
+
+  public void parseAttributeClauses(AttributeClausesContext ctx,
+      CreateTimeSeriesOperator createTimeSeriesOperator) {
+    final String dataType = ctx.dataType().getChild(0).getText().toUpperCase();
+    final TSDataType tsDataType = TSDataType.valueOf(dataType);
+    createTimeSeriesOperator.setDataType(tsDataType);
+
+    final IoTDBDescriptor ioTDBDescriptor = IoTDBDescriptor.getInstance();
+    TSEncoding encoding = ioTDBDescriptor.getDefualtEncodingByType(tsDataType);
+    if (Objects.nonNull(ctx.encoding())) {
+      String encodingString = ctx.encoding().getChild(0).getText().toUpperCase();
+      encoding = TSEncoding.valueOf(encodingString);
+    }
+    createTimeSeriesOperator.setEncoding(encoding);
+
+    CompressionType compressor;
+    List<PropertyContext> properties = ctx.property();
+    if (ctx.compressor() != null) {
+      compressor = CompressionType.valueOf(ctx.compressor().getText().toUpperCase());
+    } else {
+      compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
+    }
+    Map<String, String> props = null;
+    if (ctx.property(0) != null) {
+      props = new HashMap<>(properties.size());
+      for (PropertyContext property : properties) {
+        props.put(property.ID().getText().toLowerCase(),
+            property.propertyValue().getText().toLowerCase());
+      }
+    }
+    createTimeSeriesOperator.setCompressor(compressor);
+    createTimeSeriesOperator.setProps(props);
+    if (ctx.tagClause() != null) {
+      parseTagClause(ctx.tagClause(), createTimeSeriesOperator);
+    }
+    if (ctx.attributeClause() != null) {
+      parseAttributeClause(ctx.attributeClause(), createTimeSeriesOperator);
+    }
+  }
+
+  public void parseAttributeClause(AttributeClauseContext ctx, Operator operator) {
+    Map<String, String> attributes = extractMap(ctx.property(), ctx.property(0));
+    if (operator instanceof CreateTimeSeriesOperator) {
+      ((CreateTimeSeriesOperator) operator).setAttributes(attributes);
+    } else if (operator instanceof AlterTimeSeriesOperator) {
+      ((AlterTimeSeriesOperator) operator).setAttributesMap(attributes);
     }
-    return new InOperator(ctx.OPERATOR_IN().getSymbol().getType(), path, not, values);
   }
 
-  private FilterOperator parseBasicFunctionOperator(PredicateContext ctx, PartialPath path) {
-    BasicFunctionOperator basic;
-    if (ctx.constant().dateExpression() != null) {
-      if (!path.equals(TIME_PATH)) {
-        throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
-      }
-      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
-          Long.toString(parseDateExpression(ctx.constant().dateExpression())));
-    } else {
-      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
-          ctx.constant().getText());
+  public void parseTagClause(TagClauseContext ctx, Operator operator) {
+    Map<String, String> tags = extractMap(ctx.property(), ctx.property(0));
+    if (operator instanceof CreateTimeSeriesOperator) {
+      ((CreateTimeSeriesOperator) operator).setTags(tags);
+    } else if (operator instanceof AlterTimeSeriesOperator) {
+      ((AlterTimeSeriesOperator) operator).setTagsMap(tags);
     }
-    return basic;
   }
 
-  private PartialPath parseSuffixPath(SuffixPathContext ctx) {
-    List<NodeNameContext> nodeNames = ctx.nodeName();
-    String[] path = new String[nodeNames.size()];
-    for (int i = 0; i < nodeNames.size(); i++) {
-      path[i] = nodeNames.get(i).getText();
+  private Map<String, String> extractMap(List<PropertyContext> property2,
+      PropertyContext property3) {
+    String value;
+    Map<String, String> tags = new HashMap<>(property2.size());
+    if (property3 != null) {
+      for (PropertyContext property : property2) {
+        if (property.propertyValue().stringLiteral() != null) {
+          value = removeStringQuote(property.propertyValue().getText());
+        } else {
+          value = property.propertyValue().getText();
+        }
+        tags.put(property.ID().getText(), value);
+      }
     }
-    return new PartialPath(path);
+    return tags;
   }
 
-  /**
-   * parse time expression, which is addition and subtraction expression of duration time, now() or
-   * DataTimeFormat time. <p> eg. now() + 1d - 2h </p>
-   */
-  private Long parseDateExpression(DateExpressionContext ctx) {
-    long time = parseTimeFormat(ctx.getChild(0).getText());
-    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
-      if (ctx.getChild(i).getText().equals("+")) {
-        time += parseDuration(ctx.getChild(i + 1).getText());
-      } else {
-        time -= parseDuration(ctx.getChild(i + 1).getText());
-      }
+  private PartialPath parseFullPath(FullPathContext ctx) {
+    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
+    String[] path = new String[nodeNamesWithoutStar.size() + 1];
+    int i = 0;
+    if (ctx.ROOT() != null) {
+      path[0] = ctx.ROOT().getText();
     }
-    return time;
+    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
+      i++;
+      path[i] = nodeNameWithoutStar.getText();
+    }
+    return new PartialPath(path);
   }
 
   /**
    * function for parsing time format.
    */
-  long parseTimeFormat(String timestampStr) throws SQLParserException {
+  public long parseTimeFormat(String timestampStr) throws SQLParserException {
     if (timestampStr == null || timestampStr.trim().equals("")) {
       throw new SQLParserException("input timestamp cannot be empty");
     }
@@ -1698,243 +1912,4 @@ public class LogicalGenerator extends SqlBaseBaseListener {
               + "refer to user document for more info.", timestampStr));
     }
   }
-
-  /**
-   * for delete command, time should only have an end time.
-   *
-   * @param operator delete logical plan
-   */
-  private Pair<Long, Long> parseDeleteTimeInterval(DeleteDataOperator operator) {
-    FilterOperator filterOperator = operator.getFilterOperator();
-    if (!filterOperator.isLeaf() && filterOperator.getTokenIntType() != SQLConstant.KW_AND) {
-      throw new SQLParserException(
-          DELETE_RANGE_ERROR_MSG);
-    }
-
-    if (filterOperator.isLeaf()) {
-      return calcOperatorInterval(filterOperator);
-    }
-
-    List<FilterOperator> children = filterOperator.getChildren();
-    FilterOperator lOperator = children.get(0);
-    FilterOperator rOperator = children.get(1);
-    if (!lOperator.isLeaf() || !rOperator.isLeaf()) {
-      throw new SQLParserException(
-          DELETE_RANGE_ERROR_MSG);
-    }
-
-    Pair<Long, Long> leftOpInterval = calcOperatorInterval(lOperator);
-    Pair<Long, Long> rightOpInterval = calcOperatorInterval(rOperator);
-    Pair<Long, Long> parsedInterval = new Pair<>(
-        Math.max(leftOpInterval.left, rightOpInterval.left),
-        Math.min(leftOpInterval.right, rightOpInterval.right));
-    if (parsedInterval.left > parsedInterval.right) {
-      throw new SQLParserException(
-          "Invalid delete range: [" + parsedInterval.left + ", " + parsedInterval.right + "]");
-    }
-    return parsedInterval;
-  }
-
-  private Pair<Long, Long> calcOperatorInterval(FilterOperator filterOperator) {
-    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
-    switch (filterOperator.getTokenIntType()) {
-      case SQLConstant.LESSTHAN:
-        return new Pair<>(Long.MIN_VALUE, time - 1);
-      case SQLConstant.LESSTHANOREQUALTO:
-        return new Pair<>(Long.MIN_VALUE, time);
-      case SQLConstant.GREATERTHAN:
-        return new Pair<>(time + 1, Long.MAX_VALUE);
-      case SQLConstant.GREATERTHANOREQUALTO:
-        return new Pair<>(time, Long.MAX_VALUE);
-      case SQLConstant.EQUAL:
-        return new Pair<>(time, time);
-      default:
-        throw new SQLParserException(
-            DELETE_RANGE_ERROR_MSG);
-    }
-  }
-
-  @Override
-  public void enterShowMergeStatus(ShowMergeStatusContext ctx) {
-    super.enterShowMergeStatus(ctx);
-    initializedOperator = new ShowMergeStatusOperator(SQLConstant.TOK_SHOW_MERGE_STATUS);
-  }
-
-  @Override
-  public void enterDeletePartition(DeletePartitionContext ctx) {
-    super.enterDeletePartition(ctx);
-    DeletePartitionOperator deletePartitionOperator = new DeletePartitionOperator(
-        SQLConstant.TOK_DELETE_PARTITION);
-    deletePartitionOperator.setStorageGroupName(parsePrefixPath(ctx.prefixPath()));
-    Set<Long> idSet = new HashSet<>();
-    for (TerminalNode terminalNode : ctx.INT()) {
-      idSet.add(Long.parseLong(terminalNode.getText()));
-    }
-    deletePartitionOperator.setPartitionIds(idSet);
-    initializedOperator = deletePartitionOperator;
-  }
-
-  @Override
-  public void enterCreateSnapshot(CreateSnapshotContext ctx) {
-    super.enterCreateSnapshot(ctx);
-    initializedOperator = new CreateSnapshotOperator(SQLConstant.TOK_CREATE_SCHEMA_SNAPSHOT);
-  }
-
-  /**
-   * for create index command, time should only have an end time.
-   *
-   * @param operator create index plan
-   */
-  private long parseCreateIndexFilter(CreateIndexOperator operator) {
-    FilterOperator filterOperator = operator.getFilterOperator();
-    if (filterOperator.getTokenIntType() != SQLConstant.GREATERTHAN
-        && filterOperator.getTokenIntType() != SQLConstant.GREATERTHANOREQUALTO) {
-      throw new SQLParserException(
-          "For create index command, where clause must be like : time > XXX or time >= XXX");
-    }
-    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
-    if (filterOperator.getTokenIntType() == SQLConstant.LESSTHAN) {
-      time = time - 1;
-    }
-    return time;
-  }
-
-  /**
-   * For parsing CreateIndex
-   *
-   * <p>The default implementation does nothing.</p>
-   */
-  @Override
-  public void enterCreateIndex(SqlBaseParser.CreateIndexContext ctx) {
-    super.enterCreateIndex(ctx);
-    createIndexOp = new CreateIndexOperator(SQLConstant.TOK_CREATE_INDEX);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
-    }
-    createIndexOp.setSelectOperator(selectOp);
-    initializedOperator = createIndexOp;
-    operatorType = SQLConstant.TOK_CREATE_INDEX;
-  }
-
-  @Override
-  public void enterDropIndex(SqlBaseParser.DropIndexContext ctx) {
-    super.enterDropIndex(ctx);
-    DropIndexOperator dropIndexOperator = new DropIndexOperator(SQLConstant.TOK_DROP_INDEX);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
-    }
-    dropIndexOperator.setSelectOperator(selectOp);
-    try {
-      dropIndexOperator.setIndexType(IndexType.getIndexType(ctx.indexName.getText()));
-    } catch (UnsupportedIndexTypeException e) {
-      throw new SQLParserException(
-          String.format(ctx.indexName.getText()));
-    }
-    initializedOperator = dropIndexOperator;
-    operatorType = SQLConstant.TOK_DROP_INDEX;
-  }
-
-  private FilterOperator parseIndexPredicate(IndexPredicateClauseContext ctx, PartialPath path) {
-    if (queryIndexOp != null) {
-      throw new SQLParserException("Index query statement allows only one index predicate");
-    }
-    if (RESERVED_TIME.equals(path.getFullPath())) {
-      throw new SQLParserException("In the index predicate, left path cannot be TIME");
-    }
-    queryIndexOp = new QueryIndexOperator(SQLConstant.TOK_QUERY_INDEX);
-    initializedOperator = queryIndexOp;
-    operatorType = SQLConstant.TOK_QUERY_INDEX;
-
-    Map<String, Object> props = new HashMap<>();
-    if (ctx.LIKE() != null) {
-      // whole matching case
-      if (indexTopK == NON_SET_TOP_K) {
-        throw new SQLParserException(
-            "TopK hasn't been set in the whole matching of similarity search");
-      }
-      if (queryOp.getSelectedPaths().size() != 1) {
-        throw new SQLParserException("Index query statement allows only one select path");
-      }
-      if (!path.equals(queryOp.getSelectedPaths().get(0))) {
-        throw new SQLParserException("In the index query statement, "
-            + "the path in select element and the index predicate should be same");
-      }
-      props.put(TOP_K, indexTopK);
-      props.put(PATTERN, parseSequence(ctx.sequenceClause(0)));
-      queryIndexOp.setIndexType(IndexType.RTREE_PAA);
-    } else if (ctx.CONTAIN() != null) {
-      // subsequence matching case
-      List<double[]> compositePattern = new ArrayList<>();
-      List<Double> thresholds = new ArrayList<>();
-      for (int i = 0; i < ctx.sequenceClause().size(); i++) {
-        compositePattern.add(parseSequence(ctx.sequenceClause(i)));
-        thresholds.add(Double.parseDouble(ctx.constant(i).getText()));
-      }
-      props.put(PATTERN, compositePattern);
-      props.put(THRESHOLD, thresholds);
-      queryIndexOp.setIndexType(IndexType.ELB_INDEX);
-    } else {
-      throw new SQLParserException("Unknown index predicate: " + ctx);
-    }
-    queryIndexOp.setFromOperator(queryOp.getFromOperator());
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    selectOp.addSelectPath(path);
-    queryIndexOp.setSelectOperator(selectOp);
-    queryOp = null;
-    queryIndexOp.setProps(props);
-    return null;
-  }
-
-  private double[] parseSequence(SequenceClauseContext ctx) {
-    int seqLen = ctx.constant().size();
-    double[] sequence = new double[seqLen];
-    for (int i = 0; i < seqLen; i++) {
-      sequence[i] = Double.parseDouble(ctx.constant(i).getText());
-    }
-    return sequence;
-  }
-
-  /**
-   * In query index statement, the where clause should have only one index predicate.
-   */
-  private void checkQueryIndex(WhereClauseContext ctx) {
-    boolean queryValid = true;
-    OrExpressionContext or = ctx.orExpression();
-    if (or.andExpression() == null || or.andExpression().size() != 1) {
-      queryValid = false;
-    } else {
-      AndExpressionContext and = or.andExpression(0);
-      if (and.predicate() == null || and.predicate(0).indexPredicateClause() == null)
-        queryValid = false;
-    }
-    if (!queryValid) {
-      throw new SQLParserException(
-          "In query index statement, the where clause should have and only have one index predicate.");
-    }
-  }
-
-  /**
-   * @param ctx Top ClauseContext
-   */
-  @Override
-  public void enterTopClause(TopClauseContext ctx) {
-    super.enterTopClause(ctx);
-    int top;
-    try {
-      top = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException("Out of range. TOP <N>: N should be Int32.");
-    }
-    if (top <= 0) {
-      throw new SQLParserException("TOP <N>: N should be greater than 0.");
-    }
-    indexTopK = top;
-  }
-
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
index 57d632b..057e4bc 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
@@ -18,1923 +18,51 @@
  */
 package org.apache.iotdb.db.qp.strategy;
 
-import static org.apache.iotdb.db.index.common.IndexConstant.NON_SET_TOP_K;
-import static org.apache.iotdb.db.index.common.IndexConstant.PATTERN;
-import static org.apache.iotdb.db.index.common.IndexConstant.THRESHOLD;
-import static org.apache.iotdb.db.index.common.IndexConstant.TOP_K;
-import static org.apache.iotdb.db.qp.constant.SQLConstant.RESERVED_TIME;
-import static org.apache.iotdb.db.qp.constant.SQLConstant.TIME_PATH;
-
-import java.io.File;
 import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import org.antlr.v4.runtime.tree.TerminalNode;
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.exception.index.UnsupportedIndexTypeException;
-import org.apache.iotdb.db.exception.runtime.SQLParserException;
-import org.apache.iotdb.db.index.common.IndexUtils;
-import org.apache.iotdb.db.metadata.PartialPath;
-import org.apache.iotdb.db.qp.constant.DatetimeUtils;
-import org.apache.iotdb.db.qp.constant.SQLConstant;
-import org.apache.iotdb.db.qp.logical.RootOperator;
-import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
-import org.apache.iotdb.db.qp.logical.crud.DeleteDataOperator;
-import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
-import org.apache.iotdb.db.qp.logical.crud.FromOperator;
-import org.apache.iotdb.db.qp.logical.crud.InOperator;
-import org.apache.iotdb.db.qp.logical.crud.InsertOperator;
-import org.apache.iotdb.db.qp.logical.crud.QueryIndexOperator;
-import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
-import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
-import org.apache.iotdb.db.qp.logical.crud.UpdateOperator;
-import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator;
-import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator.AlterType;
-import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
-import org.apache.iotdb.db.qp.logical.sys.AuthorOperator.AuthorType;
-import org.apache.iotdb.db.qp.logical.sys.ClearCacheOperator;
-import org.apache.iotdb.db.qp.logical.sys.CountOperator;
-import org.apache.iotdb.db.qp.logical.sys.CreateIndexOperator;
-import org.apache.iotdb.db.qp.logical.sys.CreateSnapshotOperator;
-import org.apache.iotdb.db.qp.logical.sys.CreateTimeSeriesOperator;
-import org.apache.iotdb.db.qp.logical.sys.DataAuthOperator;
-import org.apache.iotdb.db.qp.logical.sys.DeletePartitionOperator;
-import org.apache.iotdb.db.qp.logical.sys.DeleteStorageGroupOperator;
-import org.apache.iotdb.db.qp.logical.sys.DeleteTimeSeriesOperator;
-import org.apache.iotdb.db.qp.logical.sys.DropIndexOperator;
-import org.apache.iotdb.db.qp.logical.sys.FlushOperator;
-import org.apache.iotdb.db.qp.logical.sys.LoadConfigurationOperator;
-import org.apache.iotdb.db.qp.logical.sys.LoadConfigurationOperator.LoadConfigurationOperatorType;
-import org.apache.iotdb.db.qp.logical.sys.LoadDataOperator;
-import org.apache.iotdb.db.qp.logical.sys.LoadFilesOperator;
-import org.apache.iotdb.db.qp.logical.sys.MergeOperator;
-import org.apache.iotdb.db.qp.logical.sys.MoveFileOperator;
-import org.apache.iotdb.db.qp.logical.sys.RemoveFileOperator;
-import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
-import org.apache.iotdb.db.qp.logical.sys.SetTTLOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowChildPathsOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowDevicesOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowMergeStatusOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowStorageGroupOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowTTLOperator;
-import org.apache.iotdb.db.qp.logical.sys.ShowTimeSeriesOperator;
-import org.apache.iotdb.db.qp.logical.sys.TracingOperator;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AliasContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlignByDeviceClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlterUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AndExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AsClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AsElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AttributeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AttributeClausesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ConstantContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountDevicesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountNodesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateSnapshotContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DateExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeletePartitionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DropRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DropUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FillClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FlushContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FromClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FullMergeContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FullPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionAsClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionAsElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionCallContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.FunctionElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantRoleToUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GrantWatermarkEmbeddingContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.GroupByTimeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.IndexPredicateClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertColumnSpecContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertValuesSpecContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LastClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LimitClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllRoleOfUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllUserOfRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListPrivilegesRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListPrivilegesUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListRolePrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListUserPrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadConfigurationStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadFilesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LoadStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.MergeContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.MoveFileContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.NodeNameContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.NodeNameWithoutStarContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OffsetClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OrExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.OrderByTimeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PredicateContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PrefixPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PrivilegesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PropertyContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.PropertyValueContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RemoveFileContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeRoleContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeRoleFromUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeUserContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RevokeWatermarkEmbeddingContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.RootOrIdContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SelectElementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SelectStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SequenceClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetColContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SetTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowAllTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowChildPathsContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowDevicesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowMergeStatusContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowStorageGroupContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowVersionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ShowWhereClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SlimitClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SoffsetClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.StringLiteralContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SuffixPathContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TagClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TimeIntervalContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TopClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TracingOffContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TracingOnContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TypeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UnsetTTLStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UpdateStatementContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.WhereClauseContext;
-import org.apache.iotdb.db.query.executor.fill.IFill;
-import org.apache.iotdb.db.query.executor.fill.LinearFill;
-import org.apache.iotdb.db.query.executor.fill.PreviousFill;
-import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.utils.Pair;
-import org.apache.iotdb.tsfile.utils.StringContainer;
-import org.apache.iotdb.db.index.common.IndexType;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CharStreams;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.atn.PredictionMode;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.db.qp.sql.IoTDBSqlVisitor;
+import org.apache.iotdb.db.qp.sql.SqlBaseLexer;
+import org.apache.iotdb.db.qp.sql.SqlBaseParser;
 
 /**
- * This class is a listener and you can get an operator which is a logical plan.
+ * LogicalGenerator.
+ *
  */
-public class LogicalGenerator extends SqlBaseBaseListener {
-
-  private RootOperator initializedOperator = null;
-  private ZoneId zoneId;
-  private int operatorType;
-  private CreateTimeSeriesOperator createTimeSeriesOperator;
-  private AlterTimeSeriesOperator alterTimeSeriesOperator;
-  private InsertOperator insertOp;
-  private SelectOperator selectOp;
-  private UpdateOperator updateOp;
-  private QueryOperator queryOp;
-  private DeleteDataOperator deleteDataOp;
-  private CreateIndexOperator createIndexOp;
-  private QueryIndexOperator queryIndexOp;
-  private int indexTopK = NON_SET_TOP_K;
-  private static final String DELETE_RANGE_ERROR_MSG =
-    "For delete statement, where clause can only contain atomic expressions like : " +
-      "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'";
-
-
-  LogicalGenerator(ZoneId zoneId) {
-    this.zoneId = zoneId;
-  }
-
-  RootOperator getLogicalPlan() {
-    return initializedOperator;
-  }
-
-  @Override
-  public void enterCountTimeseries(CountTimeseriesContext ctx) {
-    super.enterCountTimeseries(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    if (ctx.INT() != null) {
-      initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_NODE_TIMESERIES,
-          path, Integer.parseInt(ctx.INT().getText()));
-    } else {
-      initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_TIMESERIES,
-          path);
-    }
-  }
-
-  @Override
-  public void enterCountDevices(CountDevicesContext ctx) {
-    super.enterCountDevices(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_DEVICES, path);
-  }
-
-  @Override
-  public void enterCountStorageGroup(CountStorageGroupContext ctx) {
-    super.enterCountStorageGroup(ctx);
-    PrefixPathContext pathContext = ctx.prefixPath();
-    PartialPath path = (pathContext != null ? parsePrefixPath(pathContext) : new PartialPath(SQLConstant.getSingleRootArray()));
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_STORAGE_GROUP, path);
-  }
-
-  @Override
-  public void enterFlush(FlushContext ctx) {
-    super.enterFlush(ctx);
-    FlushOperator flushOperator = new FlushOperator(SQLConstant.TOK_FLUSH);
-    if (ctx.booleanClause() != null) {
-      flushOperator.setSeq(Boolean.parseBoolean(ctx.booleanClause().getText()));
-    }
-    if (ctx.prefixPath(0) != null) {
-      List<PartialPath> storageGroups = new ArrayList<>();
-      for (PrefixPathContext prefixPathContext : ctx.prefixPath()) {
-        storageGroups.add(parsePrefixPath(prefixPathContext));
-      }
-      flushOperator.setStorageGroupList(storageGroups);
-    }
-
-    initializedOperator = flushOperator;
-  }
-
-  @Override
-  public void enterTracingOn(TracingOnContext ctx) {
-    super.enterTracingOn(ctx);
-    initializedOperator = new TracingOperator(SQLConstant.TOK_TRACING, true);
-  }
-
-  @Override
-  public void enterTracingOff(TracingOffContext ctx) {
-    super.enterTracingOff(ctx);
-    initializedOperator = new TracingOperator(SQLConstant.TOK_TRACING, false);
-  }
-
-  @Override
-  public void enterMerge(MergeContext ctx) {
-    super.enterMerge(ctx);
-    initializedOperator = new MergeOperator(SQLConstant.TOK_MERGE);
-  }
-
-  @Override
-  public void enterFullMerge(FullMergeContext ctx) {
-    super.enterFullMerge(ctx);
-    initializedOperator = new MergeOperator(SQLConstant.TOK_FULL_MERGE);
-  }
-
-  @Override
-  public void enterClearcache(SqlBaseParser.ClearcacheContext ctx) {
-    super.enterClearcache(ctx);
-    initializedOperator = new ClearCacheOperator(SQLConstant.TOK_CLEAR_CACHE);
-  }
-
-  @Override
-  public void enterCountNodes(CountNodesContext ctx) {
-    super.enterCountNodes(ctx);
-    initializedOperator = new CountOperator(SQLConstant.TOK_COUNT_NODES,
-        parsePrefixPath(ctx.prefixPath()), Integer.parseInt(ctx.INT().getText()));
-  }
-
-  @Override
-  public void enterShowDevices(ShowDevicesContext ctx) {
-    super.enterShowDevices(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowDevicesOperator(SQLConstant.TOK_DEVICES,
-          new PartialPath(SQLConstant.getSingleRootArray()));
-    }
-  }
-
-  @Override
-  public void enterShowChildPaths(ShowChildPathsContext ctx) {
-    super.enterShowChildPaths(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowChildPathsOperator(SQLConstant.TOK_CHILD_PATHS,
-          new PartialPath(SQLConstant.getSingleRootArray()));
-    }
-  }
-
-  @Override
-  public void enterShowStorageGroup(ShowStorageGroupContext ctx) {
-    super.enterShowStorageGroup(ctx);
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
-          parsePrefixPath(ctx.prefixPath()));
-    } else {
-      initializedOperator = new ShowStorageGroupOperator(SQLConstant.TOK_STORAGE_GROUP,
-          new PartialPath(SQLConstant.getSingleRootArray()));
-    }
-  }
-
-  @Override
-  public void enterLoadFiles(LoadFilesContext ctx) {
-    super.enterLoadFiles(ctx);
-    if (ctx.autoCreateSchema() != null) {
-      if (ctx.autoCreateSchema().INT() != null) {
-        initializedOperator = new LoadFilesOperator(
-            new File(removeStringQuote(ctx.stringLiteral().getText())),
-            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
-            Integer.parseInt(ctx.autoCreateSchema().INT().getText())
-        );
-      } else {
-        initializedOperator = new LoadFilesOperator(
-            new File(removeStringQuote(ctx.stringLiteral().getText())),
-            Boolean.parseBoolean(ctx.autoCreateSchema().booleanClause().getText()),
-            IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
-        );
-      }
-    } else {
-      initializedOperator = new LoadFilesOperator(
-          new File(removeStringQuote(ctx.stringLiteral().getText())),
-          true,
-          IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel()
-      );
-    }
-  }
-
-  @Override
-  public void enterMoveFile(MoveFileContext ctx) {
-    super.enterMoveFile(ctx);
-    initializedOperator = new MoveFileOperator(
-        new File(removeStringQuote(ctx.stringLiteral(0).getText())),
-        new File(removeStringQuote(ctx.stringLiteral(1).getText())));
-  }
-
-  @Override
-  public void enterRemoveFile(RemoveFileContext ctx) {
-    super.enterRemoveFile(ctx);
-    initializedOperator = new RemoveFileOperator(
-        new File(removeStringQuote(ctx.stringLiteral().getText())));
-  }
-
-  @Override
-  public void enterLoadConfigurationStatement(LoadConfigurationStatementContext ctx) {
-    super.enterLoadConfigurationStatement(ctx);
-    if (ctx.GLOBAL() != null) {
-      initializedOperator = new LoadConfigurationOperator(LoadConfigurationOperatorType.GLOBAL);
-    } else {
-      initializedOperator = new LoadConfigurationOperator(LoadConfigurationOperatorType.LOCAL);
-    }
-
-  }
-
-  @Override
-  public void enterShowVersion(ShowVersionContext ctx) {
-    super.enterShowVersion(ctx);
-    initializedOperator = new ShowOperator(SQLConstant.TOK_VERSION);
-  }
-
-  @Override
-  public void enterShowFlushTaskInfo(SqlBaseParser.ShowFlushTaskInfoContext ctx) {
-    super.enterShowFlushTaskInfo(ctx);
-    initializedOperator = new ShowOperator(SQLConstant.TOK_FLUSH_TASK_INFO);
-  }
-
-  @Override
-  public void enterShowTimeseries(ShowTimeseriesContext ctx) {
-    super.enterShowTimeseries(ctx);
-    boolean orderByHeat = ctx.LATEST() != null;
-    if (ctx.prefixPath() != null) {
-      initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES,
-          parsePrefixPath(ctx.prefixPath()), orderByHeat);
-    } else {
-      initializedOperator = new ShowTimeSeriesOperator(SQLConstant.TOK_TIMESERIES, new PartialPath(SQLConstant.getSingleRootArray()),
-          orderByHeat);
-    }
-  }
-
-  @Override
-  public void enterCreateTimeseries(CreateTimeseriesContext ctx) {
-    super.enterCreateTimeseries(ctx);
-    createTimeSeriesOperator = new CreateTimeSeriesOperator(SQLConstant.TOK_METADATA_CREATE);
-    operatorType = SQLConstant.TOK_METADATA_CREATE;
-    createTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
-  }
-
-  @Override
-  public void enterAlterTimeseries(SqlBaseParser.AlterTimeseriesContext ctx) {
-    super.enterAlterTimeseries(ctx);
-    alterTimeSeriesOperator = new AlterTimeSeriesOperator(SQLConstant.TOK_METADATA_ALTER);
-    operatorType = SQLConstant.TOK_METADATA_ALTER;
-    alterTimeSeriesOperator.setPath(parseFullPath(ctx.fullPath()));
-  }
-
-  @Override
-  public void enterAlterClause(SqlBaseParser.AlterClauseContext ctx) {
-    super.enterAlterClause(ctx);
-    Map<String, String> alterMap = new HashMap<>();
-    // rename
-    if (ctx.RENAME() != null) {
-      alterTimeSeriesOperator.setAlterType(AlterType.RENAME);
-      alterMap.put(ctx.beforeName.getText(), ctx.currentName.getText());
-    } else if (ctx.SET() != null) {
-      // set
-      alterTimeSeriesOperator.setAlterType(AlterType.SET);
-      setMap(ctx, alterMap);
-    } else if (ctx.DROP() != null) {
-      // drop
-      alterTimeSeriesOperator.setAlterType(AlterType.DROP);
-      for (TerminalNode dropId : ctx.ID()) {
-        alterMap.put(dropId.getText(), null);
-      }
-    } else if (ctx.TAGS() != null) {
-      // add tag
-      alterTimeSeriesOperator.setAlterType(AlterType.ADD_TAGS);
-      setMap(ctx, alterMap);
-    } else if (ctx.ATTRIBUTES() != null) {
-      // add attribute
-      alterTimeSeriesOperator.setAlterType(AlterType.ADD_ATTRIBUTES);
-      setMap(ctx, alterMap);
-    } else {
-      // upsert
-      alterTimeSeriesOperator.setAlterType(AlterType.UPSERT);
-    }
-    alterTimeSeriesOperator.setAlterMap(alterMap);
-    initializedOperator = alterTimeSeriesOperator;
-  }
-
-  private void setMap(SqlBaseParser.AlterClauseContext ctx, Map<String, String> alterMap) {
-    List<PropertyContext> tagsList = ctx.property();
-    if (ctx.property(0) != null) {
-      for (PropertyContext property : tagsList) {
-        String value;
-        if (property.propertyValue().stringLiteral() != null) {
-          value = removeStringQuote(property.propertyValue().getText());
-        } else {
-          value = property.propertyValue().getText();
-        }
-        alterMap.put(property.ID().getText(), value);
-      }
-    }
-  }
-
-  @Override
-  public void enterAlias(AliasContext ctx) {
-    super.enterAlias(ctx);
-    createTimeSeriesOperator.setAlias(ctx.ID().getText());
-  }
-
-  @Override
-  public void enterCreateUser(CreateUserContext ctx) {
-    super.enterCreateUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
-        AuthorOperator.AuthorType.CREATE_USER);
-    authorOperator.setUserName(ctx.ID().getText());
-    authorOperator.setPassWord(removeStringQuote(ctx.password.getText()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_CREATE;
-  }
-
-  @Override
-  public void enterCreateRole(CreateRoleContext ctx) {
-    super.enterCreateRole(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
-        AuthorOperator.AuthorType.CREATE_ROLE);
-    authorOperator.setRoleName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_CREATE;
-  }
-
-  @Override
-  public void enterAlterUser(AlterUserContext ctx) {
-    super.enterAlterUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_UPDATE_USER,
-        AuthorOperator.AuthorType.UPDATE_USER);
-    if (ctx.ID() != null) {
-      authorOperator.setUserName(ctx.ID().getText());
-    } else {
-      authorOperator.setUserName(ctx.ROOT().getText());
-    }
-    authorOperator.setNewPassword(removeStringQuote(ctx.password.getText()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_UPDATE_USER;
-  }
-
-  @Override
-  public void enterDropUser(DropUserContext ctx) {
-    super.enterDropUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_DROP,
-        AuthorOperator.AuthorType.DROP_USER);
-    authorOperator.setUserName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_DROP;
-  }
-
-  @Override
-  public void enterDropRole(DropRoleContext ctx) {
-    super.enterDropRole(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_DROP,
-        AuthorOperator.AuthorType.DROP_ROLE);
-    authorOperator.setRoleName(ctx.ID().getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_DROP;
-  }
-
-  @Override
-  public void enterGrantUser(GrantUserContext ctx) {
-    super.enterGrantUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorOperator.AuthorType.GRANT_USER);
-    authorOperator.setUserName(ctx.ID().getText());
-    authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
-    authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterGrantRole(GrantRoleContext ctx) {
-    super.enterGrantRole(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorType.GRANT_ROLE);
-    authorOperator.setRoleName(ctx.ID().getText());
-    authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
-    authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterRevokeUser(RevokeUserContext ctx) {
-    super.enterRevokeUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorType.REVOKE_USER);
-    authorOperator.setUserName(ctx.ID().getText());
-    authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
-    authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterRevokeRole(RevokeRoleContext ctx) {
-    super.enterRevokeRole(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorType.REVOKE_ROLE);
-    authorOperator.setRoleName(ctx.ID().getText());
-    authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
-    authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterGrantRoleToUser(GrantRoleToUserContext ctx) {
-    super.enterGrantRoleToUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorOperator.AuthorType.GRANT_ROLE_TO_USER);
-    authorOperator.setRoleName(ctx.roleName.getText());
-    authorOperator.setUserName(ctx.userName.getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterRevokeRoleFromUser(RevokeRoleFromUserContext ctx) {
-    super.enterRevokeRoleFromUser(ctx);
-    AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
-        AuthorType.REVOKE_ROLE_FROM_USER);
-    authorOperator.setRoleName(ctx.roleName.getText());
-    authorOperator.setUserName(ctx.userName.getText());
-    initializedOperator = authorOperator;
-    operatorType = SQLConstant.TOK_AUTHOR_GRANT;
-  }
-
-  @Override
-  public void enterLoadStatement(LoadStatementContext ctx) {
-    super.enterLoadStatement(ctx);
-    if (ctx.prefixPath().nodeName().size() < 3) {
-      throw new SQLParserException("data load command: child count < 3\n");
-    }
-
-    String csvPath = ctx.stringLiteral().getText();
-    StringContainer sc = new StringContainer(TsFileConstant.PATH_SEPARATOR);
-    List<NodeNameContext> nodeNames = ctx.prefixPath().nodeName();
-    sc.addTail(ctx.prefixPath().ROOT().getText());
-    for (NodeNameContext nodeName : nodeNames) {
-      sc.addTail(nodeName.getText());
-    }
-    initializedOperator = new LoadDataOperator(SQLConstant.TOK_DATALOAD,
-        removeStringQuote(csvPath),
-        sc.toString());
-    operatorType = SQLConstant.TOK_DATALOAD;
-  }
-
-  @Override
-  public void enterGrantWatermarkEmbedding(GrantWatermarkEmbeddingContext ctx) {
-    super.enterGrantWatermarkEmbedding(ctx);
-    List<RootOrIdContext> rootOrIdList = ctx.rootOrId();
-    List<String> users = new ArrayList<>();
-    for (RootOrIdContext rootOrId : rootOrIdList) {
-      users.add(rootOrId.getText());
-    }
-    initializedOperator = new DataAuthOperator(SQLConstant.TOK_GRANT_WATERMARK_EMBEDDING, users);
-  }
-
-  @Override
-  public void enterRevokeWatermarkEmbedding(RevokeWatermarkEmbeddingContext ctx) {
-    super.enterRevokeWatermarkEmbedding(ctx);
-    List<RootOrIdContext> rootOrIdList = ctx.rootOrId();
-    List<String> users = new ArrayList<>();
-    for (RootOrIdContext rootOrId : rootOrIdList) {
-      users.add(rootOrId.getText());
-    }
-    initializedOperator = new DataAuthOperator(SQLConstant.TOK_REVOKE_WATERMARK_EMBEDDING, users);
-    operatorType = SQLConstant.TOK_REVOKE_WATERMARK_EMBEDDING;
-  }
-
-  @Override
-  public void enterListUser(ListUserContext ctx) {
-    super.enterListUser(ctx);
-    initializedOperator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_USER);
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListRole(ListRoleContext ctx) {
-    super.enterListRole(ctx);
-    initializedOperator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_ROLE);
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListPrivilegesUser(ListPrivilegesUserContext ctx) {
-    super.enterListPrivilegesUser(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
-    operator.setUserName(ctx.rootOrId().getText());
-    operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListPrivilegesRole(ListPrivilegesRoleContext ctx) {
-    super.enterListPrivilegesRole(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
-    operator.setRoleName((ctx.ID().getText()));
-    operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListUserPrivileges(ListUserPrivilegesContext ctx) {
-    super.enterListUserPrivileges(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
-    operator.setUserName(ctx.rootOrId().getText());
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListRolePrivileges(ListRolePrivilegesContext ctx) {
-    super.enterListRolePrivileges(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
-    operator.setRoleName(ctx.ID().getText());
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListAllRoleOfUser(ListAllRoleOfUserContext ctx) {
-    super.enterListAllRoleOfUser(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_USER_ROLES);
-    initializedOperator = operator;
-    operator.setUserName(ctx.rootOrId().getText());
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterListAllUserOfRole(ListAllUserOfRoleContext ctx) {
-    super.enterListAllUserOfRole(ctx);
-    AuthorOperator operator = new AuthorOperator(SQLConstant.TOK_LIST,
-        AuthorOperator.AuthorType.LIST_ROLE_USERS);
-    initializedOperator = operator;
-    operator.setRoleName((ctx.ID().getText()));
-    operatorType = SQLConstant.TOK_LIST;
-  }
-
-  @Override
-  public void enterSetTTLStatement(SetTTLStatementContext ctx) {
-    super.enterSetTTLStatement(ctx);
-    SetTTLOperator operator = new SetTTLOperator(SQLConstant.TOK_SET);
-    operator.setStorageGroup(parsePrefixPath(ctx.prefixPath()));
-    operator.setDataTTL(Long.parseLong(ctx.INT().getText()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_SET;
-  }
-
-  @Override
-  public void enterUnsetTTLStatement(UnsetTTLStatementContext ctx) {
-    super.enterUnsetTTLStatement(ctx);
-    SetTTLOperator operator = new SetTTLOperator(SQLConstant.TOK_UNSET);
-    operator.setStorageGroup(parsePrefixPath(ctx.prefixPath()));
-    initializedOperator = operator;
-    operatorType = SQLConstant.TOK_UNSET;
-  }
-
-  @Override
-  public void enterShowTTLStatement(ShowTTLStatementContext ctx) {
-    super.enterShowTTLStatement(ctx);
-    List<PartialPath> storageGroups = new ArrayList<>();
-    List<PrefixPathContext> prefixPathList = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPathList) {
-      storageGroups.add(parsePrefixPath(prefixPath));
-    }
-    initializedOperator = new ShowTTLOperator(storageGroups);
-  }
-
-  @Override
-  public void enterShowAllTTLStatement(ShowAllTTLStatementContext ctx) {
-    super.enterShowAllTTLStatement(ctx);
-    List<PartialPath> storageGroups = new ArrayList<>();
-    initializedOperator = new ShowTTLOperator(storageGroups);
-  }
-
-  private String[] parsePrivilege(PrivilegesContext ctx) {
-    List<StringLiteralContext> privilegeList = ctx.stringLiteral();
-    List<String> privileges = new ArrayList<>();
-    for (StringLiteralContext privilege : privilegeList) {
-      privileges.add(removeStringQuote(privilege.getText()));
-    }
-    return privileges.toArray(new String[0]);
-  }
-
-  private String removeStringQuote(String src) {
-    if (src.charAt(0) == '\'' && src.charAt(src.length() - 1) == '\'') {
-      return src.substring(1, src.length() - 1);
-    } else if (src.charAt(0) == '\"' && src.charAt(src.length() - 1) == '\"') {
-      return src.substring(1, src.length() - 1);
-    } else {
-      throw new SQLParserException("error format for string with quote:" + src);
-    }
-  }
-
-  @Override
-  public void enterDeleteTimeseries(DeleteTimeseriesContext ctx) {
-    super.enterDeleteTimeseries(ctx);
-    List<PartialPath> deletePaths = new ArrayList<>();
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      deletePaths.add(parsePrefixPath(prefixPath));
-    }
-    DeleteTimeSeriesOperator deleteTimeSeriesOperator = new DeleteTimeSeriesOperator(
-        SQLConstant.TOK_METADATA_DELETE);
-    deleteTimeSeriesOperator.setDeletePathList(deletePaths);
-    initializedOperator = deleteTimeSeriesOperator;
-    operatorType = SQLConstant.TOK_METADATA_DELETE;
-  }
-
-  @Override
-  public void enterSetStorageGroup(SetStorageGroupContext ctx) {
-    super.enterSetStorageGroup(ctx);
-    SetStorageGroupOperator setStorageGroupOperator = new SetStorageGroupOperator(
-        SQLConstant.TOK_METADATA_SET_FILE_LEVEL);
-    PartialPath path = parsePrefixPath(ctx.prefixPath());
-    setStorageGroupOperator.setPath(path);
-    initializedOperator = setStorageGroupOperator;
-    operatorType = SQLConstant.TOK_METADATA_SET_FILE_LEVEL;
-  }
-
-  @Override
-  public void enterDeleteStorageGroup(DeleteStorageGroupContext ctx) {
-    super.enterDeleteStorageGroup(ctx);
-    List<PartialPath> deletePaths = new ArrayList<>();
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      deletePaths.add(parsePrefixPath(prefixPath));
-    }
-    DeleteStorageGroupOperator deleteStorageGroupOperator = new DeleteStorageGroupOperator(
-        SQLConstant.TOK_METADATA_DELETE_FILE_LEVEL);
-    deleteStorageGroupOperator.setDeletePathList(deletePaths);
-    initializedOperator = deleteStorageGroupOperator;
-    operatorType = SQLConstant.TOK_METADATA_DELETE_FILE_LEVEL;
-  }
-
-  @Override
-  public void enterDeleteStatement(DeleteStatementContext ctx) {
-    super.enterDeleteStatement(ctx);
-    operatorType = SQLConstant.TOK_DELETE;
-    deleteDataOp = new DeleteDataOperator(SQLConstant.TOK_DELETE);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
-    }
-    deleteDataOp.setSelectOperator(selectOp);
-    initializedOperator = deleteDataOp;
-  }
-
-  @Override
-  public void enterDisableAlign(SqlBaseParser.DisableAlignContext ctx) {
-    super.enterDisableAlign(ctx);
-    queryOp.setAlignByTime(false);
-  }
-
-  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
-  @Override
-  public void enterGroupByFillClause(SqlBaseParser.GroupByFillClauseContext ctx) {
-    super.enterGroupByFillClause(ctx);
-    queryOp.setGroupByTime(true);
-    queryOp.setFill(true);
-    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
-
-    // parse timeUnit
-    queryOp.setUnit(parseDuration(ctx.DURATION().getText()));
-    queryOp.setSlidingStep(queryOp.getUnit());
-
-    parseTimeInterval(ctx.timeInterval());
-
-    List<TypeClauseContext> list = ctx.typeClause();
-    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
-    for (TypeClauseContext typeClause : list) {
-      // group by fill doesn't support linear fill
-      if (typeClause.linearClause() != null) {
-        throw new SQLParserException("group by fill doesn't support linear fill");
-      }
-      // all type use the same fill way
-      if (SQLConstant.ALL.equalsIgnoreCase(typeClause.dataType().getText())) {
-        IFill fill;
-        if (typeClause.previousUntilLastClause() != null) {
-          long preRange;
-          if (typeClause.previousUntilLastClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousUntilLastClause().DURATION().getText());
-          } else {
-            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-          }
-          fill = new PreviousFill(preRange, true);
-        } else {
-          long preRange;
-          if (typeClause.previousClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousClause().DURATION().getText());
-          } else {
-            preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-          }
-          fill = new PreviousFill(preRange);
-        }
-        for (TSDataType tsDataType : TSDataType.values()) {
-          fillTypes.put(tsDataType, fill.copy());
-        }
-        break;
-      } else {
-        parseTypeClause(typeClause, fillTypes);
-      }
-    }
-    queryOp.setFill(true);
-    queryOp.setFillTypes(fillTypes);
-  }
-
-  private void parseTimeInterval(TimeIntervalContext timeInterval) {
-    long startTime;
-    long endTime;
-    if (timeInterval.timeValue(0).INT() != null) {
-      startTime = Long.parseLong(timeInterval.timeValue(0).INT().getText());
-    } else if (timeInterval.timeValue(0).dateExpression() != null) {
-      startTime = parseDateExpression(timeInterval.timeValue(0).dateExpression());
-    } else {
-      startTime = parseTimeFormat(timeInterval.timeValue(0).dateFormat().getText());
-    }
-    if (timeInterval.timeValue(1).INT() != null) {
-      endTime = Long.parseLong(timeInterval.timeValue(1).INT().getText());
-    } else if (timeInterval.timeValue(1).dateExpression() != null) {
-      endTime = parseDateExpression(timeInterval.timeValue(1).dateExpression());
-    } else {
-      endTime = parseTimeFormat(timeInterval.timeValue(1).dateFormat().getText());
-    }
-
-    queryOp.setStartTime(startTime);
-    queryOp.setEndTime(endTime);
-    if (startTime >= endTime) {
-      throw new SQLParserException("start time should be smaller than endTime in GroupBy");
-    }
-  }
-
-  @Override
-  public void enterGroupByTimeClause(GroupByTimeClauseContext ctx) {
-    super.enterGroupByTimeClause(ctx);
-
-    queryOp.setGroupByTime(true);
-    queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
-    // parse timeUnit
-    queryOp.setUnit(parseDuration(ctx.DURATION(0).getText()));
-    queryOp.setSlidingStep(queryOp.getUnit());
-    // parse sliding step
-    if (ctx.DURATION().size() == 2) {
-      queryOp.setSlidingStep(parseDuration(ctx.DURATION(1).getText()));
-      if (queryOp.getSlidingStep() < queryOp.getUnit()) {
-        throw new SQLParserException(
-            "The third parameter sliding step shouldn't be smaller than the second parameter time interval.");
-      }
-    }
-
-    parseTimeInterval(ctx.timeInterval());
-
-    if (ctx.INT() != null) {
-      queryOp.setGroupByLevel(true);
-      queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
-    }
-  }
-
-  @Override
-  public void enterGroupByLevelClause(SqlBaseParser.GroupByLevelClauseContext ctx) {
-    super.enterGroupByLevelClause(ctx);
-    queryOp.setGroupByLevel(true);
-
-    queryOp.setLevel(Integer.parseInt(ctx.INT().getText()));
-  }
-
-  @Override
-  public void enterFillClause(FillClauseContext ctx) {
-    super.enterFillClause(ctx);
-    FilterOperator filterOperator = queryOp.getFilterOperator();
-    if (!filterOperator.isLeaf() || filterOperator.getTokenIntType() != SQLConstant.EQUAL) {
-      throw new SQLParserException("Only \"=\" can be used in fill function");
-    }
-    List<TypeClauseContext> list = ctx.typeClause();
-    Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class);
-    for (TypeClauseContext typeClause : list) {
-      parseTypeClause(typeClause, fillTypes);
-    }
-    queryOp.setFill(true);
-    queryOp.setFillTypes(fillTypes);
-  }
-
-  private void parseTypeClause(TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) {
-    TSDataType dataType = parseType(ctx.dataType().getText());
-    if (ctx.linearClause() != null && dataType == TSDataType.TEXT) {
-      throw new SQLParserException(String.format("type %s cannot use %s fill function"
-          , dataType, ctx.linearClause().LINEAR().getText()));
-    }
-
-    int defaultFillInterval = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
-
-    if (ctx.linearClause() != null) {  // linear
-      if (ctx.linearClause().DURATION(0) != null) {
-        long beforeRange = parseDuration(ctx.linearClause().DURATION(0).getText());
-        long afterRange = parseDuration(ctx.linearClause().DURATION(1).getText());
-        fillTypes.put(dataType, new LinearFill(beforeRange, afterRange));
-      } else {
-        fillTypes.put(dataType, new LinearFill(defaultFillInterval, defaultFillInterval));
-      }
-    } else if (ctx.previousClause() != null) { // previous
-      if (ctx.previousClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousClause().DURATION().getText());
-        fillTypes.put(dataType, new PreviousFill(preRange));
-      } else {
-        fillTypes.put(dataType, new PreviousFill(defaultFillInterval));
-      }
-    } else { // previous until last
-      if (ctx.previousUntilLastClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousUntilLastClause().DURATION().getText());
-        fillTypes.put(dataType, new PreviousFill(preRange, true));
-      } else {
-        fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true));
-      }
-    }
-  }
-
-  @Override
-  public void enterAlignByDeviceClause(AlignByDeviceClauseContext ctx) {
-    super.enterAlignByDeviceClause(ctx);
-    queryOp.setAlignByDevice(true);
-  }
-
-  /**
-   * parse datatype node.
-   */
-  private TSDataType parseType(String datatype) {
-    String type = datatype.toLowerCase();
-    switch (type) {
-      case "int32":
-        return TSDataType.INT32;
-      case "int64":
-        return TSDataType.INT64;
-      case "float":
-        return TSDataType.FLOAT;
-      case "double":
-        return TSDataType.DOUBLE;
-      case "boolean":
-        return TSDataType.BOOLEAN;
-      case "text":
-        return TSDataType.TEXT;
-      default:
-        throw new SQLParserException("not a valid fill type : " + type);
-    }
-  }
-
-  @Override
-  public void enterLimitClause(LimitClauseContext ctx) {
-    super.enterLimitClause(ctx);
-    int limit;
-    try {
-      limit = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException("Out of range. LIMIT <N>: N should be Int32.");
-    }
-    if (limit <= 0) {
-      throw new SQLParserException("LIMIT <N>: N should be greater than 0.");
-    }
-    if (initializedOperator instanceof ShowTimeSeriesOperator) {
-      ((ShowTimeSeriesOperator) initializedOperator).setLimit(limit);
-    } else {
-      queryOp.setRowLimit(limit);
-    }
-  }
-
-  @Override
-  public void enterOffsetClause(OffsetClauseContext ctx) {
-    super.enterOffsetClause(ctx);
-    int offset;
-    try {
-      offset = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32.");
-    }
-    if (offset < 0) {
-      throw new SQLParserException("OFFSET <OFFSETValue>: OFFSETValue should >= 0.");
-    }
-    if (initializedOperator instanceof ShowTimeSeriesOperator) {
-      ((ShowTimeSeriesOperator) initializedOperator).setOffset(offset);
-    } else {
-      queryOp.setRowOffset(offset);
-    }
-  }
-
-  @Override
-  public void enterOrderByTimeClause(OrderByTimeClauseContext ctx) {
-    super.enterOrderByTimeClause(ctx);
-    queryOp.setColumn(ctx.TIME().getText());
-    if (ctx.DESC() != null) {
-      queryOp.setAscending(false);
-    }
-  }
-
-  @Override
-  public void enterSlimitClause(SlimitClauseContext ctx) {
-    super.enterSlimitClause(ctx);
-    int slimit;
-    try {
-      slimit = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. SLIMIT <SN>: SN should be Int32.");
-    }
-    if (slimit <= 0) {
-      throw new SQLParserException("SLIMIT <SN>: SN should be greater than 0.");
-    }
-    queryOp.setSeriesLimit(slimit);
-  }
-
-  @Override
-  public void enterSoffsetClause(SoffsetClauseContext ctx) {
-    super.enterSoffsetClause(ctx);
-    int soffset;
+public class LogicalGenerator {
+
+  public LogicalGenerator() { }
+
+  public Operator generate(String sql, ZoneId zoneId) throws ParseCancellationException {
+    IoTDBSqlVisitor ioTDBSqlVisitor = new IoTDBSqlVisitor();
+    ioTDBSqlVisitor.setZoneId(zoneId);
+    CharStream charStream1 = CharStreams.fromString(sql);
+    SqlBaseLexer lexer1 = new SqlBaseLexer(charStream1);
+    CommonTokenStream tokens1 = new CommonTokenStream(lexer1);
+    SqlBaseParser parser1 = new SqlBaseParser(tokens1);
+    parser1.getInterpreter().setPredictionMode(PredictionMode.SLL);
+    parser1.removeErrorListeners();
+    parser1.addErrorListener(SQLParseError.INSTANCE);
+    ParseTree tree;
     try {
-      soffset = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException(
-          "Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.");
+      tree = parser1.singleStatement();  // STAGE 1
     }
-    if (soffset < 0) {
-      throw new SQLParserException(
-          "SOFFSET <SOFFSETValue>: SOFFSETValue should >= 0.");
-    }
-    queryOp.setSeriesOffset(soffset);
-  }
-
-  @Override
-  public void enterInsertColumnSpec(InsertColumnSpecContext ctx) {
-    super.enterInsertColumnSpec(ctx);
-    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
-    List<String> measurementList = new ArrayList<>();
-    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
-      String measurement = nodeNameWithoutStar.getText();
-      measurementList.add(measurement);
-    }
-    insertOp.setMeasurementList(measurementList.toArray(new String[0]));
-  }
-
-  @Override
-  public void enterInsertValuesSpec(InsertValuesSpecContext ctx) {
-    super.enterInsertValuesSpec(ctx);
-    long timestamp;
-    if (ctx.dateFormat() != null) {
-      timestamp = parseTimeFormat(ctx.dateFormat().getText());
-    } else {
-      timestamp = Long.parseLong(ctx.INT().getText());
-    }
-    insertOp.setTime(timestamp);
-    List<String> valueList = new ArrayList<>();
-    List<ConstantContext> values = ctx.constant();
-    for (ConstantContext value : values) {
-      valueList.add(value.getText());
-    }
-    insertOp.setValueList(valueList.toArray(new String[0]));
-    initializedOperator = insertOp;
-  }
-
-  private PartialPath parseFullPath(FullPathContext ctx) {
-    List<NodeNameWithoutStarContext> nodeNamesWithoutStar = ctx.nodeNameWithoutStar();
-    String[] path = new String[nodeNamesWithoutStar.size() + 1];
-    int i = 0;
-    if (ctx.ROOT() != null) {
-      path[0] = ctx.ROOT().getText();
-    }
-    for (NodeNameWithoutStarContext nodeNameWithoutStar : nodeNamesWithoutStar) {
-      i++;
-      path[i] = nodeNameWithoutStar.getText();
-    }
-    return new PartialPath(path);
-  }
-
-  @Override
-  public void enterAttributeClauses(AttributeClausesContext ctx) {
-    super.enterAttributeClauses(ctx);
-    final String dataType = ctx.dataType().getChild(0).getText().toUpperCase();
-    final TSDataType tsDataType = TSDataType.valueOf(dataType);
-    createTimeSeriesOperator.setDataType(tsDataType);
-
-    final IoTDBDescriptor ioTDBDescriptor = IoTDBDescriptor.getInstance();
-    TSEncoding encoding = ioTDBDescriptor.getDefualtEncodingByType(tsDataType);
-    if (Objects.nonNull(ctx.encoding())) {
-      String encodingString = ctx.encoding().getChild(0).getText().toUpperCase();
-      encoding = TSEncoding.valueOf(encodingString);
-    }
-    createTimeSeriesOperator.setEncoding(encoding);
-
-    CompressionType compressor;
-    List<PropertyContext> properties = ctx.property();
-    if (ctx.compressor() != null) {
-      compressor = CompressionType.valueOf(ctx.compressor().getText().toUpperCase());
-    } else {
-      compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
-    }
-    Map<String, String> props = null;
-    if (ctx.property(0) != null) {
-      props = new HashMap<>(properties.size());
-      for (PropertyContext property : properties) {
-        props.put(property.ID().getText().toLowerCase(),
-            property.propertyValue().getText().toLowerCase());
-      }
-    }
-    createTimeSeriesOperator.setCompressor(compressor);
-    createTimeSeriesOperator.setProps(props);
-    initializedOperator = createTimeSeriesOperator;
-  }
-
-  @Override
-  public void enterIndexWithClause(SqlBaseParser.IndexWithClauseContext ctx) {
-    super.enterIndexWithClause(ctx);
-    IndexType indexType;
-    try {
-      indexType = IndexType.getIndexType(ctx.indexName.getText());
-    } catch (UnsupportedIndexTypeException e) {
-      throw new SQLParserException(
-          String.format(ctx.indexName.getText()));
-    }
-
-    List<PropertyContext> properties = ctx.property();
-    Map<String, String> props = new HashMap<>(properties.size(), 1);
-    if (ctx.property(0) != null) {
-      for (PropertyContext property : properties) {
-        String k = property.ID().getText().toUpperCase();
-        String v = property.propertyValue().getText().toUpperCase();
-        v = IndexUtils.removeQuotation(v);
-        props.put(k, v);
-      }
-    }
-
-    if (operatorType == SQLConstant.TOK_CREATE_INDEX) {
-      createIndexOp.setIndexType(indexType);
-      createIndexOp.setProps(props);
-    } else {
-      throw new SQLParserException("WITH clause only supports CREATE INDEX");
-    }
-  }
-
-  @Override
-  public void enterAliasClause(SqlBaseParser.AliasClauseContext ctx) {
-    super.enterAliasClause(ctx);
-    if (alterTimeSeriesOperator != null && ctx.ID() != null) {
-      alterTimeSeriesOperator.setAlias(ctx.ID().getText());
-    }
-  }
-
-
-  @Override
-  public void enterAttributeClause(AttributeClauseContext ctx) {
-    super.enterAttributeClause(ctx);
-    Map<String, String> attributes = extractMap(ctx.property(), ctx.property(0));
-    if (createTimeSeriesOperator != null) {
-      createTimeSeriesOperator.setAttributes(attributes);
-    } else if (alterTimeSeriesOperator != null) {
-      alterTimeSeriesOperator.setAttributesMap(attributes);
-    }
-  }
-
-  @Override
-  public void enterTagClause(TagClauseContext ctx) {
-    super.enterTagClause(ctx);
-    Map<String, String> tags = extractMap(ctx.property(), ctx.property(0));
-    if (createTimeSeriesOperator != null) {
-      createTimeSeriesOperator.setTags(tags);
-    } else if (alterTimeSeriesOperator != null) {
-      alterTimeSeriesOperator.setTagsMap(tags);
-    }
-  }
-
-  private Map<String, String> extractMap(List<PropertyContext> property2,
-      PropertyContext property3) {
-    String value;
-    Map<String, String> tags = new HashMap<>(property2.size());
-    if (property3 != null) {
-      for (PropertyContext property : property2) {
-        if (property.propertyValue().stringLiteral() != null) {
-          value = removeStringQuote(property.propertyValue().getText());
-        } else {
-          value = property.propertyValue().getText();
-        }
-        tags.put(property.ID().getText(), value);
-      }
-    }
-    return tags;
-  }
-
-  @Override
-  public void enterInsertStatement(InsertStatementContext ctx) {
-    super.enterInsertStatement(ctx);
-    insertOp = new InsertOperator(SQLConstant.TOK_INSERT);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    operatorType = SQLConstant.TOK_INSERT;
-    selectOp.addSelectPath(parsePrefixPath(ctx.prefixPath()));
-    insertOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterUpdateStatement(UpdateStatementContext ctx) {
-    super.enterUpdateStatement(ctx);
-    updateOp = new UpdateOperator(SQLConstant.TOK_UPDATE);
-    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
-    fromOp.addPrefixTablePath(parsePrefixPath(ctx.prefixPath()));
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    operatorType = SQLConstant.TOK_UPDATE;
-    initializedOperator = updateOp;
-  }
-
-  @Override
-  public void enterSelectStatement(SelectStatementContext ctx) {
-    super.enterSelectStatement(ctx);
-    operatorType = SQLConstant.TOK_QUERY;
-    queryOp = new QueryOperator(SQLConstant.TOK_QUERY);
-    initializedOperator = queryOp;
-  }
-
-  @Override
-  public void enterFromClause(FromClauseContext ctx) {
-    super.enterFromClause(ctx);
-    FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM);
-    List<PrefixPathContext> prefixFromPaths = ctx.prefixPath();
-    for (PrefixPathContext prefixFromPath : prefixFromPaths) {
-      PartialPath path = parsePrefixPath(prefixFromPath);
-      fromOp.addPrefixTablePath(path);
-    }
-    switch (operatorType) {
-      case SQLConstant.TOK_QUERY:
-        queryOp.setFromOperator(fromOp);
-        break;
-      case SQLConstant.TOK_QUERY_INDEX:
-        queryIndexOp.setFromOperator(fromOp);
-        break;
-      default:
-        throw new SQLParserException("From clause only support query and index query.");
-    }
-  }
-
-  @Override
-  public void enterFunctionElement(FunctionElementContext ctx) {
-    super.enterFunctionElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<FunctionCallContext> functionCallContextList = ctx.functionCall();
-    for (FunctionCallContext functionCallContext : functionCallContextList) {
-      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
-      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
-    }
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterSelectElement(SelectElementContext ctx) {
-    super.enterSelectElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<SqlBaseParser.SuffixPathOrConstantContext> suffixPathOrConstants = ctx.suffixPathOrConstant();
-    for (SqlBaseParser.SuffixPathOrConstantContext suffixPathOrConstant : suffixPathOrConstants) {
-      if (suffixPathOrConstant.suffixPath() != null) {
-        PartialPath path = parseSuffixPath(suffixPathOrConstant.suffixPath());
-        selectOp.addSelectPath(path);
-      } else {
-        PartialPath path = new PartialPath(new String[]{suffixPathOrConstant.SINGLE_QUOTE_STRING_LITERAL().getText()});
-        selectOp.addSelectPath(path);
-      }
-    }
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterLastElement(SqlBaseParser.LastElementContext ctx) {
-    super.enterLastElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    selectOp.setLastQuery();
-    LastClauseContext lastClauseContext = ctx.lastClause();
-    if (lastClauseContext.asClause().size() != 0) {
-      parseAsClause(lastClauseContext.asClause());
-    } else {
-      List<SuffixPathContext> suffixPaths = lastClauseContext.suffixPath();
-      for (SuffixPathContext suffixPath : suffixPaths) {
-        PartialPath path = parseSuffixPath(suffixPath);
-        selectOp.addSelectPath(path);
-      }
-    }
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterAsElement(AsElementContext ctx) {
-    super.enterAsElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    parseAsClause(ctx.asClause());
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  public void parseAsClause(List<AsClauseContext> asClauseContexts) {
-    for (AsClauseContext asClauseContext : asClauseContexts) {
-      PartialPath path = parseSuffixPath(asClauseContext.suffixPath());
-      if (asClauseContext.ID() != null) {
-        path.setTsAlias(asClauseContext.ID().toString());
-      }
-      selectOp.addSelectPath(path);
-    }
-  }
-
-  @Override
-  public void enterFunctionAsElement(FunctionAsElementContext ctx) {
-    super.enterFunctionAsElement(ctx);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<FunctionAsClauseContext> functionAsClauseContexts = ctx.functionAsClause();
-    for (FunctionAsClauseContext functionAsClauseContext : functionAsClauseContexts) {
-      FunctionCallContext functionCallContext = functionAsClauseContext.functionCall();
-      PartialPath path = parseSuffixPath(functionCallContext.suffixPath());
-      if (functionAsClauseContext.ID() != null) {
-        path.setTsAlias(functionAsClauseContext.ID().toString());
-      }
-      selectOp.addClusterPath(path, functionCallContext.functionName().getText());
-    }
-    queryOp.setSelectOperator(selectOp);
-  }
-
-  @Override
-  public void enterSetCol(SetColContext ctx) {
-    super.enterSetCol(ctx);
-    selectOp.addSelectPath(parseSuffixPath(ctx.suffixPath()));
-    updateOp.setSelectOperator(selectOp);
-    updateOp.setValue(ctx.constant().getText());
-  }
-
-
-  private PartialPath parsePrefixPath(PrefixPathContext ctx) {
-    List<NodeNameContext> nodeNames = ctx.nodeName();
-    String[] path = new String[nodeNames.size() + 1];
-    path[0] = ctx.ROOT().getText();
-    for (int i = 0; i < nodeNames.size(); i++) {
-      path[i + 1] = nodeNames.get(i).getText();
+    catch (Exception ex) {
+      CharStream charStream2 = CharStreams.fromString(sql);
+      SqlBaseLexer lexer2 = new SqlBaseLexer(charStream2);
+      CommonTokenStream tokens2 = new CommonTokenStream(lexer2);
+      SqlBaseParser parser2 = new SqlBaseParser(tokens2);
+      parser2.getInterpreter().setPredictionMode(PredictionMode.LL);
+      parser2.removeErrorListeners();
+      parser2.addErrorListener(SQLParseError.INSTANCE);
+      tree = parser2.singleStatement();  // STAGE 2
+      // if we parse ok, it's LL not SLL
     }
-    return new PartialPath(path);
+    return ioTDBSqlVisitor.visit(tree);
   }
-
-  /**
-   * parse duration to time value.
-   *
-   * @param durationStr represent duration string like: 12d8m9ns, 1y1mo, etc.
-   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
-   */
-  private Long parseDuration(String durationStr) {
-    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
-
-    long total = 0;
-    long tmp = 0;
-    for (int i = 0; i < durationStr.length(); i++) {
-      char ch = durationStr.charAt(i);
-      if (Character.isDigit(ch)) {
-        tmp *= 10;
-        tmp += (ch - '0');
-      } else {
-        String unit = durationStr.charAt(i) + "";
-        // This is to identify units with two letters.
-        if (i + 1 < durationStr.length() && !Character.isDigit(durationStr.charAt(i + 1))) {
-          i++;
-          unit += durationStr.charAt(i);
-        }
-        total += DatetimeUtils
-            .convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision);
-        tmp = 0;
-      }
-    }
-    if (total <= 0) {
-      throw new SQLParserException("Interval must more than 0.");
-    }
-    return total;
-  }
-
-  @Override
-  public void enterWhereClause(WhereClauseContext ctx) {
-    super.enterWhereClause(ctx);
-    FilterOperator whereOp = new FilterOperator(SQLConstant.TOK_WHERE);
-    whereOp.addChildOperator(parseOrExpression(ctx.orExpression()));
-    switch (operatorType) {
-      case SQLConstant.TOK_DELETE:
-        deleteDataOp.setFilterOperator(whereOp.getChildren().get(0));
-        Pair<Long, Long> timeInterval = parseDeleteTimeInterval(deleteDataOp);
-        deleteDataOp.setStartTime(timeInterval.left);
-        deleteDataOp.setEndTime(timeInterval.right);
-        break;
-      case SQLConstant.TOK_QUERY:
-        queryOp.setFilterOperator(whereOp.getChildren().get(0));
-        break;
-      case SQLConstant.TOK_UPDATE:
-        updateOp.setFilterOperator(whereOp.getChildren().get(0));
-        break;
-      case SQLConstant.TOK_CREATE_INDEX:
-        createIndexOp.setFilterOperator(whereOp.getChildren().get(0));
-        long indexTime = parseCreateIndexFilter(createIndexOp);
-        createIndexOp.setTime(indexTime);
-        break;
-      case SQLConstant.TOK_QUERY_INDEX:
-        checkQueryIndex(ctx);
-        break;
-      default:
-        throw new SQLParserException("Where only support select, delete, update, create index.");
-    }
-  }
-
-  @Override
-  public void enterShowWhereClause(ShowWhereClauseContext ctx) {
-    super.enterShowWhereClause(ctx);
-
-    ShowTimeSeriesOperator operator = (ShowTimeSeriesOperator) initializedOperator;
-    PropertyValueContext propertyValueContext;
-    if (ctx.containsExpression() != null) {
-      operator.setContains(true);
-      propertyValueContext = ctx.containsExpression().propertyValue();
-      operator.setKey(ctx.containsExpression().ID().getText());
-    } else {
-      operator.setContains(false);
-      propertyValueContext = ctx.property().propertyValue();
-      operator.setKey(ctx.property().ID().getText());
-    }
-    String value;
-    if (propertyValueContext.stringLiteral() != null) {
-      value = removeStringQuote(propertyValueContext.getText());
-    } else {
-      value = propertyValueContext.getText();
-    }
-    operator.setValue(value);
-  }
-
-  private FilterOperator parseOrExpression(OrExpressionContext ctx) {
-    if (ctx.andExpression().size() == 1) {
-      return parseAndExpression(ctx.andExpression(0));
-    }
-    FilterOperator binaryOp = new FilterOperator(SQLConstant.KW_OR);
-    if (ctx.andExpression().size() > 2) {
-      binaryOp.addChildOperator(parseAndExpression(ctx.andExpression(0)));
-      binaryOp.addChildOperator(parseAndExpression(ctx.andExpression(1)));
-      for (int i = 2; i < ctx.andExpression().size(); i++) {
-        FilterOperator op = new FilterOperator(SQLConstant.KW_OR);
-        op.addChildOperator(binaryOp);
-        op.addChildOperator(parseAndExpression(ctx.andExpression(i)));
-        binaryOp = op;
-      }
-    } else {
-      for (AndExpressionContext andExpressionContext : ctx.andExpression()) {
-        binaryOp.addChildOperator(parseAndExpression(andExpressionContext));
-      }
-    }
-    return binaryOp;
-  }
-
-  private FilterOperator parseAndExpression(AndExpressionContext ctx) {
-    if (ctx.predicate().size() == 1) {
-      return parsePredicate(ctx.predicate(0));
-    }
-    FilterOperator binaryOp = new FilterOperator(SQLConstant.KW_AND);
-    int size = ctx.predicate().size();
-    if (size > 2) {
-      binaryOp.addChildOperator(parsePredicate(ctx.predicate(0)));
-      binaryOp.addChildOperator(parsePredicate(ctx.predicate(1)));
-      for (int i = 2; i < size; i++) {
-        FilterOperator op = new FilterOperator(SQLConstant.KW_AND);
-        op.addChildOperator(binaryOp);
-        op.addChildOperator(parsePredicate(ctx.predicate(i)));
-        binaryOp = op;
-      }
-    } else {
-      for (PredicateContext predicateContext : ctx.predicate()) {
-        binaryOp.addChildOperator(parsePredicate(predicateContext));
-      }
-    }
-    return binaryOp;
-  }
-
-  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning
-  private FilterOperator parsePredicate(PredicateContext ctx) {
-    if (ctx.OPERATOR_NOT() != null) {
-      FilterOperator notOp = new FilterOperator(SQLConstant.KW_NOT);
-      notOp.addChildOperator(parseOrExpression(ctx.orExpression()));
-      return notOp;
-    } else if (ctx.LR_BRACKET() != null && ctx.OPERATOR_NOT() == null) {
-      return parseOrExpression(ctx.orExpression());
-    } else {
-      PartialPath path = null;
-      if (ctx.TIME() != null || ctx.TIMESTAMP() != null) {
-        path = new PartialPath(SQLConstant.getSingleTimeArray());
-      }
-      if (ctx.fullPath() != null) {
-        path = parseFullPath(ctx.fullPath());
-      }
-      if (ctx.suffixPath() != null) {
-        path = parseSuffixPath(ctx.suffixPath());
-      }
-      if (path == null) {
-        throw new SQLParserException("Path is null, please check the sql.");
-      }
-      if (ctx.inClause() != null) {
-        return parseInOperator(ctx.inClause(), path);
-      } else if (ctx.indexPredicateClause() != null) {
-        return parseIndexPredicate(ctx.indexPredicateClause(), path);
-      } else {
-        return parseBasicFunctionOperator(ctx, path);
-      }
-    }
-  }
-
-  private FilterOperator parseInOperator(InClauseContext ctx, PartialPath path) {
-    Set<String> values = new HashSet<>();
-    boolean not = ctx.OPERATOR_NOT() != null;
-    for (ConstantContext constant : ctx.constant()) {
-      if (constant.dateExpression() != null) {
-        if (!path.equals(TIME_PATH)) {
-          throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
-        }
-        values.add(Long.toString(parseDateExpression(constant.dateExpression())));
-      } else {
-        values.add(constant.getText());
-      }
-    }
-    return new InOperator(ctx.OPERATOR_IN().getSymbol().getType(), path, not, values);
-  }
-
-  private FilterOperator parseBasicFunctionOperator(PredicateContext ctx, PartialPath path) {
-    BasicFunctionOperator basic;
-    if (ctx.constant().dateExpression() != null) {
-      if (!path.equals(TIME_PATH)) {
-        throw new SQLParserException(path.getFullPath(), "Date can only be used to time");
-      }
-      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
-          Long.toString(parseDateExpression(ctx.constant().dateExpression())));
-    } else {
-      basic = new BasicFunctionOperator(ctx.comparisonOperator().type.getType(), path,
-          ctx.constant().getText());
-    }
-    return basic;
-  }
-
-  private PartialPath parseSuffixPath(SuffixPathContext ctx) {
-    List<NodeNameContext> nodeNames = ctx.nodeName();
-    String[] path = new String[nodeNames.size()];
-    for (int i = 0; i < nodeNames.size(); i++) {
-      path[i] = nodeNames.get(i).getText();
-    }
-    return new PartialPath(path);
-  }
-
-  /**
-   * parse time expression, which is addition and subtraction expression of duration time, now() or
-   * DataTimeFormat time. <p> eg. now() + 1d - 2h </p>
-   */
-  private Long parseDateExpression(DateExpressionContext ctx) {
-    long time = parseTimeFormat(ctx.getChild(0).getText());
-    for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
-      if (ctx.getChild(i).getText().equals("+")) {
-        time += parseDuration(ctx.getChild(i + 1).getText());
-      } else {
-        time -= parseDuration(ctx.getChild(i + 1).getText());
-      }
-    }
-    return time;
-  }
-
-  /**
-   * function for parsing time format.
-   */
-  long parseTimeFormat(String timestampStr) throws SQLParserException {
-    if (timestampStr == null || timestampStr.trim().equals("")) {
-      throw new SQLParserException("input timestamp cannot be empty");
-    }
-    long startupNano = IoTDBDescriptor.getInstance().getConfig().getStartUpNanosecond();
-    if (timestampStr.equalsIgnoreCase(SQLConstant.NOW_FUNC)) {
-      String timePrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
-      switch (timePrecision) {
-        case "ns":
-          return System.currentTimeMillis() * 1000_000
-              + (System.nanoTime() - startupNano) % 1000_000;
-        case "us":
-          return System.currentTimeMillis() * 1000
-              + (System.nanoTime() - startupNano) / 1000 % 1000;
-        default:
-          return System.currentTimeMillis();
-      }
-    }
-    try {
-      return DatetimeUtils.convertDatetimeStrToLong(timestampStr, zoneId);
-    } catch (Exception e) {
-      throw new SQLParserException(String
-          .format("Input time format %s error. "
-              + "Input like yyyy-MM-dd HH:mm:ss, yyyy-MM-ddTHH:mm:ss or "
-              + "refer to user document for more info.", timestampStr));
-    }
-  }
-
-  /**
-   * for delete command, time should only have an end time.
-   *
-   * @param operator delete logical plan
-   */
-  private Pair<Long, Long> parseDeleteTimeInterval(DeleteDataOperator operator) {
-    FilterOperator filterOperator = operator.getFilterOperator();
-    if (!filterOperator.isLeaf() && filterOperator.getTokenIntType() != SQLConstant.KW_AND) {
-      throw new SQLParserException(
-          DELETE_RANGE_ERROR_MSG);
-    }
-
-    if (filterOperator.isLeaf()) {
-      return calcOperatorInterval(filterOperator);
-    }
-
-    List<FilterOperator> children = filterOperator.getChildren();
-    FilterOperator lOperator = children.get(0);
-    FilterOperator rOperator = children.get(1);
-    if (!lOperator.isLeaf() || !rOperator.isLeaf()) {
-      throw new SQLParserException(
-          DELETE_RANGE_ERROR_MSG);
-    }
-
-    Pair<Long, Long> leftOpInterval = calcOperatorInterval(lOperator);
-    Pair<Long, Long> rightOpInterval = calcOperatorInterval(rOperator);
-    Pair<Long, Long> parsedInterval = new Pair<>(
-        Math.max(leftOpInterval.left, rightOpInterval.left),
-        Math.min(leftOpInterval.right, rightOpInterval.right));
-    if (parsedInterval.left > parsedInterval.right) {
-      throw new SQLParserException(
-          "Invalid delete range: [" + parsedInterval.left + ", " + parsedInterval.right + "]");
-    }
-    return parsedInterval;
-  }
-
-  private Pair<Long, Long> calcOperatorInterval(FilterOperator filterOperator) {
-    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
-    switch (filterOperator.getTokenIntType()) {
-      case SQLConstant.LESSTHAN:
-        return new Pair<>(Long.MIN_VALUE, time - 1);
-      case SQLConstant.LESSTHANOREQUALTO:
-        return new Pair<>(Long.MIN_VALUE, time);
-      case SQLConstant.GREATERTHAN:
-        return new Pair<>(time + 1, Long.MAX_VALUE);
-      case SQLConstant.GREATERTHANOREQUALTO:
-        return new Pair<>(time, Long.MAX_VALUE);
-      case SQLConstant.EQUAL:
-        return new Pair<>(time, time);
-      default:
-        throw new SQLParserException(
-            DELETE_RANGE_ERROR_MSG);
-    }
-  }
-
-  @Override
-  public void enterShowMergeStatus(ShowMergeStatusContext ctx) {
-    super.enterShowMergeStatus(ctx);
-    initializedOperator = new ShowMergeStatusOperator(SQLConstant.TOK_SHOW_MERGE_STATUS);
-  }
-
-  @Override
-  public void enterDeletePartition(DeletePartitionContext ctx) {
-    super.enterDeletePartition(ctx);
-    DeletePartitionOperator deletePartitionOperator = new DeletePartitionOperator(
-        SQLConstant.TOK_DELETE_PARTITION);
-    deletePartitionOperator.setStorageGroupName(parsePrefixPath(ctx.prefixPath()));
-    Set<Long> idSet = new HashSet<>();
-    for (TerminalNode terminalNode : ctx.INT()) {
-      idSet.add(Long.parseLong(terminalNode.getText()));
-    }
-    deletePartitionOperator.setPartitionIds(idSet);
-    initializedOperator = deletePartitionOperator;
-  }
-
-  @Override
-  public void enterCreateSnapshot(CreateSnapshotContext ctx) {
-    super.enterCreateSnapshot(ctx);
-    initializedOperator = new CreateSnapshotOperator(SQLConstant.TOK_CREATE_SCHEMA_SNAPSHOT);
-  }
-
-  /**
-   * for create index command, time should only have an end time.
-   *
-   * @param operator create index plan
-   */
-  private long parseCreateIndexFilter(CreateIndexOperator operator) {
-    FilterOperator filterOperator = operator.getFilterOperator();
-    if (filterOperator.getTokenIntType() != SQLConstant.GREATERTHAN
-        && filterOperator.getTokenIntType() != SQLConstant.GREATERTHANOREQUALTO) {
-      throw new SQLParserException(
-          "For create index command, where clause must be like : time > XXX or time >= XXX");
-    }
-    long time = Long.parseLong(((BasicFunctionOperator) filterOperator).getValue());
-    if (filterOperator.getTokenIntType() == SQLConstant.LESSTHAN) {
-      time = time - 1;
-    }
-    return time;
-  }
-
-  /**
-   * For parsing CreateIndex
-   *
-   * <p>The default implementation does nothing.</p>
-   */
-  @Override
-  public void enterCreateIndex(SqlBaseParser.CreateIndexContext ctx) {
-    super.enterCreateIndex(ctx);
-    createIndexOp = new CreateIndexOperator(SQLConstant.TOK_CREATE_INDEX);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
-    }
-    createIndexOp.setSelectOperator(selectOp);
-    initializedOperator = createIndexOp;
-    operatorType = SQLConstant.TOK_CREATE_INDEX;
-  }
-
-  @Override
-  public void enterDropIndex(SqlBaseParser.DropIndexContext ctx) {
-    super.enterDropIndex(ctx);
-    DropIndexOperator dropIndexOperator = new DropIndexOperator(SQLConstant.TOK_DROP_INDEX);
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath());
-    for (PrefixPathContext prefixPath : prefixPaths) {
-      PartialPath path = parsePrefixPath(prefixPath);
-      selectOp.addSelectPath(path);
-    }
-    dropIndexOperator.setSelectOperator(selectOp);
-    try {
-      dropIndexOperator.setIndexType(IndexType.getIndexType(ctx.indexName.getText()));
-    } catch (UnsupportedIndexTypeException e) {
-      throw new SQLParserException(
-          String.format(ctx.indexName.getText()));
-    }
-    initializedOperator = dropIndexOperator;
-    operatorType = SQLConstant.TOK_DROP_INDEX;
-  }
-
-  private FilterOperator parseIndexPredicate(IndexPredicateClauseContext ctx, PartialPath path) {
-    if (queryIndexOp != null) {
-      throw new SQLParserException("Index query statement allows only one index predicate");
-    }
-    if (RESERVED_TIME.equals(path.getFullPath())) {
-      throw new SQLParserException("In the index predicate, left path cannot be TIME");
-    }
-    queryIndexOp = new QueryIndexOperator(SQLConstant.TOK_QUERY_INDEX);
-    initializedOperator = queryIndexOp;
-    operatorType = SQLConstant.TOK_QUERY_INDEX;
-
-    Map<String, Object> props = new HashMap<>();
-    if (ctx.LIKE() != null) {
-      // whole matching case
-      if (indexTopK == NON_SET_TOP_K) {
-        throw new SQLParserException(
-            "TopK hasn't been set in the whole matching of similarity search");
-      }
-      if (queryOp.getSelectedPaths().size() != 1) {
-        throw new SQLParserException("Index query statement allows only one select path");
-      }
-      if (!path.equals(queryOp.getSelectedPaths().get(0))) {
-        throw new SQLParserException("In the index query statement, "
-            + "the path in select element and the index predicate should be same");
-      }
-      props.put(TOP_K, indexTopK);
-      props.put(PATTERN, parseSequence(ctx.sequenceClause(0)));
-      queryIndexOp.setIndexType(IndexType.RTREE_PAA);
-    } else if (ctx.CONTAIN() != null) {
-      // subsequence matching case
-      List<double[]> compositePattern = new ArrayList<>();
-      List<Double> thresholds = new ArrayList<>();
-      for (int i = 0; i < ctx.sequenceClause().size(); i++) {
-        compositePattern.add(parseSequence(ctx.sequenceClause(i)));
-        thresholds.add(Double.parseDouble(ctx.constant(i).getText()));
-      }
-      props.put(PATTERN, compositePattern);
-      props.put(THRESHOLD, thresholds);
-      queryIndexOp.setIndexType(IndexType.ELB_INDEX);
-    } else {
-      throw new SQLParserException("Unknown index predicate: " + ctx);
-    }
-    queryIndexOp.setFromOperator(queryOp.getFromOperator());
-    selectOp = new SelectOperator(SQLConstant.TOK_SELECT);
-    selectOp.addSelectPath(path);
-    queryIndexOp.setSelectOperator(selectOp);
-    queryOp = null;
-    queryIndexOp.setProps(props);
-    return null;
-  }
-
-  private double[] parseSequence(SequenceClauseContext ctx) {
-    int seqLen = ctx.constant().size();
-    double[] sequence = new double[seqLen];
-    for (int i = 0; i < seqLen; i++) {
-      sequence[i] = Double.parseDouble(ctx.constant(i).getText());
-    }
-    return sequence;
-  }
-
-  /**
-   * In query index statement, the where clause should have only one index predicate.
-   */
-  private void checkQueryIndex(WhereClauseContext ctx) {
-    boolean queryValid = true;
-    OrExpressionContext or = ctx.orExpression();
-    if (or.andExpression() == null || or.andExpression().size() != 1) {
-      queryValid = false;
-    } else {
-      AndExpressionContext and = or.andExpression(0);
-      if (and.predicate() == null || and.predicate(0).indexPredicateClause() == null)
-        queryValid = false;
-    }
-    if (!queryValid) {
-      throw new SQLParserException(
-          "In query index statement, the where clause should have and only have one index predicate.");
-    }
-  }
-
-  /**
-   * @param ctx Top ClauseContext
-   */
-  @Override
-  public void enterTopClause(TopClauseContext ctx) {
-    super.enterTopClause(ctx);
-    int top;
-    try {
-      top = Integer.parseInt(ctx.INT().getText());
-    } catch (NumberFormatException e) {
-      throw new SQLParserException("Out of range. TOP <N>: N should be Int32.");
-    }
-    if (top <= 0) {
-      throw new SQLParserException("TOP <N>: N should be greater than 0.");
-    }
-    indexTopK = top;
-  }
-
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/ParseDriver.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/ParseDriver.java
deleted file mode 100644
index 89b05e6..0000000
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/ParseDriver.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.qp.strategy;
-
-import java.time.ZoneId;
-import org.antlr.v4.runtime.CharStream;
-import org.antlr.v4.runtime.CharStreams;
-import org.antlr.v4.runtime.CommonTokenStream;
-import org.antlr.v4.runtime.atn.PredictionMode;
-import org.antlr.v4.runtime.misc.ParseCancellationException;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import org.apache.iotdb.db.qp.logical.Operator;
-
-/**
- * ParseDriver.
- *
- */
-public class ParseDriver {
-  private ParseTreeWalker walker;
-
-  public ParseDriver() {
-    walker = new ParseTreeWalker();
-  }
-
-  public Operator parse(String sql, ZoneId zoneId) throws ParseCancellationException {
-    LogicalGenerator logicalGenerator = new LogicalGenerator(zoneId);
-    CharStream charStream1 = CharStreams.fromString(sql);
-    SqlBaseLexer lexer1 = new SqlBaseLexer(charStream1);
-    CommonTokenStream tokens1 = new CommonTokenStream(lexer1);
-    SqlBaseParser parser1 = new SqlBaseParser(tokens1);
-    parser1.getInterpreter().setPredictionMode(PredictionMode.SLL);
-    parser1.removeErrorListeners();
-    parser1.addErrorListener(LogicalGeneratorError.INSTANCE);
-    ParseTree tree;
-    try {
-      tree = parser1.singleStatement();  // STAGE 1
-    }
-    catch (Exception ex) {
-      CharStream charStream2 = CharStreams.fromString(sql);
-      SqlBaseLexer lexer2 = new SqlBaseLexer(charStream2);
-      CommonTokenStream tokens2 = new CommonTokenStream(lexer2);
-      SqlBaseParser parser2 = new SqlBaseParser(tokens2);
-      parser2.getInterpreter().setPredictionMode(PredictionMode.LL);
-      parser2.removeErrorListeners();
-      parser2.addErrorListener(LogicalGeneratorError.INSTANCE);
-      tree = parser2.singleStatement();  // STAGE 2
-      // if we parse ok, it's LL not SLL
-    }
-    walker.walk(logicalGenerator, tree);
-    return logicalGenerator.getLogicalPlan();
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index 1a4dbe6..82add5a 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -41,7 +41,6 @@ import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
 import org.apache.iotdb.db.qp.logical.crud.DeleteDataOperator;
 import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
 import org.apache.iotdb.db.qp.logical.crud.InsertOperator;
-import org.apache.iotdb.db.qp.logical.crud.QueryIndexOperator;
 import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
@@ -215,9 +214,6 @@ public class PhysicalGenerator {
       case QUERY:
         QueryOperator query = (QueryOperator) operator;
         return transformQuery(query, fetchSize);
-      case QUERY_INDEX:
-        QueryIndexOperator queryIndexOp = (QueryIndexOperator) operator;
-        return transformQuery(queryIndexOp, fetchSize);
       case TTL:
         switch (operator.getTokenIntType()) {
           case SQLConstant.TOK_SET:
@@ -398,7 +394,7 @@ public class PhysicalGenerator {
       ((FillQueryPlan) queryPlan).setFillType(queryOperator.getFillTypes());
     } else if (queryOperator.isLastQuery()) {
       queryPlan = new LastQueryPlan();
-    } else if (queryOperator instanceof QueryIndexOperator) {
+    } else if (queryOperator.getIndexType() != null) {
       queryPlan = new QueryIndexPlan();
     } else {
       queryPlan = new RawDataQueryPlan();
@@ -608,9 +604,11 @@ public class PhysicalGenerator {
         }
       }
     }
-    if(queryOperator instanceof QueryIndexOperator) {
-      ((QueryIndexPlan) queryPlan).setIndexType(((QueryIndexOperator) queryOperator).getIndexType());
-      ((QueryIndexPlan) queryPlan).setProps(((QueryIndexOperator) queryOperator).getProps());
+    if(queryOperator.getIndexType() != null) {
+      if(queryPlan instanceof QueryIndexPlan) {
+        ((QueryIndexPlan) queryPlan).setIndexType(queryOperator.getIndexType());
+        ((QueryIndexPlan) queryPlan).setProps(queryOperator.getProps());
+      }
       return queryPlan;
     }
     try {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorError.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/SQLParseError.java
similarity index 89%
rename from server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorError.java
rename to server/src/main/java/org/apache/iotdb/db/qp/strategy/SQLParseError.java
index 69cd382..85c0e78 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorError.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/SQLParseError.java
@@ -23,9 +23,9 @@ import org.antlr.v4.runtime.RecognitionException;
 import org.antlr.v4.runtime.Recognizer;
 import org.antlr.v4.runtime.misc.ParseCancellationException;
 
-public class LogicalGeneratorError extends BaseErrorListener {
+public class SQLParseError extends BaseErrorListener {
 
-  public static final LogicalGeneratorError INSTANCE = new LogicalGeneratorError();
+  public static final SQLParseError INSTANCE = new SQLParseError();
 
   @Override
   public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
index cb68c38..2900138 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
@@ -33,7 +33,6 @@ import org.apache.iotdb.db.qp.logical.crud.BasicFunctionOperator;
 import org.apache.iotdb.db.qp.logical.crud.FilterOperator;
 import org.apache.iotdb.db.qp.logical.crud.FromOperator;
 import org.apache.iotdb.db.qp.logical.crud.FunctionOperator;
-import org.apache.iotdb.db.qp.logical.crud.QueryIndexOperator;
 import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.crud.SFWOperator;
 import org.apache.iotdb.db.qp.logical.crud.SelectOperator;
@@ -98,7 +97,7 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
         int seriesLimit = ((QueryOperator) operator).getSeriesLimit();
         int seriesOffset = ((QueryOperator) operator).getSeriesOffset();
         concatSelect(prefixPaths, select, seriesLimit, seriesOffset, maxDeduplicatedPathNum,
-            !(operator instanceof QueryIndexOperator));
+            ((QueryOperator) operator).getIndexType() == null);
       } else {
         isAlignByDevice = true;
         for (PartialPath path : initialSuffixPaths) {
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/IndexLogicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/IndexLogicalPlanTest.java
index f1bd22e..fc7dbd4 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/IndexLogicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/IndexLogicalPlanTest.java
@@ -31,27 +31,27 @@ import org.apache.iotdb.db.exception.metadata.IllegalPathException;
 import org.apache.iotdb.db.index.common.IndexType;
 import org.apache.iotdb.db.qp.logical.Operator;
 import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
-import org.apache.iotdb.db.qp.logical.crud.QueryIndexOperator;
+import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.sys.CreateIndexOperator;
 import org.apache.iotdb.db.qp.logical.sys.DropIndexOperator;
-import org.apache.iotdb.db.qp.strategy.ParseDriver;
+import org.apache.iotdb.db.qp.strategy.LogicalGenerator;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
 public class IndexLogicalPlanTest {
 
-  private ParseDriver parseDriver;
+  private LogicalGenerator generator;
 
   @Before
   public void before() {
-    parseDriver = new ParseDriver();
+    generator = new LogicalGenerator();
   }
 
   @Test
   public void testParseCreateIndexWholeMatching() {
     String sqlStr = "CREATE INDEX ON root.Ery.*.Glu WHERE time > 50 WITH INDEX=RTREE_PAA, PAA_dim=8";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(CreateIndexOperator.class, op.getClass());
     CreateIndexOperator createOperator = (CreateIndexOperator) op;
     Assert.assertEquals(OperatorType.CREATE_INDEX, createOperator.getType());
@@ -67,7 +67,7 @@ public class IndexLogicalPlanTest {
   @Test
   public void testParseCreateIndexSubMatching() {
     String sqlStr = "CREATE INDEX ON root.Wind.AZQ02.Speed WITH INDEX=ELB_INDEX, BLOCK_SIZE=5";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(CreateIndexOperator.class, op.getClass());
     CreateIndexOperator createOperator = (CreateIndexOperator) op;
     Assert.assertEquals(OperatorType.CREATE_INDEX, createOperator.getType());
@@ -83,7 +83,7 @@ public class IndexLogicalPlanTest {
   @Test
   public void testParseDropIndexWholeMatching() {
     String sqlStr = "DROP INDEX RTREE_PAA ON root.Ery.*.Glu";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(DropIndexOperator.class, op.getClass());
     DropIndexOperator dropIndexOperator = (DropIndexOperator) op;
     Assert.assertEquals(OperatorType.DROP_INDEX, dropIndexOperator.getType());
@@ -96,7 +96,7 @@ public class IndexLogicalPlanTest {
   @Test
   public void testParseDropIndexSubMatching() {
     String sqlStr = "DROP INDEX ELB_INDEX ON root.Wind.AZQ02.Speed";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(DropIndexOperator.class, op.getClass());
     DropIndexOperator dropIndexOperator = (DropIndexOperator) op;
     Assert.assertEquals(OperatorType.DROP_INDEX, dropIndexOperator.getType());
@@ -110,10 +110,10 @@ public class IndexLogicalPlanTest {
   @Test
   public void testParseQueryIndexWholeMatching() throws IllegalPathException {
     String sqlStr = "SELECT TOP 2 Glu FROM root.Ery.* WHERE Glu LIKE (0, 120, 20, 80, 120, 100, 80, 0)";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
-    Assert.assertEquals(QueryIndexOperator.class, op.getClass());
-    QueryIndexOperator queryOperator = (QueryIndexOperator) op;
-    Assert.assertEquals(OperatorType.QUERY_INDEX, queryOperator.getType());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
+    Assert.assertEquals(QueryOperator.class, op.getClass());
+    QueryOperator queryOperator = (QueryOperator) op;
+    Assert.assertEquals(OperatorType.QUERY, queryOperator.getType());
     Assert.assertEquals("Glu",
         queryOperator.getSelectedPaths().get(0).getFullPath());
     Assert.assertEquals("root.Ery.*",
@@ -131,10 +131,10 @@ public class IndexLogicalPlanTest {
         + "CONTAIN (15, 14, 12, 12, 12, 11) WITH TOLERANCE 1 "
         + "CONCAT (10, 20, 25, 24, 14, 8) WITH TOLERANCE 2 "
         + "CONCAT  (8, 9, 10, 14, 15, 15) WITH TOLERANCE 1";
-    Operator op = parseDriver.parse(sqlStr, ZoneId.systemDefault());
-    Assert.assertEquals(QueryIndexOperator.class, op.getClass());
-    QueryIndexOperator queryOperator = (QueryIndexOperator) op;
-    Assert.assertEquals(OperatorType.QUERY_INDEX, queryOperator.getType());
+    Operator op = generator.generate(sqlStr, ZoneId.systemDefault());
+    Assert.assertEquals(QueryOperator.class, op.getClass());
+    QueryOperator queryOperator = (QueryOperator) op;
+    Assert.assertEquals(OperatorType.QUERY, queryOperator.getType());
     Assert.assertEquals("Speed",
         queryOperator.getSelectedPaths().get(0).getFullPath());
     Assert.assertEquals("root.Wind.AZQ02",
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
index 614117e..f048a28 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/LogicalPlanSmallTest.java
@@ -32,7 +32,7 @@ import org.apache.iotdb.db.qp.logical.crud.DeleteDataOperator;
 import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
 import org.apache.iotdb.db.qp.logical.sys.DeleteStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
-import org.apache.iotdb.db.qp.strategy.ParseDriver;
+import org.apache.iotdb.db.qp.strategy.LogicalGenerator;
 import org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer;
 import org.apache.iotdb.db.service.IoTDB;
 import org.junit.Assert;
@@ -41,18 +41,18 @@ import org.junit.Test;
 
 public class LogicalPlanSmallTest {
 
-  private ParseDriver parseDriver;
+  private LogicalGenerator logicalGenerator;
 
   @Before
   public void before() {
-    parseDriver = new ParseDriver();
+    logicalGenerator = new LogicalGenerator();
   }
 
   @Test
   public void testLimit() {
     String sqlStr = "select * from root.vehicle.d1 limit 10";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertEquals(10, ((QueryOperator) operator).getRowLimit());
     Assert.assertEquals(0, ((QueryOperator) operator).getRowOffset());
@@ -63,8 +63,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testOffset() {
     String sqlStr = "select * from root.vehicle.d1 limit 10 offset 20";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertEquals(10, ((QueryOperator) operator).getRowLimit());
     Assert.assertEquals(20, ((QueryOperator) operator).getRowOffset());
@@ -75,8 +75,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testSlimit() {
     String sqlStr = "select * from root.vehicle.d1 limit 10 slimit 1";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertEquals(10, ((QueryOperator) operator).getRowLimit());
     Assert.assertEquals(0, ((QueryOperator) operator).getRowOffset());
@@ -87,8 +87,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testSOffset() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 50 slimit 10 soffset 100";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertEquals(50, ((QueryOperator) operator).getRowLimit());
     Assert.assertEquals(0, ((QueryOperator) operator).getRowOffset());
@@ -99,8 +99,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testSOffsetTimestamp() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and timestamp <= now() limit 50 slimit 10 soffset 100";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertEquals(50, ((QueryOperator) operator).getRowLimit());
     Assert.assertEquals(0, ((QueryOperator) operator).getRowOffset());
@@ -111,16 +111,16 @@ public class LogicalPlanSmallTest {
   @Test(expected = SQLParserException.class)
   public void testLimitOutOfRange() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 1111111111111111111111";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: Out of range. LIMIT <N>: N should be Int32.
   }
 
   @Test(expected = SQLParserException.class)
   public void testLimitNotPositive() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 0";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: LIMIT <N>: N should be greater than 0.
   }
 
@@ -128,32 +128,32 @@ public class LogicalPlanSmallTest {
   public void testOffsetOutOfRange() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() "
         + "limit 1 offset 1111111111111111111111";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: Out of range. OFFSET <OFFSETValue>: OFFSETValue should be Int32.
   }
 
   @Test(expected = ParseCancellationException.class)
   public void testOffsetNotPositive() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() limit 1 offset -1";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: OFFSET <OFFSETValue>: OFFSETValue should >= 0.
   }
 
   @Test(expected = SQLParserException.class)
   public void testSlimitOutOfRange() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() slimit 1111111111111111111111";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: Out of range. SLIMIT <SN>: SN should be Int32.
   }
 
   @Test(expected = SQLParserException.class)
   public void testSlimitNotPositive() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() slimit 0";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: SLIMIT <SN>: SN should be greater than 0.
   }
 
@@ -161,16 +161,16 @@ public class LogicalPlanSmallTest {
   public void testSoffsetOutOfRange() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() "
         + "slimit 1 soffset 1111111111111111111111";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     // expected to throw SQLParserException: Out of range. SOFFSET <SOFFSETValue>: SOFFSETValue should be Int32.
   }
 
   @Test
   public void testSoffsetNotPositive() {
     String sqlStr = "select * from root.vehicle.d1 where s1 < 20 and time <= now() slimit 1 soffset 1";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(1, ((QueryOperator) operator).getSeriesOffset());
     Assert.assertEquals(1, ((QueryOperator) operator).getSeriesLimit());
   }
@@ -178,8 +178,8 @@ public class LogicalPlanSmallTest {
   @Test(expected = LogicalOptimizeException.class)
   public void testSoffsetExceedColumnNum() throws QueryProcessException {
     String sqlStr = "select s1 from root.vehicle.d1 where s1 < 20 and time <= now() slimit 2 soffset 1";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     IoTDB.metaManager.init();
     ConcatPathOptimizer concatPathOptimizer = new ConcatPathOptimizer();
     concatPathOptimizer.transform(operator, 1000);
@@ -190,8 +190,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testDeleteStorageGroup() throws IllegalPathException {
     String sqlStr = "delete storage group root.vehicle.d1";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(DeleteStorageGroupOperator.class, operator.getClass());
     PartialPath path = new PartialPath("root.vehicle.d1");
     Assert.assertEquals(path, ((DeleteStorageGroupOperator) operator).getDeletePathList().get(0));
@@ -200,8 +200,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testDisableAlign() {
     String sqlStr = "select * from root.vehicle disable align";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertFalse(((QueryOperator) operator).isAlignByTime());
   }
@@ -209,8 +209,8 @@ public class LogicalPlanSmallTest {
   @Test
   public void testNotDisableAlign() {
     String sqlStr = "select * from root.vehicle";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     Assert.assertTrue(((QueryOperator) operator).isAlignByTime());
   }
@@ -218,21 +218,21 @@ public class LogicalPlanSmallTest {
   @Test(expected = ParseCancellationException.class)
   public void testDisableAlignConflictAlignByDevice() {
     String sqlStr = "select * from root.vehicle disable align align by device";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr, ZoneId.systemDefault());
   }
 
   @Test
   public void testChineseCharacter() throws IllegalPathException {
     String sqlStr1 = "set storage group to root.一级";
-    RootOperator operator = (RootOperator) parseDriver
-        .parse(sqlStr1, ZoneId.systemDefault());
+    RootOperator operator = (RootOperator) logicalGenerator
+        .generate(sqlStr1, ZoneId.systemDefault());
     Assert.assertEquals(SetStorageGroupOperator.class, operator.getClass());
     Assert.assertEquals(new PartialPath("root.一级"), ((SetStorageGroupOperator) operator).getPath());
 
     String sqlStr2 = "select * from root.一级.设备1 limit 10 offset 20";
-    operator = (RootOperator) parseDriver
-        .parse(sqlStr2, ZoneId.systemDefault());
+    operator = (RootOperator) logicalGenerator
+        .generate(sqlStr2, ZoneId.systemDefault());
     Assert.assertEquals(QueryOperator.class, operator.getClass());
     ArrayList<PartialPath> paths = new ArrayList<>();
     paths.add(new PartialPath("*"));
@@ -252,7 +252,7 @@ public class LogicalPlanSmallTest {
               + "FIRST_VALUE.SUM.LAST_VALUE.LAST.DISABLE.ALIGN.COMPRESSION.TIME.ATTRIBUTES.TAGS.RENAME.FULL.CLEAR.CACHE."
               + "SNAPSHOT.FOR.SCHEMA.TRACING.OFF where time>=1 and time < 3";
 
-      Operator op = parseDriver.parse(sql, ZoneId.systemDefault());
+      Operator op = logicalGenerator.generate(sql, ZoneId.systemDefault());
       Assert.assertEquals(DeleteDataOperator.class, op.getClass());
     } catch (ParseCancellationException ignored) {
     }
@@ -261,7 +261,7 @@ public class LogicalPlanSmallTest {
   @Test
   public void testRangeDelete() throws IllegalPathException {
     String sql1 = "delete from root.d1.s1 where time>=1 and time < 3";
-    Operator op = parseDriver.parse(sql1, ZoneId.systemDefault());
+    Operator op = logicalGenerator.generate(sql1, ZoneId.systemDefault());
     Assert.assertEquals(DeleteDataOperator.class, op.getClass());
     ArrayList<PartialPath> paths = new ArrayList<>();
     paths.add(new PartialPath("root.d1.s1"));
@@ -270,37 +270,37 @@ public class LogicalPlanSmallTest {
     Assert.assertEquals(2, ((DeleteDataOperator) op).getEndTime());
 
     String sql2 = "delete from root.d1.s1 where time>=1";
-    op = parseDriver.parse(sql2, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql2, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(1, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(Long.MAX_VALUE, ((DeleteDataOperator) op).getEndTime());
 
     String sql3 = "delete from root.d1.s1 where time>1";
-    op = parseDriver.parse(sql3, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql3, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(2, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(Long.MAX_VALUE, ((DeleteDataOperator) op).getEndTime());
 
     String sql4 = "delete from root.d1.s1 where time <= 1";
-    op = parseDriver.parse(sql4, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql4, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(Long.MIN_VALUE, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(1, ((DeleteDataOperator) op).getEndTime());
 
     String sql5 = "delete from root.d1.s1 where time<1";
-    op = parseDriver.parse(sql5, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql5, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(Long.MIN_VALUE, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(0, ((DeleteDataOperator) op).getEndTime());
 
     String sql6 = "delete from root.d1.s1 where time = 3";
-    op = parseDriver.parse(sql6, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql6, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(3, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(3, ((DeleteDataOperator) op).getEndTime());
 
     String sql7 = "delete from root.d1.s1 where time > 5 and time >= 2";
-    op = parseDriver.parse(sql7, ZoneId.systemDefault());
+    op = logicalGenerator.generate(sql7, ZoneId.systemDefault());
     Assert.assertEquals(paths, ((DeleteDataOperator) op).getSelectedPaths());
     Assert.assertEquals(6, ((DeleteDataOperator) op).getStartTime());
     Assert.assertEquals(Long.MAX_VALUE, ((DeleteDataOperator) op).getEndTime());
@@ -311,7 +311,7 @@ public class LogicalPlanSmallTest {
     String sql = "delete from root.d1.s1 where time>=1 and time < 3 or time >1";
     String errorMsg = null;
     try {
-      parseDriver.parse(sql, ZoneId.systemDefault());
+      logicalGenerator.generate(sql, ZoneId.systemDefault());
     } catch (SQLParserException e) {
       errorMsg = e.getMessage();
     }
@@ -323,7 +323,7 @@ public class LogicalPlanSmallTest {
     sql = "delete from root.d1.s1 where time>=1 or time < 3";
     errorMsg = null;
     try {
-      parseDriver.parse(sql, ZoneId.systemDefault());
+      logicalGenerator.generate(sql, ZoneId.systemDefault());
     } catch (SQLParserException e) {
       errorMsg = e.getMessage();
     }
@@ -335,7 +335,7 @@ public class LogicalPlanSmallTest {
     String sql7 = "delete from root.d1.s1 where time = 1 and time < -1";
     errorMsg = null;
     try {
-      parseDriver.parse(sql7, ZoneId.systemDefault());
+      logicalGenerator.generate(sql7, ZoneId.systemDefault());
     } catch (RuntimeException e) {
       errorMsg = e.getMessage();
     }
@@ -344,7 +344,7 @@ public class LogicalPlanSmallTest {
     sql = "delete from root.d1.s1 where time > 5 and time <= 0";
     errorMsg = null;
     try {
-      parseDriver.parse(sql, ZoneId.systemDefault());
+      logicalGenerator.generate(sql, ZoneId.systemDefault());
     } catch (SQLParserException e) {
       errorMsg = e.getMessage();
     }
diff --git a/server/src/test/java/org/apache/iotdb/db/sql/DatetimeQueryDataSetUtilsTest.java b/server/src/test/java/org/apache/iotdb/db/qp/sql/DatetimeQueryDataSetUtilsTest.java
similarity index 99%
rename from server/src/test/java/org/apache/iotdb/db/sql/DatetimeQueryDataSetUtilsTest.java
rename to server/src/test/java/org/apache/iotdb/db/qp/sql/DatetimeQueryDataSetUtilsTest.java
index c3043e3..1052f45 100644
--- a/server/src/test/java/org/apache/iotdb/db/sql/DatetimeQueryDataSetUtilsTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/sql/DatetimeQueryDataSetUtilsTest.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.sql;
+package org.apache.iotdb.db.qp.sql;
 
 import static org.junit.Assert.assertEquals;
 
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorTest.java b/server/src/test/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorTest.java
index c19a69c..cbf11e2 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/strategy/LogicalGeneratorTest.java
@@ -28,17 +28,19 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.query.LogicalOperatorException;
 import org.apache.iotdb.db.exception.runtime.SQLParserException;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
+import org.apache.iotdb.db.qp.sql.IoTDBSqlVisitor;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
 public class LogicalGeneratorTest {
 
-  LogicalGenerator generator;
+  IoTDBSqlVisitor visitor;
 
   @Before
   public void setUp() throws Exception {
-    generator = new LogicalGenerator(ZonedDateTime.now().getOffset());
+    visitor = new IoTDBSqlVisitor();
+    visitor.setZoneId(ZonedDateTime.now().getOffset());
   }
 
   @After
@@ -46,8 +48,8 @@ public class LogicalGeneratorTest {
   }
 
   @Test
-  public void testParseTimeFormatNow() throws LogicalOperatorException {
-    long now = generator.parseTimeFormat(SQLConstant.NOW_FUNC);
+  public void testParseTimeFormatNow() {
+    long now = visitor.parseTimeFormat(SQLConstant.NOW_FUNC);
     for (int i = 0; i <= 12; i++) {
       ZoneOffset offset1, offset2;
       if (i < 10) {
@@ -68,18 +70,18 @@ public class LogicalGeneratorTest {
   }
 
   @Test
-  public void testParseTimeFormatNowPrecision() throws LogicalOperatorException {
+  public void testParseTimeFormatNowPrecision() {
     String timePrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
     IoTDBDescriptor.getInstance().getConfig().setTimestampPrecision("ms");
-    long now_ms = generator.parseTimeFormat(SQLConstant.NOW_FUNC);
+    long now_ms = visitor.parseTimeFormat(SQLConstant.NOW_FUNC);
     String ms_str = String.valueOf(now_ms);
 
     IoTDBDescriptor.getInstance().getConfig().setTimestampPrecision("us");
-    long now_us = generator.parseTimeFormat(SQLConstant.NOW_FUNC);
+    long now_us = visitor.parseTimeFormat(SQLConstant.NOW_FUNC);
     String us_str = String.valueOf(now_us);
 
     IoTDBDescriptor.getInstance().getConfig().setTimestampPrecision("ns");
-    long now_ns = generator.parseTimeFormat(SQLConstant.NOW_FUNC);
+    long now_ns = visitor.parseTimeFormat(SQLConstant.NOW_FUNC);
     String ns_str = String.valueOf(now_ns);
 
     assertEquals(ms_str.length() + 3, (us_str).length());
@@ -88,12 +90,12 @@ public class LogicalGeneratorTest {
   }
 
   @Test(expected = SQLParserException.class)
-  public void testParseTimeFormatFail1() throws LogicalOperatorException {
-    generator.parseTimeFormat(null);
+  public void testParseTimeFormatFail1() {
+    visitor.parseTimeFormat(null);
   }
 
   @Test(expected = SQLParserException.class)
-  public void testParseTimeFormatFail2() throws LogicalOperatorException {
-    generator.parseTimeFormat("");
+  public void testParseTimeFormatFail2() {
+    visitor.parseTimeFormat("");
   }
 }