You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2022/08/03 08:29:09 UTC

[iotdb] branch master updated: [IOTDB-4024] Implement ColumnTransformerVisitor for Expression (#6872)

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

jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new bcc8913814 [IOTDB-4024] Implement ColumnTransformerVisitor for Expression (#6872)
bcc8913814 is described below

commit bcc8913814d5781111201ac41a6b7494c0d15276
Author: Liao Lanyu <10...@users.noreply.github.com>
AuthorDate: Wed Aug 3 16:29:04 2022 +0800

    [IOTDB-4024] Implement ColumnTransformerVisitor for Expression (#6872)
---
 .../iotdb/db/mpp/plan/expression/Expression.java   | 144 +++----
 .../plan/expression/binary/AdditionExpression.java |  12 -
 .../plan/expression/binary/BinaryExpression.java   |  74 +---
 .../plan/expression/binary/DivisionExpression.java |  12 -
 .../plan/expression/binary/EqualToExpression.java  |  11 -
 .../expression/binary/GreaterEqualExpression.java  |  12 -
 .../expression/binary/GreaterThanExpression.java   |  12 -
 .../expression/binary/LessEqualExpression.java     |  12 -
 .../plan/expression/binary/LessThanExpression.java |  12 -
 .../plan/expression/binary/LogicAndExpression.java |  11 -
 .../plan/expression/binary/LogicOrExpression.java  |  11 -
 .../plan/expression/binary/ModuloExpression.java   |  12 -
 .../binary/MultiplicationExpression.java           |  12 -
 .../plan/expression/binary/NonEqualExpression.java |  12 -
 .../expression/binary/SubtractionExpression.java   |  12 -
 .../mpp/plan/expression/leaf/ConstantOperand.java  |  37 +-
 .../plan/expression/leaf/TimeSeriesOperand.java    |  36 +-
 .../mpp/plan/expression/leaf/TimestampOperand.java |  35 +-
 .../plan/expression/multi/FunctionExpression.java  |  93 +---
 .../plan/expression/ternary/BetweenExpression.java |  18 -
 .../plan/expression/ternary/TernaryExpression.java |  91 +---
 .../db/mpp/plan/expression/unary/InExpression.java |   9 -
 .../plan/expression/unary/IsNullExpression.java    |   9 -
 .../mpp/plan/expression/unary/LikeExpression.java  |   9 -
 .../plan/expression/unary/LogicNotExpression.java  |   9 -
 .../plan/expression/unary/NegationExpression.java  |   9 -
 .../plan/expression/unary/RegularExpression.java   |   9 -
 .../mpp/plan/expression/unary/UnaryExpression.java |  61 +--
 .../visitor/ColumnTransformerVisitor.java          | 478 +++++++++++++++++++++
 .../plan/expression/visitor/ExpressionVisitor.java |  73 ++++
 .../db/mpp/plan/planner/OperatorTreeGenerator.java |  33 +-
 31 files changed, 686 insertions(+), 694 deletions(-)

diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/Expression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/Expression.java
index df6ab6cd18..3436370342 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/Expression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/Expression.java
@@ -48,9 +48,8 @@ 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.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.memory.LayerMemoryAssigner;
@@ -75,10 +74,24 @@ import java.util.Set;
 /** A skeleton class for expression */
 public abstract class Expression {
 
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // Operations that Class Expression is not responsible for should be done through a visitor ////
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Accessible for {@link ExpressionVisitor}, use {@link ExpressionVisitor#process(Expression)}
+   * instead.
+   */
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitExpression(this, context);
+  }
+
   /////////////////////////////////////////////////////////////////////////////////////////////////
   // Expression type inferring for execution plan generation //////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////////////////////////////
 
+  public abstract ExpressionType getExpressionType();
+
   public boolean isBuiltInAggregationFunctionExpression() {
     return false;
   }
@@ -95,6 +108,25 @@ public abstract class Expression {
     return false;
   }
 
+  public abstract boolean isMappable(TypeProvider typeProvider);
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // isConstantOperand
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  protected Boolean isConstantOperandCache = null;
+
+  /** If this expression and all of its sub-expressions are {@link ConstantOperand}. */
+  public final boolean isConstantOperand() {
+    if (isConstantOperandCache == null) {
+      isConstantOperandCache = isConstantOperandInternal();
+    }
+    return isConstantOperandCache;
+  }
+
+  /** Sub-classes should override this method indicating if the expression is a constant operand */
+  protected abstract boolean isConstantOperandInternal();
+
   /////////////////////////////////////////////////////////////////////////////////////////////////
   // Operations for time series paths
   /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -174,36 +206,6 @@ public abstract class Expression {
       LayerMemoryAssigner memoryAssigner)
       throws QueryProcessException, IOException;
 
-  public abstract boolean isMappable(TypeProvider typeProvider);
-
-  public abstract ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize);
-
-  /////////////////////////////////////////////////////////////////////////////////////////////////
-  // isConstantOperand
-  /////////////////////////////////////////////////////////////////////////////////////////////////
-
-  protected Boolean isConstantOperandCache = null;
-
-  /** If this expression and all of its sub-expressions are {@link ConstantOperand}. */
-  public final boolean isConstantOperand() {
-    if (isConstantOperandCache == null) {
-      isConstantOperandCache = isConstantOperandInternal();
-    }
-    return isConstantOperandCache;
-  }
-
-  /** Sub-classes should override this method indicating if the expression is a constant operand */
-  protected abstract boolean isConstantOperandInternal();
-
   /////////////////////////////////////////////////////////////////////////////////////////////////
   // toString
   /////////////////////////////////////////////////////////////////////////////////////////////////
@@ -259,44 +261,6 @@ public abstract class Expression {
     return getExpressionString().equals(((Expression) o).getExpressionString());
   }
 
-  /////////////////////////////////////////////////////////////////////////////////////////////////
-  // iterator: level-order traversal iterator
-  /////////////////////////////////////////////////////////////////////////////////////////////////
-
-  /** returns an iterator to traverse all the successor expressions in a level-order */
-  public final Iterator<Expression> iterator() {
-    return new ExpressionIterator(this);
-  }
-
-  /** the iterator of an Expression tree with level-order traversal */
-  private static class ExpressionIterator implements Iterator<Expression> {
-
-    private final Deque<Expression> queue = new LinkedList<>();
-
-    public ExpressionIterator(Expression expression) {
-      queue.add(expression);
-    }
-
-    @Override
-    public boolean hasNext() {
-      return !queue.isEmpty();
-    }
-
-    @Override
-    public Expression next() {
-      if (!hasNext()) {
-        return null;
-      }
-      Expression current = queue.pop();
-      if (current != null) {
-        for (Expression subExp : current.getExpressions()) {
-          queue.push(subExp);
-        }
-      }
-      return current;
-    }
-  }
-
   /**
    * returns the DIRECT children expressions if it has any, otherwise an EMPTY list will be returned
    */
@@ -429,9 +393,45 @@ public abstract class Expression {
     return expression;
   }
 
-  public abstract ExpressionType getExpressionType();
-
   protected abstract void serialize(ByteBuffer byteBuffer);
 
   protected abstract void serialize(DataOutputStream stream) throws IOException;
+
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+  // iterator: level-order traversal iterator
+  /////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /** returns an iterator to traverse all the successor expressions in a level-order */
+  public final Iterator<Expression> iterator() {
+    return new ExpressionIterator(this);
+  }
+
+  /** the iterator of an Expression tree with level-order traversal */
+  private static class ExpressionIterator implements Iterator<Expression> {
+
+    private final Deque<Expression> queue = new LinkedList<>();
+
+    public ExpressionIterator(Expression expression) {
+      queue.add(expression);
+    }
+
+    @Override
+    public boolean hasNext() {
+      return !queue.isEmpty();
+    }
+
+    @Override
+    public Expression next() {
+      if (!hasNext()) {
+        return null;
+      }
+      Expression current = queue.pop();
+      if (current != null) {
+        for (Expression subExp : current.getExpressions()) {
+          queue.push(subExp);
+        }
+      }
+      return current;
+    }
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/AdditionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/AdditionExpression.java
index 9aaaed7778..d4c80fe955 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/AdditionExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/AdditionExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticAdditionColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticAdditionTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticBinaryTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -40,15 +37,6 @@ public class AdditionExpression extends ArithmeticBinaryExpression {
     super(byteBuffer);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new ArithmeticAdditionColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected ArithmeticBinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/BinaryExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/BinaryExpression.java
index 3ba78df364..8e1ce8d452 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/BinaryExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/BinaryExpression.java
@@ -24,11 +24,9 @@ import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.SingleInputColumnMultiReferenceIntermediateLayer;
@@ -40,8 +38,6 @@ import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
 import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFExecutor;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -68,6 +64,11 @@ public abstract class BinaryExpression extends Expression {
     this.rightExpression = Expression.deserialize(byteBuffer);
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitBinaryExpression(this, context);
+  }
+
   public Expression getLeftExpression() {
     return leftExpression;
   }
@@ -326,69 +327,6 @@ public abstract class BinaryExpression extends Expression {
     return leftExpression.isMappable(typeProvider) && rightExpression.isMappable(typeProvider);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    if (!cache.containsKey(this)) {
-      if (hasSeen.containsKey(this)) {
-        IdentityColumnTransformer identity =
-            new IdentityColumnTransformer(
-                TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                originSize + commonTransformerList.size());
-        ColumnTransformer columnTransformer = hasSeen.get(this);
-        columnTransformer.addReferenceCount();
-        commonTransformerList.add(columnTransformer);
-        leafList.add(identity);
-        inputDataTypes.add(typeProvider.getType(getExpressionString()));
-        cache.put(this, identity);
-      } else {
-        ColumnTransformer leftColumnTransformer =
-            leftExpression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-        ColumnTransformer rightColumnTransformer =
-            rightExpression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-        cache.put(
-            this,
-            getConcreteBinaryColumnTransformer(
-                leftColumnTransformer,
-                rightColumnTransformer,
-                TypeFactory.getType(typeProvider.getType(getExpressionString()))));
-      }
-    }
-
-    ColumnTransformer res = cache.get(this);
-    res.addReferenceCount();
-    return res;
-  }
-
-  protected abstract ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer, ColumnTransformer rightColumnTransformer, Type type);
-
   protected abstract BinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader);
 
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/DivisionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/DivisionExpression.java
index 3de8f65909..26ecfdb071 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/DivisionExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/DivisionExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticDivisionColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticDivisionTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -40,15 +37,6 @@ public class DivisionExpression extends ArithmeticBinaryExpression {
     super(byteBuffer);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new ArithmeticDivisionColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected ArithmeticBinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/EqualToExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/EqualToExpression.java
index 8afacb03da..a9a683ce87 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/EqualToExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/EqualToExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareEqualToColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareEqualToTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,14 +43,6 @@ public class EqualToExpression extends CompareBinaryExpression {
     return new CompareEqualToTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareEqualToColumnTransformer(type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "=";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterEqualExpression.java
index 2b5a57e3f3..d87a42046f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterEqualExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterEqualExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareGreaterEqualColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareGreaterEqualTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -47,15 +44,6 @@ public class GreaterEqualExpression extends CompareBinaryExpression {
         leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareGreaterEqualColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return ">=";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterThanExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterThanExpression.java
index 0406279b11..848557695c 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterThanExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/GreaterThanExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareGreaterThanColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareGreaterThanTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -47,15 +44,6 @@ public class GreaterThanExpression extends CompareBinaryExpression {
         leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareGreaterThanColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return ">";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessEqualExpression.java
index 53bec2b992..36c9e12294 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessEqualExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessEqualExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareLessEqualColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareLessEqualTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,15 +43,6 @@ public class LessEqualExpression extends CompareBinaryExpression {
     return new CompareLessEqualTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareLessEqualColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "<=";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessThanExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessThanExpression.java
index aedc252bda..630b7a4edc 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessThanExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LessThanExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareLessThanColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareLessThanTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,15 +43,6 @@ public class LessThanExpression extends CompareBinaryExpression {
     return new CompareLessThanTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareLessThanColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "<";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicAndExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicAndExpression.java
index b55491776d..68addddc49 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicAndExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicAndExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.LogicAndColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.LogicAndTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.LogicBinaryTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,14 +43,6 @@ public class LogicAndExpression extends LogicBinaryExpression {
     return new LogicAndTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new LogicAndColumnTransformer(type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "&";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicOrExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicOrExpression.java
index 8c091e5287..785263b210 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicOrExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/LogicOrExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.LogicOrColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.LogicBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.LogicOrTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,14 +43,6 @@ public class LogicOrExpression extends LogicBinaryExpression {
     return new LogicOrTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new LogicOrColumnTransformer(type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "|";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/ModuloExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/ModuloExpression.java
index b2faae3b75..24f7ab6b40 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/ModuloExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/ModuloExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticModuloColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticModuloTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -40,15 +37,6 @@ public class ModuloExpression extends ArithmeticBinaryExpression {
     super(byteBuffer);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new ArithmeticModuloColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected ArithmeticBinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/MultiplicationExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/MultiplicationExpression.java
index d1aa27e093..adc381612d 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/MultiplicationExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/MultiplicationExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticMultiplicationColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticMultiplicationTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -40,15 +37,6 @@ public class MultiplicationExpression extends ArithmeticBinaryExpression {
     super(byteBuffer);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new ArithmeticMultiplicationColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected ArithmeticBinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/NonEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/NonEqualExpression.java
index 396cd1c0fe..2a25f392f2 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/NonEqualExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/NonEqualExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareNonEqualColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.CompareNonEqualTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -46,15 +43,6 @@ public class NonEqualExpression extends CompareBinaryExpression {
     return new CompareNonEqualTransformer(leftParentLayerPointReader, rightParentLayerPointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new CompareNonEqualColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected String operator() {
     return "!=";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/SubtractionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/SubtractionExpression.java
index b9bfe65c17..946179f782 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/SubtractionExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/binary/SubtractionExpression.java
@@ -22,11 +22,8 @@ package org.apache.iotdb.db.mpp.plan.expression.binary;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticSubtractionColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticBinaryTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.binary.ArithmeticSubtractionTransformer;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -40,15 +37,6 @@ public class SubtractionExpression extends ArithmeticBinaryExpression {
     super(byteBuffer);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteBinaryColumnTransformer(
-      ColumnTransformer leftColumnTransformer,
-      ColumnTransformer rightColumnTransformer,
-      Type type) {
-    return new ArithmeticSubtractionColumnTransformer(
-        type, leftColumnTransformer, rightColumnTransformer);
-  }
-
   @Override
   protected ArithmeticBinaryTransformer constructTransformer(
       LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/ConstantOperand.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/ConstantOperand.java
index 452e042240..de0584f4fe 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/ConstantOperand.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/ConstantOperand.java
@@ -24,19 +24,15 @@ import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 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.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.ConstantColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.ConstantIntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.memory.LayerMemoryAssigner;
 import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
-import org.apache.iotdb.db.mpp.transformation.dag.util.TransformUtils;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.apache.commons.lang3.Validate;
@@ -64,6 +60,11 @@ public class ConstantOperand extends LeafOperand {
     valueString = ReadWriteIOUtils.readString(byteBuffer);
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitConstantOperand(this, context);
+  }
+
   public TSDataType getDataType() {
     return dataType;
   }
@@ -159,32 +160,6 @@ public class ConstantOperand extends LeafOperand {
     return expressionIntermediateLayerMap.get(this);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    ColumnTransformer res =
-        cache.computeIfAbsent(
-            this,
-            e -> {
-              ConstantColumnTransformer columnTransformer =
-                  new ConstantColumnTransformer(
-                      TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                      TransformUtils.transformConstantOperandToColumn(this));
-              leafList.add(columnTransformer);
-              return columnTransformer;
-            });
-    res.addReferenceCount();
-    return res;
-  }
-
   @Override
   public String getExpressionStringInternal() {
     return valueString;
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimeSeriesOperand.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimeSeriesOperand.java
index 3ac07b4a84..06baccbce1 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimeSeriesOperand.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimeSeriesOperand.java
@@ -26,11 +26,9 @@ import org.apache.iotdb.db.metadata.path.PathDeserializeUtil;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 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.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.SingleInputColumnMultiReferenceIntermediateLayer;
@@ -39,7 +37,6 @@ import org.apache.iotdb.db.mpp.transformation.dag.memory.LayerMemoryAssigner;
 import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -68,6 +65,11 @@ public class TimeSeriesOperand extends LeafOperand {
     this.path = path;
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTimeSeriesOperand(this, context);
+  }
+
   @Override
   public boolean isConstantOperandInternal() {
     return false;
@@ -174,32 +176,6 @@ public class TimeSeriesOperand extends LeafOperand {
     return expressionIntermediateLayerMap.get(this);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    ColumnTransformer res =
-        cache.computeIfAbsent(
-            this,
-            e -> {
-              IdentityColumnTransformer identity =
-                  new IdentityColumnTransformer(
-                      TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                      inputLocations.get(getExpressionString()).get(0).getValueColumnIndex());
-              leafList.add(identity);
-              return identity;
-            });
-    res.addReferenceCount();
-    return res;
-  }
-
   @Override
   public String getExpressionStringInternal() {
     return path.isMeasurementAliasExists() ? path.getFullPathWithAlias() : path.getFullPath();
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimestampOperand.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimestampOperand.java
index dc854b9a93..5adecbe211 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimestampOperand.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/leaf/TimestampOperand.java
@@ -25,11 +25,9 @@ import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 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.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.TimeColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.SingleInputColumnMultiReferenceIntermediateLayer;
@@ -38,7 +36,6 @@ import org.apache.iotdb.db.mpp.transformation.dag.memory.LayerMemoryAssigner;
 import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -59,6 +56,11 @@ public class TimestampOperand extends LeafOperand {
     // do nothing
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTimeStampOperand(this, context);
+  }
+
   @Override
   public boolean isTimeSeriesGeneratingFunctionExpression() {
     return true;
@@ -157,31 +159,6 @@ public class TimestampOperand extends LeafOperand {
     return expressionIntermediateLayerMap.get(this);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    ColumnTransformer res =
-        cache.computeIfAbsent(
-            this,
-            e -> {
-              TimeColumnTransformer timeColumnTransformer =
-                  new TimeColumnTransformer(
-                      TypeFactory.getType(typeProvider.getType(getExpressionString())));
-              leafList.add(timeColumnTransformer);
-              return timeColumnTransformer;
-            });
-    res.addReferenceCount();
-    return res;
-  }
-
   @Override
   protected boolean isConstantOperandInternal() {
     return false;
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
index 5b9b1325c2..049381ede7 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java
@@ -29,11 +29,8 @@ import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 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.leaf.TimeSeriesOperand;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.multi.MappableUDFColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.MultiInputColumnIntermediateLayer;
@@ -53,7 +50,6 @@ import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer;
 import org.apache.iotdb.db.utils.TypeInferenceUtils;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 import org.apache.iotdb.udf.api.customizer.strategy.AccessStrategy;
 
@@ -147,6 +143,11 @@ public class FunctionExpression extends Expression {
                         || v.isBuiltInAggregationFunctionExpression());
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitFunctionExpression(this, context);
+  }
+
   @Override
   public boolean isBuiltInAggregationFunctionExpression() {
     return isBuiltInAggregationFunctionExpression;
@@ -321,88 +322,6 @@ public class FunctionExpression extends Expression {
     memoryAssigner.increaseExpressionReference(this);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    if (!cache.containsKey(this)) {
-      if (hasSeen.containsKey(this)) {
-        IdentityColumnTransformer identity =
-            new IdentityColumnTransformer(
-                TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                originSize + commonTransformerList.size());
-        ColumnTransformer columnTransformer = hasSeen.get(this);
-        columnTransformer.addReferenceCount();
-        commonTransformerList.add(columnTransformer);
-        inputDataTypes.add(typeProvider.getType(getExpressionString()));
-        leafList.add(identity);
-        cache.put(this, identity);
-      } else {
-        if (isBuiltInAggregationFunctionExpression) {
-          IdentityColumnTransformer identity =
-              new IdentityColumnTransformer(
-                  TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                  inputLocations.get(getExpressionString()).get(0).getValueColumnIndex());
-          leafList.add(identity);
-          cache.put(this, identity);
-        } else {
-          ColumnTransformer[] inputColumnTransformers =
-              expressions.stream()
-                  .map(
-                      expression ->
-                          expression.constructColumnTransformer(
-                              udtfContext,
-                              typeProvider,
-                              leafList,
-                              inputLocations,
-                              cache,
-                              hasSeen,
-                              commonTransformerList,
-                              inputDataTypes,
-                              originSize))
-                  .toArray(ColumnTransformer[]::new);
-
-          TSDataType[] inputTransformerDataTypes =
-              expressions.stream()
-                  .map(expression -> expression.inferTypes(typeProvider))
-                  .toArray(TSDataType[]::new);
-
-          UDTFExecutor executor = udtfContext.getExecutorByFunctionExpression(this);
-
-          // Mappable UDF does not need PointCollector, so memoryBudget and queryId is not
-          // needed.
-          executor.beforeStart(
-              0,
-              0,
-              expressions.stream().map(Expression::toString).collect(Collectors.toList()),
-              expressions.stream()
-                  .map(f -> typeProvider.getType(f.toString()))
-                  .collect(Collectors.toList()),
-              functionAttributes);
-
-          cache.put(
-              this,
-              new MappableUDFColumnTransformer(
-                  TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                  inputColumnTransformers,
-                  inputTransformerDataTypes,
-                  udtfContext.getExecutorByFunctionExpression(this)));
-        }
-      }
-    }
-
-    ColumnTransformer res = cache.get(this);
-    res.addReferenceCount();
-    return res;
-  }
-
   @Override
   public IntermediateLayer constructIntermediateLayer(
       long queryId,
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/BetweenExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/BetweenExpression.java
index 6b71fcdc45..b1445eca59 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/BetweenExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/BetweenExpression.java
@@ -25,13 +25,9 @@ import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ternary.BetweenColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ternary.TernaryColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.ternary.BetweenTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.ternary.TernaryTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.io.DataOutputStream;
@@ -77,20 +73,6 @@ public class BetweenExpression extends TernaryExpression {
         isNotBetween);
   }
 
-  @Override
-  protected TernaryColumnTransformer getConcreteTernaryTransformer(
-      ColumnTransformer firstColumnTransformer,
-      ColumnTransformer secondColumnTransformer,
-      ColumnTransformer thirdColumnTransformer,
-      Type returnType) {
-    return new BetweenColumnTransformer(
-        returnType,
-        firstColumnTransformer,
-        secondColumnTransformer,
-        thirdColumnTransformer,
-        isNotBetween);
-  }
-
   @Override
   protected String operator() {
     return "between";
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/TernaryExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/TernaryExpression.java
index 780ee96851..0c8a5fb547 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/TernaryExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/ternary/TernaryExpression.java
@@ -26,12 +26,9 @@ import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ternary.TernaryColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.SingleInputColumnMultiReferenceIntermediateLayer;
@@ -43,8 +40,6 @@ import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
 import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFExecutor;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -87,6 +82,11 @@ public abstract class TernaryExpression extends Expression {
     this.thirdExpression = Expression.deserialize(byteBuffer);
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitTernaryExpression(this, context);
+  }
+
   @Override
   public boolean isConstantOperandInternal() {
     return firstExpression.isConstantOperand()
@@ -174,85 +174,6 @@ public abstract class TernaryExpression extends Expression {
         && thirdExpression.isMappable(typeProvider);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    if (!cache.containsKey(this)) {
-      if (hasSeen.containsKey(this)) {
-        IdentityColumnTransformer identity =
-            new IdentityColumnTransformer(
-                TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                originSize + commonTransformerList.size());
-        ColumnTransformer columnTransformer = hasSeen.get(this);
-        columnTransformer.addReferenceCount();
-        commonTransformerList.add(columnTransformer);
-        leafList.add(identity);
-        inputDataTypes.add(typeProvider.getType(getExpressionString()));
-        cache.put(this, identity);
-      } else {
-        ColumnTransformer firstColumnTransformer =
-            firstExpression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-        ColumnTransformer secondColumnTransformer =
-            secondExpression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-        ColumnTransformer thirdColumnTransformer =
-            thirdExpression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-
-        cache.put(
-            this,
-            getConcreteTernaryTransformer(
-                firstColumnTransformer,
-                secondColumnTransformer,
-                thirdColumnTransformer,
-                TypeFactory.getType(typeProvider.getType(getExpressionString()))));
-      }
-    }
-
-    ColumnTransformer res = cache.get(this);
-    res.addReferenceCount();
-    return res;
-  }
-
-  protected abstract TernaryColumnTransformer getConcreteTernaryTransformer(
-      ColumnTransformer firstColumnTransformer,
-      ColumnTransformer secondColumnTransformer,
-      ColumnTransformer thirdColumnTransformer,
-      Type returnType);
-
   @Override
   public void constructUdfExecutors(
       Map<String, UDTFExecutor> expressionName2Executor, ZoneId zoneId) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/InExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/InExpression.java
index 5e97e28875..47aa0dd53e 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/InExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/InExpression.java
@@ -26,12 +26,9 @@ 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.multi.FunctionExpression;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.InColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.InTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.io.DataOutputStream;
@@ -110,12 +107,6 @@ public class InExpression extends UnaryExpression {
     return new InTransformer(pointReader, isNotIn, values);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new InColumnTransformer(returnType, childColumnTransformer, isNotIn, values);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new InExpression(childExpression, isNotIn, values);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/IsNullExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/IsNullExpression.java
index 537f1edc3e..83f4e3a3b0 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/IsNullExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/IsNullExpression.java
@@ -23,12 +23,9 @@ import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.IsNullColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.IsNullTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.io.DataOutputStream;
@@ -77,12 +74,6 @@ public class IsNullExpression extends UnaryExpression {
     return new IsNullTransformer(pointReader, isNot);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new IsNullColumnTransformer(returnType, childColumnTransformer, isNot);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new IsNullExpression(childExpression, isNot);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LikeExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LikeExpression.java
index e86c484fb3..d14b2c30a3 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LikeExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LikeExpression.java
@@ -24,12 +24,9 @@ import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.RegularColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.RegularTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.io.DataOutputStream;
@@ -149,12 +146,6 @@ public class LikeExpression extends UnaryExpression {
     return new RegularTransformer(pointReader, pattern);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new RegularColumnTransformer(returnType, childColumnTransformer, pattern);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new LikeExpression(childExpression, patternString, pattern);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LogicNotExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LogicNotExpression.java
index 3f4c91dace..9a7191d497 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LogicNotExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/LogicNotExpression.java
@@ -27,12 +27,9 @@ 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.multi.FunctionExpression;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.LogicNotColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.LogicNotTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -51,12 +48,6 @@ public class LogicNotExpression extends UnaryExpression {
     return new LogicNotTransformer(pointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new LogicNotColumnTransformer(returnType, childColumnTransformer);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new LogicNotExpression(childExpression);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/NegationExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/NegationExpression.java
index 306e8ddd76..2b9cba69b8 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/NegationExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/NegationExpression.java
@@ -27,12 +27,9 @@ 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.multi.FunctionExpression;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.ArithmeticNegationColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.ArithmeticNegationTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 
 import java.nio.ByteBuffer;
 
@@ -51,12 +48,6 @@ public class NegationExpression extends UnaryExpression {
     return new ArithmeticNegationTransformer(pointReader);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new ArithmeticNegationColumnTransformer(returnType, childColumnTransformer);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new NegationExpression(childExpression);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/RegularExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/RegularExpression.java
index 4dcb052055..aee30c1a3f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/RegularExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/RegularExpression.java
@@ -24,12 +24,9 @@ import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.ExpressionType;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.unary.RegularColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.Transformer;
 import org.apache.iotdb.db.mpp.transformation.dag.transformer.unary.RegularTransformer;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import org.apache.commons.lang3.Validate;
@@ -75,12 +72,6 @@ public class RegularExpression extends UnaryExpression {
     return new RegularTransformer(pointReader, pattern);
   }
 
-  @Override
-  protected ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType) {
-    return new RegularColumnTransformer(returnType, childColumnTransformer, pattern);
-  }
-
   @Override
   protected Expression constructExpression(Expression childExpression) {
     return new RegularExpression(childExpression, patternString, pattern);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/UnaryExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/UnaryExpression.java
index 72aefade90..2ba93e2e10 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/UnaryExpression.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/unary/UnaryExpression.java
@@ -24,11 +24,9 @@ import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.ExpressionVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
 import org.apache.iotdb.db.mpp.transformation.api.LayerPointReader;
-import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
-import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
 import org.apache.iotdb.db.mpp.transformation.dag.input.QueryDataSetInputLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.IntermediateLayer;
 import org.apache.iotdb.db.mpp.transformation.dag.intermediate.SingleInputColumnMultiReferenceIntermediateLayer;
@@ -40,8 +38,6 @@ import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFExecutor;
 import org.apache.iotdb.db.qp.physical.crud.UDTFPlan;
 import org.apache.iotdb.db.qp.utils.WildcardsRemover;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.type.Type;
-import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -65,6 +61,11 @@ public abstract class UnaryExpression extends Expression {
     return expression;
   }
 
+  @Override
+  public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+    return visitor.visitUnaryExpression(this, context);
+  }
+
   @Override
   public final boolean isConstantOperandInternal() {
     return expression.isConstantOperand();
@@ -200,56 +201,6 @@ public abstract class UnaryExpression extends Expression {
     return expression.isMappable(typeProvider);
   }
 
-  @Override
-  public ColumnTransformer constructColumnTransformer(
-      UDTFContext udtfContext,
-      TypeProvider typeProvider,
-      List<LeafColumnTransformer> leafList,
-      Map<String, List<InputLocation>> inputLocations,
-      Map<Expression, ColumnTransformer> cache,
-      Map<Expression, ColumnTransformer> hasSeen,
-      List<ColumnTransformer> commonTransformerList,
-      List<TSDataType> inputDataTypes,
-      int originSize) {
-    if (!cache.containsKey(this)) {
-      if (hasSeen.containsKey(this)) {
-        IdentityColumnTransformer identity =
-            new IdentityColumnTransformer(
-                TypeFactory.getType(typeProvider.getType(getExpressionString())),
-                originSize + commonTransformerList.size());
-        ColumnTransformer columnTransformer = hasSeen.get(this);
-        columnTransformer.addReferenceCount();
-        commonTransformerList.add(columnTransformer);
-        leafList.add(identity);
-        inputDataTypes.add(typeProvider.getType(getExpressionString()));
-        cache.put(this, identity);
-      } else {
-        ColumnTransformer childColumnTransformer =
-            expression.constructColumnTransformer(
-                udtfContext,
-                typeProvider,
-                leafList,
-                inputLocations,
-                cache,
-                hasSeen,
-                commonTransformerList,
-                inputDataTypes,
-                originSize);
-        cache.put(
-            this,
-            getConcreteUnaryColumnTransformer(
-                childColumnTransformer,
-                TypeFactory.getType(typeProvider.getType(getExpressionString()))));
-      }
-    }
-    ColumnTransformer res = cache.get(this);
-    res.addReferenceCount();
-    return res;
-  }
-
-  protected abstract ColumnTransformer getConcreteUnaryColumnTransformer(
-      ColumnTransformer childColumnTransformer, Type returnType);
-
   protected abstract Transformer constructTransformer(LayerPointReader pointReader);
 
   @Override
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ColumnTransformerVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ColumnTransformerVisitor.java
new file mode 100644
index 0000000000..313082a8df
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ColumnTransformerVisitor.java
@@ -0,0 +1,478 @@
+/*
+ * 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.db.mpp.plan.analyze.TypeProvider;
+import org.apache.iotdb.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression;
+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.ternary.BetweenExpression;
+import org.apache.iotdb.db.mpp.plan.expression.ternary.TernaryExpression;
+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.RegularExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression;
+import org.apache.iotdb.db.mpp.plan.planner.plan.parameter.InputLocation;
+import org.apache.iotdb.db.mpp.transformation.dag.column.ColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticAdditionColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticDivisionColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticModuloColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticMultiplicationColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.ArithmeticSubtractionColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareEqualToColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareGreaterEqualColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareGreaterThanColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareLessEqualColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareLessThanColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.CompareNonEqualColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.LogicAndColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.binary.LogicOrColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.ConstantColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.IdentityColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.LeafColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.leaf.TimeColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.multi.MappableUDFColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.ternary.BetweenColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.ArithmeticNegationColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.InColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.IsNullColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.LogicNotColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.column.unary.RegularColumnTransformer;
+import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFContext;
+import org.apache.iotdb.db.mpp.transformation.dag.udf.UDTFExecutor;
+import org.apache.iotdb.db.mpp.transformation.dag.util.TransformUtils;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.read.common.type.Type;
+import org.apache.iotdb.tsfile.read.common.type.TypeFactory;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/** Responsible for constructing {@link ColumnTransformer} through Expression. */
+public class ColumnTransformerVisitor
+    extends ExpressionVisitor<
+        ColumnTransformer, ColumnTransformerVisitor.ColumnTransformerVisitorContext> {
+
+  @Override
+  public ColumnTransformer visitExpression(
+      Expression expression, ColumnTransformerVisitorContext context) {
+    throw new UnsupportedOperationException(
+        "Unsupported statement type: " + expression.getClass().getName());
+  }
+
+  @Override
+  public ColumnTransformer visitUnaryExpression(
+      UnaryExpression unaryExpression, ColumnTransformerVisitorContext context) {
+    if (!context.cache.containsKey(unaryExpression)) {
+      if (context.hasSeen.containsKey(unaryExpression)) {
+        IdentityColumnTransformer identity =
+            new IdentityColumnTransformer(
+                TypeFactory.getType(
+                    context.typeProvider.getType(unaryExpression.getExpressionString())),
+                context.originSize + context.commonTransformerList.size());
+        ColumnTransformer columnTransformer = context.hasSeen.get(unaryExpression);
+        columnTransformer.addReferenceCount();
+        context.commonTransformerList.add(columnTransformer);
+        context.leafList.add(identity);
+        context.inputDataTypes.add(
+            context.typeProvider.getType(unaryExpression.getExpressionString()));
+        context.cache.put(unaryExpression, identity);
+      } else {
+        ColumnTransformer childColumnTransformer =
+            this.process(unaryExpression.getExpression(), context);
+        context.cache.put(
+            unaryExpression,
+            getConcreteUnaryColumnTransformer(
+                unaryExpression,
+                childColumnTransformer,
+                TypeFactory.getType(
+                    context.typeProvider.getType(unaryExpression.getExpressionString()))));
+      }
+    }
+    ColumnTransformer res = context.cache.get(unaryExpression);
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitBinaryExpression(
+      BinaryExpression binaryExpression, ColumnTransformerVisitorContext context) {
+    if (!context.cache.containsKey(binaryExpression)) {
+      if (context.hasSeen.containsKey(binaryExpression)) {
+        IdentityColumnTransformer identity =
+            new IdentityColumnTransformer(
+                TypeFactory.getType(
+                    context.typeProvider.getType(binaryExpression.getExpressionString())),
+                context.originSize + context.commonTransformerList.size());
+        ColumnTransformer columnTransformer = context.hasSeen.get(binaryExpression);
+        columnTransformer.addReferenceCount();
+        context.commonTransformerList.add(columnTransformer);
+        context.leafList.add(identity);
+        context.inputDataTypes.add(
+            context.typeProvider.getType(binaryExpression.getExpressionString()));
+        context.cache.put(binaryExpression, identity);
+      } else {
+        ColumnTransformer leftColumnTransformer =
+            this.process(binaryExpression.getLeftExpression(), context);
+        ColumnTransformer rightColumnTransformer =
+            this.process(binaryExpression.getRightExpression(), context);
+        context.cache.put(
+            binaryExpression,
+            getConcreteBinaryColumnTransformer(
+                binaryExpression,
+                leftColumnTransformer,
+                rightColumnTransformer,
+                TypeFactory.getType(
+                    context.typeProvider.getType(binaryExpression.getExpressionString()))));
+      }
+    }
+
+    ColumnTransformer res = context.cache.get(binaryExpression);
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitTernaryExpression(
+      TernaryExpression ternaryExpression, ColumnTransformerVisitorContext context) {
+    if (!context.cache.containsKey(ternaryExpression)) {
+      if (context.hasSeen.containsKey(ternaryExpression)) {
+        IdentityColumnTransformer identity =
+            new IdentityColumnTransformer(
+                TypeFactory.getType(
+                    context.typeProvider.getType(ternaryExpression.getExpressionString())),
+                context.originSize + context.commonTransformerList.size());
+        ColumnTransformer columnTransformer = context.hasSeen.get(ternaryExpression);
+        columnTransformer.addReferenceCount();
+        context.commonTransformerList.add(columnTransformer);
+        context.leafList.add(identity);
+        context.inputDataTypes.add(
+            context.typeProvider.getType(ternaryExpression.getExpressionString()));
+        context.cache.put(ternaryExpression, identity);
+      } else {
+        ColumnTransformer firstColumnTransformer =
+            this.process(ternaryExpression.getFirstExpression(), context);
+        ColumnTransformer secondColumnTransformer =
+            this.process(ternaryExpression.getSecondExpression(), context);
+        ColumnTransformer thirdColumnTransformer =
+            this.process(ternaryExpression.getThirdExpression(), context);
+        context.cache.put(
+            ternaryExpression,
+            getConcreteTernaryTransformer(
+                ternaryExpression,
+                firstColumnTransformer,
+                secondColumnTransformer,
+                thirdColumnTransformer,
+                TypeFactory.getType(
+                    context.typeProvider.getType(ternaryExpression.getExpressionString()))));
+      }
+    }
+
+    ColumnTransformer res = context.cache.get(ternaryExpression);
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitFunctionExpression(
+      FunctionExpression functionExpression, ColumnTransformerVisitorContext context) {
+    List<Expression> expressions = functionExpression.getExpressions();
+    if (!context.cache.containsKey(functionExpression)) {
+      if (context.hasSeen.containsKey(functionExpression)) {
+        IdentityColumnTransformer identity =
+            new IdentityColumnTransformer(
+                TypeFactory.getType(
+                    context.typeProvider.getType(functionExpression.getExpressionString())),
+                context.originSize + context.commonTransformerList.size());
+        ColumnTransformer columnTransformer = context.hasSeen.get(functionExpression);
+        columnTransformer.addReferenceCount();
+        context.commonTransformerList.add(columnTransformer);
+        context.inputDataTypes.add(
+            context.typeProvider.getType(functionExpression.getExpressionString()));
+        context.leafList.add(identity);
+        context.cache.put(functionExpression, identity);
+      } else {
+        if (functionExpression.isBuiltInAggregationFunctionExpression()) {
+          IdentityColumnTransformer identity =
+              new IdentityColumnTransformer(
+                  TypeFactory.getType(
+                      context.typeProvider.getType(functionExpression.getExpressionString())),
+                  context
+                      .inputLocations
+                      .get(functionExpression.getExpressionString())
+                      .get(0)
+                      .getValueColumnIndex());
+          context.leafList.add(identity);
+          context.cache.put(functionExpression, identity);
+        } else {
+          ColumnTransformer[] inputColumnTransformers =
+              expressions.stream()
+                  .map(expression -> this.process(expression, context))
+                  .toArray(ColumnTransformer[]::new);
+
+          TSDataType[] inputTransformerDataTypes =
+              expressions.stream()
+                  .map(expression -> expression.inferTypes(context.typeProvider))
+                  .toArray(TSDataType[]::new);
+
+          UDTFExecutor executor =
+              context.udtfContext.getExecutorByFunctionExpression(functionExpression);
+
+          // Mappable UDF does not need PointCollector, so memoryBudget and queryId is not
+          // needed.
+          executor.beforeStart(
+              0,
+              0,
+              expressions.stream().map(Expression::toString).collect(Collectors.toList()),
+              expressions.stream()
+                  .map(f -> context.typeProvider.getType(f.toString()))
+                  .collect(Collectors.toList()),
+              functionExpression.getFunctionAttributes());
+
+          context.cache.put(
+              functionExpression,
+              new MappableUDFColumnTransformer(
+                  TypeFactory.getType(
+                      context.typeProvider.getType(functionExpression.getExpressionString())),
+                  inputColumnTransformers,
+                  inputTransformerDataTypes,
+                  context.udtfContext.getExecutorByFunctionExpression(functionExpression)));
+        }
+      }
+    }
+    ColumnTransformer res = context.cache.get(functionExpression);
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitTimeStampOperand(
+      TimestampOperand timestampOperand, ColumnTransformerVisitorContext context) {
+    ColumnTransformer res =
+        context.cache.computeIfAbsent(
+            timestampOperand,
+            e -> {
+              TimeColumnTransformer timeColumnTransformer =
+                  new TimeColumnTransformer(
+                      TypeFactory.getType(
+                          context.typeProvider.getType(timestampOperand.getExpressionString())));
+              context.leafList.add(timeColumnTransformer);
+              return timeColumnTransformer;
+            });
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitTimeSeriesOperand(
+      TimeSeriesOperand timeSeriesOperand, ColumnTransformerVisitorContext context) {
+    ColumnTransformer res =
+        context.cache.computeIfAbsent(
+            timeSeriesOperand,
+            e -> {
+              IdentityColumnTransformer identity =
+                  new IdentityColumnTransformer(
+                      TypeFactory.getType(
+                          context.typeProvider.getType(timeSeriesOperand.getExpressionString())),
+                      context
+                          .inputLocations
+                          .get(timeSeriesOperand.getExpressionString())
+                          .get(0)
+                          .getValueColumnIndex());
+              context.leafList.add(identity);
+              return identity;
+            });
+    res.addReferenceCount();
+    return res;
+  }
+
+  @Override
+  public ColumnTransformer visitConstantOperand(
+      ConstantOperand constantOperand, ColumnTransformerVisitorContext context) {
+    ColumnTransformer res =
+        context.cache.computeIfAbsent(
+            constantOperand,
+            e -> {
+              ConstantColumnTransformer columnTransformer =
+                  new ConstantColumnTransformer(
+                      TypeFactory.getType(
+                          context.typeProvider.getType(constantOperand.getExpressionString())),
+                      TransformUtils.transformConstantOperandToColumn(constantOperand));
+              context.leafList.add(columnTransformer);
+              return columnTransformer;
+            });
+    res.addReferenceCount();
+    return res;
+  }
+
+  private ColumnTransformer getConcreteUnaryColumnTransformer(
+      Expression expression, ColumnTransformer childColumnTransformer, Type returnType) {
+    switch (expression.getExpressionType()) {
+      case IN:
+        InExpression inExpression = (InExpression) expression;
+        return new InColumnTransformer(
+            returnType, childColumnTransformer, inExpression.isNotIn(), inExpression.getValues());
+      case IS_NULL:
+        IsNullExpression isNullExpression = (IsNullExpression) expression;
+        return new IsNullColumnTransformer(
+            returnType, childColumnTransformer, isNullExpression.isNot());
+      case LOGIC_NOT:
+        return new LogicNotColumnTransformer(returnType, childColumnTransformer);
+      case NEGATION:
+        return new ArithmeticNegationColumnTransformer(returnType, childColumnTransformer);
+      case LIKE:
+        LikeExpression likeExpression = (LikeExpression) expression;
+        return new RegularColumnTransformer(
+            returnType, childColumnTransformer, likeExpression.getPattern());
+      case REGEXP:
+        RegularExpression regularExpression = (RegularExpression) expression;
+        return new RegularColumnTransformer(
+            returnType, childColumnTransformer, regularExpression.getPattern());
+      default:
+        throw new UnsupportedOperationException(
+            "Unsupported Expression Type: " + expression.getExpressionType());
+    }
+  }
+
+  private ColumnTransformer getConcreteBinaryColumnTransformer(
+      Expression expression,
+      ColumnTransformer leftColumnTransformer,
+      ColumnTransformer rightColumnTransformer,
+      Type returnType) {
+    switch (expression.getExpressionType()) {
+      case ADDITION:
+        return new ArithmeticAdditionColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case SUBTRACTION:
+        return new ArithmeticSubtractionColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case MULTIPLICATION:
+        return new ArithmeticMultiplicationColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case DIVISION:
+        return new ArithmeticDivisionColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case MODULO:
+        return new ArithmeticModuloColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case EQUAL_TO:
+        return new CompareEqualToColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case NON_EQUAL:
+        return new CompareNonEqualColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case GREATER_THAN:
+        return new CompareGreaterThanColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case GREATER_EQUAL:
+        return new CompareGreaterEqualColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case LESS_THAN:
+        return new CompareLessThanColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case LESS_EQUAL:
+        return new CompareLessEqualColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case LOGIC_AND:
+        return new LogicAndColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      case LOGIC_OR:
+        return new LogicOrColumnTransformer(
+            returnType, leftColumnTransformer, rightColumnTransformer);
+      default:
+        throw new UnsupportedOperationException(
+            "Unsupported Expression Type: " + expression.getExpressionType());
+    }
+  }
+
+  private ColumnTransformer getConcreteTernaryTransformer(
+      Expression expression,
+      ColumnTransformer firstColumnTransformer,
+      ColumnTransformer secondColumnTransformer,
+      ColumnTransformer thirdColumnTransformer,
+      Type returnType) {
+    switch (expression.getExpressionType()) {
+      case BETWEEN:
+        BetweenExpression betweenExpression = (BetweenExpression) expression;
+        return new BetweenColumnTransformer(
+            returnType,
+            firstColumnTransformer,
+            secondColumnTransformer,
+            thirdColumnTransformer,
+            betweenExpression.isNotBetween());
+      default:
+        throw new UnsupportedOperationException(
+            "Unsupported Expression Type: " + expression.getExpressionType());
+    }
+  }
+
+  public static class ColumnTransformerVisitorContext {
+    // UDTFContext of expression
+    UDTFContext udtfContext;
+
+    // TypeProvider of expression
+    TypeProvider typeProvider;
+
+    // LeafColumnTransformer for LeafOperand
+    List<LeafColumnTransformer> leafList;
+
+    // Index of input column
+    Map<String, List<InputLocation>> inputLocations;
+
+    // cache for constructing ColumnTransformer tree
+    Map<Expression, ColumnTransformer> cache;
+
+    // Sub expressions that has been seen in filter
+    Map<Expression, ColumnTransformer> hasSeen;
+
+    // Common Transformer between filter and project
+    List<ColumnTransformer> commonTransformerList;
+
+    List<TSDataType> inputDataTypes;
+
+    int originSize;
+
+    public ColumnTransformerVisitorContext(
+        UDTFContext udtfContext,
+        TypeProvider typeProvider,
+        List<LeafColumnTransformer> leafList,
+        Map<String, List<InputLocation>> inputLocations,
+        Map<Expression, ColumnTransformer> cache,
+        Map<Expression, ColumnTransformer> hasSeen,
+        List<ColumnTransformer> commonTransformerList,
+        List<TSDataType> inputDataTypes,
+        int originSize) {
+      this.udtfContext = udtfContext;
+      this.typeProvider = typeProvider;
+      this.leafList = leafList;
+      this.inputLocations = inputLocations;
+      this.cache = cache;
+      this.hasSeen = hasSeen;
+      this.commonTransformerList = commonTransformerList;
+      this.inputDataTypes = inputDataTypes;
+      this.originSize = originSize;
+    }
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionVisitor.java
new file mode 100644
index 0000000000..a210c13c16
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/visitor/ExpressionVisitor.java
@@ -0,0 +1,73 @@
+/*
+ * 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.db.mpp.plan.expression.Expression;
+import org.apache.iotdb.db.mpp.plan.expression.binary.BinaryExpression;
+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.ternary.TernaryExpression;
+import org.apache.iotdb.db.mpp.plan.expression.unary.UnaryExpression;
+
+/**
+ * This class provides a visitor of {@link Expression}, which can be extended to create a visitor
+ * which only needs to handle a subset of the available methods.
+ *
+ * @param <R> The return type of the visit operation.
+ * @param <C> The context information during visiting.
+ */
+public abstract class ExpressionVisitor<R, C> {
+
+  public R process(Expression expression, C context) {
+    return expression.accept(this, context);
+  }
+
+  public abstract R visitExpression(Expression expression, C context);
+
+  public R visitUnaryExpression(UnaryExpression unaryExpression, C context) {
+    return visitExpression(unaryExpression, context);
+  }
+
+  public R visitBinaryExpression(BinaryExpression binaryExpression, C context) {
+    return visitExpression(binaryExpression, context);
+  }
+
+  public R visitTernaryExpression(TernaryExpression ternaryExpression, C context) {
+    return visitExpression(ternaryExpression, context);
+  }
+
+  public R visitFunctionExpression(FunctionExpression functionExpression, C context) {
+    return visitExpression(functionExpression, context);
+  }
+
+  public R visitTimeStampOperand(TimestampOperand timestampOperand, C context) {
+    return visitExpression(timestampOperand, context);
+  }
+
+  public R visitTimeSeriesOperand(TimeSeriesOperand timeSeriesOperand, C context) {
+    return visitExpression(timeSeriesOperand, context);
+  }
+
+  public R visitConstantOperand(ConstantOperand constantOperand, C context) {
+    return visitExpression(constantOperand, context);
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
index a981c9e631..c67c3bfd6d 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java
@@ -105,6 +105,7 @@ import org.apache.iotdb.db.mpp.execution.operator.source.SeriesScanOperator;
 import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider;
 import org.apache.iotdb.db.mpp.plan.expression.Expression;
 import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
+import org.apache.iotdb.db.mpp.plan.expression.visitor.ColumnTransformerVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanVisitor;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.metedata.read.CountSchemaMergeNode;
@@ -862,8 +863,10 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
     // records subexpression -> ColumnTransformer for filter
     Map<Expression, ColumnTransformer> filterExpressionColumnTransformerMap = new HashMap<>();
 
-    ColumnTransformer filterOutputTransformer =
-        filterExpression.constructColumnTransformer(
+    ColumnTransformerVisitor visitor = new ColumnTransformerVisitor();
+
+    ColumnTransformerVisitor.ColumnTransformerVisitorContext filterColumnTransformerContext =
+        new ColumnTransformerVisitor.ColumnTransformerVisitorContext(
             filterContext,
             typeProvider,
             filterLeafColumnTransformerList,
@@ -874,6 +877,9 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
             ImmutableList.of(),
             0);
 
+    ColumnTransformer filterOutputTransformer =
+        visitor.process(filterExpression, filterColumnTransformerContext);
+
     List<ColumnTransformer> projectOutputTransformerList = new ArrayList<>();
 
     Map<Expression, ColumnTransformer> projectExpressionColumnTransformerMap = new HashMap<>();
@@ -884,18 +890,21 @@ public class OperatorTreeGenerator extends PlanVisitor<Operator, LocalExecutionP
       UDTFContext projectContext = new UDTFContext(node.getZoneId());
       projectContext.constructUdfExecutors(projectExpressions);
 
+      ColumnTransformerVisitor.ColumnTransformerVisitorContext projectColumnTransformerContext =
+          new ColumnTransformerVisitor.ColumnTransformerVisitorContext(
+              projectContext,
+              typeProvider,
+              projectLeafColumnTransformerList,
+              inputLocations,
+              projectExpressionColumnTransformerMap,
+              filterExpressionColumnTransformerMap,
+              commonTransformerList,
+              filterOutputDataTypes,
+              inputLocations.size());
+
       for (Expression expression : projectExpressions) {
         projectOutputTransformerList.add(
-            expression.constructColumnTransformer(
-                projectContext,
-                typeProvider,
-                projectLeafColumnTransformerList,
-                inputLocations,
-                projectExpressionColumnTransformerMap,
-                filterExpressionColumnTransformerMap,
-                commonTransformerList,
-                filterOutputDataTypes,
-                inputLocations.size()));
+            visitor.process(expression, projectColumnTransformerContext));
       }
     }