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/12/25 08:53:49 UTC

(iotdb) branch beyyes/template_value_filter updated: perfect template align by device impl

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

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


The following commit(s) were added to refs/heads/beyyes/template_value_filter by this push:
     new 8921e537f32 perfect template align by device impl
8921e537f32 is described below

commit 8921e537f328dc4cd6c762ec453a11e7f295766a
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Mon Dec 25 16:53:34 2023 +0800

    perfect template align by device impl
---
 .../db/queryengine/plan/analyze/Analysis.java      |  2 +-
 .../plan/analyze/ExpressionAnalyzer.java           |  2 +-
 .../queryengine/plan/analyze/TemplatedAnalyze.java |  4 +-
 .../db/queryengine/plan/analyze/TemplatedInfo.java | 54 +++++++++++------
 ...ncatDeviceAndBindSchemaForPredicateVisitor.java |  4 +-
 .../TemplatedConcatDeviceAndPredicateVisitor.java  | 67 ++++++++++++++++++++++
 .../plan/planner/LogicalPlanBuilder.java           |  3 +-
 .../plan/planner/OperatorTreeGenerator.java        | 12 +++-
 .../plan/planner/TemplatedLogicalPlan.java         | 30 ++++++----
 .../plan/planner/TemplatedLogicalPlanBuilder.java  | 20 +++++--
 .../plan/planner/plan/node/process/FilterNode.java | 25 ++++----
 .../plan/optimization/TestPlanBuilder.java         |  3 +-
 .../plan/plan/QueryLogicalPlanUtil.java            | 18 ++++--
 .../plan/node/process/FilterNodeSerdeTest.java     |  3 +-
 14 files changed, 189 insertions(+), 58 deletions(-)

diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analysis.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analysis.java
index cce4ab322d9..93220f20da1 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analysis.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/Analysis.java
@@ -282,7 +282,7 @@ public class Analysis {
   // when deviceTemplate is not empty and all expressions in this query are templated measurements,
   // i.e. no aggregation and arithmetic expression
   private boolean onlyQueryTemplateMeasurements = true;
-  // if it is wildcard query
+  // if it is wildcard query in templated align by device query
   private boolean templateWildCardQuery;
   // all queried measurementList and schemaList in deviceTemplate.
   private List<String> measurementList;
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/ExpressionAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/ExpressionAnalyzer.java
index 08e58bd4cbe..52707248033 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/ExpressionAnalyzer.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/ExpressionAnalyzer.java
@@ -43,6 +43,7 @@ import org.apache.iotdb.db.queryengine.plan.expression.unary.UnaryExpression;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.BindTypeForTimeSeriesOperandVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.CollectAggregationExpressionsVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.CollectSourceExpressionsVisitor;
+import org.apache.iotdb.db.queryengine.plan.expression.visitor.ConcatDeviceAndBindSchemaForPredicateVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.ExpressionNormalizeVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.GetMeasurementExpressionVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.LowercaseNormalizeVisitor;
@@ -50,7 +51,6 @@ import org.apache.iotdb.db.queryengine.plan.expression.visitor.ReplaceRawPathWit
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.BindSchemaForExpressionVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.BindSchemaForPredicateVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatDeviceAndBindSchemaForExpressionVisitor;
-import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatDeviceAndBindSchemaForPredicateVisitor;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatExpressionWithSuffixPathsVisitor;
 import org.apache.iotdb.db.queryengine.plan.statement.component.ResultColumn;
 import org.apache.iotdb.db.utils.constant.SqlConstant;
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedAnalyze.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedAnalyze.java
index 798e4cdc5fe..17f411e33f1 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedAnalyze.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedAnalyze.java
@@ -132,8 +132,8 @@ public class TemplatedAnalyze {
             }
           }
           if (queryStatement.getSelectComponent().getResultColumns().size() == 1
-              && !paginationController.hasCurOffset()
-              && !paginationController.hasCurLimit()) {
+              && queryStatement.getSeriesOffset() == 0
+              && queryStatement.getSeriesLimit() == 0) {
             analysis.setTemplateWildCardQuery();
           }
         } else if (expression instanceof TimeSeriesOperand) {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedInfo.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedInfo.java
index 60c8ea1cce7..b32e5b03d86 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedInfo.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/TemplatedInfo.java
@@ -31,8 +31,10 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -49,11 +51,13 @@ public class TemplatedInfo {
   private boolean queryAllSensors;
   private List<String> selectMeasurements;
   private List<Integer> deviceToMeasurementIndexes;
-  private long offsetValue;
+  private final long offsetValue;
   private long limitValue;
-  public Expression whereExpression;
-  public ZoneId zoneId;
-  public boolean keepNull;
+  // these variables below are use in value filter condition
+  private final Expression predicate;
+  private final ZoneId zoneId;
+  private boolean keepNull;
+  private Map<String, IMeasurementSchema> schemaMap;
 
   public TemplatedInfo(
       List<String> measurementList,
@@ -66,8 +70,9 @@ public class TemplatedInfo {
       List<Integer> deviceToMeasurementIndexes,
       long offsetValue,
       long limitValue,
-      Expression whereExpression,
-      ZoneId zoneId) {
+      Expression predicate,
+      ZoneId zoneId,
+      Map<String, IMeasurementSchema> schemaMap) {
     this.measurementList = measurementList;
     this.schemaList = schemaList;
     this.dataTypes = dataTypes;
@@ -78,8 +83,9 @@ public class TemplatedInfo {
     this.deviceToMeasurementIndexes = deviceToMeasurementIndexes;
     this.offsetValue = offsetValue;
     this.limitValue = limitValue;
-    this.whereExpression = whereExpression;
+    this.predicate = predicate;
     this.zoneId = zoneId;
+    this.schemaMap = schemaMap;
   }
 
   public void setMeasurementList(List<String> measurementList) {
@@ -158,12 +164,20 @@ public class TemplatedInfo {
     return this.deviceToMeasurementIndexes;
   }
 
-  public static class FilterInfo {
-    private Expression predicate;
-    boolean keepNull;
-    ZoneId zoneId;
+  public Expression getPredicate() {
+    return this.predicate;
+  }
+
+  public ZoneId getZoneId() {
+    return this.zoneId;
+  }
+
+  public boolean isKeepNull() {
+    return this.keepNull;
+  }
 
-    public FilterInfo(Expression predicate) {}
+  public Map<String, IMeasurementSchema> getSchemaMap() {
+    return this.schemaMap;
   }
 
   public void serialize(ByteBuffer byteBuffer) {
@@ -197,9 +211,9 @@ public class TemplatedInfo {
     ReadWriteIOUtils.write(offsetValue, byteBuffer);
     ReadWriteIOUtils.write(limitValue, byteBuffer);
 
-    if (whereExpression != null) {
+    if (predicate != null) {
       ReadWriteIOUtils.write((byte) 1, byteBuffer);
-      Expression.serialize(whereExpression, byteBuffer);
+      Expression.serialize(predicate, byteBuffer);
       ReadWriteIOUtils.write(zoneId.getId(), byteBuffer);
     } else {
       ReadWriteIOUtils.write((byte) 0, byteBuffer);
@@ -237,9 +251,9 @@ public class TemplatedInfo {
     ReadWriteIOUtils.write(offsetValue, stream);
     ReadWriteIOUtils.write(limitValue, stream);
 
-    if (whereExpression != null) {
+    if (predicate != null) {
       ReadWriteIOUtils.write((byte) 1, stream);
-      Expression.serialize(whereExpression, stream);
+      Expression.serialize(predicate, stream);
       ReadWriteIOUtils.write(zoneId.getId(), stream);
     } else {
       ReadWriteIOUtils.write((byte) 0, stream);
@@ -297,9 +311,14 @@ public class TemplatedInfo {
     Expression predicate = null;
     ZoneId zone = null;
     byte hasFilter = ReadWriteIOUtils.readByte(byteBuffer);
+    Map<String, IMeasurementSchema> currentSchemaMap = null;
     if (hasFilter == 1) {
       predicate = Expression.deserialize(byteBuffer);
       zone = ZoneId.of(Objects.requireNonNull(ReadWriteIOUtils.readString(byteBuffer)));
+      currentSchemaMap = new HashMap<>();
+      for (IMeasurementSchema measurementSchema : measurementSchemaList) {
+        currentSchemaMap.put(measurementSchema.getMeasurementId(), measurementSchema);
+      }
     }
 
     return new TemplatedInfo(
@@ -314,6 +333,7 @@ public class TemplatedInfo {
         offsetValue,
         limitValue,
         predicate,
-        zone);
+        zone,
+        currentSchemaMap);
   }
 }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/cartesian/ConcatDeviceAndBindSchemaForPredicateVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/ConcatDeviceAndBindSchemaForPredicateVisitor.java
similarity index 96%
rename from iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/cartesian/ConcatDeviceAndBindSchemaForPredicateVisitor.java
rename to iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/ConcatDeviceAndBindSchemaForPredicateVisitor.java
index 722938fef6f..d6d1f53212a 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/cartesian/ConcatDeviceAndBindSchemaForPredicateVisitor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/ConcatDeviceAndBindSchemaForPredicateVisitor.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian;
+package org.apache.iotdb.db.queryengine.plan.expression.visitor;
 
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
@@ -29,6 +29,7 @@ import org.apache.iotdb.db.queryengine.plan.expression.leaf.NullOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimestampOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
+import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.CartesianProductVisitor;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,6 +42,7 @@ import static org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.
 
 public class ConcatDeviceAndBindSchemaForPredicateVisitor
     extends CartesianProductVisitor<ConcatDeviceAndBindSchemaForPredicateVisitor.Context> {
+
   @Override
   public List<Expression> visitFunctionExpression(FunctionExpression predicate, Context context) {
     if (predicate.isBuiltInAggregationFunctionExpression() && context.isWhere()) {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/TemplatedConcatDeviceAndPredicateVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/TemplatedConcatDeviceAndPredicateVisitor.java
new file mode 100644
index 00000000000..8e9ca1a2795
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/expression/visitor/TemplatedConcatDeviceAndPredicateVisitor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.queryengine.plan.expression.visitor;
+
+import org.apache.iotdb.commons.path.MeasurementPath;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.queryengine.plan.expression.Expression;
+import org.apache.iotdb.db.queryengine.plan.expression.leaf.NullOperand;
+import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+
+import java.util.Map;
+
+public class TemplatedConcatDeviceAndPredicateVisitor
+    extends ReconstructVisitor<TemplatedConcatDeviceAndPredicateVisitor.Context> {
+
+  @Override
+  public Expression visitTimeSeriesOperand(
+      TimeSeriesOperand predicate, TemplatedConcatDeviceAndPredicateVisitor.Context context) {
+    PartialPath measurementPath = predicate.getPath();
+    PartialPath concatPath = context.getDevicePath().concatPath(measurementPath);
+    IMeasurementSchema schema = null;
+    if (context.getSchemaMap().containsKey(measurementPath.getMeasurement())) {
+      schema = context.getSchemaMap().get(measurementPath.getMeasurement());
+      MeasurementPath fullMeasurementPath = new MeasurementPath(concatPath, schema);
+      return new TimeSeriesOperand(fullMeasurementPath);
+    } else {
+      return new NullOperand();
+    }
+  }
+
+  public static class Context {
+    private final PartialPath devicePath;
+
+    private final Map<String, IMeasurementSchema> schemaMap;
+
+    public Context(PartialPath devicePath, Map<String, IMeasurementSchema> schemaMap) {
+      this.devicePath = devicePath;
+      this.schemaMap = schemaMap;
+    }
+
+    public PartialPath getDevicePath() {
+      return devicePath;
+    }
+
+    public Map<String, IMeasurementSchema> getSchemaMap() {
+      return this.schemaMap;
+    }
+  }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
index 047fab98504..453cd8869dd 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LogicalPlanBuilder.java
@@ -1142,7 +1142,8 @@ public class LogicalPlanBuilder {
             filterExpression,
             isGroupByTime,
             zoneId,
-            scanOrder);
+            scanOrder,
+            null);
     updateTypeProvider(selectExpressions);
     return this;
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
index e184bf8ff18..64e0e097e09 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/OperatorTreeGenerator.java
@@ -145,6 +145,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.leaf.TimestampOperand;
 import org.apache.iotdb.db.queryengine.plan.expression.visitor.ColumnTransformerVisitor;
+import org.apache.iotdb.db.queryengine.plan.expression.visitor.TemplatedConcatDeviceAndPredicateVisitor;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metedata.read.CountSchemaMergeNode;
@@ -1162,7 +1163,16 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
 
   @Override
   public Operator visitFilter(FilterNode node, LocalExecutionPlanContext context) {
-    final Expression filterExpression = node.getPredicate();
+    Expression filterExpression = node.getPredicate();
+    if (node.getDevicePathNodes() != null) {
+      PartialPath devicePath = new PartialPath(node.getDevicePathNodes());
+      filterExpression =
+          new TemplatedConcatDeviceAndPredicateVisitor()
+              .process(
+                  filterExpression,
+                  new TemplatedConcatDeviceAndPredicateVisitor.Context(
+                      devicePath, context.getTypeProvider().getTemplatedInfo().getSchemaMap()));
+    }
     final Map<NodeRef<Expression>, TSDataType> expressionTypes = new HashMap<>();
     ExpressionTypeAnalyzer.analyzeExpression(expressionTypes, filterExpression);
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlan.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlan.java
index d62a3b25b15..d637f8e70ea 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlan.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlan.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.db.queryengine.plan.planner;
 
+import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.plan.analyze.Analysis;
@@ -138,6 +139,9 @@ public class TemplatedLogicalPlan {
       for (Expression expression : whereSourceExpressions) {
         if (expression instanceof TimeSeriesOperand) {
           String measurement = ((TimeSeriesOperand) expression).getPath().getMeasurement();
+          if (!analysis.getDeviceTemplate().getSchemaMap().containsKey(measurement)) {
+            continue;
+          }
           if (!selectExpressions.contains(measurement)) {
             selectExpressions.add(measurement);
             mergedMeasurementList.add(measurement);
@@ -159,17 +163,22 @@ public class TemplatedLogicalPlan {
             analysis.isLastLevelUseWildcard());
 
     if (whereExpression != null) {
-      //      Expression[] outputExpressions = new Expression[measurementList.size()];
-      //      for (int i = 0; i < analysis.getMeasurementList().size(); i++) {
-      //        outputExpressions[i] =
-      //            new TimeSeriesOperand(
-      //                new MeasurementPath(
-      //                    devicePath.concatNode(measurementList.get(i)).getNodes(),
-      // schemaList.get(i)));
-      //      }
+      Expression[] outputExpressions = new Expression[measurementList.size()];
+      for (int i = 0; i < analysis.getMeasurementList().size(); i++) {
+        outputExpressions[i] =
+            new TimeSeriesOperand(
+                new MeasurementPath(
+                    devicePath.concatNode(measurementList.get(i)).getNodes(), schemaList.get(i)));
+      }
 
       planBuilder =
-          planBuilder.planFilter(devicePath, whereExpression, queryStatement.isGroupByTime());
+          planBuilder.planFilter(
+              devicePath,
+              whereExpression,
+              outputExpressions,
+              queryStatement.isGroupByTime(),
+              queryStatement.getSelectComponent().getZoneId(),
+              queryStatement.getResultTimeOrder());
     }
 
     if (context.getTypeProvider().getTemplatedInfo() == null) {
@@ -192,7 +201,8 @@ public class TemplatedLogicalPlan {
                   0,
                   limitValue,
                   whereExpression,
-                  queryStatement.getSelectComponent().getZoneId()));
+                  queryStatement.getSelectComponent().getZoneId(),
+                  analysis.getDeviceTemplate().getSchemaMap()));
     }
 
     return planBuilder.getRoot();
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlanBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlanBuilder.java
index 46ea96a53f5..21ab46dccdd 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlanBuilder.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TemplatedLogicalPlanBuilder.java
@@ -32,6 +32,7 @@ import org.apache.iotdb.db.queryengine.plan.planner.plan.node.source.SeriesScanN
 import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
 import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
 
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -107,16 +108,27 @@ public class TemplatedLogicalPlanBuilder extends LogicalPlanBuilder {
   }
 
   public TemplatedLogicalPlanBuilder planFilter(
-      PartialPath devicePath, Expression filterExpression, boolean isGroupByTime) {
+      PartialPath devicePath,
+      Expression filterExpression,
+      Expression[] outputExpressions,
+      boolean isGroupByTime,
+      ZoneId zoneId,
+      Ordering scanOrder) {
 
     if (filterExpression == null) {
       return this;
     }
 
     this.root =
-        new FilterNode(context.getQueryId().genPlanNodeId(), this.getRoot(), devicePath.getNodes());
-
-    // updateTypeProvider(Collections.singletonList(filterExpression));
+        new FilterNode(
+            context.getQueryId().genPlanNodeId(),
+            this.getRoot(),
+            outputExpressions,
+            filterExpression,
+            isGroupByTime,
+            zoneId,
+            scanOrder,
+            devicePath.getNodes());
 
     return this;
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/FilterNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/FilterNode.java
index c2f9ab20a86..c53c64c4731 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/FilterNode.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/process/FilterNode.java
@@ -41,15 +41,9 @@ import java.util.Objects;
 public class FilterNode extends TransformNode {
 
   private final Expression predicate;
-  // this variable is only use in TemplatedLogicalPlan process.
-  private String[] devicePathNodes;
 
-  /** This construction method are only used in TemplatedLogicalPlan. */
-  public FilterNode(PlanNodeId id, PlanNode childPlanNode, String[] devicePathNodes) {
-    super(id, childPlanNode, null, false, null, null);
-    this.predicate = null;
-    this.devicePathNodes = devicePathNodes;
-  }
+  // this variable is only use in TemplatedLogicalPlan process.
+  private final String[] devicePathNodes;
 
   public FilterNode(
       PlanNodeId id,
@@ -58,11 +52,14 @@ public class FilterNode extends TransformNode {
       Expression predicate,
       boolean keepNull,
       ZoneId zoneId,
-      Ordering scanOrder) {
+      Ordering scanOrder,
+      String[] devicePathNodes) {
     super(id, childPlanNode, outputExpressions, keepNull, zoneId, scanOrder);
     this.predicate = predicate;
+    this.devicePathNodes = devicePathNodes;
   }
 
+  /** This construction method is only used in inner of class `FilterNode`. */
   public FilterNode(
       PlanNodeId id,
       Expression[] outputExpressions,
@@ -171,9 +168,9 @@ public class FilterNode extends TransformNode {
     return new FilterNode(
         planNodeId,
         outputExpressions,
-        typeProvider.getTemplatedInfo().whereExpression,
-        typeProvider.getTemplatedInfo().keepNull,
-        typeProvider.getTemplatedInfo().zoneId,
+        typeProvider.getTemplatedInfo().getPredicate(),
+        typeProvider.getTemplatedInfo().isKeepNull(),
+        typeProvider.getTemplatedInfo().getZoneId(),
         typeProvider.getTemplatedInfo().getScanOrder(),
         devicePathNodes);
   }
@@ -182,6 +179,10 @@ public class FilterNode extends TransformNode {
     return predicate;
   }
 
+  public String[] getDevicePathNodes() {
+    return this.devicePathNodes;
+  }
+
   @Override
   public String toString() {
     return "FilterNode-" + this.getPlanNodeId();
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
index c3684bc9140..f0ee1ad9ff9 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/optimization/TestPlanBuilder.java
@@ -286,7 +286,8 @@ public class TestPlanBuilder {
             predicate,
             isGroupByTime,
             ZonedDateTime.now().getOffset(),
-            Ordering.ASC);
+            Ordering.ASC,
+            null);
     return this;
   }
 
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/QueryLogicalPlanUtil.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/QueryLogicalPlanUtil.java
index 9aaef681fe2..7e024516a45 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/QueryLogicalPlanUtil.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/QueryLogicalPlanUtil.java
@@ -232,7 +232,8 @@ public class QueryLogicalPlanUtil {
             predicate,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     OffsetNode offsetNode = new OffsetNode(queryId.genPlanNodeId(), filterNode, 100);
     LimitNode limitNode = new LimitNode(queryId.genPlanNodeId(), offsetNode, 100);
@@ -285,7 +286,8 @@ public class QueryLogicalPlanUtil {
             predicate1,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     List<PlanNode> sourceNodeList2 = new ArrayList<>();
     sourceNodeList2.add(
@@ -324,7 +326,8 @@ public class QueryLogicalPlanUtil {
             predicate2,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     Map<String, List<Integer>> deviceToMeasurementIndexesMap = new HashMap<>();
     deviceToMeasurementIndexesMap.put("root.sg.d1", Arrays.asList(1, 2, 3));
@@ -790,7 +793,8 @@ public class QueryLogicalPlanUtil {
             predicate,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     AggregationNode aggregationNode =
         new AggregationNode(
@@ -910,7 +914,8 @@ public class QueryLogicalPlanUtil {
             predicate1,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     AggregationNode aggregationNode1 =
         new AggregationNode(
@@ -966,7 +971,8 @@ public class QueryLogicalPlanUtil {
             predicate2,
             false,
             ZonedDateTime.now().getOffset(),
-            Ordering.DESC);
+            Ordering.DESC,
+            null);
 
     AggregationNode aggregationNode2 =
         new AggregationNode(
diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FilterNodeSerdeTest.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FilterNodeSerdeTest.java
index 89cb7822a8a..6fb31f0bc24 100644
--- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FilterNodeSerdeTest.java
+++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/plan/node/process/FilterNodeSerdeTest.java
@@ -53,7 +53,8 @@ public class FilterNodeSerdeTest {
                 new ConstantOperand(TSDataType.INT64, "100")),
             false,
             ZoneId.systemDefault(),
-            Ordering.ASC);
+            Ordering.ASC,
+            null);
 
     ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
     filterNode.serialize(byteBuffer);