This is an automated email from the ASF dual-hosted git repository. hui pushed a commit to branch lmh/modifySchemaTreeInterface in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 71ad1571ac49cd5a1e6d23a621295ebf84022dac Author: Minghui Liu <[email protected]> AuthorDate: Thu Dec 15 22:22:59 2022 +0800 refactor analyze groupByTag --- .../apache/iotdb/db/mpp/plan/analyze/Analysis.java | 8 --- .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 70 +++++++++------------- .../db/mpp/plan/analyze/ExpressionAnalyzer.java | 1 + .../db/mpp/plan/statement/crud/QueryStatement.java | 15 ++++- 4 files changed, 43 insertions(+), 51 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analysis.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analysis.java index 4b08a15181..2b4ad26216 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analysis.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analysis.java @@ -36,7 +36,6 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.GroupByTimeParameter; import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.IntoPathDescriptor; import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.OrderByParameter; import org.apache.iotdb.db.mpp.plan.statement.Statement; -import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement; import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import org.apache.iotdb.tsfile.read.filter.basic.Filter; import org.apache.iotdb.tsfile.utils.Pair; @@ -258,13 +257,6 @@ public class Analysis { return type; } - public boolean hasDataSource() { - return (dataPartition != null && !dataPartition.isEmpty()) - || (schemaPartition != null && !schemaPartition.isEmpty()) - || (statement instanceof QueryStatement - && ((QueryStatement) statement).isAggregationQuery()); - } - public LinkedHashMap<Expression, Set<Expression>> getCrossGroupByExpressions() { return crossGroupByExpressions; } 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 469c6b5f6a..5bcffe3b7e 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 @@ -266,11 +266,15 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> } else { Map<Integer, List<Pair<Expression, String>>> outputExpressionMap = analyzeSelect(analysis, queryStatement, schemaTree); + outputExpressions = new ArrayList<>(); outputExpressionMap.values().forEach(outputExpressions::addAll); + analyzeHaving(analysis, queryStatement, schemaTree); + analyzeGroupByLevel(analysis, queryStatement, outputExpressionMap, outputExpressions); - analyzeGroupByTag(analysis, queryStatement, outputExpressions, schemaTree); + analyzeGroupByTag(analysis, queryStatement, outputExpressions); + Set<Expression> selectExpressions = outputExpressions.stream() .map(Pair::getLeft) @@ -729,61 +733,43 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> private void analyzeGroupByTag( Analysis analysis, QueryStatement queryStatement, - List<Pair<Expression, String>> outputExpressions, - ISchemaTree schemaTree) { + List<Pair<Expression, String>> outputExpressions) { if (!queryStatement.isGroupByTag()) { return; } if (analysis.hasValueFilter()) { throw new SemanticException("Only time filters are supported in GROUP BY TAGS query"); } + + List<String> tagKeys = queryStatement.getGroupByTagComponent().getTagKeys(); Map<List<String>, LinkedHashMap<Expression, List<Expression>>> tagValuesToGroupedTimeseriesOperands = new HashMap<>(); - LinkedHashMap<Expression, Set<Expression>> groupByTagOutputExpressions = new LinkedHashMap<>(); - List<String> tagKeys = queryStatement.getGroupByTagComponent().getTagKeys(); - List<MeasurementPath> allSelectedPath = schemaTree.getAllMeasurement(); - Map<MeasurementPath, Map<String, String>> queriedTagMap = new HashMap<>(); - allSelectedPath.forEach(v -> queriedTagMap.put(v, v.getTagMap())); + LinkedHashMap<Expression, Set<Expression>> outputExpressionToRawExpressionsMap = + new LinkedHashMap<>(); for (Pair<Expression, String> outputExpressionAndAlias : outputExpressions) { - if (!(outputExpressionAndAlias.getLeft() instanceof FunctionExpression - && outputExpressionAndAlias.getLeft().getExpressions().get(0) instanceof TimeSeriesOperand - && outputExpressionAndAlias.getLeft().isBuiltInAggregationFunctionExpression())) { - throw new SemanticException( - outputExpressionAndAlias.getLeft() - + " can't be used in group by tag. It will be supported in the future."); - } - FunctionExpression outputExpression = (FunctionExpression) outputExpressionAndAlias.getLeft(); - MeasurementPath measurementPath = - (MeasurementPath) - ((TimeSeriesOperand) outputExpression.getExpressions().get(0)).getPath(); - MeasurementPath fakePath = null; - try { - fakePath = - new MeasurementPath(measurementPath.getMeasurement(), measurementPath.getSeriesType()); - } catch (IllegalPathException e) { - // do nothing - } - Expression measurementExpression = new TimeSeriesOperand(fakePath); - Expression groupedExpression = - new FunctionExpression( - outputExpression.getFunctionName(), - outputExpression.getFunctionAttributes(), - Collections.singletonList(measurementExpression)); - groupByTagOutputExpressions - .computeIfAbsent(groupedExpression, v -> new HashSet<>()) - .add(outputExpression); - Map<String, String> tagMap = queriedTagMap.get(measurementPath); + FunctionExpression rawExpression = (FunctionExpression) outputExpressionAndAlias.getLeft(); + FunctionExpression measurementExpression = + (FunctionExpression) ExpressionAnalyzer.getMeasurementExpression(rawExpression); + outputExpressionToRawExpressionsMap + .computeIfAbsent(measurementExpression, v -> new HashSet<>()) + .add(rawExpression); + + Map<String, String> tagMap = + ((MeasurementPath) + ((TimeSeriesOperand) measurementExpression.getExpressions().get(0)).getPath()) + .getTagMap(); List<String> tagValues = new ArrayList<>(); for (String tagKey : tagKeys) { tagValues.add(tagMap.get(tagKey)); } tagValuesToGroupedTimeseriesOperands .computeIfAbsent(tagValues, key -> new LinkedHashMap<>()) - .computeIfAbsent(groupedExpression, key -> new ArrayList<>()) - .add(outputExpression.getExpressions().get(0)); + .computeIfAbsent(measurementExpression, key -> new ArrayList<>()) + .add(rawExpression.getExpressions().get(0)); } + // update outputExpressions outputExpressions.clear(); for (String tagKey : tagKeys) { Expression tagKeyExpression = @@ -791,14 +777,14 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> analyzeExpression(analysis, tagKeyExpression); outputExpressions.add(new Pair<>(tagKeyExpression, null)); } - for (Expression groupByTagOutputExpression : groupByTagOutputExpressions.keySet()) { + for (Expression outputExpression : outputExpressionToRawExpressionsMap.keySet()) { // TODO: support alias - analyzeExpression(analysis, groupByTagOutputExpression); - outputExpressions.add(new Pair<>(groupByTagOutputExpression, null)); + analyzeExpression(analysis, outputExpression); + outputExpressions.add(new Pair<>(outputExpression, null)); } analysis.setTagKeys(queryStatement.getGroupByTagComponent().getTagKeys()); analysis.setTagValuesToGroupedTimeseriesOperands(tagValuesToGroupedTimeseriesOperands); - analysis.setCrossGroupByExpressions(groupByTagOutputExpressions); + analysis.setCrossGroupByExpressions(outputExpressionToRawExpressionsMap); } private void analyzeDeviceToAggregation( diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java index d0be42611a..cd8143ea08 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java @@ -1185,6 +1185,7 @@ public class ExpressionAnalyzer { if (rawPath.isMeasurementAliasExists()) { measurementWithSchema.setMeasurementAlias(rawPath.getMeasurementAlias()); } + measurementWithSchema.setTagMap(rawPath.getTagMap()); return new TimeSeriesOperand(measurementWithSchema); } else if (expression instanceof LeafOperand) { return expression; 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 f8c84f38e5..a1e164c7d8 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 @@ -25,6 +25,7 @@ import org.apache.iotdb.db.mpp.plan.analyze.ExpressionAnalyzer; import org.apache.iotdb.db.mpp.plan.constant.StatementType; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; +import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression; import org.apache.iotdb.db.mpp.plan.statement.Statement; import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor; import org.apache.iotdb.db.mpp.plan.statement.component.FillComponent; @@ -355,6 +356,9 @@ public class QueryStatement extends Statement { : resultColumn.getExpression().getExpressionString()); } if (isGroupByTag()) { + if (hasHaving()) { + throw new SemanticException("Having clause is not supported yet in GROUP BY TAGS query"); + } for (String s : getGroupByTagComponent().getTagKeys()) { if (outputColumn.contains(s)) { throw new SemanticException("Output column is duplicated with the tag key: " + s); @@ -363,6 +367,15 @@ public class QueryStatement extends Statement { if (rowLimit > 0 || rowOffset > 0 || seriesLimit > 0 || seriesOffset > 0) { throw new SemanticException("Limit or slimit are not supported yet in GROUP BY TAGS"); } + for (ResultColumn resultColumn : selectComponent.getResultColumns()) { + Expression expression = resultColumn.getExpression(); + if (!(expression instanceof FunctionExpression + && expression.getExpressions().get(0) instanceof TimeSeriesOperand + && expression.isBuiltInAggregationFunctionExpression())) { + throw new SemanticException( + expression + " can't be used in group by tag. It will be supported in the future."); + } + } } } else { if (isGroupByTime() || isGroupByLevel()) { @@ -371,7 +384,7 @@ public class QueryStatement extends Statement { } } - if (getHavingCondition() != null) { + if (hasHaving()) { Expression havingExpression = getHavingCondition().getPredicate(); if (ExpressionAnalyzer.identifyOutputColumnType(havingExpression, true) != ResultColumn.ColumnType.AGGREGATION) {
