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

ericpai pushed a commit to branch feature/iotdb-4639
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 2159cc751607f253bbc9890f0c07497aed0ec07e
Author: ericpai <[email protected]>
AuthorDate: Wed Oct 19 10:34:03 2022 +0800

    Add special limit clause for group by tags
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  2 +-
 .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java  |  5 ++-
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |  5 +++
 .../db/mpp/plan/statement/crud/QueryStatement.java | 19 +++++++++---
 .../iotdb/db/mpp/plan/plan/LogicalPlannerTest.java | 36 ++++++++++++++++++++++
 5 files changed, 60 insertions(+), 7 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 5ef759a569..5621932b60 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
@@ -428,7 +428,7 @@ specialClause
     | groupByTimeClause havingClause? orderByClause? specialLimit? 
#groupByTimeStatement
     | groupByFillClause havingClause? orderByClause? specialLimit? 
#groupByFillStatement
     | groupByLevelClause havingClause? orderByClause? specialLimit? 
#groupByLevelStatement
-    | groupByTagClause orderByClause? #groupByTagStatement
+    | groupByTagClause orderByClause? specialLimit? #groupByTagStatement
     | fillClause orderByClause? specialLimit? #fillStatement
     ;
 
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 925d5558ec..6cb199c569 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -381,7 +381,10 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       boolean hasAlias = resultColumn.hasAlias();
       List<Expression> resultExpressions =
           
ExpressionAnalyzer.removeWildcardInExpression(resultColumn.getExpression(), 
schemaTree);
-      if (hasAlias && !queryStatement.isGroupByLevel() && 
resultExpressions.size() > 1) {
+      if (hasAlias
+          && !queryStatement.isGroupByLevel()
+          && !queryStatement.isGroupByTag()
+          && resultExpressions.size() > 1) {
         throw new SemanticException(
             String.format(
                 "alias '%s' can only be matched with one time series", 
resultColumn.getAlias()));
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 14bf81bd82..c7a94881e5 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
@@ -1124,6 +1124,11 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       parseOrderByClause(ctx.orderByClause());
     }
 
+    // parse limit & offset
+    if (ctx.specialLimit() != null) {
+      return visit(ctx.specialLimit());
+    }
+
     return queryStatement;
   }
 
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 ae6586de5f..e894c70d06 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
@@ -314,18 +314,27 @@ public class QueryStatement extends Statement {
         throw new SemanticException("AGGREGATION doesn't support disable align 
clause.");
       }
       if (isGroupByLevel() && isAlignByDevice()) {
-        throw new SemanticException("group by level does not support align by 
device now.");
+        throw new SemanticException("GROUP BY LEVEL does not support align by 
device now.");
       }
       if (isGroupByTag() && isAlignByDevice()) {
-        throw new SemanticException("group by tag does not support align by 
device now.");
-      }
-      if (isGroupByTag() && isGroupByLevel()) {
-        throw new SemanticException("group by level cannot be used togather 
with group by tag");
+        throw new SemanticException("GROUP BY TAGS does not support align by 
device now.");
       }
+      Set<String> outputColumn = new HashSet<>();
       for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
         if (resultColumn.getColumnType() != 
ResultColumn.ColumnType.AGGREGATION) {
           throw new SemanticException("Raw data and aggregation hybrid query 
is not supported.");
         }
+        outputColumn.add(
+            resultColumn.getAlias() != null
+                ? resultColumn.getAlias()
+                : resultColumn.getExpression().getExpressionString());
+      }
+      if (isGroupByTag()) {
+        for (String s : getGroupByTagComponent().getTagKeys()) {
+          if (outputColumn.contains(s)) {
+            throw new SemanticException("Output column is duplicated with the 
tag key: " + s);
+          }
+        }
       }
     } else {
       if (isGroupByTime() || isGroupByLevel()) {
diff --git 
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/plan/LogicalPlannerTest.java
 
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/plan/LogicalPlannerTest.java
index fe2b9500a0..410cabafff 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/mpp/plan/plan/LogicalPlannerTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/mpp/plan/plan/LogicalPlannerTest.java
@@ -683,6 +683,42 @@ public class LogicalPlannerTest {
     }
   }
 
+  @Test
+  public void testGroupByTagWithIllegalSpecialLimitClause() {
+    String[] inputSql =
+        new String[] {
+          "select max_value(s1) from root.** group by tags(key1) disable 
align",
+          "select max_value(s1) from root.** group by tags(key1) align by 
device",
+          "select max_value(s1) from root.** group by tags(key1) without null 
any",
+        };
+    String[] expectedMsg =
+        new String[] {
+          "AGGREGATION doesn't support disable align clause",
+          "GROUP BY TAGS does not support align by device now",
+          "WITHOUT NULL clause is not supported yet"
+        };
+    for (int i = 0; i < inputSql.length; i++) {
+      try {
+        parseSQLToPlanNode(inputSql[i]);
+        fail();
+      } catch (Exception e) {
+        Assert.assertTrue(inputSql[i], 
e.getMessage().contains(expectedMsg[i]));
+      }
+    }
+  }
+
+  @Test
+  public void testGroupByTagWithDuplicatedAliasWithTagKey() {
+    String sql = "select max_value(s1) as key1 from root.** group by 
tags(key1)";
+    try {
+      parseSQLToPlanNode(sql);
+      fail();
+    } catch (Exception e) {
+      Assert.assertTrue(
+          e.getMessage().contains("Output column is duplicated with the tag 
key: key1"));
+    }
+  }
+
   private PlanNode parseSQLToPlanNode(String sql) {
     Statement statement = StatementGenerator.createStatement(sql, 
ZonedDateTime.now().getOffset());
     MPPQueryContext context = new MPPQueryContext(new QueryId("test_query"));

Reply via email to