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"));
