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

hui pushed a commit to branch lmh/FixSqlOrder
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit bf472b60a273efc9b81cb61213dbbb28c9a26f79
Author: liuminghui233 <[email protected]>
AuthorDate: Wed Nov 23 16:34:24 2022 +0800

    refactor IoTDBSqlParser.g4 & ASTVisitor
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   | 203 +++----
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       | 635 +++++++--------------
 .../db/mpp/plan/statement/crud/QueryStatement.java |   3 +
 3 files changed, 290 insertions(+), 551 deletions(-)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index eee28fb877..9ec8a4c9dc 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -291,12 +291,12 @@ showStorageGroup
 
 // Show Devices
 showDevices
-    : SHOW DEVICES prefixPath? (WITH (STORAGE GROUP | DATABASE))? limitClause?
+    : SHOW DEVICES prefixPath? (WITH (STORAGE GROUP | DATABASE))? 
rowPaginationClause?
     ;
 
 // Show Timeseries
 showTimeseries
-    : SHOW LATEST? TIMESERIES prefixPath? tagWhereClause? limitClause?
+    : SHOW LATEST? TIMESERIES prefixPath? tagWhereClause? rowPaginationClause?
     ;
 
 // Show Child Paths
@@ -413,63 +413,75 @@ selectStatement
     : selectClause
         intoClause?
         fromClause
-        whereClause? specialClause?
+        whereClause?
+        groupByClause?
+        havingClause?
+        orderByClause?
+        fillClause?
+        paginationClause?
+        alignByClause?
+    | selectClause
+        intoClause?
+        fromClause
+        whereClause?
+        groupByClause?
+        havingClause?
+        fillClause?
+        orderByClause?
+        paginationClause?
+        alignByClause?
     ;
 
-intoClause
-    : INTO ALIGNED? intoPath (COMMA intoPath)*
-    | INTO intoItem (COMMA intoItem)*
+// ---- Select Clause
+selectClause
+    : SELECT LAST? resultColumn (COMMA resultColumn)*
     ;
 
-intoPath
-    : ROOT (DOT nodeNameInIntoPath)* #fullPathInIntoPath
-    | nodeNameInIntoPath (DOT nodeNameInIntoPath)* #suffixPathInIntoPath
+resultColumn
+    : expression (AS alias)?
     ;
 
-intoItem
-    : ALIGNED? intoPath LR_BRACKET nodeNameInIntoPath (COMMA 
nodeNameInIntoPath)* RR_BRACKET
+// ---- Into Clause
+intoClause
+    : INTO intoItem (COMMA intoItem)*
     ;
 
-nodeNameInIntoPath
-    : nodeNameWithoutWildcard
-    | DOUBLE_COLON
+intoItem
+    : ALIGNED? intoPath LR_BRACKET nodeNameInIntoPath (COMMA 
nodeNameInIntoPath)* RR_BRACKET
     ;
 
-specialClause
-    : specialLimit #specialLimitStatement
-    | orderByClause specialLimit? #orderByTimeStatement
-    | groupByTimeClause havingClause? orderByClause? specialLimit? 
#groupByTimeStatement
-    | groupByFillClause havingClause? orderByClause? specialLimit? 
#groupByFillStatement
-    | groupByLevelClause havingClause? orderByClause? specialLimit? 
#groupByLevelStatement
-    | groupByTagClause havingClause? orderByClause? specialLimit? 
#groupByTagStatement
-    | fillClause orderByClause? specialLimit? #fillStatement
+// ---- From Clause
+fromClause
+    : FROM prefixPath (COMMA prefixPath)*
     ;
 
-specialLimit
-    : limitClause slimitClause? alignByDeviceClauseOrDisableAlign? 
#limitStatement
-    | slimitClause limitClause? alignByDeviceClauseOrDisableAlign? 
#slimitStatement
-    | withoutNullClause limitClause? slimitClause? 
alignByDeviceClauseOrDisableAlign? #withoutNullStatement
-    | alignByDeviceClauseOrDisableAlign 
#alignByDeviceClauseOrDisableAlignStatement
+// ---- Where Clause
+whereClause
+    : WHERE expression
     ;
 
-havingClause
-    : HAVING expression
+// ---- Group By Clause
+groupByClause
+    : GROUP BY groupByAttributeClause (COMMA groupByAttributeClause)*
     ;
 
-alignByDeviceClauseOrDisableAlign
-    : alignByDeviceClause
-    | disableAlign
+groupByAttributeClause
+    : TIME? LR_BRACKET (timeRange COMMA)? interval=DURATION_LITERAL (COMMA 
step=DURATION_LITERAL)? RR_BRACKET
+    | LEVEL operator_eq INTEGER_LITERAL (COMMA INTEGER_LITERAL)*
+    | TAGS LR_BRACKET identifier (COMMA identifier)* RR_BRACKET
     ;
 
-alignByDeviceClause
-    : ALIGN BY DEVICE
-    | GROUP BY DEVICE
+timeRange
+    : LS_BRACKET startTime=timeValue COMMA endTime=timeValue RR_BRACKET
+    | LR_BRACKET startTime=timeValue COMMA endTime=timeValue RS_BRACKET
     ;
 
-disableAlign
-    : DISABLE ALIGN
+// ---- Having Clause
+havingClause
+    : HAVING expression
     ;
 
+// ---- Order By Clause
 orderByClause
     : ORDER BY orderByAttributeClause (COMMA orderByAttributeClause)*
     ;
@@ -484,62 +496,48 @@ sortKey
     | DEVICE
     ;
 
