This is an automated email from the ASF dual-hosted git repository. xiangweiwei pushed a commit to branch ReQuery1 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 2e5c4ca10e05a118000e6d557906107d2627c22a Author: Alima777 <[email protected]> AuthorDate: Wed Apr 28 21:08:37 2021 +0800 Restructure query operator --- .../antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 | 1 - .../query/ClusterPhysicalGeneratorTest.java | 8 +- .../main/java/org/apache/iotdb/db/qp/Planner.java | 6 +- .../db/qp/logical/crud/FillQueryOperator.java | 23 ++ .../iotdb/db/qp/logical/crud/FilterOperator.java | 3 +- .../iotdb/db/qp/logical/crud/FromOperator.java | 5 +- .../qp/logical/crud/GroupByFillQueryOperator.java | 23 ++ .../db/qp/logical/crud/GroupByQueryOperator.java | 76 +++++ .../iotdb/db/qp/logical/crud/QueryOperator.java | 141 +------- .../iotdb/db/qp/logical/crud/SFWOperator.java | 42 +-- .../db/qp/logical/crud/SelectAggrOperator.java | 37 ++ .../db/qp/logical/crud/SelectLastOperator.java | 15 + .../iotdb/db/qp/logical/crud/SelectOperator.java | 70 ++-- .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 379 ++++++++++++++------- .../iotdb/db/qp/strategy/PhysicalGenerator.java | 43 +-- 15 files changed, 522 insertions(+), 350 deletions(-) diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 index c753069..ae94df0 100644 --- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 +++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/SqlBase.g4 @@ -252,7 +252,6 @@ specialClause | groupByTimeClause orderByTimeClause? specialLimit? #groupByTimeStatement | groupByFillClause orderByTimeClause? specialLimit? #groupByFillStatement | fillClause slimitClause? alignByDeviceClauseOrDisableAlign? #fillStatement - | alignByDeviceClauseOrDisableAlign #alignByDeviceStatementOrDisableAlignInSpecialClause | groupByLevelClause orderByTimeClause? specialLimit? #groupByLevelStatement ; diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterPhysicalGeneratorTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterPhysicalGeneratorTest.java index b6dc1f6..a3fb4f2 100644 --- a/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterPhysicalGeneratorTest.java +++ b/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterPhysicalGeneratorTest.java @@ -23,7 +23,6 @@ import org.apache.iotdb.cluster.common.TestUtils; import org.apache.iotdb.db.exception.metadata.IllegalPathException; import org.apache.iotdb.db.exception.query.QueryProcessException; import org.apache.iotdb.db.metadata.PartialPath; -import org.apache.iotdb.db.qp.constant.SQLConstant; import org.apache.iotdb.db.qp.logical.crud.FromOperator; import org.apache.iotdb.db.qp.logical.crud.QueryOperator; import org.apache.iotdb.db.qp.logical.crud.SelectOperator; @@ -49,12 +48,11 @@ public class ClusterPhysicalGeneratorTest extends BaseQueryTest { @Test public void test() throws QueryProcessException, IllegalPathException { - QueryOperator operator = new QueryOperator(SQLConstant.TOK_QUERY); + QueryOperator operator = new QueryOperator(); - SelectOperator selectOperator = - new SelectOperator(SQLConstant.TOK_SELECT, ZoneId.systemDefault()); + SelectOperator selectOperator = new SelectOperator(ZoneId.systemDefault()); selectOperator.setSuffixPathList(pathList); - FromOperator fromOperator = new FromOperator(SQLConstant.TOK_FROM); + FromOperator fromOperator = new FromOperator(); fromOperator.addPrefixTablePath(new PartialPath(TestUtils.getTestSg(0))); operator.setSelectOperator(selectOperator); 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 355b7ef..5a57278 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 @@ -91,9 +91,9 @@ public class Planner { long endTime = rawDataQueryReq.getEndTime(); // construct query operator and set its global time filter - QueryOperator queryOp = new QueryOperator(SQLConstant.TOK_QUERY); - FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM); - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + QueryOperator queryOp = new QueryOperator(); + FromOperator fromOp = new FromOperator(); + SelectOperator selectOp = new SelectOperator(zoneId); // iterate the path list and add it to from operator for (String p : paths) { diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FillQueryOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FillQueryOperator.java new file mode 100644 index 0000000..6918109 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FillQueryOperator.java @@ -0,0 +1,23 @@ +package org.apache.iotdb.db.qp.logical.crud; + +import org.apache.iotdb.db.query.executor.fill.IFill; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.util.Map; + +public class FillQueryOperator extends QueryOperator { + + public FillQueryOperator() { + super(); + } + + private Map<TSDataType, IFill> fillTypes; + + public Map<TSDataType, IFill> getFillTypes() { + return fillTypes; + } + + public void setFillTypes(Map<TSDataType, IFill> fillTypes) { + this.fillTypes = fillTypes; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java index 315223e..d28ea53 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java @@ -47,7 +47,7 @@ import static org.apache.iotdb.db.qp.constant.SQLConstant.KW_OR; */ public class FilterOperator extends Operator implements Comparable<FilterOperator> { - // it is the symbol of token. e.g. AND is & and OR is | + // The symbol of token. e.g. AND is & and OR is | String tokenSymbol; private List<FilterOperator> childOperators; @@ -168,7 +168,6 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato * @return - pair.left: UnaryQueryFilter constructed by its one child; pair.right: Path * represented by this child. * @throws MetadataException exception in filter transforming - * @param pathTSDataTypeHashMap */ protected Pair<IUnaryExpression, String> transformToSingleQueryFilter( Map<PartialPath, TSDataType> pathTSDataTypeHashMap) diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FromOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FromOperator.java index 60fed66..b508df7 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FromOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FromOperator.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.qp.logical.crud; import org.apache.iotdb.db.metadata.PartialPath; +import org.apache.iotdb.db.qp.constant.SQLConstant; import org.apache.iotdb.db.qp.logical.Operator; import java.util.ArrayList; @@ -29,8 +30,8 @@ public class FromOperator extends Operator { private List<PartialPath> prefixList; - public FromOperator(int tokenIntType) { - super(tokenIntType); + public FromOperator() { + super(SQLConstant.TOK_FROM); operatorType = OperatorType.FROM; prefixList = new ArrayList<>(); } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java new file mode 100644 index 0000000..bb10baa --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByFillQueryOperator.java @@ -0,0 +1,23 @@ +package org.apache.iotdb.db.qp.logical.crud; + +import org.apache.iotdb.db.query.executor.fill.IFill; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.util.Map; + +public class GroupByFillQueryOperator extends GroupByQueryOperator { + + public GroupByFillQueryOperator() { + super(); + }; + + private Map<TSDataType, IFill> fillTypes; + + public Map<TSDataType, IFill> getFillTypes() { + return fillTypes; + } + + public void setFillTypes(Map<TSDataType, IFill> fillTypes) { + this.fillTypes = fillTypes; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByQueryOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByQueryOperator.java new file mode 100644 index 0000000..983674f --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/GroupByQueryOperator.java @@ -0,0 +1,76 @@ +package org.apache.iotdb.db.qp.logical.crud; + +public class GroupByQueryOperator extends QueryOperator { + + private long startTime; + private long endTime; + // time interval + private long unit; + // sliding step + private long slidingStep; + // if it is left close and right open interval + private boolean leftCRightO; + + private boolean isIntervalByMonth = false; + private boolean isSlidingStepByMonth = false; + + public GroupByQueryOperator() { + super(); + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public long getUnit() { + return unit; + } + + public void setUnit(long unit) { + this.unit = unit; + } + + public long getSlidingStep() { + return slidingStep; + } + + public void setSlidingStep(long slidingStep) { + this.slidingStep = slidingStep; + } + + public boolean isLeftCRightO() { + return leftCRightO; + } + + public void setLeftCRightO(boolean leftCRightO) { + this.leftCRightO = leftCRightO; + } + + public boolean isSlidingStepByMonth() { + return isSlidingStepByMonth; + } + + public void setSlidingStepByMonth(boolean isSlidingStepByMonth) { + this.isSlidingStepByMonth = isSlidingStepByMonth; + } + + public boolean isIntervalByMonth() { + return isIntervalByMonth; + } + + public void setIntervalByMonth(boolean isIntervalByMonth) { + this.isIntervalByMonth = isIntervalByMonth; + } +} 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 87aa1d9..fc8991f 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,31 +19,14 @@ package org.apache.iotdb.db.qp.logical.crud; import org.apache.iotdb.db.index.common.IndexType; +import org.apache.iotdb.db.qp.constant.SQLConstant; 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; import java.util.Map; /** this class extends {@code RootOperator} and process getIndex statement */ public class QueryOperator extends SFWOperator { - private long startTime; - private long endTime; - // time interval - private long unit; - // sliding step - private long slidingStep; - private boolean isGroupByTime = false; - private boolean isIntervalByMonth = false; - private boolean isSlidingStepByMonth = false; - // if it is left close and right open interval - private boolean leftCRightO; - - private Map<TSDataType, IFill> fillTypes; - private boolean isFill = false; - - private boolean isGroupByLevel = false; private int level = -1; private int rowLimit = 0; @@ -54,19 +37,25 @@ public class QueryOperator extends SFWOperator { private boolean isAlignByDevice = false; private boolean isAlignByTime = true; - private String column; - private boolean ascending = true; private Map<String, Object> props; private IndexType indexType; - public QueryOperator(int tokenIntType) { - super(tokenIntType); + public QueryOperator() { + super(SQLConstant.TOK_QUERY); operatorType = Operator.OperatorType.QUERY; } + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + public Map<String, Object> getProps() { return props; } @@ -83,38 +72,6 @@ public class QueryOperator extends SFWOperator { this.indexType = indexType; } - public boolean isFill() { - return isFill; - } - - public void setFill(boolean fill) { - isFill = fill; - } - - public Map<TSDataType, IFill> getFillTypes() { - return fillTypes; - } - - public void setFillTypes(Map<TSDataType, IFill> fillTypes) { - this.fillTypes = fillTypes; - } - - public boolean isGroupByLevel() { - return isGroupByLevel; - } - - public void setGroupByLevel(boolean isGroupBy) { - this.isGroupByLevel = isGroupBy; - } - - public boolean isLeftCRightO() { - return leftCRightO; - } - - public void setLeftCRightO(boolean leftCRightO) { - this.leftCRightO = leftCRightO; - } - public int getRowLimit() { return rowLimit; } @@ -155,44 +112,12 @@ public class QueryOperator extends SFWOperator { return seriesLimit > 0; } - public long getUnit() { - return unit; - } - - public void setUnit(long unit) { - this.unit = unit; - } - - public long getStartTime() { - return startTime; - } - - public void setStartTime(long startTime) { - this.startTime = startTime; - } - - public long getEndTime() { - return endTime; - } - - public void setEndTime(long endTime) { - this.endTime = endTime; - } - - public long getSlidingStep() { - return slidingStep; - } - - public void setSlidingStep(long slidingStep) { - this.slidingStep = slidingStep; - } - public boolean isAlignByDevice() { return isAlignByDevice; } - public void setAlignByDevice(boolean isAlignByDevice) { - this.isAlignByDevice = isAlignByDevice; + public void setAlignByDevice(boolean alignByDevice) { + this.isAlignByDevice = alignByDevice; } public boolean isAlignByTime() { @@ -203,46 +128,6 @@ public class QueryOperator extends SFWOperator { this.isAlignByTime = isAlignByTime; } - public int getLevel() { - return level; - } - - public void setLevel(int level) { - this.level = level; - } - - public boolean isGroupByTime() { - return isGroupByTime; - } - - public void setGroupByTime(boolean groupByTime) { - isGroupByTime = groupByTime; - } - - public boolean isSlidingStepByMonth() { - return isSlidingStepByMonth; - } - - public void setSlidingStepByMonth(boolean isSlidingStepByMonth) { - this.isSlidingStepByMonth = isSlidingStepByMonth; - } - - public boolean isIntervalByMonth() { - return isIntervalByMonth; - } - - public void setIntervalByMonth(boolean isIntervalByMonth) { - this.isIntervalByMonth = isIntervalByMonth; - } - - public String getColumn() { - return column; - } - - public void setColumn(String column) { - this.column = column; - } - public boolean isAscending() { return ascending; } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SFWOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SFWOperator.java index 14d510b..1b20d27 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SFWOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SFWOperator.java @@ -29,42 +29,30 @@ import java.util.List; */ public abstract class SFWOperator extends RootOperator { - private SelectOperator selectOperator; - private FromOperator fromOperator; - private FilterOperator filterOperator; - private boolean hasAggregation = false; - private boolean hasUdf = false; - private boolean lastQuery = false; + protected SelectOperator selectOperator; + protected FromOperator fromOperator; + protected FilterOperator filterOperator; public SFWOperator(int tokenIntType) { super(tokenIntType); operatorType = OperatorType.SFW; } - public FromOperator getFromOperator() { - return fromOperator; + public SelectOperator getSelectOperator() { + return selectOperator; } - public void setFromOperator(FromOperator from) { - this.fromOperator = from; + /** set selectOperator, then init hasAggregation according to selectOperator. */ + public void setSelectOperator(SelectOperator selectOperator) { + this.selectOperator = selectOperator; } - public SelectOperator getSelectOperator() { - return selectOperator; + public FromOperator getFromOperator() { + return fromOperator; } - /** set selectOperator, then init hasAggregation according to selectOperator. */ - public void setSelectOperator(SelectOperator sel) { - this.selectOperator = sel; - if (sel.hasAggregation()) { - hasAggregation = true; - } - if (sel.isUdfQuery()) { - hasUdf = true; - } - if (sel.isLastQuery()) { - lastQuery = true; - } + public void setFromOperator(FromOperator fromOperator) { + this.fromOperator = fromOperator; } public FilterOperator getFilterOperator() { @@ -85,14 +73,14 @@ public abstract class SFWOperator extends RootOperator { } public boolean hasAggregation() { - return hasAggregation; + return selectOperator.hasAggregation(); } public boolean hasUdf() { - return hasUdf; + return selectOperator.isUdfQuery(); } public boolean isLastQuery() { - return lastQuery; + return selectOperator.isLastQuery(); } } diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectAggrOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectAggrOperator.java new file mode 100644 index 0000000..0a70a61 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectAggrOperator.java @@ -0,0 +1,37 @@ +package org.apache.iotdb.db.qp.logical.crud; + +import org.apache.iotdb.db.metadata.PartialPath; + +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; + +public class SelectAggrOperator extends SelectOperator { + + private List<String> aggregations = new ArrayList<>(); + + /** init with tokenIntType, default operatorType is <code>OperatorType.SELECT</code>. */ + public SelectAggrOperator(ZoneId zoneId) { + super(zoneId); + } + + public void addClusterPath(PartialPath suffixPath, String aggregation) { + suffixList.add(suffixPath); + if (aggregations == null) { + aggregations = new ArrayList<>(); + } + aggregations.add(aggregation); + } + + public List<String> getAggregations() { + return this.aggregations; + } + + public void setAggregations(List<String> aggregations) { + this.aggregations = aggregations; + } + + public boolean hasAggregation() { + return true; // todo: hasBuiltinAggregation || hasUDAF + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectLastOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectLastOperator.java new file mode 100644 index 0000000..8796713 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectLastOperator.java @@ -0,0 +1,15 @@ +package org.apache.iotdb.db.qp.logical.crud; + +import java.time.ZoneId; + +public class SelectLastOperator extends SelectOperator { + + /** init with tokenIntType, default operatorType is <code>OperatorType.SELECT</code>. */ + public SelectLastOperator(ZoneId zoneId) { + super(zoneId); + } + + public boolean isLastQuery() { + return true; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectOperator.java index 5b34ea5..082978f 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/SelectOperator.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.qp.logical.crud; import org.apache.iotdb.db.metadata.PartialPath; +import org.apache.iotdb.db.qp.constant.SQLConstant; import org.apache.iotdb.db.qp.logical.Operator; import org.apache.iotdb.db.query.udf.core.context.UDFContext; @@ -27,28 +28,19 @@ import java.util.ArrayList; import java.util.List; /** this class maintains information from select clause. */ -public final class SelectOperator extends Operator { +public class SelectOperator extends Operator { - private final ZoneId zoneId; - private List<PartialPath> suffixList; - private List<String> aggregations; + protected final ZoneId zoneId; + protected List<PartialPath> suffixList = new ArrayList<>(); private List<UDFContext> udfList; - private boolean lastQuery; - private boolean udfQuery; - private boolean hasBuiltinAggregation; + private boolean udfQuery = false; /** init with tokenIntType, default operatorType is <code>OperatorType.SELECT</code>. */ - public SelectOperator(int tokenIntType, ZoneId zoneId) { - super(tokenIntType); - this.zoneId = zoneId; + public SelectOperator(ZoneId zoneId) { + super(SQLConstant.TOK_SELECT); operatorType = OperatorType.SELECT; - suffixList = new ArrayList<>(); - aggregations = new ArrayList<>(); - udfList = new ArrayList<>(); - lastQuery = false; - udfQuery = false; - hasBuiltinAggregation = false; + this.zoneId = zoneId; } public ZoneId getZoneId() { @@ -59,34 +51,6 @@ public final class SelectOperator extends Operator { suffixList.add(suffixPath); } - public void addClusterPath(PartialPath suffixPath, String aggregation) { - suffixList.add(suffixPath); - aggregations.add(aggregation); - if (aggregation != null) { - hasBuiltinAggregation = true; - } - } - - public boolean isLastQuery() { - return this.lastQuery; - } - - public void setLastQuery() { - lastQuery = true; - } - - public List<String> getAggregations() { - return this.aggregations; - } - - public void setAggregations(List<String> aggregations) { - this.aggregations = aggregations; - } - - public boolean hasAggregation() { - return hasBuiltinAggregation; // todo: hasBuiltinAggregation || hasUDAF - } - public void setSuffixPathList(List<PartialPath> suffixPaths) { suffixList = suffixPaths; } @@ -99,6 +63,9 @@ public final class SelectOperator extends Operator { if (udf != null) { udfQuery = true; } + if (udfList == null) { + udfList = new ArrayList<>(); + } udfList.add(udf); } @@ -113,4 +80,19 @@ public final class SelectOperator extends Operator { public void setUdfList(List<UDFContext> udfList) { this.udfList = udfList; } + + public boolean isLastQuery() { + return false; + } + + public boolean hasAggregation() { + return false; // todo: hasBuiltinAggregation || hasUDAF + } + + // TODO: package it + public List<String> getAggregations() { + return new ArrayList<>(); + } + + public void setAggregations(List<String> aggregations) {} } 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 9003016..020ce16 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 @@ -29,11 +29,16 @@ import org.apache.iotdb.db.qp.constant.SQLConstant; 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.FillQueryOperator; 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.GroupByFillQueryOperator; +import org.apache.iotdb.db.qp.logical.crud.GroupByQueryOperator; 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.QueryOperator; +import org.apache.iotdb.db.qp.logical.crud.SelectAggrOperator; +import org.apache.iotdb.db.qp.logical.crud.SelectLastOperator; import org.apache.iotdb.db.qp.logical.crud.SelectOperator; import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator; import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator.AlterType; @@ -78,7 +83,144 @@ import org.apache.iotdb.db.qp.logical.sys.StartTriggerOperator; import org.apache.iotdb.db.qp.logical.sys.StopTriggerOperator; import org.apache.iotdb.db.qp.logical.sys.TracingOperator; import org.apache.iotdb.db.qp.physical.crud.GroupByTimePlan; -import org.apache.iotdb.db.qp.sql.SqlBaseParser.*; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.AggregationCallContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.AggregationElementContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.AliasClauseContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlignByDeviceClauseOrDisableAlignContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.AlignByDeviceClauseOrDisableAlignInSpecialLimitContext; +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.BuiltInFunctionCallContext; +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.CreateFunctionContext; +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.CreateTriggerContext; +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.DropFunctionContext; +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.DropTriggerContext; +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.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.InsertMultiValueContext; +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.KillQueryContext; +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.MeasurementNameContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.MeasurementValueContext; +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.SelectStatementContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.SequenceClauseContext; +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.ShowChildNodesContext; +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.ShowFunctionsContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowMergeStatusContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.ShowQueryProcesslistContext; +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.ShowTriggersContext; +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.StartTriggerContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.StopTriggerContext; +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.TableCallContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.TableElementContext; +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.TriggerAttributeContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.TypeClauseContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.UdfAttributeContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.UdfCallContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.UnsetTTLStatementContext; +import org.apache.iotdb.db.qp.sql.SqlBaseParser.WhereClauseContext; import org.apache.iotdb.db.qp.utils.DatetimeUtils; import org.apache.iotdb.db.query.executor.fill.IFill; import org.apache.iotdb.db.query.executor.fill.LinearFill; @@ -119,7 +261,6 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { + "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'"; private ZoneId zoneId; QueryOperator queryOp; - private boolean isParsingSlidingStep; public void setZoneId(ZoneId zoneId) { this.zoneId = zoneId; @@ -173,7 +314,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitInsertStatement(InsertStatementContext ctx) { InsertOperator insertOp = new InsertOperator(SQLConstant.TOK_INSERT); - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); selectOp.addSelectPath(parsePrefixPath(ctx.prefixPath())); insertOp.setSelectOperator(selectOp); parseInsertColumnSpec(ctx.insertColumnsSpec(), insertOp); @@ -184,7 +325,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitDeleteStatement(DeleteStatementContext ctx) { DeleteDataOperator deleteDataOp = new DeleteDataOperator(SQLConstant.TOK_DELETE); - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); List<PrefixPathContext> prefixPaths = ctx.prefixPath(); for (PrefixPathContext prefixPath : prefixPaths) { PartialPath path = parsePrefixPath(prefixPath); @@ -229,7 +370,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitCreateIndex(CreateIndexContext ctx) { CreateIndexOperator createIndexOp = new CreateIndexOperator(SQLConstant.TOK_CREATE_INDEX); - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath()); for (PrefixPathContext prefixPath : prefixPaths) { PartialPath path = parsePrefixPath(prefixPath); @@ -291,7 +432,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitDropIndex(DropIndexContext ctx) { DropIndexOperator dropIndexOperator = new DropIndexOperator(SQLConstant.TOK_DROP_INDEX); - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); List<PrefixPathContext> prefixPaths = Collections.singletonList(ctx.prefixPath()); for (PrefixPathContext prefixPath : prefixPaths) { PartialPath path = parsePrefixPath(prefixPath); @@ -869,8 +1010,20 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitSelectStatement(SelectStatementContext ctx) { - queryOp = new QueryOperator(SQLConstant.TOK_QUERY); + // 1. Visit special clause first to initialize different query operator + if (ctx.specialClause() != null) { + visit(ctx.specialClause()); + } + // 2. There is no special clause in query statement. + if (queryOp == null) { + queryOp = new QueryOperator(); + } + // 3. Visit select, from, where in sequence SelectOperator selectOp = (SelectOperator) visit(ctx.selectElements()); + if ((queryOp instanceof GroupByQueryOperator || queryOp.getLevel() != -1) + && !selectOp.hasAggregation()) { + throw new SQLParserException(GroupByTimePlan.LACK_FUNC_ERROR_MESSAGE); + } queryOp.setSelectOperator(selectOp); FromOperator fromOp = (FromOperator) visit(ctx.fromClause()); queryOp.setFromOperator(fromOp); @@ -890,32 +1043,29 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { queryOp.setFilterOperator(whereOp.getChildren().get(0)); } } - if (ctx.specialClause() != null) { - visit(ctx.specialClause()); - } return queryOp; } @Override public Operator visitAggregationElement(AggregationElementContext ctx) { - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectAggrOperator selectAggrOp = new SelectAggrOperator(zoneId); for (AggregationCallContext aggregationCallContext : ctx.aggregationCall()) { BuiltInFunctionCallContext builtInFunctionCallContext = aggregationCallContext.builtInFunctionCall(); UdfCallContext udfCallContext = aggregationCallContext.udfCall(); if (builtInFunctionCallContext != null) { - selectOp.addClusterPath( + selectAggrOp.addClusterPath( parseSuffixPath(builtInFunctionCallContext.suffixPath()), builtInFunctionCallContext.functionName().getText()); - selectOp.addUdf(null); + selectAggrOp.addUdf(null); } else if (udfCallContext != null) { - selectOp.addClusterPath(null, null); - parseUdfCall(udfCallContext, selectOp); + selectAggrOp.addClusterPath(null, null); + parseUdfCall(udfCallContext, selectAggrOp); } } - return selectOp; + return selectAggrOp; } public void parseUdfCall(UdfCallContext udfCall, SelectOperator selectOp) { @@ -936,8 +1086,8 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitLastElement(LastElementContext ctx) { - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); - selectOp.setLastQuery(); + SelectOperator selectOp = new SelectLastOperator(zoneId); + LastClauseContext lastClauseContext = ctx.lastClause(); if (lastClauseContext.asClause().size() != 0) { parseAsClause(lastClauseContext.asClause(), selectOp); @@ -953,14 +1103,14 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitAsElement(AsElementContext ctx) { - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); parseAsClause(ctx.asClause(), selectOp); return selectOp; } @Override public Operator visitFunctionAsElement(FunctionAsElementContext ctx) { - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectAggrOperator selectAggrOperator = new SelectAggrOperator(zoneId); List<FunctionAsClauseContext> functionAsClauseContexts = ctx.functionAsClause(); for (FunctionAsClauseContext functionAsClauseContext : functionAsClauseContexts) { BuiltInFunctionCallContext functionCallContext = @@ -969,9 +1119,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { if (functionAsClauseContext.ID() != null) { path.setTsAlias(functionAsClauseContext.ID().toString()); } - selectOp.addClusterPath(path, functionCallContext.functionName().getText()); + selectAggrOperator.addClusterPath(path, functionCallContext.functionName().getText()); } - return selectOp; + return selectAggrOperator; } public void parseAsClause(List<AsClauseContext> asClauseContexts, SelectOperator selectOp) { @@ -986,6 +1136,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitSpecialLimitStatement(SpecialLimitStatementContext ctx) { + if (queryOp == null) { + queryOp = new QueryOperator(); + } return visit(ctx.specialLimit()); } @@ -996,11 +1149,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { parseSlimitClause(ctx.slimitClause(), queryOp); } if (ctx.alignByDeviceClauseOrDisableAlign() != null) { - if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) { - parseAlignByDeviceClause(queryOp); - } else { - parseDisableAlign(queryOp); - } + parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign()); } return queryOp; } @@ -1012,11 +1161,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { parseLimitClause(ctx.limitClause(), queryOp); } if (ctx.alignByDeviceClauseOrDisableAlign() != null) { - if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) { - parseAlignByDeviceClause(queryOp); - } else { - parseDisableAlign(queryOp); - } + parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign()); } return queryOp; } @@ -1032,9 +1177,21 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { return queryOp; } + private void parseAlignByDeviceClauseOrDisableAlign( + AlignByDeviceClauseOrDisableAlignContext ctx) { + if (ctx.alignByDeviceClause() != null) { + parseAlignByDeviceClause(queryOp); + } else { + parseDisableAlign(queryOp); + } + } + @Override public Operator visitOrderByTimeStatement(OrderByTimeStatementContext ctx) { - parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp); + if (queryOp == null) { + queryOp = new QueryOperator(); + } + parseOrderByTimeClause(ctx.orderByTimeClause()); if (ctx.specialLimit() != null) { return visit(ctx.specialLimit()); } @@ -1043,9 +1200,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitGroupByTimeStatement(GroupByTimeStatementContext ctx) { - parseGroupByTimeClause(ctx.groupByTimeClause(), queryOp); + parseGroupByTimeClause(ctx.groupByTimeClause()); if (ctx.orderByTimeClause() != null) { - parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp); + parseOrderByTimeClause(ctx.orderByTimeClause()); } if (ctx.specialLimit() != null) { return visit(ctx.specialLimit()); @@ -1055,9 +1212,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitGroupByFillStatement(GroupByFillStatementContext ctx) { - parseGroupByFillClause(ctx.groupByFillClause(), queryOp); + parseGroupByFillClause(ctx.groupByFillClause()); if (ctx.orderByTimeClause() != null) { - parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp); + parseOrderByTimeClause(ctx.orderByTimeClause()); } if (ctx.specialLimit() != null) { return visit(ctx.specialLimit()); @@ -1067,36 +1224,21 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitFillStatement(FillStatementContext ctx) { - parseFillClause(ctx.fillClause(), queryOp); + parseFillClause(ctx.fillClause()); if (ctx.slimitClause() != null) { parseSlimitClause(ctx.slimitClause(), queryOp); } if (ctx.alignByDeviceClauseOrDisableAlign() != null) { - if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) { - parseAlignByDeviceClause(queryOp); - } else { - parseDisableAlign(queryOp); - } - } - return queryOp; - } - - @Override - public Operator visitAlignByDeviceStatementOrDisableAlignInSpecialClause( - AlignByDeviceStatementOrDisableAlignInSpecialClauseContext ctx) { - if (ctx.alignByDeviceClauseOrDisableAlign().alignByDeviceClause() != null) { - parseAlignByDeviceClause(queryOp); - } else { - parseDisableAlign(queryOp); + parseAlignByDeviceClauseOrDisableAlign(ctx.alignByDeviceClauseOrDisableAlign()); } return queryOp; } @Override public Operator visitGroupByLevelStatement(GroupByLevelStatementContext ctx) { - parseGroupByLevelClause(ctx.groupByLevelClause(), queryOp); + parseGroupByLevelClause(ctx.groupByLevelClause()); if (ctx.orderByTimeClause() != null) { - parseOrderByTimeClause(ctx.orderByTimeClause(), queryOp); + parseOrderByTimeClause(ctx.orderByTimeClause()); } if (ctx.specialLimit() != null) { return visit(ctx.specialLimit()); @@ -1106,7 +1248,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitTableElement(TableElementContext ctx) { - SelectOperator selectOp = new SelectOperator(SQLConstant.TOK_SELECT, zoneId); + SelectOperator selectOp = new SelectOperator(zoneId); for (TableCallContext tableCallContext : ctx.tableCall()) { SuffixPathContext suffixPathContext = tableCallContext.suffixPath(); @@ -1130,7 +1272,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { @Override public Operator visitFromClause(FromClauseContext ctx) { - FromOperator fromOp = new FromOperator(SQLConstant.TOK_FROM); + FromOperator fromOp = new FromOperator(); List<PrefixPathContext> prefixFromPaths = ctx.prefixPath(); for (PrefixPathContext prefixFromPath : prefixFromPaths) { PartialPath path = parsePrefixPath(prefixFromPath); @@ -1198,26 +1340,27 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { return sequence; } - public void parseGroupByLevelClause(GroupByLevelClauseContext ctx, QueryOperator queryOp) { - if (!queryOp.hasAggregation()) { - throw new SQLParserException(GroupByTimePlan.LACK_FUNC_ERROR_MESSAGE); + public void parseGroupByLevelClause(GroupByLevelClauseContext ctx) { + if (queryOp == null) { + queryOp = new QueryOperator(); } - queryOp.setGroupByLevel(true); queryOp.setLevel(Integer.parseInt(ctx.INT().getText())); } - public void parseFillClause(FillClauseContext ctx, QueryOperator queryOp) { - FilterOperator filterOperator = queryOp.getFilterOperator(); + public void parseFillClause(FillClauseContext ctx) { + /* FilterOperator filterOperator = queryOp.getFilterOperator(); if (!filterOperator.isLeaf() || filterOperator.getTokenIntType() != SQLConstant.EQUAL) { throw new SQLParserException("Only \"=\" can be used in fill function"); - } + }*/ + FillQueryOperator fillQueryOperator = new FillQueryOperator(); 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); + fillQueryOperator.setFillTypes(fillTypes); + + queryOp = fillQueryOperator; } private void parseLimitClause(LimitClauseContext ctx, Operator operator) { @@ -1292,47 +1435,43 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { queryOp.setSeriesOffset(soffset); } - private void parseGroupByTimeClause(GroupByTimeClauseContext ctx, QueryOperator queryOp) { - if (!queryOp.hasAggregation()) { - throw new SQLParserException(GroupByTimePlan.LACK_FUNC_ERROR_MESSAGE); - } - queryOp.setGroupByTime(true); - queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null); + private void parseGroupByTimeClause(GroupByTimeClauseContext ctx) { + GroupByQueryOperator groupByTimeOperator = new GroupByQueryOperator(); + groupByTimeOperator.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null); // parse timeUnit - queryOp.setUnit(parseDuration(ctx.DURATION(0).getText())); - queryOp.setSlidingStep(queryOp.getUnit()); + groupByTimeOperator.setUnit( + parseDuration(ctx.DURATION(0).getText(), groupByTimeOperator, false)); // parse sliding step if (ctx.DURATION().size() == 2) { - isParsingSlidingStep = true; - queryOp.setSlidingStep(parseDuration(ctx.DURATION(1).getText())); - isParsingSlidingStep = false; - if (queryOp.getSlidingStep() < queryOp.getUnit()) { + groupByTimeOperator.setSlidingStep( + parseDuration(ctx.DURATION(1).getText(), groupByTimeOperator, true)); + if (groupByTimeOperator.getSlidingStep() < groupByTimeOperator.getUnit()) { throw new SQLParserException( "The third parameter sliding step shouldn't be smaller than the second parameter time interval."); } + } else { + groupByTimeOperator.setSlidingStep(groupByTimeOperator.getUnit()); + groupByTimeOperator.setSlidingStepByMonth(groupByTimeOperator.isIntervalByMonth()); } - parseTimeInterval(ctx.timeInterval(), queryOp); - + parseTimeInterval(ctx.timeInterval(), groupByTimeOperator); if (ctx.INT() != null) { - queryOp.setGroupByLevel(true); - queryOp.setLevel(Integer.parseInt(ctx.INT().getText())); + groupByTimeOperator.setLevel(Integer.parseInt(ctx.INT().getText())); } + + queryOp = groupByTimeOperator; } - private void parseGroupByFillClause(GroupByFillClauseContext ctx, QueryOperator queryOp) { - if (!queryOp.hasAggregation()) { - throw new SQLParserException(GroupByTimePlan.LACK_FUNC_ERROR_MESSAGE); - } - queryOp.setGroupByTime(true); - queryOp.setFill(true); - queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null); + private void parseGroupByFillClause(GroupByFillClauseContext ctx) { + GroupByFillQueryOperator groupByFillOperator = new GroupByFillQueryOperator(); + groupByFillOperator.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null); // parse timeUnit - queryOp.setUnit(parseDuration(ctx.DURATION().getText())); - queryOp.setSlidingStep(queryOp.getUnit()); + groupByFillOperator.setUnit( + parseDuration(ctx.DURATION().getText(), groupByFillOperator, false)); + groupByFillOperator.setSlidingStep(groupByFillOperator.getUnit()); - parseTimeInterval(ctx.timeInterval(), queryOp); + parseTimeInterval(ctx.timeInterval(), groupByFillOperator); List<TypeClauseContext> list = ctx.typeClause(); Map<TSDataType, IFill> fillTypes = new EnumMap<>(TSDataType.class); @@ -1347,7 +1486,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { if (typeClause.previousUntilLastClause() != null) { long preRange; if (typeClause.previousUntilLastClause().DURATION() != null) { - preRange = parseDuration(typeClause.previousUntilLastClause().DURATION().getText()); + preRange = + parseDuration( + typeClause.previousUntilLastClause().DURATION().getText(), null, false); } else { preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval(); } @@ -1355,7 +1496,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { } else { long preRange; if (typeClause.previousClause().DURATION() != null) { - preRange = parseDuration(typeClause.previousClause().DURATION().getText()); + preRange = parseDuration(typeClause.previousClause().DURATION().getText(), null, false); } else { preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval(); } @@ -1369,8 +1510,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { parseTypeClause(typeClause, fillTypes); } } - queryOp.setFill(true); - queryOp.setFillTypes(fillTypes); + groupByFillOperator.setFillTypes(fillTypes); + + queryOp = groupByFillOperator; } private void parseTypeClause(TypeClauseContext ctx, Map<TSDataType, IFill> fillTypes) { @@ -1386,22 +1528,23 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { 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()); + long beforeRange = parseDuration(ctx.linearClause().DURATION(0).getText(), null, false); + long afterRange = parseDuration(ctx.linearClause().DURATION(1).getText(), null, false); 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()); + long preRange = parseDuration(ctx.previousClause().DURATION().getText(), null, false); 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()); + long preRange = + parseDuration(ctx.previousUntilLastClause().DURATION().getText(), null, false); fillTypes.put(dataType, new PreviousFill(preRange, true)); } else { fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true)); @@ -1430,8 +1573,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { } } - private void parseOrderByTimeClause(OrderByTimeClauseContext ctx, QueryOperator queryOp) { - queryOp.setColumn(ctx.TIME().getText()); + private void parseOrderByTimeClause(OrderByTimeClauseContext ctx) { if (ctx.DESC() != null) { queryOp.setAscending(false); } @@ -1445,7 +1587,8 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { queryOp.setAlignByTime(false); } - private void parseTimeInterval(TimeIntervalContext timeInterval, QueryOperator queryOp) { + private void parseTimeInterval( + TimeIntervalContext timeInterval, GroupByQueryOperator groupByQueryOperator) { long startTime; long endTime; if (timeInterval.timeValue(0).INT() != null) { @@ -1463,10 +1606,10 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { endTime = parseTimeFormat(timeInterval.timeValue(1).dateFormat().getText()); } - queryOp.setStartTime(startTime); - queryOp.setEndTime(endTime); + groupByQueryOperator.setStartTime(startTime); + groupByQueryOperator.setEndTime(endTime); if (startTime >= endTime) { - throw new SQLParserException("start time should be smaller than endTime in GroupBy"); + throw new SQLParserException("Start time should be smaller than endTime in GroupBy"); } } @@ -1684,9 +1827,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { 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()); + time += parseDuration(ctx.getChild(i + 1).getText(), null, false); } else { - time -= parseDuration(ctx.getChild(i + 1).getText()); + time -= parseDuration(ctx.getChild(i + 1).getText(), null, false); } } return time; @@ -1698,7 +1841,8 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { * @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) { + private Long parseDuration( + String durationStr, QueryOperator queryOperator, boolean isParsingSlidingStep) { String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision(); long total = 0; @@ -1710,20 +1854,17 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { tmp += (ch - '0'); } else { String unit = durationStr.charAt(i) + ""; - // This is to identify units with two letters. + // To identify units with two letters. if (i + 1 < durationStr.length() && !Character.isDigit(durationStr.charAt(i + 1))) { i++; unit += durationStr.charAt(i); } - if (unit.equalsIgnoreCase("mo")) { - // interval is by month, sliding step by default equals to interval - if (!isParsingSlidingStep) { - queryOp.setIntervalByMonth(true); + if (unit.equalsIgnoreCase("mo") && queryOperator instanceof GroupByQueryOperator) { + if (isParsingSlidingStep) { + ((GroupByQueryOperator) queryOperator).setSlidingStepByMonth(true); + } else { + ((GroupByQueryOperator) queryOperator).setIntervalByMonth(true); } - queryOp.setSlidingStepByMonth(true); - } else if (isParsingSlidingStep) { - // parsing sliding step value, and unit is not by month - queryOp.setSlidingStepByMonth(false); } total += DatetimeUtils.convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision); 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 fdb331b..e3ff621 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 @@ -30,7 +30,10 @@ 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.BasicFunctionOperator; import org.apache.iotdb.db.qp.logical.crud.DeleteDataOperator; +import org.apache.iotdb.db.qp.logical.crud.FillQueryOperator; import org.apache.iotdb.db.qp.logical.crud.FilterOperator; +import org.apache.iotdb.db.qp.logical.crud.GroupByFillQueryOperator; +import org.apache.iotdb.db.qp.logical.crud.GroupByQueryOperator; import org.apache.iotdb.db.qp.logical.crud.InsertOperator; import org.apache.iotdb.db.qp.logical.crud.QueryOperator; import org.apache.iotdb.db.qp.logical.sys.AlterTimeSeriesOperator; @@ -472,9 +475,9 @@ public class PhysicalGenerator { throw new QueryProcessException( "User-defined and built-in hybrid aggregation is not supported."); } - if (queryOperator.isGroupByTime() && queryOperator.isFill()) { + if (queryOperator instanceof GroupByFillQueryOperator) { queryPlan = new GroupByTimeFillPlan(); - } else if (queryOperator.isGroupByTime()) { + } else if (queryOperator instanceof GroupByQueryOperator) { queryPlan = new GroupByTimePlan(); } else { queryPlan = new AggregationPlan(); @@ -482,29 +485,31 @@ public class PhysicalGenerator { ((AggregationPlan) queryPlan) .setAggregations(queryOperator.getSelectOperator().getAggregations()); - if (queryOperator.isGroupByTime()) { + if (queryOperator instanceof GroupByQueryOperator) { GroupByTimePlan groupByTimePlan = (GroupByTimePlan) queryPlan; - groupByTimePlan.setInterval(queryOperator.getUnit()); - groupByTimePlan.setIntervalByMonth(queryOperator.isIntervalByMonth()); - groupByTimePlan.setSlidingStep(queryOperator.getSlidingStep()); - groupByTimePlan.setSlidingStepByMonth(queryOperator.isSlidingStepByMonth()); - groupByTimePlan.setLeftCRightO(queryOperator.isLeftCRightO()); - if (!queryOperator.isLeftCRightO()) { - groupByTimePlan.setStartTime(queryOperator.getStartTime() + 1); - groupByTimePlan.setEndTime(queryOperator.getEndTime() + 1); + GroupByQueryOperator tmpOperator = (GroupByQueryOperator) queryOperator; + groupByTimePlan.setInterval(tmpOperator.getUnit()); + groupByTimePlan.setIntervalByMonth(tmpOperator.isIntervalByMonth()); + groupByTimePlan.setSlidingStep(tmpOperator.getSlidingStep()); + groupByTimePlan.setSlidingStepByMonth(tmpOperator.isSlidingStepByMonth()); + groupByTimePlan.setLeftCRightO(tmpOperator.isLeftCRightO()); + if (!tmpOperator.isLeftCRightO()) { + groupByTimePlan.setStartTime(tmpOperator.getStartTime() + 1); + groupByTimePlan.setEndTime(tmpOperator.getEndTime() + 1); } else { - groupByTimePlan.setStartTime(queryOperator.getStartTime()); - groupByTimePlan.setEndTime(queryOperator.getEndTime()); + groupByTimePlan.setStartTime(tmpOperator.getStartTime()); + groupByTimePlan.setEndTime(tmpOperator.getEndTime()); } } - if (queryOperator.isFill()) { - ((GroupByTimeFillPlan) queryPlan).setFillType(queryOperator.getFillTypes()); + if (queryOperator instanceof GroupByFillQueryOperator) { + ((GroupByTimeFillPlan) queryPlan) + .setFillType(((GroupByFillQueryOperator) queryOperator).getFillTypes()); for (String aggregation : queryPlan.getAggregations()) { if (!SQLConstant.LAST_VALUE.equals(aggregation)) { throw new QueryProcessException("Group By Fill only support last_value function"); } } - } else if (queryOperator.isGroupByLevel()) { + } else if (queryOperator.getLevel() != -1) { ((AggregationPlan) queryPlan).setLevel(queryOperator.getLevel()); try { if (!verifyAllAggregationDataTypesEqual(queryOperator)) { @@ -533,7 +538,7 @@ public class PhysicalGenerator { } long time = Long.parseLong(((BasicFunctionOperator) timeFilter).getValue()); queryPlan.setQueryTime(time); - queryPlan.setFillType(queryOperator.getFillTypes()); + queryPlan.setFillType(((FillQueryOperator) queryOperator).getFillTypes()); return queryPlan; } } @@ -544,7 +549,7 @@ public class PhysicalGenerator { if (queryOperator.hasAggregation()) { queryPlan = new AggPhysicalPlanRule().transform(queryOperator); - } else if (queryOperator.isFill()) { + } else if (queryOperator instanceof FillQueryOperator) { queryPlan = new FillPhysicalPlanRule().transform(queryOperator); } else if (queryOperator.isLastQuery()) { queryPlan = new LastQueryPlan(); @@ -983,7 +988,7 @@ public class PhysicalGenerator { } private static boolean verifyAllAggregationDataTypesEqual(QueryOperator queryOperator) - throws MetadataException { + throws MetadataException, QueryProcessException { List<String> aggregations = queryOperator.getSelectOperator().getAggregations(); if (aggregations.isEmpty()) { return true;
