You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ca...@apache.org on 2023/11/13 03:46:01 UTC

(iotdb) 02/02: add template examination for TemplatedDeviceAnalyze

This is an automated email from the ASF dual-hosted git repository.

caogaofei pushed a commit to branch beyyes/multi_devices_fe
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit f25db9683c733c02435babd78459bf0f54828c90
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Mon Nov 13 11:40:17 2023 +0800

    add template examination for TemplatedDeviceAnalyze
---
 .../queryengine/plan/analyze/AnalyzeVisitor.java   | 31 ++++++++---
 .../plan/analyze/TemplatedDeviceAnalyze.java       | 62 ++++++++++++++++++++--
 2 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 6e9c298d3f9..70cd42448ba 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -266,12 +266,31 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
 
       List<Pair<Expression, String>> outputExpressions;
       if (queryStatement.isAlignByDevice()) {
+        // examine that if all devices are in same template
+        if (!queryStatement.isAggregationQuery() && !queryStatement.isSelectInto()) {
+          Template template = null;
+          List<PartialPath> devicePatternList = queryStatement.getFromComponent().getPrefixPaths();
+          for (PartialPath devicePath : devicePatternList) {
+            Map<Integer, Template> templateMap = schemaFetcher.checkAllRelatedTemplate(devicePath);
+            if (templateMap.size() == 1) {
+              if (template == null) {
+                template = templateMap.values().iterator().next();
+              } else {
+                if (templateMap.values().iterator().next().getId() != template.getId()) {
+                  template = null;
+                  break;
+                }
+              }
+            } else {
+              break;
+            }
+          }
 
-        // TODO examine that if all devices are in same template
-        if (!queryStatement.isAggregationQuery()) {
-          return new TemplatedDeviceAnalyze(
-                  analysis, queryStatement, context, schemaTree, partitionFetcher)
-              .visitQuery();
+          if (template != null) {
+            return new TemplatedDeviceAnalyze(
+                    analysis, queryStatement, context, schemaTree, partitionFetcher)
+                .visitQuery();
+          }
         }
 
         List<PartialPath> deviceList = analyzeFrom(queryStatement, schemaTree);
@@ -1813,7 +1832,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
     analysis.setGlobalTimeFilter(globalTimeFilter);
   }
 
-  private void analyzeFill(Analysis analysis, QueryStatement queryStatement) {
+  static void analyzeFill(Analysis analysis, QueryStatement queryStatement) {
     if (queryStatement.getFillComponent() == null) {
       return;
     }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedDeviceAnalyze.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedDeviceAnalyze.java
index 6cef714dc6d..a1c0b2cb637 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedDeviceAnalyze.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedDeviceAnalyze.java
@@ -35,6 +35,7 @@ import org.apache.iotdb.db.queryengine.plan.expression.Expression;
 import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
 import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
+import org.apache.iotdb.db.queryengine.plan.statement.component.SortItem;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.QueryStatement;
 import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager;
 import org.apache.iotdb.db.schemaengine.template.Template;
@@ -67,9 +68,11 @@ import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.END_TI
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.WHERE_WRONG_TYPE_ERROR_MSG;
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.analyzeDeviceViewSpecialProcess;
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.analyzeExpressionType;
+import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.analyzeFill;
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.analyzeOutput;
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.checkDeviceViewInputUniqueness;
 import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeVisitor.getTimePartitionSlotList;
+import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.concatDeviceAndBindSchemaForExpression;
 import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.getMeasurementExpression;
 import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.normalizeExpression;
 import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.searchAggregationExpressions;
@@ -133,7 +136,7 @@ public class TemplatedDeviceAnalyze {
     }
   }
 
-  /** 并行 最上层比如加sort fe 线程管理 */
+  /** add multi-threading impl */
   public Analysis visitQuery() {
 
     long startTime = System.currentTimeMillis();
@@ -165,7 +168,7 @@ public class TemplatedDeviceAnalyze {
     analysis.setDeviceList(deviceList);
 
     // analyzeDeviceToGroupBy(analysis, queryStatement, schemaTree, deviceList);
-    // analyzeDeviceToOrderBy(analysis, queryStatement, schemaTree, deviceList);
+    analyzeDeviceToOrderBy(analysis, queryStatement, schemaTree, deviceList);
     // analyzeHaving(analysis, queryStatement, schemaTree, deviceList);
     // analyzeDeviceToAggregation(analysis, queryStatement);
     analyzeDeviceToSourceTransform(analysis, queryStatement);
@@ -184,7 +187,7 @@ public class TemplatedDeviceAnalyze {
 
     // analyzeInto(analysis, queryStatement, deviceList, outputExpressions);
     // analyzeGroupByTime(analysis, queryStatement);
-    // analyzeFill(analysis, queryStatement);
+    analyzeFill(analysis, queryStatement);
 
     // generate result set header according to output expressions
     analyzeOutput(analysis, queryStatement, outputExpressions);
@@ -319,6 +322,59 @@ public class TemplatedDeviceAnalyze {
     return outputExpressions;
   }
 
+  private void analyzeDeviceToOrderBy(
+      Analysis analysis,
+      QueryStatement queryStatement,
+      ISchemaTree schemaTree,
+      List<PartialPath> deviceSet) {
+    if (!queryStatement.hasOrderByExpression()) {
+      return;
+    }
+
+    Map<String, Set<Expression>> deviceToOrderByExpressions = new LinkedHashMap<>();
+    Map<String, List<SortItem>> deviceToSortItems = new LinkedHashMap<>();
+    // build the device-view outputColumn for the sortNode above the deviceViewNode
+    Set<Expression> deviceViewOrderByExpression = new LinkedHashSet<>();
+    for (PartialPath device : deviceSet) {
+      Set<Expression> orderByExpressionsForOneDevice = new LinkedHashSet<>();
+      for (Expression expressionForItem : queryStatement.getExpressionSortItemList()) {
+        List<Expression> expressions =
+            concatDeviceAndBindSchemaForExpression(expressionForItem, device, schemaTree);
+        if (expressions.isEmpty()) {
+          throw new SemanticException(
+              String.format(
+                  "%s in order by clause doesn't exist.", expressionForItem.getExpressionString()));
+        }
+        if (expressions.size() > 1) {
+          throw new SemanticException(
+              String.format(
+                  "%s in order by clause shouldn't refer to more than one timeseries.",
+                  expressionForItem.getExpressionString()));
+        }
+        expressionForItem = expressions.get(0);
+        TSDataType dataType = analyzeExpressionType(analysis, expressionForItem);
+        if (!dataType.isComparable()) {
+          throw new SemanticException(
+              String.format("The data type of %s is not comparable", dataType));
+        }
+
+        Expression deviceViewExpression = getMeasurementExpression(expressionForItem, analysis);
+        analyzeExpressionType(analysis, deviceViewExpression);
+
+        deviceViewOrderByExpression.add(deviceViewExpression);
+        orderByExpressionsForOneDevice.add(expressionForItem);
+      }
+      deviceToSortItems.put(
+          device.getFullPath(), queryStatement.getUpdatedSortItems(orderByExpressionsForOneDevice));
+      deviceToOrderByExpressions.put(device.getFullPath(), orderByExpressionsForOneDevice);
+    }
+
+    analysis.setOrderByExpressions(deviceViewOrderByExpression);
+    queryStatement.updateSortItems(deviceViewOrderByExpression);
+    analysis.setDeviceToSortItems(deviceToSortItems);
+    analysis.setDeviceToOrderByExpressions(deviceToOrderByExpressions);
+  }
+
   private void analyzeDeviceToSourceTransform(Analysis analysis, QueryStatement queryStatement) {
     if (queryStatement.isAggregationQuery()) {
       Map<String, Set<Expression>> deviceToSourceTransformExpressions =