-groupByTimeClause
-    : GROUP BY TIME? LR_BRACKET (timeRange COMMA)? interval=DURATION_LITERAL 
(COMMA step=DURATION_LITERAL)? fillClause? RR_BRACKET
-    | GROUP BY TIME? LR_BRACKET (timeRange COMMA)? interval=DURATION_LITERAL 
(COMMA step=DURATION_LITERAL)? RR_BRACKET
-    COMMA LEVEL operator_eq INTEGER_LITERAL (COMMA INTEGER_LITERAL)* 
fillClause?
-    | GROUP BY TIME? LR_BRACKET (timeRange COMMA)? interval=DURATION_LITERAL 
(COMMA step=DURATION_LITERAL)? RR_BRACKET
-    COMMA TAGS LR_BRACKET identifier (COMMA identifier)* RR_BRACKET
-    ;
-
-groupByFillClause
-    : GROUP BY TIME? LR_BRACKET (timeRange COMMA)? interval=DURATION_LITERAL 
(COMMA step=DURATION_LITERAL)? RR_BRACKET
-    fillClause
-    ;
-
-groupByLevelClause
-    : GROUP BY LEVEL operator_eq INTEGER_LITERAL (COMMA INTEGER_LITERAL)* 
fillClause?
+// ---- Fill Clause
+fillClause
+    : FILL LR_BRACKET (LINEAR | PREVIOUS | constant) RR_BRACKET
     ;
 
-groupByTagClause
-    : GROUP BY TAGS LR_BRACKET identifier (COMMA identifier)* RR_BRACKET
+// ---- Pagination Clause
+paginationClause
+    : seriesPaginationClause rowPaginationClause?
+    | rowPaginationClause seriesPaginationClause?
     ;
 
-fillClause
-    : FILL LR_BRACKET (linearClause | previousClause | specificValueClause | 
previousUntilLastClause | oldTypeClause (COMMA oldTypeClause)*) RR_BRACKET
+rowPaginationClause
+    : limitClause offsetClause?
+    | offsetClause? limitClause
     ;
 
-withoutNullClause
-    : WITHOUT NULL_LITERAL (ALL | ANY) (LR_BRACKET expression (COMMA 
expression)* RR_BRACKET)?
+seriesPaginationClause
+    : slimitClause soffsetClause?
+    | soffsetClause? slimitClause
     ;
 
-oldTypeClause
-    : (ALL | dataType=attributeValue) LS_BRACKET linearClause RS_BRACKET
-    | (ALL | dataType=attributeValue) LS_BRACKET previousClause RS_BRACKET
-    | (ALL | dataType=attributeValue) LS_BRACKET specificValueClause RS_BRACKET
-    | (ALL | dataType=attributeValue) LS_BRACKET previousUntilLastClause 
RS_BRACKET
+limitClause
+    : LIMIT rowLimit=INTEGER_LITERAL
     ;
 
-linearClause
-    : LINEAR (COMMA aheadDuration=DURATION_LITERAL COMMA 
behindDuration=DURATION_LITERAL)?
+offsetClause
+    : OFFSET rowOffset=INTEGER_LITERAL
     ;
 
-previousClause
-    : PREVIOUS (COMMA DURATION_LITERAL)?
+slimitClause
+    : SLIMIT seriesLimit=INTEGER_LITERAL
     ;
 
-specificValueClause
-    : constant?
+soffsetClause
+    : SOFFSET seriesOffset=INTEGER_LITERAL
     ;
 
-previousUntilLastClause
-    : PREVIOUSUNTILLAST (COMMA DURATION_LITERAL)?
+// ---- Align By Clause
+alignByClause
+    : ALIGN BY (TIME | DEVICE)
     ;
 
-timeRange
-    : LS_BRACKET startTime=timeValue COMMA endTime=timeValue RR_BRACKET
-    | LR_BRACKET startTime=timeValue COMMA endTime=timeValue RS_BRACKET
-    ;
 
 // Insert Statement
 insertStatement
@@ -566,11 +564,7 @@ measurementValue
 
 // Delete Statement
 deleteStatement
