This is an automated email from the ASF dual-hosted git repository. hui pushed a commit to branch lmh/SupportQueryWithView in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 46ce80bd7c3f4621117cbcadff9ccaf7d18cace8 Author: Minghui Liu <[email protected]> AuthorDate: Sat May 27 21:55:43 2023 +0800 tmp save --- .../visitor/GetSourcePathsVisitor.java | 4 + .../apache/iotdb/db/mpp/plan/analyze/Analysis.java | 11 ++ .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 100 ++++++++------- .../db/mpp/plan/analyze/ExpressionAnalyzer.java | 14 +-- .../iotdb/db/mpp/plan/analyze/ExpressionUtils.java | 137 ++++----------------- .../visitor/ExpressionAnalyzeVisitor.java | 2 +- .../visitor/GetMeasurementExpressionVisitor.java | 16 ++- .../expression/visitor/ReconstructVisitor.java | 3 +- .../RemoveWildcardAndViewInExpressionVisitor.java | 95 -------------- .../{ => cartesian}/CartesianProductVisitor.java | 5 +- .../ConcatDeviceAndRemoveWildcardVisitor.java | 28 ++++- .../ConcatExpressionWithSuffixPathsVisitor.java | 2 +- .../RemoveWildcardAndViewInFilterVisitor.java | 9 +- .../RemoveWildcardInExpressionVisitor.java | 59 ++++++--- .../RemoveWildcardInFilterByDeviceVisitor.java | 2 +- .../RemoveWildcardInFilterVisitor.java | 25 +++- .../db/mpp/plan/planner/LogicalPlanBuilder.java | 4 +- .../db/mpp/plan/planner/LogicalPlanVisitor.java | 1 + .../plan/planner/distribution/SourceRewriter.java | 59 ++++++--- 19 files changed, 261 insertions(+), 315 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java index 321742fdf4c..1874234a39f 100644 --- a/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/metadata/view/viewExpression/visitor/GetSourcePathsVisitor.java @@ -36,6 +36,10 @@ import java.util.List; /** Use this visitor to find all the paths of time series used in one expression. */ public class GetSourcePathsVisitor extends ViewExpressionVisitor<List<PartialPath>, Void> { + public static List<PartialPath> getSourcePaths(ViewExpression viewExpression) { + return new GetSourcePathsVisitor().process(viewExpression, null); + } + @Override public List<PartialPath> visitExpression(ViewExpression expression, Void context) { return new ArrayList<>(); 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 db2ae86e9d6..dc2adf437f0 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 @@ -154,6 +154,8 @@ public class Analysis { // not 0 because device is the first column private Map<String, List<Integer>> deviceViewInputIndexesMap; + private Map<String, List<String>> outputDeviceToQueryDeviceMap; + private Set<Expression> deviceViewOutputExpressions; // indicates whether DeviceView need special process when rewriteSource in DistributionPlan, @@ -435,6 +437,15 @@ public class Analysis { return deviceViewInputIndexesMap; } + public Map<String, List<String>> getOutputDeviceToQueryDeviceMap() { + return outputDeviceToQueryDeviceMap; + } + + public void setOutputDeviceToQueryDeviceMap( + Map<String, List<String>> outputDeviceToQueryDeviceMap) { + this.outputDeviceToQueryDeviceMap = outputDeviceToQueryDeviceMap; + } + public Set<Expression> getSourceExpressions() { return sourceExpressions; } 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 909b3e24685..f4329bfd8bf 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 @@ -50,7 +50,6 @@ import org.apache.iotdb.db.exception.sql.MeasurementNotExistException; import org.apache.iotdb.db.exception.sql.SemanticException; import org.apache.iotdb.db.exception.sql.StatementAnalyzeException; import org.apache.iotdb.db.metadata.template.Template; -import org.apache.iotdb.db.metadata.view.viewExpression.visitor.GetSourcePathsVisitor; import org.apache.iotdb.db.mpp.common.MPPQueryContext; import org.apache.iotdb.db.mpp.common.header.ColumnHeader; import org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant; @@ -189,6 +188,7 @@ import static org.apache.iotdb.commons.conf.IoTDBConstant.ALLOWED_SCHEMA_PROPS; import static org.apache.iotdb.commons.conf.IoTDBConstant.DEADBAND; import static org.apache.iotdb.commons.conf.IoTDBConstant.LOSS; import static org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD; +import static org.apache.iotdb.db.metadata.view.viewExpression.visitor.GetSourcePathsVisitor.getSourcePaths; import static org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant.DEVICE; import static org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant.ENDTIME; import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetricSet.PARTITION_FETCHER; @@ -322,6 +322,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> outputExpressions = new ArrayList<>(); outputExpressionMap.values().forEach(outputExpressions::addAll); + analysis.setOutputExpressions(outputExpressions); if (outputExpressions.isEmpty()) { return finishQuery(queryStatement, analysis); } @@ -351,7 +352,6 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> analyzeInto(analysis, queryStatement, outputExpressions); } - analysis.setOutputExpressions(outputExpressions); analyzeGroupByTime(analysis, queryStatement); @@ -452,39 +452,38 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> analysis.setSourceExpressions(sourceExpressions); } - private ISchemaTree findAllViewsInTreeThenReFetchAndMerge(ISchemaTree originSchemaTree) { - if (originSchemaTree.hasLogicalViewMeasurement()) { - PathPatternTree patternTree = new PathPatternTree(); - GetSourcePathsVisitor getSourcePathsVisitor = new GetSourcePathsVisitor(); - boolean needToReFetch = false; - try { - Pair<List<MeasurementPath>, Integer> tempPair = - originSchemaTree.searchMeasurementPaths(new PartialPath("root.**")); - for (MeasurementPath measurementPath : tempPair.left) { - if (measurementPath.getMeasurementSchema().isLogicalView()) { - LogicalViewSchema logicalViewSchema = - (LogicalViewSchema) measurementPath.getMeasurementSchema(); - ViewExpression viewExpression = logicalViewSchema.getExpression(); - List<PartialPath> pathsNeedToReFetch = - getSourcePathsVisitor.process(viewExpression, null); - for (PartialPath path : pathsNeedToReFetch) { - patternTree.appendFullPath(path); - needToReFetch = true; - } + private void findAllViewsInTreeThenReFetchAndMerge(ISchemaTree originSchemaTree) { + if (!originSchemaTree.hasLogicalViewMeasurement()) { + return; + } + + PathPatternTree patternTree = new PathPatternTree(); + boolean needToReFetch = false; + try { + Pair<List<MeasurementPath>, Integer> tempPair = + originSchemaTree.searchMeasurementPaths(new PartialPath("root.**")); + for (MeasurementPath measurementPath : tempPair.left) { + if (measurementPath.getMeasurementSchema().isLogicalView()) { + LogicalViewSchema logicalViewSchema = + (LogicalViewSchema) measurementPath.getMeasurementSchema(); + ViewExpression viewExpression = logicalViewSchema.getExpression(); + List<PartialPath> pathsNeedToReFetch = getSourcePaths(viewExpression); + for (PartialPath path : pathsNeedToReFetch) { + patternTree.appendFullPath(path); + needToReFetch = true; } } - } catch (Exception e) { - throw new RuntimeException(e); - } - if (needToReFetch) { - ISchemaTree viewSchemaTree = this.schemaFetcher.fetchSchema(patternTree, null); - originSchemaTree.mergeSchemaTree(viewSchemaTree); - Set<String> allDatabases = viewSchemaTree.getDatabases(); - allDatabases.addAll(originSchemaTree.getDatabases()); - originSchemaTree.setDatabases(allDatabases); } + } catch (Exception e) { + throw new RuntimeException(e); + } + if (needToReFetch) { + ISchemaTree viewSchemaTree = this.schemaFetcher.fetchSchema(patternTree, null); + originSchemaTree.mergeSchemaTree(viewSchemaTree); + Set<String> allDatabases = viewSchemaTree.getDatabases(); + allDatabases.addAll(originSchemaTree.getDatabases()); + originSchemaTree.setDatabases(allDatabases); } - return originSchemaTree; } private Map<Integer, List<Pair<Expression, String>>> analyzeSelect( @@ -525,17 +524,18 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> } else { Expression expressionWithoutAlias = ExpressionAnalyzer.removeAliasFromExpression(expression); - String alias = expression.getStringWithViewOfThisExpression(); - alias = hasAlias ? resultColumn.getAlias() : alias; if (hasAlias) { + String alias = resultColumn.getAlias(); if (aliasSet.contains(alias)) { throw new SemanticException( String.format("alias '%s' can only be matched with one time series", alias)); } aliasSet.add(alias); } + String outputColumnName = + hasAlias ? resultColumn.getAlias() : expression.getOutputSymbol(); analyzeExpression(analysis, expressionWithoutAlias); - outputExpressions.add(new Pair<>(expressionWithoutAlias, alias)); + outputExpressions.add(new Pair<>(expressionWithoutAlias, outputColumnName)); } paginationController.consumeLimit(); } else { @@ -625,13 +625,10 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> // add outputExpressions Expression measurementExpressionWithoutAlias = ExpressionAnalyzer.removeAliasFromExpression(measurementExpression); - String alias = - !Objects.equals(measurementExpressionWithoutAlias, measurementExpression) - ? measurementExpression.getExpressionString() - : null; - alias = hasAlias ? resultColumn.getAlias() : alias; + String outputColumnName = + hasAlias ? resultColumn.getAlias() : measurementExpression.getOutputSymbol(); analyzeExpression(analysis, measurementExpressionWithoutAlias); - outputExpressions.add(new Pair<>(measurementExpressionWithoutAlias, alias)); + outputExpressions.add(new Pair<>(measurementExpressionWithoutAlias, outputColumnName)); // add deviceToSelectExpressions for (String deviceName : deviceToSelectExpressionsOfOneMeasurement.keySet()) { @@ -1190,7 +1187,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> List<String> deviceViewOutputColumns = deviceViewOutputExpressions.stream() - .map(Expression::getExpressionString) + .map(Expression::getOutputSymbol) .collect(Collectors.toList()); Map<String, Set<String>> deviceToOutputColumnsMap = new LinkedHashMap<>(); @@ -1205,11 +1202,25 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> outputColumns.add(ENDTIME); } for (Expression expression : outputExpressionsUnderDevice) { - outputColumns.add(ExpressionAnalyzer.getMeasurementExpression(expression).toString()); + outputColumns.add( + ExpressionAnalyzer.getMeasurementExpression(expression).getOutputSymbol()); } deviceToOutputColumnsMap.put(deviceName, outputColumns); } + Map<String, Set<Expression>> deviceToSourceExpressions = + analysis.getDeviceToSourceExpressions(); + Map<String, List<String>> outputDeviceToQueryDeviceMap = new LinkedHashMap<>(); + for (String deviceName : deviceToSourceExpressions.keySet()) { + Set<Expression> sourceExpressionsUnderDevice = deviceToSourceExpressions.get(deviceName); + Set<String> queriedDevices = new HashSet<>(); + for (Expression expression : sourceExpressionsUnderDevice) { + queriedDevices.add(ExpressionAnalyzer.getDeviceNameInSourceExpression(expression)); + } + outputDeviceToQueryDeviceMap.put(deviceName, new ArrayList<>(queriedDevices)); + } + analysis.setOutputDeviceToQueryDeviceMap(outputDeviceToQueryDeviceMap); + Map<String, List<Integer>> deviceViewInputIndexesMap = new HashMap<>(); for (String deviceName : deviceToOutputColumnsMap.keySet()) { List<String> outputsUnderDevice = new ArrayList<>(deviceToOutputColumnsMap.get(deviceName)); @@ -1558,7 +1569,10 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext> Analysis analysis, QueryStatement queryStatement, ISchemaTree schemaTree) { Set<String> deviceSet = new HashSet<>(); if (queryStatement.isAlignByDevice()) { - deviceSet = analysis.getDeviceToSourceExpressions().keySet(); + deviceSet = + analysis.getOutputDeviceToQueryDeviceMap().values().stream() + .flatMap(List::stream) + .collect(Collectors.toSet()); } else { for (Expression expression : analysis.getSourceExpressions()) { deviceSet.add(ExpressionAnalyzer.getDeviceNameInSourceExpression(expression)); 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 8525bedf97a..1d050087766 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 @@ -46,16 +46,16 @@ import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression; import org.apache.iotdb.db.mpp.plan.expression.visitor.BindTypeForTimeSeriesOperandVisitor; import org.apache.iotdb.db.mpp.plan.expression.visitor.CollectAggregationExpressionsVisitor; import org.apache.iotdb.db.mpp.plan.expression.visitor.CollectSourceExpressionsVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.ConcatDeviceAndRemoveWildcardVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.ConcatExpressionWithSuffixPathsVisitor; import org.apache.iotdb.db.mpp.plan.expression.visitor.GetMeasurementExpressionVisitor; import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveAliasFromExpressionVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveWildcardAndViewInExpressionVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveWildcardAndViewInFilterVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveWildcardInExpressionVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveWildcardInFilterByDeviceVisitor; -import org.apache.iotdb.db.mpp.plan.expression.visitor.RemoveWildcardInFilterVisitor; import org.apache.iotdb.db.mpp.plan.expression.visitor.ReplaceRawPathWithGroupedPathVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.ConcatDeviceAndRemoveWildcardVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.ConcatExpressionWithSuffixPathsVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardAndViewInExpressionVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardAndViewInFilterVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardInExpressionVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardInFilterByDeviceVisitor; +import org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardInFilterVisitor; import org.apache.iotdb.db.mpp.plan.statement.component.ResultColumn; import org.apache.iotdb.tsfile.common.constant.TsFileConstant; import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionUtils.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionUtils.java index 921c012d5be..025919d39c3 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionUtils.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionUtils.java @@ -22,19 +22,8 @@ package org.apache.iotdb.db.mpp.plan.analyze; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.ExpressionType; -import org.apache.iotdb.db.mpp.plan.expression.binary.AdditionExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.DivisionExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.EqualToExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterThanExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.LessEqualExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression; +import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression; import org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.LogicOrExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.ModuloExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.MultiplicationExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.NonEqualExpression; -import org.apache.iotdb.db.mpp.plan.expression.binary.SubtractionExpression; import org.apache.iotdb.db.mpp.plan.expression.binary.WhenThenExpression; import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; @@ -42,12 +31,7 @@ import org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand; import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression; import org.apache.iotdb.db.mpp.plan.expression.other.CaseWhenThenExpression; import org.apache.iotdb.db.mpp.plan.expression.ternary.BetweenExpression; -import org.apache.iotdb.db.mpp.plan.expression.unary.InExpression; -import org.apache.iotdb.db.mpp.plan.expression.unary.IsNullExpression; -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.expression.ternary.TernaryExpression; import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression; import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import org.apache.iotdb.tsfile.read.filter.TimeFilter; @@ -63,7 +47,7 @@ public class ExpressionUtils { List<? extends PartialPath> actualPaths) { List<Expression> resultExpressions = new ArrayList<>(); for (PartialPath actualPath : actualPaths) { - resultExpressions.add(new TimeSeriesOperand(actualPath)); + resultExpressions.add(reconstructTimeSeriesOperand(actualPath)); } return resultExpressions; } @@ -76,19 +60,16 @@ public class ExpressionUtils { FunctionExpression expression, List<List<Expression>> childExpressionsList) { List<Expression> resultExpressions = new ArrayList<>(); for (List<Expression> functionExpressions : childExpressionsList) { - resultExpressions.add( - new FunctionExpression( - expression.getFunctionName(), - expression.getFunctionAttributes(), - functionExpressions)); + resultExpressions.add(reconstructFunctionExpression(expression, functionExpressions)); } return resultExpressions; } public static Expression reconstructFunctionExpression( FunctionExpression expression, List<Expression> childExpressions) { - return new FunctionExpression( - expression.getFunctionName(), expression.getFunctionAttributes(), childExpressions); + FunctionExpression copiedFunctionExpression = (FunctionExpression) expression.copy(); + copiedFunctionExpression.setExpressions(childExpressions); + return copiedFunctionExpression; } public static List<Expression> reconstructUnaryExpressions( @@ -111,98 +92,34 @@ public class ExpressionUtils { public static Expression reconstructUnaryExpression( UnaryExpression expression, Expression childExpression) { - switch (expression.getExpressionType()) { - case IS_NULL: - return new IsNullExpression(childExpression, ((IsNullExpression) expression).isNot()); - case IN: - return new InExpression( - childExpression, - ((InExpression) expression).isNotIn(), - ((InExpression) expression).getValues()); - case LIKE: - return new LikeExpression( - childExpression, - ((LikeExpression) expression).getPatternString(), - ((LikeExpression) expression).getPattern()); - case LOGIC_NOT: - return new LogicNotExpression(childExpression); - - case NEGATION: - return new NegationExpression(childExpression); - - case REGEXP: - return new RegularExpression( - childExpression, - ((RegularExpression) expression).getPatternString(), - ((RegularExpression) expression).getPattern()); - - default: - throw new IllegalArgumentException( - "unsupported expression type: " + expression.getExpressionType()); - } + UnaryExpression copiedUnaryExpression = (UnaryExpression) expression.copy(); + copiedUnaryExpression.setExpression(childExpression); + return copiedUnaryExpression; } public static List<Expression> reconstructBinaryExpressions( - ExpressionType expressionType, + BinaryExpression expression, List<Expression> leftExpressions, List<Expression> rightExpressions) { List<Expression> resultExpressions = new ArrayList<>(); for (Expression le : leftExpressions) { for (Expression re : rightExpressions) { - resultExpressions.add(reconstructBinaryExpression(expressionType, le, re)); + resultExpressions.add(reconstructBinaryExpression(expression, le, re)); } } return resultExpressions; } public static Expression reconstructBinaryExpression( - ExpressionType expressionType, Expression leftExpression, Expression rightExpression) { - switch (expressionType) { - case ADDITION: - return new AdditionExpression(leftExpression, rightExpression); - - case SUBTRACTION: - return new SubtractionExpression(leftExpression, rightExpression); - case MULTIPLICATION: - return new MultiplicationExpression(leftExpression, rightExpression); - case DIVISION: - return new DivisionExpression(leftExpression, rightExpression); - case MODULO: - return new ModuloExpression(leftExpression, rightExpression); - - case LESS_THAN: - return new LessThanExpression(leftExpression, rightExpression); - case LESS_EQUAL: - return new LessEqualExpression(leftExpression, rightExpression); - - case GREATER_THAN: - return new GreaterThanExpression(leftExpression, rightExpression); - - case GREATER_EQUAL: - return new GreaterEqualExpression(leftExpression, rightExpression); - - case EQUAL_TO: - return new EqualToExpression(leftExpression, rightExpression); - - case NON_EQUAL: - return new NonEqualExpression(leftExpression, rightExpression); - - case LOGIC_AND: - return new LogicAndExpression(leftExpression, rightExpression); - - case LOGIC_OR: - return new LogicOrExpression(leftExpression, rightExpression); - - case WHEN_THEN: - return new WhenThenExpression(leftExpression, rightExpression); - - default: - throw new IllegalArgumentException("unsupported expression type: " + expressionType); - } + BinaryExpression expression, Expression leftExpression, Expression rightExpression) { + BinaryExpression copiedBinaryExpression = (BinaryExpression) expression.copy(); + copiedBinaryExpression.setLeftExpression(leftExpression); + copiedBinaryExpression.setRightExpression(rightExpression); + return copiedBinaryExpression; } public static List<Expression> reconstructTernaryExpressions( - Expression expression, + TernaryExpression expression, List<Expression> firstExpressions, List<Expression> secondExpressions, List<Expression> thirdExpressions) { @@ -217,21 +134,15 @@ public class ExpressionUtils { } public static Expression reconstructTernaryExpression( - Expression expression, + TernaryExpression expression, Expression firstExpression, Expression secondExpression, Expression thirdExpression) { - switch (expression.getExpressionType()) { - case BETWEEN: - return new BetweenExpression( - firstExpression, - secondExpression, - thirdExpression, - ((BetweenExpression) expression).isNotBetween()); - default: - throw new IllegalArgumentException( - "unsupported expression type: " + expression.getExpressionType()); - } + TernaryExpression copiedTernaryExpression = (TernaryExpression) expression.copy(); + copiedTernaryExpression.setFirstExpression(firstExpression); + copiedTernaryExpression.setFirstExpression(secondExpression); + copiedTernaryExpression.setThirdExpression(thirdExpression); + return copiedTernaryExpression; } /** diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionAnalyzeVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionAnalyzeVisitor.java index fdb5f34df30..8f9b346fa6b 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionAnalyzeVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionAnalyzeVisitor.java @@ -31,7 +31,7 @@ public abstract class ExpressionAnalyzeVisitor<R, C> extends ExpressionVisitor<R "unsupported expression type: " + expression.getExpressionType()); } - List<R> getResultsFromChild(Expression expression, C context) { + protected List<R> getResultsFromChild(Expression expression, C context) { return expression.getExpressions().stream() .map(child -> this.process(child, context)) .collect(Collectors.toList()); diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/GetMeasurementExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/GetMeasurementExpressionVisitor.java index a47c88a2742..60f346163d0 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/GetMeasurementExpressionVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/GetMeasurementExpressionVisitor.java @@ -29,6 +29,18 @@ import java.util.ArrayList; import java.util.List; public class GetMeasurementExpressionVisitor extends ReconstructVisitor<Void> { + + @Override + public Expression process(Expression expression, Void context) { + Expression newExpression = expression.accept(this, context); + + if (expression.getViewPath() != null) { + PartialPath viewPath = expression.getViewPath(); + newExpression.setViewPath(new PartialPath(viewPath.getMeasurement(), false)); + } + return newExpression; + } + @Override public Expression visitFunctionExpression(FunctionExpression functionExpression, Void context) { List<Expression> childExpressions = new ArrayList<>(); @@ -36,8 +48,8 @@ public class GetMeasurementExpressionVisitor extends ReconstructVisitor<Void> { childExpressions.add(process(suffixExpression, null)); } return new FunctionExpression( - ((FunctionExpression) functionExpression).getFunctionName(), - ((FunctionExpression) functionExpression).getFunctionAttributes(), + functionExpression.getFunctionName(), + functionExpression.getFunctionAttributes(), childExpressions); } diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ReconstructVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ReconstructVisitor.java index 83f2ad01d87..52e96f770e9 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ReconstructVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ReconstructVisitor.java @@ -48,8 +48,7 @@ public abstract class ReconstructVisitor<C> extends ExpressionAnalyzeVisitor<Exp @Override public Expression visitBinaryExpression(BinaryExpression binaryExpression, C context) { List<Expression> childResults = getResultsFromChild(binaryExpression, context); - return reconstructBinaryExpression( - binaryExpression.getExpressionType(), childResults.get(0), childResults.get(1)); + return reconstructBinaryExpression(binaryExpression, childResults.get(0), childResults.get(1)); } @Override diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInExpressionVisitor.java deleted file mode 100644 index 303df8ce695..00000000000 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInExpressionVisitor.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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.expression.visitor; - -import org.apache.iotdb.commons.path.MeasurementPath; -import org.apache.iotdb.commons.path.PartialPath; -import org.apache.iotdb.commons.schema.view.LogicalViewSchema; -import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression; -import org.apache.iotdb.db.metadata.view.viewExpression.visitor.TransformToExpressionVisitor; -import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree; -import org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils; -import org.apache.iotdb.db.mpp.plan.expression.Expression; -import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; -import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema; - -import java.util.ArrayList; -import java.util.List; - -public class RemoveWildcardAndViewInExpressionVisitor extends RemoveWildcardInExpressionVisitor { - private final TransformToExpressionVisitor transformToExpressionVisitor; - - private final CompleteMeasurementSchemaVisitor completeMeasurementSchemaVisitor; - - boolean hasProcessedLogicalView; - - public RemoveWildcardAndViewInExpressionVisitor() { - super(); - this.transformToExpressionVisitor = new TransformToExpressionVisitor(); - this.completeMeasurementSchemaVisitor = new CompleteMeasurementSchemaVisitor(); - this.hasProcessedLogicalView = false; - } - - public boolean isHasProcessedLogicalView() { - return this.hasProcessedLogicalView; - } - - private Expression transformViewPath(MeasurementPath measurementPath, ISchemaTree schemaTree) { - IMeasurementSchema measurementSchema = measurementPath.getMeasurementSchema(); - if (measurementSchema.isLogicalView()) { - ViewExpression viewExpression = ((LogicalViewSchema) measurementSchema).getExpression(); - // complete measurementPaths in expressions. - Expression expression = this.transformToExpressionVisitor.process(viewExpression, null); - expression = this.completeMeasurementSchemaVisitor.process(expression, schemaTree); - return expression; - } else { - throw new RuntimeException( - new UnsupportedOperationException( - "Can not construct expression using non view path in transformViewPath!")); - } - } - - @Override - public List<Expression> visitTimeSeriesOperand( - TimeSeriesOperand timeSeriesOperand, ISchemaTree schemaTree) { - PartialPath timeSeriesOperandPath = timeSeriesOperand.getPath(); - List<MeasurementPath> actualPaths = - schemaTree.searchMeasurementPaths(timeSeriesOperandPath).left; - // process logical view - List<MeasurementPath> nonViewActualPaths = new ArrayList<>(); - List<MeasurementPath> viewPaths = new ArrayList<>(); - for (MeasurementPath measurementPath : actualPaths) { - if (measurementPath.getMeasurementSchema().isLogicalView()) { - this.hasProcessedLogicalView = true; - viewPaths.add(measurementPath); - } else { - nonViewActualPaths.add(measurementPath); - } - } - List<Expression> reconstructTimeSeriesOperands = - ExpressionUtils.reconstructTimeSeriesOperands(nonViewActualPaths); - // handle logical views - for (MeasurementPath measurementPath : viewPaths) { - Expression replacedExpression = this.transformViewPath(measurementPath, schemaTree); - replacedExpression.setViewPathOfThisExpression(measurementPath); - reconstructTimeSeriesOperands.add(replacedExpression); - } - return reconstructTimeSeriesOperands; - } -} diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/CartesianProductVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/CartesianProductVisitor.java similarity index 94% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/CartesianProductVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/CartesianProductVisitor.java index 7d824b0e25d..6830b8cf2e8 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/CartesianProductVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/CartesianProductVisitor.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression; @@ -25,6 +25,7 @@ import org.apache.iotdb.db.mpp.plan.expression.leaf.NullOperand; import org.apache.iotdb.db.mpp.plan.expression.other.CaseWhenThenExpression; import org.apache.iotdb.db.mpp.plan.expression.ternary.TernaryExpression; import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression; +import org.apache.iotdb.db.mpp.plan.expression.visitor.ExpressionAnalyzeVisitor; import java.util.ArrayList; import java.util.Collections; @@ -52,7 +53,7 @@ public abstract class CartesianProductVisitor<C> public List<Expression> visitBinaryExpression(BinaryExpression binaryExpression, C context) { List<List<Expression>> childResultsList = getResultsFromChild(binaryExpression, context); return reconstructBinaryExpressions( - binaryExpression.getExpressionType(), childResultsList.get(0), childResultsList.get(1)); + binaryExpression, childResultsList.get(0), childResultsList.get(1)); } @Override diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatDeviceAndRemoveWildcardVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatDeviceAndRemoveWildcardVisitor.java similarity index 78% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatDeviceAndRemoveWildcardVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatDeviceAndRemoveWildcardVisitor.java index a9f1b50ad2b..92b0b73a51d 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatDeviceAndRemoveWildcardVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatDeviceAndRemoveWildcardVisitor.java @@ -17,11 +17,12 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree; +import org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; @@ -34,7 +35,7 @@ import java.util.List; import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.cartesianProduct; import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructFunctionExpressions; -import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructTimeSeriesOperands; +import static org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardInExpressionVisitor.transformViewPath; import static org.apache.iotdb.db.utils.TypeInferenceUtils.bindTypeForAggregationNonSeriesInputExpressions; public class ConcatDeviceAndRemoveWildcardVisitor @@ -77,8 +78,27 @@ public class ConcatDeviceAndRemoveWildcardVisitor if (actualPaths.isEmpty()) { return Collections.emptyList(); } - List<PartialPath> noStarPaths = new ArrayList<>(actualPaths); - return reconstructTimeSeriesOperands(noStarPaths); + + // process logical view + List<MeasurementPath> nonViewActualPaths = new ArrayList<>(); + List<MeasurementPath> viewPaths = new ArrayList<>(); + for (MeasurementPath measurementPath : actualPaths) { + if (measurementPath.getMeasurementSchema().isLogicalView()) { + // this.hasProcessedLogicalView = true; + viewPaths.add(measurementPath); + } else { + nonViewActualPaths.add(measurementPath); + } + } + List<Expression> reconstructTimeSeriesOperands = + ExpressionUtils.reconstructTimeSeriesOperands(nonViewActualPaths); + // handle logical views + for (MeasurementPath measurementPath : viewPaths) { + Expression replacedExpression = transformViewPath(measurementPath, context.getSchemaTree()); + replacedExpression.setViewPath(measurementPath); + reconstructTimeSeriesOperands.add(replacedExpression); + } + return reconstructTimeSeriesOperands; } @Override diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatExpressionWithSuffixPathsVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatExpressionWithSuffixPathsVisitor.java similarity index 98% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatExpressionWithSuffixPathsVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatExpressionWithSuffixPathsVisitor.java index a8e565e7dae..1bfdaebf1ac 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ConcatExpressionWithSuffixPathsVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/ConcatExpressionWithSuffixPathsVisitor.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.commons.path.PathPatternTree; diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInFilterVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardAndViewInFilterVisitor.java similarity index 95% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInFilterVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardAndViewInFilterVisitor.java index 550f5ac7299..f2b8efd31b2 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardAndViewInFilterVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardAndViewInFilterVisitor.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; @@ -28,6 +28,7 @@ import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.leaf.NullOperand; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; +import org.apache.iotdb.db.mpp.plan.expression.visitor.CompleteMeasurementSchemaVisitor; import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema; import java.util.ArrayList; @@ -51,10 +52,6 @@ public class RemoveWildcardAndViewInFilterVisitor extends RemoveWildcardInFilter this.hasProcessedLogicalView = false; } - public boolean isHasProcessedLogicalView() { - return this.hasProcessedLogicalView; - } - private Expression transformViewPath(MeasurementPath measurementPath, ISchemaTree schemaTree) { IMeasurementSchema measurementSchema = measurementPath.getMeasurementSchema(); if (measurementSchema.isLogicalView()) { @@ -101,7 +98,7 @@ public class RemoveWildcardAndViewInFilterVisitor extends RemoveWildcardInFilter for (MeasurementPath measurementPath : viewPathList) { Expression replacedExpression = this.transformViewPath(measurementPath, context.getSchemaTree()); - replacedExpression.setViewPathOfThisExpression(measurementPath); + replacedExpression.setViewPath(measurementPath); reconstructTimeSeriesOperands.add(replacedExpression); } return reconstructTimeSeriesOperands; diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInExpressionVisitor.java similarity index 63% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInExpressionVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInExpressionVisitor.java index 353c567bc84..52def910af5 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInExpressionVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInExpressionVisitor.java @@ -17,16 +17,21 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; +import org.apache.iotdb.commons.schema.view.LogicalViewSchema; +import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression; +import org.apache.iotdb.db.metadata.view.viewExpression.visitor.TransformToExpressionVisitor; import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree; import org.apache.iotdb.db.mpp.plan.expression.Expression; import org.apache.iotdb.db.mpp.plan.expression.leaf.ConstantOperand; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand; import org.apache.iotdb.db.mpp.plan.expression.leaf.TimestampOperand; import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression; +import org.apache.iotdb.db.mpp.plan.expression.visitor.CompleteMeasurementSchemaVisitor; +import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema; import java.util.ArrayList; import java.util.Collections; @@ -37,16 +42,18 @@ import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructFu import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructTimeSeriesOperands; import static org.apache.iotdb.db.utils.TypeInferenceUtils.bindTypeForAggregationNonSeriesInputExpressions; -public class RemoveWildcardInExpressionVisitor extends CartesianProductVisitor<ISchemaTree> { +public class RemoveWildcardInExpressionVisitor + extends CartesianProductVisitor<RemoveWildcardInExpressionVisitor.Context> { + @Override public List<Expression> visitFunctionExpression( - FunctionExpression functionExpression, ISchemaTree schemaTree) { + FunctionExpression functionExpression, Context context) { // One by one, remove the wildcards from the input expressions. In most cases, an expression // will produce multiple expressions after removing the wildcards. We use extendedExpressions // to collect the produced expressions. List<List<Expression>> extendedExpressions = new ArrayList<>(); for (Expression originExpression : functionExpression.getExpressions()) { - List<Expression> actualExpressions = process(originExpression, schemaTree); + List<Expression> actualExpressions = process(originExpression, context); if (actualExpressions.isEmpty()) { // Let's ignore the eval of the function which has at least one non-existence series as // input. See IOTDB-1212: https://github.com/apache/iotdb/pull/3101 @@ -61,9 +68,7 @@ public class RemoveWildcardInExpressionVisitor extends CartesianProductVisitor<I if (functionExpression.isBuiltInAggregationFunctionExpression()) { List<Expression> children = functionExpression.getExpressions(); bindTypeForAggregationNonSeriesInputExpressions( - ((FunctionExpression) functionExpression).getFunctionName(), - children, - extendedExpressions); + functionExpression.getFunctionName(), children, extendedExpressions); break; } } @@ -73,27 +78,53 @@ public class RemoveWildcardInExpressionVisitor extends CartesianProductVisitor<I List<List<Expression>> childExpressionsList = new ArrayList<>(); cartesianProduct(extendedExpressions, childExpressionsList, 0, new ArrayList<>()); - return reconstructFunctionExpressions( - (FunctionExpression) functionExpression, childExpressionsList); + return reconstructFunctionExpressions(functionExpression, childExpressionsList); } @Override public List<Expression> visitTimeSeriesOperand( - TimeSeriesOperand timeSeriesOperand, ISchemaTree schemaTree) { + TimeSeriesOperand timeSeriesOperand, Context context) { PartialPath path = timeSeriesOperand.getPath(); - List<MeasurementPath> actualPaths = schemaTree.searchMeasurementPaths(path).left; + List<MeasurementPath> actualPaths = context.getSchemaTree().searchMeasurementPaths(path).left; return reconstructTimeSeriesOperands(actualPaths); } @Override public List<Expression> visitTimeStampOperand( - TimestampOperand timestampOperand, ISchemaTree context) { + TimestampOperand timestampOperand, Context context) { return Collections.singletonList(timestampOperand); } @Override - public List<Expression> visitConstantOperand( - ConstantOperand constantOperand, ISchemaTree context) { + public List<Expression> visitConstantOperand(ConstantOperand constantOperand, Context context) { return Collections.singletonList(constantOperand); } + + public static Expression transformViewPath( + MeasurementPath measurementPath, ISchemaTree schemaTree) { + IMeasurementSchema measurementSchema = measurementPath.getMeasurementSchema(); + if (measurementSchema.isLogicalView()) { + ViewExpression viewExpression = ((LogicalViewSchema) measurementSchema).getExpression(); + // complete measurementPaths in expressions. + Expression expression = new TransformToExpressionVisitor().process(viewExpression, null); + expression = new CompleteMeasurementSchemaVisitor().process(expression, schemaTree); + return expression; + } else { + throw new RuntimeException( + new UnsupportedOperationException( + "Can not construct expression using non view path in transformViewPath!")); + } + } + + public static class Context { + private final ISchemaTree schemaTree; + + public Context(ISchemaTree schemaTree) { + this.schemaTree = schemaTree; + } + + public ISchemaTree getSchemaTree() { + return schemaTree; + } + } } diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterByDeviceVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterByDeviceVisitor.java similarity index 98% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterByDeviceVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterByDeviceVisitor.java index 4dfb8c1617a..0d3e7665a69 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterByDeviceVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterByDeviceVisitor.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterVisitor.java similarity index 84% rename from server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterVisitor.java rename to server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterVisitor.java index 5d7d3bdb31d..4e816d6b91d 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/RemoveWildcardInFilterVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/cartesian/RemoveWildcardInFilterVisitor.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.iotdb.db.mpp.plan.expression.visitor; +package org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian; import org.apache.iotdb.commons.path.MeasurementPath; import org.apache.iotdb.commons.path.PartialPath; @@ -40,6 +40,7 @@ import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.cartesianProd import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructBinaryExpressions; import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructFunctionExpressions; import static org.apache.iotdb.db.mpp.plan.analyze.ExpressionUtils.reconstructTimeSeriesOperands; +import static org.apache.iotdb.db.mpp.plan.expression.visitor.cartesian.RemoveWildcardInExpressionVisitor.transformViewPath; import static org.apache.iotdb.db.utils.TypeInferenceUtils.bindTypeForAggregationNonSeriesInputExpressions; public class RemoveWildcardInFilterVisitor @@ -56,8 +57,7 @@ public class RemoveWildcardInFilterVisitor resultExpressions.addAll(rightExpressions); return resultExpressions; } - return reconstructBinaryExpressions( - binaryExpression.getExpressionType(), leftExpressions, rightExpressions); + return reconstructBinaryExpressions(binaryExpression, leftExpressions, rightExpressions); } @Override @@ -96,16 +96,29 @@ public class RemoveWildcardInFilterVisitor concatPaths.add(filterPath); } - List<PartialPath> noStarPaths = new ArrayList<>(); + List<MeasurementPath> nonViewPathList = new ArrayList<>(); + List<MeasurementPath> viewPathList = new ArrayList<>(); for (PartialPath concatPath : concatPaths) { List<MeasurementPath> actualPaths = context.getSchemaTree().searchMeasurementPaths(concatPath).left; if (actualPaths.isEmpty()) { return Collections.singletonList(new NullOperand()); } - noStarPaths.addAll(actualPaths); + for (MeasurementPath measurementPath : actualPaths) { + if (measurementPath.getMeasurementSchema().isLogicalView()) { + viewPathList.add(measurementPath); + } else { + nonViewPathList.add(measurementPath); + } + } + } + List<Expression> reconstructTimeSeriesOperands = reconstructTimeSeriesOperands(nonViewPathList); + for (MeasurementPath measurementPath : viewPathList) { + Expression replacedExpression = transformViewPath(measurementPath, context.getSchemaTree()); + replacedExpression.setViewPath(measurementPath); + reconstructTimeSeriesOperands.add(replacedExpression); } - return reconstructTimeSeriesOperands(noStarPaths); + return reconstructTimeSeriesOperands; } @Override diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java index b191f3f2a1c..1aa9b38e7bc 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanBuilder.java @@ -537,6 +537,7 @@ public class LogicalPlanBuilder { Map<String, PlanNode> deviceNameToSourceNodesMap, Set<Expression> deviceViewOutputExpressions, Map<String, List<Integer>> deviceToMeasurementIndexesMap, + Map<String, List<String>> outputDeviceToQueryDeviceMap, Set<Expression> selectExpression, QueryStatement queryStatement) { List<String> outputColumnNames = @@ -582,7 +583,8 @@ public class LogicalPlanBuilder { context.getQueryId().genPlanNodeId(), orderByParameter, outputColumnNames, - deviceToMeasurementIndexesMap); + deviceToMeasurementIndexesMap, + outputDeviceToQueryDeviceMap); for (Map.Entry<String, PlanNode> entry : deviceNameToSourceNodesMap.entrySet()) { String deviceName = entry.getKey(); diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java index ed82734b768..37b8d9ea9ae 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanVisitor.java @@ -163,6 +163,7 @@ public class LogicalPlanVisitor extends StatementVisitor<PlanNode, MPPQueryConte deviceToSubPlanMap, analysis.getDeviceViewOutputExpressions(), analysis.getDeviceViewInputIndexesMap(), + analysis.getOutputDeviceToQueryDeviceMap(), analysis.getSelectExpressions(), queryStatement); } else { diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/distribution/SourceRewriter.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/distribution/SourceRewriter.java index 03cc0fba950..bd4eb70941d 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/distribution/SourceRewriter.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/distribution/SourceRewriter.java @@ -72,6 +72,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -165,31 +166,54 @@ public class SourceRewriter extends SimplePlanNodeRewriter<DistributionPlanConte List<DeviceViewSplit> deviceViewSplits = new ArrayList<>(); // Step 1: constructs DeviceViewSplit + Map<String, List<String>> outputDeviceToQueryDeviceMap = + analysis.getOutputDeviceToQueryDeviceMap(); for (int i = 0; i < node.getDevices().size(); i++) { - String device = node.getDevices().get(i); + String outputDevice = node.getDevices().get(i); PlanNode child = node.getChildren().get(i); - List<TRegionReplicaSet> regionReplicaSets = - analysis.getPartitionInfo(device, analysis.getGlobalTimeFilter()); - deviceViewSplits.add(new DeviceViewSplit(device, child, regionReplicaSets)); + List<TRegionReplicaSet> regionReplicaSets = new ArrayList<>(); + for (String queriedDevice : outputDeviceToQueryDeviceMap.get(outputDevice)) { + regionReplicaSets.addAll( + analysis.getPartitionInfo(queriedDevice, analysis.getGlobalTimeFilter())); + } + deviceViewSplits.add(new DeviceViewSplit(outputDevice, child, regionReplicaSets)); relatedDataRegions.addAll(regionReplicaSets); } // Step 2: Iterate all partition and create DeviceViewNode for each region List<PlanNode> deviceViewNodeList = new ArrayList<>(); - for (TRegionReplicaSet regionReplicaSet : relatedDataRegions) { - List<String> devices = new ArrayList<>(); - List<PlanNode> children = new ArrayList<>(); - for (DeviceViewSplit split : deviceViewSplits) { - if (split.needDistributeTo(regionReplicaSet)) { - devices.add(split.device); - children.add(split.buildPlanNodeInRegion(regionReplicaSet, context.queryContext)); - } + Iterator<DeviceViewSplit> deviceViewSplitIterator = deviceViewSplits.listIterator(); + while (deviceViewSplitIterator.hasNext()) { + DeviceViewSplit deviceViewSplit = deviceViewSplitIterator.next(); + String outputDevice = deviceViewSplit.device; + + if (outputDeviceToQueryDeviceMap.get(outputDevice).size() > 1) { + DeviceViewNode deviceViewNode = cloneDeviceViewNodeWithoutChild(node, context); + deviceViewNode.addChildDeviceNode( + outputDevice, process(deviceViewSplit.root, context).get(0)); + deviceViewNodeList.add(deviceViewNode); + deviceViewSplitIterator.remove(); } - DeviceViewNode regionDeviceViewNode = cloneDeviceViewNodeWithoutChild(node, context); - for (int i = 0; i < devices.size(); i++) { - regionDeviceViewNode.addChildDeviceNode(devices.get(i), children.get(i)); + } + + if (deviceViewSplits.size() > 0) { + for (TRegionReplicaSet regionReplicaSet : relatedDataRegions) { + List<String> devices = new ArrayList<>(); + List<PlanNode> children = new ArrayList<>(); + for (DeviceViewSplit split : deviceViewSplits) { + if (split.needDistributeTo(regionReplicaSet)) { + devices.add(split.device); + children.add(split.buildPlanNodeInRegion(regionReplicaSet, context.queryContext)); + } + } + DeviceViewNode regionDeviceViewNode = cloneDeviceViewNodeWithoutChild(node, context); + for (int i = 0; i < devices.size(); i++) { + regionDeviceViewNode.addChildDeviceNode(devices.get(i), children.get(i)); + } + if (regionDeviceViewNode.getChildren().size() > 0) { + deviceViewNodeList.add(regionDeviceViewNode); + } } - deviceViewNodeList.add(regionDeviceViewNode); } if (deviceViewNodeList.size() == 1) { @@ -229,7 +253,8 @@ public class SourceRewriter extends SimplePlanNodeRewriter<DistributionPlanConte context.queryContext.getQueryId().genPlanNodeId(), node.getMergeOrderParameter(), node.getOutputColumnNames(), - node.getDeviceToMeasurementIndexesMap()); + node.getDeviceToMeasurementIndexesMap(), + node.getOutputDeviceToQueryDeviceMap()); } private static class DeviceViewSplit {
