You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hu...@apache.org on 2022/07/20 03:18:51 UTC
[iotdb] 01/04: refactor Order by in SQL parser & QueryStatement
This is an automated email from the ASF dual-hosted git repository.
hui pushed a commit to branch lmh/orderBySensor
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit c53a1d49ed29dfe73ff725152f2dc3e75fc2857d
Author: Minghui Liu <li...@foxmail.com>
AuthorDate: Tue Jul 19 17:51:01 2022 +0800
refactor Order by in SQL parser & QueryStatement
---
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 24 +++++--
.../iotdb/db/mpp/plan/parser/ASTVisitor.java | 47 ++++++++----
.../{OrderBy.java => OrderByComponent.java} | 32 +++++----
.../db/mpp/plan/statement/component/SortItem.java | 83 ++++++++++++++++++++++
.../db/mpp/plan/statement/crud/QueryStatement.java | 12 ++--
.../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 36 +++++++---
6 files changed, 182 insertions(+), 52 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 fe0add2da7..03868d644a 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
@@ -379,11 +379,11 @@ intoPath
specialClause
: specialLimit #specialLimitStatement
- | orderByTimeClause specialLimit? #orderByTimeStatement
- | groupByTimeClause orderByTimeClause? specialLimit? #groupByTimeStatement
- | groupByFillClause orderByTimeClause? specialLimit? #groupByFillStatement
- | groupByLevelClause orderByTimeClause? specialLimit? #groupByLevelStatement
- | fillClause orderByTimeClause? specialLimit? #fillStatement
+ | orderByClause specialLimit? #orderByTimeStatement
+ | groupByTimeClause orderByClause? specialLimit? #groupByTimeStatement
+ | groupByFillClause orderByClause? specialLimit? #groupByFillStatement
+ | groupByLevelClause orderByClause? specialLimit? #groupByLevelStatement
+ | fillClause orderByClause? specialLimit? #fillStatement
;
specialLimit
@@ -407,8 +407,18 @@ disableAlign
: DISABLE ALIGN
;
-orderByTimeClause
- : ORDER BY TIME (DESC | ASC)?
+orderByClause
+ : ORDER BY orderByAttributeClause (COMMA orderByAttributeClause)*
+ ;
+
+orderByAttributeClause
+ : sortKey (DESC | ASC)
+ ;
+
+sortKey
+ : TIME
+ | TIMESERIES
+ | DEVICE
;
groupByTimeClause
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 7c8f642936..8d5f002540 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
@@ -64,10 +64,11 @@ import org.apache.iotdb.db.mpp.plan.statement.component.FillPolicy;
import org.apache.iotdb.db.mpp.plan.statement.component.FromComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByLevelComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByTimeComponent;
-import org.apache.iotdb.db.mpp.plan.statement.component.OrderBy;
+import org.apache.iotdb.db.mpp.plan.statement.component.OrderByComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultSetFormat;
import org.apache.iotdb.db.mpp.plan.statement.component.SelectComponent;
+import org.apache.iotdb.db.mpp.plan.statement.component.SortItem;
import org.apache.iotdb.db.mpp.plan.statement.component.WhereCondition;
import org.apache.iotdb.db.mpp.plan.statement.crud.DeleteDataStatement;
import org.apache.iotdb.db.mpp.plan.statement.crud.InsertStatement;
@@ -142,9 +143,11 @@ import java.net.URISyntaxException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.regex.Pattern;
/** Parse AST to Statement. */
@@ -790,8 +793,8 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
parseGroupByTimeClause(ctx.groupByTimeClause());
// parse order by time
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
// parse limit & offset
@@ -808,8 +811,8 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
parseGroupByTimeClause(ctx.groupByFillClause());
// parse order by time
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
// parse limit & offset
@@ -938,8 +941,8 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
parseGroupByLevelClause(ctx.groupByLevelClause());
// parse order by time
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
// parse limit & offset
@@ -972,8 +975,8 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
parseFillClause(ctx.fillClause());
// parse order by time
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
// parse limit & offset
@@ -1182,7 +1185,7 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
@Override
public Statement visitOrderByTimeStatement(IoTDBSqlParser.OrderByTimeStatementContext ctx) {
// parse ORDER BY TIME
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ parseOrderByClause(ctx.orderByClause());
// parse others
if (ctx.specialLimit() != null) {
@@ -1192,10 +1195,28 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
}
// parse ORDER BY TIME
- private void parseOrderByTimeClause(IoTDBSqlParser.OrderByTimeClauseContext ctx) {
- if (ctx.DESC() != null) {
- queryStatement.setResultOrder(OrderBy.TIMESTAMP_DESC);
+ private void parseOrderByClause(IoTDBSqlParser.OrderByClauseContext ctx) {
+ OrderByComponent orderByComponent = new OrderByComponent();
+ Set<SortItem.SortKey> sortKeySet = new HashSet<>();
+ for (IoTDBSqlParser.OrderByAttributeClauseContext orderByAttributeClauseContext :
+ ctx.orderByAttributeClause()) {
+ SortItem sortItem = parseOrderByAttributeClause(orderByAttributeClauseContext);
+
+ SortItem.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(
+ SortItem.SortKey.valueOf(ctx.sortKey().getText().toUpperCase()),
+ ctx.DESC() != null ? SortItem.Ordering.DESC : SortItem.Ordering.ASC);
}
// ResultSetFormat Clause
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderBy.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderByComponent.java
similarity index 68%
rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderBy.java
rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderByComponent.java
index e72029b7d4..1aa09bbcae 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderBy.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/OrderByComponent.java
@@ -19,21 +19,23 @@
package org.apache.iotdb.db.mpp.plan.statement.component;
-/** The order of query result set by timestamp */
-public enum OrderBy {
- TIMESTAMP_ASC,
- TIMESTAMP_DESC,
- DEVICE_ASC,
- DEVICE_DESC;
+import java.util.ArrayList;
+import java.util.List;
- public OrderBy reverse() {
- switch (this) {
- case TIMESTAMP_ASC:
- return TIMESTAMP_DESC;
- case TIMESTAMP_DESC:
- return TIMESTAMP_ASC;
- default:
- throw new UnsupportedOperationException();
- }
+/** The order of query result set */
+public class OrderByComponent {
+
+ private final List<SortItem> sortItemList;
+
+ public OrderByComponent() {
+ this.sortItemList = new ArrayList<>();
+ }
+
+ public void addSortItem(SortItem sortItem) {
+ this.sortItemList.add(sortItem);
+ }
+
+ public List<SortItem> getSortItemList() {
+ return sortItemList;
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/SortItem.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/SortItem.java
new file mode 100644
index 0000000000..bbdff9f01b
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/component/SortItem.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.plan.statement.component;
+
+import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
+
+import java.util.Objects;
+
+public class SortItem extends StatementNode {
+
+ public enum SortKey {
+ TIME,
+ TIMESERIES,
+ DEVICE
+ }
+
+ public enum Ordering {
+ ASC,
+ DESC;
+
+ public Ordering reverse() {
+ if (this == ASC) {
+ return DESC;
+ } else {
+ return ASC;
+ }
+ }
+ }
+
+ private final SortKey sortKey;
+ private final Ordering ordering;
+
+ public SortItem(SortKey sortKey, Ordering ordering) {
+ this.sortKey = sortKey;
+ this.ordering = ordering;
+ }
+
+ public SortKey getSortKey() {
+ return sortKey;
+ }
+
+ public Ordering getOrdering() {
+ return ordering;
+ }
+
+ public SortItem reverse() {
+ return new SortItem(getSortKey(), getOrdering().reverse());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ SortItem sortItem = (SortItem) o;
+ return sortKey == sortItem.sortKey && ordering == sortItem.ordering;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(sortKey, ordering);
+ }
+}
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 17f433a2e7..2da55d6f42 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
@@ -31,7 +31,7 @@ import org.apache.iotdb.db.mpp.plan.statement.component.FillComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.FromComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByLevelComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.GroupByTimeComponent;
-import org.apache.iotdb.db.mpp.plan.statement.component.OrderBy;
+import org.apache.iotdb.db.mpp.plan.statement.component.OrderByComponent;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn;
import org.apache.iotdb.db.mpp.plan.statement.component.ResultSetFormat;
import org.apache.iotdb.db.mpp.plan.statement.component.SelectComponent;
@@ -76,7 +76,7 @@ public class QueryStatement extends Statement {
protected FillComponent fillComponent;
- protected OrderBy resultOrder = OrderBy.TIMESTAMP_ASC;
+ protected OrderByComponent orderByComponent;
protected ResultSetFormat resultSetFormat = ResultSetFormat.ALIGN_BY_TIME;
@@ -159,12 +159,12 @@ public class QueryStatement extends Statement {
this.fillComponent = fillComponent;
}
- public OrderBy getResultOrder() {
- return resultOrder;
+ public OrderByComponent getOrderByComponent() {
+ return orderByComponent;
}
- public void setResultOrder(OrderBy resultOrder) {
- this.resultOrder = resultOrder;
+ public void setOrderByComponent(OrderByComponent orderByComponent) {
+ this.orderByComponent = orderByComponent;
}
public ResultSetFormat getResultSetFormat() {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 79bb5d9db0..d4c58d998c 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -53,6 +53,7 @@ import org.apache.iotdb.db.mpp.plan.expression.unary.LikeExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.LogicNotExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.NegationExpression;
import org.apache.iotdb.db.mpp.plan.expression.unary.RegularExpression;
+import org.apache.iotdb.db.mpp.plan.statement.component.SortItem;
import org.apache.iotdb.db.qp.constant.FilterConstant;
import org.apache.iotdb.db.qp.constant.FilterConstant.FilterType;
import org.apache.iotdb.db.qp.constant.SQLConstant;
@@ -1341,7 +1342,7 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
@Override
public Operator visitOrderByTimeStatement(IoTDBSqlParser.OrderByTimeStatementContext ctx) {
queryOp = new QueryOperator();
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ parseOrderByClause(ctx.orderByClause());
if (ctx.specialLimit() != null) {
return visit(ctx.specialLimit());
}
@@ -1352,8 +1353,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
public Operator visitGroupByTimeStatement(IoTDBSqlParser.GroupByTimeStatementContext ctx) {
queryOp = new GroupByQueryOperator();
parseGroupByTimeClause(ctx.groupByTimeClause());
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
if (ctx.specialLimit() != null) {
return visit(ctx.specialLimit());
@@ -1365,8 +1366,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
public Operator visitGroupByFillStatement(IoTDBSqlParser.GroupByFillStatementContext ctx) {
queryOp = new GroupByFillQueryOperator();
parseGroupByFillClause(ctx.groupByFillClause());
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
if (ctx.specialLimit() != null) {
return visit(ctx.specialLimit());
@@ -1378,8 +1379,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
public Operator visitGroupByLevelStatement(IoTDBSqlParser.GroupByLevelStatementContext ctx) {
queryOp = new AggregationQueryOperator();
parseGroupByLevelClause(ctx.groupByLevelClause());
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
if (ctx.specialLimit() != null) {
return visit(ctx.specialLimit());
@@ -1391,8 +1392,8 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
public Operator visitFillStatement(IoTDBSqlParser.FillStatementContext ctx) {
queryOp = new FillQueryOperator();
parseFillClause(ctx.fillClause());
- if (ctx.orderByTimeClause() != null) {
- parseOrderByTimeClause(ctx.orderByTimeClause());
+ if (ctx.orderByClause() != null) {
+ parseOrderByClause(ctx.orderByClause());
}
if (ctx.specialLimit() != null) {
return visit(ctx.specialLimit());
@@ -1480,8 +1481,15 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
specialClauseComponent.setAlignByTime(false);
}
- private void parseOrderByTimeClause(IoTDBSqlParser.OrderByTimeClauseContext ctx) {
- if (ctx.DESC() != null) {
+ private void parseOrderByClause(IoTDBSqlParser.OrderByClauseContext ctx) {
+ if (ctx.orderByAttributeClause().size() > 0) {
+ throw new SQLParserException("Sorting by multiple fields is not supported.");
+ }
+ SortItem sortItem = parseOrderByAttributeClause(ctx.orderByAttributeClause(0));
+ if (sortItem.getSortKey() != SortItem.SortKey.TIME) {
+ throw new SQLParserException("It only supports sorting by time.");
+ }
+ if (sortItem.getOrdering() == SortItem.Ordering.DESC) {
SpecialClauseComponent specialClauseComponent = queryOp.getSpecialClauseComponent();
if (specialClauseComponent == null) {
specialClauseComponent = new SpecialClauseComponent();
@@ -1491,6 +1499,12 @@ public class IoTDBSqlVisitor extends IoTDBSqlParserBaseVisitor<Operator> {
}
}
+ private SortItem parseOrderByAttributeClause(IoTDBSqlParser.OrderByAttributeClauseContext ctx) {
+ return new SortItem(
+ SortItem.SortKey.valueOf(ctx.sortKey().getText().toUpperCase()),
+ ctx.DESC() != null ? SortItem.Ordering.DESC : SortItem.Ordering.ASC);
+ }
+
private void parseGroupByTimeClause(IoTDBSqlParser.GroupByTimeClauseContext ctx) {
GroupByClauseComponent groupByClauseComponent = new GroupByClauseComponent();
groupByClauseComponent.setLeftCRightO(ctx.timeRange().LS_BRACKET() != null);