-    : DELETE FROM prefixPath (COMMA prefixPath)* (whereClause)?
-    ;
-
-whereClause
-    : WHERE expression
+    : DELETE FROM prefixPath (COMMA prefixPath)* whereClause?
     ;
 
 /**
@@ -853,6 +847,11 @@ suffixPath
     : nodeName (DOT nodeName)*
     ;
 
+intoPath
+    : ROOT (DOT nodeNameInIntoPath)* #fullPathInIntoPath
+    | nodeNameInIntoPath (DOT nodeNameInIntoPath)* #suffixPathInIntoPath
+    ;
+
 nodeName
     : wildcard
     | wildcard? identifier wildcard?
@@ -863,6 +862,11 @@ nodeNameWithoutWildcard
     : identifier
     ;
 
+nodeNameInIntoPath
+    : nodeNameWithoutWildcard
+    | DOUBLE_COLON
+    ;
+
 wildcard
     : STAR
     | DOUBLE_STAR
@@ -938,25 +942,6 @@ operator_eq
     | OPERATOR_DEQ
     ;
 
-
-// Select Clause
-
-selectClause
-    : SELECT LAST? resultColumn (COMMA resultColumn)*
-    ;
-
-resultColumn
-    : expression (AS alias)?
-    ;
-
-
-// From Clause
-
-fromClause
-    : FROM prefixPath (COMMA prefixPath)*
-    ;
-
-
 // Attribute Clause
 
 attributeClauses
@@ -996,23 +981,3 @@ attributeValue
     : identifier
     | constant
     ;
-
-// Limit & Offset Clause
-
-limitClause
-    : LIMIT INTEGER_LITERAL offsetClause?
-    | offsetClause? LIMIT INTEGER_LITERAL
-    ;
-
-offsetClause
-    : OFFSET INTEGER_LITERAL
-    ;
-
-slimitClause
-    : SLIMIT INTEGER_LITERAL soffsetClause?
-    | soffsetClause? SLIMIT INTEGER_LITERAL
-    ;
-
-soffsetClause
-    : SOFFSET INTEGER_LITERAL
-    ;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index f2557cc6f3..cc453de4dd 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -165,8 +165,6 @@ import 
org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CountTimeseriesContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.CreateFunctionContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.DropFunctionContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ExpressionContext;
-import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.GroupByTagClauseContext;
-import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.GroupByTagStatementContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.IdentifierContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParser.ShowFunctionsContext;
 import org.apache.iotdb.db.qp.sql.IoTDBSqlParserBaseVisitor;
@@ -192,7 +190,6 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;
@@ -209,10 +206,6 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       "For delete statement, where clause can only contain time expressions, "
           + "value filter is not currently supported.";
 
-  /** For create-cq clause and select-into clause, used to match "{x}", where 
x is an integer. */
-  private static final Pattern leveledPathNodePattern = 
Pattern.compile("\\$\\{\\w+}");
-
-  // TODO: add comment
   private ZoneId zoneId;
 
   public void setZoneId(ZoneId zoneId) {
@@ -566,8 +559,14 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     if (ctx.tagWhereClause() != null) {
       parseTagWhereClause(ctx.tagWhereClause(), showTimeSeriesStatement);
     }
-    if (ctx.limitClause() != null) {
-      parseLimitClause(ctx.limitClause(), showTimeSeriesStatement);
+    if (ctx.rowPaginationClause() != null) {
+      if (ctx.rowPaginationClause().limitClause() != null) {
+        
showTimeSeriesStatement.setLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
+      }
+      if (ctx.rowPaginationClause().offsetClause() != null) {
+        showTimeSeriesStatement.setOffset(
+            parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
+      }
     }
     return showTimeSeriesStatement;
   }
@@ -624,8 +623,13 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       showDevicesStatement =
           new ShowDevicesStatement(new 
PartialPath(SQLConstant.getSingleRootArray()));
     }
-    if (ctx.limitClause() != null) {
-      parseLimitClause(ctx.limitClause(), showDevicesStatement);
+    if (ctx.rowPaginationClause() != null) {
+      if (ctx.rowPaginationClause().limitClause() != null) {
+        
showDevicesStatement.setLimit(parseLimitClause(ctx.rowPaginationClause().limitClause()));
+      }
+      if (ctx.rowPaginationClause().offsetClause() != null) {
+        
showDevicesStatement.setOffset(parseOffsetClause(ctx.rowPaginationClause().offsetClause()));
+      }
     }
     // show devices with database
     if (ctx.WITH() != null) {
@@ -907,39 +911,108 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
   /** Data Manipulation Language (DML) */
 
   // Select Statement 
========================================================================
-
-  private QueryStatement queryStatement;
-
   @Override
   public Statement visitSelectStatement(IoTDBSqlParser.SelectStatementContext 
ctx) {
-    // initialize query statement
-    queryStatement = new QueryStatement();
+    QueryStatement queryStatement = new QueryStatement();
 
-    // parse select, from
-    parseSelectClause(ctx.selectClause());
-    parseFromClause(ctx.fromClause());
+    // parse SELECT & FROM
+    queryStatement.setSelectComponent(parseSelectClause(ctx.selectClause()));
+    queryStatement.setFromComponent(parseFromClause(ctx.fromClause()));
 
-    // parse into clause
+    // parse INTO
     if (ctx.intoClause() != null) {
-      parseIntoClause(ctx.intoClause());
+      queryStatement.setIntoComponent(parseIntoClause(ctx.intoClause()));
     }
 
-    // parse where clause
+    // parse WHERE
     if (ctx.whereClause() != null) {
-      WhereCondition whereCondition = parseWhereClause(ctx.whereClause());
-      queryStatement.setWhereCondition(whereCondition);
+      queryStatement.setWhereCondition(parseWhereClause(ctx.whereClause()));
+    }
+
+    // parse GROUP BY
+    if (ctx.groupByClause() != null) {
+      Set<String> groupByKeys = new HashSet<>();
+      List<IoTDBSqlParser.GroupByAttributeClauseContext> groupByAttributes =
+          ctx.groupByClause().groupByAttributeClause();
+      for (IoTDBSqlParser.GroupByAttributeClauseContext groupByAttribute : 
groupByAttributes) {
+        if (groupByAttribute.TIME() != null || groupByAttribute.interval != 
null) {
+          if (groupByKeys.contains("TIME")) {
+            throw new SemanticException("duplicated group by key: TIME");
+          }
+
+          groupByKeys.add("TIME");
+          
queryStatement.setGroupByTimeComponent(parseGroupByTimeClause(groupByAttribute));
+        } else if (groupByAttribute.LEVEL() != null) {
+          if (groupByKeys.contains("LEVEL")) {
+            throw new SemanticException("duplicated group by key: LEVEL");
+          }
+
+          groupByKeys.add("LEVEL");
+          
queryStatement.setGroupByLevelComponent(parseGroupByLevelClause(groupByAttribute));
+        } else if (groupByAttribute.TAGS() != null) {
+          if (groupByKeys.contains("TAGS")) {
+            throw new SemanticException("duplicated group by key: TAGS");
+          }
+
+          groupByKeys.add("TAGS");
+          
queryStatement.setGroupByTagComponent(parseGroupByTagClause(groupByAttribute));
+        } else {
+          throw new SQLParserException("Unknown GROUP BY type.");
+        }
+      }
+    }
+
+    // parse HAVING
+    if (ctx.havingClause() != null) {
+      queryStatement.setHavingCondition(parseHavingClause(ctx.havingClause()));
+    }
+
+    // parse ORDER BY
+    if (ctx.orderByClause() != null) {
+      
queryStatement.setOrderByComponent(parseOrderByClause(ctx.orderByClause()));
+    }
+
+    // parse FILL
+    if (ctx.fillClause() != null) {
+      queryStatement.setFillComponent(parseFillClause(ctx.fillClause()));
+    }
+
+    if (ctx.paginationClause() != null) {
+      // parse SLIMIT & SOFFSET
+      if (ctx.paginationClause().seriesPaginationClause() != null) {
+        if (ctx.paginationClause().seriesPaginationClause().slimitClause() != 
null) {
+          queryStatement.setSeriesLimit(
+              
parseSLimitClause(ctx.paginationClause().seriesPaginationClause().slimitClause()));
+        }
+        if (ctx.paginationClause().seriesPaginationClause().soffsetClause() != 
null) {
+          queryStatement.setSeriesOffset(
+              
parseSOffsetClause(ctx.paginationClause().seriesPaginationClause().soffsetClause()));
+        }
+      }
+
+      // parse LIMIT & OFFSET
+      if (ctx.paginationClause().rowPaginationClause() != null) {
+        if (ctx.paginationClause().rowPaginationClause().limitClause() != 
null) {
+          queryStatement.setRowLimit(
+              
parseLimitClause(ctx.paginationClause().rowPaginationClause().limitClause()));
+        }
+        if (ctx.paginationClause().rowPaginationClause().offsetClause() != 
null) {
+          queryStatement.setRowOffset(
+              
parseOffsetClause(ctx.paginationClause().rowPaginationClause().offsetClause()));
+        }
+      }
     }
 
-    // parser special clause
-    if (ctx.specialClause() != null) {
-      queryStatement = (QueryStatement) visit(ctx.specialClause());
+    // parse ALIGN BY
+    if (ctx.alignByClause() != null) {
+      queryStatement.setResultSetFormat(parseAlignBy(ctx.alignByClause()));
     }
+
     return queryStatement;
   }
 
-  // Select Clause
-
-  public void parseSelectClause(IoTDBSqlParser.SelectClauseContext ctx) {
+  // ---- Select Clause
+  private SelectComponent parseSelectClause(IoTDBSqlParser.SelectClauseContext 
ctx) {
     SelectComponent selectComponent = new SelectComponent(zoneId);
 
     // parse LAST
@@ -962,8 +1035,7 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     }
     selectComponent.setAliasToColumnMap(aliasToColumnMap);
 
-    // set selectComponent
-    queryStatement.setSelectComponent(selectComponent);
+    return selectComponent;
   }
 
   private ResultColumn parseResultColumn(IoTDBSqlParser.ResultColumnContext 
resultColumnContext) {
@@ -980,128 +1052,60 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     return new ResultColumn(expression, alias, columnType);
   }
 
-  // From Clause
-
-  public void parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
+  // ---- From Clause
+  private FromComponent parseFromClause(IoTDBSqlParser.FromClauseContext ctx) {
     FromComponent fromComponent = new FromComponent();
     List<IoTDBSqlParser.PrefixPathContext> prefixFromPaths = ctx.prefixPath();
     for (IoTDBSqlParser.PrefixPathContext prefixFromPath : prefixFromPaths) {
       PartialPath path = parsePrefixPath(prefixFromPath);
       fromComponent.addPrefixPath(path);
     }
-    queryStatement.setFromComponent(fromComponent);
+    return fromComponent;
   }
 
-  // Where Clause
-
-  public WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext 
ctx) {
-    Expression predicate =
-        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == 
null);
-    return new WhereCondition(predicate);
-  }
-
-  // Group By Time Clause
-
-  @Override
-  public Statement 
visitGroupByTimeStatement(IoTDBSqlParser.GroupByTimeStatementContext ctx) {
-    // parse group by time clause
-    parseGroupByTimeClause(ctx.groupByTimeClause());
-
-    // parse order by time
-    if (ctx.orderByClause() != null) {
-      parseOrderByClause(ctx.orderByClause());
+  // ---- Into Clause
+  private IntoComponent parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
+    List<IntoItem> intoItems = new ArrayList<>();
+    for (IoTDBSqlParser.IntoItemContext intoItemContext : ctx.intoItem()) {
+      intoItems.add(parseIntoItem(intoItemContext));
     }
-
-    // parse Having
-    if (ctx.havingClause() != null) {
-      parseHavingClause(ctx.havingClause());
-    }
-
-    // parse limit & offset
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
-    }
-
-    return queryStatement;
+    return new IntoComponent(intoItems);
   }
 
-  @Override
-  public Statement 
visitGroupByFillStatement(IoTDBSqlParser.GroupByFillStatementContext ctx) {
-    // parse group by time clause & fill clause
-    parseGroupByTimeClause(ctx.groupByFillClause());
-
-    // parse order by time
-    if (ctx.orderByClause() != null) {
-      parseOrderByClause(ctx.orderByClause());
-    }
-
-    // parse Having
-    if (ctx.havingClause() != null) {
-      parseHavingClause(ctx.havingClause());
-    }
-
-    // parse limit & offset
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
-    }
-    return queryStatement;
+  private IntoItem parseIntoItem(IoTDBSqlParser.IntoItemContext 
intoItemContext) {
+    boolean isAligned = intoItemContext.ALIGNED() != null;
+    PartialPath intoDevice = parseIntoPath(intoItemContext.intoPath());
+    List<String> intoMeasurements =
+        intoItemContext.nodeNameInIntoPath().stream()
+            .map(this::parseNodeNameInIntoPath)
+            .collect(Collectors.toList());
+    return new IntoItem(intoDevice, intoMeasurements, isAligned);
   }
 
-  private void parseGroupByTimeClause(IoTDBSqlParser.GroupByTimeClauseContext 
ctx) {
-    GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();
-
-    // parse time range
-    if (ctx.timeRange() != null) {
-      parseTimeRange(ctx.timeRange(), groupByTimeComponent);
-      groupByTimeComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != 
null);
-    }
-
-    // parse time interval
-    groupByTimeComponent.setInterval(
-        parseTimeIntervalOrSlidingStep(ctx.interval.getText(), true, 
groupByTimeComponent));
-    if (groupByTimeComponent.getInterval() <= 0) {
-      throw new SemanticException(
-          "The second parameter time interval should be a positive integer.");
-    }
-
-    // parse sliding step
-    if (ctx.step != null) {
-      groupByTimeComponent.setSlidingStep(
-          parseTimeIntervalOrSlidingStep(ctx.step.getText(), false, 
groupByTimeComponent));
+  private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext 
intoPathContext) {
+    if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
+      return 
parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) 
intoPathContext);
     } else {
-      groupByTimeComponent.setSlidingStep(groupByTimeComponent.getInterval());
-      
groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
-    }
-
-    // parse GroupByLevel clause
-    if (ctx.LEVEL() != null && ctx.INTEGER_LITERAL() != null) {
-      GroupByLevelComponent groupByLevelComponent = new 
GroupByLevelComponent();
-      int[] levels = new int[ctx.INTEGER_LITERAL().size()];
-      for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
-        levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
-      }
-      groupByLevelComponent.setLevels(levels);
-      queryStatement.setGroupByLevelComponent(groupByLevelComponent);
-    }
-
-    if (ctx.TAGS() != null) {
-      List<String> tagKeys = new ArrayList<>();
-      for (IdentifierContext identifierContext : ctx.identifier()) {
-        tagKeys.add(identifierContext.getText());
+      List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
+          ((IoTDBSqlParser.SuffixPathInIntoPathContext) 
intoPathContext).nodeNameInIntoPath();
+      String[] path = new String[nodeNames.size()];
+      for (int i = 0; i < nodeNames.size(); i++) {
+        path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
       }
-      queryStatement.setGroupByTagComponent(new GroupByTagComponent(tagKeys));
-    }
-
-    // parse fill clause
-    if (ctx.fillClause() != null) {
-      parseFillClause(ctx.fillClause());
+      return new PartialPath(path);
     }
+  }
 
-    // set groupByTimeComponent
-    queryStatement.setGroupByTimeComponent(groupByTimeComponent);
+  // ---- Where Clause
+  private WhereCondition parseWhereClause(IoTDBSqlParser.WhereClauseContext 
ctx) {
+    Expression predicate =
+        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == 
null);
+    return new WhereCondition(predicate);
   }
 
-  private void parseGroupByTimeClause(IoTDBSqlParser.GroupByFillClauseContext 
ctx) {
+  // ---- Group By Clause
+  private GroupByTimeComponent parseGroupByTimeClause(
+      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
     GroupByTimeComponent groupByTimeComponent = new GroupByTimeComponent();
 
     // parse time range
@@ -1127,16 +1131,10 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       
groupByTimeComponent.setSlidingStepByMonth(groupByTimeComponent.isIntervalByMonth());
     }
 
-    // parse fill clause
-    if (ctx.fillClause() != null) {
-      parseFillClause(ctx.fillClause());
-    }
-
-    // set groupByTimeComponent
-    queryStatement.setGroupByTimeComponent(groupByTimeComponent);
+    return groupByTimeComponent;
   }
 
-  /** parse time range (startTime and endTime) in group by query. */
+  /** parse time range (startTime and endTime) in group by time. */
   private void parseTimeRange(
       IoTDBSqlParser.TimeRangeContext timeRange, GroupByTimeComponent 
groupByClauseComponent) {
     long currentTime = DateTimeUtils.currentTime();
@@ -1167,71 +1165,19 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     return DateTimeUtils.convertDurationStrToLong(duration);
   }
 
-  // Group By Level Clause
-  @Override
-  public Statement 
visitGroupByLevelStatement(IoTDBSqlParser.GroupByLevelStatementContext ctx) {
-    // parse GroupByLevel clause
-    parseGroupByLevelClause(ctx.groupByLevelClause());
-
-    // parse order by time
-    if (ctx.orderByClause() != null) {
-      parseOrderByClause(ctx.orderByClause());
-    }
-
-    // parse Having
-    if (ctx.havingClause() != null) {
-      parseHavingClause(ctx.havingClause());
-    }
-
-    // parse limit & offset
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
-    }
-    return queryStatement;
-  }
-
-  public void parseGroupByLevelClause(IoTDBSqlParser.GroupByLevelClauseContext 
ctx) {
+  private GroupByLevelComponent parseGroupByLevelClause(
+      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
     GroupByLevelComponent groupByLevelComponent = new GroupByLevelComponent();
     int[] levels = new int[ctx.INTEGER_LITERAL().size()];
     for (int i = 0; i < ctx.INTEGER_LITERAL().size(); i++) {
       levels[i] = Integer.parseInt(ctx.INTEGER_LITERAL().get(i).getText());
     }
     groupByLevelComponent.setLevels(levels);
-
-    // parse fill clause
-    if (ctx.fillClause() != null) {
-      parseFillClause(ctx.fillClause());
-    }
-
-    queryStatement.setGroupByLevelComponent(groupByLevelComponent);
-  }
-
-  // HAVING Clause
-  public void parseHavingClause(IoTDBSqlParser.HavingClauseContext ctx) {
-    Expression predicate =
-        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == 
null);
-    queryStatement.setHavingCondition(new HavingCondition(predicate));
-  }
-
-  @Override
-  public Statement visitGroupByTagStatement(GroupByTagStatementContext ctx) {
-    // parse group by tag clause
-    parseGroupByTagClause(ctx.groupByTagClause());
-
-    // parse order by time
-    if (ctx.orderByClause() != null) {
-      parseOrderByClause(ctx.orderByClause());
-    }
-
-    // parse limit & offset
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
-    }
-
-    return queryStatement;
+    return groupByLevelComponent;
   }
 
-  public void parseGroupByTagClause(GroupByTagClauseContext ctx) {
+  private GroupByTagComponent parseGroupByTagClause(
+      IoTDBSqlParser.GroupByAttributeClauseContext ctx) {
     Set<String> tagKeys = new LinkedHashSet<>();
     for (IdentifierContext identifierContext : ctx.identifier()) {
       String key = parseIdentifier(identifierContext.getText());
@@ -1240,53 +1186,56 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       }
       tagKeys.add(key);
     }
-    queryStatement.setGroupByTagComponent(new GroupByTagComponent(new 
ArrayList<>(tagKeys)));
+    return new GroupByTagComponent(new ArrayList<>(tagKeys));
   }
 
-  // Fill Clause
-  @Override
-  public Statement visitFillStatement(IoTDBSqlParser.FillStatementContext ctx) 
{
-    // parse fill
-    parseFillClause(ctx.fillClause());
+  // ---- Having Clause
+  private HavingCondition parseHavingClause(IoTDBSqlParser.HavingClauseContext 
ctx) {
+    Expression predicate =
+        parseExpression(ctx.expression(), ctx.expression().OPERATOR_NOT() == 
null);
+    return new HavingCondition(predicate);
+  }
 
-    // parse order by time
-    if (ctx.orderByClause() != null) {
-      parseOrderByClause(ctx.orderByClause());
-    }
+  // ---- Order By Clause
+  private OrderByComponent 
parseOrderByClause(IoTDBSqlParser.OrderByClauseContext ctx) {
+    OrderByComponent orderByComponent = new OrderByComponent();
+    Set<SortKey> sortKeySet = new HashSet<>();
+    for (IoTDBSqlParser.OrderByAttributeClauseContext 
orderByAttributeClauseContext :
+        ctx.orderByAttributeClause()) {
+      SortItem sortItem = 
parseOrderByAttributeClause(orderByAttributeClauseContext);
 
-    // parse limit & offset
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
+      SortKey sortKey = sortItem.getSortKey();
+      if (sortKeySet.contains(sortKey)) {
+        throw new SemanticException(String.format("ORDER BY: duplicate sort 
key '%s'", sortKey));
+      } else {
+        sortKeySet.add(sortKey);
+        orderByComponent.addSortItem(sortItem);
+      }
     }
-    return queryStatement;
+    return orderByComponent;
+  }
+
+  private SortItem 
parseOrderByAttributeClause(IoTDBSqlParser.OrderByAttributeClauseContext ctx) {
+    return new SortItem(
+        SortKey.valueOf(ctx.sortKey().getText().toUpperCase()),
+        ctx.DESC() != null ? Ordering.DESC : Ordering.ASC);
   }
 
-  public void parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
+  // ---- Fill Clause
+  public FillComponent parseFillClause(IoTDBSqlParser.FillClauseContext ctx) {
     FillComponent fillComponent = new FillComponent();
-    if (ctx.linearClause() != null) {
-      if (ctx.linearClause().DURATION_LITERAL().size() > 0) {
-        throw new SemanticException("The specified fill time range is not 
supported.");
-      }
+    if (ctx.LINEAR() != null) {
       fillComponent.setFillPolicy(FillPolicy.LINEAR);
-    } else if (ctx.previousClause() != null) {
-      if (ctx.previousClause().DURATION_LITERAL() != null) {
-        throw new SemanticException("The specified fill time range is not 
supported.");
-      }
+    } else if (ctx.PREVIOUS() != null) {
       fillComponent.setFillPolicy(FillPolicy.PREVIOUS);
-    } else if (ctx.specificValueClause() != null) {
+    } else if (ctx.constant() != null) {
       fillComponent.setFillPolicy(FillPolicy.VALUE);
-      if (ctx.specificValueClause().constant() != null) {
-        Literal fillValue = parseLiteral(ctx.specificValueClause().constant());
-        fillComponent.setFillValue(fillValue);
-      } else {
-        throw new SemanticException("fill value cannot be null");
-      }
-    } else if (ctx.previousUntilLastClause() != null) {
-      throw new SemanticException("PREVIOUSUNTILLAST fill is not supported 
yet.");
-    } else if (ctx.oldTypeClause() != null) {
-      throw new SemanticException("The specified fill datatype is not 
supported.");
+      Literal fillValue = parseLiteral(ctx.constant());
+      fillComponent.setFillValue(fillValue);
+    } else {
+      throw new SemanticException("Unknown FILL type.");
     }
-    queryStatement.setFillComponent(fillComponent);
+    return fillComponent;
   }
 
   private Literal parseLiteral(ConstantContext constantContext) {
@@ -1306,36 +1255,8 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     }
   }
 
-  // Other Clauses
-  @Override
-  public Statement 
visitSpecialLimitStatement(IoTDBSqlParser.SpecialLimitStatementContext ctx) {
-    return visit(ctx.specialLimit());
-  }
-
-  @Override
-  public Statement visitLimitStatement(IoTDBSqlParser.LimitStatementContext 
ctx) {
-    if ((ctx.limitClause() != null || ctx.slimitClause() != null)
-        && queryStatement.isGroupByTag()) {
-      // TODO: I will support limit and slimit in later PRs
-      throw new SemanticException("Limit or slimit are not supported yet in 
GROUP BY TAGS");
-    }
-    // parse LIMIT
-    parseLimitClause(ctx.limitClause(), queryStatement);
-
-    // parse SLIMIT
-    if (ctx.slimitClause() != null) {
-      parseSlimitClause(ctx.slimitClause());
-    }
-
-    // parse ALIGN BY DEVICE or DISABLE ALIGN
-    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
-      
parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
-    }
-    return queryStatement;
-  }
-
   // parse LIMIT & OFFSET
-  private void parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx, 
Statement statement) {
+  private int parseLimitClause(IoTDBSqlParser.LimitClauseContext ctx) {
     int limit;
     try {
       limit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
@@ -1345,22 +1266,10 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     if (limit <= 0) {
       throw new SemanticException("LIMIT <N>: N should be greater than 0.");
     }
-    if (statement instanceof ShowTimeSeriesStatement) {
-      ((ShowTimeSeriesStatement) statement).setLimit(limit);
-    } else if (statement instanceof ShowDevicesStatement) {
-      ((ShowDevicesStatement) statement).setLimit(limit);
-    } else {
-      queryStatement.setRowLimit(limit);
-    }
-
-    // parse OFFSET
-    if (ctx.offsetClause() != null) {
-      parseOffsetClause(ctx.offsetClause(), statement);
-    }
+    return limit;
   }
 
-  // parse OFFSET
-  private void parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx, 
Statement statement) {
+  private int parseOffsetClause(IoTDBSqlParser.OffsetClauseContext ctx) {
     int offset;
     try {
       offset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
@@ -1371,34 +1280,11 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     if (offset < 0) {
       throw new SemanticException("OFFSET <OFFSETValue>: OFFSETValue should >= 
0.");
     }
-    if (statement instanceof ShowTimeSeriesStatement) {
-      ((ShowTimeSeriesStatement) statement).setOffset(offset);
-    } else if (statement instanceof ShowDevicesStatement) {
-      ((ShowDevicesStatement) statement).setOffset(offset);
-    } else {
-      queryStatement.setRowOffset(offset);
-    }
-  }
-
-  @Override
-  public Statement visitSlimitStatement(IoTDBSqlParser.SlimitStatementContext 
ctx) {
-    // parse SLIMIT
-    parseSlimitClause(ctx.slimitClause());
-
-    // parse LIMIT
-    if (ctx.limitClause() != null) {
-      parseLimitClause(ctx.limitClause(), queryStatement);
-    }
-
-    // parse ALIGN BY DEVICE or DISABLE ALIGN
-    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
-      
parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
-    }
-    return queryStatement;
+    return offset;
   }
 
   // parse SLIMIT & SOFFSET
-  private void parseSlimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
+  private int parseSLimitClause(IoTDBSqlParser.SlimitClauseContext ctx) {
     int slimit;
     try {
       slimit = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
@@ -1408,16 +1294,11 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     if (slimit <= 0) {
       throw new SemanticException("SLIMIT <SN>: SN should be greater than 0.");
     }
-    queryStatement.setSeriesLimit(slimit);
-
-    // parse SOFFSET
-    if (ctx.soffsetClause() != null) {
-      parseSoffsetClause(ctx.soffsetClause());
-    }
+    return slimit;
   }
 
   // parse SOFFSET
-  public void parseSoffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
+  public int parseSOffsetClause(IoTDBSqlParser.SoffsetClauseContext ctx) {
     int soffset;
     try {
       soffset = Integer.parseInt(ctx.INTEGER_LITERAL().getText());
@@ -1428,130 +1309,15 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
     if (soffset < 0) {
       throw new SemanticException("SOFFSET <SOFFSETValue>: SOFFSETValue should 
>= 0.");
     }
-    queryStatement.setSeriesOffset(soffset);
+    return soffset;
   }
 
-  // WITHOUT NULL Clause
-
-  @Override
-  public Statement 
visitWithoutNullStatement(IoTDBSqlParser.WithoutNullStatementContext ctx) {
-    // parse WITHOUT NULL
-    parseWithoutNullClause(ctx.withoutNullClause());
-
-    // parse LIMIT & OFFSET
-    if (ctx.limitClause() != null) {
-      parseLimitClause(ctx.limitClause(), queryStatement);
-    }
-
-    // parse SLIMIT & SOFFSET
-    if (ctx.slimitClause() != null) {
-      parseSlimitClause(ctx.slimitClause());
-    }
-
-    // parse ALIGN BY DEVICE or DISABLE ALIGN
-    if (ctx.alignByDeviceClauseOrDisableAlign() != null) {
-      
parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
-    }
-    return queryStatement;
-  }
-
-  // parse WITHOUT NULL
-  private void parseWithoutNullClause(IoTDBSqlParser.WithoutNullClauseContext 
ctx) {
-    throw new SemanticException("WITHOUT NULL clause is not supported yet.");
-  }
-
-  // ORDER BY TIME Clause
-
-  @Override
-  public Statement 
visitOrderByTimeStatement(IoTDBSqlParser.OrderByTimeStatementContext ctx) {
-    // parse ORDER BY TIME
-    parseOrderByClause(ctx.orderByClause());
-
-    // parse others
-    if (ctx.specialLimit() != null) {
-      return visit(ctx.specialLimit());
-    }
-    return queryStatement;
-  }
-
-  // parse ORDER BY TIME
-  private void parseOrderByClause(IoTDBSqlParser.OrderByClauseContext ctx) {
-    OrderByComponent orderByComponent = new OrderByComponent();
-    Set<SortKey> sortKeySet = new HashSet<>();
-    for (IoTDBSqlParser.OrderByAttributeClauseContext 
orderByAttributeClauseContext :
-        ctx.orderByAttributeClause()) {
-      SortItem sortItem = 
parseOrderByAttributeClause(orderByAttributeClauseContext);
-
-      SortKey sortKey = sortItem.getSortKey();
-      if (sortKeySet.contains(sortKey)) {
-        throw new SemanticException(String.format("ORDER BY: duplicate sort 
key '%s'", sortKey));
-      } else {
-        sortKeySet.add(sortKey);
-        orderByComponent.addSortItem(sortItem);
-      }
-    }
-    queryStatement.setOrderByComponent(orderByComponent);
-  }
-
-  private SortItem 
parseOrderByAttributeClause(IoTDBSqlParser.OrderByAttributeClauseContext ctx) {
-    return new SortItem(
-        SortKey.valueOf(ctx.sortKey().getText().toUpperCase()),
-        ctx.DESC() != null ? Ordering.DESC : Ordering.ASC);
-  }
-
-  // ResultSetFormat Clause
-
-  @Override
-  public Statement visitAlignByDeviceClauseOrDisableAlignStatement(
-      IoTDBSqlParser.AlignByDeviceClauseOrDisableAlignStatementContext ctx) {
-    
parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign());
-    return queryStatement;
-  }
-
-  private void parseAlignByDeviceClauseOrDisableAlign(
-      IoTDBSqlParser.AlignByDeviceClauseOrDisableAlignContext ctx) {
-    if (ctx.alignByDeviceClause() != null) {
-      queryStatement.setResultSetFormat(ResultSetFormat.ALIGN_BY_DEVICE);
-    } else {
-      queryStatement.setResultSetFormat(ResultSetFormat.DISABLE_ALIGN);
-    }
-  }
-
-  // parse INTO clause
-
-  private void parseIntoClause(IoTDBSqlParser.IntoClauseContext ctx) {
-    if (ctx.intoItem().size() > 0) {
-      List<IntoItem> intoItems = new ArrayList<>();
-      for (IoTDBSqlParser.IntoItemContext intoItemContext : ctx.intoItem()) {
-        intoItems.add(parseIntoItem(intoItemContext));
-      }
-      queryStatement.setIntoComponent(new IntoComponent(intoItems));
+  // ---- Align By Clause
+  private ResultSetFormat parseAlignBy(IoTDBSqlParser.AlignByClauseContext 
ctx) {
+    if (ctx.DEVICE() != null) {
+      return ResultSetFormat.ALIGN_BY_DEVICE;
     } else {
-      throw new SemanticException("The syntax of SELECT INTO statement has 
changed from v0.14");
-    }
-  }
-
-  private IntoItem parseIntoItem(IoTDBSqlParser.IntoItemContext 
intoItemContext) {
-    boolean isAligned = intoItemContext.ALIGNED() != null;
-    PartialPath intoDevice = parseIntoPath(intoItemContext.intoPath());
-    List<String> intoMeasurements =
-        intoItemContext.nodeNameInIntoPath().stream()
-            .map(this::parseNodeNameInIntoPath)
-            .collect(Collectors.toList());
-    return new IntoItem(intoDevice, intoMeasurements, isAligned);
-  }
-
-  private PartialPath parseIntoPath(IoTDBSqlParser.IntoPathContext 
intoPathContext) {
-    if (intoPathContext instanceof IoTDBSqlParser.FullPathInIntoPathContext) {
-      return 
parseFullPathInIntoPath((IoTDBSqlParser.FullPathInIntoPathContext) 
intoPathContext);
-    } else {
-      List<IoTDBSqlParser.NodeNameInIntoPathContext> nodeNames =
-          ((IoTDBSqlParser.SuffixPathInIntoPathContext) 
intoPathContext).nodeNameInIntoPath();
-      String[] path = new String[nodeNames.size()];
-      for (int i = 0; i < nodeNames.size(); i++) {
-        path[i] = parseNodeNameInIntoPath(nodeNames.get(i));
-      }
-      return new PartialPath(path);
+      return ResultSetFormat.ALIGN_BY_TIME;
     }
   }
 
@@ -3070,7 +2836,12 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
   private void parseSelectStatementForPipe(
       IoTDBSqlParser.SelectStatementContext ctx, CreatePipeStatement statement)
       throws SQLParserException {
-    if (ctx.intoClause() != null || ctx.specialClause() != null) {
+    if (ctx.intoClause() != null
+        || ctx.groupByClause() != null
+        || ctx.havingClause() != null
+        || ctx.fillClause() != null
+        || ctx.paginationClause() != null
+        || ctx.alignByClause() != null) {
       throw new SQLParserException("Not support for this sql in pipe.");
     }
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
index c36680252c..049c955829 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/crud/QueryStatement.java
@@ -353,6 +353,9 @@ public class QueryStatement extends Statement {
             throw new SemanticException("Output column is duplicated with the 
tag key: " + s);
           }
         }
+        if (rowLimit > 0 || rowOffset > 0 || seriesLimit > 0 || seriesOffset > 
0) {
+          throw new SemanticException("Limit or slimit are not supported yet 
in GROUP BY TAGS");
+        }
       }
     } else {
       if (isGroupByTime() || isGroupByLevel()) {


Reply via email to